#include <stdio.h>
#include "util.h"
#include "vpr_types.h"
#include "globals.h"
#include "hash.h"
#include "vpr_utils.h"
#include "check_netlist.h"
#include "assert.h"
Go to the source code of this file.
Functions | |
static int | check_connections_to_global_fb_pins (int inet) |
static int | check_fb_conn (int iblk, int num_conn) |
static void | check_for_multiple_sink_connections (void) |
static int | check_for_duplicate_block_names (void) |
static int | get_num_conn (int bnum) |
static int | check_subblocks (int iblk, t_subblock_data *subblock_data_ptr, int *num_uses_of_fb_pin, int **num_uses_of_sblk_opin) |
static int | check_subblock_pin (int fb_pin, int min_val, int max_val, enum e_pin_type pin_type, int iblk, int isubblk, t_subblock *subblock_inf) |
static int | check_internal_subblock_connections (t_subblock_data *subblock_data_ptr, int iblk, int **num_uses_of_sblk_opin) |
static int | check_fb_to_subblock_connections (int iblk, t_subblock *subblock_inf, int num_subblocks, int *num_uses_of_fb_pin) |
void | check_netlist (t_subblock_data *subblock_data_ptr) |
static int check_connections_to_global_fb_pins | ( | int | inet | ) | [static] |
Definition at line 136 of file check_netlist.c.
00137 { 00138 00139 /* Checks that a global net (inet) connects only to global FB input pins * 00140 * and that non-global nets never connects to a global FB pin. Either * 00141 * global or non-global nets are allowed to connect to pads. */ 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 /* For now global signals can be driven by an I/O pad or any FB output * 00149 * although a FB output generates a warning. I could make a global FB * 00150 * output pin type to allow people to make architectures that didn't have * 00151 * this warning. */ 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 /* Allow a FB output pin to drive a global net (warning only). */ 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 { /* Otherwise -> Error */ 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 } /* End for all pins */ 00191 00192 return (error); 00193 }
static int check_fb_conn | ( | int | iblk, | |
int | num_conn | |||
) | [static] |
Definition at line 197 of file check_netlist.c.
00199 { 00200 00201 /* Checks that the connections into and out of the fb make sense. */ 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 /* Allow the case where we have only one OUTPUT pin connected to continue. * 00224 * This is used sometimes as a constant generator for a primary output, * 00225 * but I will still warn the user. If the only pin connected is an input, * 00226 * abort. */ 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 /* This case should already have been flagged as an error -- this is * 00258 * just a redundant double check. */ 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 }
static int check_fb_to_subblock_connections | ( | int | iblk, | |
t_subblock * | subblock_inf, | |||
int | num_subblocks, | |||
int * | num_uses_of_fb_pin | |||
) | [static] |
Definition at line 664 of file check_netlist.c.
00668 { 00669 00670 /* This routine checks that each non-OPEN clb input pin connects to some * 00671 * subblock inputs, and that each non-OPEN clb output pin is driven by * 00672 * exactly one subblock output. It returns the number of errors found. * 00673 * Note that num_uses_of_fb_pin is used to store the number of out-edges * 00674 * (fanout) for a FB ipin, and the number of in-edges (fanin) for a FB * 00675 * opin. */ 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 /* Count how many things connect to each clb output pin. */ 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) /* Guaranteed to connect to DRIVER pin only */ 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 { /* FB output */ 00703 if(num_uses_of_fb_pin[ipin] == 0) 00704 { /* No driver? */ 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 { /* Multiple drivers? */ 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 { /* FB ipin */ 00724 if(num_uses_of_fb_pin[ipin] <= 0) 00725 { /* Fans out? */ 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 /* End if not OPEN */ 00735 else if(is_opin(ipin, block[iblk].type)) 00736 { /* OPEN FB output pin */ 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 }
static int check_for_duplicate_block_names | ( | void | ) | [static] |
Definition at line 272 of file check_netlist.c.
00273 { 00274 00275 /* Checks that all blocks have duplicate names. Returns the number of * 00276 * duplicate names. */ 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 }
static void check_for_multiple_sink_connections | ( | void | ) | [static] |
Definition at line 442 of file check_netlist.c.
00443 { 00444 00445 /* The check is for nets that connect more than once to the same class of * 00446 * pins on the same block. For LUTs and cluster-based logic blocks that * 00447 * doesn't make sense, although for some logic blocks it does. The router * 00448 * can now handle this case, so maybe I should get rid of this check. */ 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 /* Have to do the check block by block, rather than net by net, for speed. * 00457 * This makes the code a bit messy. */ 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 /* Two DRIVER pins can never connect to the same net (already checked by * 00466 * the multiple driver check) so skip that check. */ 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 }
static int check_internal_subblock_connections | ( | t_subblock_data * | subblock_data_ptr, | |
int | iblk, | |||
int ** | num_uses_of_sblk_opin | |||
) | [static] |
Definition at line 542 of file check_netlist.c.
00545 { 00546 00547 /* This routine checks that all subblocks in this block are either * 00548 * completely empty (no pins hooked to anything) or have their output used * 00549 * somewhere. It also counts the number of constant generators (no input * 00550 * sblks) and the number of FFs used in the circuit. */ 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 /* Subblock inputs and outputs are faked for I/O's so this is an internal error */ 00593 assert((has_inputs && !has_outputs) 00594 || (!has_inputs && has_outputs)); 00595 } 00596 else if(!has_outputs) 00597 { /* Output unused */ 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 /* End if output unused */ 00612 /* Check that subblocks whose output is used have inputs. */ 00613 else 00614 { /* Subblock output is used. */ 00615 00616 if(!has_inputs) 00617 { /* No inputs are used */ 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 { /* Both input and output are used */ 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 } /* End for all subblocks */ 00656 00657 subblock_data_ptr->num_const_gen += num_const_gen; 00658 subblock_data_ptr->num_ff += num_ff; 00659 return (error); 00660 }
void check_netlist | ( | t_subblock_data * | subblock_data_ptr | ) |
Definition at line 52 of file check_netlist.c.
00053 { 00054 00055 /* This routine checks that the netlist makes sense, and sets the num_ff * 00056 * and num_const_gen members of subblock_data. */ 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 /* Determine max number of subblocks for all types */ 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 /* one mem alloc to save space */ 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 /* Check that nets fanout and have a driver. */ 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 /* Check that each block makes sense. */ 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 }
static int check_subblock_pin | ( | int | fb_pin, | |
int | min_val, | |||
int | max_val, | |||
enum e_pin_type | pin_type, | |||
int | iblk, | |||
int | isubblk, | |||
t_subblock * | subblock_inf | |||
) | [static] |
Definition at line 394 of file check_netlist.c.
00401 { 00402 00403 /* Checks that this subblock pin connects to a valid clb pin or BLE output * 00404 * within the clb. Returns the number of errors found. */ 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 { /* clb pin */ 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 }
static int check_subblocks | ( | int | iblk, | |
t_subblock_data * | subblock_data_ptr, | |||
int * | num_uses_of_fb_pin, | |||
int ** | num_uses_of_sblk_opin | |||
) | [static] |
Definition at line 310 of file check_netlist.c.
00314 { 00315 00316 /* This routine checks the subblocks of iblk (which must be a FB). It * 00317 * returns the number of errors found. */ 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 /* Check that all pins connect to the proper type of FB pin and are in the * 00340 * correct range. */ 00341 00342 for(isub = 0; isub < num_subblocks; isub++) 00343 { 00344 00345 for(ipin = 0; ipin < subblock_lut_size; ipin++) 00346 { /* Input pins */ 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 { /* Output pins. */ 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 /* Subblock clock pin. */ 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 } /* End subblock for loop. */ 00372 00373 /* If pins out of range, return. Could get seg faults otherwise. */ 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 }
static int get_num_conn | ( | int | bnum | ) | [static] |
Definition at line 519 of file check_netlist.c.
00520 { 00521 00522 /* This routine returns the number of connections to a block. */ 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 }