VPR-6.0
|
00001 #include <string.h> 00002 #include <stdio.h> 00003 #include <assert.h> 00004 #include "util.h" 00005 #include "vpr_types.h" 00006 #include "globals.h" 00007 #include "read_blif.h" 00008 #include "arch_types.h" 00009 00010 /* PRINT_PIN_NETS */ 00011 00012 /* TODO: use hash table instead of this to keep data structures consistent */ 00013 #define HASHSIZE 4093 00014 00015 #define MAX_ATOM_PARSE 200000000 00016 00017 /** 00018 * @file 00019 * 00020 * This source file will read in a FLAT blif netlist consisting 00021 * of .inputs, .outputs, .names and .latch commands. It currently 00022 * does not handle hierarchical blif files. Hierarchical 00023 * blif files can be flattened via the read_blif and write_blif 00024 * commands of sis. LUT circuits should only have .names commands; 00025 * there should be no gates. This parser performs limited error 00026 * checking concerning the consistency of the netlist it obtains. 00027 * .inputs and .outputs statements must be given; this parser does 00028 * not infer primary inputs and outputs from non-driven and fanout 00029 * free nodes. This parser can be extended to do this if necessary, 00030 * or the sis read_blif and write_blif commands can be used to put a 00031 * netlist into the standard format. 00032 * V. Betz, August 25, 1994. 00033 * Added more error checking, March 30, 1995, V. Betz 00034 */ 00035 00036 00037 static int *num_driver, *temp_num_pins; 00038 static int *logical_block_input_count, *logical_block_output_count; 00039 static int num_blif_models; 00040 00041 /**@{*/ 00042 /** # of .input, .output, .model and .end lines */ 00043 static int ilines, olines, model_lines, endlines; 00044 static struct hash_logical_nets **hash; 00045 static char *model; 00046 static FILE *blif; 00047 /**@}*/ 00048 00049 static int add_vpack_net(char *ptr, 00050 int type, 00051 int bnum, 00052 int bport, 00053 int bpin, 00054 boolean is_global, 00055 int doall); 00056 static void get_tok(char *buffer, 00057 int pass, 00058 int doall, 00059 boolean *done, 00060 boolean *add_truth_table, 00061 INP t_model* inpad_model, 00062 INP t_model* outpad_model, 00063 INP t_model* logic_model, 00064 INP t_model* latch_model, 00065 INP t_model* user_models); 00066 static void init_parse(int doall); 00067 static void check_net(boolean sweep_hanging_nets_and_inputs); 00068 static void free_parse(void); 00069 static void io_line(int in_or_out, 00070 int doall, t_model *io_model); 00071 static void add_lut(int doall, 00072 t_model *logic_model); 00073 static void add_latch(int doall, INP t_model *latch_model); 00074 static void add_subckt(int doall, INP t_model *user_models); 00075 static void dum_parse(char *buf); 00076 static int hash_value(char *name); 00077 static void check_and_count_models(int doall, const char* model_name, t_model* user_models); 00078 static void load_default_models(INP t_model *library_models, OUTP t_model** inpad_model, OUTP t_model** outpad_model, 00079 OUTP t_model** logic_model, OUTP t_model** latch_model); 00080 00081 void 00082 read_blif(char *blif_file, 00083 boolean sweep_hanging_nets_and_inputs, 00084 t_model *user_models, 00085 t_model *library_models) 00086 { 00087 char buffer[BUFSIZE]; 00088 int pass, doall; 00089 boolean done; 00090 boolean add_truth_table; 00091 t_model *inpad_model, *outpad_model, *logic_model, *latch_model; 00092 00093 00094 blif = fopen(blif_file, "r"); 00095 if(blif == NULL) { 00096 printf("Failed to open blif file %s\n", blif_file); 00097 exit(1); 00098 } 00099 load_default_models(library_models, &inpad_model, &outpad_model, &logic_model, &latch_model); 00100 00101 /* doall = 0 means do a counting pass, doall = 1 means allocate and load data structures */ 00102 for(doall = 0; doall <= 1; doall++) 00103 { 00104 init_parse(doall); 00105 00106 /* Three passes to ensure inputs are first blocks, outputs second and * 00107 * LUTs and latches third, subckts last. Just makes the output netlist more readable. */ 00108 00109 for(pass = 0; pass <= 4; pass++) 00110 { 00111 linenum = 0; /* Reset line number. */ 00112 done = FALSE; 00113 add_truth_table = FALSE; 00114 model_lines = 0; 00115 while(my_fgets(buffer, BUFSIZE, blif) != NULL) 00116 { 00117 get_tok(buffer, pass, doall, &done, &add_truth_table, inpad_model, outpad_model, logic_model, latch_model, user_models); 00118 } 00119 rewind(blif); /* Start at beginning of file again */ 00120 } 00121 } 00122 fclose(blif); 00123 check_net(sweep_hanging_nets_and_inputs); 00124 free_parse(); 00125 } 00126 00127 /** Allocates and initializes the data structures needed for the parse. */ 00128 static void 00129 init_parse(int doall) 00130 { 00131 int i; 00132 struct hash_logical_nets *h_ptr; 00133 00134 if(!doall) 00135 { /* Initialization before first (counting) pass */ 00136 num_logical_nets = 0; 00137 /* TODO: use hash table instead of this */ 00138 hash = (struct hash_logical_nets **)my_calloc(sizeof(struct hash_logical_nets *), HASHSIZE); 00139 } 00140 /* Allocate memory for second (load) pass */ 00141 else 00142 { 00143 vpack_net = (struct s_net *)my_calloc(num_logical_nets, sizeof(struct s_net)); 00144 logical_block = (struct s_logical_block *)my_calloc(num_logical_blocks, sizeof(struct s_logical_block)); 00145 num_driver = (int *)my_malloc(num_logical_nets * sizeof(int)); 00146 temp_num_pins = (int *)my_malloc(num_logical_nets * sizeof(int)); 00147 00148 logical_block_input_count = my_calloc(num_logical_blocks, sizeof(int)); 00149 logical_block_output_count = my_calloc(num_logical_blocks, sizeof(int)); 00150 00151 00152 for(i = 0; i < num_logical_nets; i++) 00153 { 00154 num_driver[i] = 0; 00155 vpack_net[i].num_sinks = 0; 00156 vpack_net[i].name = NULL; 00157 vpack_net[i].node_block = NULL; 00158 vpack_net[i].node_block_port = NULL; 00159 vpack_net[i].node_block_pin = NULL; 00160 vpack_net[i].is_global = FALSE; 00161 } 00162 00163 for(i = 0; i < num_logical_blocks; i++) 00164 { 00165 logical_block[i].index = i; 00166 } 00167 00168 00169 for(i = 0; i < HASHSIZE; i++) 00170 { 00171 h_ptr = hash[i]; 00172 while(h_ptr != NULL) 00173 { 00174 vpack_net[h_ptr->index].node_block = (int *)my_malloc(h_ptr->count * sizeof(int)); 00175 vpack_net[h_ptr->index].node_block_port = (int *)my_malloc(h_ptr->count * sizeof(int)); 00176 vpack_net[h_ptr->index].node_block_pin = (int *)my_malloc(h_ptr->count * sizeof(int)); 00177 00178 /* For avoiding assigning values beyond end of pins array. */ 00179 temp_num_pins[h_ptr->index] = h_ptr->count; 00180 vpack_net[h_ptr->index].name = my_strdup(h_ptr->name); 00181 h_ptr = h_ptr->next; 00182 } 00183 } 00184 #ifdef PRINT_PIN_NETS 00185 printf("i\ttemp_num_pins\n\n"); 00186 for (i=0;i<num_logical_nets;i++) { 00187 printf("%d\t%d\n",i,temp_num_pins[i]); 00188 } 00189 printf("num_logical_nets %d\n", num_logical_nets); 00190 #endif 00191 } 00192 00193 /* Initializations for both passes. */ 00194 00195 ilines = 0; 00196 olines = 0; 00197 model_lines = 0; 00198 endlines = 0; 00199 num_p_inputs = 0; 00200 num_p_outputs = 0; 00201 num_luts = 0; 00202 num_latches = 0; 00203 num_logical_blocks = 0; 00204 num_blif_models = 0; 00205 num_subckts = 0; 00206 } 00207 00208 00209 /** Figures out which, if any token is at the start of this line and 00210 * takes the appropriate action. 00211 */ 00212 static void 00213 get_tok(char *buffer, 00214 int pass, 00215 int doall, 00216 boolean *done, 00217 boolean *add_truth_table, 00218 INP t_model* inpad_model, 00219 INP t_model* outpad_model, 00220 INP t_model* logic_model, 00221 INP t_model* latch_model, 00222 INP t_model* user_models) 00223 { 00224 #define TOKENS " \t\n" 00225 char *ptr; 00226 char *fn; 00227 struct s_linked_vptr *data; 00228 00229 ptr = my_strtok(buffer, TOKENS, blif, buffer); 00230 if(ptr == NULL) 00231 return; 00232 00233 if(*add_truth_table) { 00234 if(ptr[0] == '0' || ptr[0] == '1' || ptr[0] == '-') { 00235 data = my_malloc(sizeof(struct s_linked_vptr)); 00236 fn = ptr; 00237 ptr = my_strtok(NULL, TOKENS, blif, buffer); 00238 if(!ptr || strlen(ptr) != 1) { 00239 if(strlen(fn) == 1) { 00240 /* constant generator */ 00241 data->next = logical_block[num_logical_blocks - 1].truth_table; 00242 data->data_vptr = my_malloc(strlen(fn) + 4); 00243 sprintf(data->data_vptr, " %s", fn); 00244 logical_block[num_logical_blocks - 1].truth_table = data; 00245 ptr = fn; 00246 } else { 00247 printf(ERRTAG "Unknown truth table data %s %s\n", fn, ptr); 00248 exit(1); 00249 } 00250 } else { 00251 data->next = logical_block[num_logical_blocks - 1].truth_table; 00252 data->data_vptr = my_malloc(strlen(fn) + 3); 00253 sprintf(data->data_vptr, "%s %s", fn, ptr); 00254 logical_block[num_logical_blocks - 1].truth_table = data; 00255 } 00256 } 00257 } 00258 00259 if(strcmp(ptr, ".names") == 0) 00260 { 00261 *add_truth_table = FALSE; 00262 if(pass == 3) 00263 { 00264 add_lut(doall, logic_model); 00265 *add_truth_table = doall; 00266 } 00267 else 00268 { 00269 dum_parse(buffer); 00270 } 00271 return; 00272 } 00273 00274 if(strcmp(ptr, ".latch") == 0) 00275 { 00276 *add_truth_table = FALSE; 00277 if(pass == 3) 00278 { 00279 add_latch(doall, latch_model); 00280 } 00281 else 00282 { 00283 dum_parse(buffer); 00284 } 00285 return; 00286 } 00287 00288 if(strcmp(ptr, ".model") == 0) 00289 { 00290 *add_truth_table = FALSE; 00291 ptr = my_strtok(NULL, TOKENS, blif, buffer); 00292 if(doall && pass == 4) 00293 { 00294 if(ptr != NULL) 00295 { 00296 model = (char *)my_malloc((strlen(ptr) + 1) * sizeof(char)); 00297 strcpy(model, ptr); 00298 if(blif_circuit_name == NULL) { 00299 blif_circuit_name = my_strdup(model); 00300 } 00301 } 00302 else 00303 { 00304 model = (char *)my_malloc(sizeof(char)); 00305 model[0] = '\0'; 00306 } 00307 } 00308 00309 if(pass == 0 && model_lines > 0) { 00310 check_and_count_models(doall, ptr, user_models); 00311 } else { 00312 dum_parse(buffer); 00313 } 00314 model_lines++; 00315 return; 00316 } 00317 00318 if(strcmp(ptr, ".inputs") == 0) 00319 { 00320 *add_truth_table = FALSE; 00321 /* packing can only one fully defined model */ 00322 if(pass == 1 && model_lines == 1) 00323 { 00324 io_line(DRIVER, doall, inpad_model); 00325 *done = 1; 00326 } 00327 else 00328 { 00329 dum_parse(buffer); 00330 if(pass == 4 && doall) 00331 ilines++; /* Error checking only */ 00332 } 00333 return; 00334 } 00335 00336 if(strcmp(ptr, ".outputs") == 0) 00337 { 00338 *add_truth_table = FALSE; 00339 /* packing can only one fully defined model */ 00340 if(pass == 2 && model_lines == 1) 00341 { 00342 io_line(RECEIVER, doall, outpad_model); 00343 *done = 1; 00344 } 00345 else 00346 { 00347 dum_parse(buffer); 00348 if(pass == 4 && doall) 00349 olines++; /* Make sure only one .output line */ 00350 } /* For error checking only */ 00351 return; 00352 } 00353 if(strcmp(ptr, ".end") == 0) 00354 { 00355 *add_truth_table = FALSE; 00356 if(pass == 4 && doall) 00357 { 00358 endlines++; /* Error checking only */ 00359 } 00360 return; 00361 } 00362 00363 if(strcmp(ptr, ".subckt") == 0) 00364 { 00365 *add_truth_table = FALSE; 00366 if(pass == 3) 00367 { 00368 add_subckt(doall, user_models); 00369 } 00370 } 00371 00372 /* Could have numbers following a .names command, so not matching any * 00373 * of the tokens above is not an error. */ 00374 00375 } 00376 00377 00378 /** Continue parsing to the end of this (possibly continued) line. */ 00379 static void 00380 dum_parse(char *buf) 00381 { 00382 while(my_strtok(NULL, TOKENS, blif, buf) != NULL) 00383 ; 00384 } 00385 00386 00387 /** Adds a LUT as VPACK_COMB from (.names) currently being parsed to the logical_block array. Adds 00388 * its pins to the nets data structure by calling add_vpack_net. If doall is 00389 * zero this is a counting pass; if it is 1 this is the final (loading) 00390 * pass. 00391 */ 00392 static void 00393 add_lut(int doall, 00394 t_model *logic_model) 00395 { 00396 char *ptr, **saved_names, buf[BUFSIZE]; 00397 int i, j, output_net_index; 00398 00399 saved_names = (char**) alloc_matrix(0, logic_model->inputs->size, 0, BUFSIZE - 1, sizeof(char)); 00400 00401 num_logical_blocks++; 00402 00403 /* Count # nets connecting */ 00404 i = 0; 00405 while((ptr = my_strtok(NULL, TOKENS, blif, buf)) != NULL) 00406 { 00407 strcpy(saved_names[i], ptr); 00408 i++; 00409 } 00410 output_net_index = i - 1; 00411 if(strcmp(saved_names[output_net_index],"unconn") == 0) { 00412 /* unconn is a keyword to pad unused pins, ignore this block */ 00413 free_matrix(saved_names, 0, logic_model->inputs->size, 0, sizeof(char)); 00414 num_logical_blocks--; 00415 return; 00416 } 00417 00418 if(!doall) 00419 { /* Counting pass only ... */ 00420 for(j = 0; j <= output_net_index; j++) 00421 /* On this pass it doesn't matter if RECEIVER or DRIVER. Just checking if in hash. [0] should be DRIVER */ 00422 add_vpack_net(saved_names[j], RECEIVER, num_logical_blocks - 1, 0, j, FALSE, doall); 00423 free_matrix(saved_names, 0, logic_model->inputs->size, 0, sizeof(char)); 00424 return; 00425 } 00426 00427 logical_block[num_logical_blocks - 1].model = logic_model; 00428 00429 if(output_net_index > logic_model->inputs->size) { 00430 printf(ERRTAG "LUT size of %d in .blif file is too big for FPGA which has a maximum LUT size of %d\n", 00431 output_net_index, logic_model->inputs->size); 00432 exit(1); 00433 } 00434 assert(logic_model->inputs->next == NULL); 00435 assert(logic_model->outputs->next == NULL); 00436 assert(logic_model->outputs->size == 1); 00437 00438 logical_block[num_logical_blocks - 1].input_nets = 00439 (int **) my_malloc(sizeof(int*)); 00440 logical_block[num_logical_blocks - 1].output_nets = 00441 (int **) my_malloc(sizeof(int*)); 00442 logical_block[num_logical_blocks - 1].clock_net = OPEN; 00443 00444 logical_block[num_logical_blocks - 1].input_nets[0] = 00445 (int *) my_malloc(logic_model->inputs->size * sizeof(int)); 00446 logical_block[num_logical_blocks - 1].output_nets[0] = 00447 (int *) my_malloc(sizeof(int)); 00448 00449 logical_block[num_logical_blocks - 1].type = VPACK_COMB; 00450 for(i = 0; i < output_net_index; i++) /* Do inputs */ 00451 logical_block[num_logical_blocks - 1].input_nets[0][i] = add_vpack_net(saved_names[i], RECEIVER, num_logical_blocks - 1, 0, i, FALSE, doall); 00452 logical_block[num_logical_blocks - 1].output_nets[0][0] = add_vpack_net(saved_names[output_net_index], DRIVER, num_logical_blocks - 1, 0, 0, FALSE, doall); 00453 00454 for(i = output_net_index; i < logic_model->inputs->size; i++) 00455 logical_block[num_logical_blocks - 1].input_nets[0][i] = OPEN; 00456 00457 logical_block[num_logical_blocks - 1].name = my_strdup(saved_names[output_net_index]); 00458 logical_block[num_logical_blocks - 1].truth_table = NULL; 00459 num_luts++; 00460 00461 free_matrix(saved_names, 0, logic_model->inputs->size, 0, sizeof(char)); 00462 } 00463 00464 /** Adds the flipflop (.latch) currently being parsed to the logical_block array. 00465 * Adds its pins to the nets data structure by calling add_vpack_net. If doall 00466 * is zero this is a counting pass; if it is 1 this is the final 00467 * (loading) pass. Blif format for a latch is: 00468 * .latch <input> <output> <type (latch on)> <control (clock)> <init_val> 00469 * The latch pins are in .nets 0 to 2 in the order: Q D CLOCK. 00470 */ 00471 static void 00472 add_latch(int doall, INP t_model *latch_model) 00473 { 00474 00475 char *ptr, buf[BUFSIZE], saved_names[6][BUFSIZE]; 00476 int i; 00477 00478 num_logical_blocks++; 00479 00480 /* Count # parameters, making sure we don't go over 6 (avoids memory corr.) */ 00481 /* Note that we can't rely on the tokens being around unless we copy them. */ 00482 00483 for(i = 0; i < 6; i++) 00484 { 00485 ptr = my_strtok(NULL, TOKENS, blif, buf); 00486 if(ptr == NULL) 00487 break; 00488 strcpy(saved_names[i], ptr); 00489 } 00490 00491 if(i != 5) 00492 { 00493 fprintf(stderr, "Error: .latch does not have 5 parameters.\n" "check the netlist, line %d.\n", linenum); 00494 exit(1); 00495 } 00496 00497 if(!doall) 00498 { /* If only a counting pass ... */ 00499 add_vpack_net(saved_names[0], RECEIVER, num_logical_blocks - 1, 0, 0, FALSE, doall); /* D */ 00500 add_vpack_net(saved_names[1], DRIVER, num_logical_blocks - 1, 0, 0, FALSE, doall); /* Q */ 00501 add_vpack_net(saved_names[3], RECEIVER, num_logical_blocks - 1, 0, 0, TRUE, doall); /* Clock */ 00502 return; 00503 } 00504 00505 logical_block[num_logical_blocks - 1].model = latch_model; 00506 logical_block[num_logical_blocks - 1].type = VPACK_LATCH; 00507 00508 logical_block[num_logical_blocks - 1].input_nets = 00509 (int **) my_malloc(sizeof(int*)); 00510 logical_block[num_logical_blocks - 1].output_nets = 00511 (int **) my_malloc(sizeof(int*)); 00512 00513 logical_block[num_logical_blocks - 1].input_nets[0] = 00514 (int *) my_malloc(sizeof(int)); 00515 logical_block[num_logical_blocks - 1].output_nets[0] = 00516 (int *) my_malloc(sizeof(int)); 00517 00518 logical_block[num_logical_blocks - 1].output_nets[0][0] = add_vpack_net(saved_names[1], DRIVER, num_logical_blocks - 1, 0, 0, FALSE, doall); /* Q */ 00519 logical_block[num_logical_blocks - 1].input_nets[0][0] = add_vpack_net(saved_names[0], RECEIVER, num_logical_blocks - 1, 0, 0, FALSE, doall); /* D */ 00520 logical_block[num_logical_blocks - 1].clock_net = add_vpack_net(saved_names[3], RECEIVER, num_logical_blocks - 1, 0, 0, TRUE, doall); /* Clock */ 00521 00522 logical_block[num_logical_blocks - 1].name = my_strdup(saved_names[1]); 00523 logical_block[num_logical_blocks - 1].truth_table = NULL; 00524 num_latches++; 00525 } 00526 00527 static void 00528 add_subckt(int doall, t_model *user_models) 00529 { 00530 char *ptr; 00531 char *close_bracket; 00532 char subckt_name[BUFSIZE]; 00533 char buf[BUFSIZE]; 00534 fpos_t current_subckt_pos; 00535 int i, j, iparse; 00536 int subckt_index_signals = 0; 00537 char **subckt_signal_name = NULL; 00538 char *port_name, *pin_number; 00539 char **circuit_signal_name = NULL; 00540 char *subckt_logical_block_name = NULL; 00541 short toggle = 0; 00542 int input_net_count, output_net_count, input_port_count, output_port_count; 00543 t_model *cur_model; 00544 t_model_ports *port; 00545 boolean found_subckt_signal; 00546 00547 num_logical_blocks++; 00548 num_subckts++; 00549 00550 /* now we have to find the matching subckt */ 00551 /* find the name we are looking for */ 00552 strcpy(subckt_name, my_strtok(NULL, TOKENS, blif, buf)); 00553 /* get all the signals in the form z=r */ 00554 iparse = 0; 00555 while(iparse < MAX_ATOM_PARSE) 00556 { 00557 iparse++; 00558 /* Assumpiton is that it will be "signal1, =, signal1b, spacing, and repeat" */ 00559 ptr = my_strtok(NULL, " \t\n=", blif, buf); 00560 00561 if(ptr == NULL && toggle == 0) 00562 break; 00563 else if (ptr == NULL && toggle == 1) 00564 { 00565 printf("subckt %s formed incorrectly with signal=signal at\n", subckt_name, buf); 00566 exit(-1); 00567 } 00568 else if (toggle == 0) 00569 { 00570 /* ELSE - parse in one or the other */ 00571 /* allocate a new spot for both the circuit_signal name and the subckt_signal name */ 00572 subckt_signal_name = (char**)my_realloc(subckt_signal_name, (subckt_index_signals+1)*sizeof(char**)); 00573 circuit_signal_name = (char**)my_realloc(circuit_signal_name, (subckt_index_signals+1)*sizeof(char**)); 00574 00575 /* copy in the subckt_signal name */ 00576 subckt_signal_name[subckt_index_signals] = my_strdup(ptr); 00577 00578 toggle = 1; 00579 } 00580 else if (toggle == 1) 00581 { 00582 /* copy in the circuit_signal name */ 00583 circuit_signal_name[subckt_index_signals] = my_strdup(ptr); 00584 if(!doall) { 00585 /* Counting pass, does not matter if driver or receiver and pin number does not matter */ 00586 add_vpack_net(circuit_signal_name[subckt_index_signals], RECEIVER, num_logical_blocks - 1, 0, 0, FALSE, doall); 00587 } 00588 00589 toggle = 0; 00590 subckt_index_signals++; 00591 } 00592 } 00593 assert(iparse < MAX_ATOM_PARSE); 00594 /* record the position of the parse so far so when we resume we will move to the next item */ 00595 if (fgetpos(blif, ¤t_subckt_pos) != 0) 00596 { 00597 printf("Error in file pointer read - read_blif.c\n"); 00598 exit(-1); 00599 } 00600 00601 input_net_count = 0; 00602 output_net_count = 0; 00603 00604 if (doall) 00605 { 00606 /* get the matching model to this subckt */ 00607 00608 cur_model = user_models; 00609 while(cur_model != NULL) { 00610 if(strcmp(cur_model->name, subckt_name) == 0) { 00611 break; 00612 } 00613 cur_model = cur_model->next; 00614 } 00615 if (cur_model == NULL) 00616 { 00617 printf("Didn't find matching model to subckt %s - error\n", subckt_name); 00618 exit(-1); 00619 } 00620 00621 /* IF - do all then we need to allocate a string to hold all the subckt info */ 00622 00623 /* initialize the logical_block structure */ 00624 00625 /* record model info */ 00626 logical_block[num_logical_blocks-1].model = cur_model; 00627 00628 /* allocate space for inputs and initialize all input nets to OPEN */ 00629 input_port_count = 0; 00630 port = cur_model->inputs; 00631 while(port) { 00632 if(!port->is_clock) { 00633 input_port_count++; 00634 } 00635 port = port->next; 00636 } 00637 logical_block[num_logical_blocks-1].input_nets = my_malloc(input_port_count * sizeof(int *)); 00638 00639 port = cur_model->inputs; 00640 while(port) { 00641 if(port->is_clock) { 00642 /* Clock ports are different from regular input ports, skip */ 00643 port = port->next; 00644 continue; 00645 } 00646 assert (port->size >= 0); 00647 logical_block[num_logical_blocks-1].input_nets[port->index] = my_malloc(port->size * sizeof(int)); 00648 for(j = 0; j < port->size; j++) { 00649 logical_block[num_logical_blocks-1].input_nets[port->index][j] = OPEN; 00650 } 00651 port = port->next; 00652 } 00653 assert(port == NULL || (port->is_clock && port->next == NULL)); 00654 00655 /* allocate space for outputs and initialize all output nets to OPEN */ 00656 output_port_count = 0; 00657 port = cur_model->outputs; 00658 while(port){ 00659 port = port->next; 00660 output_port_count++; 00661 } 00662 logical_block[num_logical_blocks-1].output_nets = my_malloc(output_port_count * sizeof(int *)); 00663 00664 port = cur_model->outputs; 00665 while(port) { 00666 assert (port->size >= 0); 00667 logical_block[num_logical_blocks-1].output_nets[port->index] = my_malloc(port->size * sizeof(int)); 00668 for(j = 0; j < port->size; j++) { 00669 logical_block[num_logical_blocks-1].output_nets[port->index][j] = OPEN; 00670 } 00671 port = port->next; 00672 } 00673 assert(port == NULL); 00674 00675 /* initialize clock data */ 00676 logical_block[num_logical_blocks-1].clock_net = OPEN; 00677 00678 logical_block[num_logical_blocks-1].type = VPACK_COMB; 00679 logical_block[num_logical_blocks - 1].truth_table = NULL; 00680 00681 /* setup the index signal if open or not */ 00682 00683 for(i = 0; i < subckt_index_signals; i++) { 00684 found_subckt_signal = FALSE; 00685 /* determine the port name and the pin_number of the subckt */ 00686 port_name = my_strdup(subckt_signal_name[i]); 00687 pin_number = strrchr(port_name, '['); 00688 if(pin_number == NULL) { 00689 pin_number = "0"; /* default to 0 */ 00690 } else { 00691 /* The pin numbering is port_name[pin_number] so need to go one to the right of [ then NULL out ] */ 00692 *pin_number = '\0'; 00693 pin_number++; 00694 close_bracket = pin_number; 00695 while(*close_bracket != '\0' && *close_bracket != ']') { 00696 close_bracket++; 00697 } 00698 *close_bracket = '\0'; 00699 } 00700 00701 port = cur_model->inputs; 00702 while(port) { 00703 if(strcmp(port_name, port->name) == 0) { 00704 if(found_subckt_signal) { 00705 printf(ERRTAG "Two instances of %s subckt signal found in subckt %s\n", 00706 subckt_signal_name[i], subckt_name); 00707 } 00708 found_subckt_signal = TRUE; 00709 if(port->is_clock) { 00710 assert(logical_block[num_logical_blocks-1].clock_net == OPEN); 00711 assert(my_atoi(pin_number) == 0); 00712 logical_block[num_logical_blocks-1].clock_net = 00713 add_vpack_net(circuit_signal_name[i], RECEIVER, num_logical_blocks - 1, port->index, my_atoi(pin_number), TRUE, doall); 00714 } else { 00715 logical_block[num_logical_blocks-1].input_nets[port->index][my_atoi(pin_number)] = 00716 add_vpack_net(circuit_signal_name[i], RECEIVER, num_logical_blocks - 1, port->index, my_atoi(pin_number), FALSE, doall); 00717 input_net_count++; 00718 } 00719 } 00720 port = port->next; 00721 } 00722 00723 port = cur_model->outputs; 00724 while(port) { 00725 if(strcmp(port_name, port->name) == 0) { 00726 if(found_subckt_signal) { 00727 printf(ERRTAG "Two instances of %s subckt signal found in subckt %s\n", 00728 subckt_signal_name[i], subckt_name); 00729 } 00730 found_subckt_signal = TRUE; 00731 logical_block[num_logical_blocks-1].output_nets[port->index][my_atoi(pin_number)] = 00732 add_vpack_net(circuit_signal_name[i], DRIVER, num_logical_blocks - 1, port->index, my_atoi(pin_number), FALSE, doall); 00733 if(subckt_logical_block_name == NULL && circuit_signal_name[i] != NULL) { 00734 subckt_logical_block_name = circuit_signal_name[i]; 00735 } 00736 output_net_count++; 00737 } 00738 port = port->next; 00739 } 00740 00741 /* record the name to be first output net parsed */ 00742 logical_block[num_logical_blocks-1].name = my_strdup(subckt_logical_block_name); 00743 00744 if(!found_subckt_signal) { 00745 printf("Unknown subckt port %s\n", subckt_signal_name[i]); 00746 exit(1); 00747 } 00748 } 00749 } 00750 00751 for(i = 0; i < subckt_index_signals; i++) { 00752 free(subckt_signal_name[i]); 00753 free(circuit_signal_name[i]); 00754 } 00755 free(subckt_signal_name); 00756 free(circuit_signal_name); 00757 00758 /* now that you've done the analysis, move the file pointer back */ 00759 if (fsetpos(blif, ¤t_subckt_pos) != 0) 00760 { 00761 printf("Error in moving back file pointer - read_blif.c\n"); 00762 exit(-1); 00763 } 00764 } 00765 00766 /** Adds an input or output logical_block to the logical_block data structures. 00767 * in_or_out: DRIVER for input, RECEIVER for output. 00768 * doall: 1 for final pass when structures are loaded. 0 for 00769 * first pass when hash table is built and pins, nets, etc. are counted. 00770 */ 00771 static void 00772 io_line(int in_or_out, 00773 int doall, t_model *io_model) 00774 { 00775 char *ptr; 00776 char buf2[BUFSIZE]; 00777 int nindex, len, iparse; 00778 00779 iparse = 0; 00780 while(iparse < MAX_ATOM_PARSE) 00781 { 00782 iparse++; 00783 ptr = my_strtok(NULL, TOKENS, blif, buf2); 00784 if(ptr == NULL) 00785 return; 00786 num_logical_blocks++; 00787 00788 nindex = add_vpack_net(ptr, in_or_out, num_logical_blocks - 1, 0, 0, FALSE, doall); 00789 /* zero offset indexing */ 00790 if(!doall) 00791 continue; /* Just counting things when doall == 0 */ 00792 00793 logical_block[num_logical_blocks -1].clock_net = OPEN; 00794 logical_block[num_logical_blocks -1].input_nets = NULL; 00795 logical_block[num_logical_blocks -1].output_nets = NULL; 00796 logical_block[num_logical_blocks - 1].model = io_model; 00797 00798 len = strlen(ptr); 00799 if(in_or_out == RECEIVER) 00800 { /* output pads need out: prefix 00801 * to make names unique from LUTs */ 00802 logical_block[num_logical_blocks - 1].name = (char *)my_malloc((len + 1 + 4) * sizeof(char)); /* Space for out: at start */ 00803 strcpy(logical_block[num_logical_blocks - 1].name, "out:"); 00804 strcat(logical_block[num_logical_blocks - 1].name, ptr); 00805 logical_block[num_logical_blocks -1].input_nets = (int **)my_malloc(sizeof(int*)); 00806 logical_block[num_logical_blocks -1].input_nets[0] = (int *)my_malloc(sizeof(int)); 00807 logical_block[num_logical_blocks - 1].input_nets[0][0] = OPEN; 00808 } 00809 else 00810 { 00811 assert(in_or_out == DRIVER); 00812 logical_block[num_logical_blocks - 1].name = (char *)my_malloc((len + 1) * sizeof (char)); 00813 strcpy(logical_block[num_logical_blocks - 1].name, ptr); 00814 logical_block[num_logical_blocks -1].output_nets = (int **)my_malloc(sizeof(int*)); 00815 logical_block[num_logical_blocks -1].output_nets[0] = (int *)my_malloc(sizeof(int)); 00816 logical_block[num_logical_blocks - 1].output_nets[0][0] = OPEN; 00817 } 00818 00819 if(in_or_out == DRIVER) 00820 { /* processing .inputs line */ 00821 num_p_inputs++; 00822 logical_block[num_logical_blocks - 1].type = VPACK_INPAD; 00823 logical_block[num_logical_blocks - 1].output_nets[0][0] = nindex; 00824 } 00825 else 00826 { /* processing .outputs line */ 00827 num_p_outputs++; 00828 logical_block[num_logical_blocks - 1].type = VPACK_OUTPAD; 00829 logical_block[num_logical_blocks - 1].input_nets[0][0] = nindex; 00830 } 00831 logical_block[num_logical_blocks - 1].truth_table = NULL; 00832 } 00833 assert(iparse < MAX_ATOM_PARSE); 00834 } 00835 00836 static void check_and_count_models(int doall, const char* model_name, t_model *user_models) { 00837 fpos_t start_pos; 00838 t_model *user_model; 00839 00840 num_blif_models++; 00841 if(doall) { 00842 /* get start position to do two passes on model */ 00843 if (fgetpos(blif, &start_pos) != 0) 00844 { 00845 printf(ERRTAG "in file pointer read - read_blif.c\n"); 00846 exit(-1); 00847 } 00848 00849 /* get corresponding architecture model */ 00850 user_model = user_models; 00851 while(user_model) { 00852 if(0 == strcmp(model_name, user_model->name)) { 00853 break; 00854 } 00855 user_model = user_model->next; 00856 } 00857 if(user_model == NULL) { 00858 printf(ERRTAG "No corresponding model %s in architecture description \n", model_name); 00859 exit(1); 00860 } 00861 00862 /* check ports */ 00863 } 00864 } 00865 00866 00867 /** This routine is given a vpack_net name in *ptr, either DRIVER or RECEIVER 00868 * specifying whether the logical_block number (bnum) and the output pin (bpin) is driving this 00869 * vpack_net or in the fan-out and doall, which is 0 for the counting pass 00870 * and 1 for the loading pass. It updates the vpack_net data structure and 00871 * returns the vpack_net number so the calling routine can update the logical_block 00872 * data structure. 00873 */ 00874 static int 00875 add_vpack_net(char *ptr, 00876 int type, 00877 int bnum, 00878 int bport, 00879 int bpin, 00880 boolean is_global, 00881 int doall) 00882 { 00883 struct hash_logical_nets *h_ptr, *prev_ptr; 00884 int index, j, nindex; 00885 00886 if(strcmp(ptr, "open") == 0) { 00887 printf(ERRTAG "net name \"open\" is a reserved keyword in VPR"); 00888 exit(1); 00889 } 00890 00891 if(strcmp(ptr, "unconn") == 0) { 00892 return OPEN; 00893 } 00894 index = hash_value(ptr); 00895 00896 if(doall) { 00897 if(type == RECEIVER && !is_global) { 00898 logical_block_input_count[bnum]++; 00899 } else if (type == DRIVER) { 00900 logical_block_output_count[bnum]++; 00901 } 00902 } 00903 00904 h_ptr = hash[index]; 00905 prev_ptr = h_ptr; 00906 00907 while(h_ptr != NULL) 00908 { 00909 if(strcmp(h_ptr->name, ptr) == 0) 00910 { /* Net already in hash table */ 00911 nindex = h_ptr->index; 00912 00913 if(!doall) 00914 { /* Counting pass only */ 00915 (h_ptr->count)++; 00916 return (nindex); 00917 } 00918 00919 if(type == DRIVER) 00920 { 00921 num_driver[nindex]++; 00922 j = 0; /* Driver always in position 0 of pinlist */ 00923 } 00924 else 00925 { 00926 vpack_net[nindex].num_sinks++; 00927 if((num_driver[nindex] < 0) || (num_driver[nindex] > 1)) { 00928 printf(ERRTAG "number of drivers for net #%d (%s) has %d drivers.\n", 00929 nindex, ptr, num_driver[index]); 00930 } 00931 j = vpack_net[nindex].num_sinks; 00932 00933 /* num_driver is the number of signal drivers of this vpack_net. * 00934 * should always be zero or 1 unless the netlist is bad. */ 00935 if((vpack_net[nindex].num_sinks - num_driver[nindex]) >= temp_num_pins[nindex]) 00936 { 00937 printf ("Error: Net #%d (%s) has no driver and will cause\n", nindex, ptr); 00938 printf("memory corruption.\n"); 00939 exit(1); 00940 } 00941 } 00942 vpack_net[nindex].node_block[j] = bnum; 00943 vpack_net[nindex].node_block_port[j] = bport; 00944 vpack_net[nindex].node_block_pin[j] = bpin; 00945 vpack_net[nindex].is_global = is_global; 00946 return (nindex); 00947 } 00948 prev_ptr = h_ptr; 00949 h_ptr = h_ptr->next; 00950 } 00951 00952 /* Net was not in the hash table. */ 00953 00954 if(doall == 1) 00955 { 00956 printf("Error in add_vpack_net: the second (load) pass could not\n"); 00957 printf("find vpack_net %s in the symbol table.\n", ptr); 00958 exit(1); 00959 } 00960 00961 /* Add the vpack_net (only counting pass will add nets to symbol table). */ 00962 00963 num_logical_nets++; 00964 h_ptr = (struct hash_logical_nets *)my_malloc(sizeof(struct hash_logical_nets)); 00965 if(prev_ptr == NULL) 00966 { 00967 hash[index] = h_ptr; 00968 } 00969 else 00970 { 00971 prev_ptr->next = h_ptr; 00972 } 00973 h_ptr->next = NULL; 00974 h_ptr->index = num_logical_nets - 1; 00975 h_ptr->count = 1; 00976 h_ptr->name = my_strdup(ptr); 00977 return (h_ptr->index); 00978 } 00979 00980 00981 static int 00982 hash_value(char *name) 00983 { 00984 00985 int i, k; 00986 int val = 0, mult = 1; 00987 00988 i = strlen(name); 00989 k = max(i - 7, 0); 00990 for(i = strlen(name) - 1; i >= k; i--) 00991 { 00992 val += mult * ((int)name[i]); 00993 mult *= 10; 00994 } 00995 val += (int)name[0]; 00996 val %= HASHSIZE; 00997 00998 return (val); 00999 } 01000 01001 01002 /** Echo back the netlist data structures to file input.echo to 01003 * allow the user to look at the internal state of the program 01004 * and check the parsing. 01005 */ 01006 void 01007 echo_input(char *blif_file, 01008 char *echo_file, 01009 t_model *library_models) 01010 { 01011 int i, j; 01012 FILE *fp; 01013 t_model_ports *port; 01014 t_model *latch_model; 01015 t_model *logic_model; 01016 t_model *cur; 01017 int *lut_distribution; 01018 int num_absorbable_latch; 01019 int inet; 01020 01021 cur = library_models; 01022 logic_model = latch_model = NULL; 01023 while(cur) { 01024 if(strcmp(cur->name, MODEL_LOGIC) == 0) { 01025 logic_model = cur; 01026 assert(logic_model->inputs->next == NULL); 01027 } else if(strcmp(cur->name, MODEL_LATCH) == 0) { 01028 latch_model = cur; 01029 assert(latch_model->inputs->size == 1); 01030 } 01031 cur = cur->next; 01032 } 01033 01034 lut_distribution = my_calloc(logic_model->inputs[0].size + 1, sizeof(int)); 01035 num_absorbable_latch = 0; 01036 for(i = 0; i < num_logical_blocks; i++) { 01037 if(logical_block[i].model == logic_model) { 01038 if(logic_model == NULL) 01039 continue; 01040 for(j = 0; j < logic_model->inputs[0].size; j++) { 01041 if(logical_block[i].input_nets[0][j] == OPEN) { 01042 break; 01043 } 01044 } 01045 lut_distribution[j]++; 01046 } else if (logical_block[i].model == latch_model) { 01047 if(latch_model == NULL) 01048 continue; 01049 inet = logical_block[i].input_nets[0][0]; 01050 if (vpack_net[inet].num_sinks == 1 && logical_block[vpack_net[inet].node_block[0]].model == logic_model) { 01051 num_absorbable_latch++; 01052 } 01053 } 01054 } 01055 01056 printf("Input netlist file: %s Model: %s\n", blif_file, model); 01057 printf("Primary Inputs: %d. Primary Outputs: %d.\n", num_p_inputs, num_p_outputs); 01058 printf("LUTs: %d. Latches: %d Subckts: %d.\n", num_luts, num_latches, num_subckts); 01059 printf("# Standard absorbable latches: %d\n", num_absorbable_latch); 01060 for(i = 0; i < logic_model->inputs[0].size + 1; i++) { 01061 printf("LUT size %d = %d, ", i, lut_distribution[i]); 01062 } 01063 printf("\n"); 01064 printf("Total Blocks: %d. Total Nets: %d\n", num_logical_blocks, num_logical_nets); 01065 01066 fp = my_fopen(echo_file, "w", 0); 01067 01068 fprintf(fp, "Input netlist file: %s Model: %s\n", blif_file, model); 01069 fprintf(fp, "num_p_inputs: %d, num_p_outputs: %d, num_luts: %d," " num_latches: %d\n", num_p_inputs, num_p_outputs, num_luts, num_latches); 01070 fprintf(fp, "num_logical_blocks: %d, num_logical_nets: %d\n", num_logical_blocks, num_logical_nets); 01071 01072 fprintf(fp, "\nNet\tName\t\t#Pins\tDriver\tRecvs.\n"); 01073 for(i = 0; i < num_logical_nets; i++) 01074 { 01075 fprintf(fp, "\n%d\t%s\t", i, vpack_net[i].name); 01076 if(strlen(vpack_net[i].name) < 8) 01077 fprintf(fp, "\t"); /* Name field is 16 chars wide */ 01078 fprintf(fp, "%d", vpack_net[i].num_sinks + 1); 01079 for(j = 0; j <= vpack_net[i].num_sinks; j++) 01080 fprintf(fp, "\t(%d,%d,%d)", vpack_net[i].node_block[j], vpack_net[i].node_block_port[j], vpack_net[i].node_block_pin[j]); 01081 } 01082 01083 fprintf(fp, "\n\n\nBlocks\t\t\tBlock Type Legend:\n"); 01084 fprintf(fp, "\t\t\tINPAD = %d\tOUTPAD = %d\n", VPACK_INPAD, VPACK_OUTPAD); 01085 fprintf(fp, "\t\t\tCOMB = %d\t\tLATCH = %d\n", VPACK_COMB, VPACK_LATCH); 01086 fprintf(fp, "\t\t\tEMPTY = %d\n", VPACK_EMPTY); 01087 01088 for(i = 0; i < num_logical_blocks; i++) 01089 { 01090 fprintf(fp, "\nblock %d\t%s\t", i, logical_block[i].name); 01091 fprintf(fp, "type: %d\n", logical_block[i].type); 01092 fprintf(fp, "model name: %s\n", logical_block[i].model->name); 01093 01094 port = logical_block[i].model->inputs; 01095 01096 while(port) { 01097 fprintf(fp, "\tInput Port: %s\n", port->name); 01098 for(j = 0; j < port->size; j++) { 01099 if(logical_block[i].input_nets[port->index][j] == OPEN) 01100 fprintf(fp, "\tOPEN"); 01101 else 01102 fprintf(fp, "\t%d", logical_block[i].input_nets[port->index][j]); 01103 } 01104 port = port->next; 01105 } 01106 01107 port = logical_block[i].model->outputs; 01108 while(port) { 01109 fprintf(fp, "\tOutput Port: %s\n", port->name); 01110 for(j = 0; j < port->size; j++) { 01111 if(logical_block[i].output_nets[port->index][j] == OPEN) { 01112 fprintf(fp, "\tOPEN"); 01113 } else { 01114 fprintf(fp, "\t%d", logical_block[i].output_nets[port->index][j]); 01115 } 01116 } 01117 port = port->next; 01118 } 01119 01120 fprintf(fp, "\n\tclock net %d\n", logical_block[i].clock_net); 01121 } 01122 01123 fprintf(fp, "\n"); 01124 fclose(fp); 01125 } 01126 01127 01128 01129 /** load default vpack models (inpad, outpad, logic) */ 01130 static void 01131 load_default_models(INP t_model *library_models, OUTP t_model** inpad_model, OUTP t_model** outpad_model, 01132 OUTP t_model** logic_model, OUTP t_model** latch_model) 01133 { 01134 t_model *cur_model; 01135 cur_model = library_models; 01136 *inpad_model = *outpad_model = *logic_model = *latch_model = NULL; 01137 while(cur_model) { 01138 if(strcmp(MODEL_INPUT, cur_model->name) == 0) { 01139 assert(cur_model->inputs == NULL); 01140 assert(cur_model->outputs->next == NULL); 01141 assert(cur_model->outputs->size == 1); 01142 *inpad_model = cur_model; 01143 } else if(strcmp(MODEL_OUTPUT, cur_model->name) == 0) { 01144 assert(cur_model->outputs == NULL); 01145 assert(cur_model->inputs->next == NULL); 01146 assert(cur_model->inputs->size == 1); 01147 *outpad_model = cur_model; 01148 } else if(strcmp(MODEL_LOGIC, cur_model->name) == 0) { 01149 assert(cur_model->inputs->next == NULL); 01150 assert(cur_model->outputs->next == NULL); 01151 assert(cur_model->outputs->size == 1); 01152 *logic_model = cur_model; 01153 } else if(strcmp(MODEL_LATCH, cur_model->name) == 0) { 01154 assert(cur_model->outputs->next == NULL); 01155 assert(cur_model->outputs->size == 1); 01156 *latch_model = cur_model; 01157 } else { 01158 assert(0); 01159 } 01160 cur_model = cur_model->next; 01161 } 01162 } 01163 01164 01165 /** Checks the input netlist for obvious errors. */ 01166 static void 01167 check_net(boolean sweep_hanging_nets_and_inputs) 01168 { 01169 int i, j, k, error, iblk, ipin, iport, inet, check_net; 01170 boolean found; 01171 int count_inputs, count_outputs; 01172 int explicit_vpack_models; 01173 t_model_ports *port; 01174 struct s_linked_vptr *p_io_removed; 01175 int removed_nets; 01176 01177 explicit_vpack_models = num_blif_models + 1; 01178 01179 error = 0; 01180 removed_nets = 0; 01181 01182 if(ilines != explicit_vpack_models) 01183 { 01184 printf(ERRTAG "Found %d .inputs lines; expected %d.\n", ilines, explicit_vpack_models); 01185 error++; 01186 } 01187 01188 if(olines != explicit_vpack_models) 01189 { 01190 printf(ERRTAG "Found %d .outputs lines; expected %d.\n", olines,explicit_vpack_models); 01191 error++; 01192 } 01193 01194 if(model_lines != explicit_vpack_models) 01195 { 01196 printf(ERRTAG "Found %d .model lines; expected %d.\n", model_lines, num_blif_models + 1); 01197 error++; 01198 } 01199 01200 if(endlines != explicit_vpack_models) 01201 { 01202 printf(ERRTAG "Found %d .end lines; expected %d.\n", endlines, explicit_vpack_models); 01203 error++; 01204 } 01205 for(i = 0; i < num_logical_nets; i++) 01206 { 01207 01208 if(num_driver[i] != 1) 01209 { 01210 printf(ERRTAG "vpack_net %s has" " %d signals driving it.\n", vpack_net[i].name, num_driver[i]); 01211 error++; 01212 } 01213 01214 if(vpack_net[i].num_sinks == 0) 01215 { 01216 01217 /* If this is an input pad, it is unused and I just remove it with * 01218 * a warning message. Lots of the mcnc circuits have this problem. 01219 01220 Also, subckts from ODIN often have unused driven nets 01221 */ 01222 01223 iblk = vpack_net[i].node_block[0]; 01224 iport = vpack_net[i].node_block_port[0]; 01225 ipin = vpack_net[i].node_block_pin[0]; 01226 01227 assert((vpack_net[i].num_sinks - num_driver[i]) == -1); 01228 01229 /* All nets should connect to inputs of block except output pads */ 01230 if(logical_block[iblk].type != VPACK_OUTPAD) { 01231 if(sweep_hanging_nets_and_inputs) { 01232 removed_nets++; 01233 vpack_net[i].node_block[0] = OPEN; 01234 vpack_net[i].node_block_port[0] = OPEN; 01235 vpack_net[i].node_block_pin[0] = OPEN; 01236 logical_block[iblk].output_nets[iport][ipin] = OPEN; 01237 logical_block_output_count[iblk]--; 01238 } else { 01239 printf(WARNTAG "vpack_net %s has no fanout.\n", vpack_net[i].name); 01240 } 01241 continue; 01242 } 01243 } 01244 01245 if(strcmp(vpack_net[i].name, "open") == 0 || strcmp(vpack_net[i].name, "unconn") == 0) 01246 { 01247 printf(ERRTAG "vpack_net #%d has the reserved name %s.\n", i, vpack_net[i].name); 01248 error++; 01249 } 01250 01251 for(j = 0; j <= vpack_net[i].num_sinks; j++) { 01252 iblk = vpack_net[i].node_block[j]; 01253 iport = vpack_net[i].node_block_port[j]; 01254 ipin = vpack_net[i].node_block_pin[j]; 01255 if(ipin == OPEN) { 01256 /* Clocks are not connected to regular pins on a block hence open */ 01257 check_net = logical_block[iblk].clock_net; 01258 if(check_net != i) { 01259 printf("Internal Error: clock net for block %s #%d is net %s #%d but connecting net is %s #%d\n", 01260 logical_block[iblk].name, iblk, 01261 vpack_net[check_net].name, check_net, 01262 vpack_net[i].name, i); 01263 error++; 01264 } 01265 01266 } else { 01267 if(j == 0) { 01268 check_net = logical_block[iblk].output_nets[iport][ipin]; 01269 if(check_net != i) { 01270 printf("Internal Error: output net for block %s #%d is net %s #%d but connecting net is %s #%d\n", 01271 logical_block[iblk].name, iblk, 01272 vpack_net[check_net].name, check_net, 01273 vpack_net[i].name, i); 01274 error++; 01275 } 01276 } else { 01277 if(vpack_net[i].is_global) { 01278 check_net = logical_block[iblk].clock_net; 01279 } else { 01280 check_net = logical_block[iblk].input_nets[iport][ipin]; 01281 } 01282 if(check_net != i) { 01283 printf("Internal Error: input net for block %s #%d is net %s #%d but connecting net is %s #%d\n", 01284 logical_block[iblk].name, iblk, 01285 vpack_net[check_net].name, check_net, 01286 vpack_net[i].name, i); 01287 error++; 01288 } 01289 } 01290 } 01291 } 01292 } 01293 printf("Swept away %d nets with no fanout\n", removed_nets); 01294 for(i = 0; i < num_logical_blocks; i++) 01295 { 01296 /* This block has no output and is not an output pad so it has no use, hence we remove it */ 01297 if((logical_block_output_count[i] == 0) && (logical_block[i].type != VPACK_OUTPAD)) { 01298 printf(WARNTAG "logical_block %s #%d has no fanout.\n", logical_block[i].name, i); 01299 if(sweep_hanging_nets_and_inputs && (logical_block[i].type == VPACK_INPAD)) { 01300 logical_block[i].type = VPACK_EMPTY; 01301 printf(" Removing input\n"); 01302 p_io_removed = my_malloc(sizeof(struct s_linked_vptr)); 01303 p_io_removed->data_vptr = my_strdup(logical_block[i].name); 01304 p_io_removed->next = circuit_p_io_removed; 01305 circuit_p_io_removed = p_io_removed; 01306 continue; 01307 } else { 01308 printf(" " ERRTAG " sweep hanging nodes in your logic synthesis tool because VPR can't do this yet\n"); 01309 error++; 01310 } 01311 } 01312 count_inputs = 0; 01313 count_outputs = 0; 01314 port = logical_block[i].model->inputs; 01315 while(port) { 01316 if(port->is_clock) 01317 { 01318 port = port->next; 01319 continue; 01320 } 01321 01322 for(j = 0; j < port->size; j++) 01323 { 01324 if(logical_block[i].input_nets[port->index][j] == OPEN) 01325 continue; 01326 count_inputs++; 01327 inet = logical_block[i].input_nets[port->index][j]; 01328 found = FALSE; 01329 for(k = 1; k <= vpack_net[inet].num_sinks; k++) 01330 { 01331 if(vpack_net[inet].node_block[k] == i) { 01332 if(vpack_net[inet].node_block_port[k] == port->index) { 01333 if(vpack_net[inet].node_block_pin[k] == j) { 01334 found = TRUE; 01335 } 01336 } 01337 } 01338 } 01339 assert(found == TRUE); 01340 } 01341 port = port->next; 01342 } 01343 assert(count_inputs == logical_block_input_count[i]); 01344 logical_block[i].used_input_pins = count_inputs; 01345 01346 port = logical_block[i].model->outputs; 01347 while(port) { 01348 for(j = 0; j < port->size; j++) 01349 { 01350 if(logical_block[i].output_nets[port->index][j] == OPEN) 01351 continue; 01352 count_outputs++; 01353 inet = logical_block[i].output_nets[port->index][j]; 01354 vpack_net[inet].is_const_gen = FALSE; 01355 if(count_inputs == 0 && logical_block[i].type != VPACK_INPAD && logical_block[i].type != VPACK_OUTPAD && logical_block[i].clock_net == OPEN) { 01356 printf("Net is a constant generator: %s\n", vpack_net[inet].name); 01357 vpack_net[inet].is_const_gen = TRUE; 01358 } 01359 found = FALSE; 01360 if(vpack_net[inet].node_block[0] == i) { 01361 if(vpack_net[inet].node_block_port[0] == port->index) { 01362 if(vpack_net[inet].node_block_pin[0] == j) { 01363 found = TRUE; 01364 } 01365 } 01366 } 01367 assert(found == TRUE); 01368 } 01369 port = port->next; 01370 } 01371 assert(count_outputs == logical_block_output_count[i]); 01372 01373 if(logical_block[i].type == VPACK_LATCH) 01374 { 01375 if(logical_block_input_count[i] != 1) 01376 { 01377 printf (ERRTAG "Latch #%d with output %s has %d input pin(s), expected one (D).\n", i, logical_block[i].name, logical_block_input_count[i]); 01378 error++; 01379 } 01380 if(logical_block_output_count[i] != 1) 01381 { 01382 printf (ERRTAG "Latch #%d with output %s has %d output pin(s), expected one (Q).\n", i, logical_block[i].name, logical_block_output_count[i]); 01383 error++; 01384 } 01385 if(logical_block[i].clock_net == OPEN) 01386 { 01387 printf (ERRTAG "Latch #%d with output %s has no clock.\n", i, logical_block[i].name); 01388 error++; 01389 } 01390 } 01391 01392 else if(logical_block[i].type == VPACK_INPAD) 01393 { 01394 if(logical_block_input_count[i] != 0) { 01395 printf (ERRTAG "io inpad logical_block #%d name %s of type %d" "has %d input pins.\n", 01396 i, logical_block[i].name, logical_block[i].type, logical_block_input_count[i]); 01397 error++; 01398 } 01399 if(logical_block_output_count[i] != 1) { 01400 printf (ERRTAG "io inpad logical_block #%d name %s of type %d" "has %d output pins.\n", 01401 i, logical_block[i].name, logical_block[i].type, logical_block_output_count[i]); 01402 error++; 01403 } 01404 if(logical_block[i].clock_net != OPEN) 01405 { 01406 printf (ERRTAG "io inpad #%d with output %s has clock.\n", i, logical_block[i].name); 01407 error++; 01408 } 01409 } 01410 else if(logical_block[i].type == VPACK_OUTPAD) 01411 { 01412 if(logical_block_input_count[i] != 1) { 01413 printf (ERRTAG "io outpad logical_block #%d name %s of type %d" "has %d input pins.\n", 01414 i, logical_block[i].name, logical_block[i].type, logical_block_input_count[i]); 01415 error++; 01416 } 01417 if(logical_block_output_count[i] != 0) { 01418 printf (ERRTAG "io outpad logical_block #%d name %s of type %d" "has %d output pins.\n", 01419 i, logical_block[i].name, logical_block[i].type, logical_block_output_count[i]); 01420 error++; 01421 } 01422 if(logical_block[i].clock_net != OPEN) 01423 { 01424 printf (ERRTAG "io outpad #%d with name %s has clock.\n", i, logical_block[i].name); 01425 error++; 01426 } 01427 } 01428 else if(logical_block[i].type == VPACK_COMB) 01429 { 01430 if(logical_block_input_count[i] <= 0) 01431 { 01432 printf ("Warning: logical_block #%d with output %s has only %d pin.\n", i, logical_block[i].name, logical_block_input_count[i]); 01433 01434 if(logical_block_input_count[i] < 0) 01435 { 01436 error++; 01437 } 01438 else 01439 { 01440 if(logical_block_output_count[i] > 0) { 01441 printf ("\tBlock contains output -- may be a constant generator.\n"); 01442 } else { 01443 printf ("\t" ERRTAG "Block contains no output.\n"); 01444 error++; 01445 } 01446 } 01447 } 01448 01449 if(strcmp(logical_block[i].model->name, MODEL_LOGIC) == 0) { 01450 if(logical_block_output_count[i] != 1) { 01451 printf (ERRTAG "logical_block #%d name %s of model %s \n has %d output pins instead of 1.\n", 01452 i, logical_block[i].name, logical_block[i].model->name, logical_block_output_count[i]); 01453 error++; 01454 } 01455 } 01456 } else { 01457 printf(ERRTAG "Unknown type for logical_block #%d %s\n", i, logical_block[i].name); 01458 } 01459 } 01460 01461 if(error != 0) 01462 { 01463 printf("Found %d fatal errors in the input netlist.\n", error); 01464 exit(1); 01465 } 01466 } 01467 01468 01469 /** Release memory needed only during blif network parsing. */ 01470 static void 01471 free_parse(void) 01472 { 01473 int i; 01474 struct hash_logical_nets *h_ptr, *temp_ptr; 01475 01476 for(i = 0; i < HASHSIZE; i++) 01477 { 01478 h_ptr = hash[i]; 01479 while(h_ptr != NULL) 01480 { 01481 free((void *)h_ptr->name); 01482 temp_ptr = h_ptr->next; 01483 free((void *)h_ptr); 01484 h_ptr = temp_ptr; 01485 } 01486 } 01487 free((void *)num_driver); 01488 free((void *)hash); 01489 free((void *)temp_num_pins); 01490 } 01491