VPR-7.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
read_blif.c
Go to the documentation of this file.
1 #include <string.h>
2 #include <stdio.h>
3 #include <time.h>
4 #include "assert.h"
5 #include "util.h"
6 #include "vpr_types.h"
7 #include "globals.h"
8 #include "read_blif.h"
9 #include "arch_types.h"
10 #include "ReadOptions.h"
11 #include "hash.h"
12 
13 /* PRINT_PIN_NETS */
14 
15 struct s_model_stats {
17  int count;
18 };
19 
20 #define MAX_ATOM_PARSE 200000000
21 
22 /* This source file will read in a FLAT blif netlist consisting *
23  * of .inputs, .outputs, .names and .latch commands. It currently *
24  * does not handle hierarchical blif files. Hierarchical *
25  * blif files can be flattened via the read_blif and write_blif *
26  * commands of sis. LUT circuits should only have .names commands; *
27  * there should be no gates. This parser performs limited error *
28  * checking concerning the consistency of the netlist it obtains. *
29  * .inputs and .outputs statements must be given; this parser does *
30  * not infer primary inputs and outputs from non-driven and fanout *
31  * free nodes. This parser can be extended to do this if necessary, *
32  * or the sis read_blif and write_blif commands can be used to put a *
33  * netlist into the standard format. *
34  * V. Betz, August 25, 1994. *
35  * Added more error checking, March 30, 1995, V. Betz */
36 
37 static int *num_driver, *temp_num_pins;
39 static int num_blif_models;
40 static int num_luts = 0, num_latches = 0, num_subckts = 0;
41 
42 /* # of .input, .output, .model and .end lines */
44 static struct s_hash **blif_hash;
45 static char *model = NULL;
46 static FILE *blif;
47 
48 static int add_vpack_net(char *ptr, int type, int bnum, int bport, int bpin,
49  boolean is_global, int doall);
50 static void get_blif_tok(char *buffer, int doall, boolean *done,
51  boolean *add_truth_table, INP t_model* inpad_model,
52  INP t_model* outpad_model, INP t_model* logic_model,
53  INP t_model* latch_model, INP t_model* user_models);
54 static void init_parse(int doall);
55 static void check_net(boolean sweep_hanging_nets_and_inputs);
56 static void free_parse(void);
57 static void io_line(int in_or_out, int doall, t_model *io_model);
58 static boolean add_lut(int doall, t_model *logic_model);
59 static void add_latch(int doall, INP t_model *latch_model);
60 static void add_subckt(int doall, INP t_model *user_models);
61 static void check_and_count_models(int doall, const char* model_name,
62  t_model* user_models);
63 static void load_default_models(INP t_model *library_models,
64  OUTP t_model** inpad_model, OUTP t_model** outpad_model,
65  OUTP t_model** logic_model, OUTP t_model** latch_model);
66 static void read_activity(char * activity_file);
67 static void read_blif(char *blif_file, boolean sweep_hanging_nets_and_inputs,
68  t_model *user_models, t_model *library_models,
69  boolean read_activity_file, char * activity_file);
70 
71 static void absorb_buffer_luts(void);
72 static void compress_netlist(void);
73 static void show_blif_stats(t_model *user_models, t_model *library_models);
74 static bool add_activity_to_net(char * net_name, float probability,
75  float density);
76 
77 static void read_blif(char *blif_file, boolean sweep_hanging_nets_and_inputs,
78  t_model *user_models, t_model *library_models,
79  boolean read_activity_file, char * activity_file) {
80  char buffer[BUFSIZE];
81  int doall;
82  boolean done;
83  boolean add_truth_table;
84  t_model *inpad_model, *outpad_model, *logic_model, *latch_model;
85  clock_t begin, end;
86 
87  blif = fopen(blif_file, "r");
88  if (blif == NULL ) {
89  vpr_printf(TIO_MESSAGE_ERROR, "Failed to open blif file '%s'.\n",
90  blif_file);
91  exit(1);
92  }
93  load_default_models(library_models, &inpad_model, &outpad_model,
94  &logic_model, &latch_model);
95 
96  /* doall = 0 means do a counting pass, doall = 1 means allocate and load data structures */
97  for (doall = 0; doall <= 1; doall++) {
98  begin = clock();
99 
100  init_parse(doall);
101 
102  end = clock();
103 #ifdef CLOCKS_PER_SEC
104  vpr_printf(TIO_MESSAGE_INFO,
105  "Loop for doall = %d, init_parse took %g seconds.\n", doall,
106  (float) (end - begin) / CLOCKS_PER_SEC);
107 #else
108  vpr_printf(TIO_MESSAGE_INFO, "Loop for doall = %d, init_parse took %g seconds.\n", doall, (float)(end - begin) / CLK_PER_SEC);
109 #endif
110 
111  begin = clock();
112  file_line_number = 0; /* Reset line number. */
113  done = FALSE;
114  add_truth_table = FALSE;
115  model_lines = 0;
116  while (my_fgets(buffer, BUFSIZE, blif) != NULL ) {
117  get_blif_tok(buffer, doall, &done, &add_truth_table, inpad_model,
118  outpad_model, logic_model, latch_model, user_models);
119  }
120  rewind(blif); /* Start at beginning of file again */
121 
122  end = clock();
123 #ifdef CLOCKS_PER_SEC
124  vpr_printf(TIO_MESSAGE_INFO, "Loop for doall = %d took %g seconds.\n",
125  doall, (float) (end - begin) / CLOCKS_PER_SEC);
126 #else
127  vpr_printf(TIO_MESSAGE_INFO, "Loop for doall = %d took %g seconds.\n", doall, (float)(end - begin) / CLK_PER_SEC);
128 #endif
129 
130  }
131 
132  /*checks how well the hash function is performing*/
133 #ifdef VERBOSE
134  get_hash_stats(blif_hash, "blif_hash");
135 #endif
136 
137  fclose(blif);
138  check_net(sweep_hanging_nets_and_inputs);
139 
140  /* Read activity file */
141  if (read_activity_file) {
142  read_activity(activity_file);
143  }
144  free_parse();
145 }
146 
147 static void init_parse(int doall) {
148 
149  /* Allocates and initializes the data structures needed for the parse. */
150 
151  int i;
152  struct s_hash *h_ptr;
153 
154  if (!doall) { /* Initialization before first (counting) pass */
155  num_logical_nets = 0;
156  blif_hash = (struct s_hash **) my_calloc(sizeof(struct s_hash *),
157  HASHSIZE);
158  }
159  /* Allocate memory for second (load) pass */
160  else {
162  sizeof(struct s_net));
164  sizeof(struct s_logical_block));
165  num_driver = (int *) my_malloc(num_logical_nets * sizeof(int));
166  temp_num_pins = (int *) my_malloc(num_logical_nets * sizeof(int));
167 
169  sizeof(int));
171  sizeof(int));
172 
173  for (i = 0; i < num_logical_nets; i++) {
174  num_driver[i] = 0;
175  vpack_net[i].num_sinks = 0;
176  vpack_net[i].name = NULL;
177  vpack_net[i].node_block = NULL;
178  vpack_net[i].node_block_port = NULL;
179  vpack_net[i].node_block_pin = NULL;
181  }
182 
183  for (i = 0; i < num_logical_blocks; i++) {
184  logical_block[i].index = i;
185  }
186 
187  for (i = 0; i < HASHSIZE; i++) {
188  h_ptr = blif_hash[i];
189  while (h_ptr != NULL ) {
190  vpack_net[h_ptr->index].node_block = (int *) my_malloc(
191  h_ptr->count * sizeof(int));
192  vpack_net[h_ptr->index].node_block_port = (int *) my_malloc(
193  h_ptr->count * sizeof(int));
194  vpack_net[h_ptr->index].node_block_pin = (int *) my_malloc(
195  h_ptr->count * sizeof(int));
196 
197  /* For avoiding assigning values beyond end of pins array. */
198  temp_num_pins[h_ptr->index] = h_ptr->count;
199  vpack_net[h_ptr->index].name = my_strdup(h_ptr->name);
200  h_ptr = h_ptr->next;
201  }
202  }
203 #ifdef PRINT_PIN_NETS
204  vpr_printf(TIO_MESSAGE_INFO, "i\ttemp_num_pins\n");
205  for (i = 0;i < num_logical_nets;i++) {
206  vpr_printf(TIO_MESSAGE_INFO, "%d\t%d\n",i,temp_num_pins[i]);
207  }
208  vpr_printf(TIO_MESSAGE_INFO, "num_logical_nets %d\n", num_logical_nets);
209 #endif
210  }
211 
212  /* Initializations for both passes. */
213 
214  ilines = 0;
215  olines = 0;
216  model_lines = 0;
217  endlines = 0;
218  num_p_inputs = 0;
219  num_p_outputs = 0;
220  num_luts = 0;
221  num_latches = 0;
222  num_logical_blocks = 0;
223  num_blif_models = 0;
224  num_subckts = 0;
225 }
226 
227 static void get_blif_tok(char *buffer, int doall, boolean *done,
228  boolean *add_truth_table, INP t_model* inpad_model,
229  INP t_model* outpad_model, INP t_model* logic_model,
230  INP t_model* latch_model, INP t_model* user_models) {
231 
232  /* Figures out which, if any token is at the start of this line and *
233  * takes the appropriate action. */
234 
235 #define BLIF_TOKENS " \t\n"
236  char *ptr;
237  char *fn;
238  struct s_linked_vptr *data;
239 
240  ptr = my_strtok(buffer, TOKENS, blif, buffer);
241  if (ptr == NULL )
242  return;
243 
244  if (*add_truth_table) {
245  if (ptr[0] == '0' || ptr[0] == '1' || ptr[0] == '-') {
246  data = (struct s_linked_vptr*) my_malloc(
247  sizeof(struct s_linked_vptr));
248  fn = ptr;
249  ptr = my_strtok(NULL, BLIF_TOKENS, blif, buffer);
250  if (!ptr || strlen(ptr) != 1) {
251  if (strlen(fn) == 1) {
252  /* constant generator */
253  data->next =
255  data->data_vptr = my_malloc(strlen(fn) + 4);
256  sprintf((char*) (data->data_vptr), " %s", fn);
258  ptr = fn;
259  } else {
260  vpr_printf(TIO_MESSAGE_ERROR,
261  "Unknown truth table data %s %s.\n", fn, ptr);
262  exit(1);
263  }
264  } else {
266  data->data_vptr = my_malloc(strlen(fn) + 3);
267  sprintf((char*) data->data_vptr, "%s %s", fn, ptr);
269  }
270  }
271  }
272 
273  if (strcmp(ptr, ".names") == 0) {
274  *add_truth_table = FALSE;
275  *add_truth_table = add_lut(doall, logic_model);
276  return;
277  }
278 
279  if (strcmp(ptr, ".latch") == 0) {
280  *add_truth_table = FALSE;
281  add_latch(doall, latch_model);
282  return;
283  }
284 
285  if (strcmp(ptr, ".model") == 0) {
286  *add_truth_table = FALSE;
287  ptr = my_strtok(NULL, TOKENS, blif, buffer);
288  if (doall) {
289  if (ptr != NULL ) {
290  if(model != NULL) {
291  free(model);
292  }
293  model = (char *) my_malloc((strlen(ptr) + 1) * sizeof(char));
294  strcpy(model, ptr);
295  if (blif_circuit_name == NULL ) {
297  }
298  } else {
299  if(model != NULL) {
300  free(model);
301  }
302  model = (char *) my_malloc(sizeof(char));
303  model[0] = '\0';
304  }
305  }
306 
307  if (model_lines > 0) {
308  check_and_count_models(doall, ptr, user_models);
309  } else {
310  dum_parse(buffer);
311  }
312  model_lines++;
313  return;
314  }
315 
316  if (strcmp(ptr, ".inputs") == 0) {
317  *add_truth_table = FALSE;
318  /* packing can only one fully defined model */
319  if (model_lines == 1) {
320  io_line(DRIVER, doall, inpad_model);
321  *done = (boolean) 1;
322  }
323  if (doall)
324  ilines++; /* Error checking only */
325  return;
326  }
327 
328  if (strcmp(ptr, ".outputs") == 0) {
329  *add_truth_table = FALSE;
330  /* packing can only one fully defined model */
331  if (model_lines == 1) {
332  io_line(RECEIVER, doall, outpad_model);
333  *done = (boolean) 1;
334  }
335  if (doall)
336  olines++; /* Make sure only one .output line */
337  /* For error checking only */
338  return;
339  }
340  if (strcmp(ptr, ".end") == 0) {
341  *add_truth_table = FALSE;
342  if (doall) {
343  endlines++; /* Error checking only */
344  }
345  return;
346  }
347 
348  if (strcmp(ptr, ".subckt") == 0) {
349  *add_truth_table = FALSE;
350  add_subckt(doall, user_models);
351  }
352 
353  /* Could have numbers following a .names command, so not matching any *
354  * of the tokens above is not an error. */
355 
356 }
357 
358 void dum_parse(char *buf) {
359 
360  /* Continue parsing to the end of this (possibly continued) line. */
361 
362  while (my_strtok(NULL, TOKENS, blif, buf) != NULL )
363  ;
364 }
365 
366 static boolean add_lut(int doall, t_model *logic_model) {
367 
368  /* Adds a LUT as VPACK_COMB from (.names) currently being parsed to the logical_block array. Adds *
369  * its pins to the nets data structure by calling add_vpack_net. If doall is *
370  * zero this is a counting pass; if it is 1 this is the final (loading) *
371  * pass. */
372 
373  char *ptr, **saved_names, buf[BUFSIZE];
374  int i, j, output_net_index;
375 
376  saved_names = (char**) alloc_matrix(0, logic_model->inputs->size, 0,
377  BUFSIZE - 1, sizeof(char));
378 
380 
381  /* Count # nets connecting */
382  i = 0;
383  while ((ptr = my_strtok(NULL, TOKENS, blif, buf)) != NULL ) {
384  if (i > logic_model->inputs->size) {
385  vpr_printf(TIO_MESSAGE_ERROR,
386  "[LINE %d] .names %s ... %s has a LUT size that exceeds the maximum LUT size (%d) of the architecture.\n",
387  file_line_number, saved_names[0], ptr,
388  logic_model->inputs->size);
389  exit(1);
390  }
391  strcpy(saved_names[i], ptr);
392  i++;
393  }
394  output_net_index = i - 1;
395  if (strcmp(saved_names[output_net_index], "unconn") == 0) {
396  /* unconn is a keyword to pad unused pins, ignore this block */
397  free_matrix(saved_names, 0, logic_model->inputs->size, 0, sizeof(char));
399  return FALSE;
400  }
401 
402  if (!doall) { /* Counting pass only ... */
403  for (j = 0; j <= output_net_index; j++)
404  /* On this pass it doesn't matter if RECEIVER or DRIVER. Just checking if in hash. [0] should be DRIVER */
405  add_vpack_net(saved_names[j], RECEIVER, num_logical_blocks - 1, 0,
406  j, FALSE, doall);
407  free_matrix(saved_names, 0, logic_model->inputs->size, 0, sizeof(char));
408  return FALSE;
409  }
410 
411  logical_block[num_logical_blocks - 1].model = logic_model;
412 
413  if (output_net_index > logic_model->inputs->size) {
414  vpr_printf(TIO_MESSAGE_ERROR,
415  "LUT size of %d in .blif file is too big for FPGA which has a maximum LUT size of %d.\n",
416  output_net_index, logic_model->inputs->size);
417  exit(1);
418  }
419  assert(logic_model->inputs->next == NULL);
420  assert(logic_model->outputs->next == NULL);
421  assert(logic_model->outputs->size == 1);
422 
424  sizeof(int*));
426  sizeof(int*));
428 
430  logic_model->inputs->size * sizeof(int));
432  sizeof(int));
433 
435  for (i = 0; i < output_net_index; i++) /* Do inputs */
436  logical_block[num_logical_blocks - 1].input_nets[0][i] = add_vpack_net(
437  saved_names[i], RECEIVER, num_logical_blocks - 1, 0, i, FALSE,
438  doall);
440  saved_names[output_net_index], DRIVER, num_logical_blocks - 1, 0, 0,
441  FALSE, doall);
442 
443  for (i = output_net_index; i < logic_model->inputs->size; i++)
444  logical_block[num_logical_blocks - 1].input_nets[0][i] = OPEN;
445 
447  saved_names[output_net_index]);
449  num_luts++;
450 
451  free_matrix(saved_names, 0, logic_model->inputs->size, 0, sizeof(char));
452  return (boolean) doall;
453 }
454 
455 static void add_latch(int doall, INP t_model *latch_model) {
456 
457  /* Adds the flipflop (.latch) currently being parsed to the logical_block array. *
458  * Adds its pins to the nets data structure by calling add_vpack_net. If doall *
459  * is zero this is a counting pass; if it is 1 this is the final *
460  * (loading) pass. Blif format for a latch is: *
461  * .latch <input> <output> <type (latch on)> <control (clock)> <init_val> *
462  * The latch pins are in .nets 0 to 2 in the order: Q D CLOCK. */
463 
464  char *ptr, buf[BUFSIZE], saved_names[6][BUFSIZE];
465  int i;
466 
468 
469  /* Count # parameters, making sure we don't go over 6 (avoids memory corr.) */
470  /* Note that we can't rely on the tokens being around unless we copy them. */
471 
472  for (i = 0; i < 6; i++) {
473  ptr = my_strtok(NULL, TOKENS, blif, buf);
474  if (ptr == NULL )
475  break;
476  strcpy(saved_names[i], ptr);
477  }
478 
479  if (i != 5) {
480  vpr_printf(TIO_MESSAGE_ERROR, ".latch does not have 5 parameters.\n");
481  vpr_printf(TIO_MESSAGE_ERROR, "Check netlist, line %d.\n",
483  exit(1);
484  }
485 
486  if (!doall) { /* If only a counting pass ... */
487  add_vpack_net(saved_names[0], RECEIVER, num_logical_blocks - 1, 0, 0,
488  FALSE, doall); /* D */
489  add_vpack_net(saved_names[1], DRIVER, num_logical_blocks - 1, 0, 0,
490  FALSE, doall); /* Q */
491  add_vpack_net(saved_names[3], RECEIVER, num_logical_blocks - 1, 0, 0,
492  TRUE, doall); /* Clock */
493  return;
494  }
495 
496  logical_block[num_logical_blocks - 1].model = latch_model;
498 
500  sizeof(int*));
502  sizeof(int*));
503 
505  sizeof(int));
507  sizeof(int));
508 
510  saved_names[1], DRIVER, num_logical_blocks - 1, 0, 0, FALSE, doall); /* Q */
512  saved_names[0], RECEIVER, num_logical_blocks - 1, 0, 0, FALSE,
513  doall); /* D */
515  saved_names[3], RECEIVER, num_logical_blocks - 1, 0, 0, TRUE,
516  doall); /* Clock */
517 
518  logical_block[num_logical_blocks - 1].name = my_strdup(saved_names[1]);
520  num_latches++;
521 }
522 
523 static void add_subckt(int doall, t_model *user_models) {
524  char *ptr;
525  char *close_bracket;
526  char subckt_name[BUFSIZE];
527  char buf[BUFSIZE];
528  //fpos_t current_subckt_pos;
529  int i, j, iparse;
530  int subckt_index_signals = 0;
531  char **subckt_signal_name = NULL;
532  char *port_name, *pin_number;
533  char **circuit_signal_name = NULL;
534  char *subckt_logical_block_name = NULL;
535  short toggle = 0;
536  int input_net_count, output_net_count, input_port_count, output_port_count;
537  t_model *cur_model;
538  t_model_ports *port;
539  boolean found_subckt_signal;
540 
542  num_subckts++;
543 
544  /* now we have to find the matching subckt */
545  /* find the name we are looking for */
546  strcpy(subckt_name, my_strtok(NULL, TOKENS, blif, buf));
547  /* get all the signals in the form z=r */
548  iparse = 0;
549  while (iparse < MAX_ATOM_PARSE) {
550  iparse++;
551  /* Assumption is that it will be "signal1, =, signal1b, spacing, and repeat" */
552  ptr = my_strtok(NULL, " \t\n=", blif, buf);
553 
554  if (ptr == NULL && toggle == 0)
555  break;
556  else if (ptr == NULL && toggle == 1) {
557  vpr_printf(TIO_MESSAGE_ERROR,
558  "subckt %s formed incorrectly with signal=signal at %s.\n",
559  subckt_name, buf);
560  exit(-1);
561  } else if (toggle == 0) {
562  /* ELSE - parse in one or the other */
563  /* allocate a new spot for both the circuit_signal name and the subckt_signal name */
564  subckt_signal_name = (char**) my_realloc(subckt_signal_name,
565  (subckt_index_signals + 1) * sizeof(char**));
566  circuit_signal_name = (char**) my_realloc(circuit_signal_name,
567  (subckt_index_signals + 1) * sizeof(char**));
568 
569  /* copy in the subckt_signal name */
570  subckt_signal_name[subckt_index_signals] = my_strdup(ptr);
571 
572  toggle = 1;
573  } else if (toggle == 1) {
574  /* copy in the circuit_signal name */
575  circuit_signal_name[subckt_index_signals] = my_strdup(ptr);
576  if (!doall) {
577  /* Counting pass, does not matter if driver or receiver and pin number does not matter */
578  add_vpack_net(circuit_signal_name[subckt_index_signals],
579  RECEIVER, num_logical_blocks - 1, 0, 0, FALSE, doall);
580  }
581 
582  toggle = 0;
583  subckt_index_signals++;
584  }
585  }
586  assert(iparse < MAX_ATOM_PARSE);
587  /* record the position of the parse so far so when we resume we will move to the next item */
588  //if (fgetpos(blif, &current_subckt_pos) != 0) {
589  // vpr_printf(TIO_MESSAGE_ERROR, "In file pointer read - read_blif.c\n");
590  // exit(-1);
591  //}
592  input_net_count = 0;
593  output_net_count = 0;
594 
595  if (doall) {
596  /* get the matching model to this subckt */
597 
598  cur_model = user_models;
599  while (cur_model != NULL ) {
600  if (strcmp(cur_model->name, subckt_name) == 0) {
601  break;
602  }
603  cur_model = cur_model->next;
604  }
605  if (cur_model == NULL ) {
606  vpr_printf(TIO_MESSAGE_ERROR,
607  "Did not find matching model to subckt %s.\n", subckt_name);
608  exit(-1);
609  }
610 
611  /* IF - do all then we need to allocate a string to hold all the subckt info */
612 
613  /* initialize the logical_block structure */
614 
615  /* record model info */
616  logical_block[num_logical_blocks - 1].model = cur_model;
617 
618  /* allocate space for inputs and initialize all input nets to OPEN */
619  input_port_count = 0;
620  port = cur_model->inputs;
621  while (port) {
622  if (!port->is_clock) {
623  input_port_count++;
624  }
625  port = port->next;
626  }
628  input_port_count * sizeof(int *));
629 
630  port = cur_model->inputs;
631  while (port) {
632  if (port->is_clock) {
633  /* Clock ports are different from regular input ports, skip */
634  port = port->next;
635  continue;
636  }
637  assert(port->size >= 0);
639  (int*) my_malloc(port->size * sizeof(int));
640  for (j = 0; j < port->size; j++) {
642  OPEN;
643  }
644  port = port->next;
645  }
646  assert(port == NULL || (port->is_clock && port->next == NULL));
647 
648  /* allocate space for outputs and initialize all output nets to OPEN */
649  output_port_count = 0;
650  port = cur_model->outputs;
651  while (port) {
652  port = port->next;
653  output_port_count++;
654  }
656  output_port_count * sizeof(int *));
657 
658  port = cur_model->outputs;
659  while (port) {
660  assert(port->size >= 0);
662  (int*) my_malloc(port->size * sizeof(int));
663  for (j = 0; j < port->size; j++) {
665  OPEN;
666  }
667  port = port->next;
668  }
669  assert(port == NULL);
670 
671  /* initialize clock data */
673 
677 
678  /* setup the index signal if open or not */
679 
680  for (i = 0; i < subckt_index_signals; i++) {
681  found_subckt_signal = FALSE;
682  /* determine the port name and the pin_number of the subckt */
683  port_name = my_strdup(subckt_signal_name[i]);
684  pin_number = strrchr(port_name, '[');
685  if (pin_number == NULL ) {
686  pin_number = "0"; /* default to 0 */
687  } else {
688  /* The pin numbering is port_name[pin_number] so need to go one to the right of [ then NULL out ] */
689  *pin_number = '\0';
690  pin_number++;
691  close_bracket = pin_number;
692  while (*close_bracket != '\0' && *close_bracket != ']') {
693  close_bracket++;
694  }
695  *close_bracket = '\0';
696  }
697 
698  port = cur_model->inputs;
699  while (port) {
700  if (strcmp(port_name, port->name) == 0) {
701  if (found_subckt_signal) {
702  vpr_printf(TIO_MESSAGE_ERROR,
703  "Two instances of %s subckt signal found in subckt %s.\n",
704  subckt_signal_name[i], subckt_name);
705  }
706  found_subckt_signal = TRUE;
707  if (port->is_clock) {
708  assert(
709  logical_block[num_logical_blocks-1].clock_net == OPEN);
710  assert(my_atoi(pin_number) == 0);
712  add_vpack_net(circuit_signal_name[i], RECEIVER,
713  num_logical_blocks - 1, port->index,
714  my_atoi(pin_number), TRUE, doall);
715  } else {
717  pin_number)] = add_vpack_net(
718  circuit_signal_name[i], RECEIVER,
719  num_logical_blocks - 1, port->index,
720  my_atoi(pin_number), FALSE, doall);
721  input_net_count++;
722  }
723  }
724  port = port->next;
725  }
726 
727  port = cur_model->outputs;
728  while (port) {
729  if (strcmp(port_name, port->name) == 0) {
730  if (found_subckt_signal) {
731  vpr_printf(TIO_MESSAGE_ERROR,
732  "Two instances of %s subckt signal found in subckt %s.\n",
733  subckt_signal_name[i], subckt_name);
734  }
735  found_subckt_signal = TRUE;
737  pin_number)] = add_vpack_net(circuit_signal_name[i],
738  DRIVER, num_logical_blocks - 1, port->index,
739  my_atoi(pin_number), FALSE, doall);
740  if (subckt_logical_block_name == NULL
741  && circuit_signal_name[i] != NULL ) {
742  subckt_logical_block_name = circuit_signal_name[i];
743  }
744  output_net_count++;
745  }
746  port = port->next;
747  }
748 
749  /* record the name to be first output net parsed */
750  if(logical_block[num_logical_blocks - 1].name == NULL) {
752  subckt_logical_block_name);
753  }
754 
755  if (!found_subckt_signal) {
756  vpr_printf(TIO_MESSAGE_ERROR, "Unknown subckt port %s.\n",
757  subckt_signal_name[i]);
758  exit(1);
759  }
760  free(port_name);
761  }
762  }
763 
764  for (i = 0; i < subckt_index_signals; i++) {
765  free(subckt_signal_name[i]);
766  free(circuit_signal_name[i]);
767  }
768  free(subckt_signal_name);
769  free(circuit_signal_name);
770 
771  /* now that you've done the analysis, move the file pointer back */
772  //if (fsetpos(blif, &current_subckt_pos) != 0) {
773  // vpr_printf(TIO_MESSAGE_ERROR, "In moving back file pointer - read_blif.c\n");
774  // exit(-1);
775  //}
776 }
777 
778 static void io_line(int in_or_out, int doall, t_model *io_model) {
779 
780  /* Adds an input or output logical_block to the logical_block data structures. *
781  * in_or_out: DRIVER for input, RECEIVER for output. *
782  * doall: 1 for final pass when structures are loaded. 0 for *
783  * first pass when hash table is built and pins, nets, etc. are counted. */
784 
785  char *ptr;
786  char buf2[BUFSIZE];
787  int nindex, len, iparse;
788 
789  iparse = 0;
790  while (iparse < MAX_ATOM_PARSE) {
791  iparse++;
792  ptr = my_strtok(NULL, TOKENS, blif, buf2);
793  if (ptr == NULL )
794  return;
796 
797  nindex = add_vpack_net(ptr, in_or_out, num_logical_blocks - 1, 0, 0,
798  FALSE, doall);
799  /* zero offset indexing */
800  if (!doall)
801  continue; /* Just counting things when doall == 0 */
802 
806  logical_block[num_logical_blocks - 1].model = io_model;
807 
808  len = strlen(ptr);
809  if (in_or_out == RECEIVER) { /* output pads need out: prefix
810  * to make names unique from LUTs */
812  (len + 1 + 4) * sizeof(char)); /* Space for out: at start */
813  strcpy(logical_block[num_logical_blocks - 1].name, "out:");
814  strcat(logical_block[num_logical_blocks - 1].name, ptr);
816  (int **) my_malloc(sizeof(int*));
818  (int *) my_malloc(sizeof(int));
820  } else {
821  assert(in_or_out == DRIVER);
823  (len + 1) * sizeof(char));
824  strcpy(logical_block[num_logical_blocks - 1].name, ptr);
826  (int **) my_malloc(sizeof(int*));
828  (int *) my_malloc(sizeof(int));
830  }
831 
832  if (in_or_out == DRIVER) { /* processing .inputs line */
833  num_p_inputs++;
835  logical_block[num_logical_blocks - 1].output_nets[0][0] = nindex;
836  } else { /* processing .outputs line */
837  num_p_outputs++;
839  logical_block[num_logical_blocks - 1].input_nets[0][0] = nindex;
840  }
842  }
843  assert(iparse < MAX_ATOM_PARSE);
844 }
845 
846 static void check_and_count_models(int doall, const char* model_name,
847  t_model *user_models) {
848  fpos_t start_pos;
849  t_model *user_model;
850 
851  num_blif_models++;
852  if (doall) {
853  /* get start position to do two passes on model */
854  if (fgetpos(blif, &start_pos) != 0) {
855  vpr_printf(TIO_MESSAGE_ERROR,
856  "in file pointer read - read_blif.c\n");
857  exit(-1);
858  }
859 
860  /* get corresponding architecture model */
861  user_model = user_models;
862  while (user_model) {
863  if (0 == strcmp(model_name, user_model->name)) {
864  break;
865  }
866  user_model = user_model->next;
867  }
868  if (user_model == NULL ) {
869  vpr_printf(TIO_MESSAGE_ERROR,
870  "No corresponding model %s in architecture description.\n",
871  model_name);
872  exit(1);
873  }
874 
875  /* check ports */
876  }
877 }
878 
879 static int add_vpack_net(char *ptr, int type, int bnum, int bport, int bpin,
880  boolean is_global, int doall) {
881 
882  /* This routine is given a vpack_net name in *ptr, either DRIVER or RECEIVER *
883  * specifying whether the logical_block number (bnum) and the output pin (bpin) is driving this *
884  * vpack_net or in the fan-out and doall, which is 0 for the counting pass *
885  * and 1 for the loading pass. It updates the vpack_net data structure and *
886  * returns the vpack_net number so the calling routine can update the logical_block *
887  * data structure. */
888 
889  struct s_hash *h_ptr, *prev_ptr;
890  int index, j, nindex;
891 
892  if (strcmp(ptr, "open") == 0) {
893  vpr_printf(TIO_MESSAGE_ERROR,
894  "net name \"open\" is a reserved keyword in VPR.");
895  exit(1);
896  }
897 
898  if (strcmp(ptr, "unconn") == 0) {
899  return OPEN;
900  }
901  index = hash_value(ptr);
902 
903  if (doall) {
904  if (type == RECEIVER && !is_global) {
906  } else if (type == DRIVER) {
908  }
909  }
910 
911  h_ptr = blif_hash[index];
912  prev_ptr = h_ptr;
913 
914  while (h_ptr != NULL ) {
915  if (strcmp(h_ptr->name, ptr) == 0) { /* Net already in hash table */
916  nindex = h_ptr->index;
917 
918  if (!doall) { /* Counting pass only */
919  (h_ptr->count)++;
920  return (nindex);
921  }
922 
923  if (type == DRIVER) {
924  num_driver[nindex]++;
925  j = 0; /* Driver always in position 0 of pinlist */
926  } else {
927  vpack_net[nindex].num_sinks++;
928  if ((num_driver[nindex] < 0) || (num_driver[nindex] > 1)) {
929  vpr_printf(TIO_MESSAGE_ERROR,
930  "Number of drivers for net #%d (%s) has %d drivers.\n",
931  nindex, ptr, num_driver[index]);
932  }
933  j = vpack_net[nindex].num_sinks;
934 
935  /* num_driver is the number of signal drivers of this vpack_net. *
936  * should always be zero or 1 unless the netlist is bad. */
937  if ((vpack_net[nindex].num_sinks - num_driver[nindex])
938  >= temp_num_pins[nindex]) {
939  vpr_printf(TIO_MESSAGE_ERROR,
940  "Net #%d (%s) has no driver and will cause memory corruption.\n",
941  nindex, ptr);
942  exit(1);
943  }
944  }
945  vpack_net[nindex].node_block[j] = bnum;
946  vpack_net[nindex].node_block_port[j] = bport;
947  vpack_net[nindex].node_block_pin[j] = bpin;
948  vpack_net[nindex].is_global = is_global;
949  return (nindex);
950  }
951  prev_ptr = h_ptr;
952  h_ptr = h_ptr->next;
953  }
954 
955  /* Net was not in the hash table. */
956 
957  if (doall == 1) {
958  vpr_printf(TIO_MESSAGE_ERROR,
959  "in add_vpack_net: The second (load) pass could not find vpack_net %s in the symbol table.\n",
960  ptr);
961  exit(1);
962  }
963 
964  /* Add the vpack_net (only counting pass will add nets to symbol table). */
965 
967  h_ptr = (struct s_hash *) my_malloc(sizeof(struct s_hash));
968  if (prev_ptr == NULL ) {
969  blif_hash[index] = h_ptr;
970  } else {
971  prev_ptr->next = h_ptr;
972  }
973  h_ptr->next = NULL;
974  h_ptr->index = num_logical_nets - 1;
975  h_ptr->count = 1;
976  h_ptr->name = my_strdup(ptr);
977  return (h_ptr->index);
978 }
979 
980 void echo_input(char *blif_file, char *echo_file, t_model *library_models) {
981 
982  /* Echo back the netlist data structures to file input.echo to *
983  * allow the user to look at the internal state of the program *
984  * and check the parsing. */
985 
986  int i, j;
987  FILE *fp;
988  t_model_ports *port;
989  t_model *latch_model;
990  t_model *logic_model;
991  t_model *cur;
992  int *lut_distribution;
993  int num_absorbable_latch;
994  int inet;
995 
996  cur = library_models;
997  logic_model = latch_model = NULL;
998  while (cur) {
999  if (strcmp(cur->name, MODEL_LOGIC) == 0) {
1000  logic_model = cur;
1001  assert(logic_model->inputs->next == NULL);
1002  } else if (strcmp(cur->name, MODEL_LATCH) == 0) {
1003  latch_model = cur;
1004  assert(latch_model->inputs->size == 1);
1005  }
1006  cur = cur->next;
1007  }
1008 
1009  lut_distribution = (int*) my_calloc(logic_model->inputs[0].size + 1,
1010  sizeof(int));
1011  num_absorbable_latch = 0;
1012  for (i = 0; i < num_logical_blocks; i++) {
1013  if (logical_block[i].model == logic_model) {
1014  if (logic_model == NULL )
1015  continue;
1016  for (j = 0; j < logic_model->inputs[0].size; j++) {
1017  if (logical_block[i].input_nets[0][j] == OPEN) {
1018  break;
1019  }
1020  }
1021  lut_distribution[j]++;
1022  } else if (logical_block[i].model == latch_model) {
1023  if (latch_model == NULL )
1024  continue;
1025  inet = logical_block[i].input_nets[0][0];
1026  if (vpack_net[inet].num_sinks == 1
1027  && logical_block[vpack_net[inet].node_block[0]].model
1028  == logic_model) {
1029  num_absorbable_latch++;
1030  }
1031  }
1032  }
1033 
1034  vpr_printf(TIO_MESSAGE_INFO, "Input netlist file: '%s', model: %s\n",
1035  blif_file, model);
1036  vpr_printf(TIO_MESSAGE_INFO, "Primary inputs: %d, primary outputs: %d\n",
1038  vpr_printf(TIO_MESSAGE_INFO, "LUTs: %d, latches: %d, subckts: %d\n",
1040  vpr_printf(TIO_MESSAGE_INFO, "# standard absorbable latches: %d\n",
1041  num_absorbable_latch);
1042  vpr_printf(TIO_MESSAGE_INFO, "\t");
1043  for (i = 0; i < logic_model->inputs[0].size + 1; i++) {
1044  if (i > 0)
1045  vpr_printf(TIO_MESSAGE_DIRECT, ", ");
1046  vpr_printf(TIO_MESSAGE_DIRECT, "LUT size %d = %d", i,
1047  lut_distribution[i]);
1048  }
1049  vpr_printf(TIO_MESSAGE_DIRECT, "\n");
1050  vpr_printf(TIO_MESSAGE_INFO, "Total blocks: %d, total nets: %d\n",
1051  num_logical_blocks, num_logical_nets);
1052 
1053  fp = my_fopen(echo_file, "w", 0);
1054 
1055  fprintf(fp, "Input netlist file: '%s', model: %s\n", blif_file, model);
1056  fprintf(fp,
1057  "num_p_inputs: %d, num_p_outputs: %d, num_luts: %d, num_latches: %d\n",
1059  fprintf(fp, "num_logical_blocks: %d, num_logical_nets: %d\n",
1060  num_logical_blocks, num_logical_nets);
1061 
1062  fprintf(fp, "\nNet\tName\t\t#Pins\tDriver\tRecvs.\n");
1063  for (i = 0; i < num_logical_nets; i++) {
1064  fprintf(fp, "\n%d\t%s\t", i, vpack_net[i].name);
1065  if (strlen(vpack_net[i].name) < 8)
1066  fprintf(fp, "\t"); /* Name field is 16 chars wide */
1067  fprintf(fp, "%d", vpack_net[i].num_sinks + 1);
1068  for (j = 0; j <= vpack_net[i].num_sinks; j++)
1069  fprintf(fp, "\t(%d,%d,%d)", vpack_net[i].node_block[j],
1070  vpack_net[i].node_block_port[j],
1071  vpack_net[i].node_block_pin[j]);
1072  }
1073 
1074  fprintf(fp, "\n\nBlocks\t\tBlock type legend:\n");
1075  fprintf(fp, "\t\tINPAD = %d\tOUTPAD = %d\n", VPACK_INPAD, VPACK_OUTPAD);
1076  fprintf(fp, "\t\tCOMB = %d\tLATCH = %d\n", VPACK_COMB, VPACK_LATCH);
1077  fprintf(fp, "\t\tEMPTY = %d\n", VPACK_EMPTY);
1078 
1079  for (i = 0; i < num_logical_blocks; i++) {
1080  fprintf(fp, "\nblock %d %s ", i, logical_block[i].name);
1081  fprintf(fp, "\ttype: %d ", logical_block[i].type);
1082  fprintf(fp, "\tmodel name: %s\n", logical_block[i].model->name);
1083 
1084  port = logical_block[i].model->inputs;
1085 
1086  while (port) {
1087  fprintf(fp, "\tinput port: %s \t", port->name);
1088  for (j = 0; j < port->size; j++) {
1089  if (logical_block[i].input_nets[port->index][j] == OPEN)
1090  fprintf(fp, "OPEN ");
1091  else
1092  fprintf(fp, "%d ",
1093  logical_block[i].input_nets[port->index][j]);
1094  }
1095  fprintf(fp, "\n");
1096  port = port->next;
1097  }
1098 
1099  port = logical_block[i].model->outputs;
1100  while (port) {
1101  fprintf(fp, "\toutput port: %s \t", port->name);
1102  for (j = 0; j < port->size; j++) {
1103  if (logical_block[i].output_nets[port->index][j] == OPEN) {
1104  fprintf(fp, "OPEN ");
1105  } else {
1106  fprintf(fp, "%d ",
1107  logical_block[i].output_nets[port->index][j]);
1108  }
1109  }
1110  fprintf(fp, "\n");
1111  port = port->next;
1112  }
1113 
1114  fprintf(fp, "\tclock net: %d\n", logical_block[i].clock_net);
1115  }
1116  fclose(fp);
1117 }
1118 
1119 /* load default vpack models (inpad, outpad, logic) */
1120 static void load_default_models(INP t_model *library_models,
1121  OUTP t_model** inpad_model, OUTP t_model** outpad_model,
1122  OUTP t_model** logic_model, OUTP t_model** latch_model) {
1123  t_model *cur_model;
1124  cur_model = library_models;
1125  *inpad_model = *outpad_model = *logic_model = *latch_model = NULL;
1126  while (cur_model) {
1127  if (strcmp(MODEL_INPUT, cur_model->name) == 0) {
1128  assert(cur_model->inputs == NULL);
1129  assert(cur_model->outputs->next == NULL);
1130  assert(cur_model->outputs->size == 1);
1131  *inpad_model = cur_model;
1132  } else if (strcmp(MODEL_OUTPUT, cur_model->name) == 0) {
1133  assert(cur_model->outputs == NULL);
1134  assert(cur_model->inputs->next == NULL);
1135  assert(cur_model->inputs->size == 1);
1136  *outpad_model = cur_model;
1137  } else if (strcmp(MODEL_LOGIC, cur_model->name) == 0) {
1138  assert(cur_model->inputs->next == NULL);
1139  assert(cur_model->outputs->next == NULL);
1140  assert(cur_model->outputs->size == 1);
1141  *logic_model = cur_model;
1142  } else if (strcmp(MODEL_LATCH, cur_model->name) == 0) {
1143  assert(cur_model->outputs->next == NULL);
1144  assert(cur_model->outputs->size == 1);
1145  *latch_model = cur_model;
1146  } else {
1147  assert(0);
1148  }
1149  cur_model = cur_model->next;
1150  }
1151 }
1152 
1153 static void check_net(boolean sweep_hanging_nets_and_inputs) {
1154 
1155  /* Checks the input netlist for obvious errors. */
1156 
1157  int i, j, k, error, iblk, ipin, iport, inet, L_check_net;
1158  boolean found;
1159  int count_inputs, count_outputs;
1160  int explicit_vpack_models;
1161  t_model_ports *port;
1162  struct s_linked_vptr *p_io_removed;
1163  int removed_nets;
1164  int count_unconn_blocks;
1165 
1166  explicit_vpack_models = num_blif_models + 1;
1167 
1168  error = 0;
1169  removed_nets = 0;
1170 
1171  if (ilines != explicit_vpack_models) {
1172  vpr_printf(TIO_MESSAGE_ERROR, "Found %d .inputs lines; expected %d.\n",
1173  ilines, explicit_vpack_models);
1174  error++;
1175  }
1176 
1177  if (olines != explicit_vpack_models) {
1178  vpr_printf(TIO_MESSAGE_ERROR, "Found %d .outputs lines; expected %d.\n",
1179  olines, explicit_vpack_models);
1180  error++;
1181  }
1182 
1183  if (model_lines != explicit_vpack_models) {
1184  vpr_printf(TIO_MESSAGE_ERROR, "Found %d .model lines; expected %d.\n",
1186  error++;
1187  }
1188 
1189  if (endlines != explicit_vpack_models) {
1190  vpr_printf(TIO_MESSAGE_ERROR, "Found %d .end lines; expected %d.\n",
1191  endlines, explicit_vpack_models);
1192  error++;
1193  }
1194  for (i = 0; i < num_logical_nets; i++) {
1195 
1196  if (num_driver[i] != 1) {
1197  vpr_printf(TIO_MESSAGE_ERROR,
1198  "vpack_net %s has %d signals driving it.\n",
1199  vpack_net[i].name, num_driver[i]);
1200  error++;
1201  }
1202 
1203  if (vpack_net[i].num_sinks == 0) {
1204 
1205  /* If this is an input pad, it is unused and I just remove it with *
1206  * a warning message. Lots of the mcnc circuits have this problem.
1207 
1208  Also, subckts from ODIN often have unused driven nets
1209  */
1210 
1211  iblk = vpack_net[i].node_block[0];
1212  iport = vpack_net[i].node_block_port[0];
1213  ipin = vpack_net[i].node_block_pin[0];
1214 
1215  assert((vpack_net[i].num_sinks - num_driver[i]) == -1);
1216 
1217  /* All nets should connect to inputs of block except output pads */
1218  if (logical_block[iblk].type != VPACK_OUTPAD) {
1219  if (sweep_hanging_nets_and_inputs) {
1220  removed_nets++;
1221  vpack_net[i].node_block[0] = OPEN;
1222  vpack_net[i].node_block_port[0] = OPEN;
1223  vpack_net[i].node_block_pin[0] = OPEN;
1224  logical_block[iblk].output_nets[iport][ipin] = OPEN;
1226  } else {
1227  vpr_printf(TIO_MESSAGE_WARNING,
1228  "vpack_net %s has no fanout.\n", vpack_net[i].name);
1229  }
1230  continue;
1231  }
1232  }
1233 
1234  if (strcmp(vpack_net[i].name, "open") == 0
1235  || strcmp(vpack_net[i].name, "unconn") == 0) {
1236  vpr_printf(TIO_MESSAGE_ERROR,
1237  "vpack_net #%d has the reserved name %s.\n", i,
1238  vpack_net[i].name);
1239  error++;
1240  }
1241 
1242  for (j = 0; j <= vpack_net[i].num_sinks; j++) {
1243  iblk = vpack_net[i].node_block[j];
1244  iport = vpack_net[i].node_block_port[j];
1245  ipin = vpack_net[i].node_block_pin[j];
1246  if (ipin == OPEN) {
1247  /* Clocks are not connected to regular pins on a block hence open */
1248  L_check_net = logical_block[iblk].clock_net;
1249  if (L_check_net != i) {
1250  vpr_printf(TIO_MESSAGE_ERROR,
1251  "Clock net for block %s #%d is net %s #%d but connecting net is %s #%d.\n",
1252  logical_block[iblk].name, iblk,
1253  vpack_net[L_check_net].name, L_check_net,
1254  vpack_net[i].name, i);
1255  error++;
1256  }
1257 
1258  } else {
1259  if (j == 0) {
1260  L_check_net = logical_block[iblk].output_nets[iport][ipin];
1261  if (L_check_net != i) {
1262  vpr_printf(TIO_MESSAGE_ERROR,
1263  "Output net for block %s #%d is net %s #%d but connecting net is %s #%d.\n",
1264  logical_block[iblk].name, iblk,
1265  vpack_net[L_check_net].name, L_check_net,
1266  vpack_net[i].name, i);
1267  error++;
1268  }
1269  } else {
1270  if (vpack_net[i].is_global) {
1271  L_check_net = logical_block[iblk].clock_net;
1272  } else {
1273  L_check_net =
1274  logical_block[iblk].input_nets[iport][ipin];
1275  }
1276  if (L_check_net != i) {
1277  vpr_printf(TIO_MESSAGE_ERROR,
1278  "Input net for block %s #%d is net %s #%d but connecting net is %s #%d.\n",
1279  logical_block[iblk].name, iblk,
1280  vpack_net[L_check_net].name, L_check_net,
1281  vpack_net[i].name, i);
1282  error++;
1283  }
1284  }
1285  }
1286  }
1287  }
1288  vpr_printf(TIO_MESSAGE_INFO, "Swept away %d nets with no fanout.\n",
1289  removed_nets);
1290  count_unconn_blocks = 0;
1291  for (i = 0; i < num_logical_blocks; i++) {
1292  /* This block has no output and is not an output pad so it has no use, hence we remove it */
1293  if ((logical_block_output_count[i] == 0)
1294  && (logical_block[i].type != VPACK_OUTPAD)) {
1295  vpr_printf(TIO_MESSAGE_WARNING,
1296  "logical_block %s #%d has no fanout.\n",
1297  logical_block[i].name, i);
1298  if (sweep_hanging_nets_and_inputs
1299  && (logical_block[i].type == VPACK_INPAD)) {
1301  vpr_printf(TIO_MESSAGE_INFO, "Removing input.\n");
1302  p_io_removed = (struct s_linked_vptr*) my_malloc(
1303  sizeof(struct s_linked_vptr));
1304  p_io_removed->data_vptr = my_strdup(logical_block[i].name);
1305  p_io_removed->next = circuit_p_io_removed;
1306  circuit_p_io_removed = p_io_removed;
1307  continue;
1308  } else {
1309  count_unconn_blocks++;
1310  vpr_printf(TIO_MESSAGE_WARNING,
1311  "Sweep hanging nodes in your logic synthesis tool because VPR can not do this yet.\n");
1312  }
1313  }
1314  count_inputs = 0;
1315  count_outputs = 0;
1316  port = logical_block[i].model->inputs;
1317  while (port) {
1318  if (port->is_clock) {
1319  port = port->next;
1320  continue;
1321  }
1322 
1323  for (j = 0; j < port->size; j++) {
1324  if (logical_block[i].input_nets[port->index][j] == OPEN)
1325  continue;
1326  count_inputs++;
1327  inet = logical_block[i].input_nets[port->index][j];
1328  found = FALSE;
1329  for (k = 1; k <= vpack_net[inet].num_sinks; k++) {
1330  if (vpack_net[inet].node_block[k] == i) {
1331  if (vpack_net[inet].node_block_port[k] == port->index) {
1332  if (vpack_net[inet].node_block_pin[k] == j) {
1333  found = TRUE;
1334  }
1335  }
1336  }
1337  }
1338  assert(found == TRUE);
1339  }
1340  port = port->next;
1341  }
1342  assert(count_inputs == logical_block_input_count[i]);
1343  logical_block[i].used_input_pins = count_inputs;
1344 
1345  port = logical_block[i].model->outputs;
1346  while (port) {
1347  for (j = 0; j < port->size; j++) {
1348  if (logical_block[i].output_nets[port->index][j] == OPEN)
1349  continue;
1350  count_outputs++;
1351  inet = logical_block[i].output_nets[port->index][j];
1352  vpack_net[inet].is_const_gen = FALSE;
1353  if (count_inputs == 0 && logical_block[i].type != VPACK_INPAD
1354  && logical_block[i].type != VPACK_OUTPAD
1355  && logical_block[i].clock_net == OPEN) {
1356  vpr_printf(TIO_MESSAGE_INFO,
1357  "Net is a constant generator: %s.\n",
1358  vpack_net[inet].name);
1359  vpack_net[inet].is_const_gen = TRUE;
1360  }
1361  found = FALSE;
1362  if (vpack_net[inet].node_block[0] == i) {
1363  if (vpack_net[inet].node_block_port[0] == port->index) {
1364  if (vpack_net[inet].node_block_pin[0] == j) {
1365  found = TRUE;
1366  }
1367  }
1368  }
1369  assert(found == TRUE);
1370  }
1371  port = port->next;
1372  }
1373  assert(count_outputs == logical_block_output_count[i]);
1374 
1375  if (logical_block[i].type == VPACK_LATCH) {
1376  if (logical_block_input_count[i] != 1) {
1377  vpr_printf(TIO_MESSAGE_ERROR,
1378  "Latch #%d with output %s has %d input pin(s), expected one (D).\n",
1379  i, logical_block[i].name, logical_block_input_count[i]);
1380  error++;
1381  }
1382  if (logical_block_output_count[i] != 1) {
1383  vpr_printf(TIO_MESSAGE_ERROR,
1384  "Latch #%d with output %s has %d output pin(s), expected one (Q).\n",
1385  i, logical_block[i].name,
1387  error++;
1388  }
1389  if (logical_block[i].clock_net == OPEN) {
1390  vpr_printf(TIO_MESSAGE_ERROR,
1391  "Latch #%d with output %s has no clock.\n", i,
1392  logical_block[i].name);
1393  error++;
1394  }
1395  }
1396 
1397  else if (logical_block[i].type == VPACK_INPAD) {
1398  if (logical_block_input_count[i] != 0) {
1399  vpr_printf(TIO_MESSAGE_ERROR,
1400  "IO inpad logical_block #%d name %s of type %d" "has %d input pins.\n",
1401  i, logical_block[i].name, logical_block[i].type,
1403  error++;
1404  }
1405  if (logical_block_output_count[i] != 1) {
1406  vpr_printf(TIO_MESSAGE_ERROR,
1407  "IO inpad logical_block #%d name %s of type %d" "has %d output pins.\n",
1408  i, logical_block[i].name, logical_block[i].type,
1410  error++;
1411  }
1412  if (logical_block[i].clock_net != OPEN) {
1413  vpr_printf(TIO_MESSAGE_ERROR,
1414  "IO inpad #%d with output %s has clock.\n", i,
1415  logical_block[i].name);
1416  error++;
1417  }
1418  } else if (logical_block[i].type == VPACK_OUTPAD) {
1419  if (logical_block_input_count[i] != 1) {
1420  vpr_printf(TIO_MESSAGE_ERROR,
1421  "io outpad logical_block #%d name %s of type %d" "has %d input pins.\n",
1422  i, logical_block[i].name, logical_block[i].type,
1424  error++;
1425  }
1426  if (logical_block_output_count[i] != 0) {
1427  vpr_printf(TIO_MESSAGE_ERROR,
1428  "io outpad logical_block #%d name %s of type %d" "has %d output pins.\n",
1429  i, logical_block[i].name, logical_block[i].type,
1431  error++;
1432  }
1433  if (logical_block[i].clock_net != OPEN) {
1434  vpr_printf(TIO_MESSAGE_ERROR,
1435  "io outpad #%d with name %s has clock.\n", i,
1436  logical_block[i].name);
1437  error++;
1438  }
1439  } else if (logical_block[i].type == VPACK_COMB) {
1440  if (logical_block_input_count[i] <= 0) {
1441  vpr_printf(TIO_MESSAGE_WARNING,
1442  "logical_block #%d with output %s has only %d pin.\n",
1443  i, logical_block[i].name, logical_block_input_count[i]);
1444 
1445  if (logical_block_input_count[i] < 0) {
1446  error++;
1447  } else {
1448  if (logical_block_output_count[i] > 0) {
1449  vpr_printf(TIO_MESSAGE_WARNING,
1450  "Block contains output -- may be a constant generator.\n");
1451  } else {
1452  vpr_printf(TIO_MESSAGE_WARNING,
1453  "Block contains no output.\n");
1454  }
1455  }
1456  }
1457 
1458  if (strcmp(logical_block[i].model->name, MODEL_LOGIC) == 0) {
1459  if (logical_block_output_count[i] != 1) {
1460  vpr_printf(TIO_MESSAGE_WARNING,
1461  "Logical_block #%d name %s of model %s has %d output pins instead of 1.\n",
1462  i, logical_block[i].name,
1463  logical_block[i].model->name,
1465  }
1466  }
1467  } else {
1468  vpr_printf(TIO_MESSAGE_ERROR,
1469  "Unknown type for logical_block #%d %s.\n", i,
1470  logical_block[i].name);
1471  }
1472  }
1473  vpr_printf(TIO_MESSAGE_INFO, "%d unconnected blocks in input netlist.\n", count_unconn_blocks);
1474 
1475  if (error != 0) {
1476  vpr_printf(TIO_MESSAGE_ERROR,
1477  "Found %d fatal errors in the input netlist.\n", error);
1478  exit(1);
1479  }
1480 }
1481 
1482 static void free_parse(void) {
1483 
1484  /* Release memory needed only during blif network parsing. */
1485 
1486  int i;
1487  struct s_hash *h_ptr, *temp_ptr;
1488 
1489  for (i = 0; i < HASHSIZE; i++) {
1490  h_ptr = blif_hash[i];
1491  while (h_ptr != NULL ) {
1492  free((void *) h_ptr->name);
1493  temp_ptr = h_ptr->next;
1494  free((void *) h_ptr);
1495  h_ptr = temp_ptr;
1496  }
1497  }
1498  free((void *) num_driver);
1499  free((void *) blif_hash);
1500  free((void *) temp_num_pins);
1501 }
1502 
1503 static void absorb_buffer_luts(void) {
1504  /* This routine uses a simple pattern matching algorithm to remove buffer LUTs where possible (single-input LUTs that are programmed to be a wire) */
1505 
1506  int bnum, in_blk, out_blk, ipin, out_net, in_net;
1507  int removed = 0;
1508 
1509  /* Pin ordering for the clb blocks (1 VPACK_LUT + 1 FF in each logical_block) is *
1510  * output, n VPACK_LUT inputs, clock input. */
1511 
1512  for (bnum = 0; bnum < num_logical_blocks; bnum++) {
1513  if (strcmp(logical_block[bnum].model->name, "names") == 0) {
1514  if (logical_block[bnum].truth_table != NULL
1515  && logical_block[bnum].truth_table->data_vptr) {
1516  if (strcmp("0 0",
1517  (char*) logical_block[bnum].truth_table->data_vptr) == 0
1518  || strcmp("1 1",
1519  (char*) logical_block[bnum].truth_table->data_vptr)
1520  == 0) {
1521  for (ipin = 0;
1522  ipin < logical_block[bnum].model->inputs->size;
1523  ipin++) {
1524  if (logical_block[bnum].input_nets[0][ipin] == OPEN)
1525  break;
1526  }
1527  assert(ipin == 1);
1528 
1529  assert(logical_block[bnum].clock_net == OPEN);
1530  assert(logical_block[bnum].model->inputs->next == NULL);
1531  assert(logical_block[bnum].model->outputs->size == 1);
1532  assert(logical_block[bnum].model->outputs->next == NULL);
1533 
1534  in_net = logical_block[bnum].input_nets[0][0]; /* Net driving the buffer */
1535  out_net = logical_block[bnum].output_nets[0][0]; /* Net the buffer us driving */
1536  out_blk = vpack_net[out_net].node_block[1];
1537  in_blk = vpack_net[in_net].node_block[0];
1538 
1539  assert(in_net != OPEN);
1540  assert(out_net != OPEN);
1541  assert(out_blk != OPEN);
1542  assert(in_blk != OPEN);
1543 
1544  /* TODO: Make this handle general cases, due to time reasons I can only handle buffers with single outputs */
1545  if (vpack_net[out_net].num_sinks == 1) {
1546  for (ipin = 1; ipin <= vpack_net[in_net].num_sinks;
1547  ipin++) {
1548  if (vpack_net[in_net].node_block[ipin] == bnum) {
1549  break;
1550  }
1551  }
1552  assert(ipin <= vpack_net[in_net].num_sinks);
1553 
1554  vpack_net[in_net].node_block[ipin] =
1555  vpack_net[out_net].node_block[1]; /* New output */
1556  vpack_net[in_net].node_block_port[ipin] =
1557  vpack_net[out_net].node_block_port[1];
1558  vpack_net[in_net].node_block_pin[ipin] =
1559  vpack_net[out_net].node_block_pin[1];
1560 
1561  assert(
1562  logical_block[out_blk].input_nets[vpack_net[out_net].node_block_port[1]][vpack_net[out_net].node_block_pin[1]] == out_net);
1563  logical_block[out_blk].input_nets[vpack_net[out_net].node_block_port[1]][vpack_net[out_net].node_block_pin[1]] =
1564  in_net;
1565 
1566  vpack_net[out_net].node_block[0] = OPEN; /* This vpack_net disappears; mark. */
1567  vpack_net[out_net].node_block_pin[0] = OPEN; /* This vpack_net disappears; mark. */
1568  vpack_net[out_net].node_block_port[0] = OPEN; /* This vpack_net disappears; mark. */
1569  vpack_net[out_net].num_sinks = 0; /* This vpack_net disappears; mark. */
1570 
1571  logical_block[bnum].type = VPACK_EMPTY; /* Mark logical_block that had LUT */
1572 
1573  /* error checking */
1574  for (ipin = 0; ipin <= vpack_net[out_net].num_sinks;
1575  ipin++) {
1576  assert(vpack_net[out_net].node_block[ipin] != bnum);
1577  }
1578  removed++;
1579  }
1580  }
1581  }
1582  }
1583  }
1584  vpr_printf(TIO_MESSAGE_INFO, "Removed %d LUT buffers.\n", removed);
1585 }
1586 
1587 static void compress_netlist(void) {
1588 
1589  /* This routine removes all the VPACK_EMPTY blocks and OPEN nets that *
1590  * may have been left behind post synthesis. After this *
1591  * routine, all the VPACK blocks that exist in the netlist *
1592  * are in a contiguous list with no unused spots. The same *
1593  * goes for the list of nets. This means that blocks and nets *
1594  * have to be renumbered somewhat. */
1595 
1596  int inet, iblk, index, ipin, new_num_nets, new_num_blocks, i;
1597  int *net_remap, *block_remap;
1598  int L_num_nets;
1599  t_model_ports *port;
1600  struct s_linked_vptr *tvptr, *next;
1601 
1602  new_num_nets = 0;
1603  new_num_blocks = 0;
1604  net_remap = (int *) my_malloc(num_logical_nets * sizeof(int));
1605  block_remap = (int *) my_malloc(num_logical_blocks * sizeof(int));
1606 
1607  for (inet = 0; inet < num_logical_nets; inet++) {
1608  if (vpack_net[inet].node_block[0] != OPEN) {
1609  net_remap[inet] = new_num_nets;
1610  new_num_nets++;
1611  } else {
1612  net_remap[inet] = OPEN;
1613  }
1614  }
1615 
1616  for (iblk = 0; iblk < num_logical_blocks; iblk++) {
1617  if (logical_block[iblk].type != VPACK_EMPTY) {
1618  block_remap[iblk] = new_num_blocks;
1619  new_num_blocks++;
1620  } else {
1621  block_remap[iblk] = OPEN;
1622  }
1623  }
1624 
1625  if (new_num_nets != num_logical_nets
1626  || new_num_blocks != num_logical_blocks) {
1627 
1628  for (inet = 0; inet < num_logical_nets; inet++) {
1629  if (vpack_net[inet].node_block[0] != OPEN) {
1630  index = net_remap[inet];
1631  vpack_net[index] = vpack_net[inet];
1632  for (ipin = 0; ipin <= vpack_net[index].num_sinks; ipin++) {
1633  vpack_net[index].node_block[ipin] =
1634  block_remap[vpack_net[index].node_block[ipin]];
1635  }
1636  } else {
1637  free(vpack_net[inet].name);
1638  free(vpack_net[inet].node_block);
1639  free(vpack_net[inet].node_block_port);
1640  free(vpack_net[inet].node_block_pin);
1641  }
1642  }
1643 
1644  num_logical_nets = new_num_nets;
1645  vpack_net = (struct s_net *) my_realloc(vpack_net,
1646  num_logical_nets * sizeof(struct s_net));
1647 
1648  for (iblk = 0; iblk < num_logical_blocks; iblk++) {
1649  if (logical_block[iblk].type != VPACK_EMPTY) {
1650  index = block_remap[iblk];
1651  if (index != iblk) {
1652  logical_block[index] = logical_block[iblk];
1653  logical_block[index].index = index; /* array index moved */
1654  }
1655 
1656  L_num_nets = 0;
1657  port = logical_block[index].model->inputs;
1658  while (port) {
1659  for (ipin = 0; ipin < port->size; ipin++) {
1660  if (port->is_clock) {
1661  assert(
1662  port->size == 1 && port->index == 0 && ipin == 0);
1663  if (logical_block[index].clock_net == OPEN)
1664  continue;
1665  logical_block[index].clock_net =
1666  net_remap[logical_block[index].clock_net];
1667  } else {
1668  if (logical_block[index].input_nets[port->index][ipin]
1669  == OPEN)
1670  continue;
1671  logical_block[index].input_nets[port->index][ipin] =
1672  net_remap[logical_block[index].input_nets[port->index][ipin]];
1673  }
1674  L_num_nets++;
1675  }
1676  port = port->next;
1677  }
1678 
1679  port = logical_block[index].model->outputs;
1680  while (port) {
1681  for (ipin = 0; ipin < port->size; ipin++) {
1682  if (logical_block[index].output_nets[port->index][ipin]
1683  == OPEN)
1684  continue;
1685  logical_block[index].output_nets[port->index][ipin] =
1686  net_remap[logical_block[index].output_nets[port->index][ipin]];
1687  L_num_nets++;
1688  }
1689  port = port->next;
1690  }
1691  }
1692 
1693  else {
1694  free(logical_block[iblk].name);
1695  port = logical_block[iblk].model->inputs;
1696  i = 0;
1697  while (port) {
1698  if (!port->is_clock) {
1699  if (logical_block[iblk].input_nets) {
1700  if (logical_block[iblk].input_nets[i]) {
1701  free(logical_block[iblk].input_nets[i]);
1702  logical_block[iblk].input_nets[i] = NULL;
1703  }
1704  }
1705  i++;
1706  }
1707  port = port->next;
1708  }
1709  if (logical_block[iblk].input_nets)
1710  free(logical_block[iblk].input_nets);
1711  port = logical_block[iblk].model->outputs;
1712  i = 0;
1713  while (port) {
1714  if (logical_block[iblk].output_nets) {
1715  if (logical_block[iblk].output_nets[i]) {
1716  free(logical_block[iblk].output_nets[i]);
1717  logical_block[iblk].output_nets[i] = NULL;
1718  }
1719  }
1720  i++;
1721  port = port->next;
1722  }
1723  if (logical_block[iblk].output_nets)
1724  free(logical_block[iblk].output_nets);
1725  tvptr = logical_block[iblk].truth_table;
1726  while (tvptr != NULL ) {
1727  if (tvptr->data_vptr)
1728  free(tvptr->data_vptr);
1729  next = tvptr->next;
1730  free(tvptr);
1731  tvptr = next;
1732  }
1733  }
1734  }
1735 
1736  vpr_printf(TIO_MESSAGE_INFO, "Sweeped away %d nodes.\n",
1737  num_logical_blocks - new_num_blocks);
1738 
1739  num_logical_blocks = new_num_blocks;
1741  num_logical_blocks * sizeof(struct s_logical_block));
1742  }
1743 
1744  /* Now I have to recompute the number of primary inputs and outputs, since *
1745  * some inputs may have been unused and been removed. No real need to *
1746  * recount primary outputs -- it's just done as defensive coding. */
1747 
1748  num_p_inputs = 0;
1749  num_p_outputs = 0;
1750 
1751  for (iblk = 0; iblk < num_logical_blocks; iblk++) {
1752  if (logical_block[iblk].type == VPACK_INPAD)
1753  num_p_inputs++;
1754  else if (logical_block[iblk].type == VPACK_OUTPAD)
1755  num_p_outputs++;
1756  }
1757 
1758  free(net_remap);
1759  free(block_remap);
1760 }
1761 
1762 /* Read blif file and perform basic sweep/accounting on it
1763  * - power_opts: Power options, can be NULL
1764  */
1765 void read_and_process_blif(char *blif_file,
1766  boolean sweep_hanging_nets_and_inputs, t_model *user_models,
1767  t_model *library_models, boolean read_activity_file, char * activity_file) {
1768 
1769  /* begin parsing blif input file */
1770  read_blif(blif_file, sweep_hanging_nets_and_inputs, user_models,
1771  library_models, read_activity_file, activity_file);
1772 
1773  /* TODO: Do check blif here
1774  eg.
1775  for (i = 0; i < num_logical_blocks; i++) {
1776  if (logical_block[i].model->num_inputs > max_subblock_inputs) {
1777  vpr_printf(TIO_MESSAGE_ERROR, "logical_block %s of model %s has %d inputs but architecture only supports subblocks up to %d inputs.\n",
1778  logical_block[i].name, logical_block[i].model->name, logical_block[i].model->num_inputs, max_subblock_inputs);
1779  exit(1);
1780  }
1781  }
1782  */
1783 
1786  library_models);
1787  } else
1788  ;
1789 
1791  compress_netlist(); /* remove unused inputs */
1792 
1793  /* NB: It's important to mark clocks and such *after* compressing the *
1794  * netlist because the vpack_net numbers, etc. may be changed by removing *
1795  * unused inputs . */
1796 
1797  show_blif_stats(user_models, library_models);
1800  free(model);
1803  model = NULL;
1804 }
1805 
1806 /* Output blif statistics */
1807 static void show_blif_stats(t_model *user_models, t_model *library_models) {
1808  struct s_model_stats *model_stats;
1809  struct s_model_stats *lut_model;
1810  int num_model_stats;
1811  t_model *cur;
1812  int MAX_LUT_INPUTS;
1813  int i, j, iblk, ipin, num_pins;
1814  int *num_lut_of_size;
1815 
1816  /* Store data structure for all models in FPGA */
1817  num_model_stats = 0;
1818 
1819  cur = library_models;
1820  while (cur) {
1821  num_model_stats++;
1822  cur = cur->next;
1823  }
1824 
1825  cur = user_models;
1826  while (cur) {
1827  num_model_stats++;
1828  cur = cur->next;
1829  }
1830 
1831  model_stats = (struct s_model_stats*) my_calloc(num_model_stats,
1832  sizeof(struct s_model_stats));
1833 
1834  num_model_stats = 0;
1835 
1836  lut_model = NULL;
1837  cur = library_models;
1838  while (cur) {
1839  model_stats[num_model_stats].model = cur;
1840  if (strcmp(cur->name, "names") == 0) {
1841  lut_model = &model_stats[num_model_stats];
1842  }
1843  num_model_stats++;
1844  cur = cur->next;
1845  }
1846 
1847  cur = user_models;
1848  while (cur) {
1849  model_stats[num_model_stats].model = cur;
1850  num_model_stats++;
1851  cur = cur->next;
1852  }
1853 
1854  /* Gather statistics from circuit */
1855  MAX_LUT_INPUTS = 0;
1856  for (iblk = 0; iblk < num_logical_blocks; iblk++) {
1857  if (strcmp(logical_block[iblk].model->name, "names") == 0) {
1858  MAX_LUT_INPUTS = logical_block[iblk].model->inputs->size;
1859  break;
1860  }
1861  }
1862  num_lut_of_size = (int*) my_calloc(MAX_LUT_INPUTS + 1, sizeof(int));
1863 
1864  for (i = 0; i < num_logical_blocks; i++) {
1865  for (j = 0; j < num_model_stats; j++) {
1866  if (logical_block[i].model == model_stats[j].model) {
1867  break;
1868  }
1869  }
1870  assert(j < num_model_stats);
1871  model_stats[j].count++;
1872  if (&model_stats[j] == lut_model) {
1873  num_pins = 0;
1874  for (ipin = 0; ipin < logical_block[i].model->inputs->size;
1875  ipin++) {
1876  if (logical_block[i].input_nets[0][ipin] != OPEN) {
1877  num_pins++;
1878  }
1879  }
1880  num_lut_of_size[num_pins]++;
1881  }
1882  }
1883 
1884  /* Print blif circuit stats */
1885 
1886  vpr_printf(TIO_MESSAGE_INFO, "BLIF circuit stats:\n");
1887 
1888  for (i = 0; i <= MAX_LUT_INPUTS; i++) {
1889  vpr_printf(TIO_MESSAGE_INFO, "\t%d LUTs of size %d\n",
1890  num_lut_of_size[i], i);
1891  }
1892  for (i = 0; i < num_model_stats; i++) {
1893  vpr_printf(TIO_MESSAGE_INFO, "\t%d of type %s\n", model_stats[i].count,
1894  model_stats[i].model->name);
1895  }
1896 
1897  free(model_stats);
1898  free(num_lut_of_size);
1899 }
1900 
1901 static void read_activity(char * activity_file) {
1902  int net_idx;
1903  bool fail;
1904  char buf[BUFSIZE];
1905  char * ptr;
1906  char * word1;
1907  char * word2;
1908  char * word3;
1909 
1910  FILE * act_file_hdl;
1911 
1912  if (num_logical_nets == 0) {
1913  printf("Error reading activity file. Must read netlist first\n");
1914  exit(-1);
1915  }
1916 
1917  for (net_idx = 0; net_idx < num_logical_nets; net_idx++) {
1918  if (!vpack_net[net_idx].net_power) {
1919  vpack_net[net_idx].net_power = new t_net_power;
1920  }
1921  vpack_net[net_idx].net_power->probability = -1.0;
1922  vpack_net[net_idx].net_power->density = -1.0;
1923  }
1924 
1925  act_file_hdl = my_fopen(activity_file, "r", FALSE);
1926  if (act_file_hdl == NULL ) {
1927  printf("Error: could not open activity file: %s\n", activity_file);
1928  exit(-1);
1929  }
1930 
1931  fail = FALSE;
1932  ptr = my_fgets(buf, BUFSIZE, act_file_hdl);
1933  while (ptr != NULL ) {
1934  word1 = strtok(buf, TOKENS);
1935  word2 = strtok(NULL, TOKENS);
1936  word3 = strtok(NULL, TOKENS);
1937  //printf("word1:%s|word2:%s|word3:%s\n", word1, word2, word3);
1938  fail |= add_activity_to_net(word1, atof(word2), atof(word3));
1939 
1940  ptr = my_fgets(buf, BUFSIZE, act_file_hdl);
1941  }
1942  fclose(act_file_hdl);
1943 
1944  /* Make sure all nets have an activity value */
1945  for (net_idx = 0; net_idx < num_logical_nets; net_idx++) {
1946  if (!vpack_net[net_idx].net_power
1947  || vpack_net[net_idx].net_power->probability < 0.0
1948  || vpack_net[net_idx].net_power->density < 0.0) {
1949  printf("Error: Activity file does not contain signal %s\n",
1950  vpack_net[net_idx].name);
1951  fail = TRUE;
1952  }
1953  }
1954 
1955  if (fail) {
1956  exit(-1);
1957  }
1958 }
1959 
1960 bool add_activity_to_net(char * net_name, float probability, float density) {
1961  int hash_idx, net_idx;
1962  struct s_hash * h_ptr;
1963 
1964  hash_idx = hash_value(net_name);
1965  h_ptr = blif_hash[hash_idx];
1966 
1967  while (h_ptr != NULL ) {
1968  if (strcmp(h_ptr->name, net_name) == 0) {
1969  net_idx = h_ptr->index;
1970  vpack_net[net_idx].net_power->probability = probability;
1971  vpack_net[net_idx].net_power->density = density;
1972  return false;
1973  }
1974  h_ptr = h_ptr->next;
1975  }
1976 
1977  printf(
1978  "Error: net %s found in activity file, but it does not exist in the .blif file.\n",
1979  net_name);
1980  return true;
1981 }
int * node_block_pin
Definition: vpr_types.h:509
static int * logical_block_input_count
Definition: read_blif.c:38
static int * temp_num_pins
Definition: read_blif.c:37
struct s_net_power t_net_power
Definition: vpr_types.h:43
int num_p_inputs
Definition: globals.c:18
FILE * my_fopen(const char *fname, const char *flag, int prompt)
Definition: util.c:54
static void init_parse(int doall)
Definition: read_blif.c:147
int count
Definition: hash.h:6
static int ilines
Definition: read_blif.c:43
static void get_blif_tok(char *buffer, int doall, boolean *done, boolean *add_truth_table, INP t_model *inpad_model, INP t_model *outpad_model, INP t_model *logic_model, INP t_model *latch_model, INP t_model *user_models)
Definition: read_blif.c:227
void ** alloc_matrix(int nrmin, int nrmax, int ncmin, int ncmax, size_t elsize)
Definition: util.c:551
int ** input_nets
Definition: vpr_types.h:211
static void read_blif(char *blif_file, boolean sweep_hanging_nets_and_inputs, t_model *user_models, t_model *library_models, boolean read_activity_file, char *activity_file)
Definition: read_blif.c:77
boolean is_const_gen
Definition: vpr_types.h:511
struct s_linked_vptr * circuit_p_io_removed
Definition: globals.c:90
static void read_activity(char *activity_file)
Definition: read_blif.c:1901
int index
Definition: hash.h:5
static void compress_netlist(void)
Definition: read_blif.c:1587
void free_matrix(void *vptr, int nrmin, int nrmax, int ncmin, size_t elsize)
Definition: util.c:573
#define TOKENS
Definition: vpr_types.h:66
boolean
Definition: util.h:11
static int add_vpack_net(char *ptr, int type, int bnum, int bport, int bpin, boolean is_global, int doall)
Definition: read_blif.c:879
#define MODEL_LOGIC
Definition: vpr_types.h:274
void dum_parse(char *buf)
Definition: read_blif.c:358
static void show_blif_stats(t_model *user_models, t_model *library_models)
Definition: read_blif.c:1807
#define MODEL_INPUT
Definition: vpr_types.h:276
int hash_value(char *name)
Definition: hash.c:140
static boolean add_lut(int doall, t_model *logic_model)
Definition: read_blif.c:366
static int num_blif_models
Definition: read_blif.c:39
static void free_parse(void)
Definition: read_blif.c:1482
void * my_calloc(size_t nelem, size_t size)
Definition: util.c:132
struct s_model_ports * next
Definition: logic_types.h:28
char * name
Definition: hash.h:4
int * node_block
Definition: vpr_types.h:507
struct s_linked_vptr * truth_table
Definition: vpr_types.h:227
int num_logical_nets
Definition: globals.c:17
char * name
Definition: vpr_types.h:505
static int * logical_block_output_count
Definition: read_blif.c:38
boolean is_clock
Definition: logic_types.h:26
#define BUFSIZE
Definition: graphics.c:184
char * blif_circuit_name
Definition: globals.c:21
boolean getEchoEnabled(void)
Definition: ReadOptions.c:67
#define HASHSIZE
Definition: hash.h:1
static int num_luts
Definition: read_blif.c:40
Definition: util.h:12
static void load_default_models(INP t_model *library_models, OUTP t_model **inpad_model, OUTP t_model **outpad_model, OUTP t_model **logic_model, OUTP t_model **latch_model)
Definition: read_blif.c:1120
static int model_lines
Definition: read_blif.c:43
float probability
Definition: vpr_types.h:485
static void * my_malloc(int ibytes)
Definition: graphics.c:499
boolean * is_global
static void check_net(boolean sweep_hanging_nets_and_inputs)
Definition: read_blif.c:1153
static int * num_driver
Definition: read_blif.c:37
struct s_model * next
Definition: logic_types.h:40
static void add_latch(int doall, INP t_model *latch_model)
Definition: read_blif.c:455
t_net_power * net_power
Definition: vpr_types.h:512
#define MODEL_LATCH
Definition: vpr_types.h:275
#define INP
Definition: util.h:19
int num_p_outputs
Definition: globals.c:18
static FILE * blif
Definition: read_blif.c:46
void read_and_process_blif(char *blif_file, boolean sweep_hanging_nets_and_inputs, t_model *user_models, t_model *library_models, boolean read_activity_file, char *activity_file)
Definition: read_blif.c:1765
t_model_ports * inputs
Definition: logic_types.h:35
static void add_subckt(int doall, INP t_model *user_models)
t_model_ports * outputs
Definition: logic_types.h:36
boolean isEchoFileEnabled(enum e_echo_files echo_option)
Definition: ReadOptions.c:115
static bool add_activity_to_net(char *net_name, float probability, float density)
Definition: read_blif.c:1960
char * my_strtok(char *ptr, const char *tokens, FILE *fp, char *buf)
Definition: util.c:472
struct s_linked_vptr * next
Definition: util.h:36
void echo_input(char *blif_file, char *echo_file, t_model *library_models)
Definition: read_blif.c:980
#define MODEL_OUTPUT
Definition: vpr_types.h:277
static int endlines
Definition: read_blif.c:43
struct s_hash * next
Definition: hash.h:7
static char * model
Definition: read_blif.c:45
boolean is_global
Definition: vpr_types.h:510
void * data_vptr
Definition: util.h:35
enum logical_block_types type
Definition: vpr_types.h:208
static void check_and_count_models(int doall, const char *model_name, t_model *user_models)
Definition: read_blif.c:846
#define MAX_ATOM_PARSE
Definition: read_blif.c:20
static int olines
Definition: read_blif.c:43
char * name
Definition: logic_types.h:34
static int num_subckts
Definition: read_blif.c:40
static void * my_realloc(void *memblk, int ibytes)
Definition: graphics.c:512
t_model * model
Definition: read_blif.c:16
static int num_latches
Definition: read_blif.c:40
int num_logical_blocks
Definition: globals.c:17
char * my_fgets(char *buf, int max_size, FILE *fp)
Definition: util.c:412
Definition: slre.c:50
int file_line_number
Definition: util.c:15
float density
Definition: vpr_types.h:490
struct s_net * vpack_net
Definition: globals.c:19
char * getEchoFileName(enum e_echo_files echo_option)
Definition: ReadOptions.c:122
static void io_line(int in_or_out, int doall, t_model *io_model)
Definition: read_blif.c:778
#define OUTP
Definition: util.h:20
t_model * model
Definition: vpr_types.h:209
static struct s_hash ** blif_hash
Definition: read_blif.c:44
int my_atoi(const char *str)
Definition: util.c:116
static void absorb_buffer_luts(void)
Definition: read_blif.c:1503
char * my_strdup(const char *str)
Definition: util.c:101
int ** output_nets
Definition: vpr_types.h:212
messagelogger vpr_printf
Definition: util.c:17
#define BLIF_TOKENS
int num_sinks
Definition: vpr_types.h:506
int * node_block_port
Definition: vpr_types.h:508
Definition: hash.h:3
struct s_logical_block * logical_block
Definition: globals.c:20
Definition: util.h:12
void get_hash_stats(struct s_hash **hash_table, char *hash_table_name)
Definition: hash.c:160