VPR-7.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
output_clustering.c
Go to the documentation of this file.
1 /*
2  Jason Luu 2008
3  Print complex block information to a file
4  */
5 
6 #include <assert.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "util.h"
11 #include "vpr_types.h"
12 #include "globals.h"
13 #include "output_clustering.h"
14 #include "read_xml_arch_file.h"
15 
16 #define LINELENGTH 1024
17 #define TAB_LENGTH 4
18 
19 /****************** Subroutines local to this module ************************/
20 
21 /**************** Subroutine definitions ************************************/
22 
23 static void print_tabs(FILE *fpout, int num_tabs) {
24  int i;
25  for (i = 0; i < num_tabs; i++) {
26  fprintf(fpout, "\t");
27  }
28 }
29 
30 static void print_string(const char *str_ptr, int *column, int num_tabs, FILE * fpout) {
31 
32  /* Prints string without making any lines longer than LINELENGTH. Column *
33  * points to the column in which the next character will go (both used and *
34  * updated), and fpout points to the output file. */
35 
36  int len;
37 
38  len = strlen(str_ptr);
39  if (len + 3 > LINELENGTH) {
40  vpr_printf(TIO_MESSAGE_ERROR, "in print_string: String %s is too long for desired maximum line length.\n", str_ptr);
41  exit(1);
42  }
43 
44  if (*column + len + 2 > LINELENGTH) {
45  fprintf(fpout, "\n");
46  print_tabs(fpout, num_tabs);
47  *column = num_tabs * TAB_LENGTH;
48  }
49 
50  fprintf(fpout, "%s ", str_ptr);
51  *column += len + 1;
52 }
53 
54 static void print_net_name(int inet, int *column, int num_tabs, FILE * fpout) {
55 
56  /* This routine prints out the vpack_net name (or open) and limits the *
57  * length of a line to LINELENGTH characters by using \ to continue *
58  * lines. net_num is the index of the vpack_net to be printed, while *
59  * column points to the current printing column (column is both *
60  * used and updated by this routine). fpout is the output file *
61  * pointer. */
62 
63  const char *str_ptr;
64 
65  if (inet == OPEN)
66  str_ptr = "open";
67  else
68  str_ptr = vpack_net[inet].name;
69 
70  print_string(str_ptr, column, num_tabs, fpout);
71 }
72 
73 static void print_interconnect(int inode, int *column, int num_tabs,
74  FILE * fpout) {
75 
76  /* This routine prints out the vpack_net name (or open) and limits the *
77  * length of a line to LINELENGTH characters by using \ to continue *
78  * lines. net_num is the index of the vpack_net to be printed, while *
79  * column points to the current printing column (column is both *
80  * used and updated by this routine). fpout is the output file *
81  * pointer. */
82 
83  char *str_ptr, *name;
84  int prev_node, prev_edge;
85  int len;
86 
87  if (rr_node[inode].net_num == OPEN) {
88  print_string("open", column, num_tabs, fpout);
89  } else {
90  str_ptr = NULL;
91  prev_node = rr_node[inode].prev_node;
92  prev_edge = rr_node[inode].prev_edge;
93 
94  if (prev_node == OPEN
95  && rr_node[inode].pb_graph_pin->port->parent_pb_type->num_modes
96  == 0
97  && rr_node[inode].pb_graph_pin->port->type == OUT_PORT) { /* This is a primitive output */
98  print_net_name(rr_node[inode].net_num, column, num_tabs, fpout);
99  } else {
100  name =
101  rr_node[prev_node].pb_graph_pin->output_edges[prev_edge]->interconnect->name;
102  if (rr_node[prev_node].pb_graph_pin->port->parent_pb_type->depth
104  /* Connections from siblings or children should have an explicit index, connections from parent does not need an explicit index */
105  len =
106  strlen(
107  rr_node[prev_node].pb_graph_pin->parent_node->pb_type->name)
109  / 10
110  + strlen(
111  rr_node[prev_node].pb_graph_pin->port->name)
112  + rr_node[prev_node].pb_graph_pin->pin_number
113  / 10 + strlen(name) + 11;
114  str_ptr = (char*)my_malloc(len * sizeof(char));
115  sprintf(str_ptr, "%s[%d].%s[%d]->%s ",
116  rr_node[prev_node].pb_graph_pin->parent_node->pb_type->name,
118  rr_node[prev_node].pb_graph_pin->port->name,
119  rr_node[prev_node].pb_graph_pin->pin_number, name);
120  } else {
121  len =
122  strlen(
123  rr_node[prev_node].pb_graph_pin->parent_node->pb_type->name)
124  + strlen(
125  rr_node[prev_node].pb_graph_pin->port->name)
126  + rr_node[prev_node].pb_graph_pin->pin_number
127  / 10 + strlen(name) + 8;
128  str_ptr = (char*)my_malloc(len * sizeof(char));
129  sprintf(str_ptr, "%s.%s[%d]->%s ",
130  rr_node[prev_node].pb_graph_pin->parent_node->pb_type->name,
131  rr_node[prev_node].pb_graph_pin->port->name,
132  rr_node[prev_node].pb_graph_pin->pin_number, name);
133  }
134  print_string(str_ptr, column, num_tabs, fpout);
135  }
136  if (str_ptr)
137  free(str_ptr);
138  }
139 }
140 
141 static void print_open_pb_graph_node(t_pb_graph_node * pb_graph_node,
142  int pb_index, boolean is_used, int tab_depth, FILE * fpout) {
143  int column = 0;
144  int i, j, k, m;
145  const t_pb_type * pb_type, *child_pb_type;
146  t_mode * mode = NULL;
147  int prev_edge, prev_node;
148  t_pb_graph_pin *pb_graph_pin;
149  int mode_of_edge, port_index, node_index;
150 
151  mode_of_edge = UNDEFINED;
152 
153  pb_type = pb_graph_node->pb_type;
154 
155  print_tabs(fpout, tab_depth);
156 
157  if (is_used) {
158  /* Determine mode if applicable */
159  port_index = 0;
160  for (i = 0; i < pb_type->num_ports; i++) {
161  if (pb_type->ports[i].type == OUT_PORT) {
162  assert(!pb_type->ports[i].is_clock);
163  for (j = 0; j < pb_type->ports[i].num_pins; j++) {
164  node_index =
165  pb_graph_node->output_pins[port_index][j].pin_count_in_cluster;
166  if (pb_type->num_modes > 0
167  && rr_node[node_index].net_num != OPEN) {
168  prev_edge = rr_node[node_index].prev_edge;
169  prev_node = rr_node[node_index].prev_node;
170  pb_graph_pin = rr_node[prev_node].pb_graph_pin;
171  mode_of_edge =
172  pb_graph_pin->output_edges[prev_edge]->interconnect->parent_mode_index;
173  assert(
174  mode == NULL || &pb_type->modes[mode_of_edge] == mode);
175  mode = &pb_type->modes[mode_of_edge];
176  }
177  }
178  port_index++;
179  }
180  }
181 
182  assert(mode != NULL && mode_of_edge != UNDEFINED);
183  fprintf(fpout,
184  "<block name=\"open\" instance=\"%s[%d]\" mode=\"%s\">\n",
185  pb_graph_node->pb_type->name, pb_index, mode->name);
186 
187  print_tabs(fpout, tab_depth);
188  fprintf(fpout, "\t<inputs>\n");
189  port_index = 0;
190  for (i = 0; i < pb_type->num_ports; i++) {
191  if (!pb_type->ports[i].is_clock
192  && pb_type->ports[i].type == IN_PORT) {
193  print_tabs(fpout, tab_depth);
194  fprintf(fpout, "\t\t<port name=\"%s\">",
195  pb_graph_node->pb_type->ports[i].name);
196  for (j = 0; j < pb_type->ports[i].num_pins; j++) {
197  node_index =
198  pb_graph_node->input_pins[port_index][j].pin_count_in_cluster;
199  print_interconnect(node_index, &column, tab_depth + 2,
200  fpout);
201  }
202  fprintf(fpout, "</port>\n");
203  port_index++;
204  }
205  }
206  print_tabs(fpout, tab_depth);
207  fprintf(fpout, "\t</inputs>\n");
208 
209  column = tab_depth * TAB_LENGTH + 8; /* Next column I will write to. */
210  print_tabs(fpout, tab_depth);
211  fprintf(fpout, "\t<outputs>\n");
212  port_index = 0;
213  for (i = 0; i < pb_type->num_ports; i++) {
214  if (pb_type->ports[i].type == OUT_PORT) {
215  print_tabs(fpout, tab_depth);
216  fprintf(fpout, "\t\t<port name=\"%s\">",
217  pb_graph_node->pb_type->ports[i].name);
218  assert(!pb_type->ports[i].is_clock);
219  for (j = 0; j < pb_type->ports[i].num_pins; j++) {
220  node_index =
221  pb_graph_node->output_pins[port_index][j].pin_count_in_cluster;
222  print_interconnect(node_index, &column, tab_depth + 2,
223  fpout);
224  }
225  fprintf(fpout, "</port>\n");
226  port_index++;
227  }
228  }
229  print_tabs(fpout, tab_depth);
230  fprintf(fpout, "\t</outputs>\n");
231 
232  column = tab_depth * TAB_LENGTH + 8; /* Next column I will write to. */
233  print_tabs(fpout, tab_depth);
234  fprintf(fpout, "\t<clocks>\n");
235  port_index = 0;
236  for (i = 0; i < pb_type->num_ports; i++) {
237  if (pb_type->ports[i].is_clock
238  && pb_type->ports[i].type == IN_PORT) {
239  print_tabs(fpout, tab_depth);
240  fprintf(fpout, "\t\t<port name=\"%s\">",
241  pb_graph_node->pb_type->ports[i].name);
242  for (j = 0; j < pb_type->ports[i].num_pins; j++) {
243  node_index =
244  pb_graph_node->clock_pins[port_index][j].pin_count_in_cluster;
245  print_interconnect(node_index, &column, tab_depth + 2,
246  fpout);
247  }
248  fprintf(fpout, "</port>\n");
249  port_index++;
250  }
251  }
252  print_tabs(fpout, tab_depth);
253  fprintf(fpout, "\t</clocks>\n");
254 
255  if (pb_type->num_modes > 0) {
256  for (i = 0; i < mode->num_pb_type_children; i++) {
257  child_pb_type = &mode->pb_type_children[i];
258  for (j = 0; j < mode->pb_type_children[i].num_pb; j++) {
259  port_index = 0;
260  is_used = FALSE;
261  for (k = 0; k < child_pb_type->num_ports && !is_used; k++) {
262  if (child_pb_type->ports[k].type == OUT_PORT) {
263  for (m = 0; m < child_pb_type->ports[k].num_pins;
264  m++) {
265  node_index =
266  pb_graph_node->child_pb_graph_nodes[mode_of_edge][i][j].output_pins[port_index][m].pin_count_in_cluster;
267  if (rr_node[node_index].net_num != OPEN) {
268  is_used = TRUE;
269  break;
270  }
271  }
272  port_index++;
273  }
274  }
276  &pb_graph_node->child_pb_graph_nodes[mode_of_edge][i][j],
277  j, is_used, tab_depth + 1, fpout);
278  }
279  }
280  }
281 
282  print_tabs(fpout, tab_depth);
283  fprintf(fpout, "</block>\n");
284  } else {
285  fprintf(fpout, "<block name=\"open\" instance=\"%s[%d]\"/>\n",
286  pb_graph_node->pb_type->name, pb_index);
287  }
288 }
289 
290 static void print_pb(FILE *fpout, t_pb * pb, int pb_index, int tab_depth) {
291 
292  int column;
293  int i, j, k, m;
294  const t_pb_type *pb_type, *child_pb_type;
295  t_pb_graph_node *pb_graph_node;
296  t_mode *mode;
297  int port_index, node_index;
298  boolean is_used;
299 
300  pb_type = pb->pb_graph_node->pb_type;
301  pb_graph_node = pb->pb_graph_node;
302  mode = &pb_type->modes[pb->mode];
303  column = tab_depth * TAB_LENGTH + 8; /* Next column I will write to. */
304  print_tabs(fpout, tab_depth);
305  if (pb_type->num_modes == 0) {
306  fprintf(fpout, "<block name=\"%s\" instance=\"%s[%d]\">\n", pb->name,
307  pb_type->name, pb_index);
308  } else {
309  fprintf(fpout, "<block name=\"%s\" instance=\"%s[%d]\" mode=\"%s\">\n",
310  pb->name, pb_type->name, pb_index, mode->name);
311  }
312 
313  print_tabs(fpout, tab_depth);
314  fprintf(fpout, "\t<inputs>\n");
315  port_index = 0;
316  for (i = 0; i < pb_type->num_ports; i++) {
317  if (!pb_type->ports[i].is_clock && pb_type->ports[i].type == IN_PORT) {
318  print_tabs(fpout, tab_depth);
319  fprintf(fpout, "\t\t<port name=\"%s\">",
320  pb_graph_node->pb_type->ports[i].name);
321  for (j = 0; j < pb_type->ports[i].num_pins; j++) {
322  node_index =
323  pb->pb_graph_node->input_pins[port_index][j].pin_count_in_cluster;
324  if (pb_type->parent_mode == NULL) {
325  print_net_name(rr_node[node_index].net_num, &column,
326  tab_depth, fpout);
327  } else {
328  print_interconnect(node_index, &column, tab_depth + 2,
329  fpout);
330  }
331  }
332  fprintf(fpout, "</port>\n");
333  port_index++;
334  }
335  }
336  print_tabs(fpout, tab_depth);
337  fprintf(fpout, "\t</inputs>\n");
338 
339  column = tab_depth * TAB_LENGTH + 8; /* Next column I will write to. */
340  print_tabs(fpout, tab_depth);
341  fprintf(fpout, "\t<outputs>\n");
342  port_index = 0;
343  for (i = 0; i < pb_type->num_ports; i++) {
344  if (pb_type->ports[i].type == OUT_PORT) {
345  assert(!pb_type->ports[i].is_clock);
346  print_tabs(fpout, tab_depth);
347  fprintf(fpout, "\t\t<port name=\"%s\">",
348  pb_graph_node->pb_type->ports[i].name);
349  for (j = 0; j < pb_type->ports[i].num_pins; j++) {
350  node_index =
351  pb->pb_graph_node->output_pins[port_index][j].pin_count_in_cluster;
352  print_interconnect(node_index, &column, tab_depth + 2, fpout);
353  }
354  fprintf(fpout, "</port>\n");
355  port_index++;
356  }
357  }
358  print_tabs(fpout, tab_depth);
359  fprintf(fpout, "\t</outputs>\n");
360 
361  column = tab_depth * TAB_LENGTH + 8; /* Next column I will write to. */
362  print_tabs(fpout, tab_depth);
363  fprintf(fpout, "\t<clocks>\n");
364  port_index = 0;
365  for (i = 0; i < pb_type->num_ports; i++) {
366  if (pb_type->ports[i].is_clock && pb_type->ports[i].type == IN_PORT) {
367  print_tabs(fpout, tab_depth);
368  fprintf(fpout, "\t\t<port name=\"%s\">",
369  pb_graph_node->pb_type->ports[i].name);
370  for (j = 0; j < pb_type->ports[i].num_pins; j++) {
371  node_index =
372  pb->pb_graph_node->clock_pins[port_index][j].pin_count_in_cluster;
373  if (pb_type->parent_mode == NULL) {
374  print_net_name(rr_node[node_index].net_num, &column,
375  tab_depth, fpout);
376  } else {
377  print_interconnect(node_index, &column, tab_depth + 2,
378  fpout);
379  }
380  }
381  fprintf(fpout, "</port>\n");
382  port_index++;
383  }
384  }
385  print_tabs(fpout, tab_depth);
386  fprintf(fpout, "\t</clocks>\n");
387 
388  if (pb_type->num_modes > 0) {
389  for (i = 0; i < mode->num_pb_type_children; i++) {
390  for (j = 0; j < mode->pb_type_children[i].num_pb; j++) {
391  /* If child pb is not used but routing is used, I must print things differently */
392  if ((pb->child_pbs[i] != NULL)
393  && (pb->child_pbs[i][j].name != NULL)) {
394  print_pb(fpout, &pb->child_pbs[i][j], j, tab_depth + 1);
395  } else {
396  is_used = FALSE;
397  child_pb_type = &mode->pb_type_children[i];
398  port_index = 0;
399 
400  for (k = 0; k < child_pb_type->num_ports && !is_used; k++) {
401  if (child_pb_type->ports[k].type == OUT_PORT) {
402  for (m = 0; m < child_pb_type->ports[k].num_pins;
403  m++) {
404  node_index =
405  pb_graph_node->child_pb_graph_nodes[pb->mode][i][j].output_pins[port_index][m].pin_count_in_cluster;
406  if (rr_node[node_index].net_num != OPEN) {
407  is_used = TRUE;
408  break;
409  }
410  }
411  port_index++;
412  }
413  }
415  &pb_graph_node->child_pb_graph_nodes[pb->mode][i][j],
416  j, is_used, tab_depth + 1, fpout);
417  }
418  }
419  }
420  }
421  print_tabs(fpout, tab_depth);
422  fprintf(fpout, "</block>\n");
423 }
424 
425 static void print_clusters(t_block *clb, int num_clusters, FILE * fpout) {
426 
427  /* Prints out one cluster (clb). Both the external pins and the *
428  * internal connections are printed out. */
429 
430  int icluster;
431 
432  for (icluster = 0; icluster < num_clusters; icluster++) {
433  rr_node = clb[icluster].pb->rr_graph;
434 
435  /* TODO: Must do check that total CLB pins match top-level pb pins, perhaps check this earlier? */
436 
437  print_pb(fpout, clb[icluster].pb, icluster, 1);
438  }
439 }
440 
441 static void print_stats(t_block *clb, int num_clusters) {
442 
443  /* Prints out one cluster (clb). Both the external pins and the *
444  * internal connections are printed out. */
445 
446  int ipin, icluster, itype, inet;/*, iblk;*/
447  /*int unabsorbable_ffs;*/
448  int total_nets_absorbed;
449  boolean * nets_absorbed;
450 
451  int *num_clb_types, *num_clb_inputs_used, *num_clb_outputs_used;
452 
453  nets_absorbed = NULL;
454  num_clb_types = num_clb_inputs_used = num_clb_outputs_used = NULL;
455 
456  num_clb_types = (int*) my_calloc(num_types, sizeof(int));
457  num_clb_inputs_used = (int*) my_calloc(num_types, sizeof(int));
458  num_clb_outputs_used = (int*) my_calloc(num_types, sizeof(int));
459 
460 
461  nets_absorbed = (boolean *) my_calloc(num_logical_nets, sizeof(boolean));
462  for (inet = 0; inet < num_logical_nets; inet++) {
463  nets_absorbed[inet] = TRUE;
464  }
465 
466 #if 0
467 
468 /*counting number of flipflops which cannot be absorbed to check the optimality of the packer wrt CLB density*/
469 
470  unabsorbable_ffs = 0;
471  for (iblk = 0; iblk < num_logical_blocks; iblk++) {
472  if (strcmp(logical_block[iblk].model->name, "latch") == 0) {
473  if (vpack_net[logical_block[iblk].input_nets[0][0]].num_sinks > 1
474  || strcmp(
475  logical_block[vpack_net[logical_block[iblk].input_nets[0][0]].node_block[0]].model->name,
476  "names") != 0) {
477  unabsorbable_ffs++;
478  }
479  }
480  }
481  vpr_printf(TIO_MESSAGE_INFO, "\n");
482  vpr_printf(TIO_MESSAGE_INFO, "%d FFs in input netlist not absorbable (ie. impossible to form BLE).\n", unabsorbable_ffs);
483 #endif
484 
485  /* Counters used only for statistics purposes. */
486 
487  for (icluster = 0; icluster < num_clusters; icluster++) {
488  for (ipin = 0; ipin < clb[icluster].type->num_pins; ipin++) {
489  if (clb[icluster].nets[ipin] != OPEN) {
490  nets_absorbed[clb[icluster].nets[ipin]] = FALSE;
491  if (clb[icluster].type->class_inf[clb[icluster].type->pin_class[ipin]].type
492  == RECEIVER) {
493  num_clb_inputs_used[clb[icluster].type->index]++;
494  } else if (clb[icluster].type->class_inf[clb[icluster].type->pin_class[ipin]].type
495  == DRIVER) {
496  num_clb_outputs_used[clb[icluster].type->index]++;
497  }
498  }
499  }
500  num_clb_types[clb[icluster].type->index]++;
501  }
502 
503  for (itype = 0; itype < num_types; itype++) {
504  if (num_clb_types[itype] == 0) {
505  vpr_printf(TIO_MESSAGE_INFO, "\t%s: # blocks: %d, average # input + clock pins used: %g, average # output pins used: %g\n",
506  type_descriptors[itype].name, num_clb_types[itype], 0.0, 0.0);
507  } else {
508  vpr_printf(TIO_MESSAGE_INFO, "\t%s: # blocks: %d, average # input + clock pins used: %g, average # output pins used: %g\n",
509  type_descriptors[itype].name, num_clb_types[itype],
510  (float) num_clb_inputs_used[itype] / (float) num_clb_types[itype],
511  (float) num_clb_outputs_used[itype] / (float) num_clb_types[itype]);
512  }
513  }
514 
515  total_nets_absorbed = 0;
516  for (inet = 0; inet < num_logical_nets; inet++) {
517  if (nets_absorbed[inet] == TRUE) {
518  total_nets_absorbed++;
519  }
520  }
521  vpr_printf(TIO_MESSAGE_INFO, "Absorbed logical nets %d out of %d nets, %d nets not absorbed.\n",
522  total_nets_absorbed, num_logical_nets, num_logical_nets - total_nets_absorbed);
523  free(nets_absorbed);
524  free(num_clb_types);
525  free(num_clb_inputs_used);
526  free(num_clb_outputs_used);
527  /* TODO: print more stats */
528 }
529 
530 void output_clustering(t_block *clb, int num_clusters, boolean global_clocks,
531  boolean * is_clock, char *out_fname, boolean skip_clustering) {
532 
533  /*
534  * This routine dumps out the output netlist in a format suitable for *
535  * input to vpr. This routine also dumps out the internal structure of *
536  * the cluster, in essentially a graph based format. */
537 
538  FILE *fpout;
539  int bnum, netnum, column;
540 
541  fpout = fopen(out_fname, "w");
542 
543  fprintf(fpout, "<block name=\"%s\" instance=\"FPGA_packed_netlist[0]\">\n",
544  out_fname);
545  fprintf(fpout, "\t<inputs>\n\t\t");
546 
547  column = 2 * TAB_LENGTH; /* Organize whitespace to ident data inside block */
548  for (bnum = 0; bnum < num_logical_blocks; bnum++) {
549  if (logical_block[bnum].type == VPACK_INPAD) {
550  print_string(logical_block[bnum].name, &column, 2, fpout);
551  }
552  }
553  fprintf(fpout, "\n\t</inputs>\n");
554  fprintf(fpout, "\n\t<outputs>\n\t\t");
555 
556  column = 2 * TAB_LENGTH;
557  for (bnum = 0; bnum < num_logical_blocks; bnum++) {
558  if (logical_block[bnum].type == VPACK_OUTPAD) {
559  print_string(logical_block[bnum].name, &column, 2, fpout);
560  }
561  }
562  fprintf(fpout, "\n\t</outputs>\n");
563 
564  column = 2 * TAB_LENGTH;
565  if (global_clocks) {
566  fprintf(fpout, "\n\t<clocks>\n\t\t");
567 
568  for (netnum = 0; netnum < num_logical_nets; netnum++) {
569  if (is_clock[netnum]) {
570  print_string(vpack_net[netnum].name, &column, 2, fpout);
571  }
572  }
573  fprintf(fpout, "\n\t</clocks>\n\n");
574  }
575 
576  /* Print out all input and output pads. */
577 
578  for (bnum = 0; bnum < num_logical_blocks; bnum++) {
579  switch (logical_block[bnum].type) {
580  case VPACK_INPAD:
581  case VPACK_OUTPAD:
582  case VPACK_COMB:
583  case VPACK_LATCH:
584  if (skip_clustering) {
585  assert(0);
586  }
587  break;
588 
589  case VPACK_EMPTY:
590  vpr_printf(TIO_MESSAGE_ERROR, "in output_netlist: logical_block %d is VPACK_EMPTY.\n",
591  bnum);
592  exit(1);
593  break;
594 
595  default:
596  vpr_printf(TIO_MESSAGE_ERROR, "in output_netlist: Unexpected type %d for logical_block %d.\n",
597  logical_block[bnum].type, bnum);
598  }
599  }
600 
601  if (skip_clustering == FALSE)
602  print_clusters(clb, num_clusters, fpout);
603 
604  fprintf(fpout, "</block>\n\n");
605 
606  fclose(fpout);
607 
608  print_stats(clb, num_clusters);
609 }
boolean is_clock
char * name
Definition: vpr_types.h:179
t_pb_graph_pin ** clock_pins
static void print_interconnect(int inode, int *column, int num_tabs, FILE *fpout)
struct s_pb ** child_pbs
Definition: vpr_types.h:185
char * name
int num_pins
static void print_clusters(t_block *clb, int num_clusters, FILE *fpout)
struct s_pb_type * pb_type_children
t_rr_node * rr_node
Definition: globals.c:70
#define LINELENGTH
int net_num
Definition: vpr_types.h:917
struct s_rr_node * rr_graph
Definition: vpr_types.h:188
t_mode * modes
struct s_pb_graph_edge ** output_edges
int prev_node
Definition: vpr_types.h:915
static void print_string(const char *str_ptr, int *column, int num_tabs, FILE *fpout)
void * my_calloc(size_t nelem, size_t size)
Definition: util.c:132
enum PORTS type
int num_logical_nets
Definition: globals.c:17
char * name
Definition: vpr_types.h:505
t_pb_graph_pin ** output_pins
t_type_ptr type
Definition: vpr_types.h:561
static void print_stats(t_block *clb, int num_clusters)
#define UNDEFINED
Definition: vpr_types.h:103
t_interconnect * interconnect
Definition: util.h:12
t_mode * parent_mode
static void * my_malloc(int ibytes)
Definition: graphics.c:499
void output_clustering(t_block *clb, int num_clusters, boolean global_clocks, boolean *is_clock, char *out_fname, boolean skip_clustering)
static void print_pb(FILE *fpout, t_pb *pb, int pb_index, int tab_depth)
char * name
struct s_pb_graph_node * parent_node
struct s_pb_graph_node *** child_pb_graph_nodes
int num_pb_type_children
static void print_open_pb_graph_node(t_pb_graph_node *pb_graph_node, int pb_index, boolean is_used, int tab_depth, FILE *fpout)
static char * model
Definition: read_blif.c:45
struct s_pb_type * pb_type
struct s_pb_type * parent_pb_type
int num_types
Definition: globals.c:37
t_pb_graph_pin * pb_graph_pin
Definition: vpr_types.h:918
t_port * ports
int num_logical_blocks
Definition: globals.c:17
Definition: slre.c:50
int * nets
Definition: vpr_types.h:562
t_pb * pb
Definition: vpr_types.h:567
struct s_type_descriptor * type_descriptors
Definition: globals.c:38
struct s_net * vpack_net
Definition: globals.c:19
int prev_edge
Definition: vpr_types.h:916
static void print_tabs(FILE *fpout, int num_tabs)
int mode
Definition: vpr_types.h:183
static void print_net_name(int inet, int *column, int num_tabs, FILE *fpout)
messagelogger vpr_printf
Definition: util.c:17
t_pb_graph_node * pb_graph_node
Definition: vpr_types.h:180
t_pb_graph_pin ** input_pins
#define TAB_LENGTH
struct s_logical_block * logical_block
Definition: globals.c:20
Definition: util.h:12