00001 #include <stdio.h>
00002 #include "util.h"
00003 #include "vpr_types.h"
00004 #include "globals.h"
00005 #include "hash.h"
00006 #include "vpr_utils.h"
00007 #include "check_netlist.h"
00008 #include "assert.h"
00009
00010
00011
00012
00013 static int check_connections_to_global_fb_pins(int inet);
00014
00015 static int check_fb_conn(int iblk,
00016 int num_conn);
00017
00018 static void check_for_multiple_sink_connections(void);
00019
00020 static int check_for_duplicate_block_names(void);
00021
00022 static int get_num_conn(int bnum);
00023
00024 static int check_subblocks(int iblk,
00025 t_subblock_data * subblock_data_ptr,
00026 int *num_uses_of_fb_pin,
00027 int **num_uses_of_sblk_opin);
00028
00029 static int check_subblock_pin(int fb_pin,
00030 int min_val,
00031 int max_val,
00032 enum e_pin_type pin_type,
00033 int iblk,
00034 int isubblk,
00035 t_subblock * subblock_inf);
00036
00037 static int check_internal_subblock_connections(t_subblock_data
00038 * subblock_data_ptr,
00039 int iblk,
00040 int **num_uses_of_sblk_opin);
00041
00042 static int check_fb_to_subblock_connections(int iblk,
00043 t_subblock * subblock_inf,
00044 int num_subblocks,
00045 int *num_uses_of_fb_pin);
00046
00047
00048
00049
00050
00051 void
00052 check_netlist(t_subblock_data * subblock_data_ptr)
00053 {
00054
00055
00056
00057
00058
00059 int i, error, num_conn, max_subblocks, max_pins, max_sub_opins;
00060 int *num_uses_of_fb_pin, **num_uses_of_sblk_opin,
00061 *num_subblocks_per_block;
00062 struct s_hash **net_hash_table, *h_ptr;
00063
00064 net_hash_table = alloc_hash_table();
00065
00066 num_subblocks_per_block = subblock_data_ptr->num_subblocks_per_block;
00067 subblock_data_ptr->num_ff = 0;
00068 subblock_data_ptr->num_const_gen = 0;
00069
00070 error = 0;
00071 max_pins = 0;
00072 max_sub_opins = 0;
00073
00074
00075 max_subblocks = 0;
00076 for(i = 0; i < num_types; i++)
00077 {
00078 max_subblocks =
00079 max(max_subblocks, type_descriptors[i].max_subblocks);
00080 max_pins = max(max_pins, type_descriptors[i].num_pins);
00081 max_sub_opins =
00082 max(max_sub_opins, type_descriptors[i].max_subblock_outputs);
00083 }
00084
00085
00086 num_uses_of_fb_pin = (int *)my_malloc(max_pins * sizeof(int));
00087 num_uses_of_sblk_opin =
00088 (int **)alloc_matrix(0, max_subblocks - 1, 0, max_sub_opins - 1,
00089 sizeof(int));
00090
00091
00092
00093 for(i = 0; i < num_nets; i++)
00094 {
00095 h_ptr = insert_in_hash_table(net_hash_table, net[i].name, i);
00096 if(h_ptr->count != 1) {
00097 printf("Error: net %s has multiple drivers.\n", net[i].name);
00098 error++;
00099 }
00100
00101 if(net[i].num_sinks == 0)
00102 {
00103 printf("Error: net %s has no fanout.\n", net[i].name);
00104 error++;
00105 }
00106
00107 error += check_connections_to_global_fb_pins(i);
00108 }
00109 free_hash_table(net_hash_table);
00110
00111
00112 for(i = 0; i < num_blocks; i++)
00113 {
00114 num_conn = get_num_conn(i);
00115 error += check_fb_conn(i, num_conn);
00116 error += check_subblocks(i, subblock_data_ptr, num_uses_of_fb_pin,
00117 num_uses_of_sblk_opin);
00118 }
00119
00120 check_for_multiple_sink_connections();
00121
00122 error += check_for_duplicate_block_names();
00123
00124 free(num_uses_of_fb_pin);
00125 free_matrix(num_uses_of_sblk_opin, 0, max_subblocks - 1, 0, sizeof(int));
00126
00127 if(error != 0)
00128 {
00129 printf("Found %d fatal Errors in the input netlist.\n", error);
00130 exit(1);
00131 }
00132 }
00133
00134
00135 static int
00136 check_connections_to_global_fb_pins(int inet)
00137 {
00138
00139
00140
00141
00142
00143 int ipin, num_pins, iblk, node_block_pin, error;
00144
00145 num_pins = (net[inet].num_sinks + 1);
00146 error = 0;
00147
00148
00149
00150
00151
00152
00153 for(ipin = 0; ipin < num_pins; ipin++)
00154 {
00155 iblk = net[inet].node_block[ipin];
00156
00157 node_block_pin = net[inet].node_block_pin[ipin];
00158
00159 if(block[iblk].type->is_global_pin[node_block_pin] !=
00160 net[inet].is_global)
00161 {
00162
00163
00164
00165 if(ipin == 0 && net[inet].is_global)
00166 {
00167 printf
00168 ("Warning in check_connections_to_global_fb_pins:\n"
00169 "\tnet #%d (%s) is driven by FB output pin (#%d)\n"
00170 "\ton block #%d (%s).\n", inet,
00171 net[inet].name, node_block_pin, iblk,
00172 block[iblk].name);
00173 }
00174 else
00175 {
00176 printf
00177 ("Error in check_connections_to_global_fb_pins:\n"
00178 "\tpin %d on net #%d (%s) connects to FB input pin (#%d)\n"
00179 "\ton block #%d (%s).\n", ipin, inet,
00180 net[inet].name, node_block_pin, iblk,
00181 block[iblk].name);
00182 error++;
00183 }
00184
00185 if(net[inet].is_global)
00186 printf("\tNet is global, but FB pin is not.\n\n");
00187 else
00188 printf("\tCLB pin is global, but net is not.\n\n");
00189 }
00190 }
00191
00192 return (error);
00193 }
00194
00195
00196 static int
00197 check_fb_conn(int iblk,
00198 int num_conn)
00199 {
00200
00201
00202
00203 int iclass, ipin, error;
00204 t_type_ptr type;
00205
00206 error = 0;
00207 type = block[iblk].type;
00208
00209 if(type == IO_TYPE)
00210 {
00211 if(num_conn != 1)
00212 {
00213 printf(ERRTAG "io blk #%d (%s) has %d pins.\n",
00214 iblk, block[iblk].name, num_conn);
00215 error++;
00216 }
00217 }
00218 else if(num_conn < 2)
00219 {
00220 printf("Warning: logic block #%d (%s) has only %d pin.\n",
00221 iblk, block[iblk].name, num_conn);
00222
00223
00224
00225
00226
00227
00228 if(num_conn == 1)
00229 {
00230 for(ipin = 0; ipin < type->num_pins; ipin++)
00231 {
00232 if(block[iblk].nets[ipin] != OPEN)
00233 {
00234 iclass = type->pin_class[ipin];
00235
00236 if(type->class_inf[iclass].type != DRIVER)
00237 {
00238 error++;
00239 }
00240 else
00241 {
00242 printf
00243 ("\tPin is an output -- may be a constant generator.\n"
00244 "\tNon-fatal, but check this.\n");
00245 }
00246
00247 break;
00248 }
00249 }
00250 }
00251 else
00252 {
00253 error++;
00254 }
00255 }
00256
00257
00258
00259
00260 if(num_conn > type->num_pins)
00261 {
00262 printf("Error: logic block #%d with output %s has %d pins.\n",
00263 iblk, block[iblk].name, num_conn);
00264 error++;
00265 }
00266
00267 return (error);
00268 }
00269
00270
00271 static int
00272 check_for_duplicate_block_names(void)
00273 {
00274
00275
00276
00277
00278 int error, iblk;
00279 struct s_hash **block_hash_table, *h_ptr;
00280 struct s_hash_iterator hash_iterator;
00281
00282 error = 0;
00283 block_hash_table = alloc_hash_table();
00284
00285 for(iblk = 0; iblk < num_blocks; iblk++)
00286 h_ptr =
00287 insert_in_hash_table(block_hash_table, block[iblk].name, iblk);
00288
00289 hash_iterator = start_hash_table_iterator();
00290 h_ptr = get_next_hash(block_hash_table, &hash_iterator);
00291
00292 while(h_ptr != NULL)
00293 {
00294 if(h_ptr->count != 1)
00295 {
00296 printf
00297 ("Error: %d blocks are named %s. Block names must be unique."
00298 "\n", h_ptr->count, h_ptr->name);
00299 error++;
00300 }
00301 h_ptr = get_next_hash(block_hash_table, &hash_iterator);
00302 }
00303
00304 free_hash_table(block_hash_table);
00305 return (error);
00306 }
00307
00308
00309 static int
00310 check_subblocks(int iblk,
00311 t_subblock_data * subblock_data_ptr,
00312 int *num_uses_of_fb_pin,
00313 int **num_uses_of_sblk_opin)
00314 {
00315
00316
00317
00318
00319 int error, isub, ipin, fb_pin, num_pins_fb;
00320 int num_subblocks, max_subblocks_per_block, subblock_lut_size,
00321 num_outputs;
00322 t_subblock *subblock_inf;
00323
00324 num_pins_fb = block[iblk].type->num_pins;
00325 error = 0;
00326 subblock_inf = subblock_data_ptr->subblock_inf[iblk];
00327 num_subblocks = subblock_data_ptr->num_subblocks_per_block[iblk];
00328 max_subblocks_per_block = block[iblk].type->max_subblocks;
00329 subblock_lut_size = block[iblk].type->max_subblock_inputs;
00330 num_outputs = block[iblk].type->max_subblock_outputs;
00331
00332 if(num_subblocks < 1 || num_subblocks > max_subblocks_per_block)
00333 {
00334 printf("Error: block #%d (%s) contains %d subblocks.\n",
00335 iblk, block[iblk].name, num_subblocks);
00336 error++;
00337 }
00338
00339
00340
00341
00342 for(isub = 0; isub < num_subblocks; isub++)
00343 {
00344
00345 for(ipin = 0; ipin < subblock_lut_size; ipin++)
00346 {
00347 fb_pin = subblock_inf[isub].inputs[ipin];
00348 error += check_subblock_pin(fb_pin, 0,
00349 (num_pins_fb +
00350 (num_subblocks *
00351 num_outputs) - 1), RECEIVER,
00352 iblk, isub, subblock_inf);
00353
00354 }
00355
00356 for(ipin = 0; ipin < num_outputs; ++ipin)
00357 {
00358 fb_pin = subblock_inf[isub].outputs[ipin];
00359 error += check_subblock_pin(fb_pin, 0, (num_pins_fb - 1),
00360 DRIVER, iblk, isub,
00361 subblock_inf);
00362 }
00363
00364
00365 fb_pin = subblock_inf[isub].clock;
00366 error += check_subblock_pin(fb_pin, 0,
00367 (num_pins_fb +
00368 (num_subblocks * num_outputs) - 1),
00369 RECEIVER, iblk, isub, subblock_inf);
00370
00371 }
00372
00373
00374
00375 if(error != 0)
00376 return (error);
00377
00378 load_one_fb_fanout_count(subblock_inf,
00379 num_subblocks, num_uses_of_fb_pin,
00380 num_uses_of_sblk_opin, iblk);
00381
00382 error += check_fb_to_subblock_connections(iblk, subblock_inf,
00383 num_subblocks,
00384 num_uses_of_fb_pin);
00385
00386 error += check_internal_subblock_connections(subblock_data_ptr, iblk,
00387 num_uses_of_sblk_opin);
00388
00389 return (error);
00390 }
00391
00392
00393 static int
00394 check_subblock_pin(int fb_pin,
00395 int min_val,
00396 int max_val,
00397 enum e_pin_type pin_type,
00398 int iblk,
00399 int isubblk,
00400 t_subblock * subblock_inf)
00401 {
00402
00403
00404
00405
00406 int iclass;
00407 t_type_ptr type;
00408
00409 type = block[iblk].type;
00410
00411 if(fb_pin != OPEN)
00412 {
00413 if(fb_pin < min_val || fb_pin > max_val)
00414 {
00415 printf("Error: Block #%d (%s) subblock #%d (%s)"
00416 "connects to nonexistent clb pin #%d.\n", iblk,
00417 block[iblk].name, isubblk,
00418 subblock_inf[isubblk].name, fb_pin);
00419 return (1);
00420 }
00421
00422 if(fb_pin < type->num_pins)
00423 {
00424 iclass = type->pin_class[fb_pin];
00425 if(type->class_inf[iclass].type != pin_type)
00426 {
00427 printf
00428 ("Error: Block #%d (%s) subblock #%d (%s) pin connects\n"
00429 "\tto clb pin (#%d) of wrong input/output type.\n",
00430 iblk, block[iblk].name, isubblk,
00431 subblock_inf[isubblk].name, fb_pin);
00432 return (1);
00433 }
00434 }
00435 }
00436
00437 return (0);
00438 }
00439
00440
00441 static void
00442 check_for_multiple_sink_connections(void)
00443 {
00444
00445
00446
00447
00448
00449
00450 int iblk, ipin, inet, iclass, class_pin;
00451 int *num_pins_connected;
00452 t_type_ptr type;
00453
00454 num_pins_connected = my_calloc(num_nets, sizeof(int));
00455
00456
00457
00458
00459 for(iblk = 0; iblk < num_blocks; iblk++)
00460 {
00461 type = block[iblk].type;
00462 for(iclass = 0; iclass < type->num_class; iclass++)
00463 {
00464
00465
00466
00467
00468 if(type->class_inf[iclass].type == DRIVER)
00469 continue;
00470
00471 for(class_pin = 0;
00472 class_pin < type->class_inf[iclass].num_pins;
00473 class_pin++)
00474 {
00475 ipin = type->class_inf[iclass].pinlist[class_pin];
00476 inet = block[iblk].nets[ipin];
00477
00478 if(inet != OPEN)
00479 num_pins_connected[inet]++;
00480 }
00481
00482 for(class_pin = 0;
00483 class_pin < type->class_inf[iclass].num_pins;
00484 class_pin++)
00485 {
00486
00487 ipin = type->class_inf[iclass].pinlist[class_pin];
00488 inet = block[iblk].nets[ipin];
00489
00490 if(inet != OPEN)
00491 {
00492 if(num_pins_connected[inet] > 1)
00493 {
00494 printf
00495 ("Warning: block %d (%s) connects %d pins of class "
00496 "%d to net %d (%s).\n", iblk,
00497 block[iblk].name,
00498 num_pins_connected[inet],
00499 iclass, inet,
00500 net[inet].name);
00501
00502 printf
00503 ("\tThis does not make sense for many logic blocks "
00504 "(e.g. LUTs).\n"
00505 "\tBe sure you really want this.\n");
00506 }
00507
00508 num_pins_connected[inet] = 0;
00509 }
00510 }
00511 }
00512 }
00513
00514 free(num_pins_connected);
00515 }
00516
00517
00518 static int
00519 get_num_conn(int bnum)
00520 {
00521
00522
00523
00524 int i, num_conn;
00525 t_type_ptr type;
00526
00527 type = block[bnum].type;
00528
00529 num_conn = 0;
00530
00531 for(i = 0; i < type->num_pins; i++)
00532 {
00533 if(block[bnum].nets[i] != OPEN)
00534 num_conn++;
00535 }
00536
00537 return (num_conn);
00538 }
00539
00540
00541 static int
00542 check_internal_subblock_connections(t_subblock_data * subblock_data_ptr,
00543 int iblk,
00544 int **num_uses_of_sblk_opin)
00545 {
00546
00547
00548
00549
00550
00551
00552 int num_const_gen, num_ff, isub, ipin, error, opin, i;
00553 boolean has_inputs, has_outputs;
00554 int subblock_lut_size;
00555 int num_subblocks;
00556 t_subblock *subblock_inf;
00557 t_type_ptr type;
00558
00559 type = block[iblk].type;
00560 subblock_lut_size = type->max_subblock_inputs;
00561 num_subblocks = subblock_data_ptr->num_subblocks_per_block[iblk];
00562 subblock_inf = subblock_data_ptr->subblock_inf[iblk];
00563
00564 num_const_gen = 0;
00565 num_ff = 0;
00566 error = 0;
00567
00568 for(isub = 0; isub < num_subblocks; isub++)
00569 {
00570
00571 has_inputs = FALSE;
00572 for(ipin = 0; ipin < subblock_lut_size; ipin++)
00573 {
00574 if(subblock_inf[isub].inputs[ipin] != OPEN)
00575 {
00576 has_inputs = TRUE;
00577 break;
00578 }
00579 }
00580 has_outputs = FALSE;
00581 for(opin = 0; opin < type->max_subblock_outputs; opin++)
00582 {
00583 if(num_uses_of_sblk_opin[isub][opin] != 0)
00584 {
00585 has_outputs = TRUE;
00586 break;
00587 }
00588 }
00589
00590 if(type == IO_TYPE)
00591 {
00592
00593 assert((has_inputs && !has_outputs)
00594 || (!has_inputs && has_outputs));
00595 }
00596 else if(!has_outputs)
00597 {
00598
00599 if(has_inputs || subblock_inf[isub].clock != OPEN)
00600 {
00601 printf
00602 ("Error: output of subblock #%d (%s) of block #%d (%s) is "
00603 "never used.\n", isub,
00604 subblock_inf[isub].name, iblk,
00605 block[iblk].name);
00606 error++;
00607 }
00608 }
00609
00610
00611
00612
00613 else
00614 {
00615
00616 if(!has_inputs)
00617 {
00618 if(subblock_inf[isub].clock == OPEN)
00619 {
00620 printf
00621 ("Warning: block #%d (%s), subblock #%d (%s) is a "
00622 "constant generator.\n\t(Has no inputs.)\n",
00623 iblk, block[iblk].name, isub,
00624 subblock_inf[isub].name);
00625 num_const_gen++;
00626 }
00627 else
00628 {
00629 printf
00630 ("Error: block #%d (%s), subblock #%d (%s) is a CLOCKED "
00631 "\n\tconstant generator.\n\t(Has no inputs but is clocked.)\n",
00632 iblk, block[iblk].name, isub,
00633 subblock_inf[isub].name);
00634 num_const_gen++;
00635 error++;
00636 }
00637 }
00638
00639 else
00640 {
00641 if(subblock_inf[isub].clock != OPEN)
00642 {
00643 for(i = 0; i < type->max_subblock_outputs;
00644 i++)
00645 {
00646 if(subblock_inf[isub].
00647 outputs[i] != OPEN)
00648 {
00649 num_ff++;
00650 }
00651 }
00652 }
00653 }
00654 }
00655 }
00656
00657 subblock_data_ptr->num_const_gen += num_const_gen;
00658 subblock_data_ptr->num_ff += num_ff;
00659 return (error);
00660 }
00661
00662
00663 static int
00664 check_fb_to_subblock_connections(int iblk,
00665 t_subblock * subblock_inf,
00666 int num_subblocks,
00667 int *num_uses_of_fb_pin)
00668 {
00669
00670
00671
00672
00673
00674
00675
00676
00677 int ipin, isub, fb_pin, error;
00678 int num_outputs;
00679
00680 error = 0;
00681 num_outputs = block[iblk].type->max_subblock_outputs;
00682
00683
00684
00685 for(isub = 0; isub < num_subblocks; isub++)
00686 {
00687 for(ipin = 0; ipin < num_outputs; ++ipin)
00688 {
00689 fb_pin = subblock_inf[isub].outputs[ipin];
00690
00691 if(fb_pin != OPEN)
00692 num_uses_of_fb_pin[fb_pin]++;
00693 }
00694 }
00695
00696 for(ipin = 0; ipin < block[iblk].type->num_pins; ipin++)
00697 {
00698
00699 if(block[iblk].nets[ipin] != OPEN)
00700 {
00701 if(is_opin(ipin, block[iblk].type))
00702 {
00703 if(num_uses_of_fb_pin[ipin] == 0)
00704 {
00705 printf
00706 ("Error: output pin %d on block #%d (%s) is not driven "
00707 "by any subblock.\n", ipin, iblk,
00708 block[iblk].name);
00709 error++;
00710 }
00711 else if(num_uses_of_fb_pin[ipin] > 1)
00712 {
00713 printf
00714 ("Error: output pin %d on block #%d (%s) is driven "
00715 "by %d subblocks.\n", ipin, iblk,
00716 block[iblk].name,
00717 num_uses_of_fb_pin[ipin]);
00718 error++;
00719 }
00720 }
00721
00722 else
00723 {
00724 if(num_uses_of_fb_pin[ipin] <= 0)
00725 {
00726 printf
00727 ("Error: pin %d on block #%d (%s) does not fanout to any "
00728 "subblocks.\n", ipin, iblk,
00729 block[iblk].name);
00730 error++;
00731 }
00732 }
00733 }
00734
00735 else if(is_opin(ipin, block[iblk].type))
00736 {
00737 if(num_uses_of_fb_pin[ipin] > 1)
00738 {
00739 printf
00740 ("Error: pin %d on block #%d (%s) is driven by %d "
00741 "subblocks.\n", ipin, iblk, block[iblk].name,
00742 num_uses_of_fb_pin[ipin]);
00743 error++;
00744 }
00745 }
00746 }
00747
00748 return (error);
00749 }