VPR-6.0

vpr/SRC/base/read_blif.c

Go to the documentation of this file.
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, &current_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, &current_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