VPR-7.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
verilog_writer.c
Go to the documentation of this file.
1 
2 #include "verilog_writer.h"
3 
4 /***********************************************************************************************************
5 
6 Author: Miad Nasr; August 30, 2012
7 
8 The code in this file generates the Verilog and SDF files for the post-synthesized circuit. The Verilog file
9 can be used to perform functional simulation and the SDF file enables timing simulation of the post-synthesized circuit.
10 
11 The Verilog file contains instantiated modules of the primitives in the circuit. Currently VPR can generate
12 Verilog files for circuits that only contain LUTs , Flip Flops , IOs , Multipliers , and BRAMs. The Verilog
13 description of these primitives are in the primitives.v file. To simulate the post-synthesized circuit, one
14 must include the generated Verilog file and also the primitives.v Verilog file, in the simulation directory.
15 
16 If one wants to generate the post-synthesized Verilog file of a circuit that contains a primitive other than
17 those mentioned above, he/she should contact the VTR team to have the source code updated. Furthermore to
18 perform simulation on that circuit the Verilog description of that new primitive must be appended to the
19 primitives.v file as a separate module.
20 
21 The VTR team can be contacted through the VTR website:
22 http://code.google.com/p/vtr-verilog-to-routing/
23 
24 ***********************************************************************************************************/
25 
26 /*The verilog_writer function is the main function that will generate and write to the verilog and SDF files
27 All the functions declared bellow are called directly or indirectly by verilog_writer()
28 
29 Basic Description of how verilog_writer() writes the Verilog and SDF files:
30 
31 First - The name of the clock signal in the circuit is stored in clock_name. the find_clock_name() function
32  searches through all the inputs of the design and returns the name of the clock in the design. The verilog
33  writer currently works with only single clocked circuits
34 
35 Second - instantiate_top_level() module is called. This function will will traverse through all the inputs and
36  outputs in the circuit and instantiate the list of inputs and inputs in the top level module
37 
38 Third - instantiate_SDF_header() is a short function that will just write the top level declarations in the SDF file.
39 
40 Fourth - All the wires in the design are instantiated. This is done in the way demonstrated bellow:
41 
42  Traverse through all primitives
43 
44  -For each primitive traverse through all input ports
45  -For each input port traverse through all input pins and then instantiate the wire
46 
47  -For each primitive traverse through all output ports
48  -For each output port traverse through all output pins and then instantiate the wire
49 
50 Fifth - Instantiate_input_interconnect() will instantiate the interconnect modules that connect the inputs to the design to the rest of the primitives.
51 
52 Sixth - Instantiate_primitive_modules() will instantiate all the primitives in the design. This is how this function works in summary:
53 
54  Traverse through all primitives
55 
56  -For each primitive instantiate the primitive module and instantiate inputs/outputs by traversing
57  -For each primitive instantiate the interconnect modules that conect the outputs of that primitive
58  to other primitives
59  -Instantiate the SDF block corersponding to this primitive
60 
61 
62 */
63 
64 void verilog_writer(void)
65 {
66  FILE *verilog;
67  FILE *SDF;
68  char * verilog_file_name = (char *)malloc((strlen(blif_circuit_name) + strlen("_post_synthesis.v") + 1) *sizeof(char));/*creating the Verilog file name*/
69  char * sdf_file_name = (char *)malloc((strlen(blif_circuit_name) + strlen("_post_synthesis.sdf") + 1) *sizeof(char));/*creating the SDF file name*/
70  char *clock_name;/*Will need to store the clock name of the design if any exist*/
71  assert(verilog_file_name);
72  assert(sdf_file_name);
73  printf("\nWriting the post-synthesized circuit Verilog and SDF.....\n...");
74 
75  sprintf(verilog_file_name, "%s%s", blif_circuit_name, "_post_synthesis.v");
76  sprintf(sdf_file_name, "%s%s", blif_circuit_name, "_post_synthesis.sdf");
77 
78  /*Openning the post synthesized netlist files*/
79  verilog = fopen(verilog_file_name , "w");
80  SDF = fopen(sdf_file_name , "w");
81 
82  clock_name = find_clock_name();
85  instantiate_wires(verilog);
86  instantiate_input_interconnect(verilog , SDF , clock_name);
87  instantiate_primitive_modules(verilog,clock_name,SDF);
88 
89  fprintf(verilog , "\nendmodule\n");
90  fprintf(SDF , ")\n");
91  fclose(verilog);
92  fclose(SDF);
93  printf("Done\n\n");
94 }
95 
96 /*The function instantiate_top_level_module instantiates the top level verilog module of the post-synthesized circuit and the list of inputs and outputs to that module*/
97 void instantiate_top_level_module(FILE *verilog)
98 {
99  int i,place_comma;
100  pb_list *temp=NULL;
101  pb_list *current;
102  char *fixed_name = NULL;
103 
104 
105  fprintf(verilog , "module %s(\n" , blif_circuit_name);
106  place_comma=0;
107  for(i=0 ; i<num_blocks ; i++)/*go through all the blocks in the design*/
108  {
109  if(!strcmp(block[i].pb->pb_graph_node->pb_type->name,"io"))/*if this block is an i/o block*/
110  {
111  temp = traverse_clb(block[i].pb , temp);/*find all the primitives in this block*/
112  for(current=temp ; current!=NULL ; current=current->next)/*traverse through all the primitives in this block*/
113  {
114  if(place_comma){ /*need this for correct placement of commas and verilog syntax correctness*/
115  fprintf(verilog ,"\t,");
116  }
117  else{
118  fprintf(verilog ,"\t");
119  place_comma=1;
120  }
121  fixed_name = fix_name(current->pb->name);/*need to do this, because some names contain characters that cause syntax errors in verilog (e.g. '~' , '^',)*/
122  if(!strcmp(logical_block[current->pb->logical_block].model->name,"input")){/*if this primitive is an input pin, declare as input*/
123 
124  fprintf(verilog , "input %s\n",fixed_name);/*declaring the inputs*/
125 
126 
127  }
128  else if(!strcmp(logical_block[current->pb->logical_block].model->name,"output")){
129 
130  fprintf(verilog , "output %s\n",fixed_name);/*declaring the outputs*/
131  }
132  free(fixed_name);
133  }
134  }
135  temp = free_linked_list(temp);
136  }
137  fprintf(verilog , ");\n\n");
138 
139 }
140 
141 void instantiate_SDF_header(FILE *SDF)
142 {
143  fprintf(SDF , "(DELAYFILE\n\t(SDFVERSION \"2.1\")\n\t(DIVIDER /)\n\t(TIMESCALE 1 ps)\n\n ");
144 }
145 
146 /*The instantiate_wires function instantiates all the wire in the post-synthesized design*/
147 void instantiate_wires(FILE *verilog)
148 {
149  int i,j,k;
150  pb_list *primitive_list=NULL;
151  pb_list *current;
152  char *fixed_name = NULL;
153 
154  for(i=0; i<num_blocks ; i++)/*go through all the blocks in the design*/
155  {
156  primitive_list = traverse_clb(block[i].pb , primitive_list);/*find all the primitives in this block*/
157 
158  for(current=primitive_list ; current!=NULL ; current=current->next)/*traverse through all the primitives in this block*/
159  {
160  fixed_name = fix_name(current->pb->name);/*need to do this, because some names contain characters that cause syntax errors in verilog (e.g. '~' , '^',)*/
161  for(j=0 ; j<current->pb->pb_graph_node->num_output_ports ; j++)/*go through all the found primitives and instantiate their output wires*/
162  {
163  for(k=0 ; k<current->pb->pb_graph_node->num_output_pins[j] ; k++)
164  {
165 
166 
167  fprintf(verilog , "wire %s_output_%d_%d;\n" , fixed_name , j , k);
168 
169  if(!strcmp(logical_block[current->pb->logical_block].model->name,"input"))/*if that pin is an inpad pin then have to connect the
170  inputs to the module to this wire*/
171  {
172  fprintf(verilog , "assign %s_output_%d_%d = %s;\n\n",fixed_name , j , k , fixed_name);
173  }
174 
175 
176  }
177  }
178  for(j=0 ; j<current->pb->pb_graph_node->num_input_ports ; j++)/*instantiating the input wire modules for each primitive*/
179  {
180  for(k=0 ; k<current->pb->pb_graph_node->num_input_pins[j] ; k++)
181  {
182  fprintf(verilog , "wire %s_input_%d_%d;\n" , fixed_name , j , k);
183  if(!strcmp(logical_block[current->pb->logical_block].model->name,"output"))/*if that pin is an outpad then have to connect the input to the outputs
184  of the top level module*/
185  {
186  fprintf(verilog , "assign %s = %s_input_%d_%d;\n\n",fixed_name , fixed_name , j , k);
187  }
188  }
189  }
190  free(fixed_name);
191  }
192  primitive_list = free_linked_list(primitive_list);
193  }
194 }
195 
196 /*
197  The function instantiate_input_interconnect will instantiate the interconnect segments from input pins to the rest of the design.
198  This function is necessary because the inputs to the design are not instantiated as a module in verilog.
199 */
200 void instantiate_input_interconnect(FILE *verilog , FILE *SDF , char *clock_name)
201 {
202  int blocks;
203  pb_list *current;
204  pb_list *primitive_list = NULL;
205  conn_list *downhill = NULL;
206 
207  for(blocks=0 ; blocks<num_blocks ; blocks++)
208  {
209  if(strcmp(block[blocks].pb->pb_graph_node->pb_type->name,"io"))/*if this is an io block*/
210  {
211  continue;
212  }
213  primitive_list = traverse_clb(block[blocks].pb , primitive_list);/*find all the primitives in that block*/
214  for(current=primitive_list ; current!=NULL ; current=current->next)/*traversing through all the found primitives*/
215  {
216  if(strcmp(logical_block[current->pb->logical_block].model->name,"input"))/*if that primitive is an inpad*/
217  {
218  continue;
219  }
220  if(clock_name && !strcmp(current->pb->name,clock_name))/*If this is the clock signal, then don't instantiate an interconnect for it*/
221  {
222  continue;
223  }
224  downhill = find_connected_primitives_downhill(blocks , current->pb , downhill );/*find all the other primitives that it connects to*/
225 
226  /*traverse_linked_list_conn(downhill);*/
227  interconnect_printing(verilog , downhill);/*Print the interconnects modules that connect the inputs to the rest of the design*/
228  SDF_interconnect_delay_printing(SDF , downhill);/*Print the Delays of the interconnect module to the SDF file*/
229  downhill = free_linked_list_conn(downhill);
230  break;
231  }
232  primitive_list = free_linked_list(primitive_list);
233  }
234 }
235 
236 /*This function instantiates the primitive verilog modules e.g. LUTs ,Flip Flops, etc.*/
237 void instantiate_primitive_modules(FILE *fp, char *clock_name , FILE *SDF)
238 {
239  int i,j,k,h;
240  pb_list *primitives = NULL;
241  pb_list *current;
242 
243  int place_comma=0;
244  char *truth_table = NULL;
245  int inputs_to_lut;
246  char *fixed_name = NULL;
247  int power;
248  for(i=0 ; i<num_blocks ; i++)
249  {
250  primitives = traverse_clb(block[i].pb , primitives);/*find all the primitives inside block i*/
251  for(current=primitives ; current!=NULL ; current=current->next)/*traverse through all the found primitives*/
252  {
253 
254  fixed_name = fix_name(current->pb->name);
255 
256  if(!strcmp(logical_block[current->pb->logical_block].model->name,"names"))/*if this primitive is a lut*/
257  {
258  inputs_to_lut = find_number_of_inputs(current->pb);
259  assert((inputs_to_lut >= 3) && (inputs_to_lut <= 7));/*currently the primitives.v file only contains the verilog description for 4LUTs and 6LUTs*/
260  truth_table=load_truth_table(inputs_to_lut,current->pb);/*load_truth_table will find the truth table corresponding to this lut, and store it in "truth_table"*/
261 
262  /*instantiating the 6 input lut module and passing the truth table as parameter*/
263 
264  power = 1 << inputs_to_lut;
265  fprintf(fp , "\nLUT_%d #(%d'b%s) lut_%s(", inputs_to_lut , power , truth_table , fixed_name);
266 
267  free(truth_table);
268 
269  j=0;
270  for(k=0 ; k<current->pb->pb_graph_node->num_input_ports ; k++)/*traverse through all the input pins of the lut*/
271  {
272  for(h=0 ; h<current->pb->pb_graph_node->num_input_pins[k] ; h++)
273  {
274  if(current->pb->rr_graph[current->pb->pb_graph_node->input_pins[k][h].pin_count_in_cluster].net_num != OPEN)/*check if that pin is used*/
275  {
276  if(place_comma)/*need this flag check to properly place the commas*/
277  {
278  fprintf(fp , " , %s_input_%d_%d" , fixed_name , k , j); // j was h
279  }
280  else
281  {
282  fprintf(fp , "%s_input_%d_%d" , fixed_name , k , j); // j was h
283  place_comma=1;
284  }
285  j++;
286  }
287  }
288  }
289  while(j<inputs_to_lut)/*if (after writing all the inputs to the lut module) there are still some
290  inputs unused (i.e. not all the inputs to the lut are used) place a logic zero instead*/
291  {
292  if(place_comma && j)
293  {
294  j++;
295  fprintf(fp , " , 1'b0");
296  }
297  else
298  {
299  j++;
300  fprintf(fp , "1'b0");
301  place_comma=1;
302  }
303  }
304 
305  place_comma=0;
306  fprintf(fp , " , %s_output_0_0 );\n\n",fixed_name);/*finaly write the output of the module*/
307 
308  instantiate_interconnect(fp,i,current->pb,SDF);/*this function will instantiate the routing
309  interconnect from the output of this lut to
310  the inputs of other luts that it connects to*/
311  sdf_LUT_delay_printing(SDF , current->pb);/*This function will instantiate the internal delays of the lut to the SDF file*/
312  }
313  else if(!strcmp(logical_block[current->pb->logical_block].model->name,"latch"))/*If this primitive is a Flip Flop*/
314  {
315  char *fixed_clock_name;
316  fixed_clock_name = fix_name(clock_name);
317  fprintf(fp , "\nD_Flip_Flop DFF_%s(%s_output_0_0 , %s_input_0_0 , 1'b1 , 1'b1 , %s_output_0_0 );\n",fixed_name,fixed_clock_name,fixed_name,fixed_name);
318  instantiate_interconnect(fp , i , current->pb , SDF);
319  sdf_DFF_delay_printing(SDF , current->pb);
320  free(fixed_clock_name);
321  }
322  else if(!strcmp(logical_block[current->pb->logical_block].model->name,"multiply") ||
323  !strcmp(logical_block[current->pb->logical_block].model->name,"adder")) /*If this primitive is a multiplier or an adder */
324  {
325  /** multipliers and adders are handled quite similarly **/
326 
327  int mult = !strcmp(logical_block[current->pb->logical_block].model->name,"multiply");
328  int num_inputs = logical_block[current->pb->logical_block].pb->pb_graph_node->num_input_pins[0];/*what is the data width*/
329  int i_port , i_pin ;
330  place_comma = 0;
331  if (mult)
332  fprintf(fp , "\nmult #(%d)%s(" , num_inputs , fixed_name);
333  else
334  fprintf(fp , "\nripple_adder #(%d)%s(" , num_inputs , fixed_name);
335 
336  /*Traversing through all the input ports of this multiplier*/
337  for(i_port=0 ; i_port<logical_block[current->pb->logical_block].pb->pb_graph_node->num_input_ports ; i_port++)
338  {
339  if(i_port == 0)/*This if-else statement will make sure that the signals are concatinated in verilog*/
340  {
341  fprintf(fp , "{");
342  }
343  else{
344  fprintf(fp , ",{");
345  }
346  place_comma = 0;
347  /*Traversing through all the input pins of this input port*/
348  for(i_pin=logical_block[current->pb->logical_block].pb->pb_graph_node->num_input_pins[i_port]-1 ; i_pin>=0 ; i_pin--)
349  {
350  /*If this input pin is used*/
351  if(current->pb->rr_graph[current->pb->pb_graph_node->input_pins[i_port][i_pin].pin_count_in_cluster].net_num != OPEN)
352  {
353  if(place_comma)/*need this flag check to properly place the commas*/
354  {
355  fprintf(fp , " , %s_input_%d_%d" , fixed_name , i_port , i_pin);
356  }
357  else
358  {
359  fprintf(fp , "%s_input_%d_%d" , fixed_name , i_port , i_pin);
360  place_comma=1;
361  }
362 
363  }
364  else{/*If this pin was not used, then instantiate logic zero*/
365  if(place_comma)
366  {
367  fprintf(fp , ", 1'b0");
368  }
369  else{
370  fprintf(fp , " 1'b0");
371  place_comma = 1;
372  }
373  }
374  }
375  fprintf(fp , "}");/*End concatination*/
376  }
377  /*Traversing through all the output ports of this multiplier*/
378  for(i_port=0 ; i_port<logical_block[current->pb->logical_block].pb->pb_graph_node->num_output_ports ; i_port++)
379  {
380  fprintf(fp , ",{");/*Since there is only a single output port for multipliers we only need to concatinate once*/
381  place_comma = 0;
382  /*Traversing through all the output pins of this output port*/
383  for(i_pin=logical_block[current->pb->logical_block].pb->pb_graph_node->num_output_pins[i_port]-1 ; i_pin>=0 ; i_pin--)
384  {
385  if(place_comma)
386  {
387  fprintf(fp , ", %s_output_%d_%d" , fixed_name , i_port , i_pin);
388  }
389  else{
390  fprintf(fp , " %s_output_%d_%d" , fixed_name , i_port , i_pin);
391  place_comma = 1;
392  }
393  }
394  fprintf(fp , "}");/*End concatination*/
395  }
396  fprintf(fp , ");\n\n");
397  instantiate_interconnect(fp , i , current->pb , SDF);
398  if (mult)
399  SDF_Mult_delay_printing(SDF, current->pb);
400  else
401  SDF_Adder_delay_printing(SDF, current->pb);
402  }
403  else if(!strcmp(logical_block[current->pb->logical_block].model->name,"single_port_ram")){/*If this primitive is a single port RAM block*/
404 
405  char *fixed_clock_name;
406  int i_port,i_pin;
407  int data_width,addr_width;
408 
409  data_width = logical_block[current->pb->logical_block].pb->pb_graph_node->num_input_pins[1];/*the data_width (word width) is the number of inputs in the data port*/
410  addr_width = logical_block[current->pb->logical_block].pb->pb_graph_node->num_input_pins[0];/*the addr_width (address width) is the number of inputs in the addr port*/
411 
412  fprintf(fp , "\nsingle_port_ram #(%d,%d)%s(" , addr_width , data_width , fixed_name);/*Passing the address width and data width as a verilog parameter*/
413  /*Traversign through all the input ports of this single_port_ram*/
414  for(i_port=0 ; i_port<logical_block[current->pb->logical_block].pb->pb_graph_node->num_input_ports ; i_port++)
415  {
416  if(i_port == 0)/*This if-else statement will make sure that the signals are concatinated in verilog*/
417  {
418  fprintf(fp , "{");
419  }
420  else{
421  fprintf(fp , ",{");
422  }
423  place_comma = 0;
424  /*Traversing through all the input pins of this input port*/
425  for(i_pin=logical_block[current->pb->logical_block].pb->pb_graph_node->num_input_pins[i_port]-1 ; i_pin>=0 ; i_pin--)
426  {
427  /*If this input pin is used*/
428  if(current->pb->rr_graph[current->pb->pb_graph_node->input_pins[i_port][i_pin].pin_count_in_cluster].net_num != OPEN)
429  {
430  if(place_comma)/*need this flag check to properly place the commas*/
431  {
432  fprintf(fp , " , %s_input_%d_%d" , fixed_name , i_port , i_pin);
433  }
434  else
435  {
436  fprintf(fp , "%s_input_%d_%d" , fixed_name , i_port , i_pin);
437  place_comma=1;
438  }
439  }
440  else{/*If this input pin is not used then instantiate a logic zero*/
441  if(place_comma)
442  {
443  fprintf(fp , ", 1'b0");
444  }
445  else{
446  fprintf(fp , " 1'b0");
447  place_comma = 1;
448  }
449  }
450  }
451  fprintf(fp , "}");/*End concatination*/
452  }
453  /*Traversign through all the output ports of this single_port_ram*/
454  for(i_port=0 ; i_port<logical_block[current->pb->logical_block].pb->pb_graph_node->num_output_ports ; i_port++)
455  {
456  fprintf(fp , ",{");/*Since there is only a single output port for single_port_rams we only need to concatinate once*/
457  place_comma = 0;
458  /*Traverse through all the output pins of this output port*/
459  for(i_pin=logical_block[current->pb->logical_block].pb->pb_graph_node->num_output_pins[i_port]-1 ; i_pin>=0 ; i_pin--)
460  {
461  if(place_comma)
462  {
463  fprintf(fp , ", %s_output_%d_%d" , fixed_name , i_port , i_pin);
464  }
465  else{
466  fprintf(fp , " %s_output_%d_%d" , fixed_name , i_port , i_pin);
467  place_comma = 1;
468  }
469  }
470  fprintf(fp , "}");/*End concatination*/
471  }
472  fixed_clock_name = fix_name(clock_name);/*Must also instantiate the clock signal to the RAM block*/
473  fprintf(fp , ", %s_output_0_0" , fixed_clock_name);
474  fprintf(fp , ");\n\n");
475  free(fixed_clock_name);
476  instantiate_interconnect(fp , i , current->pb , SDF);
477  SDF_ram_single_port_delay_printing(SDF , current->pb);
478  }
479  else if(!strcmp(logical_block[current->pb->logical_block].model->name,"dual_port_ram")){/*If this primitive is a dual_port_ram*/
480 
481  int data1_width,data2_width,addr1_width,addr2_width,i_port,i_pin;
482  char *fixed_clock_name;
483 
484  /*The Input ports of dual port rams are in this order:
485  0-addr1
486  1-addr2
487  2-data1
488  3-data2
489  4-we1
490  5-we2
491 
492  The verilog primitives module only accepts instatiation in this order else the simulation will give error or give incorrect simulation results*/
493 
494  data1_width = current->pb->pb_graph_node->num_input_pins[2];/*the data_width (word width) for the first port, is the number of inputs in the first data port*/
495  addr1_width = current->pb->pb_graph_node->num_input_pins[0];/*the addr_width (address width) for the first port, is the number of inputs in the first addr port*/
496  data2_width = current->pb->pb_graph_node->num_input_pins[3];/*the data_width (word width) for the second port, is the number of inputs in the second data port*/
497  addr2_width = current->pb->pb_graph_node->num_input_pins[1];/*the addr_width (address width) for the second port is the number of inputs in the second addr port*/
498 
499  fprintf(fp , "\ndual_port_ram #(%d,%d,%d,%d)%s(" , addr1_width , data1_width , addr2_width , data2_width , fixed_name);/*passing the addr_wdith and data_wdith for both ports as verilog parameter*/
500 
501  for(i_port=0 ; i_port<logical_block[current->pb->logical_block].pb->pb_graph_node->num_input_ports ; i_port++)
502  {
503  if(i_port == 0)
504  {
505  fprintf(fp , "{");
506  }
507  else{
508  fprintf(fp , ",{");
509  }
510  place_comma = 0;
511  /*Traversign through all the input pins of this input port*/
512  for(i_pin=logical_block[current->pb->logical_block].pb->pb_graph_node->num_input_pins[i_port]-1 ; i_pin>=0 ; i_pin--)
513  {
514  /*If this pin is used*/
515  if(current->pb->rr_graph[current->pb->pb_graph_node->input_pins[i_port][i_pin].pin_count_in_cluster].net_num != OPEN)
516  {
517  if(place_comma)/*need this flag check to properly place the commas*/
518  {
519  fprintf(fp , " , %s_input_%d_%d" , fixed_name , i_port , i_pin);
520  }
521  else
522  {
523  fprintf(fp , "%s_input_%d_%d" , fixed_name , i_port , i_pin);
524  place_comma=1;
525  }
526  }
527  else{/*If this pin is not used, then instantiate logic zero instead*/
528  if(place_comma)
529  {
530  fprintf(fp , ", 1'b0");
531  }
532  else{
533  fprintf(fp , " 1'b0");
534  place_comma = 1;
535  }
536  }
537  }
538  fprintf(fp , "}");/*End concatination*/
539  }
540  /*Traversign through all the output ports of this dual_port_ram*/
541  for(i_port=0 ; i_port<logical_block[current->pb->logical_block].pb->pb_graph_node->num_output_ports ; i_port++)
542  {
543  fprintf(fp , ",{");
544  place_comma = 0;
545  /*Traverse through all the output pins of this output port*/
546  for(i_pin=logical_block[current->pb->logical_block].pb->pb_graph_node->num_output_pins[i_port]-1 ; i_pin>=0 ; i_pin--)
547  {
548  if(place_comma)
549  {
550  fprintf(fp , ", %s_output_%d_%d" , fixed_name , i_port , i_pin);
551  }
552  else{
553  fprintf(fp , " %s_output_%d_%d" , fixed_name , i_port , i_pin);
554  place_comma = 1;
555  }
556  }
557  fprintf(fp , "}");
558  }
559  fixed_clock_name = fix_name(clock_name);/*Must also instantiate the clock */
560  fprintf(fp , ", %s_output_0_0" , fixed_clock_name);
561  fprintf(fp , ");\n\n");
562  free(fixed_clock_name);
563  instantiate_interconnect(fp , i , current->pb , SDF);
564  SDF_ram_dual_port_delay_printing(SDF , current->pb);
565 
566  }
567  else if(strcmp(logical_block[current->pb->logical_block].model->name,"input") && strcmp(logical_block[current->pb->logical_block].model->name,"output"))
568  /*If this primitive is anything else, but an input or an output*/
569  {
570  printf("Failed to generate post-synthesized verilog and sdf files. Primitive %s is unknown.\n\nAcceptable primitives are: LUTs, Flip Flops, IOs, Adders, Rams, and Multiplier blocks.\n\nTo generate the post synthesized verilog and SDF files successfully, you must append the verilog code for the %s to the primitives.v file, and contact the VPR developers team on the website: http://code.google.com/p/vtr-verilog-to-routing/ to update the VPR source code to handle the new primitive. \n",logical_block[current->pb->logical_block].model->name , logical_block[current->pb->logical_block].model->name);
571  exit(1);
572  }
573  free(fixed_name);
574  }
575  primitives = free_linked_list(primitives);
576  }
577 }
578 
579 /*This function instantiates the interconnect modules that connect from the output pins of the primitive "pb" to whatever it connects to block_num is the block number that the pb resides in*/
580 void instantiate_interconnect(FILE *verilog , int block_num , t_pb *pb , FILE *SDF)
581 {
582  conn_list *downhill_connections = NULL;
583 
584  downhill_connections = find_connected_primitives_downhill(block_num , pb , downhill_connections);/*find all the other luts that the lut corresponding to "pb", connects to*/
585 
586  interconnect_printing(verilog , downhill_connections);
587  SDF_interconnect_delay_printing(SDF , downhill_connections);
588  downhill_connections = free_linked_list_conn(downhill_connections);
589 }
590 
591 /*load_truth_table returns the truth table of the LUT corresponding to "pb"
592 inputs: total number of inputs that the LUT has.
593 pb: the t_pb data structure corresponding to the LUT*/
594 
595 char *load_truth_table(int inputs , t_pb *pb)
596 {
597  int number_of_dont_cares=0;
598  int tries,shift,which_row,i,j;
599  int possibles = 1 << inputs;
600  char *tt_row_blif;
601  char *possible_row = (char *)malloc(inputs+1 * sizeof(char));
602  char *tt = (char *)malloc((possibles+1) * sizeof(char));
603  struct s_linked_vptr *current;
604  int number_of_used_inputs_to_lut;
605  char set_to;
606  assert(possible_row);
607  assert(tt);
608 
609  if (logical_block[pb->logical_block].truth_table) { // ??? janders ???? how can you have a LUT without a truth table???
610  tt_row_blif = (char *)logical_block[pb->logical_block].truth_table->data_vptr;
611  }
612  else { // must be producing a GROUND
613  for (i = 0; i < possibles; i++)
614  tt[i] = '0';
615  tt[possibles] = '\0';
616  free(possible_row);
617  return tt;
618  }
619  set_to = tt_row_blif[strlen(tt_row_blif)-1];
620 
621  /*filling the truth table with the state that is opposite to the output state in the blif truth table*/
622  if(set_to =='1')
623  {
624  for(i=0 ; i<possibles ; i++)
625  {
626  tt[i]='0';
627  }
628  }
629  else{
630  for(i=0 ; i<possibles ; i++)
631  {
632  tt[i]='1';
633  }
634  }
635  tt[possibles] = '\0';/*null terminating the tt string*/
636  /*The code bellow will populate the tt[] array with the truth table of the LUT with "pb"
637 
638  The truth table is stored as a linked list in the VPR. Each node in the linked list stores one line of the truth table. This line is in the exact same format as in the blif file. Each line of the truth table is read by traversing through each node of the linked list. The code bellow then parses each line of the truth table. That line might not have all the inputs to the lut specified, or there could be don't cares in that line of the truth table. at the end we need the output value of the LUT for every possible combination of inputs, which is not given in the blif truth table.
639 
640  The code bellow first counts the number of don't cares in that line of the truth table. It also creates a temporary string "possible_row". and there are n=2^(number of don't cares) possibilities in a particular line of the truth table So in a separate loop we find the nth possibility of the truth table*/
641 
642  for(current=logical_block[pb->logical_block].truth_table ; current!=NULL ; current=current->next)/*traversing through all the lines of the blif truth table*/
643  {
644 
645  tt_row_blif=(char *)current->data_vptr;/*tt_row_blif stores the current truth table line*/
646 
647 
648  /*counting number of don't cares in this line of the blif truth table*/
649  number_of_used_inputs_to_lut = strlen(tt_row_blif)-2;/*used*/
650  if(number_of_used_inputs_to_lut == 0)/*If this is a constant generator, then the truth table only contains the constant value that it generates.*/
651  {
652  for(i=0 ; i<possibles ; i++)
653  {
654  tt[i] = tt_row_blif[1];
655  }
656  }
657  else{
658  for(i=0; i<inputs ; i++)
659  {
660  if(tt_row_blif[i] == '-')
661  {
662  number_of_dont_cares++;
663  }
664  }
665  tries = 1 << number_of_dont_cares;/*how many possibilities are there for this line of the blif truth table*/
666 
667  for(i=0 ; i<(tries) ; i++)/*traverse through all the possibilities for this line of the blif truth table*/
668  {
669  shift=number_of_dont_cares-1;
670  for(j=0 ; j<number_of_used_inputs_to_lut ; j++)/*going through all the columns of the blif truth table*/
671  {
672  if(tt_row_blif[j]=='-')/*if this column represents a don't care*/
673  {
674  /*creating a temporary truth table row by taking different values of the possiblity 'i' depending on the shift value*/
675  if(((i>>shift) & 0x1) == 1)
676  {
677  possible_row[j] = '1';
678  }
679  else{
680  possible_row[j] = '0';
681  }
682  shift--;/*reduce the shift value by one*/
683  }
684  else
685  {
686  possible_row[j]=tt_row_blif[j];
687  }
688  }
689  possible_row[j]=0x0;/*null terminate the temporary truth table row*/
690  which_row = find_index(possible_row,inputs);/*find index returns the index of the 64bit truth table that this temporary truth table row corresponds to*/
691  tt[possibles-1-which_row] = set_to;
692  }
693  }
694  number_of_dont_cares = 0;
695  }
696  free(possible_row);
697  return(tt);
698 }
699 
700 int find_index(char *row,int inputs)/*returns the index of the 64bit truth table that this temporary truth table row corresponds to*/
701 {
702  int index=0;/*initially setting index to 0*/
703  int or_=0x1;
704  int i,length;
705 
706  for(i=strlen(row)-1 ; i>=0 ; i--)/*traverse through the columns of this truth table row*/
707  {
708  if(row[i] == '1')
709  {
710  index |= or_;/*if this column is logic 1, then set this column in index to logic 1.*/
711  }
712  or_ = or_ << 1;
713  }
714  length = strlen(row);
715  if(length<inputs)/*if the number of used inputs to the lut is less than the total inputs to the lut*/
716  {
717  index = index << (inputs-(strlen(row)));/*shift the index value by the difference*/
718  }
719  return(index);
720 
721 }
722 
723 /*The names of some primitives contain certain characters that would cause syntax errors in Verilog (e.g. '^' , '~' , '[' , etc. ). This function returns a new string
724  with those illegal characters removed and replaced with '_'*/
725 char *fix_name(char *name)
726 {
727  int i;
728 
729  char *new_;
730  new_=my_strdup(name);
731 
732  for(i=0 ; new_[i]!='\0' ; i++)
733  {
734  if(new_[i]=='^' || (int)new_[i]<48 || ((int)new_[i]>57 && (int)new_[i]<65) || ((int)new_[i]>90 && (int)new_[i]<97) || (int)new_[i]>122)
735  {
736  new_[i]='_';
737  }
738  }
739  return(new_);
740 }
741 
742 /*This function finds the number of inputs to a primitive.*/
744 {
745  int i,j,count=0;
746  for(i=0 ; i<pb->pb_graph_node->num_input_ports ; i++)
747  {
748  for(j=0 ; j<pb->pb_graph_node->num_input_pins[i] ; j++)
749  {
750  count++;
751  }
752  }
753  return(count);
754 }
755 
756 /*This function is a utility function called by intantiate_interconnect*/
757 void interconnect_printing(FILE *fp , conn_list *downhill)
758 {
759  char *fixed_name1;
760  char *fixed_name2;
761  conn_list *connections;
762  int port_number_out=-1,port_number_in=-1,i;
763 
764  for(connections=downhill ; connections!=NULL ; connections=connections->next)/*traverse through all the connected primitives and instantiate a routing interconect module*/
765  {
766  fixed_name1 = fix_name(connections->driver_pb->name);
767  fixed_name2 = fix_name(connections->load_pb->name);
768 
769  for(i=0 ; i<connections->load_pin->parent_node->num_input_ports ; i++)
770  {
771  if(!strcmp(connections->load_pin->parent_node->input_pins[i][0].port->name,connections->load_pin->port->name))
772  {
773  port_number_out = i;
774  }
775  }
776  for(i=0 ; i<connections->driver_pin->parent_node->num_output_ports ; i++)
777  {
778  if(!strcmp(connections->driver_pin->parent_node->output_pins[i][0].port->name,connections->driver_pin->port->name))
779  {
780  port_number_in = i;
781  }
782  }
783  assert(port_number_out >= 0 && port_number_in >= 0);
784 
785  fprintf(fp , "interconnect routing_segment_%s_output_%d_%d_to_%s_input_%d_%d( %s_output_%d_%d , %s_input_%d_%d );\n",
786  fixed_name1 , port_number_in/*connections->driver_pin->port->port_index_by_type*/ , connections->driver_pin->pin_number,
787  fixed_name2 , port_number_out , connections->load_pin->pin_number,
788  fixed_name1 , port_number_in/*connections->driver_pin->port->port_index_by_type*/ , connections->driver_pin->pin_number,
789  fixed_name2 , port_number_out , connections->load_pin->pin_number);
790 
791  free(fixed_name1);
792  free(fixed_name2);
793  }
794 }
795 
796 /*This funciton will instantiate the SDF cell that contains the delay information of the Verilog interconnect modules*/
797 void SDF_interconnect_delay_printing(FILE *SDF , conn_list *downhill)
798 {
799  conn_list *connections;
800  char *fixed_name1;
801  char *fixed_name2;
802  float internal_delay;
803  int del;
804  int port_number_out=-1,port_number_in=-1,i;
805 
806  for(connections=downhill ; connections!=NULL ; connections=connections->next)/*traverse through all the connected primitives and instantiate a routing interconect module*/
807  {
808  fixed_name1 = fix_name(connections->driver_pb->name);
809  fixed_name2 = fix_name(connections->load_pb->name);
810 
811  for(i=0 ; i<connections->load_pin->parent_node->num_input_ports ; i++)
812  {
813  if(!strcmp(connections->load_pin->parent_node->input_pins[i][0].port->name,connections->load_pin->port->name))
814  {
815  port_number_out = i;
816  }
817  }
818  for(i=0 ; i<connections->driver_pin->parent_node->num_output_ports ; i++)
819  {
820  if(!strcmp(connections->driver_pin->parent_node->output_pins[i][0].port->name,connections->driver_pin->port->name))
821  {
822  port_number_in = i;
823  }
824  }
825  internal_delay = connections->driver_to_load_delay;
826  internal_delay = internal_delay * 1000000000000.00; /*converting the delay from seconds to picoseconds*/
827  internal_delay = internal_delay + 0.5; /*Rounding the delay to the nearset picosecond*/
828  del = (int)internal_delay;
829 
830  fprintf(SDF , "\t(CELL\n\t(CELLTYPE \"interconnect\")\n\t(INSTANCE inst/routing_segment_%s_output_%d_%d_to_%s_input_%d_%d)\n" ,
831  fixed_name1 , port_number_in/*connections->driver_pin->port->port_index_by_type*/ , connections->driver_pin->pin_number,
832  fixed_name2 , port_number_out , connections->load_pin->pin_number);
833  fprintf(SDF , "\t\t(DELAY\n\t\t(ABSOLUTE\n\t\t\t(IOPATH datain dataout (%d:%d:%d)(%d:%d:%d))\n\t\t)\n\t\t)\n\t)\n" ,
834  del , del , del , del , del , del);
835 
836  free(fixed_name1);
837  free(fixed_name2);
838 
839  }
840 }
841 
842 /*This function instantiates the SDF cell that contains the delay information of a LUT*/
843 void sdf_LUT_delay_printing(FILE *SDF , t_pb *pb)
844 {
845  char *fixed_name;
846  int j,pin_count;
847  float internal_delay;
848  int del;
849  int logical_block_index = pb->logical_block;
850  int record = 0;
851 
852  fixed_name = fix_name(pb->name);
853 
854  for(j=0 ; j < pb->pb_graph_node->num_input_pins[0] ; j++)/*Assuming that LUTs have a single input port*/
855  {
856  if (logical_block[logical_block_index].input_nets[0][j] != OPEN)
857  {
858 
859  int q;
860  pin_count = OPEN;
861  for (q = 0; q < pb->pb_graph_node->num_input_pins[0]; q++)
862  {
863  pin_count = pb->pb_graph_node->input_pins[0][q].pin_count_in_cluster;
864  if (logical_block[logical_block_index].pb->rr_graph[pin_count].net_num == logical_block[logical_block_index].input_nets[0][j])
865  break;
866  }
867 
868  assert(q != pb->pb_graph_node->num_input_pins[0]);
869 
870  internal_delay = pb->rr_graph[pin_count].tnode->out_edges->Tdel;
871  internal_delay = internal_delay * 1000000000000.00;/*converting the delay from seconds to picoseconds*/
872  internal_delay = internal_delay + 0.5; /*Rounding the delay to the nearset picosecond*/
873  del = (int)internal_delay;
874 
875  if (!record) { // print the SDF record header
876  fprintf(SDF , "\t(CELL\n\t(CELLTYPE \"LUT_%d\")\n\t(INSTANCE inst/lut_%s)\n\t\t(DELAY\n\t\t(ABSOLUTE\n" , find_number_of_inputs(pb) , fixed_name);
877  record = 1;
878  }
879 
880  fprintf(SDF , "\t\t\t(IOPATH inter%d/datain inter%d/dataout (%d:%d:%d)(%d:%d:%d))\n" , j , j , del , del , del , del , del , del);
881  }
882  }
883  if (record)
884  fprintf(SDF , "\t\t)\n\t\t)\n\t)\n");
885  free(fixed_name);
886 }
887 
888 /*This function instantiates the SdF cell that contains the delay information of a Flip Flop*/
889 void sdf_DFF_delay_printing(FILE *SDF , t_pb *pb)
890 {
891  char *fixed_name;
892  float internal_delay;
893  int del,pin_count;
894 
895  fixed_name = fix_name(pb->name);
896  fprintf(SDF , "\t(CELL\n\t(CELLTYPE \"D_Flip_Flop\")\n\t(INSTANCE inst/DFF_%s)\n\t\t(DELAY\n\t\t(ABSOLUTE\n" , fixed_name);
897 
898  pin_count = pb->pb_graph_node->output_pins[0][0].pin_count_in_cluster; // the Q output of the FF (which has only a single output port and pin)
899  assert(pb->rr_graph[pin_count].tnode);
900  internal_delay = pb->rr_graph[pin_count].tnode->T_arr * 1.0E12 + 0.5;
901  del = (int)internal_delay;
902 
903  fprintf(SDF , "\t\t\t(IOPATH (posedge clock) Q (%d:%d:%d)(%d:%d:%d))\n" , del , del , del , del , del , del);
904  fprintf(SDF , "\t\t)\n\t\t)\n\t)\n");
905  free(fixed_name);
906 }
907 
908 void SDF_Mult_delay_printing(FILE *SDF , t_pb *pb)
909 {
910  char *fixed_name;
911  int pin_count;
912  float internal_delay;
913  int del;
914 
915  fixed_name = fix_name(pb->name);
916  fprintf(SDF , "\t(CELL\n\t(CELLTYPE \"mult\")\n\t(INSTANCE inst/%s)\n\t\t(DELAY\n\t\t(ABSOLUTE\n" , fixed_name);
917 
918 
919  pin_count = pb->pb_graph_node->input_pins[0][0].pin_count_in_cluster;
920  assert(pb->rr_graph[pin_count].tnode);
921  internal_delay = pb->rr_graph[pin_count].tnode->out_edges->Tdel;
922  internal_delay = internal_delay * 1000000000000.00;/*converting the delay from seconds to picoseconds*/
923  internal_delay = internal_delay + 0.5; /*Rounding the delay to the nearset picosecond*/
924  del = (int)internal_delay;
925  fprintf(SDF , "\t\t\t(IOPATH delay/A delay/B (%d:%d:%d)(%d:%d:%d))\n" , del , del , del , del , del , del);
926 
927  pin_count = pb->pb_graph_node->input_pins[1][0].pin_count_in_cluster;
928  assert(pb->rr_graph[pin_count].tnode);
929  internal_delay = pb->rr_graph[pin_count].tnode->out_edges->Tdel;
930  internal_delay = internal_delay * 1.0E12;/*converting the delay from seconds to picoseconds*/
931  internal_delay = internal_delay + 0.5; /*Rounding the delay to the nearset picosecond*/
932  del = (int)internal_delay;
933  fprintf(SDF , "\t\t\t(IOPATH delay2/A delay2/B (%d:%d:%d)(%d:%d:%d))\n" , del , del , del , del , del , del);
934 
935  fprintf(SDF , "\t\t)\n\t\t)\n\t)\n");
936  free(fixed_name);
937 
938 }
939 
940 void SDF_Adder_delay_printing(FILE *SDF , t_pb *pb)
941 {
942  int i, j, k;
943  int total_input_ports = pb->pb_graph_node->num_input_ports;
944  int pin_count;
945  char *fixed_name;
946  int record = 0;
947 
948  fixed_name = fix_name(pb->name);
949 
950  for (i = 0; i < total_input_ports; i++) {
951 
952  for (j = 0; j < pb->pb_graph_node->num_input_pins[i]; j++) {
953 
954  pin_count = pb->pb_graph_node->input_pins[i][j].pin_count_in_cluster;
955 
956  t_tnode* tNodeInput = pb->rr_graph[pin_count].tnode; // source pin of timing arc
957 
958  if (!tNodeInput)
959  continue; // no timing information on pin
960 
961  for (k = 0; k < tNodeInput->num_edges; k++) {
962 
963  t_tnode tNodeOutput = tnode[tNodeInput->out_edges[k].to_node]; // dest pin of timing arc
964  int del = tNodeInput->out_edges[k].Tdel * 1.0E12 + 0.5;
965 
966  if (!record) { // print the SDF record header
967  fprintf(SDF , "\t(CELL\n\t(CELLTYPE \"ripple_adder\")\n\t(INSTANCE inst/%s)\n\t\t(DELAY\n\t\t(ABSOLUTE\n" , fixed_name);
968  record = 1;
969  }
970 
971  fprintf(SDF , "\t\t\t(IOPATH %s %s (%d:%d:%d)(%d:%d:%d))\n" , tNodeInput->pb_graph_pin->port->name,
972  tNodeOutput.pb_graph_pin->port->name,
973  del , del , del , del , del , del);
974 
975  }
976  j = pb->pb_graph_node->num_input_pins[i]; // skip to the next port -- JANDERS to fix
977  // what we really want to do here is find the max delay between any pin of the input port, to any pin of the output port
978  }
979  }
980 
981  if (record)
982  fprintf(SDF , "\t\t)\n\t\t)\n\t)\n");
983  free(fixed_name);
984 }
985 
986 
988 {
989  // int num_inputs;
990  char *fixed_name;
991  int pin_count;
992  float internal_delay;
993  int del;
994 
995  // num_inputs = pb->pb_graph_node->num_input_pins[0];
996  fixed_name = fix_name(pb->name);
997  fprintf(SDF , "\t(CELL\n\t(CELLTYPE \"single_port_ram\")\n\t(INSTANCE inst/%s)\n\t\t(DELAY\n\t\t(ABSOLUTE\n" , fixed_name);
998 
999  pin_count = pb->pb_graph_node->output_pins[0][0].pin_count_in_cluster; // an output pin of the RAM
1000  assert(pb->rr_graph[pin_count].tnode);
1001  internal_delay = pb->rr_graph[pin_count].tnode->T_arr * 1.0E12 + 0.5;
1002  del = (int)internal_delay;
1003 
1004  fprintf(SDF , "\t\t\t(IOPATH (posedge clock) out (%d:%d:%d)(%d:%d:%d))" , del , del , del , del , del , del);
1005 
1006  fprintf(SDF , "\t\t)\n\t\t)\n\t)\n");
1007  free(fixed_name);
1008 
1009 }
1010 
1012 {
1013  // int num_inputs;
1014  char *fixed_name;
1015  int pin_count;
1016  float internal_delay;
1017  int del;
1018 
1019  // num_inputs = pb->pb_graph_node->num_input_pins[0];
1020  fixed_name = fix_name(pb->name);
1021  fprintf(SDF , "\t(CELL\n\t(CELLTYPE \"dual_port_ram\")\n\t(INSTANCE inst/%s)\n\t\t(DELAY\n\t\t(ABSOLUTE\n" , fixed_name);
1022 
1023  pin_count = pb->pb_graph_node->output_pins[0][0].pin_count_in_cluster; // an output pin of the RAM
1024  assert(pb->rr_graph[pin_count].tnode);
1025  internal_delay = pb->rr_graph[pin_count].tnode->T_arr * 1.0E12 + 0.5;
1026  del = (int)internal_delay;
1027 
1028  fprintf(SDF , "\t\t\t(IOPATH (posedge clock) out1 (%d:%d:%d)(%d:%d:%d))" , del , del , del , del , del , del);
1029  fprintf(SDF , "\t\t\t(IOPATH (posedge clock) out2 (%d:%d:%d)(%d:%d:%d))" , del , del , del , del , del , del);
1030 
1031  fprintf(SDF , "\t\t)\n\t\t)\n\t)\n");
1032  free(fixed_name);
1033 }
1034 
1035 char *find_clock_name(void)
1036 {
1037  int j;
1038  char *clock_in_the_design=NULL;
1039  int clocks = 0;
1040  for(j=0 ; j<num_nets ; j++)/*Doing this to find the clock name in the design and storing it in clock_,*/
1041  {
1042  /* TODO fix this Hack: Currently detect if a clb_net is a clock using global and not vcc/gnd, need better way */
1043  if(clb_net[j].is_global == TRUE && strcmp(clb_net[j].name, "gnd") != 0 && strcmp(clb_net[j].name, "vcc") != 0)
1044  {
1045  clock_in_the_design = clb_net[j].name;
1046  clocks++;
1047  }
1048  }
1049  if (clocks > 1) {
1050  printf("The post-layout netlist generator presently handles single-clock designs only. Your design contains %d clocks. \n"
1051  "Future VTR releases may support post-layout netlist generation for multi-clock designs.\n", clocks);
1052  exit(1);
1053  }
1054  return(clock_in_the_design);
1055 }
1056 /*The traverse_clb function returns a linked list of all the primitives inside a complex block.
1057 
1058  These primitives may be LUTs , FlipFlops , etc.
1059  block_num: the block number for the complex block.
1060  pb: The t_pb data structure corresponding to the complex block. (i.e block[block_num].pb)
1061  prim_list: A pin_list pointer corresponding to the head of the linked list. The function will populate this head pointer.*/
1062 
1063 pb_list *traverse_clb(t_pb *pb , pb_list *prim_list)
1064 {
1065  int i,j;
1066  const t_pb_type *pb_type;
1067  if(pb == NULL || pb->name == NULL) { /*Reached a pb with no content*/
1068  return(prim_list);
1069  }
1070 
1071  pb_type = pb->pb_graph_node->pb_type;
1072 
1073  if(pb->child_pbs == NULL) {/*reached a primitive*/
1074  prim_list = insert_to_linked_list(pb , prim_list); /*add the primitive to the linked list*/
1075  }
1076 
1077  if(pb_type->num_modes > 0) { /*Traversing through the children of the pb*/
1078  for(i = 0; i < pb_type->modes[pb->mode].num_pb_type_children; i++) {
1079  for(j = 0; j < pb_type->modes[pb->mode].pb_type_children[i].num_pb; j++) {
1080  prim_list = traverse_clb(&(pb->child_pbs[i][j]) , prim_list);
1081  }
1082  }
1083  }
1084 
1085  return(prim_list);
1086 
1087 }
1088 
1089 /*The find_connected_primitives_downhill function will return a linked list of all the primitives that a particular primitive connects to.
1090 
1091  block_num: the block number of the complex block that the primitive resides in.
1092  pb: A pointer to the t_pb data structure that represents the primitive (not the complex block).
1093  list: A head pointer to the start of a linked list. This function will populate the linked list. The linked list can be empty (i.e list=NULL)
1094  or contain other primitives.*/
1095 
1097 {
1098  int i,j,k,q,r;
1099  int total_output_pins;
1100  int pin_number , port_number_out=-1 , pin_number_out , starting_block , next_block , vpck_net , pin_count;
1101  float delay , start_delay , end_delay;
1102 
1103  char *temp_port_name = (char *)malloc(1000 * sizeof(char));
1104  int total_output_ports = pb->pb_graph_node->num_output_ports;
1105  int model_port_index;
1106 
1107  assert(temp_port_name);
1108 
1109  /*iterates through all output pins of the primitive "pb", and finds the other primitive and pin they connect to*/
1110  for(i=0 ; i < total_output_ports ; i++)
1111  {
1112  total_output_pins = pb->pb_graph_node->num_output_pins[i];
1113  for(j=0 ; j < total_output_pins ; j++)
1114  {
1115 
1116  model_port_index = pb->pb_graph_node->output_pins[i][j].port->model_port->index;
1117 
1118  pin_number = pb->pb_graph_node->output_pins[i][j].pin_count_in_cluster; /*pin count of the output pin*/
1119  starting_block = pb->logical_block; /*logical block index for the source primitive*/
1120 
1121  vpck_net = logical_block[starting_block].output_nets[model_port_index][j]; /*The index for the vpack_net struct corresponding to this source to sink(s) connections*/
1122 
1123  if (pb->rr_graph[pin_number].net_num != OPEN) /* If this output pin is used*/
1124  { /*Then we will use the logical_block netlist method for finding the connectivity and timing information*/
1125  if(vpck_net != OPEN)
1126  {
1127 
1128  for(k=1 ; k<vpack_net[vpck_net].num_sinks+1 ; k++)/*traversing through all the sink primitives that the source primitive connects to*/
1129  {
1130  next_block = vpack_net[vpck_net].node_block[k];/*next_blk holds the logical block index for the primitive that the source primitive connects to*/
1131 
1132 #if 0
1133 
1134  // we now need to map between the port on the logical block to the port on the physical block
1136  port_number_out = iPin->port->index;
1137 
1138  // because of possible pin swaps, we need to find the physical on load block that
1139  // has the correct attached net
1140  for (q = 0; q < logical_block[next_block].pb->pb_graph_node->num_input_pins[port_number_out]; q++)
1141  {
1142  int physical_pin_pos = logical_block[next_block].pb->pb_graph_node->input_pins[port_number_out][q].pin_count_in_cluster;
1143  if (logical_block[next_block].pb->rr_graph[physical_pin_pos].net_num == vpck_net)
1144  break;
1145  }
1146 
1147  assert(q != logical_block[next_block].pb->pb_graph_node->num_input_pins[port_number_out]);
1148 
1149  pin_number_out = q;
1150 #endif
1151 
1152  port_number_out = pin_number_out = -1;
1153 
1154  for (r = 0; r < logical_block[next_block].pb->pb_graph_node->num_input_ports; r++) {
1155  for (q = 0; q < logical_block[next_block].pb->pb_graph_node->num_input_pins[r]; q++) {
1156  int physical_pin_pos = logical_block[next_block].pb->pb_graph_node->input_pins[r][q].pin_count_in_cluster;
1157  if (logical_block[next_block].pb->rr_graph[physical_pin_pos].net_num == vpck_net) {
1158  port_number_out = r;
1159  pin_number_out = q;
1160  r = logical_block[next_block].pb->pb_graph_node->num_input_ports;
1161  break;
1162  }
1163  }
1164  }
1165 
1166  assert(port_number_out != -1);
1167  assert(pin_number_out != -1);
1168 
1169  int unswapped_pin_number = vpack_net[vpck_net].node_block_pin[k];
1170 
1171  pin_count = logical_block[next_block].pb->pb_graph_node->input_pins[port_number_out][pin_number_out].pin_count_in_cluster;/*pin count for the sink pin*/
1172  assert(logical_block[next_block].pb->rr_graph[pin_count].tnode);
1173 
1174  start_delay = pb->rr_graph[pin_number].tnode->T_arr; /*The arrival time of the source pin*/
1175  end_delay = logical_block[next_block].pb->rr_graph[pin_count].tnode->T_arr;/*The arrival time of the sink pin*/
1176  delay = end_delay - start_delay; /*The difference of start and end arrival times is the delay for going from the source to sink pin*/
1177  list=insert_to_linked_list_conn(pb , logical_block[next_block].pb ,
1178  &pb->pb_graph_node->output_pins[i][j] ,
1179  &logical_block[next_block].pb->pb_graph_node->input_pins[port_number_out][unswapped_pin_number] ,
1180  delay , list);/*Insert this sink primitive in the linked list pointer to by "list"*/
1181 
1182  }
1183  }
1184  }
1185  }
1186  }
1187  free(temp_port_name);
1188  return(list);
1189 }
1190 
1192 {
1193  pb_list *new_list = (pb_list *)malloc(1 * sizeof(pb_list));
1194  assert(new_list);
1195  new_list->pb = pb_new;
1196  new_list->next = list;
1197  list = new_list;
1198  return(list);
1199 }
1200 
1201 conn_list *insert_to_linked_list_conn(t_pb *driver_new , t_pb *load_new , t_pb_graph_pin *driver_pin_ , t_pb_graph_pin *load_pin_ , float path_delay , conn_list *list)
1202 {
1203  conn_list *new_list = (conn_list *)malloc(1 * sizeof(conn_list));
1204  assert(new_list);
1205  new_list->driver_pb = driver_new;
1206  new_list->load_pb = load_new;
1207  new_list->driver_pin = driver_pin_;
1208  new_list->load_pin = load_pin_;
1209  new_list->driver_to_load_delay = path_delay;
1210  new_list->next = list;
1211  list = new_list;
1212  return(list);
1213 }
1214 
1215 /*traverse_linked_list_conn can be used to print out the found connections of a primitive to the screen */
1217 {
1218  conn_list *current;
1219 
1220  for(current=list ; current != NULL ; current=current->next)
1221  {
1222  printf(" driver=> type: %s , name: %s , output: [%d][%d] , load=> type: %s , name: %s input: [%d][%d]\npath delay: %e\n\n",current->driver_pb->pb_graph_node->pb_type->name ,
1223  current->driver_pb->name,
1224  current->driver_pin->port->index , current->driver_pin->pin_number ,
1225  current->load_pb->pb_graph_node->pb_type->name,
1226  current->load_pb->name,
1227  current->load_pin->port->index , current->load_pin->pin_number,
1228  current->driver_to_load_delay );
1229  }
1230 }
1231 
1232 /*traverse_linked_list can be used to print out the primitives of a clb to the screen */
1234 {
1235  pb_list *current;
1236 
1237  for(current=list ; current!=NULL ; current=current->next)
1238  {
1239  printf("type: %s , name: %s \n", logical_block[current->pb->logical_block].model->name , current->pb->name);
1240  }
1241 }
1242 
1244 {
1245  pb_list *current;
1246  pb_list *temp_free;
1247 
1248  current=list;
1249  while(current!=NULL)
1250  {
1251  temp_free=current;
1252  current=current->next;
1253  free(temp_free);
1254  }
1255  list = NULL;
1256  return(list);
1257 }
1258 
1260 {
1261  conn_list *current;
1262  conn_list *temp_free;
1263 
1264  current=list;
1265  while(current!=NULL)
1266  {
1267  temp_free=current;
1268  current=current->next;
1269  free(temp_free);
1270  }
1271  list = NULL;
1272  return(list);
1273 }
1274 
int * node_block_pin
Definition: vpr_types.h:509
char * name
Definition: vpr_types.h:179
struct s_pb ** child_pbs
Definition: vpr_types.h:185
t_model_ports * model_port
int ** input_nets
Definition: vpr_types.h:211
struct s_pb_type * pb_type_children
void instantiate_interconnect(FILE *verilog, int block_num, t_pb *pb, FILE *SDF)
t_pb_graph_pin * driver_pin
int net_num
Definition: vpr_types.h:917
int find_index(char *row, int inputs)
struct s_rr_node * rr_graph
Definition: vpr_types.h:188
t_tnode * tnode
Definition: vpr_types.h:919
t_mode * modes
float T_arr
Definition: vpr_types.h:343
pb_list * traverse_clb(t_pb *pb, pb_list *prim_list)
void sdf_LUT_delay_printing(FILE *SDF, t_pb *pb)
t_pb_graph_pin * load_pin
int num_nets
Definition: globals.c:27
int * node_block
Definition: vpr_types.h:507
struct s_linked_vptr * truth_table
Definition: vpr_types.h:227
char * name
Definition: vpr_types.h:505
t_pb_graph_pin ** output_pins
void instantiate_primitive_modules(FILE *fp, char *clock_name, FILE *SDF)
int num_blocks
Definition: globals.c:30
void instantiate_SDF_header(FILE *SDF)
char * blif_circuit_name
Definition: globals.c:21
void interconnect_printing(FILE *fp, conn_list *downhill)
char * name
Definition: vpr_types.h:560
void SDF_ram_dual_port_delay_printing(FILE *SDF, t_pb *pb)
int num_edges
Definition: vpr_types.h:342
void SDF_Adder_delay_printing(FILE *SDF, t_pb *pb)
boolean * is_global
t_tnode * tnode
Definition: path_delay.c:143
pb_list * insert_to_linked_list(t_pb *pb_new, pb_list *list)
void verilog_writer(void)
char * load_truth_table(int inputs, t_pb *pb)
struct s_block * block
Definition: globals.c:31
struct s_net * clb_net
Definition: globals.c:28
char * name
void traverse_linked_list_conn(conn_list *list)
struct s_pb_graph_node * parent_node
int logical_block
Definition: vpr_types.h:181
char * find_clock_name(void)
float Tdel
Definition: vpr_types.h:297
void SDF_ram_single_port_delay_printing(FILE *SDF, t_pb *pb)
struct s_linked_vptr * next
Definition: util.h:36
int num_pb_type_children
void instantiate_input_interconnect(FILE *verilog, FILE *SDF, char *clock_name)
t_pb_graph_pin * pb_graph_pin
Definition: vpr_types.h:358
void traverse_linked_list(pb_list *list)
void * data_vptr
Definition: util.h:35
conn_list * insert_to_linked_list_conn(t_pb *driver_new, t_pb *load_new, t_pb_graph_pin *driver_pin_, t_pb_graph_pin *load_pin_, float path_delay, conn_list *list)
t_tedge * out_edges
Definition: vpr_types.h:336
struct s_pb_type * pb_type
char * name
Definition: logic_types.h:34
void instantiate_wires(FILE *verilog)
int to_node
Definition: vpr_types.h:296
struct found_pins * next
struct found_connectivity * next
void sdf_DFF_delay_printing(FILE *SDF, t_pb *pb)
Definition: slre.c:50
conn_list * free_linked_list_conn(conn_list *list)
void SDF_interconnect_delay_printing(FILE *SDF, conn_list *downhill)
struct s_net * vpack_net
Definition: globals.c:19
void SDF_Mult_delay_printing(FILE *SDF, t_pb *pb)
pb_list * free_linked_list(pb_list *list)
int mode
Definition: vpr_types.h:183
t_model * model
Definition: vpr_types.h:209
char * my_strdup(const char *str)
Definition: util.c:101
int ** output_nets
Definition: vpr_types.h:212
int find_number_of_inputs(t_pb *pb)
conn_list * find_connected_primitives_downhill(int block_num, t_pb *pb, conn_list *list)
t_pb_graph_node * pb_graph_node
Definition: vpr_types.h:180
int num_sinks
Definition: vpr_types.h:506
char * fix_name(char *name)
t_pb_graph_pin ** input_pins
struct s_logical_block * logical_block
Definition: globals.c:20
Definition: util.h:12
void instantiate_top_level_module(FILE *verilog)
t_pb_graph_pin * get_pb_graph_node_pin_from_vpack_net(int inet, int ipin)
Definition: vpr_utils.c:343