VPR-7.0
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
read_xml_arch_file.c
Go to the documentation of this file.
1 /* The XML parser processes an XML file into a tree data structure composed of *
2  * ezxml_t nodes. Each ezxml_t node represents an XML element. For example *
3  * <a> <b/> </a> will generate two ezxml_t nodes. One called "a" and its *
4  * child "b". Each ezxml_t node can contain various XML data such as attribute *
5  * information and text content. The XML parser provides several functions to *
6  * help the developer build, traverse, and free this ezxml_t tree. *
7  * *
8  * The function ezxml_parse_file reads in an architecture file. *
9  * *
10  * The function FindElement returns a child ezxml_t node for a given ezxml_t *
11  * node that matches a name provided by the developer. *
12  * *
13  * The function FreeNode frees a child ezxml_t node. All children nodes must *
14  * be freed before the parent can be freed. *
15  * *
16  * The function FindProperty is used to extract attributes from an ezxml_t node. *
17  * The corresponding ezxml_set_attr is used to then free an attribute after it *
18  * is read. We have several helper functions that perform this common *
19  * read/store/free operation in one step such as GetIntProperty and *
20  * GetFloatProperty. *
21  * *
22  * Because of how the XML tree traversal works, we free everything when we're *
23  * done reading an architecture file to make sure that there isn't some part *
24  * of the architecture file that got missed. *
25  */
26 
27 #include <string.h>
28 #include <assert.h>
29 #include "util.h"
30 #include "arch_types.h"
31 #include "ReadLine.h"
32 #include "ezxml.h"
33 #include "read_xml_arch_file.h"
34 #include "read_xml_util.h"
35 
36 enum Fc_type {
38 };
39 
40 /* This identifies the t_type_ptr of an IO block */
41 static t_type_ptr IO_TYPE = NULL;
42 
43 /* This identifies the t_type_ptr of an Empty block */
44 static t_type_ptr EMPTY_TYPE = NULL;
45 
46 /* This identifies the t_type_ptr of the default logic block */
47 static t_type_ptr FILL_TYPE = NULL;
48 
49 /* Describes the different types of CLBs available */
51 
52 /* Function prototypes */
53 /* Populate data */
54 static void SetupEmptyType(void);
55 static void SetupPinLocationsAndPinClasses(ezxml_t Locations,
56  t_type_descriptor * Type);
57 static void SetupGridLocations(ezxml_t Locations, t_type_descriptor * Type);
58 #if 0
59 static void SetupTypeTiming(ezxml_t timing,
60  t_type_descriptor * Type);
61 #endif
62 /* Process XML hiearchy */
63 static void ProcessPb_Type(INOUTP ezxml_t Parent, t_pb_type * pb_type,
64  t_mode * mode);
65 static void ProcessPb_TypePort(INOUTP ezxml_t Parent, t_port * port,
66  e_power_estimation_method power_method);
67 static void ProcessPinToPinAnnotations(ezxml_t parent,
68  t_pin_to_pin_annotation *annotation);
69 static void ProcessInterconnect(INOUTP ezxml_t Parent, t_mode * mode);
70 static void ProcessMode(INOUTP ezxml_t Parent, t_mode * mode,
71  boolean * default_leakage_mode);
72 static void Process_Fc(ezxml_t Node, t_type_descriptor * Type);
73 static void ProcessComplexBlockProps(ezxml_t Node, t_type_descriptor * Type);
74 static void ProcessChanWidthDistr(INOUTP ezxml_t Node,
75  OUTP struct s_arch *arch);
76 static void ProcessChanWidthDistrDir(INOUTP ezxml_t Node, OUTP t_chan * chan);
77 static void ProcessModels(INOUTP ezxml_t Node, OUTP struct s_arch *arch);
78 static void ProcessLayout(INOUTP ezxml_t Node, OUTP struct s_arch *arch);
79 static void ProcessDevice(INOUTP ezxml_t Node, OUTP struct s_arch *arch,
80  INP boolean timing_enabled);
82  char *new_name, t_pb_type *copy);
83 static void ProcessLutClass(INOUTP t_pb_type *lut_pb_type);
84 static void ProcessMemoryClass(INOUTP t_pb_type *mem_pb_type);
85 static void ProcessComplexBlocks(INOUTP ezxml_t Node,
86  OUTP t_type_descriptor ** Types, OUTP int *NumTypes,
87  INP boolean timing_enabled);
88 static void ProcessSwitches(INOUTP ezxml_t Node,
89  OUTP struct s_switch_inf **Switches, OUTP int *NumSwitches,
90  INP boolean timing_enabled);
91 static void ProcessDirects(INOUTP ezxml_t Parent, OUTP t_direct_inf **Directs,
92  OUTP int *NumDirects, INP boolean timing_enabled);
93 static void ProcessSegments(INOUTP ezxml_t Parent,
94  OUTP struct s_segment_inf **Segs, OUTP int *NumSegs,
95  INP struct s_switch_inf *Switches, INP int NumSwitches,
96  INP boolean timing_enabled);
97 static void ProcessCB_SB(INOUTP ezxml_t Node, INOUTP boolean * list,
98  INP int len);
99 static void ProcessPower( INOUTP ezxml_t parent,
100  INOUTP t_power_arch * power_arch, INP t_type_descriptor * Types,
101  INP int NumTypes);
102 
103 static void ProcessClocks(ezxml_t Parent, t_clock_arch * clocks);
104 
105 static void CreateModelLibrary(OUTP struct s_arch *arch);
106 static void UpdateAndCheckModels(INOUTP struct s_arch *arch);
107 static void SyncModelsPbTypes(INOUTP struct s_arch *arch,
108  INP t_type_descriptor * Types, INP int NumTypes);
109 static void SyncModelsPbTypes_rec(INOUTP struct s_arch *arch,
111 
112 static void PrintPb_types_rec(INP FILE * Echo, INP const t_pb_type * pb_type,
113  int level);
115 static void ProcessPb_TypePort_Power(ezxml_t Parent, t_port * port,
116  e_power_estimation_method power_method);
118  e_power_estimation_method parent_power_method);
119 
120 /* Sets up the pinloc map and pin classes for the type. Unlinks the loc nodes
121  * from the XML tree.
122  * Pins and pin classses must already be setup by SetupPinClasses */
124  t_type_descriptor * Type) {
125  int i, j, k, Count, Len;
126  int capacity, pin_count;
127  int num_class;
128  const char * Prop;
129 
130  ezxml_t Cur, Prev;
131  char **Tokens, **CurTokens;
132 
133  capacity = Type->capacity;
134 
135  Prop = FindProperty(Locations, "pattern", TRUE);
136  if (strcmp(Prop, "spread") == 0) {
138  } else if (strcmp(Prop, "custom") == 0) {
140  } else {
141  vpr_printf(TIO_MESSAGE_ERROR,
142  "[LINE %d] %s is an invalid pin location pattern.\n",
143  Locations->line, Prop);
144  exit(1);
145  }
146  ezxml_set_attr(Locations, "pattern", NULL);
147 
148  /* Alloc and clear pin locations */
149  Type->pinloc = (int ***) my_malloc(Type->height * sizeof(int **));
150  Type->pin_height = (int *) my_calloc(Type->num_pins, sizeof(int));
151  for (i = 0; i < Type->height; ++i) {
152  Type->pinloc[i] = (int **) my_malloc(4 * sizeof(int *));
153  for (j = 0; j < 4; ++j) {
154  Type->pinloc[i][j] = (int *) my_malloc(
155  Type->num_pins * sizeof(int));
156  for (k = 0; k < Type->num_pins; ++k) {
157  Type->pinloc[i][j][k] = 0;
158  }
159  }
160  }
161 
162  Type->pin_loc_assignments = (char****) my_malloc(
163  Type->height * sizeof(char***));
164  Type->num_pin_loc_assignments = (int**) my_malloc(
165  Type->height * sizeof(int*));
166  for (i = 0; i < Type->height; i++) {
167  Type->pin_loc_assignments[i] = (char***) my_calloc(4, sizeof(char**));
168  Type->num_pin_loc_assignments[i] = (int*) my_calloc(4, sizeof(int));
169  }
170 
171  /* Load the pin locations */
173  Cur = Locations->child;
174  while (Cur) {
175  CheckElement(Cur, "loc");
176 
177  /* Get offset */
178  i = GetIntProperty(Cur, "offset", FALSE, 0);
179  if ((i < 0) || (i >= Type->height)) {
180  vpr_printf(TIO_MESSAGE_ERROR,
181  "[LINE %d] %d is an invalid offset for type '%s'.\n",
182  Cur->line, i, Type->name);
183  exit(1);
184  }
185 
186  /* Get side */
187  Prop = FindProperty(Cur, "side", TRUE);
188  if (0 == strcmp(Prop, "left")) {
189  j = LEFT;
190  }
191 
192  else if (0 == strcmp(Prop, "top")) {
193  j = TOP;
194  }
195 
196  else if (0 == strcmp(Prop, "right")) {
197  j = RIGHT;
198  }
199 
200  else if (0 == strcmp(Prop, "bottom")) {
201  j = BOTTOM;
202  }
203 
204  else {
205  vpr_printf(TIO_MESSAGE_ERROR,
206  "[LINE %d] '%s' is not a valid side.\n", Cur->line,
207  Prop);
208  exit(1);
209  }
210  ezxml_set_attr(Cur, "side", NULL);
211 
212  /* Check location is on perimeter */
213  if ((TOP == j) && (i != (Type->height - 1))) {
214  vpr_printf(TIO_MESSAGE_ERROR,
215  "[LINE %d] Locations are only allowed on large block "
216  "perimeter. 'top' side should be at offset %d only.\n",
217  Cur->line, (Type->height - 1));
218  exit(1);
219  }
220  if ((BOTTOM == j) && (i != 0)) {
221  vpr_printf(TIO_MESSAGE_ERROR,
222  "[LINE %d] Locations are only allowed on large block "
223  "perimeter. 'bottom' side should be at offset 0 only.\n",
224  Cur->line);
225  exit(1);
226  }
227 
228  /* Go through lists of pins */
229  CountTokensInString(Cur->txt, &Count, &Len);
230  Type->num_pin_loc_assignments[i][j] = Count;
231  if (Count > 0) {
232  Tokens = GetNodeTokens(Cur);
233  CurTokens = Tokens;
234  Type->pin_loc_assignments[i][j] = (char**) my_calloc(Count,
235  sizeof(char*));
236  for (k = 0; k < Count; k++) {
237  /* Store location assignment */
238  Type->pin_loc_assignments[i][j][k] = my_strdup(*CurTokens);
239 
240  /* Advance through list of pins in this location */
241  ++CurTokens;
242  }
243  FreeTokens(&Tokens);
244  }
245  Prev = Cur;
246  Cur = Cur->next;
247  FreeNode(Prev);
248  }
249  }
250 
251  /* Setup pin classes */
252  num_class = 0;
253  for (i = 0; i < Type->pb_type->num_ports; i++) {
254  if (Type->pb_type->ports[i].equivalent) {
255  num_class += capacity;
256  } else {
257  num_class += capacity * Type->pb_type->ports[i].num_pins;
258  }
259  }
260  Type->class_inf = (struct s_class*) my_calloc(num_class,
261  sizeof(struct s_class));
262  Type->num_class = num_class;
263  Type->pin_class = (int*) my_malloc(Type->num_pins * sizeof(int) * capacity);
264  Type->is_global_pin = (boolean*) my_malloc(
265  Type->num_pins * sizeof(boolean) * capacity);
266  for (i = 0; i < Type->num_pins * capacity; i++) {
267  Type->pin_class[i] = OPEN;
268  Type->is_global_pin[i] = (boolean) OPEN;
269  }
270 
271  pin_count = 0;
272 
273  /* Equivalent pins share the same class, non-equivalent pins belong to different pin classes */
274  num_class = 0;
275  for (i = 0; i < capacity; ++i) {
276  for (j = 0; j < Type->pb_type->num_ports; ++j) {
277  if (Type->pb_type->ports[j].equivalent) {
278  Type->class_inf[num_class].num_pins =
279  Type->pb_type->ports[j].num_pins;
280  Type->class_inf[num_class].pinlist = (int *) my_malloc(
281  sizeof(int) * Type->pb_type->ports[j].num_pins);
282  }
283 
284  for (k = 0; k < Type->pb_type->ports[j].num_pins; ++k) {
285  if (!Type->pb_type->ports[j].equivalent) {
286  Type->class_inf[num_class].num_pins = 1;
287  Type->class_inf[num_class].pinlist = (int *) my_malloc(
288  sizeof(int) * 1);
289  Type->class_inf[num_class].pinlist[0] = pin_count;
290  } else {
291  Type->class_inf[num_class].pinlist[k] = pin_count;
292  }
293 
294  if (Type->pb_type->ports[j].type == IN_PORT) {
295  Type->class_inf[num_class].type = RECEIVER;
296  } else {
297  assert(Type->pb_type->ports[j].type == OUT_PORT);
298  Type->class_inf[num_class].type = DRIVER;
299  }
300  Type->pin_class[pin_count] = num_class;
301  Type->is_global_pin[pin_count] =
302  (boolean) (Type->pb_type->ports[j].is_clock
303  || Type->pb_type->ports[j].is_non_clock_global);
304  pin_count++;
305 
306  if (!Type->pb_type->ports[j].equivalent) {
307  num_class++;
308  }
309  }
310  if (Type->pb_type->ports[j].equivalent) {
311  num_class++;
312  }
313  }
314  }
315  assert(num_class == Type->num_class);
316  assert(pin_count == Type->num_pins);
317 }
318 
319 /* Sets up the grid_loc_def for the type. Unlinks the loc nodes
320  * from the XML tree. */
321 static void SetupGridLocations(ezxml_t Locations, t_type_descriptor * Type) {
322  int i;
323 
324  ezxml_t Cur, Prev;
325  const char *Prop;
326 
327  Type->num_grid_loc_def = CountChildren(Locations, "loc", 1);
328  Type->grid_loc_def = (struct s_grid_loc_def *) my_calloc(
329  Type->num_grid_loc_def, sizeof(struct s_grid_loc_def));
330 
331  /* Load the pin locations */
332  Cur = Locations->child;
333  i = 0;
334  while (Cur) {
335  CheckElement(Cur, "loc");
336 
337  /* loc index */
338  Prop = FindProperty(Cur, "type", TRUE);
339  if (Prop) {
340  if (strcmp(Prop, "perimeter") == 0) {
341  if (Type->num_grid_loc_def != 1) {
342  vpr_printf(TIO_MESSAGE_ERROR,
343  "[LINE %d] Another loc specified for perimeter.\n",
344  Cur->line);
345  exit(1);
346  }
348  assert(IO_TYPE == Type);
349  /* IO goes to boundary */
350  } else if (strcmp(Prop, "fill") == 0) {
351  if (Type->num_grid_loc_def != 1 || FILL_TYPE != NULL) {
352  vpr_printf(TIO_MESSAGE_ERROR,
353  "[LINE %d] Another loc specified for fill.\n",
354  Cur->line);
355  exit(1);
356  }
357  Type->grid_loc_def[i].grid_loc_type = FILL;
358  FILL_TYPE = Type;
359  } else if (strcmp(Prop, "col") == 0) {
361  } else if (strcmp(Prop, "rel") == 0) {
363  } else {
364  vpr_printf(TIO_MESSAGE_ERROR,
365  "[LINE %d] Unknown grid location type '%s' for type '%s'.\n",
366  Cur->line, Prop, Type->name);
367  exit(1);
368  }
369  ezxml_set_attr(Cur, "type", NULL);
370  }
371  Prop = FindProperty(Cur, "start", FALSE);
372  if (Type->grid_loc_def[i].grid_loc_type == COL_REPEAT) {
373  if (Prop == NULL) {
374  vpr_printf(TIO_MESSAGE_ERROR,
375  "[LINE %d] grid location property 'start' must be specified for grid location type 'col'.\n",
376  Cur->line);
377  exit(1);
378  }
379  Type->grid_loc_def[i].start_col = my_atoi(Prop);
380  ezxml_set_attr(Cur, "start", NULL);
381  } else if (Prop != NULL) {
382  vpr_printf(TIO_MESSAGE_ERROR,
383  "[LINE %d] grid location property 'start' valid for grid location type 'col' only.\n",
384  Cur->line);
385  exit(1);
386  }
387  Prop = FindProperty(Cur, "repeat", FALSE);
388  if (Type->grid_loc_def[i].grid_loc_type == COL_REPEAT) {
389  if (Prop != NULL) {
390  Type->grid_loc_def[i].repeat = my_atoi(Prop);
391  ezxml_set_attr(Cur, "repeat", NULL);
392  }
393  } else if (Prop != NULL) {
394  vpr_printf(TIO_MESSAGE_ERROR,
395  "[LINE %d] grid location property 'repeat' valid for grid location type 'col' only.\n",
396  Cur->line);
397  exit(1);
398  }
399  Prop = FindProperty(Cur, "pos", FALSE);
400  if (Type->grid_loc_def[i].grid_loc_type == COL_REL) {
401  if (Prop == NULL) {
402  vpr_printf(TIO_MESSAGE_ERROR,
403  "[LINE %d] grid location property 'pos' must be specified for grid location type 'rel'.\n",
404  Cur->line);
405  exit(1);
406  }
407  Type->grid_loc_def[i].col_rel = (float) atof(Prop);
408  ezxml_set_attr(Cur, "pos", NULL);
409  } else if (Prop != NULL) {
410  vpr_printf(TIO_MESSAGE_ERROR,
411  "[LINE %d] grid location property 'pos' valid for grid location type 'rel' only.\n",
412  Cur->line);
413  exit(1);
414  }
415 
416  Type->grid_loc_def[i].priority = GetIntProperty(Cur, "priority", FALSE,
417  1);
418 
419  Prev = Cur;
420  Cur = Cur->next;
421  FreeNode(Prev);
422  i++;
423  }
424 }
425 
427  t_pin_to_pin_annotation *annotation) {
428  int i = 0;
429  const char *Prop;
430 
431  if (FindProperty(Parent, "max", FALSE)) {
432  i++;
433  }
434  if (FindProperty(Parent, "min", FALSE)) {
435  i++;
436  }
437  if (FindProperty(Parent, "type", FALSE)) {
438  i++;
439  }
440  if (FindProperty(Parent, "value", FALSE)) {
441  i++;
442  }
443  if (0 == strcmp(Parent->name, "C_constant")
444  || 0 == strcmp(Parent->name, "C_matrix")
445  || 0 == strcmp(Parent->name, "pack_pattern")) {
446  i = 1;
447  }
448 
449  annotation->num_value_prop_pairs = i;
450  annotation->prop = (int*) my_calloc(i, sizeof(int));
451  annotation->value = (char**) my_calloc(i, sizeof(char *));
452 
453  /* Todo: This is slow, I should use a case lookup */
454  i = 0;
455  if (0 == strcmp(Parent->name, "delay_constant")) {
456  annotation->type = E_ANNOT_PIN_TO_PIN_DELAY;
457  annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
458  Prop = FindProperty(Parent, "max", FALSE);
459  if (Prop) {
460  annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_MAX;
461  annotation->value[i] = my_strdup(Prop);
462  ezxml_set_attr(Parent, "max", NULL);
463  i++;
464  }
465  Prop = FindProperty(Parent, "min", FALSE);
466  if (Prop) {
467  annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_MIN;
468  annotation->value[i] = my_strdup(Prop);
469  ezxml_set_attr(Parent, "min", NULL);
470  i++;
471  }
472  annotation->line_num = Parent->line;
473  Prop = FindProperty(Parent, "in_port", TRUE);
474  annotation->input_pins = my_strdup(Prop);
475  ezxml_set_attr(Parent, "in_port", NULL);
476  Prop = FindProperty(Parent, "out_port", TRUE);
477  annotation->output_pins = my_strdup(Prop);
478  ezxml_set_attr(Parent, "out_port", NULL);
479  } else if (0 == strcmp(Parent->name, "delay_matrix")) {
480  annotation->type = E_ANNOT_PIN_TO_PIN_DELAY;
481  annotation->format = E_ANNOT_PIN_TO_PIN_MATRIX;
482  Prop = FindProperty(Parent, "type", TRUE);
483  annotation->value[i] = my_strdup(Parent->txt);
484  ezxml_set_txt(Parent, "");
485  if (0 == strcmp(Prop, "max")) {
486  annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_MAX;
487  } else {
488  assert(0 == strcmp(Prop, "min"));
489  annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_MIN;
490  }
491  ezxml_set_attr(Parent, "type", NULL);
492  i++;
493  Prop = FindProperty(Parent, "in_port", TRUE);
494  annotation->input_pins = my_strdup(Prop);
495  ezxml_set_attr(Parent, "in_port", NULL);
496  Prop = FindProperty(Parent, "out_port", TRUE);
497  annotation->output_pins = my_strdup(Prop);
498  ezxml_set_attr(Parent, "out_port", NULL);
499  } else if (0 == strcmp(Parent->name, "C_constant")) {
500  annotation->type = E_ANNOT_PIN_TO_PIN_CAPACITANCE;
501  annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
502  Prop = FindProperty(Parent, "C", TRUE);
503  annotation->value[i] = my_strdup(Prop);
504  ezxml_set_attr(Parent, "C", NULL);
505  annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_CAPACITANCE_C;
506  i++;
507 
508  Prop = FindProperty(Parent, "in_port", FALSE);
509  annotation->input_pins = my_strdup(Prop);
510  ezxml_set_attr(Parent, "in_port", NULL);
511  Prop = FindProperty(Parent, "out_port", FALSE);
512  annotation->output_pins = my_strdup(Prop);
513  ezxml_set_attr(Parent, "out_port", NULL);
514  assert(
515  annotation->output_pins != NULL || annotation->input_pins != NULL);
516  } else if (0 == strcmp(Parent->name, "C_matrix")) {
517  annotation->type = E_ANNOT_PIN_TO_PIN_CAPACITANCE;
518  annotation->format = E_ANNOT_PIN_TO_PIN_MATRIX;
519  annotation->value[i] = my_strdup(Parent->txt);
520  ezxml_set_txt(Parent, "");
521  annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_CAPACITANCE_C;
522  i++;
523  Prop = FindProperty(Parent, "in_port", FALSE);
524  annotation->input_pins = my_strdup(Prop);
525  ezxml_set_attr(Parent, "in_port", NULL);
526  Prop = FindProperty(Parent, "out_port", FALSE);
527  annotation->output_pins = my_strdup(Prop);
528  ezxml_set_attr(Parent, "out_port", NULL);
529  assert(
530  annotation->output_pins != NULL || annotation->input_pins != NULL);
531  } else if (0 == strcmp(Parent->name, "T_setup")) {
532  annotation->type = E_ANNOT_PIN_TO_PIN_DELAY;
533  annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
534  Prop = FindProperty(Parent, "value", TRUE);
535  annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_TSETUP;
536  annotation->value[i] = my_strdup(Prop);
537  ezxml_set_attr(Parent, "value", NULL);
538  i++;
539  Prop = FindProperty(Parent, "port", TRUE);
540  annotation->input_pins = my_strdup(Prop);
541  ezxml_set_attr(Parent, "port", NULL);
542  Prop = FindProperty(Parent, "clock", TRUE);
543  annotation->clock = my_strdup(Prop);
544  ezxml_set_attr(Parent, "clock", NULL);
545  } else if (0 == strcmp(Parent->name, "T_clock_to_Q")) {
546  annotation->type = E_ANNOT_PIN_TO_PIN_DELAY;
547  annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
548  Prop = FindProperty(Parent, "max", FALSE);
549  if (Prop) {
550  annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_CLOCK_TO_Q_MAX;
551  annotation->value[i] = my_strdup(Prop);
552  ezxml_set_attr(Parent, "max", NULL);
553  i++;
554  }
555  Prop = FindProperty(Parent, "min", FALSE);
556  if (Prop) {
557  annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_CLOCK_TO_Q_MIN;
558  annotation->value[i] = my_strdup(Prop);
559  ezxml_set_attr(Parent, "min", NULL);
560  i++;
561  }
562 
563  Prop = FindProperty(Parent, "port", TRUE);
564  annotation->input_pins = my_strdup(Prop);
565  ezxml_set_attr(Parent, "port", NULL);
566  Prop = FindProperty(Parent, "clock", TRUE);
567  annotation->clock = my_strdup(Prop);
568  ezxml_set_attr(Parent, "clock", NULL);
569  } else if (0 == strcmp(Parent->name, "T_hold")) {
570  annotation->type = E_ANNOT_PIN_TO_PIN_DELAY;
571  annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
572  Prop = FindProperty(Parent, "value", TRUE);
573  annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_THOLD;
574  annotation->value[i] = my_strdup(Prop);
575  ezxml_set_attr(Parent, "value", NULL);
576  i++;
577 
578  Prop = FindProperty(Parent, "port", TRUE);
579  annotation->input_pins = my_strdup(Prop);
580  ezxml_set_attr(Parent, "port", NULL);
581  Prop = FindProperty(Parent, "clock", TRUE);
582  annotation->clock = my_strdup(Prop);
583  ezxml_set_attr(Parent, "clock", NULL);
584  } else if (0 == strcmp(Parent->name, "pack_pattern")) {
586  annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
587  Prop = FindProperty(Parent, "name", TRUE);
588  annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_PACK_PATTERN_NAME;
589  annotation->value[i] = my_strdup(Prop);
590  ezxml_set_attr(Parent, "name", NULL);
591  i++;
592 
593  Prop = FindProperty(Parent, "in_port", TRUE);
594  annotation->input_pins = my_strdup(Prop);
595  ezxml_set_attr(Parent, "in_port", NULL);
596  Prop = FindProperty(Parent, "out_port", TRUE);
597  annotation->output_pins = my_strdup(Prop);
598  ezxml_set_attr(Parent, "out_port", NULL);
599  } else {
600  vpr_printf(TIO_MESSAGE_ERROR,
601  "[LINE %d] Unknown port type %s in %s in %s", Parent->line,
602  Parent->name, Parent->parent->name,
603  Parent->parent->parent->name);
604  exit(1);
605  }
606  assert(i == annotation->num_value_prop_pairs);
607 }
608 
609 static t_port * findPortByName(const char * name, t_pb_type * pb_type,
610  int * high_index, int * low_index) {
611  t_port * port;
612  int i;
613  unsigned int high;
614  unsigned int low;
615  unsigned int bracket_pos;
616  unsigned int colon_pos;
617 
618  bracket_pos = strcspn(name, "[");
619 
620  /* Find port by name */
621  port = NULL;
622  for (i = 0; i < pb_type->num_ports; i++) {
623  char * compare_to = pb_type->ports[i].name;
624 
625  if (strlen(compare_to) == bracket_pos
626  && strncmp(name, compare_to, bracket_pos)==0) {
627  port = &pb_type->ports[i];
628  break;
629  }
630  }
631  if (i >= pb_type->num_ports) {
632  return NULL;
633  }
634 
635  /* Get indices */
636  if (strlen(name) > bracket_pos) {
637  high = atoi(&name[bracket_pos + 1]);
638 
639  colon_pos = strcspn(name, ":");
640 
641  if (colon_pos < strlen(name)) {
642  low = atoi(&name[colon_pos + 1]);
643  } else {
644  low = high;
645  }
646  } else {
647  high = port->num_pins - 1;
648  low = 0;
649  }
650 
651  if (high_index && low_index) {
652  *high_index = high;
653  *low_index = low;
654  }
655 
656  return port;
657 }
658 
659 static void ProcessPb_TypePowerPinToggle(ezxml_t parent, t_pb_type * pb_type) {
660  ezxml_t cur, prev;
661  const char * prop;
662  t_port * port;
663  int high, low;
664 
665  cur = FindFirstElement(parent, "port", FALSE);
666  while (cur) {
667  prop = FindProperty(cur, "name", TRUE);
668 
669  port = findPortByName(prop, pb_type, &high, &low);
670  if (!port) {
671  vpr_printf(TIO_MESSAGE_ERROR,
672  "Could not find port '%s' needed for energy per toggle.",
673  prop);
674  return;
675  }
676  if (high != port->num_pins - 1 || low != 0) {
677  vpr_printf(TIO_MESSAGE_ERROR,
678  "Pin-toggle does not support pin indices (%s)", prop);
679  }
680 
681  if (port->port_power->pin_toggle_initialized) {
682  vpr_printf(TIO_MESSAGE_ERROR,
683  "Duplicate pin-toggle energy for port '%s'", port->name);
684  }
686  ezxml_set_attr(cur, "name", NULL);
687 
688  /* Get energy per toggle */
690  "energy_per_toggle", TRUE, 0.);
691 
692  /* Get scaled by factor */
693  boolean reverse_scaled = FALSE;
694  prop = FindProperty(cur, "scaled_by_static_prob", FALSE);
695  if (!prop) {
696  prop = FindProperty(cur, "scaled_by_static_prob_n", FALSE);
697  if (prop) {
698  reverse_scaled = TRUE;
699  }
700  }
701 
702  if (prop) {
703  port->port_power->scaled_by_port = findPortByName(prop, pb_type,
704  &high, &low);
705  if (high != low) {
706  vpr_printf(TIO_MESSAGE_ERROR,
707  "Pin-toggle 'scaled_by_static_prob' must be a single pin (%s)",
708  prop);
709  return;
710  }
711  port->port_power->scaled_by_port_pin_idx = high;
712  port->port_power->reverse_scaled = reverse_scaled;
713  }
714  ezxml_set_attr(cur, "scaled_by_static_prob", NULL);
715  ezxml_set_attr(cur, "scaled_by_static_prob_n", NULL);
716 
717  prev = cur;
718  cur = cur->next;
719  FreeNode(prev);
720  }
721 }
722 
723 static void ProcessPb_TypePower(ezxml_t Parent, t_pb_type * pb_type) {
724  ezxml_t cur, child;
725  boolean require_dynamic_absolute = FALSE;
726  boolean require_static_absolute = FALSE;
727  boolean require_dynamic_C_internal = FALSE;
728 
729  cur = FindFirstElement(Parent, "power", FALSE);
730  if (!cur) {
731  return;
732  }
733 
734  switch (pb_type->pb_type_power->estimation_method) {
736  ProcessPb_TypePowerPinToggle(cur, pb_type);
737  require_static_absolute = TRUE;
738  break;
740  require_dynamic_C_internal = TRUE;
741  require_static_absolute = TRUE;
742  break;
744  require_dynamic_absolute = TRUE;
745  require_static_absolute = TRUE;
746  break;
747  default:
748  break;
749  }
750 
751  if (require_static_absolute) {
752  child = FindElement(cur, "static_power", TRUE);
754  GetFloatProperty(child, "power_per_instance", TRUE, 0.);
755  FreeNode(child);
756  }
757 
758  if (require_dynamic_absolute) {
759  child = FindElement(cur, "dynamic_power", TRUE);
761  GetFloatProperty(child, "power_per_instance", TRUE, 0.);
762  FreeNode(child);
763  }
764 
765  if (require_dynamic_C_internal) {
766  child = FindElement(cur, "dynamic_power", TRUE);
767  pb_type->pb_type_power->C_internal = GetFloatProperty(child,
768  "C_internal", TRUE, 0.);
769  FreeNode(child);
770  }
771 
772  if (cur) {
773  FreeNode(cur);
774  }
775 
776 }
777 
778 static void ProcessPb_TypePowerEstMethod(ezxml_t Parent, t_pb_type * pb_type) {
779  ezxml_t cur;
780  const char * prop;
781 
782  e_power_estimation_method parent_power_method;
783 
784  prop = NULL;
785 
786  cur = FindFirstElement(Parent, "power", FALSE);
787  if (cur) {
788  prop = FindProperty(cur, "method", FALSE);
789  }
790 
791  if (pb_type->parent_mode && pb_type->parent_mode->parent_pb_type) {
792  parent_power_method =
794  } else {
795  parent_power_method = POWER_METHOD_AUTO_SIZES;
796  }
797 
798  if (!prop) {
799  /* default method is auto-size */
801  parent_power_method);
802  } else if (strcmp(prop, "auto-size") == 0) {
804  } else if (strcmp(prop, "specify-size") == 0) {
806  } else if (strcmp(prop, "pin-toggle") == 0) {
808  } else if (strcmp(prop, "c-internal") == 0) {
810  } else if (strcmp(prop, "absolute") == 0) {
812  } else if (strcmp(prop, "ignore") == 0) {
814  } else if (strcmp(prop, "sum-of-children") == 0) {
816  } else {
817  vpr_printf(TIO_MESSAGE_ERROR,
818  "Invalid power estimation method for pb_type '%s'",
819  pb_type->name);
820  }
821 
822  if (prop) {
823  ezxml_set_attr(cur, "method", NULL);
824  }
825 
826 }
827 
828 /* Takes in a pb_type, allocates and loads data for it and recurses downwards */
829 static void ProcessPb_Type(INOUTP ezxml_t Parent, t_pb_type * pb_type,
830  t_mode * mode) {
831  int num_ports, i, j, k, num_annotations;
832  const char *Prop;
833  ezxml_t Cur, Prev;
834  char* class_name;
835 
836  pb_type->parent_mode = mode;
837  if (mode != NULL && mode->parent_pb_type != NULL) {
838  pb_type->depth = mode->parent_pb_type->depth + 1;
839  Prop = FindProperty(Parent, "name", TRUE);
840  pb_type->name = my_strdup(Prop);
841  ezxml_set_attr(Parent, "name", NULL);
842  } else {
843  pb_type->depth = 0;
844  /* same name as type */
845  }
846 
847  Prop = FindProperty(Parent, "blif_model", FALSE);
848  pb_type->blif_model = my_strdup(Prop);
849  ezxml_set_attr(Parent, "blif_model", NULL);
850 
851  pb_type->class_type = UNKNOWN_CLASS;
852  Prop = FindProperty(Parent, "class", FALSE);
853  class_name = my_strdup(Prop);
854 
855  if (class_name) {
856  ezxml_set_attr(Parent, "class", NULL);
857  if (0 == strcmp(class_name, "lut")) {
858  pb_type->class_type = LUT_CLASS;
859  } else if (0 == strcmp(class_name, "flipflop")) {
860  pb_type->class_type = LATCH_CLASS;
861  } else if (0 == strcmp(class_name, "memory")) {
862  pb_type->class_type = MEMORY_CLASS;
863  } else {
864  vpr_printf(TIO_MESSAGE_ERROR,
865  "[LINE %d] Unknown class %s in pb_type %s\n", Parent->line,
866  class_name, pb_type->name);
867  exit(1);
868  }
869  free(class_name);
870  }
871 
872  if (mode == NULL) {
873  pb_type->num_pb = 1;
874  } else {
875  pb_type->num_pb = GetIntProperty(Parent, "num_pb", TRUE, 0);
876  }
877 
878  assert(pb_type->num_pb > 0);
879  num_ports = 0;
880  num_ports += CountChildren(Parent, "input", 0);
881  num_ports += CountChildren(Parent, "output", 0);
882  num_ports += CountChildren(Parent, "clock", 0);
883  pb_type->ports = (t_port*) my_calloc(num_ports, sizeof(t_port));
884  pb_type->num_ports = num_ports;
885 
886  /* Initialize Power Structure */
887  pb_type->pb_type_power = (t_pb_type_power*) my_calloc(1,
888  sizeof(t_pb_type_power));
889  ProcessPb_TypePowerEstMethod(Parent, pb_type);
890 
891  /* process ports */
892  j = 0;
893  for (i = 0; i < 3; i++) {
894  if (i == 0) {
895  k = 0;
896  Cur = FindFirstElement(Parent, "input", FALSE);
897  } else if (i == 1) {
898  k = 0;
899  Cur = FindFirstElement(Parent, "output", FALSE);
900  } else {
901  k = 0;
902  Cur = FindFirstElement(Parent, "clock", FALSE);
903  }
904  while (Cur != NULL) {
905  ProcessPb_TypePort(Cur, &pb_type->ports[j],
906  pb_type->pb_type_power->estimation_method);
907  pb_type->ports[j].parent_pb_type = pb_type;
908  pb_type->ports[j].index = j;
909  pb_type->ports[j].port_index_by_type = k;
910 
911  /* get next iteration */
912  Prev = Cur;
913  Cur = Cur->next;
914  j++;
915  k++;
916  FreeNode(Prev);
917  }
918  }
919  assert(j == num_ports);
920 
921  /* Count stats on the number of each type of pin */
922  pb_type->num_clock_pins = pb_type->num_input_pins =
923  pb_type->num_output_pins = 0;
924  for (i = 0; i < pb_type->num_ports; i++) {
925  if (pb_type->ports[i].type == IN_PORT
926  && pb_type->ports[i].is_clock == FALSE) {
927  pb_type->num_input_pins += pb_type->ports[i].num_pins;
928  } else if (pb_type->ports[i].type == OUT_PORT) {
929  assert(pb_type->ports[i].is_clock == FALSE);
930  pb_type->num_output_pins += pb_type->ports[i].num_pins;
931  } else {
932  assert(
933  pb_type->ports[i].is_clock && pb_type->ports[i].type == IN_PORT);
934  pb_type->num_clock_pins += pb_type->ports[i].num_pins;
935  }
936  }
937 
938  /* set max_internal_delay if exist */
939  pb_type->max_internal_delay = UNDEFINED;
940  Cur = FindElement(Parent, "max_internal_delay", FALSE);
941  if (Cur) {
942  pb_type->max_internal_delay = GetFloatProperty(Cur, "value", TRUE,
943  UNDEFINED);
944  FreeNode(Cur);
945  }
946 
947  pb_type->annotations = NULL;
948  pb_type->num_annotations = 0;
949  i = 0;
950  /* Determine if this is a leaf or container pb_type */
951  if (pb_type->blif_model != NULL) {
952  /* Process delay and capacitance annotations */
953  num_annotations = 0;
954  num_annotations += CountChildren(Parent, "delay_constant", 0);
955  num_annotations += CountChildren(Parent, "delay_matrix", 0);
956  num_annotations += CountChildren(Parent, "C_constant", 0);
957  num_annotations += CountChildren(Parent, "C_matrix", 0);
958  num_annotations += CountChildren(Parent, "T_setup", 0);
959  num_annotations += CountChildren(Parent, "T_clock_to_Q", 0);
960  num_annotations += CountChildren(Parent, "T_hold", 0);
961 
963  num_annotations, sizeof(t_pin_to_pin_annotation));
964  pb_type->num_annotations = num_annotations;
965 
966  j = 0;
967  Cur = NULL;
968  for (i = 0; i < 7; i++) {
969  if (i == 0) {
970  Cur = FindFirstElement(Parent, "delay_constant", FALSE);
971  } else if (i == 1) {
972  Cur = FindFirstElement(Parent, "delay_matrix", FALSE);
973  } else if (i == 2) {
974  Cur = FindFirstElement(Parent, "C_constant", FALSE);
975  } else if (i == 3) {
976  Cur = FindFirstElement(Parent, "C_matrix", FALSE);
977  } else if (i == 4) {
978  Cur = FindFirstElement(Parent, "T_setup", FALSE);
979  } else if (i == 5) {
980  Cur = FindFirstElement(Parent, "T_clock_to_Q", FALSE);
981  } else if (i == 6) {
982  Cur = FindFirstElement(Parent, "T_hold", FALSE);
983  }
984  while (Cur != NULL) {
985  ProcessPinToPinAnnotations(Cur, &pb_type->annotations[j]);
986 
987  /* get next iteration */
988  Prev = Cur;
989  Cur = Cur->next;
990  j++;
991  FreeNode(Prev);
992  }
993  }
994  assert(j == num_annotations);
995 
996  /* leaf pb_type, if special known class, then read class lib otherwise treat as primitive */
997  if (pb_type->class_type == LUT_CLASS) {
998  ProcessLutClass(pb_type);
999  } else if (pb_type->class_type == MEMORY_CLASS) {
1000  ProcessMemoryClass(pb_type);
1001  } else {
1002  /* other leaf pb_type do not have modes */
1003  pb_type->num_modes = 0;
1004  assert(CountChildren(Parent, "mode", 0) == 0);
1005  }
1006  } else {
1007  boolean default_leakage_mode = FALSE;
1008 
1009  /* container pb_type, process modes */
1010  assert(pb_type->class_type == UNKNOWN_CLASS);
1011  pb_type->num_modes = CountChildren(Parent, "mode", 0);
1012  pb_type->pb_type_power->leakage_default_mode = 0;
1013 
1014  if (pb_type->num_modes == 0) {
1015  /* The pb_type operates in an implied one mode */
1016  pb_type->num_modes = 1;
1017  pb_type->modes = (t_mode*) my_calloc(pb_type->num_modes,
1018  sizeof(t_mode));
1019  pb_type->modes[i].parent_pb_type = pb_type;
1020  pb_type->modes[i].index = i;
1021  ProcessMode(Parent, &pb_type->modes[i], &default_leakage_mode);
1022  i++;
1023  } else {
1024  pb_type->modes = (t_mode*) my_calloc(pb_type->num_modes,
1025  sizeof(t_mode));
1026 
1027  Cur = FindFirstElement(Parent, "mode", TRUE);
1028  while (Cur != NULL) {
1029  if (0 == strcmp(Cur->name, "mode")) {
1030  pb_type->modes[i].parent_pb_type = pb_type;
1031  pb_type->modes[i].index = i;
1032  ProcessMode(Cur, &pb_type->modes[i], &default_leakage_mode);
1033  if (default_leakage_mode) {
1034  pb_type->pb_type_power->leakage_default_mode = i;
1035  }
1036 
1037  /* get next iteration */
1038  Prev = Cur;
1039  Cur = Cur->next;
1040  i++;
1041  FreeNode(Prev);
1042  }
1043  }
1044  }
1045  assert(i == pb_type->num_modes);
1046  }
1047 
1048  ProcessPb_TypePower(Parent, pb_type);
1049 
1050 }
1051 
1052 static void ProcessPb_TypePort_Power(ezxml_t Parent, t_port * port,
1053  e_power_estimation_method power_method) {
1054  ezxml_t cur;
1055  const char * prop;
1056  bool wire_defined = FALSE;
1057 
1058  port->port_power = (t_port_power*) my_calloc(1, sizeof(t_port_power));
1059 
1060  //Defaults
1061  if (power_method == POWER_METHOD_AUTO_SIZES) {
1064  } else if (power_method == POWER_METHOD_SPECIFY_SIZES) {
1067  }
1068 
1069  cur = FindElement(Parent, "power", FALSE);
1070 
1071  if (cur) {
1072  /* Wire capacitance */
1073 
1074  /* Absolute C provided */
1075  prop = FindProperty(cur, "wire_capacitance", FALSE);
1076  if (prop) {
1077  if (!(power_method == POWER_METHOD_AUTO_SIZES
1078  || power_method == POWER_METHOD_SPECIFY_SIZES)) {
1079  vpr_printf(TIO_MESSAGE_ERROR,
1080  "Wire capacitance defined for port '%s'. This is an invalid option for the parent pb_type '%s' power estimation method.",
1081  port->name, port->parent_pb_type->name);
1082  } else {
1083  wire_defined = TRUE;
1085  port->port_power->wire.C = (float) atof(prop);
1086  }
1087  ezxml_set_attr(cur, "wire_capacitance", NULL);
1088  }
1089 
1090  /* Wire absolute length provided */
1091  prop = FindProperty(cur, "wire_length", FALSE);
1092  if (prop) {
1093  if (!(power_method == POWER_METHOD_AUTO_SIZES
1094  || power_method == POWER_METHOD_SPECIFY_SIZES)) {
1095  vpr_printf(TIO_MESSAGE_ERROR,
1096  "Wire length defined for port '%s'. This is an invalid option for the parent pb_type '%s' power estimation method.",
1097  port->name, port->parent_pb_type->name);
1098  } else if (wire_defined) {
1099  vpr_printf(TIO_MESSAGE_ERROR,
1100  "Multiple wire properties defined for port '%s', pb_type '%s'.",
1101  port->name, port->parent_pb_type->name);
1102  } else if (strcmp(prop, "auto") == 0) {
1103  wire_defined = TRUE;
1105  } else {
1106  wire_defined = TRUE;
1108  port->port_power->wire.absolute_length = (float) atof(prop);
1109  }
1110  ezxml_set_attr(cur, "wire_length", NULL);
1111  }
1112 
1113  /* Wire relative length provided */
1114  prop = FindProperty(cur, "wire_relative_length", FALSE);
1115  if (prop) {
1116  if (!(power_method == POWER_METHOD_AUTO_SIZES
1117  || power_method == POWER_METHOD_SPECIFY_SIZES)) {
1118  vpr_printf(TIO_MESSAGE_ERROR,
1119  "Wire relative length defined for port '%s'. This is an invalid option for the parent pb_type '%s' power estimation method.",
1120  port->name, port->parent_pb_type->name);
1121  } else if (wire_defined) {
1122  vpr_printf(TIO_MESSAGE_ERROR,
1123  "Multiple wire properties defined for port '%s', pb_type '%s'.",
1124  port->name, port->parent_pb_type->name);
1125  } else {
1126  wire_defined = TRUE;
1128  port->port_power->wire.relative_length = (float) atof(prop);
1129  }
1130  ezxml_set_attr(cur, "wire_relative_length", NULL);
1131  }
1132 
1133  /* Buffer Size */
1134  prop = FindProperty(cur, "buffer_size", FALSE);
1135  if (prop) {
1136  if (!(power_method == POWER_METHOD_AUTO_SIZES
1137  || power_method == POWER_METHOD_SPECIFY_SIZES)) {
1138  vpr_printf(TIO_MESSAGE_ERROR,
1139  "Buffer size defined for port '%s'. This is an invalid option for the parent pb_type '%s' power estimation method.",
1140  port->name, port->parent_pb_type->name);
1141  } else if (strcmp(prop, "auto") == 0) {
1143  } else {
1145  port->port_power->buffer_size = (float) atof(prop);
1146  }
1147  ezxml_set_attr(cur, "buffer_size", NULL);
1148  }
1149 
1150  FreeNode(cur);
1151  }
1152 }
1153 
1154 static void ProcessPb_TypePort(INOUTP ezxml_t Parent, t_port * port,
1155  e_power_estimation_method power_method) {
1156  const char *Prop;
1157  Prop = FindProperty(Parent, "name", TRUE);
1158  port->name = my_strdup(Prop);
1159  ezxml_set_attr(Parent, "name", NULL);
1160 
1161  Prop = FindProperty(Parent, "port_class", FALSE);
1162  port->port_class = my_strdup(Prop);
1163  ezxml_set_attr(Parent, "port_class", NULL);
1164 
1165  Prop = FindProperty(Parent, "chain", FALSE);
1166  port->chain_name = my_strdup(Prop);
1167  ezxml_set_attr(Parent, "chain", NULL);
1168 
1169  port->equivalent = GetBooleanProperty(Parent, "equivalent", FALSE, FALSE);
1170  port->num_pins = GetIntProperty(Parent, "num_pins", TRUE, 0);
1171  port->is_non_clock_global = GetBooleanProperty(Parent,
1172  "is_non_clock_global", FALSE, FALSE);
1173 
1174  if (0 == strcmp(Parent->name, "input")) {
1175  port->type = IN_PORT;
1176  port->is_clock = FALSE;
1177  } else if (0 == strcmp(Parent->name, "output")) {
1178  port->type = OUT_PORT;
1179  port->is_clock = FALSE;
1180  } else if (0 == strcmp(Parent->name, "clock")) {
1181  port->type = IN_PORT;
1182  port->is_clock = TRUE;
1183  if (port->is_non_clock_global == TRUE) {
1184  vpr_printf(TIO_MESSAGE_ERROR,
1185  "[LINE %d] Port %s cannot be both a clock and a non-clock simultaneously\n",
1186  Parent->line, Parent->name);
1187  }
1188  } else {
1189  vpr_printf(TIO_MESSAGE_ERROR, "[LINE %d] Unknown port type %s",
1190  Parent->line, Parent->name);
1191  exit(1);
1192  }
1193 
1194  ProcessPb_TypePort_Power(Parent, port, power_method);
1195 }
1196 
1197 static void ProcessInterconnect(INOUTP ezxml_t Parent, t_mode * mode) {
1198  int num_interconnect = 0;
1199  int i, j, k, L_index, num_annotations;
1200  const char *Prop;
1201  ezxml_t Cur, Prev;
1202  ezxml_t Cur2, Prev2;
1203 
1204  num_interconnect += CountChildren(Parent, "complete", 0);
1205  num_interconnect += CountChildren(Parent, "direct", 0);
1206  num_interconnect += CountChildren(Parent, "mux", 0);
1207 
1208  mode->num_interconnect = num_interconnect;
1209  mode->interconnect = (t_interconnect*) my_calloc(num_interconnect,
1210  sizeof(t_interconnect));
1211 
1212  i = 0;
1213  for (L_index = 0; L_index < 3; L_index++) {
1214  if (L_index == 0) {
1215  Cur = FindFirstElement(Parent, "complete", FALSE);
1216  } else if (L_index == 1) {
1217  Cur = FindFirstElement(Parent, "direct", FALSE);
1218  } else {
1219  Cur = FindFirstElement(Parent, "mux", FALSE);
1220  }
1221  while (Cur != NULL) {
1222  if (0 == strcmp(Cur->name, "complete")) {
1223  mode->interconnect[i].type = COMPLETE_INTERC;
1224  } else if (0 == strcmp(Cur->name, "direct")) {
1225  mode->interconnect[i].type = DIRECT_INTERC;
1226  } else {
1227  assert(0 == strcmp(Cur->name, "mux"));
1228  mode->interconnect[i].type = MUX_INTERC;
1229  }
1230 
1231  mode->interconnect[i].line_num = Cur->line;
1232 
1233  mode->interconnect[i].parent_mode_index = mode->index;
1234  mode->interconnect[i].parent_mode = mode;
1235 
1236  Prop = FindProperty(Cur, "input", TRUE);
1237  mode->interconnect[i].input_string = my_strdup(Prop);
1238  ezxml_set_attr(Cur, "input", NULL);
1239 
1240  Prop = FindProperty(Cur, "output", TRUE);
1241  mode->interconnect[i].output_string = my_strdup(Prop);
1242  ezxml_set_attr(Cur, "output", NULL);
1243 
1244  Prop = FindProperty(Cur, "name", TRUE);
1245  mode->interconnect[i].name = my_strdup(Prop);
1246  ezxml_set_attr(Cur, "name", NULL);
1247 
1248  /* Process delay and capacitance annotations */
1249  num_annotations = 0;
1250  num_annotations += CountChildren(Cur, "delay_constant", 0);
1251  num_annotations += CountChildren(Cur, "delay_matrix", 0);
1252  num_annotations += CountChildren(Cur, "C_constant", 0);
1253  num_annotations += CountChildren(Cur, "C_matrix", 0);
1254  num_annotations += CountChildren(Cur, "pack_pattern", 0);
1255 
1256  mode->interconnect[i].annotations =
1257  (t_pin_to_pin_annotation*) my_calloc(num_annotations,
1258  sizeof(t_pin_to_pin_annotation));
1259  mode->interconnect[i].num_annotations = num_annotations;
1260 
1261  k = 0;
1262  Cur2 = NULL;
1263  for (j = 0; j < 5; j++) {
1264  if (j == 0) {
1265  Cur2 = FindFirstElement(Cur, "delay_constant", FALSE);
1266  } else if (j == 1) {
1267  Cur2 = FindFirstElement(Cur, "delay_matrix", FALSE);
1268  } else if (j == 2) {
1269  Cur2 = FindFirstElement(Cur, "C_constant", FALSE);
1270  } else if (j == 3) {
1271  Cur2 = FindFirstElement(Cur, "C_matrix", FALSE);
1272  } else if (j == 4) {
1273  Cur2 = FindFirstElement(Cur, "pack_pattern", FALSE);
1274  }
1275  while (Cur2 != NULL) {
1277  &(mode->interconnect[i].annotations[k]));
1278 
1279  /* get next iteration */
1280  Prev2 = Cur2;
1281  Cur2 = Cur2->next;
1282  k++;
1283  FreeNode(Prev2);
1284  }
1285  }
1286  assert(k == num_annotations);
1287 
1288  /* Power */
1289  mode->interconnect[i].interconnect_power =
1291  sizeof(t_interconnect_power));
1293  FALSE;
1294 
1295  //ProcessInterconnectMuxArch(Cur, &mode->interconnect[i]);
1296 
1297  /* get next iteration */
1298  Prev = Cur;
1299  Cur = Cur->next;
1300  FreeNode(Prev);
1301  i++;
1302  }
1303  }
1304 
1305  assert(i == num_interconnect);
1306 }
1307 
1308 static void ProcessMode(INOUTP ezxml_t Parent, t_mode * mode,
1309  boolean * default_leakage_mode) {
1310  int i;
1311  const char *Prop;
1312  ezxml_t Cur, Prev;
1313 
1314  if (0 == strcmp(Parent->name, "pb_type")) {
1315  /* implied mode */
1316  mode->name = my_strdup(mode->parent_pb_type->name);
1317  } else {
1318  Prop = FindProperty(Parent, "name", TRUE);
1319  mode->name = my_strdup(Prop);
1320  ezxml_set_attr(Parent, "name", NULL);
1321  }
1322 
1323  mode->num_pb_type_children = CountChildren(Parent, "pb_type", 0);
1324  if (mode->num_pb_type_children > 0) {
1326  mode->num_pb_type_children, sizeof(t_pb_type));
1327 
1328  i = 0;
1329  Cur = FindFirstElement(Parent, "pb_type", TRUE);
1330  while (Cur != NULL) {
1331  if (0 == strcmp(Cur->name, "pb_type")) {
1332  ProcessPb_Type(Cur, &mode->pb_type_children[i], mode);
1333 
1334  /* get next iteration */
1335  Prev = Cur;
1336  Cur = Cur->next;
1337  i++;
1338  FreeNode(Prev);
1339  }
1340  }
1341  } else {
1342  mode->pb_type_children = NULL;
1343  }
1344 
1345  /* Allocate power structure */
1346  mode->mode_power = (t_mode_power*) my_calloc(1, sizeof(t_mode_power));
1347 
1348  Cur = FindElement(Parent, "interconnect", TRUE);
1349  ProcessInterconnect(Cur, mode);
1350  FreeNode(Cur);
1351 }
1352 
1353 /* Takes in the node ptr for the 'fc_in' and 'fc_out' elements and initializes
1354  * the appropriate fields of type. Unlinks the contents of the nodes. */
1355 static void Process_Fc(ezxml_t Node, t_type_descriptor * Type) {
1356  enum Fc_type def_type_in, def_type_out, ovr_type;
1357  const char *Prop, *Prop2;
1358  char *port_name;
1359  float def_in_val, def_out_val, ovr_val;
1360  int ipin, iclass, end_pin_index, start_pin_index, match_count;
1361  int iport, iport_pin, curr_pin, port_found;
1362  ezxml_t Child, Junk;
1363 
1364  def_type_in = FC_FRAC;
1365  def_type_out = FC_FRAC;
1366  def_in_val = OPEN;
1367  def_out_val = OPEN;
1368 
1369  Type->is_Fc_frac = (boolean *) my_malloc(Type->num_pins * sizeof(boolean));
1370  Type->is_Fc_full_flex = (boolean *) my_malloc(
1371  Type->num_pins * sizeof(boolean));
1372  Type->Fc = (float *) my_malloc(Type->num_pins * sizeof(float));
1373 
1374  /* Load the default fc_in, if specified */
1375  Prop = FindProperty(Node, "default_in_type", FALSE);
1376  if (Prop != NULL) {
1377  if (0 == strcmp(Prop, "abs")) {
1378  def_type_in = FC_ABS;
1379  } else if (0 == strcmp(Prop, "frac")) {
1380  def_type_in = FC_FRAC;
1381  } else if (0 == strcmp(Prop, "full")) {
1382  def_type_in = FC_FULL;
1383  } else {
1384  vpr_printf(TIO_MESSAGE_ERROR,
1385  "[LINE %d] Invalid type '%s' for Fc. Only abs, frac "
1386  "and full are allowed.\n", Node->line, Prop);
1387  exit(1);
1388  }
1389  switch (def_type_in) {
1390  case FC_FULL:
1391  def_in_val = 0.0;
1392  break;
1393  case FC_ABS:
1394  case FC_FRAC:
1395  Prop2 = FindProperty(Node, "default_in_val", TRUE);
1396  def_in_val = (float) atof(Prop2);
1397  ezxml_set_attr(Node, "default_in_val", NULL);
1398  break;
1399  default:
1400  def_in_val = -1;
1401  }
1402  /* Release the property */
1403  ezxml_set_attr(Node, "default_in_type", NULL);
1404  }
1405 
1406  /* Load the default fc_out, if specified */
1407  Prop = FindProperty(Node, "default_out_type", FALSE);
1408  if (Prop != NULL) {
1409  if (0 == strcmp(Prop, "abs")) {
1410  def_type_out = FC_ABS;
1411  } else if (0 == strcmp(Prop, "frac")) {
1412  def_type_out = FC_FRAC;
1413  } else if (0 == strcmp(Prop, "full")) {
1414  def_type_out = FC_FULL;
1415  } else {
1416  vpr_printf(TIO_MESSAGE_ERROR,
1417  "[LINE %d] Invalid type '%s' for Fc. Only abs, frac "
1418  "and full are allowed.\n", Node->line, Prop);
1419  exit(1);
1420  }
1421  switch (def_type_out) {
1422  case FC_FULL:
1423  def_out_val = 0.0;
1424  break;
1425  case FC_ABS:
1426  case FC_FRAC:
1427  Prop2 = FindProperty(Node, "default_out_val", TRUE);
1428  def_out_val = (float) atof(Prop2);
1429  ezxml_set_attr(Node, "default_out_val", NULL);
1430  break;
1431  default:
1432  def_out_val = -1;
1433  }
1434  /* Release the property */
1435  ezxml_set_attr(Node, "default_out_type", NULL);
1436  }
1437 
1438  /* Go though all the pins in Type, assign def_in_val and def_out_val *
1439  * to entries in Type->Fc array corresponding to input pins and output *
1440  * pins. Also sets up the type of fc of the pin in the boolean arrays */
1441  for (ipin = 0; ipin < Type->num_pins; ipin++) {
1442  iclass = Type->pin_class[ipin];
1443  if (Type->class_inf[iclass].type == DRIVER) {
1444  Type->Fc[ipin] = def_out_val;
1445  Type->is_Fc_full_flex[ipin] =
1446  (def_type_out == FC_FULL) ? TRUE : FALSE;
1447  Type->is_Fc_frac[ipin] = (def_type_out == FC_FRAC) ? TRUE : FALSE;
1448  } else if (Type->class_inf[iclass].type == RECEIVER) {
1449  Type->Fc[ipin] = def_in_val;
1450  Type->is_Fc_full_flex[ipin] =
1451  (def_type_in == FC_FULL) ? TRUE : FALSE;
1452  Type->is_Fc_frac[ipin] = (def_type_in == FC_FRAC) ? TRUE : FALSE;
1453  } else {
1454  Type->Fc[ipin] = -1;
1455  Type->is_Fc_full_flex[ipin] = FALSE;
1456  Type->is_Fc_frac[ipin] = FALSE;
1457  }
1458  }
1459 
1460  /* Now, check for pin-based fc override - look for pin child. */
1461  Child = ezxml_child(Node, "pin");
1462  while (Child != NULL) {
1463  /* Get all the properties of the child first */
1464  Prop = FindProperty(Child, "name", TRUE);
1465  if (Prop == NULL) {
1466  vpr_printf(TIO_MESSAGE_ERROR, "[LINE %d] Pin child with no name "
1467  "is not allowed.\n", Child->line);
1468  exit(1);
1469  }
1470  ezxml_set_attr(Child, "name", NULL);
1471 
1472  Prop2 = FindProperty(Child, "fc_type", TRUE);
1473  if (Prop2 != NULL) {
1474  if (0 == strcmp(Prop2, "abs")) {
1475  ovr_type = FC_ABS;
1476  } else if (0 == strcmp(Prop2, "frac")) {
1477  ovr_type = FC_FRAC;
1478  } else if (0 == strcmp(Prop2, "full")) {
1479  ovr_type = FC_FULL;
1480  } else {
1481  vpr_printf(TIO_MESSAGE_ERROR,
1482  "[LINE %d] Invalid type '%s' for Fc. Only abs, frac "
1483  "and full are allowed.\n", Child->line, Prop2);
1484  exit(1);
1485  }
1486  switch (ovr_type) {
1487  case FC_FULL:
1488  ovr_val = 0.0;
1489  break;
1490  case FC_ABS:
1491  case FC_FRAC:
1492  Prop2 = FindProperty(Child, "fc_val", TRUE);
1493  if (Prop2 == NULL) {
1494  vpr_printf(TIO_MESSAGE_ERROR,
1495  "[LINE %d] Pin child with no fc_val specified "
1496  "is not allowed.\n", Child->line);
1497  exit(1);
1498  }
1499  ovr_val = (float) atof(Prop2);
1500  ezxml_set_attr(Child, "fc_val", NULL);
1501  break;
1502  default:
1503  ovr_val = -1;
1504  }
1505  /* Release the property */
1506  ezxml_set_attr(Child, "fc_type", NULL);
1507 
1508  port_name = NULL;
1509 
1510  /* Search for the child pin in Type and overwrites the default values */
1511  /* Check whether the name is in the format of "<port_name>" or *
1512  * "<port_name> [start_index:end_index]" by looking for the symbol '[' */
1513  Prop2 = strstr(Prop, "[");
1514  if (Prop2 == NULL) {
1515  /* Format "port_name" , Prop stores the port_name */
1516  end_pin_index = start_pin_index = -1;
1517  } else {
1518  /* Format "port_name [start_index:end_index]" */
1519  match_count = sscanf(Prop, "%s [%d:%d]", port_name,
1520  &end_pin_index, &start_pin_index);
1521  Prop = port_name;
1522  if (match_count != 3
1523  || (match_count != 1 && port_name == NULL)) {
1524  vpr_printf(TIO_MESSAGE_ERROR,
1525  "[LINE %d] Invalid name for pin child, "
1526  "name should be in the format \"port_name\" or "
1527  "\"port_name [end_pin_index:start_pin_index]\", "
1528  " The end_pin_index and start_pin_index can be the same.\n",
1529  Child->line);
1530  exit(1);
1531  }
1532  if (end_pin_index < 0 || start_pin_index < 0) {
1533  vpr_printf(TIO_MESSAGE_ERROR,
1534  "[LINE %d] The pin_index should not "
1535  "be a negative value.\n", Child->line);
1536  exit(1);
1537  }
1538  if (end_pin_index < start_pin_index) {
1539  vpr_printf(TIO_MESSAGE_ERROR,
1540  "[LINE %d] The end_pin_index should "
1541  "be not be less than start_pin_index.\n",
1542  Child->line);
1543  exit(1);
1544  }
1545  }
1546 
1547  /* Find the matching port_name in Type */
1548  /* TODO: Check for pins assigned more than one override fc's - right now assigning the last value specified. */
1549  iport_pin = 0;
1550  port_found = FALSE;
1551  for (iport = 0;
1552  ((iport < Type->pb_type->num_ports) && (port_found == FALSE));
1553  iport++) {
1554  if (strcmp(Prop, Type->pb_type->ports[iport].name) == 0) {
1555  /* This is the port, the start_pin_index and end_pin_index offset starts
1556  * here. The indices are inclusive. */
1557  port_found = TRUE;
1558  if (end_pin_index > Type->pb_type->ports[iport].num_pins) {
1559  vpr_printf(TIO_MESSAGE_ERROR,
1560  "[LINE %d] The end_pin_index for this port: %d "
1561  "cannot be greater than the number of pins in this port: %d.\n",
1562  Child->line, end_pin_index,
1563  Type->pb_type->ports[iport].num_pins);
1564  exit(1);
1565  }
1566 
1567  // The pin indices is not specified - override whole port.
1568  if (end_pin_index == -1 && start_pin_index == -1) {
1569  start_pin_index = 0;
1570 
1571  // Minus one since it is going to be assessed inclusively.
1572  end_pin_index = Type->pb_type->ports[iport].num_pins
1573  - 1;
1574  }
1575 
1576  /* Go through the pins in the port from start_pin_index to end_pin_index
1577  * and overwrite the default fc_val and fc_type with the values parsed in
1578  * from above. */
1579  for (curr_pin = start_pin_index; curr_pin <= end_pin_index;
1580  curr_pin++) {
1581 
1582  // Check whether the value had been overwritten
1583  if (ovr_val != Type->Fc[iport_pin + curr_pin]
1584  || Type->is_Fc_full_flex[iport_pin
1585  + curr_pin]
1586  != (ovr_type == FC_FULL) ? TRUE :
1587  FALSE
1588  || Type->is_Fc_frac[iport_pin + curr_pin]
1589  != (ovr_type == FC_FRAC) ?
1590  TRUE : FALSE) {
1591  Type->Fc[iport_pin + curr_pin] = ovr_val;
1592  Type->is_Fc_full_flex[iport_pin + curr_pin] =
1593  (ovr_type == FC_FULL) ? TRUE : FALSE;
1594  Type->is_Fc_frac[iport_pin + curr_pin] =
1595  (ovr_type == FC_FRAC) ? TRUE : FALSE;
1596 
1597  } else {
1598 
1599  vpr_printf(TIO_MESSAGE_ERROR,
1600  "[LINE %d] Multiple Fc override detected!\n",
1601  Child->line);
1602  exit(1);
1603 
1604  }
1605  }
1606 
1607  } else {
1608  /* This is not the matching port, move the iport_pin index forward. */
1609  iport_pin += Type->pb_type->ports[iport].num_pins;
1610  }
1611  } /* Finish going through all the ports in pb_type looking for the pin child's port. */
1612 
1613  /* The override pin child is not in any of the ports in pb_type. */
1614  if (port_found == FALSE) {
1615  vpr_printf(TIO_MESSAGE_ERROR, "[LINE %d] The port \"%s\" "
1616  "cannot be found.\n", Child->line);
1617  exit(1);
1618  }
1619 
1620  /* End of case where fc_type of pin_child is specified. */
1621  } else {
1622  /* fc_type of pin_child is not specified. Error out. */
1623  vpr_printf(TIO_MESSAGE_ERROR,
1624  "[LINE %d] Pin child with no fc_type specified "
1625  "is not allowed.\n", Child->line);
1626  exit(1);
1627  }
1628 
1629  /* Find next child and frees up the current child. */
1630  Junk = Child;
1631  Child = ezxml_next(Child);
1632  FreeNode(Junk);
1633 
1634  } /* End of processing pin children */
1635 
1636 }
1637 
1638 /* Thie processes attributes of the 'type' tag and then unlinks them */
1640  const char *Prop;
1641 
1642  /* Load type name */
1643  Prop = FindProperty(Node, "name", TRUE);
1644  Type->name = my_strdup(Prop);
1645  ezxml_set_attr(Node, "name", NULL);
1646 
1647  /* Load properties */
1648  Type->capacity = GetIntProperty(Node, "capacity", FALSE, 1); /* TODO: Any block with capacity > 1 that is not I/O has not been tested, must test */
1649  Type->height = GetIntProperty(Node, "height", FALSE, 1);
1650  Type->area = GetFloatProperty(Node, "area", FALSE, UNDEFINED);
1651 
1652  if (atof(Prop) < 0) {
1653  vpr_printf(TIO_MESSAGE_ERROR,
1654  "[LINE %d] Area for type %s must be non-negative\n", Node->line,
1655  Type->name);
1656  exit(1);
1657  }
1658 }
1659 
1660 /* Takes in node pointing to <models> and loads all the
1661  * child type objects. Unlinks the entire <models> node
1662  * when complete. */
1663 static void ProcessModels(INOUTP ezxml_t Node, OUTP struct s_arch *arch) {
1664  const char *Prop;
1665  ezxml_t child;
1666  ezxml_t p;
1667  ezxml_t junk;
1668  ezxml_t junkp;
1669  t_model *temp;
1670  t_model_ports *tp;
1671  int L_index;
1672 
1673  L_index = NUM_MODELS_IN_LIBRARY;
1674 
1675  arch->models = NULL;
1676  child = ezxml_child(Node, "model");
1677  while (child != NULL) {
1678  temp = (t_model*) my_calloc(1, sizeof(t_model));
1679  temp->used = 0;
1680  temp->inputs = temp->outputs = NULL;
1681  temp->instances = NULL;
1682  Prop = FindProperty(child, "name", TRUE);
1683  temp->name = my_strdup(Prop);
1684  ezxml_set_attr(child, "name", NULL);
1685  temp->pb_types = NULL;
1686  temp->index = L_index;
1687  L_index++;
1688 
1689  /* Process the inputs */
1690  p = ezxml_child(child, "input_ports");
1691  junkp = p;
1692  if (p == NULL)
1693  vpr_printf(TIO_MESSAGE_ERROR,
1694  "Required input ports not found for element '%s'.\n",
1695  temp->name);
1696 
1697  p = ezxml_child(p, "port");
1698  if (p != NULL) {
1699  while (p != NULL) {
1700  tp = (t_model_ports*) my_calloc(1, sizeof(t_model_ports));
1701  Prop = FindProperty(p, "name", TRUE);
1702  tp->name = my_strdup(Prop);
1703  ezxml_set_attr(p, "name", NULL);
1704  tp->size = -1; /* determined later by pb_types */
1705  tp->min_size = -1; /* determined later by pb_types */
1706  tp->next = temp->inputs;
1707  tp->dir = IN_PORT;
1709  "is_non_clock_global", FALSE, FALSE);
1710  tp->is_clock = FALSE;
1711  Prop = FindProperty(p, "is_clock", FALSE);
1712  if (Prop && my_atoi(Prop) != 0) {
1713  tp->is_clock = TRUE;
1714  }
1715  ezxml_set_attr(p, "is_clock", NULL);
1716  if (tp->is_clock == TRUE && tp->is_non_clock_global == TRUE) {
1717  vpr_printf(TIO_MESSAGE_ERROR,
1718  "[LINE %d] Signal cannot be both a clock and a non-clock signal simultaneously\n",
1719  p->line);
1720  }
1721  temp->inputs = tp;
1722  junk = p;
1723  p = ezxml_next(p);
1724  FreeNode(junk);
1725  }
1726  } else /* No input ports? */
1727  {
1728  vpr_printf(TIO_MESSAGE_ERROR,
1729  "Required input ports not found for element '%s'.\n",
1730  temp->name);
1731  }
1732  FreeNode(junkp);
1733 
1734  /* Process the outputs */
1735  p = ezxml_child(child, "output_ports");
1736  junkp = p;
1737  if (p == NULL)
1738  vpr_printf(TIO_MESSAGE_ERROR,
1739  "Required output ports not found for element '%s'.\n",
1740  temp->name);
1741 
1742  p = ezxml_child(p, "port");
1743  if (p != NULL) {
1744  while (p != NULL) {
1745  tp = (t_model_ports*) my_calloc(1, sizeof(t_model_ports));
1746  Prop = FindProperty(p, "name", TRUE);
1747  tp->name = my_strdup(Prop);
1748  ezxml_set_attr(p, "name", NULL);
1749  tp->size = -1; /* determined later by pb_types */
1750  tp->min_size = -1; /* determined later by pb_types */
1751  tp->next = temp->outputs;
1752  tp->dir = OUT_PORT;
1753  temp->outputs = tp;
1754  junk = p;
1755  p = ezxml_next(p);
1756  FreeNode(junk);
1757  }
1758  } else /* No output ports? */
1759  {
1760  vpr_printf(TIO_MESSAGE_ERROR,
1761  "Required output ports not found for element '%s'.\n",
1762  temp->name);
1763  }
1764  FreeNode(junkp);
1765 
1766  /* Find the next model */
1767  temp->next = arch->models;
1768  arch->models = temp;
1769  junk = child;
1770  child = ezxml_next(child);
1771  FreeNode(junk);
1772  }
1773 
1774  return;
1775 }
1776 
1777 /* Takes in node pointing to <layout> and loads all the
1778  * child type objects. Unlinks the entire <layout> node
1779  * when complete. */
1780 static void ProcessLayout(INOUTP ezxml_t Node, OUTP struct s_arch *arch) {
1781  const char *Prop;
1782 
1783  arch->clb_grid.IsAuto = TRUE;
1784 
1785  /* Load width and height if applicable */
1786  Prop = FindProperty(Node, "width", FALSE);
1787  if (Prop != NULL) {
1788  arch->clb_grid.IsAuto = FALSE;
1789  arch->clb_grid.W = my_atoi(Prop);
1790  ezxml_set_attr(Node, "width", NULL);
1791 
1792  arch->clb_grid.H = GetIntProperty(Node, "height", TRUE, UNDEFINED);
1793  }
1794 
1795  /* Load aspect ratio if applicable */
1796  Prop = FindProperty(Node, "auto", arch->clb_grid.IsAuto);
1797  if (Prop != NULL) {
1798  if (arch->clb_grid.IsAuto == FALSE) {
1799  vpr_printf(TIO_MESSAGE_ERROR,
1800  "Auto-sizing, width and height cannot be specified\n");
1801  }
1802  arch->clb_grid.Aspect = (float) atof(Prop);
1803  ezxml_set_attr(Node, "auto", NULL);
1804  if (arch->clb_grid.Aspect <= 0) {
1805  vpr_printf(TIO_MESSAGE_ERROR,
1806  "Grid aspect ratio is less than or equal to zero %g\n",
1807  arch->clb_grid.Aspect);
1808  }
1809  }
1810 }
1811 
1812 /* Takes in node pointing to <device> and loads all the
1813  * child type objects. Unlinks the entire <device> node
1814  * when complete. */
1815 static void ProcessDevice(INOUTP ezxml_t Node, OUTP struct s_arch *arch,
1816  INP boolean timing_enabled) {
1817  const char *Prop;
1818  ezxml_t Cur;
1819 
1820  Cur = FindElement(Node, "sizing", TRUE);
1821  arch->R_minW_nmos = GetFloatProperty(Cur, "R_minW_nmos", timing_enabled, 0);
1822  arch->R_minW_pmos = GetFloatProperty(Cur, "R_minW_pmos", timing_enabled, 0);
1823  arch->ipin_mux_trans_size = GetFloatProperty(Cur, "ipin_mux_trans_size",
1824  FALSE, 0);
1825  FreeNode(Cur);
1826 
1827  Cur = FindElement(Node, "timing", timing_enabled);
1828  if (Cur != NULL) {
1829  arch->C_ipin_cblock = GetFloatProperty(Cur, "C_ipin_cblock", FALSE, 0);
1830  arch->T_ipin_cblock = GetFloatProperty(Cur, "T_ipin_cblock", FALSE, 0);
1831  FreeNode(Cur);
1832  }
1833 
1834  Cur = FindElement(Node, "area", TRUE);
1835  arch->grid_logic_tile_area = GetFloatProperty(Cur, "grid_logic_tile_area",
1836  FALSE, 0);
1837  FreeNode(Cur);
1838 
1839  Cur = FindElement(Node, "chan_width_distr", FALSE);
1840  if (Cur != NULL) {
1841  ProcessChanWidthDistr(Cur, arch);
1842  FreeNode(Cur);
1843  }
1844 
1845  Cur = FindElement(Node, "switch_block", TRUE);
1846  Prop = FindProperty(Cur, "type", TRUE);
1847  if (strcmp(Prop, "wilton") == 0) {
1848  arch->SBType = WILTON;
1849  } else if (strcmp(Prop, "universal") == 0) {
1850  arch->SBType = UNIVERSAL;
1851  } else if (strcmp(Prop, "subset") == 0) {
1852  arch->SBType = SUBSET;
1853  } else {
1854  vpr_printf(TIO_MESSAGE_ERROR,
1855  "[LINE %d] Unknown property %s for switch block type x\n",
1856  Cur->line, Prop);
1857  exit(1);
1858  }
1859  ezxml_set_attr(Cur, "type", NULL);
1860 
1861  arch->Fs = GetIntProperty(Cur, "fs", TRUE, 3);
1862 
1863  FreeNode(Cur);
1864 }
1865 
1866 /* Takes in node pointing to <chan_width_distr> and loads all the
1867  * child type objects. Unlinks the entire <chan_width_distr> node
1868  * when complete. */
1870  OUTP struct s_arch *arch) {
1871  ezxml_t Cur;
1872 
1873  Cur = FindElement(Node, "io", TRUE);
1874  arch->Chans.chan_width_io = GetFloatProperty(Cur, "width", TRUE, UNDEFINED);
1875  FreeNode(Cur);
1876  Cur = FindElement(Node, "x", TRUE);
1877  ProcessChanWidthDistrDir(Cur, &arch->Chans.chan_x_dist);
1878  FreeNode(Cur);
1879  Cur = FindElement(Node, "y", TRUE);
1880  ProcessChanWidthDistrDir(Cur, &arch->Chans.chan_y_dist);
1881  FreeNode(Cur);
1882 }
1883 
1884 /* Takes in node within <chan_width_distr> and loads all the
1885  * child type objects. Unlinks the entire node when complete. */
1887  const char *Prop;
1888 
1889  boolean hasXpeak, hasWidth, hasDc;
1890  hasXpeak = hasWidth = hasDc = FALSE;
1891  Prop = FindProperty(Node, "distr", TRUE);
1892  if (strcmp(Prop, "uniform") == 0) {
1893  chan->type = UNIFORM;
1894  } else if (strcmp(Prop, "gaussian") == 0) {
1895  chan->type = GAUSSIAN;
1896  hasXpeak = hasWidth = hasDc = TRUE;
1897  } else if (strcmp(Prop, "pulse") == 0) {
1898  chan->type = PULSE;
1899  hasXpeak = hasWidth = hasDc = TRUE;
1900  } else if (strcmp(Prop, "delta") == 0) {
1901  hasXpeak = hasDc = TRUE;
1902  chan->type = DELTA;
1903  } else {
1904  vpr_printf(TIO_MESSAGE_ERROR,
1905  "[LINE %d] Unknown property %s for chan_width_distr x\n",
1906  Node->line, Prop);
1907  exit(1);
1908  }
1909  ezxml_set_attr(Node, "distr", NULL);
1910  chan->peak = GetFloatProperty(Node, "peak", TRUE, UNDEFINED);
1911  chan->width = GetFloatProperty(Node, "width", hasWidth, 0);
1912  chan->xpeak = GetFloatProperty(Node, "xpeak", hasXpeak, 0);
1913  chan->dc = GetFloatProperty(Node, "dc", hasDc, 0);
1914 }
1915 
1916 static void SetupEmptyType(void) {
1917  t_type_descriptor * type;
1918  type = &cb_type_descriptors[EMPTY_TYPE->index];
1919  type->name = "<EMPTY>";
1920  type->num_pins = 0;
1921  type->height = 1;
1922  type->capacity = 0;
1923  type->num_drivers = 0;
1924  type->num_receivers = 0;
1925  type->pinloc = NULL;
1926  type->num_class = 0;
1927  type->class_inf = NULL;
1928  type->pin_class = NULL;
1929  type->is_global_pin = NULL;
1930  type->is_Fc_frac = NULL;
1931  type->is_Fc_full_flex = NULL;
1932  type->Fc = NULL;
1933  type->pb_type = NULL;
1934  type->area = UNDEFINED;
1935 
1936  /* Used as lost area filler, no definition */
1937  type->grid_loc_def = NULL;
1938  type->num_grid_loc_def = 0;
1939 }
1940 
1942  char *new_name, t_pb_type *copy) {
1943  int i, j;
1944  char *dot;
1945 
1946  assert(pb_type->blif_model != NULL);
1947 
1948  copy->name = my_strdup(new_name);
1949  copy->blif_model = my_strdup(pb_type->blif_model);
1950  copy->class_type = pb_type->class_type;
1951  copy->depth = pb_type->depth;
1952  copy->model = pb_type->model;
1953  copy->modes = NULL;
1954  copy->num_modes = 0;
1955  copy->num_clock_pins = pb_type->num_clock_pins;
1956  copy->num_input_pins = pb_type->num_input_pins;
1957  copy->num_output_pins = pb_type->num_output_pins;
1958  copy->num_pb = 1;
1959 
1960  /* Power */
1962  sizeof(t_pb_type_power));
1964  pb_type->pb_type_power->estimation_method);
1965 
1966  /* Ports */
1967  copy->num_ports = pb_type->num_ports;
1968  copy->ports = (t_port*) my_calloc(pb_type->num_ports, sizeof(t_port));
1969  for (i = 0; i < pb_type->num_ports; i++) {
1970  copy->ports[i].is_clock = pb_type->ports[i].is_clock;
1971  copy->ports[i].model_port = pb_type->ports[i].model_port;
1972  copy->ports[i].type = pb_type->ports[i].type;
1973  copy->ports[i].num_pins = pb_type->ports[i].num_pins;
1974  copy->ports[i].parent_pb_type = copy;
1975  copy->ports[i].name = my_strdup(pb_type->ports[i].name);
1976  copy->ports[i].port_class = my_strdup(pb_type->ports[i].port_class);
1977 
1978  copy->ports[i].port_power = (t_port_power*) my_calloc(1,
1979  sizeof(t_port_power));
1980  //Defaults
1984  } else if (copy->pb_type_power->estimation_method
1988  }
1989  }
1990 
1991  copy->max_internal_delay = pb_type->max_internal_delay;
1993  pb_type->num_annotations, sizeof(t_pin_to_pin_annotation));
1994  copy->num_annotations = pb_type->num_annotations;
1995  for (i = 0; i < copy->num_annotations; i++) {
1996  copy->annotations[i].clock = my_strdup(pb_type->annotations[i].clock);
1997  dot = strstr(pb_type->annotations[i].input_pins, ".");
1998  copy->annotations[i].input_pins = (char*) my_malloc(
1999  sizeof(char) * (strlen(new_name) + strlen(dot) + 1));
2000  copy->annotations[i].input_pins[0] = '\0';
2001  strcat(copy->annotations[i].input_pins, new_name);
2002  strcat(copy->annotations[i].input_pins, dot);
2003  if (pb_type->annotations[i].output_pins != NULL) {
2004  dot = strstr(pb_type->annotations[i].output_pins, ".");
2005  copy->annotations[i].output_pins = (char*) my_malloc(
2006  sizeof(char) * (strlen(new_name) + strlen(dot) + 1));
2007  copy->annotations[i].output_pins[0] = '\0';
2008  strcat(copy->annotations[i].output_pins, new_name);
2009  strcat(copy->annotations[i].output_pins, dot);
2010  } else {
2011  copy->annotations[i].output_pins = NULL;
2012  }
2013  copy->annotations[i].line_num = pb_type->annotations[i].line_num;
2014  copy->annotations[i].format = pb_type->annotations[i].format;
2015  copy->annotations[i].type = pb_type->annotations[i].type;
2017  pb_type->annotations[i].num_value_prop_pairs;
2018  copy->annotations[i].prop = (int*) my_malloc(
2019  sizeof(int) * pb_type->annotations[i].num_value_prop_pairs);
2020  copy->annotations[i].value = (char**) my_malloc(
2021  sizeof(char *) * pb_type->annotations[i].num_value_prop_pairs);
2022  for (j = 0; j < pb_type->annotations[i].num_value_prop_pairs; j++) {
2023  copy->annotations[i].prop[j] = pb_type->annotations[i].prop[j];
2024  copy->annotations[i].value[j] = my_strdup(
2025  pb_type->annotations[i].value[j]);
2026  }
2027  }
2028 
2029 }
2030 
2031 /* populate special lut class */
2032 void ProcessLutClass(INOUTP t_pb_type *lut_pb_type) {
2033  char *default_name;
2034  t_port *in_port;
2035  t_port *out_port;
2036  int i, j;
2037 
2038  if (strcmp(lut_pb_type->name, "lut") != 0) {
2039  default_name = my_strdup("lut");
2040  } else {
2041  default_name = my_strdup("lut_child");
2042  }
2043 
2044  lut_pb_type->num_modes = 2;
2045  lut_pb_type->pb_type_power->leakage_default_mode = 1;
2046  lut_pb_type->modes = (t_mode*) my_calloc(lut_pb_type->num_modes,
2047  sizeof(t_mode));
2048 
2049  /* First mode, route_through */
2050  lut_pb_type->modes[0].name = my_strdup("wire");
2051  lut_pb_type->modes[0].parent_pb_type = lut_pb_type;
2052  lut_pb_type->modes[0].index = 0;
2053  lut_pb_type->modes[0].num_pb_type_children = 0;
2054  lut_pb_type->modes[0].mode_power = (t_mode_power*) my_calloc(1,
2055  sizeof(t_mode_power));
2056 
2057  /* Process interconnect */
2058  /* TODO: add timing annotations to route-through */
2059  assert(lut_pb_type->num_ports == 2);
2060  if (strcmp(lut_pb_type->ports[0].port_class, "lut_in") == 0) {
2061  assert(strcmp(lut_pb_type->ports[1].port_class, "lut_out") == 0);
2062  in_port = &lut_pb_type->ports[0];
2063  out_port = &lut_pb_type->ports[1];
2064  } else {
2065  assert(strcmp(lut_pb_type->ports[0].port_class, "lut_out") == 0);
2066  assert(strcmp(lut_pb_type->ports[1].port_class, "lut_in") == 0);
2067  out_port = &lut_pb_type->ports[0];
2068  in_port = &lut_pb_type->ports[1];
2069  }
2070  lut_pb_type->modes[0].num_interconnect = 1;
2071  lut_pb_type->modes[0].interconnect = (t_interconnect*) my_calloc(1,
2072  sizeof(t_interconnect));
2073  lut_pb_type->modes[0].interconnect[0].name = (char*) my_calloc(
2074  strlen(lut_pb_type->name) + 10, sizeof(char));
2075  sprintf(lut_pb_type->modes[0].interconnect[0].name, "complete:%s",
2076  lut_pb_type->name);
2077  lut_pb_type->modes[0].interconnect[0].type = COMPLETE_INTERC;
2078  lut_pb_type->modes[0].interconnect[0].input_string = (char*) my_calloc(
2079  strlen(lut_pb_type->name) + strlen(in_port->name) + 2,
2080  sizeof(char));
2081  sprintf(lut_pb_type->modes[0].interconnect[0].input_string, "%s.%s",
2082  lut_pb_type->name, in_port->name);
2083  lut_pb_type->modes[0].interconnect[0].output_string = (char*) my_calloc(
2084  strlen(lut_pb_type->name) + strlen(out_port->name) + 2,
2085  sizeof(char));
2086  sprintf(lut_pb_type->modes[0].interconnect[0].output_string, "%s.%s",
2087  lut_pb_type->name, out_port->name);
2088 
2089  lut_pb_type->modes[0].interconnect[0].parent_mode_index = 0;
2090  lut_pb_type->modes[0].interconnect[0].parent_mode = &lut_pb_type->modes[0];
2091  lut_pb_type->modes[0].interconnect[0].interconnect_power =
2093 
2094  lut_pb_type->modes[0].interconnect[0].annotations =
2095  (t_pin_to_pin_annotation*) my_calloc(lut_pb_type->num_annotations,
2096  sizeof(t_pin_to_pin_annotation));
2097  lut_pb_type->modes[0].interconnect[0].num_annotations =
2098  lut_pb_type->num_annotations;
2099  for (i = 0; i < lut_pb_type->modes[0].interconnect[0].num_annotations;
2100  i++) {
2101  lut_pb_type->modes[0].interconnect[0].annotations[i].clock = my_strdup(
2102  lut_pb_type->annotations[i].clock);
2103  lut_pb_type->modes[0].interconnect[0].annotations[i].input_pins =
2104  my_strdup(lut_pb_type->annotations[i].input_pins);
2105  lut_pb_type->modes[0].interconnect[0].annotations[i].output_pins =
2106  my_strdup(lut_pb_type->annotations[i].output_pins);
2107  lut_pb_type->modes[0].interconnect[0].annotations[i].line_num =
2108  lut_pb_type->annotations[i].line_num;
2109  lut_pb_type->modes[0].interconnect[0].annotations[i].format =
2110  lut_pb_type->annotations[i].format;
2111  lut_pb_type->modes[0].interconnect[0].annotations[i].type =
2112  lut_pb_type->annotations[i].type;
2113  lut_pb_type->modes[0].interconnect[0].annotations[i].num_value_prop_pairs =
2114  lut_pb_type->annotations[i].num_value_prop_pairs;
2115  lut_pb_type->modes[0].interconnect[0].annotations[i].prop =
2116  (int*) my_malloc(
2117  sizeof(int)
2118  * lut_pb_type->annotations[i].num_value_prop_pairs);
2119  lut_pb_type->modes[0].interconnect[0].annotations[i].value =
2120  (char**) my_malloc(
2121  sizeof(char *)
2122  * lut_pb_type->annotations[i].num_value_prop_pairs);
2123  for (j = 0; j < lut_pb_type->annotations[i].num_value_prop_pairs; j++) {
2124  lut_pb_type->modes[0].interconnect[0].annotations[i].prop[j] =
2125  lut_pb_type->annotations[i].prop[j];
2126  lut_pb_type->modes[0].interconnect[0].annotations[i].value[j] =
2127  my_strdup(lut_pb_type->annotations[i].value[j]);
2128  }
2129  }
2130 
2131  /* Second mode, LUT */
2132 
2133  lut_pb_type->modes[1].name = my_strdup(lut_pb_type->name);
2134  lut_pb_type->modes[1].parent_pb_type = lut_pb_type;
2135  lut_pb_type->modes[1].index = 1;
2136  lut_pb_type->modes[1].num_pb_type_children = 1;
2137  lut_pb_type->modes[1].mode_power = (t_mode_power*) my_calloc(1,
2138  sizeof(t_mode_power));
2139  lut_pb_type->modes[1].pb_type_children = (t_pb_type*) my_calloc(1,
2140  sizeof(t_pb_type));
2141  alloc_and_load_default_child_for_pb_type(lut_pb_type, default_name,
2142  lut_pb_type->modes[1].pb_type_children);
2143  /* moved annotations to child so delete old annotations */
2144  for (i = 0; i < lut_pb_type->num_annotations; i++) {
2145  for (j = 0; j < lut_pb_type->annotations[i].num_value_prop_pairs; j++) {
2146  free(lut_pb_type->annotations[i].value[j]);
2147  }
2148  free(lut_pb_type->annotations[i].value);
2149  free(lut_pb_type->annotations[i].prop);
2150  if (lut_pb_type->annotations[i].input_pins) {
2151  free(lut_pb_type->annotations[i].input_pins);
2152  }
2153  if (lut_pb_type->annotations[i].output_pins) {
2154  free(lut_pb_type->annotations[i].output_pins);
2155  }
2156  if (lut_pb_type->annotations[i].clock) {
2157  free(lut_pb_type->annotations[i].clock);
2158  }
2159  }
2160  lut_pb_type->num_annotations = 0;
2161  free(lut_pb_type->annotations);
2162  lut_pb_type->annotations = NULL;
2163  lut_pb_type->modes[1].pb_type_children[0].depth = lut_pb_type->depth + 1;
2164  lut_pb_type->modes[1].pb_type_children[0].parent_mode =
2165  &lut_pb_type->modes[1];
2166 
2167  /* Process interconnect */
2168  lut_pb_type->modes[1].num_interconnect = 2;
2169  lut_pb_type->modes[1].interconnect = (t_interconnect*) my_calloc(2,
2170  sizeof(t_interconnect));
2171  lut_pb_type->modes[1].interconnect[0].name = (char*) my_calloc(
2172  strlen(lut_pb_type->name) + 10, sizeof(char));
2173  sprintf(lut_pb_type->modes[1].interconnect[0].name, "direct:%s",
2174  lut_pb_type->name);
2175  lut_pb_type->modes[1].interconnect[0].type = DIRECT_INTERC;
2176  lut_pb_type->modes[1].interconnect[0].input_string = (char*) my_calloc(
2177  strlen(lut_pb_type->name) + strlen(in_port->name) + 2,
2178  sizeof(char));
2179  sprintf(lut_pb_type->modes[1].interconnect[0].input_string, "%s.%s",
2180  lut_pb_type->name, in_port->name);
2181  lut_pb_type->modes[1].interconnect[0].output_string = (char*) my_calloc(
2182  strlen(default_name) + strlen(in_port->name) + 2, sizeof(char));
2183  sprintf(lut_pb_type->modes[1].interconnect[0].output_string, "%s.%s",
2184  default_name, in_port->name);
2185  lut_pb_type->modes[1].interconnect[0].infer_annotations = TRUE;
2186 
2187  lut_pb_type->modes[1].interconnect[0].parent_mode_index = 1;
2188  lut_pb_type->modes[1].interconnect[0].parent_mode = &lut_pb_type->modes[1];
2189  lut_pb_type->modes[1].interconnect[0].interconnect_power =
2191 
2192  lut_pb_type->modes[1].interconnect[1].name = (char*) my_calloc(
2193  strlen(lut_pb_type->name) + 11, sizeof(char));
2194  sprintf(lut_pb_type->modes[1].interconnect[1].name, "direct:%s",
2195  lut_pb_type->name);
2196 
2197  lut_pb_type->modes[1].interconnect[1].type = DIRECT_INTERC;
2198  lut_pb_type->modes[1].interconnect[1].input_string = (char*) my_calloc(
2199  strlen(default_name) + strlen(out_port->name) + 4, sizeof(char));
2200  sprintf(lut_pb_type->modes[1].interconnect[1].input_string, "%s.%s",
2201  default_name, out_port->name);
2202  lut_pb_type->modes[1].interconnect[1].output_string = (char*) my_calloc(
2203  strlen(lut_pb_type->name) + strlen(out_port->name)
2204  + strlen(in_port->name) + 2, sizeof(char));
2205  sprintf(lut_pb_type->modes[1].interconnect[1].output_string, "%s.%s",
2206  lut_pb_type->name, out_port->name);
2207  lut_pb_type->modes[1].interconnect[1].infer_annotations = TRUE;
2208 
2209  lut_pb_type->modes[1].interconnect[1].parent_mode_index = 1;
2210  lut_pb_type->modes[1].interconnect[1].parent_mode = &lut_pb_type->modes[1];
2211  lut_pb_type->modes[1].interconnect[1].interconnect_power =
2213 
2214  free(default_name);
2215 
2216  free(lut_pb_type->blif_model);
2217  lut_pb_type->blif_model = NULL;
2218  lut_pb_type->model = NULL;
2219 }
2220 
2221 /* populate special memory class */
2222 static void ProcessMemoryClass(INOUTP t_pb_type *mem_pb_type) {
2223  char *default_name;
2224  char *input_name, *input_port_name, *output_name, *output_port_name;
2225  int i, j, i_inter, num_pb;
2226 
2227  if (strcmp(mem_pb_type->name, "memory_slice") != 0) {
2228  default_name = my_strdup("memory_slice");
2229  } else {
2230  default_name = my_strdup("memory_slice_1bit");
2231  }
2232 
2233  mem_pb_type->modes = (t_mode*) my_calloc(1, sizeof(t_mode));
2234  mem_pb_type->modes[0].name = my_strdup(default_name);
2235  mem_pb_type->modes[0].parent_pb_type = mem_pb_type;
2236  mem_pb_type->modes[0].index = 0;
2237  mem_pb_type->modes[0].mode_power = (t_mode_power*) my_calloc(1,
2238  sizeof(t_mode_power));
2239  num_pb = OPEN;
2240  for (i = 0; i < mem_pb_type->num_ports; i++) {
2241  if (mem_pb_type->ports[i].port_class != NULL
2242  && strstr(mem_pb_type->ports[i].port_class, "data")
2243  == mem_pb_type->ports[i].port_class) {
2244  if (num_pb == OPEN) {
2245  num_pb = mem_pb_type->ports[i].num_pins;
2246  } else if (num_pb != mem_pb_type->ports[i].num_pins) {
2247  vpr_printf(TIO_MESSAGE_ERROR,
2248  "memory %s has inconsistent number of data bits %d and %d\n",
2249  mem_pb_type->name, num_pb,
2250  mem_pb_type->ports[i].num_pins);
2251  exit(1);
2252  }
2253  }
2254  }
2255 
2256  mem_pb_type->modes[0].num_pb_type_children = 1;
2257  mem_pb_type->modes[0].pb_type_children = (t_pb_type*) my_calloc(1,
2258  sizeof(t_pb_type));
2259  alloc_and_load_default_child_for_pb_type(mem_pb_type, default_name,
2260  &mem_pb_type->modes[0].pb_type_children[0]);
2261  mem_pb_type->modes[0].pb_type_children[0].depth = mem_pb_type->depth + 1;
2262  mem_pb_type->modes[0].pb_type_children[0].parent_mode =
2263  &mem_pb_type->modes[0];
2264  mem_pb_type->modes[0].pb_type_children[0].num_pb = num_pb;
2265 
2266  mem_pb_type->num_modes = 1;
2267 
2268  free(mem_pb_type->blif_model);
2269  mem_pb_type->blif_model = NULL;
2270  mem_pb_type->model = NULL;
2271 
2272  mem_pb_type->modes[0].num_interconnect = mem_pb_type->num_ports * num_pb;
2273  mem_pb_type->modes[0].interconnect = (t_interconnect*) my_calloc(
2274  mem_pb_type->modes[0].num_interconnect, sizeof(t_interconnect));
2275 
2276  for (i = 0; i < mem_pb_type->modes[0].num_interconnect; i++) {
2277  mem_pb_type->modes[0].interconnect[i].parent_mode_index = 0;
2278  mem_pb_type->modes[0].interconnect[i].parent_mode =
2279  &mem_pb_type->modes[0];
2280  }
2281 
2282  /* Process interconnect */
2283  i_inter = 0;
2284  for (i = 0; i < mem_pb_type->num_ports; i++) {
2285  mem_pb_type->modes[0].interconnect[i_inter].type = DIRECT_INTERC;
2286  input_port_name = mem_pb_type->ports[i].name;
2287  output_port_name = mem_pb_type->ports[i].name;
2288 
2289  if (mem_pb_type->ports[i].type == IN_PORT) {
2290  input_name = mem_pb_type->name;
2291  output_name = default_name;
2292  } else {
2293  input_name = default_name;
2294  output_name = mem_pb_type->name;
2295  }
2296 
2297  if (mem_pb_type->ports[i].port_class != NULL
2298  && strstr(mem_pb_type->ports[i].port_class, "data")
2299  == mem_pb_type->ports[i].port_class) {
2300 
2301  mem_pb_type->modes[0].interconnect[i_inter].name =
2302  (char*) my_calloc(i_inter / 10 + 8, sizeof(char));
2303  sprintf(mem_pb_type->modes[0].interconnect[i_inter].name,
2304  "direct%d", i_inter);
2305 
2306  if (mem_pb_type->ports[i].type == IN_PORT) {
2307  /* force data pins to be one bit wide and update stats */
2308  mem_pb_type->modes[0].pb_type_children[0].ports[i].num_pins = 1;
2309  mem_pb_type->modes[0].pb_type_children[0].num_input_pins -=
2310  (mem_pb_type->ports[i].num_pins - 1);
2311 
2312  mem_pb_type->modes[0].interconnect[i_inter].input_string =
2313  (char*) my_calloc(
2314  strlen(input_name) + strlen(input_port_name)
2315  + 2, sizeof(char));
2316  sprintf(
2317  mem_pb_type->modes[0].interconnect[i_inter].input_string,
2318  "%s.%s", input_name, input_port_name);
2319  mem_pb_type->modes[0].interconnect[i_inter].output_string =
2320  (char*) my_calloc(
2321  strlen(output_name) + strlen(output_port_name)
2322  + 2 * (6 + num_pb / 10), sizeof(char));
2323  sprintf(
2324  mem_pb_type->modes[0].interconnect[i_inter].output_string,
2325  "%s[%d:0].%s", output_name, num_pb - 1,
2326  output_port_name);
2327  } else {
2328  /* force data pins to be one bit wide and update stats */
2329  mem_pb_type->modes[0].pb_type_children[0].ports[i].num_pins = 1;
2330  mem_pb_type->modes[0].pb_type_children[0].num_output_pins -=
2331  (mem_pb_type->ports[i].num_pins - 1);
2332 
2333  mem_pb_type->modes[0].interconnect[i_inter].input_string =
2334  (char*) my_calloc(
2335  strlen(input_name) + strlen(input_port_name)
2336  + 2 * (6 + num_pb / 10), sizeof(char));
2337  sprintf(
2338  mem_pb_type->modes[0].interconnect[i_inter].input_string,
2339  "%s[%d:0].%s", input_name, num_pb - 1, input_port_name);
2340  mem_pb_type->modes[0].interconnect[i_inter].output_string =
2341  (char*) my_calloc(
2342  strlen(output_name) + strlen(output_port_name)
2343  + 2, sizeof(char));
2344  sprintf(
2345  mem_pb_type->modes[0].interconnect[i_inter].output_string,
2346  "%s.%s", output_name, output_port_name);
2347  }
2348 
2349  /* Allocate interconnect power structures */
2350  mem_pb_type->modes[0].interconnect[i_inter].interconnect_power =
2352  sizeof(t_interconnect_power));
2353  i_inter++;
2354  } else {
2355  for (j = 0; j < num_pb; j++) {
2356  /* Anything that is not data must be an input */
2357  mem_pb_type->modes[0].interconnect[i_inter].name =
2358  (char*) my_calloc(i_inter / 10 + j / 10 + 10,
2359  sizeof(char));
2360  sprintf(mem_pb_type->modes[0].interconnect[i_inter].name,
2361  "direct%d_%d", i_inter, j);
2362 
2363  if (mem_pb_type->ports[i].type == IN_PORT) {
2364  mem_pb_type->modes[0].interconnect[i_inter].type =
2365  DIRECT_INTERC;
2366  mem_pb_type->modes[0].interconnect[i_inter].input_string =
2367  (char*) my_calloc(
2368  strlen(input_name) + strlen(input_port_name)
2369  + 2, sizeof(char));
2370  sprintf(
2371  mem_pb_type->modes[0].interconnect[i_inter].input_string,
2372  "%s.%s", input_name, input_port_name);
2373  mem_pb_type->modes[0].interconnect[i_inter].output_string =
2374  (char*) my_calloc(
2375  strlen(output_name)
2376  + strlen(output_port_name)
2377  + 2 * (6 + num_pb / 10),
2378  sizeof(char));
2379  sprintf(
2380  mem_pb_type->modes[0].interconnect[i_inter].output_string,
2381  "%s[%d:%d].%s", output_name, j, j,
2382  output_port_name);
2383  } else {
2384  mem_pb_type->modes[0].interconnect[i_inter].type =
2385  DIRECT_INTERC;
2386  mem_pb_type->modes[0].interconnect[i_inter].input_string =
2387  (char*) my_calloc(
2388  strlen(input_name) + strlen(input_port_name)
2389  + 2 * (6 + num_pb / 10),
2390  sizeof(char));
2391  sprintf(
2392  mem_pb_type->modes[0].interconnect[i_inter].input_string,
2393  "%s[%d:%d].%s", input_name, j, j, input_port_name);
2394  mem_pb_type->modes[0].interconnect[i_inter].output_string =
2395  (char*) my_calloc(
2396  strlen(output_name)
2397  + strlen(output_port_name) + 2,
2398  sizeof(char));
2399  sprintf(
2400  mem_pb_type->modes[0].interconnect[i_inter].output_string,
2401  "%s.%s", output_name, output_port_name);
2402 
2403  }
2404 
2405  /* Allocate interconnect power structures */
2406  mem_pb_type->modes[0].interconnect[i_inter].interconnect_power =
2408  sizeof(t_interconnect_power));
2409  i_inter++;
2410  }
2411  }
2412  }
2413 
2414  mem_pb_type->modes[0].num_interconnect = i_inter;
2415 
2416  free(default_name);
2417 }
2418 
2419 /* Takes in node pointing to <typelist> and loads all the
2420  * child type objects. Unlinks the entire <typelist> node
2421  * when complete. */
2423  OUTP t_type_descriptor ** Types, OUTP int *NumTypes,
2424  boolean timing_enabled) {
2425  ezxml_t CurType, Prev;
2426  ezxml_t Cur;
2427  t_type_descriptor * Type;
2428  int i;
2429 
2430  /* Alloc the type list. Need one additional t_type_desctiptors:
2431  * 1: empty psuedo-type
2432  */
2433  *NumTypes = CountChildren(Node, "pb_type", 1) + 1;
2434  *Types = (t_type_descriptor *) my_malloc(
2435  sizeof(t_type_descriptor) * (*NumTypes));
2436 
2437  cb_type_descriptors = *Types;
2438 
2439  EMPTY_TYPE = &cb_type_descriptors[EMPTY_TYPE_INDEX];
2440  IO_TYPE = &cb_type_descriptors[IO_TYPE_INDEX];
2441  cb_type_descriptors[EMPTY_TYPE_INDEX].index = EMPTY_TYPE_INDEX;
2442  cb_type_descriptors[IO_TYPE_INDEX].index = IO_TYPE_INDEX;
2443  SetupEmptyType();
2444 
2445  /* Process the types */
2446  /* TODO: I should make this more flexible but release is soon and I don't have time so assert values for empty and io types*/
2447  assert(EMPTY_TYPE_INDEX == 0);
2448  assert(IO_TYPE_INDEX == 1);
2449  i = 1; /* Skip over 'empty' type */
2450  CurType = Node->child;
2451  while (CurType) {
2452  CheckElement(CurType, "pb_type");
2453 
2454  /* Alias to current type */
2455  Type = &(*Types)[i];
2456 
2457  /* Parses the properties fields of the type */
2458  ProcessComplexBlockProps(CurType, Type);
2459 
2460  /* Load pb_type info */
2461  Type->pb_type = (t_pb_type*) my_malloc(sizeof(t_pb_type));
2462  Type->pb_type->name = my_strdup(Type->name);
2463  if (i == IO_TYPE_INDEX) {
2464  if (strcmp(Type->name, "io") != 0) {
2465  vpr_printf(TIO_MESSAGE_ERROR,
2466  "First complex block must be named \"io\" and define the inputs and outputs for the FPGA");
2467  exit(1);
2468  }
2469  }
2470  ProcessPb_Type(CurType, Type->pb_type, NULL);
2471  Type->num_pins = Type->capacity
2472  * (Type->pb_type->num_input_pins
2473  + Type->pb_type->num_output_pins
2474  + Type->pb_type->num_clock_pins);
2475  Type->num_receivers = Type->capacity * Type->pb_type->num_input_pins;
2476  Type->num_drivers = Type->capacity * Type->pb_type->num_output_pins;
2477 
2478  /* Load pin names and classes and locations */
2479  Cur = FindElement(CurType, "pinlocations", TRUE);
2480  SetupPinLocationsAndPinClasses(Cur, Type);
2481  FreeNode(Cur);
2482  Cur = FindElement(CurType, "gridlocations", TRUE);
2483  SetupGridLocations(Cur, Type);
2484  FreeNode(Cur);
2485 
2486  /* Load Fc */
2487  Cur = FindElement(CurType, "fc", TRUE);
2488  Process_Fc(Cur, Type);
2489  FreeNode(Cur);
2490 
2491 #if 0
2492  Cur = FindElement(CurType, "timing", timing_enabled);
2493  if (Cur)
2494  {
2495  SetupTypeTiming(Cur, Type);
2496  FreeNode(Cur);
2497  }
2498 #endif
2499  Type->index = i;
2500 
2501  /* Type fully read */
2502  ++i;
2503 
2504  /* Free this node and get its next sibling node */
2505  Prev = CurType;
2506  CurType = CurType->next;
2507  FreeNode(Prev);
2508 
2509  }
2510  if (FILL_TYPE == NULL) {
2511  vpr_printf(TIO_MESSAGE_ERROR,
2512  "grid location type 'fill' must be specified.\n");
2513  exit(1);
2514  }
2515 }
2516 
2517 /* Loads the given architecture file. Currently only
2518  * handles type information */
2519 void XmlReadArch(INP const char *ArchFile, INP boolean timing_enabled,
2520  OUTP struct s_arch *arch, OUTP t_type_descriptor ** Types,
2521  OUTP int *NumTypes) {
2522  ezxml_t Cur, Next;
2523  const char *Prop;
2524  boolean power_reqd;
2525 
2526  /* Parse the file */
2527  Cur = ezxml_parse_file(ArchFile);
2528  if (NULL == Cur) {
2529  vpr_printf(TIO_MESSAGE_ERROR,
2530  "Unable to load architecture file '%s'.\n", ArchFile);
2531  exit(1);
2532  }
2533 
2534  /* Root node should be architecture */
2535  CheckElement(Cur, "architecture");
2536  /* TODO: do version processing properly with string delimiting on the . */
2537  Prop = FindProperty(Cur, "version", FALSE);
2538  if (Prop != NULL) {
2539  if (atof(Prop) > atof(VPR_VERSION)) {
2540  vpr_printf(TIO_MESSAGE_WARNING,
2541  "This architecture version is for VPR %f while your current VPR version is " VPR_VERSION ", compatability issues may arise\n",
2542  atof(Prop));
2543  }
2544  ezxml_set_attr(Cur, "version", NULL);
2545  }
2546 
2547  /* Process models */
2548  Next = FindElement(Cur, "models", TRUE);
2549  ProcessModels(Next, arch);
2550  FreeNode(Next);
2551  CreateModelLibrary(arch);
2552 
2553  /* Process layout */
2554  Next = FindElement(Cur, "layout", TRUE);
2555  ProcessLayout(Next, arch);
2556  FreeNode(Next);
2557 
2558  /* Process device */
2559  Next = FindElement(Cur, "device", TRUE);
2560  ProcessDevice(Next, arch, timing_enabled);
2561  FreeNode(Next);
2562 
2563  /* Process types */
2564  Next = FindElement(Cur, "complexblocklist", TRUE);
2565  ProcessComplexBlocks(Next, Types, NumTypes, timing_enabled);
2566  FreeNode(Next);
2567 
2568  /* Process switches */
2569  Next = FindElement(Cur, "switchlist", TRUE);
2570  ProcessSwitches(Next, &(arch->Switches), &(arch->num_switches),
2571  timing_enabled);
2572  FreeNode(Next);
2573 
2574  /* Process segments. This depends on switches */
2575  Next = FindElement(Cur, "segmentlist", TRUE);
2576  ProcessSegments(Next, &(arch->Segments), &(arch->num_segments),
2577  arch->Switches, arch->num_switches, timing_enabled);
2578  FreeNode(Next);
2579 
2580  /* Process directs */
2581  Next = FindElement(Cur, "directlist", FALSE);
2582  if (Next) {
2583  ProcessDirects(Next, &(arch->Directs), &(arch->num_directs),
2584  timing_enabled);
2585  FreeNode(Next);
2586  }
2587 
2588  /* Process architecture power information */
2589 
2590  /* If arch->power has been initialized, meaning the user has requested power estimation,
2591  * then the power architecture information is required.
2592  */
2593  if (arch->power) {
2594  power_reqd = TRUE;
2595  } else {
2596  power_reqd = FALSE;
2597  }
2598 
2599  Next = FindElement(Cur, "power", power_reqd);
2600  if (Next) {
2601  if (arch->power) {
2602  ProcessPower(Next, arch->power, *Types, *NumTypes);
2603  } else {
2604  /* This information still needs to be read, even if it is just
2605  * thrown away.
2606  */
2607  t_power_arch * power_arch_fake = (t_power_arch*) my_calloc(1,
2608  sizeof(t_power_arch));
2609  ProcessPower(Next, power_arch_fake, *Types, *NumTypes);
2610  free(power_arch_fake);
2611  }
2612  FreeNode(Next);
2613  }
2614 
2615 // Process Clocks
2616  Next = FindElement(Cur, "clocks", power_reqd);
2617  if (Next) {
2618  if (arch->clocks) {
2619  ProcessClocks(Next, arch->clocks);
2620  } else {
2621  /* This information still needs to be read, even if it is just
2622  * thrown away.
2623  */
2624  t_clock_arch * clocks_fake = (t_clock_arch*) my_calloc(1,
2625  sizeof(t_clock_arch));
2626  ProcessClocks(Next, clocks_fake);
2627  free(clocks_fake->clock_inf);
2628  free(clocks_fake);
2629  }
2630  FreeNode(Next);
2631  }
2632  SyncModelsPbTypes(arch, *Types, *NumTypes);
2633  UpdateAndCheckModels(arch);
2634 
2635  /* Release the full XML tree */
2636  FreeNode(Cur);
2637 }
2638 
2639 static void ProcessSegments(INOUTP ezxml_t Parent,
2640  OUTP struct s_segment_inf **Segs, OUTP int *NumSegs,
2641  INP struct s_switch_inf *Switches, INP int NumSwitches,
2642  INP boolean timing_enabled) {
2643  int i, j, length;
2644  const char *tmp;
2645 
2646  ezxml_t SubElem;
2647  ezxml_t Node;
2648 
2649  /* Count the number of segs and check they are in fact
2650  * of segment elements. */
2651  *NumSegs = CountChildren(Parent, "segment", 1);
2652 
2653  /* Alloc segment list */
2654  *Segs = NULL;
2655  if (*NumSegs > 0) {
2656  *Segs = (struct s_segment_inf *) my_malloc(
2657  *NumSegs * sizeof(struct s_segment_inf));
2658  memset(*Segs, 0, (*NumSegs * sizeof(struct s_segment_inf)));
2659  }
2660 
2661  /* Load the segments. */
2662  for (i = 0; i < *NumSegs; ++i) {
2663  Node = ezxml_child(Parent, "segment");
2664 
2665  /* Get segment length */
2666  length = 1; /* DEFAULT */
2667  tmp = FindProperty(Node, "length", FALSE);
2668  if (tmp) {
2669  if (strcmp(tmp, "longline") == 0) {
2670  (*Segs)[i].longline = TRUE;
2671  } else {
2672  length = my_atoi(tmp);
2673  }
2674  }
2675  (*Segs)[i].length = length;
2676  ezxml_set_attr(Node, "length", NULL);
2677 
2678  /* Get the frequency */
2679  (*Segs)[i].frequency = 1; /* DEFAULT */
2680  tmp = FindProperty(Node, "freq", FALSE);
2681  if (tmp) {
2682  (*Segs)[i].frequency = (int) (atof(tmp) * MAX_CHANNEL_WIDTH);
2683  }
2684  ezxml_set_attr(Node, "freq", NULL);
2685 
2686  /* Get timing info */
2687  (*Segs)[i].Rmetal = GetFloatProperty(Node, "Rmetal", timing_enabled, 0);
2688  (*Segs)[i].Cmetal = GetFloatProperty(Node, "Cmetal", timing_enabled, 0);
2689 
2690  /* Get Power info */
2691  /*
2692  (*Segs)[i].Cmetal_per_m = GetFloatProperty(Node, "Cmetal_per_m", FALSE,
2693  0.);*/
2694 
2695  /* Get the type */
2696  tmp = FindProperty(Node, "type", TRUE);
2697  if (0 == strcmp(tmp, "bidir")) {
2698  (*Segs)[i].directionality = BI_DIRECTIONAL;
2699  }
2700 
2701  else if (0 == strcmp(tmp, "unidir")) {
2702  (*Segs)[i].directionality = UNI_DIRECTIONAL;
2703  }
2704 
2705  else {
2706  vpr_printf(TIO_MESSAGE_ERROR,
2707  "[LINE %d] Invalid switch type '%s'.\n", Node->line, tmp);
2708  exit(1);
2709  }
2710  ezxml_set_attr(Node, "type", NULL);
2711 
2712  /* Get the wire and opin switches, or mux switch if unidir */
2713  if (UNI_DIRECTIONAL == (*Segs)[i].directionality) {
2714  SubElem = FindElement(Node, "mux", TRUE);
2715  tmp = FindProperty(SubElem, "name", TRUE);
2716 
2717  /* Match names */
2718  for (j = 0; j < NumSwitches; ++j) {
2719  if (0 == strcmp(tmp, Switches[j].name)) {
2720  break; /* End loop so j is where we want it */
2721  }
2722  }
2723  if (j >= NumSwitches) {
2724  vpr_printf(TIO_MESSAGE_ERROR,
2725  "[LINE %d] '%s' is not a valid mux name.\n",
2726  SubElem->line, tmp);
2727  exit(1);
2728  }
2729  ezxml_set_attr(SubElem, "name", NULL);
2730  FreeNode(SubElem);
2731 
2732  /* Unidir muxes must have the same switch
2733  * for wire and opin fanin since there is
2734  * really only the mux in unidir. */
2735  (*Segs)[i].wire_switch = j;
2736  (*Segs)[i].opin_switch = j;
2737  }
2738 
2739  else {
2740  assert(BI_DIRECTIONAL == (*Segs)[i].directionality);
2741  SubElem = FindElement(Node, "wire_switch", TRUE);
2742  tmp = FindProperty(SubElem, "name", TRUE);
2743 
2744  /* Match names */
2745  for (j = 0; j < NumSwitches; ++j) {
2746  if (0 == strcmp(tmp, Switches[j].name)) {
2747  break; /* End loop so j is where we want it */
2748  }
2749  }
2750  if (j >= NumSwitches) {
2751  vpr_printf(TIO_MESSAGE_ERROR,
2752  "[LINE %d] '%s' is not a valid wire_switch name.\n",
2753  SubElem->line, tmp);
2754  exit(1);
2755  }
2756  (*Segs)[i].wire_switch = j;
2757  ezxml_set_attr(SubElem, "name", NULL);
2758  FreeNode(SubElem);
2759  SubElem = FindElement(Node, "opin_switch", TRUE);
2760  tmp = FindProperty(SubElem, "name", TRUE);
2761 
2762  /* Match names */
2763  for (j = 0; j < NumSwitches; ++j) {
2764  if (0 == strcmp(tmp, Switches[j].name)) {
2765  break; /* End loop so j is where we want it */
2766  }
2767  }
2768  if (j >= NumSwitches) {
2769  vpr_printf(TIO_MESSAGE_ERROR,
2770  "[LINE %d] '%s' is not a valid opin_switch name.\n",
2771  SubElem->line, tmp);
2772  exit(1);
2773  }
2774  (*Segs)[i].opin_switch = j;
2775  ezxml_set_attr(SubElem, "name", NULL);
2776  FreeNode(SubElem);
2777  }
2778 
2779  /* Setup the CB list if they give one, otherwise use full */
2780  (*Segs)[i].cb_len = length;
2781  (*Segs)[i].cb = (boolean *) my_malloc(length * sizeof(boolean));
2782  for (j = 0; j < length; ++j) {
2783  (*Segs)[i].cb[j] = TRUE;
2784  }
2785  SubElem = FindElement(Node, "cb", FALSE);
2786  if (SubElem) {
2787  ProcessCB_SB(SubElem, (*Segs)[i].cb, length);
2788  FreeNode(SubElem);
2789  }
2790 
2791  /* Setup the SB list if they give one, otherwise use full */
2792  (*Segs)[i].sb_len = (length + 1);
2793  (*Segs)[i].sb = (boolean *) my_malloc((length + 1) * sizeof(boolean));
2794  for (j = 0; j < (length + 1); ++j) {
2795  (*Segs)[i].sb[j] = TRUE;
2796  }
2797  SubElem = FindElement(Node, "sb", FALSE);
2798  if (SubElem) {
2799  ProcessCB_SB(SubElem, (*Segs)[i].sb, (length + 1));
2800  FreeNode(SubElem);
2801  }
2802  FreeNode(Node);
2803  }
2804 }
2805 
2806 static void ProcessCB_SB(INOUTP ezxml_t Node, INOUTP boolean * list,
2807  INP int len) {
2808  const char *tmp = NULL;
2809  int i;
2810 
2811  /* Check the type. We only support 'pattern' for now.
2812  * Should add frac back eventually. */
2813  tmp = FindProperty(Node, "type", TRUE);
2814  if (0 == strcmp(tmp, "pattern")) {
2815  i = 0;
2816 
2817  /* Get the content string */
2818  tmp = Node->txt;
2819  while (*tmp) {
2820  switch (*tmp) {
2821  case ' ':
2822  case '\t':
2823  case '\n':
2824  break;
2825  case 'T':
2826  case '1':
2827  if (i >= len) {
2828  vpr_printf(TIO_MESSAGE_ERROR,
2829  "[LINE %d] CB or SB depopulation is too long. It "
2830 
2831  "should be (length) symbols for CBs and (length+1) "
2832  "symbols for SBs.\n", Node->line);
2833  exit(1);
2834  }
2835  list[i] = TRUE;
2836  ++i;
2837  break;
2838  case 'F':
2839  case '0':
2840  if (i >= len) {
2841  vpr_printf(TIO_MESSAGE_ERROR,
2842  "[LINE %d] CB or SB depopulation is too long. It "
2843 
2844  "should be (length) symbols for CBs and (length+1) "
2845  "symbols for SBs.\n", Node->line);
2846  exit(1);
2847  }
2848  list[i] = FALSE;
2849  ++i;
2850  break;
2851  default:
2852  vpr_printf(TIO_MESSAGE_ERROR,
2853  "[LINE %d] Invalid character %c in CB or "
2854  "SB depopulation list.\n", Node->line, *tmp);
2855  exit(1);
2856  }
2857  ++tmp;
2858  }
2859  if (i < len) {
2860  vpr_printf(TIO_MESSAGE_ERROR,
2861  "[LINE %d] CB or SB depopulation is too short. It "
2862  "should be (length) symbols for CBs and (length+1) "
2863  "symbols for SBs.\n", Node->line);
2864  exit(1);
2865  }
2866 
2867  /* Free content string */
2868  ezxml_set_txt(Node, "");
2869  }
2870 
2871  else {
2872  vpr_printf(TIO_MESSAGE_ERROR,
2873  "[LINE %d] '%s' is not a valid type for specifying "
2874  "cb and sb depopulation.\n", Node->line, tmp);
2875  exit(1);
2876  }
2877  ezxml_set_attr(Node, "type", NULL);
2878 }
2879 
2880 static void ProcessSwitches(INOUTP ezxml_t Parent,
2881  OUTP struct s_switch_inf **Switches, OUTP int *NumSwitches,
2882  INP boolean timing_enabled) {
2883  int i, j;
2884  const char *type_name;
2885  const char *switch_name;
2886  const char *buf_size;
2887 
2888  boolean has_buf_size;
2889  ezxml_t Node;
2890  has_buf_size = FALSE;
2891 
2892  /* Count the children and check they are switches */
2893  *NumSwitches = CountChildren(Parent, "switch", 1);
2894 
2895  /* Alloc switch list */
2896  *Switches = NULL;
2897  if (*NumSwitches > 0) {
2898  *Switches = (struct s_switch_inf *) my_malloc(
2899  *NumSwitches * sizeof(struct s_switch_inf));
2900  memset(*Switches, 0, (*NumSwitches * sizeof(struct s_switch_inf)));
2901  }
2902 
2903  /* Load the switches. */
2904  for (i = 0; i < *NumSwitches; ++i) {
2905  Node = ezxml_child(Parent, "switch");
2906  switch_name = FindProperty(Node, "name", TRUE);
2907  type_name = FindProperty(Node, "type", TRUE);
2908 
2909  /* Check for switch name collisions */
2910  for (j = 0; j < i; ++j) {
2911  if (0 == strcmp((*Switches)[j].name, switch_name)) {
2912  vpr_printf(TIO_MESSAGE_ERROR,
2913  "[LINE %d] Two switches with the same name '%s' were "
2914  "found.\n", Node->line, switch_name);
2915  exit(1);
2916  }
2917  }
2918  (*Switches)[i].name = my_strdup(switch_name);
2919  ezxml_set_attr(Node, "name", NULL);
2920 
2921  /* Figure out the type of switch. */
2922  if (0 == strcmp(type_name, "mux")) {
2923  (*Switches)[i].buffered = TRUE;
2924  has_buf_size = TRUE;
2925  }
2926 
2927  else if (0 == strcmp(type_name, "pass_trans")) {
2928  (*Switches)[i].buffered = FALSE;
2929  }
2930 
2931  else if (0 == strcmp(type_name, "buffer")) {
2932  (*Switches)[i].buffered = TRUE;
2933  }
2934 
2935  else {
2936  vpr_printf(TIO_MESSAGE_ERROR,
2937  "[LINE %d] Invalid switch type '%s'.\n", Node->line,
2938  type_name);
2939  exit(1);
2940  }
2941  ezxml_set_attr(Node, "type", NULL);
2942  (*Switches)[i].R = GetFloatProperty(Node, "R", timing_enabled, 0);
2943  (*Switches)[i].Cin = GetFloatProperty(Node, "Cin", timing_enabled, 0);
2944  (*Switches)[i].Cout = GetFloatProperty(Node, "Cout", timing_enabled, 0);
2945  (*Switches)[i].Tdel = GetFloatProperty(Node, "Tdel", timing_enabled, 0);
2946  (*Switches)[i].buf_size = GetFloatProperty(Node, "buf_size",
2947  has_buf_size, 0);
2948  (*Switches)[i].mux_trans_size = GetFloatProperty(Node, "mux_trans_size",
2949  FALSE, 1);
2950 
2951  buf_size = FindProperty(Node, "power_buf_size", FALSE);
2952  if (buf_size == NULL) {
2953  (*Switches)[i].power_buffer_type = POWER_BUFFER_TYPE_AUTO;
2954  } else if (strcmp(buf_size, "auto") == 0) {
2955  (*Switches)[i].power_buffer_type = POWER_BUFFER_TYPE_AUTO;
2956  } else {
2957  (*Switches)[i].power_buffer_type = POWER_BUFFER_TYPE_ABSOLUTE_SIZE;
2958  (*Switches)[i].power_buffer_size = (float) atof(buf_size);
2959  }
2960  ezxml_set_attr(Node, "power_buf_size", NULL);
2961 
2962  /* Remove the switch element from parse tree */
2963  FreeNode(Node);
2964  }
2965 }
2966 
2967 static void ProcessDirects(INOUTP ezxml_t Parent, OUTP t_direct_inf **Directs,
2968  OUTP int *NumDirects, INP boolean timing_enabled) {
2969  int i, j;
2970  const char *direct_name;
2971  const char *from_pin_name;
2972  const char *to_pin_name;
2973 
2974  ezxml_t Node;
2975 
2976  /* Count the children and check they are direct connections */
2977  *NumDirects = CountChildren(Parent, "direct", 1);
2978 
2979  /* Alloc direct list */
2980  *Directs = NULL;
2981  if (*NumDirects > 0) {
2982  *Directs = (t_direct_inf *) my_malloc(
2983  *NumDirects * sizeof(t_direct_inf));
2984  memset(*Directs, 0, (*NumDirects * sizeof(t_direct_inf)));
2985  }
2986 
2987  /* Load the directs. */
2988  for (i = 0; i < *NumDirects; ++i) {
2989  Node = ezxml_child(Parent, "direct");
2990 
2991  direct_name = FindProperty(Node, "name", TRUE);
2992  /* Check for direct name collisions */
2993  for (j = 0; j < i; ++j) {
2994  if (0 == strcmp((*Directs)[j].name, direct_name)) {
2995  vpr_printf(TIO_MESSAGE_ERROR,
2996  "[LINE %d] Two directs with the same name '%s' were "
2997  "found.\n", Node->line, direct_name);
2998  exit(1);
2999  }
3000  }
3001  (*Directs)[i].name = my_strdup(direct_name);
3002  ezxml_set_attr(Node, "name", NULL);
3003 
3004  /* Figure out the source pin and sink pin name */
3005  from_pin_name = FindProperty(Node, "from_pin", TRUE);
3006  to_pin_name = FindProperty(Node, "to_pin", TRUE);
3007 
3008  /* Check that to_pin and the from_pin are not the same */
3009  if (0 == strcmp(to_pin_name, from_pin_name)) {
3010  vpr_printf(TIO_MESSAGE_ERROR,
3011  "[LINE %d] The source pin and sink pin are the same: %s.\n",
3012  Node->line, to_pin_name);
3013  exit(1);
3014  }
3015  (*Directs)[i].from_pin = my_strdup(from_pin_name);
3016  (*Directs)[i].to_pin = my_strdup(to_pin_name);
3017  ezxml_set_attr(Node, "from_pin", NULL);
3018  ezxml_set_attr(Node, "to_pin", NULL);
3019 
3020  (*Directs)[i].x_offset = GetIntProperty(Node, "x_offset", TRUE, 0);
3021  (*Directs)[i].y_offset = GetIntProperty(Node, "y_offset", TRUE, 0);
3022  (*Directs)[i].z_offset = GetIntProperty(Node, "z_offset", TRUE, 0);
3023  ezxml_set_attr(Node, "x_offset", NULL);
3024  ezxml_set_attr(Node, "y_offset", NULL);
3025  ezxml_set_attr(Node, "z_offset", NULL);
3026 
3027  /* Check that the direct chain connection is not zero in both direction */
3028  if ((*Directs)[i].x_offset == 0 && (*Directs)[i].y_offset == 0) {
3029  vpr_printf(TIO_MESSAGE_ERROR,
3030  "[LINE %d] The x_offset and y_offset are both zero, "
3031  "this is a length 0 direct chain connection.\n",
3032  Node->line);
3033  exit(1);
3034  }
3035 
3036  (*Directs)[i].line = Node->line;
3037  /* Should I check that the direct chain offset is not greater than the chip? How? */
3038 
3039  /* Remove the direct element from parse tree */
3040  FreeNode(Node);
3041  }
3042 }
3043 
3044 static void CreateModelLibrary(OUTP struct s_arch *arch) {
3045  t_model* model_library;
3046 
3047  model_library = (t_model*) my_calloc(4, sizeof(t_model));
3048  model_library[0].name = my_strdup("input");
3049  model_library[0].index = 0;
3050  model_library[0].inputs = NULL;
3051  model_library[0].instances = NULL;
3052  model_library[0].next = &model_library[1];
3053  model_library[0].outputs = (t_model_ports*) my_calloc(1,
3054  sizeof(t_model_ports));
3055  model_library[0].outputs->dir = OUT_PORT;
3056  model_library[0].outputs->name = my_strdup("inpad");
3057  model_library[0].outputs->next = NULL;
3058  model_library[0].outputs->size = 1;
3059  model_library[0].outputs->min_size = 1;
3060  model_library[0].outputs->index = 0;
3061  model_library[0].outputs->is_clock = FALSE;
3062 
3063  model_library[1].name = my_strdup("output");
3064  model_library[1].index = 1;
3065  model_library[1].inputs = (t_model_ports*) my_calloc(1,
3066  sizeof(t_model_ports));
3067  model_library[1].inputs->dir = IN_PORT;
3068  model_library[1].inputs->name = my_strdup("outpad");
3069  model_library[1].inputs->next = NULL;
3070  model_library[1].inputs->size = 1;
3071  model_library[1].inputs->min_size = 1;
3072  model_library[1].inputs->index = 0;
3073  model_library[1].inputs->is_clock = FALSE;
3074  model_library[1].instances = NULL;
3075  model_library[1].next = &model_library[2];
3076  model_library[1].outputs = NULL;
3077 
3078  model_library[2].name = my_strdup("latch");
3079  model_library[2].index = 2;
3080  model_library[2].inputs = (t_model_ports*) my_calloc(2,
3081  sizeof(t_model_ports));
3082  model_library[2].inputs[0].dir = IN_PORT;
3083  model_library[2].inputs[0].name = my_strdup("D");
3084  model_library[2].inputs[0].next = &model_library[2].inputs[1];
3085  model_library[2].inputs[0].size = 1;
3086  model_library[2].inputs[0].min_size = 1;
3087  model_library[2].inputs[0].index = 0;
3088  model_library[2].inputs[0].is_clock = FALSE;
3089  model_library[2].inputs[1].dir = IN_PORT;
3090  model_library[2].inputs[1].name = my_strdup("clk");
3091  model_library[2].inputs[1].next = NULL;
3092  model_library[2].inputs[1].size = 1;
3093  model_library[2].inputs[1].min_size = 1;
3094  model_library[2].inputs[1].index = 0;
3095  model_library[2].inputs[1].is_clock = TRUE;
3096  model_library[2].instances = NULL;
3097  model_library[2].next = &model_library[3];
3098  model_library[2].outputs = (t_model_ports*) my_calloc(1,
3099  sizeof(t_model_ports));
3100  model_library[2].outputs->dir = OUT_PORT;
3101  model_library[2].outputs->name = my_strdup("Q");
3102  model_library[2].outputs->next = NULL;
3103  model_library[2].outputs->size = 1;
3104  model_library[2].outputs->min_size = 1;
3105  model_library[2].outputs->index = 0;
3106  model_library[2].outputs->is_clock = FALSE;
3107 
3108  model_library[3].name = my_strdup("names");
3109  model_library[3].index = 3;
3110  model_library[3].inputs = (t_model_ports*) my_calloc(1,
3111  sizeof(t_model_ports));
3112  model_library[3].inputs->dir = IN_PORT;
3113  model_library[3].inputs->name = my_strdup("in");
3114  model_library[3].inputs->next = NULL;
3115  model_library[3].inputs->size = 1;
3116  model_library[3].inputs->min_size = 1;
3117  model_library[3].inputs->index = 0;
3118  model_library[3].inputs->is_clock = FALSE;
3119  model_library[3].instances = NULL;
3120  model_library[3].next = NULL;
3121  model_library[3].outputs = (t_model_ports*) my_calloc(1,
3122  sizeof(t_model_ports));
3123  model_library[3].outputs->dir = OUT_PORT;
3124  model_library[3].outputs->name = my_strdup("out");
3125  model_library[3].outputs->next = NULL;
3126  model_library[3].outputs->size = 1;
3127  model_library[3].outputs->min_size = 1;
3128  model_library[3].outputs->index = 0;
3129  model_library[3].outputs->is_clock = FALSE;
3130 
3131  arch->model_library = model_library;
3132 }
3133 
3134 static void SyncModelsPbTypes(INOUTP struct s_arch *arch,
3135  INP t_type_descriptor * Types, INP int NumTypes) {
3136  int i;
3137  for (i = 0; i < NumTypes; i++) {
3138  if (Types[i].pb_type != NULL) {
3139  SyncModelsPbTypes_rec(arch, Types[i].pb_type);
3140  }
3141  }
3142 }
3143 
3144 static void SyncModelsPbTypes_rec(INOUTP struct s_arch *arch,
3145  INOUTP t_pb_type * pb_type) {
3146  int i, j, p;
3147  t_model *model_match_prim, *cur_model;
3148  t_model_ports *model_port;
3149  struct s_linked_vptr *old;
3150  char* blif_model_name;
3151 
3152  boolean found;
3153 
3154  if (pb_type->blif_model != NULL) {
3155 
3156  /* get actual name of subckt */
3157  if (strstr(pb_type->blif_model, ".subckt ") == pb_type->blif_model) {
3158  blif_model_name = strchr(pb_type->blif_model, ' ');
3159  } else {
3160  blif_model_name = strchr(pb_type->blif_model, '.');
3161  }
3162  if (blif_model_name) {
3163  blif_model_name++; /* get character after the '.' or ' ' */
3164  } else {
3165  vpr_printf(TIO_MESSAGE_ERROR,
3166  "Unknown blif model %s in pb_type %s\n",
3167  pb_type->blif_model, pb_type->name);
3168  }
3169 
3170  /* There are two sets of models to consider, the standard library of models and the user defined models */
3171  if ((strcmp(blif_model_name, "input") == 0)
3172  || (strcmp(blif_model_name, "output") == 0)
3173  || (strcmp(blif_model_name, "names") == 0)
3174  || (strcmp(blif_model_name, "latch") == 0)) {
3175  cur_model = arch->model_library;
3176  } else {
3177  cur_model = arch->models;
3178  }
3179 
3180  /* Determine the logical model to use */
3181  found = FALSE;
3182  model_match_prim = NULL;
3183  while (cur_model && !found) {
3184  /* blif model always starts with .subckt so need to skip first 8 characters */
3185  if (strcmp(blif_model_name, cur_model->name) == 0) {
3186  found = TRUE;
3187  model_match_prim = cur_model;
3188  }
3189  cur_model = cur_model->next;
3190  }
3191  if (found != TRUE) {
3192  vpr_printf(TIO_MESSAGE_ERROR, "No matching model for pb_type %s\n",
3193  pb_type->blif_model);
3194  exit(1);
3195  }
3196 
3197  pb_type->model = model_match_prim;
3198  old = model_match_prim->pb_types;
3199  model_match_prim->pb_types = (struct s_linked_vptr*) my_malloc(
3200  sizeof(struct s_linked_vptr));
3201  model_match_prim->pb_types->next = old;
3202  model_match_prim->pb_types->data_vptr = pb_type;
3203 
3204  for (p = 0; p < pb_type->num_ports; p++) {
3205  found = FALSE;
3206  /* TODO: Parse error checking - check if INPUT matches INPUT and OUTPUT matches OUTPUT (not yet done) */
3207  model_port = model_match_prim->inputs;
3208  while (model_port && !found) {
3209  if (strcmp(model_port->name, pb_type->ports[p].name) == 0) {
3210  if (model_port->size < pb_type->ports[p].num_pins) {
3211  model_port->size = pb_type->ports[p].num_pins;
3212  }
3213  if (model_port->min_size > pb_type->ports[p].num_pins
3214  || model_port->min_size == -1) {
3215  model_port->min_size = pb_type->ports[p].num_pins;
3216  }
3217  pb_type->ports[p].model_port = model_port;
3218  assert(pb_type->ports[p].type == model_port->dir);
3219  assert(pb_type->ports[p].is_clock == model_port->is_clock);
3220  found = TRUE;
3221  }
3222  model_port = model_port->next;
3223  }
3224  model_port = model_match_prim->outputs;
3225  while (model_port && !found) {
3226  if (strcmp(model_port->name, pb_type->ports[p].name) == 0) {
3227  if (model_port->size < pb_type->ports[p].num_pins) {
3228  model_port->size = pb_type->ports[p].num_pins;
3229  }
3230  if (model_port->min_size > pb_type->ports[p].num_pins
3231  || model_port->min_size == -1) {
3232  model_port->min_size = pb_type->ports[p].num_pins;
3233  }
3234  pb_type->ports[p].model_port = model_port;
3235  assert(pb_type->ports[p].type == model_port->dir);
3236  found = TRUE;
3237  }
3238  model_port = model_port->next;
3239  }
3240  if (found != TRUE) {
3241  vpr_printf(TIO_MESSAGE_ERROR,
3242  "No matching model port for port %s in pb_type %s\n",
3243  pb_type->ports[p].name, pb_type->name);
3244  exit(1);
3245  }
3246  }
3247  } else {
3248  for (i = 0; i < pb_type->num_modes; i++) {
3249  for (j = 0; j < pb_type->modes[i].num_pb_type_children; j++) {
3250  SyncModelsPbTypes_rec(arch,
3251  &(pb_type->modes[i].pb_type_children[j]));
3252  }
3253  }
3254  }
3255 }
3256 
3257 static void UpdateAndCheckModels(INOUTP struct s_arch *arch) {
3258  t_model * cur_model;
3259  t_model_ports *port;
3260  int i, j;
3261  cur_model = arch->models;
3262  while (cur_model) {
3263  if (cur_model->pb_types == NULL) {
3264  vpr_printf(TIO_MESSAGE_ERROR, "No pb_type found for model %s\n",
3265  cur_model->name);
3266  exit(1);
3267  }
3268  port = cur_model->inputs;
3269  i = 0;
3270  j = 0;
3271  while (port) {
3272  if (port->is_clock) {
3273  port->index = i;
3274  i++;
3275  } else {
3276  port->index = j;
3277  j++;
3278  }
3279  port = port->next;
3280  }
3281  port = cur_model->outputs;
3282  i = 0;
3283  while (port) {
3284  port->index = i;
3285  i++;
3286  port = port->next;
3287  }
3288  cur_model = cur_model->next;
3289  }
3290 }
3291 
3292 /* Output the data from architecture data so user can verify it
3293  * was interpretted correctly. */
3294 void EchoArch(INP const char *EchoFile, INP const t_type_descriptor * Types,
3295  INP int NumTypes, struct s_arch *arch) {
3296  int i, j;
3297  FILE * Echo;
3298  t_model * cur_model;
3299  t_model_ports * model_port;
3300  struct s_linked_vptr *cur_vptr;
3301 
3302  Echo = my_fopen(EchoFile, "w", 0);
3303  cur_model = NULL;
3304 
3305  for (j = 0; j < 2; j++) {
3306  if (j == 0) {
3307  fprintf(Echo, "Printing user models \n");
3308  cur_model = arch->models;
3309  } else if (j == 1) {
3310  fprintf(Echo, "Printing library models \n");
3311  cur_model = arch->model_library;
3312  }
3313  while (cur_model) {
3314  fprintf(Echo, "Model: \"%s\"\n", cur_model->name);
3315  model_port = cur_model->inputs;
3316  while (model_port) {
3317  fprintf(Echo, "\tInput Ports: \"%s\" \"%d\" min_size=\"%d\"\n",
3318  model_port->name, model_port->size,
3319  model_port->min_size);
3320  model_port = model_port->next;
3321  }
3322  model_port = cur_model->outputs;
3323  while (model_port) {
3324  fprintf(Echo, "\tOutput Ports: \"%s\" \"%d\" min_size=\"%d\"\n",
3325  model_port->name, model_port->size,
3326  model_port->min_size);
3327  model_port = model_port->next;
3328  }
3329  cur_vptr = cur_model->pb_types;
3330  i = 0;
3331  while (cur_vptr != NULL) {
3332  fprintf(Echo, "\tpb_type %d: \"%s\"\n", i,
3333  ((t_pb_type*) cur_vptr->data_vptr)->name);
3334  cur_vptr = cur_vptr->next;
3335  i++;
3336  }
3337 
3338  cur_model = cur_model->next;
3339  }
3340  }
3341 
3342  for (i = 0; i < NumTypes; ++i) {
3343  fprintf(Echo, "Type: \"%s\"\n", Types[i].name);
3344  fprintf(Echo, "\tcapacity: %d\n", Types[i].capacity);
3345  fprintf(Echo, "\theight: %d\n", Types[i].height);
3346 
3347  for (j = 0; j < Types[i].num_pins; j++) {
3348  fprintf(Echo, "\tis_Fc_frac: \n");
3349  fprintf(Echo, "\t\tPin number %d: %s\n", j,
3350  (Types[i].is_Fc_frac[j] ? "TRUE" : "FALSE"));
3351  fprintf(Echo, "\tis_Fc_full_flex: \n");
3352  fprintf(Echo, "\t\tPin number %d: %s\n", j,
3353  (Types[i].is_Fc_full_flex[j] ? "TRUE" : "FALSE"));
3354  fprintf(Echo, "\tFc_val: \n");
3355  fprintf(Echo, "\tPin number %d: %f\n", j, Types[i].Fc[j]);
3356  }
3357  fprintf(Echo, "\tnum_drivers: %d\n", Types[i].num_drivers);
3358  fprintf(Echo, "\tnum_receivers: %d\n", Types[i].num_receivers);
3359  fprintf(Echo, "\tindex: %d\n", Types[i].index);
3360  if (Types[i].pb_type) {
3361  PrintPb_types_rec(Echo, Types[i].pb_type, 2);
3362  }
3363  fprintf(Echo, "\n");
3364  }
3365  fclose(Echo);
3366 }
3367 
3368 static void PrintPb_types_rec(INP FILE * Echo, INP const t_pb_type * pb_type,
3369  int level) {
3370  int i, j, k;
3371  char *tabs;
3372 
3373  tabs = (char*) my_malloc((level + 1) * sizeof(char));
3374  for (i = 0; i < level; i++) {
3375  tabs[i] = '\t';
3376  }
3377  tabs[level] = '\0';
3378 
3379  fprintf(Echo, "%spb_type name: %s\n", tabs, pb_type->name);
3380  fprintf(Echo, "%s\tblif_model: %s\n", tabs, pb_type->blif_model);
3381  fprintf(Echo, "%s\tclass_type: %d\n", tabs, pb_type->class_type);
3382  fprintf(Echo, "%s\tnum_modes: %d\n", tabs, pb_type->num_modes);
3383  fprintf(Echo, "%s\tnum_ports: %d\n", tabs, pb_type->num_ports);
3384  for (i = 0; i < pb_type->num_ports; i++) {
3385  fprintf(Echo, "%s\tport %s type %d num_pins %d\n", tabs,
3386  pb_type->ports[i].name, pb_type->ports[i].type,
3387  pb_type->ports[i].num_pins);
3388  }
3389  for (i = 0; i < pb_type->num_modes; i++) {
3390  fprintf(Echo, "%s\tmode %s:\n", tabs, pb_type->modes[i].name);
3391  for (j = 0; j < pb_type->modes[i].num_pb_type_children; j++) {
3392  PrintPb_types_rec(Echo, &pb_type->modes[i].pb_type_children[j],
3393  level + 2);
3394  }
3395  for (j = 0; j < pb_type->modes[i].num_interconnect; j++) {
3396  fprintf(Echo, "%s\t\tinterconnect %d %s %s\n", tabs,
3397  pb_type->modes[i].interconnect[j].type,
3398  pb_type->modes[i].interconnect[j].input_string,
3399  pb_type->modes[i].interconnect[j].output_string);
3400  for (k = 0; k < pb_type->modes[i].interconnect[j].num_annotations;
3401  k++) {
3402  fprintf(Echo, "%s\t\t\tannotation %s %s %d: %s\n", tabs,
3403  pb_type->modes[i].interconnect[j].annotations[k].input_pins,
3404  pb_type->modes[i].interconnect[j].annotations[k].output_pins,
3405  pb_type->modes[i].interconnect[j].annotations[k].format,
3406  pb_type->modes[i].interconnect[j].annotations[k].value[0]);
3407  }
3408  }
3409  }
3410  free(tabs);
3411 }
3412 
3413 static void ProcessPower( INOUTP ezxml_t parent,
3414  INOUTP t_power_arch * power_arch, INP t_type_descriptor * Types,
3415  INP int NumTypes) {
3416  ezxml_t Cur;
3417 
3418  /* Get the local interconnect capacitances */
3419  power_arch->local_interc_factor = 0.5;
3420  Cur = FindElement(parent, "local_interconnect", FALSE);
3421  if (Cur) {
3422  power_arch->C_wire_local = GetFloatProperty(Cur, "C_wire", FALSE, 0.);
3423  power_arch->local_interc_factor = GetFloatProperty(Cur, "factor", FALSE,
3424  0.5);
3425  FreeNode(Cur);
3426  }
3427 
3428  /* Get segment split */
3429  /*
3430  power_arch->seg_buffer_split = 1;
3431  Cur = FindElement(parent, "segment_buffer_split", FALSE);
3432  if (Cur) {
3433  power_arch->seg_buffer_split = GetIntProperty(Cur, "split_into", TRUE,
3434  1);
3435  FreeNode(Cur);
3436  }*/
3437 
3438  /* Get logical effort factor */
3439  power_arch->logical_effort_factor = 4.0;
3440  Cur = FindElement(parent, "buffers", FALSE);
3441  if (Cur) {
3442  power_arch->logical_effort_factor = GetFloatProperty(Cur,
3443  "logical_effort_factor", TRUE, 0);
3444  FreeNode(Cur);
3445  }
3446 
3447  /* Get SRAM Size */
3448  power_arch->transistors_per_SRAM_bit = 6.0;
3449  Cur = FindElement(parent, "sram", FALSE);
3450  if (Cur) {
3451  power_arch->transistors_per_SRAM_bit = GetFloatProperty(Cur,
3452  "transistors_per_bit", TRUE, 0);
3453  FreeNode(Cur);
3454  }
3455 
3456  /* Get Mux transistor size */
3457  power_arch->mux_transistor_size = 1.0;
3458  Cur = FindElement(parent, "mux_transistor_size", FALSE);
3459  if (Cur) {
3460  power_arch->mux_transistor_size = GetFloatProperty(Cur,
3461  "mux_transistor_size", TRUE, 0);
3462  FreeNode(Cur);
3463  }
3464 
3465  /* Get FF size */
3466  power_arch->FF_size = 1.0;
3467  Cur = FindElement(parent, "FF_size", FALSE);
3468  if (Cur) {
3469  power_arch->FF_size = GetFloatProperty(Cur, "FF_size", TRUE, 0);
3470  FreeNode(Cur);
3471  }
3472 
3473  /* Get LUT transistor size */
3474  power_arch->LUT_transistor_size = 1.0;
3475  Cur = FindElement(parent, "LUT_transistor_size", FALSE);
3476  if (Cur) {
3477  power_arch->LUT_transistor_size = GetFloatProperty(Cur,
3478  "LUT_transistor_size", TRUE, 0);
3479  FreeNode(Cur);
3480  }
3481 }
3482 
3483 /* Get the clock architcture */
3484 static void ProcessClocks(ezxml_t Parent, t_clock_arch * clocks) {
3485  ezxml_t Node;
3486  int i;
3487  const char *tmp;
3488 
3489  clocks->num_global_clocks = CountChildren(Parent, "clock", 0);
3490 
3491  /* Alloc the clockdetails */
3492  clocks->clock_inf = NULL;
3493  if (clocks->num_global_clocks > 0) {
3494  clocks->clock_inf = (t_clock_network *) my_malloc(
3495  clocks->num_global_clocks * sizeof(t_clock_network));
3496  memset(clocks->clock_inf, 0,
3497  clocks->num_global_clocks * sizeof(t_clock_network));
3498  }
3499 
3500  /* Load the clock info. */
3501  for (i = 0; i < clocks->num_global_clocks; ++i) {
3502  /* get the next clock item */
3503  Node = ezxml_child(Parent, "clock");
3504 
3505  tmp = FindProperty(Node, "buffer_size", TRUE);
3506  if (strcmp(tmp, "auto") == 0) {
3507  clocks->clock_inf[i].autosize_buffer = TRUE;
3508  } else {
3509  clocks->clock_inf[i].autosize_buffer = FALSE;
3510  clocks->clock_inf[i].buffer_size = (float) atof(tmp);
3511  }
3512  ezxml_set_attr(Node, "buffer_size", NULL);
3513 
3514  clocks->clock_inf[i].C_wire = GetFloatProperty(Node, "C_wire", TRUE, 0);
3515  FreeNode(Node);
3516  }
3517 }
3518 
3520  e_power_estimation_method parent_power_method) {
3521  switch (parent_power_method) {
3522  case POWER_METHOD_IGNORE:
3526  return parent_power_method;
3528  case POWER_METHOD_ABSOLUTE:
3529  return POWER_METHOD_IGNORE;
3531  return POWER_METHOD_UNDEFINED;
3533  /* Just revert to the default */
3534  return POWER_METHOD_AUTO_SIZES;
3535  default:
3536  assert(0);
3537  return POWER_METHOD_UNDEFINED; // Should never get here, but avoids a compiler warning.
3538  }
3539 }
3540 
static void CreateModelLibrary(OUTP struct s_arch *arch)
boolean is_clock
t_clock_network * clock_inf
t_interconnect * interconnect
enum e_pb_type_class class_type
static t_port * findPortByName(const char *name, t_pb_type *pb_type, int *high_index, int *low_index)
FILE * my_fopen(const char *fname, const char *flag, int prompt)
Definition: util.c:54
Definition: ezxml.h:44
t_port_power * port_power
char * name
int num_pins
t_model_ports * model_port
char * chain_name
boolean equivalent
struct s_pb_type * pb_type_children
union s_port_power::@5 wire
enum e_power_estimation_method_ e_power_estimation_method
e_power_estimation_method power_method_inherited(e_power_estimation_method parent_power_method)
void FreeTokens(INOUTP char ***TokensPtr)
Definition: ReadLine.c:9
e_power_estimation_method estimation_method
#define NUM_MODELS_IN_LIBRARY
enum PORTS dir
Definition: logic_types.h:22
void * instances
Definition: logic_types.h:37
struct s_class * class_inf
t_model * model_library
static void SyncModelsPbTypes(INOUTP struct s_arch *arch, INP t_type_descriptor *Types, INP int NumTypes)
static void ProcessComplexBlockProps(ezxml_t Node, t_type_descriptor *Type)
char * txt
Definition: ezxml.h:47
boolean
Definition: util.h:11
static void ProcessSwitches(INOUTP ezxml_t Node, OUTP struct s_switch_inf **Switches, OUTP int *NumSwitches, INP boolean timing_enabled)
#define VPR_VERSION
Definition: arch_types.h:16
t_mode * modes
static void ProcessModels(INOUTP ezxml_t Node, OUTP struct s_arch *arch)
t_model * models
int num_interconnect
static void ProcessMemoryClass(INOUTP t_pb_type *mem_pb_type)
struct s_grid_loc_def * grid_loc_def
#define ezxml_next(xml)
Definition: ezxml.h:101
void XmlReadArch(INP const char *ArchFile, INP boolean timing_enabled, OUTP struct s_arch *arch, OUTP t_type_descriptor **Types, OUTP int *NumTypes)
void * my_calloc(size_t nelem, size_t size)
Definition: util.c:132
struct s_model_ports * next
Definition: logic_types.h:28
t_pb_type_power * pb_type_power
enum PORTS type
static void SetupEmptyType(void)
char * blif_model
t_model * model
static void SetupPinLocationsAndPinClasses(ezxml_t Locations, t_type_descriptor *Type)
boolean is_clock
Definition: logic_types.h:26
enum e_pin_to_pin_annotation_format format
static t_type_ptr IO_TYPE
static void ProcessCB_SB(INOUTP ezxml_t Node, INOUTP boolean *list, INP int len)
enum e_pin_location_distr pin_location_distribution
#define INOUTP
Definition: util.h:21
static void ProcessInterconnect(INOUTP ezxml_t Parent, t_mode *mode)
#define UNDEFINED
Definition: vpr_types.h:103
enum e_directionality directionality
enum e_pin_to_pin_annotation_type type
Definition: util.h:12
#define EMPTY_TYPE_INDEX
float relative_length
t_mode * parent_mode
static void ProcessPinToPinAnnotations(ezxml_t parent, t_pin_to_pin_annotation *annotation)
static void ProcessDirects(INOUTP ezxml_t Parent, OUTP t_direct_inf **Directs, OUTP int *NumDirects, INP boolean timing_enabled)
t_power_usage absolute_power_per_instance
static void SyncModelsPbTypes_rec(INOUTP struct s_arch *arch, INP t_pb_type *pb_type)
ezxml_t next
Definition: ezxml.h:49
#define IO_TYPE_INDEX
ezxml_t ezxml_set_attr(ezxml_t xml, char *name, char *value)
Definition: ezxml.c:1165
t_pin_to_pin_annotation * annotations
int num_annotations
ezxml_t ezxml_child(ezxml_t xml, const char *name)
Definition: ezxml.c:85
static void ProcessClocks(ezxml_t Parent, t_clock_arch *clocks)
static void * my_malloc(int ibytes)
Definition: graphics.c:499
ezxml_t FindElement(INP ezxml_t Parent, INP const char *Name, INP boolean Required)
Definition: read_xml_util.c:11
static void ProcessPb_TypePort(INOUTP ezxml_t Parent, t_port *port, e_power_estimation_method power_method)
int * pinlist
struct s_model * next
Definition: logic_types.h:40
#define MAX_CHANNEL_WIDTH
Definition: arch_types.h:25
int used
Definition: logic_types.h:38
#define INP
Definition: util.h:19
char * name
static void Process_Fc(ezxml_t Node, t_type_descriptor *Type)
t_model_ports * inputs
Definition: logic_types.h:35
static void alloc_and_load_default_child_for_pb_type(INOUTP t_pb_type *pb_type, char *new_name, t_pb_type *copy)
t_model_ports * outputs
Definition: logic_types.h:36
void FreeNode(INOUTP ezxml_t Node)
Definition: read_xml_util.c:73
static t_type_ptr FILL_TYPE
char **** pin_loc_assignments
enum e_interconnect type
struct s_linked_vptr * pb_types
Definition: logic_types.h:39
int line
Definition: ezxml.h:56
t_pin_to_pin_annotation * annotations
boolean reverse_scaled
struct s_linked_vptr * next
Definition: util.h:36
int num_pb_type_children
int scaled_by_port_pin_idx
ezxml_t FindFirstElement(INP ezxml_t Parent, INP const char *Name, INP boolean Required)
Definition: read_xml_util.c:38
static void ProcessPb_TypePowerEstMethod(ezxml_t Parent, t_pb_type *pb_type)
static void ProcessComplexBlocks(INOUTP ezxml_t Node, OUTP t_type_descriptor **Types, OUTP int *NumTypes, INP boolean timing_enabled)
void CountTokensInString(INP const char *Str, OUTP int *Num, OUTP int *Len)
int port_index_by_type
ezxml_t ezxml_set_txt(ezxml_t xml, char *txt)
Definition: ezxml.c:1152
static void ProcessPb_Type(INOUTP ezxml_t Parent, t_pb_type *pb_type, t_mode *mode)
void EchoArch(INP const char *EchoFile, INP const t_type_descriptor *Types, INP int NumTypes, struct s_arch *arch)
float absolute_length
void * data_vptr
Definition: util.h:35
int index
Definition: logic_types.h:42
ezxml_t parent
Definition: ezxml.h:53
char ** GetNodeTokens(INP ezxml_t Node)
static struct s_type_descriptor * cb_type_descriptors
static void ProcessPb_TypePowerPinToggle(ezxml_t parent, t_pb_type *pb_type)
int GetIntProperty(INP ezxml_t Parent, INP char *Name, INP boolean Required, INP int default_value)
char * name
Definition: ezxml.h:45
struct s_pb_type * pb_type
t_mode * parent_mode
struct s_pb_type * parent_pb_type
float energy_per_toggle
char * name
Definition: logic_types.h:34
int ** num_pin_loc_assignments
float GetFloatProperty(INP ezxml_t Parent, INP char *Name, INP boolean Required, INP float default_value)
e_power_buffer_type buffer_type
t_port * ports
enum e_grid_loc_type grid_loc_type
static void ProcessLayout(INOUTP ezxml_t Node, OUTP struct s_arch *arch)
Definition: slre.c:50
boolean pin_toggle_initialized
static void ProcessChanWidthDistrDir(INOUTP ezxml_t Node, OUTP t_chan *chan)
ezxml_t ezxml_parse_file(const char *file)
Definition: ezxml.c:846
static void ProcessSegments(INOUTP ezxml_t Parent, OUTP struct s_segment_inf **Segs, OUTP int *NumSegs, INP struct s_switch_inf *Switches, INP int NumSwitches, INP boolean timing_enabled)
boolean autosize_buffer
int CountChildren(INP ezxml_t Node, INP const char *Name, INP int min_count)
#define OUTP
Definition: util.h:20
enum e_pin_type type
static void ProcessLutClass(INOUTP t_pb_type *lut_pb_type)
static void SetupGridLocations(ezxml_t Locations, t_type_descriptor *Type)
float max_internal_delay
t_port * scaled_by_port
static void ProcessDevice(INOUTP ezxml_t Node, OUTP struct s_arch *arch, INP boolean timing_enabled)
e_power_wire_type wire_type
static void ProcessMode(INOUTP ezxml_t Parent, t_mode *mode, boolean *default_leakage_mode)
boolean is_non_clock_global
Definition: logic_types.h:27
int num_output_pins
boolean * is_global_pin
static t_type_ptr EMPTY_TYPE
static void ProcessPb_TypePort_Power(ezxml_t Parent, t_port *port, e_power_estimation_method power_method)
int my_atoi(const char *str)
Definition: util.c:116
char * my_strdup(const char *str)
Definition: util.c:101
struct s_pb_type * parent_pb_type
t_mode_power * mode_power
boolean GetBooleanProperty(INP ezxml_t Parent, INP char *Name, INP boolean Required, INP boolean default_value)
messagelogger vpr_printf
Definition: util.c:17
boolean * is_Fc_full_flex
ezxml_t child
Definition: ezxml.h:52
char * port_class
int num_input_pins
boolean is_non_clock_global
t_interconnect_power * interconnect_power
void CheckElement(INP ezxml_t Node, INP const char *Name)
Definition: read_xml_util.c:59
static void ProcessPower(INOUTP ezxml_t parent, INOUTP t_power_arch *power_arch, INP t_type_descriptor *Types, INP int NumTypes)
static void ProcessPb_TypePower(ezxml_t Parent, t_pb_type *pb_type)
const char * FindProperty(INP ezxml_t Parent, INP const char *Name, INP boolean)
int num_clock_pins
Definition: util.h:12
static void UpdateAndCheckModels(INOUTP struct s_arch *arch)
static void PrintPb_types_rec(INP FILE *Echo, INP const t_pb_type *pb_type, int level)
static void ProcessChanWidthDistr(INOUTP ezxml_t Node, OUTP struct s_arch *arch)