00001 #include <string.h>
00002 #include <assert.h>
00003 #include "util.h"
00004 #include "vpr_types.h"
00005 #include "ReadLine.h"
00006 #include "ezxml.h"
00007 #include "globals.h"
00008 #include "xml_arch.h"
00009
00010
00011
00012 #define EMPTY_TYPE_INDEX 0
00013 #define IO_TYPE_INDEX 1
00014 enum Fc_type
00015 { FC_ABS, FC_FRAC, FC_FULL };
00016
00017
00018
00019 static boolean IsWhitespace(char c);
00020 static void CountTokensInString(IN const char *Str,
00021 OUT int *Num,
00022 OUT int *Len);
00023 static char **GetNodeTokens(IN ezxml_t Node);
00024 static void CheckElement(IN ezxml_t Node,
00025 IN const char *Name);
00026 static void CheckText(IN ezxml_t Node);
00027 static void FreeNode(INOUT ezxml_t Node);
00028 static ezxml_t FindElement(IN ezxml_t Parent,
00029 IN const char *Name,
00030 IN boolean Required);
00031 static const char *FindProperty(IN ezxml_t Parent,
00032 IN const char *Name,
00033 IN boolean Required);
00034 static int CountChildren(IN ezxml_t Node,
00035 IN const char *Name);
00036 static void ParseFc(ezxml_t Node,
00037 enum Fc_type *Fc,
00038 float *Val);
00039 static void SetupEmptyType();
00040 static void SetupClassInf(ezxml_t Classes,
00041 t_type_descriptor * Type);
00042 static void SetupPinClasses(ezxml_t Classes,
00043 t_type_descriptor * Type);
00044 static void SetupPinLocations(ezxml_t Locations,
00045 t_type_descriptor * Type);
00046 static void SetupGridLocations(ezxml_t Locations,
00047 t_type_descriptor * Type);
00048 static void SetupTypeTiming(ezxml_t timing,
00049 t_type_descriptor * Type);
00050 static void SetupSubblocksTcomb(ezxml_t timing,
00051 t_type_descriptor * Type);
00052 static void SetupSubblocksTSeq(ezxml_t timing_seq_in,
00053 ezxml_t timing_seq_out,
00054 t_type_descriptor * Type);
00055 static void Process_Fc(ezxml_t Fc_in_node,
00056 ezxml_t Fc_out_node,
00057 t_type_descriptor * Type);
00058 static void ProcessSubblocks(INOUT ezxml_t Parent,
00059 INOUT t_type_descriptor * Type,
00060 IN boolean timing_enabled);
00061 static void ProcessTypeProps(ezxml_t Node,
00062 t_type_descriptor * Type);
00063 static void ProcessChanWidthDistr(INOUT ezxml_t Node,
00064 OUT struct s_arch *arch);
00065 static void ProcessChanWidthDistrDir(INOUT ezxml_t Node,
00066 OUT t_chan * chan);
00067 static void ProcessLayout(INOUT ezxml_t Node,
00068 OUT struct s_arch *arch);
00069 static void ProcessDevice(INOUT ezxml_t Node,
00070 OUT struct s_arch *arch,
00071 IN boolean timing_enabled);
00072 static void ProcessIO(INOUT ezxml_t Node,
00073 IN boolean timing_enabled);
00074 static void ProcessTypes(INOUT ezxml_t Node,
00075 OUT t_type_descriptor ** Types,
00076 OUT int *NumTypes,
00077 IN boolean timing_enabled);
00078 static void ProcessSwitches(INOUT ezxml_t Node,
00079 OUT struct s_switch_inf **Switches,
00080 OUT int *NumSwitches,
00081 IN boolean timing_enabled);
00082 static void ProcessSegments(INOUT ezxml_t Parent,
00083 OUT struct s_segment_inf **Segs,
00084 OUT int *NumSegs,
00085 IN struct s_switch_inf *Switches,
00086 IN int NumSwitches,
00087 IN boolean timing_enabled);
00088 static void ProcessCB_SB(INOUT ezxml_t Node,
00089 INOUT boolean * list,
00090 IN int len);
00091
00092
00093
00094 static boolean
00095 IsWhitespace(char c)
00096 {
00097 switch (c)
00098 {
00099 case ' ':
00100 case '\t':
00101 case '\r':
00102 case '\n':
00103 return TRUE;
00104 default:
00105 return FALSE;
00106 }
00107 }
00108
00109
00110
00111 static void
00112 CountTokensInString(IN const char *Str,
00113 OUT int *Num,
00114 OUT int *Len)
00115 {
00116 boolean InToken;
00117 *Num = 0;
00118 *Len = 0;
00119 InToken = FALSE;
00120 while(*Str)
00121 {
00122 if(IsWhitespace(*Str))
00123 {
00124 InToken = FALSE;
00125 }
00126
00127 else
00128
00129 {
00130 if(!InToken)
00131 {
00132 ++(*Num);
00133 }
00134 ++(*Len);
00135 InToken = TRUE;
00136 }
00137 ++Str;
00138 }
00139 }
00140
00141
00142
00143
00144 static char **
00145 GetNodeTokens(IN ezxml_t Node)
00146 {
00147 int Count, Len;
00148 char *Cur, *Dst;
00149
00150 boolean InToken;
00151 char **Tokens;
00152
00153
00154
00155 CountTokensInString(Node->txt, &Count, &Len);
00156
00157
00158 if(Count < 1)
00159 {
00160 printf(ERRTAG "Tag '%s' expected enclosed text data "
00161 "but none was found.\n", Node->name);
00162 exit(1);
00163 }
00164 Len = (sizeof(char) * Len) +
00165 (sizeof(char) * Count);
00166
00167
00168
00169 Tokens = (char **)my_malloc(sizeof(char *) * (Count + 1));
00170 Dst = (char *)my_malloc(sizeof(char) * Len);
00171 Count = 0;
00172
00173
00174 Cur = Node->txt;
00175 InToken = FALSE;
00176 while(*Cur)
00177 {
00178 if(IsWhitespace(*Cur))
00179 {
00180 if(InToken)
00181 {
00182 *Dst = '\0';
00183 ++Dst;
00184 }
00185 InToken = FALSE;
00186 }
00187
00188 else
00189 {
00190 if(!InToken)
00191 {
00192 Tokens[Count] = Dst;
00193 ++Count;
00194 }
00195 *Dst = *Cur;
00196 ++Dst;
00197 InToken = TRUE;
00198 }
00199 ++Cur;
00200 }
00201 if(InToken)
00202 {
00203 *Dst = '\0';
00204 ++Dst;
00205 }
00206 ezxml_set_txt(Node, "");
00207 Tokens[Count] = NULL;
00208
00209
00210 return Tokens;
00211 }
00212
00213
00214
00215 static void
00216 CheckElement(IN ezxml_t Node,
00217 IN const char *Name)
00218 {
00219 if(0 != strcmp(Node->name, Name))
00220 {
00221 printf(ERRTAG
00222 "Element '%s' within element '%s' does match expected "
00223 "element type of '%s'\n", Node->name, Node->parent->name,
00224 Name);
00225 exit(1);
00226 }
00227 }
00228
00229
00230
00231
00232
00233 static void
00234 FreeNode(INOUT ezxml_t Node)
00235 {
00236 ezxml_t Cur;
00237 char *Txt;
00238
00239
00240
00241 if(Node->attr[0])
00242 {
00243 printf(ERRTAG "Node '%s' has invalid property %s=\"%s\".\n",
00244 Node->name, Node->attr[0], Node->attr[1]);
00245 exit(1);
00246 }
00247
00248
00249 Txt = Node->txt;
00250 while(*Txt)
00251 {
00252 if(!IsWhitespace(*Txt))
00253 {
00254 printf(ERRTAG
00255 "Node '%s' has unexpected text '%s' within it.\n",
00256 Node->name, Node->txt);
00257 exit(1);
00258 }
00259 ++Txt;
00260 }
00261
00262
00263 Cur = Node->child;
00264 if(Cur)
00265 {
00266 printf(ERRTAG "Node '%s' on has invalid child node '%s'.\n",
00267 Node->name, Cur->name);
00268 exit(1);
00269 }
00270
00271
00272 ezxml_remove(Node);
00273 }
00274
00275
00276
00277
00278 static ezxml_t
00279 FindElement(IN ezxml_t Parent,
00280 IN const char *Name,
00281 IN boolean Required)
00282 {
00283 ezxml_t Cur;
00284
00285
00286 Cur = ezxml_child(Parent, Name);
00287
00288
00289 if(Required)
00290 {
00291 if(NULL == Cur)
00292 {
00293 printf(ERRTAG
00294 "Element '%s' not found within element '%s'.\n",
00295 Name, Parent->name);
00296 exit(1);
00297 }
00298 }
00299
00300
00301 if(Cur != NULL && Cur->next)
00302 {
00303 printf(ERRTAG "Element '%s' found twice within element '%s'.\n",
00304 Name, Parent->name);
00305 exit(1);
00306 }
00307 return Cur;
00308 }
00309 static const char *
00310 FindProperty(IN ezxml_t Parent,
00311 IN const char *Name,
00312 IN boolean Required)
00313 {
00314 const char *Res;
00315
00316 Res = ezxml_attr(Parent, Name);
00317 if(Required)
00318 {
00319 if(NULL == Res)
00320 {
00321 printf(ERRTAG
00322 "Required property '%s' not found for element '%s'.\n",
00323 Name, Parent->name);
00324 exit(1);
00325 }
00326 }
00327 return Res;
00328 }
00329
00330
00331
00332
00333
00334 static int
00335 CountChildren(IN ezxml_t Node,
00336 IN const char *Name)
00337 {
00338 ezxml_t Cur, sibling;
00339 int Count;
00340
00341 Count = 0;
00342 Cur = Node->child;
00343 while(Cur)
00344 {
00345 if(strcmp(Cur->name, Name) == 0)
00346 {
00347 ++Count;
00348 }
00349 sibling = Cur->sibling;
00350 Cur = Cur->next;
00351 if(Cur == NULL)
00352 {
00353 Cur = sibling;
00354 }
00355 }
00356
00357
00358 if(Count < 1)
00359 {
00360 printf(ERRTAG "Expected node '%s' to have "
00361 "child elements, but none found.\n", Node->name);
00362 exit(1);
00363 }
00364 return Count;
00365 }
00366
00367
00368
00369
00370 static void
00371 ParseFc(ezxml_t Node,
00372 enum Fc_type *Fc,
00373 float *Val)
00374 {
00375 const char *Prop;
00376
00377 Prop = FindProperty(Node, "type", TRUE);
00378 if(0 == strcmp(Prop, "abs"))
00379 {
00380 *Fc = FC_ABS;
00381 }
00382
00383 else if(0 == strcmp(Prop, "frac"))
00384 {
00385 *Fc = FC_FRAC;
00386 }
00387
00388 else if(0 == strcmp(Prop, "full"))
00389 {
00390 *Fc = FC_FULL;
00391 }
00392
00393 else
00394 {
00395 printf(ERRTAG "Invalid type '%s' for Fc. Only abs, frac "
00396 "and full are allowed.\n", Prop);
00397 exit(1);
00398 }
00399 switch (*Fc)
00400 {
00401 case FC_FULL:
00402 *Val = 0.0;
00403 break;
00404 case FC_ABS:
00405 case FC_FRAC:
00406 *Val = atof(Node->txt);
00407 ezxml_set_attr(Node, "type", NULL);
00408 ezxml_set_txt(Node, "");
00409 break;
00410 default:
00411 assert(0);
00412 }
00413
00414
00415 ezxml_set_attr(Node, "type", NULL);
00416 }
00417
00418
00419
00420
00421
00422
00423 static void
00424 SetupClassInf(ezxml_t Classes,
00425 t_type_descriptor * Type)
00426 {
00427 int i, k, CurClass, CurPin, NumClassPins;
00428
00429 ezxml_t Cur;
00430 const char *Prop;
00431
00432
00433
00434 Type->num_class = Type->capacity * CountChildren(Classes, "class");
00435 Type->class_inf =
00436 (t_class *) my_malloc(Type->num_class * sizeof(t_class));
00437
00438
00439 CurPin = 0;
00440 CurClass = 0;
00441 Type->num_pins = 0;
00442 Type->num_drivers = 0;
00443 Type->num_receivers = 0;
00444 for(i = 0; i < Type->capacity; ++i)
00445 {
00446
00447
00448 Cur = Classes->child;
00449 while(Cur)
00450 {
00451 CheckElement(Cur, "class");
00452
00453
00454 CountTokensInString(Cur->txt, &NumClassPins, &k);
00455 Type->num_pins += NumClassPins;
00456
00457
00458 Type->class_inf[CurClass].num_pins = NumClassPins;
00459 Type->class_inf[CurClass].pinlist =
00460 (int *)my_malloc(NumClassPins * sizeof(int));
00461 for(k = 0; k < NumClassPins; ++k)
00462 {
00463 Type->class_inf[CurClass].pinlist[k] = CurPin;
00464 ++CurPin;
00465 }
00466
00467
00468 Prop = FindProperty(Cur, "type", TRUE);
00469 if(0 == strcmp(Prop, "in"))
00470 {
00471 Type->num_receivers += NumClassPins;
00472 Type->class_inf[CurClass].type = RECEIVER;
00473 }
00474
00475 else if(0 == strcmp(Prop, "out"))
00476 {
00477 Type->num_drivers += NumClassPins;
00478 Type->class_inf[CurClass].type = DRIVER;
00479 }
00480
00481 else if(0 == strcmp(Prop, "global"))
00482 {
00483 Type->class_inf[CurClass].type = RECEIVER;
00484 }
00485
00486 else
00487 {
00488 printf(ERRTAG "Invalid pin class type '%s'.\n",
00489 Prop);
00490 exit(1);
00491 }
00492 ++CurClass;
00493 Cur = Cur->next;
00494 }
00495 }
00496 }
00497
00498
00499
00500
00501
00502
00503
00504 static void
00505 SetupPinClasses(ezxml_t Classes,
00506 t_type_descriptor * Type)
00507 {
00508 int CurClass, i, j, CurPin, PinsPerSubtile, ClassesPerSubtile;
00509
00510 ezxml_t Cur, Prev;
00511 const char *Prop;
00512
00513 boolean IsGlobal;
00514 char **Tokens;
00515 int *pin_used = NULL;
00516
00517
00518
00519 SetupClassInf(Classes, Type);
00520 PinsPerSubtile = Type->num_pins / Type->capacity;
00521 ClassesPerSubtile = Type->num_class / Type->capacity;
00522
00523
00524 Type->is_global_pin =
00525 (boolean *) my_malloc(Type->num_pins * sizeof(boolean));
00526 Type->pin_class = (int *)my_malloc(Type->num_pins * sizeof(int));
00527 pin_used = (int *)my_malloc(Type->num_pins * sizeof(int));
00528 for(i = 0; i < Type->num_pins; ++i)
00529 {
00530 pin_used[i] = FALSE;
00531 }
00532
00533
00534 CurClass = 0;
00535 Cur = Classes->child;
00536 while(Cur)
00537 {
00538 CheckElement(Cur, "class");
00539
00540
00541 IsGlobal = FALSE;
00542 Prop = FindProperty(Cur, "type", TRUE);
00543 if(0 == strcmp(Prop, "global"))
00544 {
00545 IsGlobal = TRUE;
00546 }
00547 ezxml_set_attr(Cur, "type", NULL);
00548
00549
00550 Tokens = GetNodeTokens(Cur);
00551 assert(CountTokens(Tokens) ==
00552 Type->class_inf[CurClass].num_pins);
00553 for(j = 0; j < Type->class_inf[CurClass].num_pins; ++j)
00554 {
00555 CurPin = my_atoi(Tokens[j]);
00556
00557
00558 if(pin_used[CurPin])
00559 {
00560 printf(ERRTAG
00561 "Pin %d is defined in two different classes in type '%s'.\n",
00562 CurPin, Type->name);
00563 exit(1);
00564 }
00565 pin_used[CurPin] = TRUE;
00566
00567
00568 for(i = 0; i < Type->capacity; ++i)
00569 {
00570 Type->pin_class[CurPin + (i * PinsPerSubtile)] =
00571 CurClass + (i * ClassesPerSubtile);
00572 Type->is_global_pin[CurPin +
00573 (i * PinsPerSubtile)] =
00574 IsGlobal;
00575 }
00576 }
00577 FreeTokens(&Tokens);
00578 ++CurClass;
00579 Prev = Cur;
00580 Cur = Cur->next;
00581 FreeNode(Prev);
00582 }
00583 if(pin_used)
00584 {
00585 free(pin_used);
00586 pin_used = NULL;
00587 }
00588 }
00589
00590
00591
00592
00593
00594 static void
00595 SetupPinLocations(ezxml_t Locations,
00596 t_type_descriptor * Type)
00597 {
00598 int i, j, k, l, PinsPerSubtile, Count, Len;
00599
00600 ezxml_t Cur, Prev;
00601 const char *Prop;
00602 char **Tokens, **CurTokens;
00603
00604 PinsPerSubtile = Type->num_pins / Type->capacity;
00605
00606
00607 Type->pinloc = (int ***)my_malloc(Type->height * sizeof(int **));
00608 for(i = 0; i < Type->height; ++i)
00609 {
00610 Type->pinloc[i] = (int **)my_malloc(4 * sizeof(int *));
00611 for(j = 0; j < 4; ++j)
00612 {
00613 Type->pinloc[i][j] =
00614 (int *)my_malloc(Type->num_pins * sizeof(int));
00615 for(k = 0; k < Type->num_pins; ++k)
00616 {
00617 Type->pinloc[i][j][k] = 0;
00618 }
00619 }
00620 }
00621
00622
00623 Cur = Locations->child;
00624 while(Cur)
00625 {
00626 CheckElement(Cur, "loc");
00627
00628
00629 i = 0;
00630 Prop = FindProperty(Cur, "offset", FALSE);
00631 if(Prop)
00632 {
00633 i = my_atoi(Prop);
00634 if((i < 0) || (i >= Type->height))
00635 {
00636 printf(ERRTAG
00637 "%d is an invalid offset for type '%s'.\n",
00638 i, Type->name);
00639 exit(1);
00640 }
00641 ezxml_set_attr(Cur, "offset", NULL);
00642 }
00643
00644
00645 Prop = FindProperty(Cur, "side", TRUE);
00646 if(0 == strcmp(Prop, "left"))
00647 {
00648 j = LEFT;
00649 }
00650
00651 else if(0 == strcmp(Prop, "top"))
00652 {
00653 j = TOP;
00654 }
00655
00656 else if(0 == strcmp(Prop, "right"))
00657 {
00658 j = RIGHT;
00659 }
00660
00661 else if(0 == strcmp(Prop, "bottom"))
00662 {
00663 j = BOTTOM;
00664 }
00665
00666 else
00667 {
00668 printf(ERRTAG "'%s' is not a valid side.\n", Prop);
00669 exit(1);
00670 }
00671 ezxml_set_attr(Cur, "side", NULL);
00672
00673
00674 if((TOP == j) && (i != (Type->height - 1)))
00675 {
00676 printf(ERRTAG
00677 "Locations are only allowed on large block "
00678 "perimeter. 'top' side should be at offset %d only.\n",
00679 (Type->height - 1));
00680 exit(1);
00681 }
00682 if((BOTTOM == j) && (i != 0))
00683 {
00684 printf(ERRTAG
00685 "Locations are only allowed on large block "
00686 "perimeter. 'bottom' side should be at offset 0 only.\n");
00687 exit(1);
00688 }
00689
00690
00691 CountTokensInString(Cur->txt, &Count, &Len);
00692 if(Count > 0)
00693 {
00694 Tokens = GetNodeTokens(Cur);
00695 CurTokens = Tokens;
00696 while(*CurTokens)
00697 {
00698
00699
00700 k = my_atoi(*CurTokens);
00701 if(k >= Type->num_pins)
00702 {
00703 printf(ERRTAG
00704 "Pin %d of type '%s' is not a valid pin.\n",
00705 k, Type->name);
00706 exit(1);
00707 }
00708
00709
00710 for(l = 0; l < Type->capacity; ++l)
00711 {
00712 Type->pinloc[i][j][k + (l * PinsPerSubtile)] = 1;
00713 }
00714
00715
00716 ++CurTokens;
00717 }
00718 FreeTokens(&Tokens);
00719 }
00720 Prev = Cur;
00721 Cur = Cur->next;
00722 FreeNode(Prev);
00723 }
00724 }
00725
00726
00727
00728
00729 static void
00730 SetupGridLocations(ezxml_t Locations,
00731 t_type_descriptor * Type)
00732 {
00733 int i;
00734
00735 ezxml_t Cur, Prev;
00736 const char *Prop;
00737
00738 Type->num_grid_loc_def = CountChildren(Locations, "loc");
00739 Type->grid_loc_def =
00740 (struct s_grid_loc_def *)my_calloc(Type->num_grid_loc_def,
00741 sizeof(struct s_grid_loc_def));
00742
00743
00744 Cur = Locations->child;
00745 i = 0;
00746 while(Cur)
00747 {
00748 CheckElement(Cur, "loc");
00749
00750
00751 Prop = FindProperty(Cur, "type", TRUE);
00752 if(Prop)
00753 {
00754 if(strcmp(Prop, "fill") == 0)
00755 {
00756 if(Type->num_grid_loc_def != 1)
00757 {
00758 printf(ERRTAG
00759 "Another loc specified for fill.\n");
00760 exit(1);
00761 }
00762 Type->grid_loc_def[i].grid_loc_type = FILL;
00763 FILL_TYPE = Type;
00764 }
00765 else if(strcmp(Prop, "col") == 0)
00766 {
00767 Type->grid_loc_def[i].grid_loc_type = COL_REPEAT;
00768 }
00769 else if(strcmp(Prop, "rel") == 0)
00770 {
00771 Type->grid_loc_def[i].grid_loc_type = COL_REL;
00772 }
00773 else
00774 {
00775 printf(ERRTAG
00776 "Unknown grid location type '%s' for type '%s'.\n",
00777 Prop, Type->name);
00778 exit(1);
00779 }
00780 ezxml_set_attr(Cur, "type", NULL);
00781 }
00782 Prop = FindProperty(Cur, "start", FALSE);
00783 if(Type->grid_loc_def[i].grid_loc_type == COL_REPEAT)
00784 {
00785 if(Prop == NULL)
00786 {
00787 printf(ERRTAG
00788 "grid location property 'start' must be specified for grid location type 'col'.\n");
00789 exit(1);
00790 }
00791 Type->grid_loc_def[i].start_col = my_atoi(Prop);
00792 ezxml_set_attr(Cur, "start", NULL);
00793 }
00794 else if(Prop != NULL)
00795 {
00796 printf(ERRTAG
00797 "grid location property 'start' valid for grid location type 'col' only.\n");
00798 exit(1);
00799 }
00800 Prop = FindProperty(Cur, "repeat", FALSE);
00801 if(Type->grid_loc_def[i].grid_loc_type == COL_REPEAT)
00802 {
00803 if(Prop != NULL)
00804 {
00805 Type->grid_loc_def[i].repeat = my_atoi(Prop);
00806 ezxml_set_attr(Cur, "repeat", NULL);
00807 }
00808 }
00809 else if(Prop != NULL)
00810 {
00811 printf(ERRTAG
00812 "grid location property 'repeat' valid for grid location type 'col' only.\n");
00813 exit(1);
00814 }
00815 Prop = FindProperty(Cur, "pos", FALSE);
00816 if(Type->grid_loc_def[i].grid_loc_type == COL_REL)
00817 {
00818 if(Prop == NULL)
00819 {
00820 printf(ERRTAG
00821 "grid location property 'pos' must be specified for grid location type 'rel'.\n");
00822 exit(1);
00823 }
00824 Type->grid_loc_def[i].col_rel = atof(Prop);
00825 ezxml_set_attr(Cur, "pos", NULL);
00826 }
00827 else if(Prop != NULL)
00828 {
00829 printf(ERRTAG
00830 "grid location property 'pos' valid for grid location type 'rel' only.\n");
00831 exit(1);
00832 }
00833 Prop = FindProperty(Cur, "priority", FALSE);
00834 if(Prop)
00835 {
00836 Type->grid_loc_def[i].priority = my_atoi(Prop);
00837 ezxml_set_attr(Cur, "priority", NULL);
00838 }
00839 Prev = Cur;
00840 Cur = Cur->next;
00841 FreeNode(Prev);
00842 i++;
00843 }
00844 }
00845 static void
00846 SetupTypeTiming(ezxml_t timing,
00847 t_type_descriptor * Type)
00848 {
00849 ezxml_t Cur, Prev;
00850 const char *Prop;
00851 float value;
00852 char **Tokens;
00853
00854
00855
00856 Type->type_timing_inf.T_fb_ipin_to_sblk_ipin = 0;
00857 Type->type_timing_inf.T_sblk_opin_to_fb_opin = 0;
00858 Type->type_timing_inf.T_sblk_opin_to_sblk_ipin = 0;
00859
00860
00861 Cur = timing->child;
00862 while(Cur)
00863 {
00864 CheckElement(Cur, "tedge");
00865
00866
00867 Prop = FindProperty(Cur, "type", TRUE);
00868 Tokens = GetNodeTokens(Cur);
00869 if(CountTokens(Tokens) != 1)
00870 {
00871 printf(ERRTAG
00872 "Timing for sequential subblock edges not a number.");
00873 }
00874 value = atof(Tokens[0]);
00875 if(0 == strcmp(Prop, "T_fb_ipin_to_sblk_ipin"))
00876 {
00877 Type->type_timing_inf.T_fb_ipin_to_sblk_ipin = value;
00878 }
00879 else if(0 == strcmp(Prop, "T_sblk_opin_to_fb_opin"))
00880 {
00881 Type->type_timing_inf.T_sblk_opin_to_fb_opin = value;
00882 }
00883 else if(0 == strcmp(Prop, "T_sblk_opin_to_sblk_ipin"))
00884 {
00885 Type->type_timing_inf.T_sblk_opin_to_sblk_ipin = value;
00886 }
00887 else
00888 {
00889 printf(ERRTAG "'%s' is an unrecognized timing edge.\n",
00890 Prop);
00891 exit(1);
00892 }
00893 ezxml_set_attr(Cur, "type", NULL);
00894 Prev = Cur;
00895 Cur = Cur->next;
00896 FreeNode(Prev);
00897 FreeTokens(&Tokens);
00898 }
00899 }
00900 static void
00901 SetupSubblocksTcomb(ezxml_t timing,
00902 t_type_descriptor * Type)
00903 {
00904 ezxml_t Cur, prev;
00905 t_T_subblock ** T_subblock_ptr;
00906 float **t_comb;
00907 int i, j;
00908 char **Tokens;
00909
00910 T_subblock_ptr = &Type->type_timing_inf.T_subblock;
00911 t_comb =
00912 (float **)alloc_matrix(0, Type->max_subblock_inputs - 1, 0,
00913 Type->max_subblock_outputs - 1, sizeof(float));
00914 for(i = 0; i < Type->max_subblock_inputs; i++)
00915 {
00916 for(j = 0; j < Type->max_subblock_outputs; j++)
00917 {
00918 t_comb[i][j] = 0;
00919 }
00920 }
00921
00922
00923 Cur = timing->child;
00924 i = 0;
00925 while(Cur)
00926 {
00927 CheckElement(Cur, "trow");
00928 Tokens = GetNodeTokens(Cur);
00929 if(CountTokens(Tokens) != Type->max_subblock_outputs)
00930 {
00931 printf(ERRTAG
00932 "Number of tokens %d not equal number of subblock outputs %d.",
00933 CountTokens(Tokens),
00934 Type->max_subblock_outputs);
00935 exit(1);
00936 }
00937 for(j = 0; j < Type->max_subblock_outputs; j++)
00938 {
00939 t_comb[i][j] = atof(Tokens[j]);
00940 }
00941 i++;
00942 prev = Cur;
00943 Cur = Cur->next;
00944 FreeNode(prev);
00945 FreeTokens(&Tokens);
00946 }
00947 if(i != Type->max_subblock_inputs)
00948 {
00949 printf(ERRTAG
00950 "Number of trow %d not equal number of subblock inputs %d.",
00951 i, Type->max_subblock_inputs);
00952 exit(1);
00953 }
00954 for(i = 0; i < Type->max_subblocks; i++)
00955 {
00956 (*T_subblock_ptr)[i].T_comb = t_comb;
00957 }
00958 }
00959 static void
00960 SetupSubblocksTSeq(ezxml_t timing_seq_in,
00961 ezxml_t timing_seq_out,
00962 t_type_descriptor * Type)
00963 {
00964 ezxml_t Cur, prev;
00965 t_T_subblock ** T_subblock_ptr;
00966 int i, j;
00967 float *t_seq[2];
00968
00969 ezxml_t seq_timing[2];
00970 char **Tokens;
00971
00972 T_subblock_ptr = &Type->type_timing_inf.T_subblock;
00973 seq_timing[0] = timing_seq_in;
00974 seq_timing[1] = timing_seq_out;
00975 t_seq[0] = (float *)my_calloc(Type->max_subblock_inputs, sizeof(float));
00976 t_seq[1] = (float *)my_calloc(Type->max_subblock_outputs, sizeof(float));
00977
00978
00979 for(i = 0; i < 2; i++)
00980 {
00981 Cur = seq_timing[i]->child;
00982 j = 0;
00983 while(Cur)
00984 {
00985 CheckElement(Cur, "trow");
00986 Tokens = GetNodeTokens(Cur);
00987 if(CountTokens(Tokens) != 1)
00988 {
00989 printf(ERRTAG
00990 "Timing for sequential subblock edges not a number.");
00991 }
00992 t_seq[i][j] = atof(Tokens[0]);
00993 j++;
00994 prev = Cur;
00995 Cur = Cur->next;
00996 FreeNode(prev);
00997 FreeTokens(&Tokens);
00998 }
00999 if(j != Type->max_subblock_outputs)
01000 {
01001 printf(ERRTAG
01002 "Number of trow %d not equal number of subblock outputs %d.",
01003 j, Type->max_subblock_outputs);
01004 exit(1);
01005 }
01006 }
01007 for(i = 0; i < Type->max_subblocks; i++)
01008 {
01009 (*T_subblock_ptr)[i].T_seq_in = t_seq[0];
01010 (*T_subblock_ptr)[i].T_seq_out = t_seq[1];
01011 }
01012 }
01013
01014
01015
01016
01017 static void
01018 Process_Fc(ezxml_t Fc_in_node,
01019 ezxml_t Fc_out_node,
01020 t_type_descriptor * Type)
01021 {
01022 enum Fc_type Type_in;
01023 enum Fc_type Type_out;
01024
01025 ParseFc(Fc_in_node, &Type_in, &Type->Fc_in);
01026 ParseFc(Fc_out_node, &Type_out, &Type->Fc_out);
01027 if(FC_FULL == Type_in)
01028 {
01029 printf(ERRTAG "'full' Fc type isn't allowed for Fc_in.\n");
01030 exit(1);
01031 }
01032 Type->is_Fc_out_full_flex = FALSE;
01033 Type->is_Fc_frac = FALSE;
01034 if(FC_FULL == Type_out)
01035 {
01036 Type->is_Fc_out_full_flex = TRUE;
01037 }
01038
01039 else if(Type_in != Type_out)
01040 {
01041 printf(ERRTAG
01042 "Fc_in and Fc_out must have same type unless Fc_out has type 'full'.\n");
01043 exit(1);
01044 }
01045 if(FC_FRAC == Type_in)
01046 {
01047 Type->is_Fc_frac = TRUE;
01048 }
01049 }
01050
01051
01052
01053 static void
01054 ProcessSubblocks(INOUT ezxml_t Parent,
01055 INOUT t_type_descriptor * Type,
01056 boolean timing_enabled)
01057 {
01058 const char *Prop;
01059
01060 ezxml_t CurType, Cur, Cur2;
01061 Type->max_subblocks = 1;
01062 Prop = FindProperty(Parent, "max_subblocks", FALSE);
01063 if(Prop)
01064 {
01065 Type->max_subblocks = my_atoi(Prop);
01066 ezxml_set_attr(Parent, "max_subblocks", NULL);
01067 }
01068 Type->max_subblock_inputs = 1;
01069 Prop = FindProperty(Parent, "max_subblock_inputs", FALSE);
01070 if(Prop)
01071 {
01072 Type->max_subblock_inputs = my_atoi(Prop);
01073 ezxml_set_attr(Parent, "max_subblock_inputs", NULL);
01074 }
01075 Type->max_subblock_outputs = 1;
01076 Prop = FindProperty(Parent, "max_subblock_outputs", FALSE);
01077 if(Prop)
01078 {
01079 Type->max_subblock_outputs = my_atoi(Prop);
01080 ezxml_set_attr(Parent, "max_subblock_outputs", NULL);
01081 }
01082 CurType = FindElement(Parent, "timing", timing_enabled);
01083 if(CurType != NULL)
01084 {
01085 Type->type_timing_inf.T_subblock =
01086 (t_T_subblock *) my_malloc(Type->max_subblocks *
01087 sizeof(t_T_subblock));
01088
01089
01090 Cur = FindElement(CurType, "T_comb", TRUE);
01091 SetupSubblocksTcomb(Cur, Type);
01092 FreeNode(Cur);
01093
01094
01095 Cur = FindElement(CurType, "T_seq_in", TRUE);
01096 Cur2 = FindElement(CurType, "T_seq_out", TRUE);
01097 SetupSubblocksTSeq(Cur, Cur2, Type);
01098 FreeNode(Cur);
01099 FreeNode(Cur2);
01100 FreeNode(CurType);
01101 }
01102 }
01103
01104
01105
01106 static void
01107 ProcessTypeProps(ezxml_t Node,
01108 t_type_descriptor * Type)
01109 {
01110 const char *Prop;
01111
01112
01113
01114 Prop = FindProperty(Node, "name", TRUE);
01115 Type->name = my_strdup(Prop);
01116 ezxml_set_attr(Node, "name", NULL);
01117
01118
01119 Type->capacity = 1;
01120
01121
01122 Type->height = 1;
01123 Prop = FindProperty(Node, "height", FALSE);
01124 if(Prop)
01125 {
01126 Type->height = my_atoi(Prop);
01127 ezxml_set_attr(Node, "height", NULL);
01128 }
01129 }
01130
01131
01132
01133
01134
01135 static void
01136 ProcessLayout(INOUT ezxml_t Node,
01137 OUT struct s_arch *arch)
01138 {
01139 const char *Prop;
01140
01141 arch->clb_grid.IsAuto = TRUE;
01142
01143
01144 Prop = FindProperty(Node, "width", FALSE);
01145 if(Prop != NULL)
01146 {
01147 arch->clb_grid.IsAuto = FALSE;
01148 arch->clb_grid.W = my_atoi(Prop);
01149 ezxml_set_attr(Node, "width", NULL);
01150 Prop = FindProperty(Node, "height", TRUE);
01151 if(Prop != NULL)
01152 {
01153 arch->clb_grid.H = my_atoi(Prop);
01154 ezxml_set_attr(Node, "height", NULL);
01155 }
01156 }
01157
01158
01159 Prop = FindProperty(Node, "auto", arch->clb_grid.IsAuto);
01160 if(Prop != NULL)
01161 {
01162 if(arch->clb_grid.IsAuto == FALSE)
01163 {
01164 printf(ERRTAG
01165 "Auto-sizing, width and height cannot be specified\n");
01166 }
01167 arch->clb_grid.Aspect = atof(Prop);
01168 ezxml_set_attr(Node, "auto", NULL);
01169 }
01170 }
01171
01172
01173
01174
01175
01176 static void
01177 ProcessDevice(INOUT ezxml_t Node,
01178 OUT struct s_arch *arch,
01179 IN boolean timing_enabled)
01180 {
01181 const char *Prop;
01182
01183 ezxml_t Cur;
01184 Cur = FindElement(Node, "sizing", TRUE);
01185 arch->R_minW_nmos = 0;
01186 Prop = FindProperty(Cur, "R_minW_nmos", timing_enabled);
01187 if(Prop != NULL)
01188 {
01189 arch->R_minW_nmos = atof(Prop);
01190 ezxml_set_attr(Cur, "R_minW_nmos", NULL);
01191 }
01192 arch->R_minW_pmos = 0;
01193 Prop = FindProperty(Cur, "R_minW_pmos", timing_enabled);
01194 if(Prop != NULL)
01195 {
01196 arch->R_minW_pmos = atof(Prop);
01197 ezxml_set_attr(Cur, "R_minW_pmos", NULL);
01198 }
01199 arch->ipin_mux_trans_size = 0;
01200 Prop = FindProperty(Cur, "ipin_mux_trans_size", FALSE);
01201 if(Prop != NULL)
01202 {
01203 arch->ipin_mux_trans_size = atof(Prop);
01204 ezxml_set_attr(Cur, "ipin_mux_trans_size", NULL);
01205 }
01206 FreeNode(Cur);
01207 Cur = FindElement(Node, "timing", timing_enabled);
01208 if(Cur != NULL)
01209 {
01210 arch->C_ipin_cblock = 0;
01211 Prop = FindProperty(Cur, "C_ipin_cblock", FALSE);
01212 if(Prop != NULL)
01213 {
01214 arch->C_ipin_cblock = atof(Prop);
01215 ezxml_set_attr(Cur, "C_ipin_cblock", NULL);
01216 }
01217 arch->T_ipin_cblock = 0;
01218 Prop = FindProperty(Cur, "T_ipin_cblock", FALSE);
01219 if(Prop != NULL)
01220 {
01221 arch->T_ipin_cblock = atof(Prop);
01222 ezxml_set_attr(Cur, "T_ipin_cblock", NULL);
01223 }
01224 FreeNode(Cur);
01225 }
01226 Cur = FindElement(Node, "area", TRUE);
01227 Prop = FindProperty(Cur, "grid_logic_tile_area", FALSE);
01228 arch->grid_logic_tile_area = 0;
01229 if(Prop != NULL)
01230 {
01231 arch->grid_logic_tile_area = atof(Prop);
01232 ezxml_set_attr(Cur, "grid_logic_tile_area", NULL);
01233 }
01234 FreeNode(Cur);
01235 Cur = FindElement(Node, "chan_width_distr", FALSE);
01236 if(Cur != NULL)
01237 {
01238 ProcessChanWidthDistr(Cur, arch);
01239 FreeNode(Cur);
01240 }
01241 Cur = FindElement(Node, "switch_block", TRUE);
01242 Prop = FindProperty(Cur, "type", TRUE);
01243 if(strcmp(Prop, "wilton") == 0)
01244 {
01245 arch->SBType = WILTON;
01246 }
01247 else if(strcmp(Prop, "universal") == 0)
01248 {
01249 arch->SBType = UNIVERSAL;
01250 }
01251 else if(strcmp(Prop, "subset") == 0)
01252 {
01253 arch->SBType = SUBSET;
01254 }
01255 else
01256 {
01257 printf(ERRTAG "Unknown property %s for switch block type x\n",
01258 Prop);
01259 exit(1);
01260 }
01261 ezxml_set_attr(Cur, "type", NULL);
01262 Prop = FindProperty(Cur, "fs", TRUE);
01263 arch->Fs = my_atoi(Prop);
01264 ezxml_set_attr(Cur, "fs", NULL);
01265 FreeNode(Cur);
01266 }
01267
01268
01269
01270
01271
01272 static void
01273 ProcessChanWidthDistr(INOUT ezxml_t Node,
01274 OUT struct s_arch *arch)
01275 {
01276 const char *Prop;
01277
01278 ezxml_t Cur;
01279 Cur = FindElement(Node, "io", TRUE);
01280 Prop = FindProperty(Cur, "width", TRUE);
01281 arch->Chans.chan_width_io = atof(Prop);
01282 ezxml_set_attr(Cur, "width", NULL);
01283 FreeNode(Cur);
01284 Cur = FindElement(Node, "x", TRUE);
01285 ProcessChanWidthDistrDir(Cur, &arch->Chans.chan_x_dist);
01286 FreeNode(Cur);
01287 Cur = FindElement(Node, "y", TRUE);
01288 ProcessChanWidthDistrDir(Cur, &arch->Chans.chan_y_dist);
01289 FreeNode(Cur);
01290 }
01291
01292
01293
01294
01295 static void
01296 ProcessChanWidthDistrDir(INOUT ezxml_t Node,
01297 OUT t_chan * chan)
01298 {
01299 const char *Prop;
01300
01301 boolean hasXpeak, hasWidth, hasDc;
01302 hasXpeak = hasWidth = hasDc = FALSE;
01303 Prop = FindProperty(Node, "distr", TRUE);
01304 if(strcmp(Prop, "uniform") == 0)
01305 {
01306 chan->type = UNIFORM;
01307 }
01308 else if(strcmp(Prop, "gaussian") == 0)
01309 {
01310 chan->type = GAUSSIAN;
01311 hasXpeak = hasWidth = hasDc = TRUE;
01312 }
01313 else if(strcmp(Prop, "pulse") == 0)
01314 {
01315 chan->type = PULSE;
01316 hasXpeak = hasWidth = hasDc = TRUE;
01317 }
01318 else if(strcmp(Prop, "delta") == 0)
01319 {
01320 hasXpeak = hasDc = TRUE;
01321 chan->type = DELTA;
01322 }
01323 else
01324 {
01325 printf(ERRTAG "Unknown property %s for chan_width_distr x\n",
01326 Prop);
01327 exit(1);
01328 }
01329 ezxml_set_attr(Node, "distr", NULL);
01330 Prop = FindProperty(Node, "peak", TRUE);
01331 chan->peak = atof(Prop);
01332 ezxml_set_attr(Node, "peak", NULL);
01333 Prop = FindProperty(Node, "width", hasWidth);
01334 if(hasWidth)
01335 {
01336 chan->width = atof(Prop);
01337 ezxml_set_attr(Node, "width", NULL);
01338 }
01339 Prop = FindProperty(Node, "xpeak", hasXpeak);
01340 if(hasXpeak)
01341 {
01342 chan->xpeak = atof(Prop);
01343 ezxml_set_attr(Node, "xpeak", NULL);
01344 }
01345 Prop = FindProperty(Node, "dc", hasDc);
01346 if(hasDc)
01347 {
01348 chan->dc = atof(Prop);
01349 ezxml_set_attr(Node, "dc", NULL);
01350 }
01351 }
01352 static void
01353 SetupEmptyType()
01354 {
01355 t_type_descriptor * type;
01356 type = &type_descriptors[EMPTY_TYPE->index];
01357 type->name = "<EMPTY>";
01358 type->num_pins = 0;
01359 type->height = 1;
01360 type->capacity = 0;
01361 type->num_drivers = 0;
01362 type->num_receivers = 0;
01363 type->pinloc = NULL;
01364 type->num_class = 0;
01365 type->class_inf = NULL;
01366 type->pin_class = NULL;
01367 type->is_global_pin = NULL;
01368 type->is_Fc_frac = TRUE;
01369 type->is_Fc_out_full_flex = FALSE;
01370 type->Fc_in = 0;
01371 type->Fc_out = 0;
01372 type->max_subblocks = 0;
01373 type->max_subblock_inputs = 0;
01374 type->max_subblock_outputs = 0;
01375
01376
01377 type->grid_loc_def = NULL;
01378 type->num_grid_loc_def = 0;
01379 }
01380
01381
01382
01383
01384
01385 static void
01386 ProcessIO(INOUT ezxml_t Node,
01387 IN boolean timing_enabled)
01388 {
01389 const char *Prop;
01390
01391 ezxml_t Cur, Cur2;
01392 int i, j;
01393
01394 t_type_descriptor * type;
01395 int num_inputs, num_outputs, num_clocks, num_pins, capacity, t_in, t_out;
01396 enum
01397 { INCLASS = 0, OUTCLASS = 1, CLKCLASS = 2 };
01398
01399 type = &type_descriptors[IO_TYPE->index];
01400 num_inputs = 1;
01401 num_outputs = 1;
01402 num_clocks = 1;
01403 CheckElement(Node, "io");
01404 type->name = ".io";
01405 type->height = 1;
01406
01407
01408 Prop = FindProperty(Node, "capacity", TRUE);
01409 capacity = my_atoi(Prop);
01410 type->capacity = capacity;
01411 ezxml_set_attr(Node, "capacity", NULL);
01412
01413
01414 Cur = FindElement(Node, "fc_in", TRUE);
01415 Cur2 = FindElement(Node, "fc_out", TRUE);
01416 Process_Fc(Cur, Cur2, type);
01417 FreeNode(Cur);
01418 FreeNode(Cur2);
01419
01420
01421 num_pins = 3 * capacity;
01422 type->num_pins = num_pins;
01423 type->num_drivers = num_outputs * capacity;
01424 type->num_receivers = num_inputs * capacity;
01425 type->pinloc =
01426 (int ***)alloc_matrix3(0, 0, 0, 3, 0, num_pins - 1, sizeof(int));
01427
01428
01429
01430
01431 for(i = 0; i < num_pins; ++i)
01432 {
01433 for(j = 0; j < 4; ++j)
01434 {
01435 type->pinloc[0][j][i] = 1;
01436 }
01437 }
01438
01439
01440 type->num_class = 3 * capacity;
01441 type->class_inf =
01442 (struct s_class *)my_malloc(sizeof(struct s_class) * 3 * capacity);
01443 type->pin_class = (int *)my_malloc(sizeof(int) * num_pins);
01444 type->is_global_pin = (boolean *) my_malloc(sizeof(boolean) * num_pins);
01445 for(j = 0; j < capacity; ++j)
01446 {
01447
01448
01449 type->class_inf[3 * j + INCLASS].num_pins = num_inputs;
01450 type->class_inf[3 * j + INCLASS].type = RECEIVER;
01451 type->class_inf[3 * j + INCLASS].pinlist =
01452 (int *)my_malloc(sizeof(int) * num_inputs);
01453 for(i = 0; i < num_inputs; ++i)
01454 {
01455 type->class_inf[3 * j + INCLASS].pinlist[i] =
01456 num_pins * j / capacity + i;
01457 type->pin_class[num_pins * j / capacity + i] =
01458 3 * j + INCLASS;
01459 type->is_global_pin[num_pins * j / capacity + i] = FALSE;
01460 }
01461 type->class_inf[3 * j + OUTCLASS].num_pins = num_outputs;
01462 type->class_inf[3 * j + OUTCLASS].type = DRIVER;
01463 type->class_inf[3 * j + OUTCLASS].pinlist =
01464 (int *)my_malloc(sizeof(int) * num_outputs);
01465 for(i = 0; i < num_outputs; ++i)
01466 {
01467 type->class_inf[3 * j + OUTCLASS].pinlist[i] =
01468 num_pins * j / capacity + i + num_inputs;
01469 type->pin_class[num_pins * j / capacity + i +
01470 num_inputs] = 3 * j + OUTCLASS;
01471 type->is_global_pin[num_pins * j / capacity + i +
01472 num_inputs] = FALSE;
01473 }
01474 type->class_inf[3 * j + CLKCLASS].num_pins = num_clocks;
01475 type->class_inf[3 * j + CLKCLASS].type = RECEIVER;
01476 type->class_inf[3 * j + CLKCLASS].pinlist =
01477 (int *)my_malloc(sizeof(int) * num_clocks);
01478 for(i = 0; i < num_clocks; ++i)
01479 {
01480 type->class_inf[3 * j + CLKCLASS].pinlist[i] =
01481 num_pins * j / capacity + i + num_inputs +
01482 num_outputs;
01483 type->pin_class[num_pins * j / capacity + i +
01484 num_inputs + num_outputs] =
01485 3 * j + CLKCLASS;
01486 type->is_global_pin[num_pins * j / capacity + i +
01487 num_inputs + num_outputs] = TRUE;
01488 }
01489 }
01490 type->max_subblocks = 1;
01491 type->max_subblock_inputs = 1;
01492 type->max_subblock_outputs = 1;
01493
01494
01495 type->num_grid_loc_def = 1;
01496 type->grid_loc_def =
01497 (struct s_grid_loc_def *)my_calloc(1, sizeof(struct s_grid_loc_def));
01498 type->grid_loc_def[0].grid_loc_type = BOUNDARY;
01499 type->grid_loc_def[0].priority = 0;
01500 t_in = -1;
01501 t_out = -1;
01502 Prop = FindProperty(Node, "t_inpad", timing_enabled);
01503 if(Prop != NULL)
01504 {
01505 t_in = atof(Prop);
01506 ezxml_set_attr(Node, "t_inpad", NULL);
01507 }
01508 Prop = FindProperty(Node, "t_outpad", timing_enabled);
01509 if(Prop != NULL)
01510 {
01511 t_out = atof(Prop);
01512 ezxml_set_attr(Node, "t_outpad", NULL);
01513 }
01514 if(timing_enabled)
01515 {
01516 type->type_timing_inf.T_fb_ipin_to_sblk_ipin = 0;
01517 type->type_timing_inf.T_sblk_opin_to_fb_opin = 0;
01518 type->type_timing_inf.T_sblk_opin_to_sblk_ipin = 0;
01519 type->type_timing_inf.T_subblock =
01520 (t_T_subblock *) my_malloc(sizeof(t_T_subblock));
01521 type->type_timing_inf.T_subblock[0].T_comb =
01522 (float **)my_malloc(sizeof(float *));
01523 type->type_timing_inf.T_subblock[0].T_comb[0] =
01524 (float *)my_malloc(sizeof(float));
01525 type->type_timing_inf.T_subblock[0].T_comb[0][0] = t_out;
01526 type->type_timing_inf.T_subblock[0].T_seq_in =
01527 (float *)my_malloc(sizeof(float));
01528 type->type_timing_inf.T_subblock[0].T_seq_in[0] = 0;
01529 type->type_timing_inf.T_subblock[0].T_seq_out =
01530 (float *)my_malloc(sizeof(float));
01531 type->type_timing_inf.T_subblock[0].T_seq_out[0] = t_in;
01532 }
01533 }
01534
01535
01536
01537
01538
01539 static void
01540 ProcessTypes(INOUT ezxml_t Node,
01541 OUT t_type_descriptor ** Types,
01542 OUT int *NumTypes,
01543 boolean timing_enabled)
01544 {
01545 ezxml_t CurType, Prev;
01546 ezxml_t Cur, Cur2;
01547 t_type_descriptor * Type;
01548 int i;
01549
01550
01551
01552
01553
01554
01555 *NumTypes = CountChildren(Node, "type") + 2;
01556 *Types = (t_type_descriptor *)
01557 my_malloc(sizeof(t_type_descriptor) * (*NumTypes));
01558 EMPTY_TYPE = &type_descriptors[EMPTY_TYPE_INDEX];
01559 IO_TYPE = &type_descriptors[IO_TYPE_INDEX];
01560 type_descriptors[EMPTY_TYPE_INDEX].index = EMPTY_TYPE_INDEX;
01561 type_descriptors[IO_TYPE_INDEX].index = IO_TYPE_INDEX;
01562 SetupEmptyType();
01563 Cur = FindElement(Node, "io", TRUE);
01564 ProcessIO(Cur, timing_enabled);
01565 FreeNode(Cur);
01566
01567
01568 i = 2;
01569 CurType = Node->child;
01570 while(CurType)
01571 {
01572 CheckElement(CurType, "type");
01573
01574
01575 Type = &(*Types)[i];
01576
01577
01578 ProcessTypeProps(CurType, Type);
01579
01580
01581 Cur = FindElement(CurType, "subblocks", TRUE);
01582 ProcessSubblocks(Cur, Type, timing_enabled);
01583 FreeNode(Cur);
01584
01585
01586 Cur = FindElement(CurType, "fc_in", TRUE);
01587 Cur2 = FindElement(CurType, "fc_out", TRUE);
01588 Process_Fc(Cur, Cur2, Type);
01589 FreeNode(Cur);
01590 FreeNode(Cur2);
01591
01592
01593 Cur = FindElement(CurType, "pinclasses", TRUE);
01594 SetupPinClasses(Cur, Type);
01595 FreeNode(Cur);
01596 Cur = FindElement(CurType, "pinlocations", TRUE);
01597 SetupPinLocations(Cur, Type);
01598 FreeNode(Cur);
01599 Cur = FindElement(CurType, "gridlocations", TRUE);
01600 SetupGridLocations(Cur, Type);
01601 FreeNode(Cur);
01602 Cur = FindElement(CurType, "timing", timing_enabled);
01603 if(Cur)
01604 {
01605 SetupTypeTiming(Cur, Type);
01606 FreeNode(Cur);
01607 }
01608 Type->index = i;
01609
01610
01611 ++i;
01612
01613
01614 Prev = CurType;
01615 CurType = CurType->next;
01616 FreeNode(Prev);
01617 }
01618 if(FILL_TYPE == NULL)
01619 {
01620 printf(ERRTAG "grid location type 'fill' must be specified.\n");
01621 exit(1);
01622 }
01623 }
01624
01625
01626
01627
01628 void
01629 XmlReadArch(IN const char *ArchFile,
01630 IN boolean timing_enabled,
01631 OUT struct s_arch *arch,
01632 OUT t_type_descriptor ** Types,
01633 OUT int *NumTypes)
01634 {
01635 ezxml_t Cur, Next;
01636
01637
01638 Cur = ezxml_parse_file(ArchFile);
01639 if(NULL == Cur)
01640 {
01641 printf(ERRTAG "Unable to load architecture file '%s'.\n",
01642 ArchFile);
01643 }
01644
01645
01646 CheckElement(Cur, "architecture");
01647
01648
01649 Next = FindElement(Cur, "layout", TRUE);
01650 ProcessLayout(Next, arch);
01651 FreeNode(Next);
01652
01653
01654 Next = FindElement(Cur, "device", TRUE);
01655 ProcessDevice(Next, arch, timing_enabled);
01656 FreeNode(Next);
01657
01658
01659 Next = FindElement(Cur, "typelist", TRUE);
01660 ProcessTypes(Next, Types, NumTypes, timing_enabled);
01661 FreeNode(Next);
01662
01663
01664 Next = FindElement(Cur, "switchlist", TRUE);
01665 ProcessSwitches(Next, &(arch->Switches), &(arch->num_switches),
01666 timing_enabled);
01667 FreeNode(Next);
01668
01669
01670 Next = FindElement(Cur, "segmentlist", TRUE);
01671 ProcessSegments(Next, &(arch->Segments), &(arch->num_segments),
01672 arch->Switches, arch->num_switches, timing_enabled);
01673 FreeNode(Next);
01674
01675
01676 FreeNode(Cur);
01677 }
01678 static void
01679 ProcessSegments(INOUT ezxml_t Parent,
01680 OUT struct s_segment_inf **Segs,
01681 OUT int *NumSegs,
01682 IN struct s_switch_inf *Switches,
01683 IN int NumSwitches,
01684 IN boolean timing_enabled)
01685 {
01686 int i, j, length;
01687 const char *tmp;
01688
01689 ezxml_t SubElem;
01690 ezxml_t Node;
01691
01692
01693
01694 *NumSegs = CountChildren(Parent, "segment");
01695
01696
01697 *Segs = NULL;
01698 if(*NumSegs > 0)
01699 {
01700 *Segs =
01701 (struct s_segment_inf *)my_malloc(*NumSegs *
01702 sizeof(struct
01703 s_segment_inf));
01704 memset(*Segs, 0, (*NumSegs * sizeof(struct s_segment_inf)));
01705 }
01706
01707
01708 for(i = 0; i < *NumSegs; ++i)
01709 {
01710 Node = ezxml_child(Parent, "segment");
01711
01712
01713 length = 1;
01714 tmp = FindProperty(Node, "length", FALSE);
01715 if(tmp)
01716 {
01717 if(strcmp(tmp, "longline") == 0)
01718 {
01719 (*Segs)[i].longline = TRUE;
01720 }
01721 else
01722 {
01723 length = my_atoi(tmp);
01724 }
01725 }
01726 (*Segs)[i].length = length;
01727 ezxml_set_attr(Node, "length", NULL);
01728
01729
01730 (*Segs)[i].frequency = 1;
01731 tmp = FindProperty(Node, "freq", FALSE);
01732 if(tmp)
01733 {
01734 (*Segs)[i].frequency = (int) (atof(tmp) * MAX_CHANNEL_WIDTH);
01735 }
01736 ezxml_set_attr(Node, "freq", NULL);
01737
01738
01739 (*Segs)[i].Rmetal = 0;
01740 tmp = FindProperty(Node, "Rmetal", timing_enabled);
01741 if(tmp)
01742 {
01743 (*Segs)[i].Rmetal = atof(tmp);
01744 }
01745 ezxml_set_attr(Node, "Rmetal", NULL);
01746 (*Segs)[i].Cmetal = 0;
01747 tmp = FindProperty(Node, "Cmetal", timing_enabled);
01748 if(tmp)
01749 {
01750 (*Segs)[i].Cmetal = atof(tmp);
01751 }
01752 ezxml_set_attr(Node, "Cmetal", NULL);
01753
01754
01755 tmp = FindProperty(Node, "type", TRUE);
01756 if(0 == strcmp(tmp, "bidir"))
01757 {
01758 (*Segs)[i].directionality = BI_DIRECTIONAL;
01759 }
01760
01761 else if(0 == strcmp(tmp, "unidir"))
01762 {
01763 (*Segs)[i].directionality = UNI_DIRECTIONAL;
01764 }
01765
01766 else
01767 {
01768 printf(ERRTAG "Invalid switch type '%s'.\n", tmp);
01769 exit(1);
01770 }
01771 ezxml_set_attr(Node, "type", NULL);
01772
01773
01774 if(UNI_DIRECTIONAL == (*Segs)[i].directionality)
01775 {
01776 SubElem = FindElement(Node, "mux", TRUE);
01777 tmp = FindProperty(SubElem, "name", TRUE);
01778
01779
01780 for(j = 0; j < NumSwitches; ++j)
01781 {
01782 if(0 == strcmp(tmp, Switches[j].name))
01783 {
01784 break;
01785 }
01786 }
01787 if(j >= NumSwitches)
01788 {
01789 printf(ERRTAG "'%s' is not a valid mux name.\n",
01790 tmp);
01791 exit(1);
01792 }
01793 ezxml_set_attr(SubElem, "name", NULL);
01794 FreeNode(SubElem);
01795
01796
01797
01798
01799 (*Segs)[i].wire_switch = j;
01800 (*Segs)[i].opin_switch = j;
01801 }
01802
01803 else
01804 {
01805 assert(BI_DIRECTIONAL == (*Segs)[i].directionality);
01806 SubElem = FindElement(Node, "wire_switch", TRUE);
01807 tmp = FindProperty(SubElem, "name", TRUE);
01808
01809
01810 for(j = 0; j < NumSwitches; ++j)
01811 {
01812 if(0 == strcmp(tmp, Switches[j].name))
01813 {
01814 break;
01815 }
01816 }
01817 if(j >= NumSwitches)
01818 {
01819 printf(ERRTAG
01820 "'%s' is not a valid wire_switch name.\n",
01821 tmp);
01822 exit(1);
01823 }
01824 (*Segs)[i].wire_switch = j;
01825 ezxml_set_attr(SubElem, "name", NULL);
01826 FreeNode(SubElem);
01827 SubElem = FindElement(Node, "opin_switch", TRUE);
01828 tmp = FindProperty(SubElem, "name", TRUE);
01829
01830
01831 for(j = 0; j < NumSwitches; ++j)
01832 {
01833 if(0 == strcmp(tmp, Switches[j].name))
01834 {
01835 break;
01836 }
01837 }
01838 if(j >= NumSwitches)
01839 {
01840 printf(ERRTAG
01841 "'%s' is not a valid opin_switch name.\n",
01842 tmp);
01843 exit(1);
01844 }
01845 (*Segs)[i].opin_switch = j;
01846 ezxml_set_attr(SubElem, "name", NULL);
01847 FreeNode(SubElem);
01848 }
01849
01850
01851 (*Segs)[i].cb_len = length;
01852 (*Segs)[i].cb = (boolean *) my_malloc(length * sizeof(boolean));
01853 for(j = 0; j < length; ++j)
01854 {
01855 (*Segs)[i].cb[j] = TRUE;
01856 }
01857 SubElem = FindElement(Node, "cb", FALSE);
01858 if(SubElem)
01859 {
01860 ProcessCB_SB(SubElem, (*Segs)[i].cb, length);
01861 FreeNode(SubElem);
01862 }
01863
01864
01865 (*Segs)[i].sb_len = (length + 1);
01866 (*Segs)[i].sb =
01867 (boolean *) my_malloc((length + 1) * sizeof(boolean));
01868 for(j = 0; j < (length + 1); ++j)
01869 {
01870 (*Segs)[i].sb[j] = TRUE;
01871 }
01872 SubElem = FindElement(Node, "sb", FALSE);
01873 if(SubElem)
01874 {
01875 ProcessCB_SB(SubElem, (*Segs)[i].sb, (length + 1));
01876 FreeNode(SubElem);
01877 }
01878 FreeNode(Node);
01879 }
01880 }
01881 static void
01882 ProcessCB_SB(INOUT ezxml_t Node,
01883 INOUT boolean * list,
01884 IN int len)
01885 {
01886 const char *tmp = NULL;
01887 int i;
01888
01889
01890
01891
01892 tmp = FindProperty(Node, "type", TRUE);
01893 if(0 == strcmp(tmp, "pattern"))
01894 {
01895 i = 0;
01896
01897
01898 tmp = Node->txt;
01899 while(*tmp)
01900 {
01901 switch (*tmp)
01902 {
01903 case ' ':
01904 break;
01905 case 'T':
01906 case '1':
01907 if(i >= len)
01908 {
01909 printf(ERRTAG
01910 "CB or SB depopulation is too long. It "
01911
01912 "should be (length) symbols for CBs and (length+1) "
01913 "symbols for SBs.\n");
01914 exit(1);
01915 }
01916 list[i] = TRUE;
01917 ++i;
01918 break;
01919 case 'F':
01920 case '0':
01921 if(i >= len)
01922 {
01923 printf(ERRTAG
01924 "CB or SB depopulation is too long. It "
01925
01926 "should be (length) symbols for CBs and (length+1) "
01927 "symbols for SBs.\n");
01928 exit(1);
01929 }
01930 list[i] = FALSE;
01931 ++i;
01932 break;
01933 default:
01934 printf(ERRTAG "Invalid character %c in CB or "
01935 "SB depopulation list.\n", *tmp);
01936 exit(1);
01937 }
01938 ++tmp;
01939 }
01940 if(i < len)
01941 {
01942 printf(ERRTAG "CB or SB depopulation is too short. It "
01943 "should be (length) symbols for CBs and (length+1) "
01944 "symbols for SBs.\n");
01945 exit(1);
01946 }
01947
01948
01949 ezxml_set_txt(Node, "");
01950 }
01951
01952 else
01953 {
01954 printf(ERRTAG "'%s' is not a valid type for specifying "
01955 "cb and sb depopulation.\n", tmp);
01956 exit(1);
01957 }
01958 ezxml_set_attr(Node, "type", NULL);
01959 }
01960 static void
01961 ProcessSwitches(INOUT ezxml_t Parent,
01962 OUT struct s_switch_inf **Switches,
01963 OUT int *NumSwitches,
01964 IN boolean timing_enabled)
01965 {
01966 int i, j;
01967 const char *type_name;
01968 const char *switch_name;
01969 const char *Prop;
01970
01971 boolean has_buf_size;
01972 ezxml_t Node;
01973 has_buf_size = FALSE;
01974
01975
01976 *NumSwitches = CountChildren(Parent, "switch");
01977
01978
01979 *Switches = NULL;
01980 if(*NumSwitches > 0)
01981 {
01982 *Switches =
01983 (struct s_switch_inf *)my_malloc(*NumSwitches *
01984 sizeof(struct
01985 s_switch_inf));
01986 memset(*Switches, 0,
01987 (*NumSwitches * sizeof(struct s_switch_inf)));
01988 }
01989
01990
01991 for(i = 0; i < *NumSwitches; ++i)
01992 {
01993 Node = ezxml_child(Parent, "switch");
01994 switch_name = FindProperty(Node, "name", TRUE);
01995 type_name = FindProperty(Node, "type", TRUE);
01996
01997
01998 for(j = 0; j < i; ++j)
01999 {
02000 if(0 == strcmp((*Switches)[j].name, switch_name))
02001 {
02002 printf(ERRTAG
02003 "Two switches with the same name '%s' were "
02004 "found.\n", switch_name);
02005 exit(1);
02006 }
02007 }
02008 (*Switches)[i].name = my_strdup(switch_name);
02009 ezxml_set_attr(Node, "name", NULL);
02010
02011
02012 if(0 == strcmp(type_name, "mux"))
02013 {
02014 (*Switches)[i].buffered = TRUE;
02015 has_buf_size = TRUE;
02016 }
02017
02018 else if(0 == strcmp(type_name, "pass_trans"))
02019 {
02020 (*Switches)[i].buffered = FALSE;
02021 }
02022
02023 else if(0 == strcmp(type_name, "buffer"))
02024 {
02025 (*Switches)[i].buffered = TRUE;
02026 }
02027
02028 else
02029 {
02030 printf(ERRTAG "Invalid switch type '%s'.\n", type_name);
02031 exit(1);
02032 }
02033 ezxml_set_attr(Node, "type", NULL);
02034 Prop = FindProperty(Node, "R", timing_enabled);
02035 if(Prop != NULL)
02036 {
02037 (*Switches)[i].R = atof(Prop);
02038 ezxml_set_attr(Node, "R", NULL);
02039 }
02040 Prop = FindProperty(Node, "Cin", timing_enabled);
02041 if(Prop != NULL)
02042 {
02043 (*Switches)[i].Cin = atof(Prop);
02044 ezxml_set_attr(Node, "Cin", NULL);
02045 }
02046 Prop = FindProperty(Node, "Cout", timing_enabled);
02047 if(Prop != NULL)
02048 {
02049 (*Switches)[i].Cout = atof(Prop);
02050 ezxml_set_attr(Node, "Cout", NULL);
02051 }
02052 Prop = FindProperty(Node, "Tdel", timing_enabled);
02053 if(Prop != NULL)
02054 {
02055 (*Switches)[i].Tdel = atof(Prop);
02056 ezxml_set_attr(Node, "Tdel", NULL);
02057 }
02058 Prop = FindProperty(Node, "buf_size", has_buf_size);
02059 if(has_buf_size)
02060 {
02061 (*Switches)[i].buf_size = atof(Prop);
02062 ezxml_set_attr(Node, "buf_size", NULL);
02063 }
02064 Prop = FindProperty(Node, "mux_trans_size", FALSE);
02065 if(Prop != NULL)
02066 {
02067 (*Switches)[i].mux_trans_size = atof(Prop);
02068 ezxml_set_attr(Node, "mux_trans_size", NULL);
02069 }
02070
02071
02072 FreeNode(Node);
02073 }
02074 }
02075
02076
02077
02078
02079 void
02080 EchoArch(IN const char *EchoFile,
02081 IN const t_type_descriptor * Types,
02082 IN int NumTypes)
02083 {
02084 int i, j, k;
02085
02086 FILE * Echo;
02087 Echo = my_fopen(EchoFile, "w");
02088 for(i = 0; i < NumTypes; ++i)
02089 {
02090 fprintf(Echo, "Type: \"%s\"\n", Types[i].name);
02091 fprintf(Echo, "\tcapacity: %d\n", Types[i].capacity);
02092 fprintf(Echo, "\theight: %d\n", Types[i].height);
02093 if(Types[i].num_pins > 0)
02094 {
02095 for(j = 0; j < Types[i].height; ++j)
02096 {
02097 fprintf(Echo,
02098 "\tpinloc[%d] TOP LEFT BOTTOM RIGHT:\n",
02099 j);
02100 for(k = 0; k < Types[i].num_pins; ++k)
02101 {
02102 fprintf(Echo, "\t\t%d %d %d %d\n",
02103 Types[i].pinloc[j][TOP][k],
02104 Types[i].pinloc[j][LEFT][k],
02105 Types[i].pinloc[j][BOTTOM][k],
02106 Types[i].pinloc[j][RIGHT][k]);
02107 }
02108 }
02109 }
02110 fprintf(Echo, "\tnum_pins (scaled for capacity): %d\n",
02111 Types[i].num_pins);
02112 if(Types[i].num_pins > 0)
02113 {
02114 fprintf(Echo, "\tPins: NAME CLASS IS_GLOBAL\n");
02115 for(j = 0; j < Types[i].num_pins; ++j)
02116 {
02117 fprintf(Echo, "\t\t%d %d %s\n", j,
02118 Types[i].pin_class[j],
02119 (Types[i].
02120 is_global_pin[j] ? "TRUE" : "FALSE"));
02121 }
02122 }
02123 fprintf(Echo, "\tnum_class: %d\n", Types[i].num_class);
02124 if(Types[i].num_class > 0)
02125 {
02126 for(j = 0; j < Types[i].num_class; ++j)
02127 {
02128 switch (Types[i].class_inf[j].type)
02129 {
02130 case RECEIVER:
02131 fprintf(Echo, "\t\tType: RECEIVER\n");
02132 break;
02133 case DRIVER:
02134 fprintf(Echo, "\t\tType: DRIVER\n");
02135 break;
02136 case OPEN:
02137 fprintf(Echo, "\t\tType: OPEN\n");
02138 break;
02139 default:
02140 fprintf(Echo, "\t\tType: UNKNOWN\n");
02141 break;
02142 }
02143 fprintf(Echo, "\t\t\tnum_pins: %d\n",
02144 Types[i].class_inf[j].num_pins);
02145 fprintf(Echo, "\t\t\tpins: ");
02146 for(k = 0; k < Types[i].class_inf[j].num_pins;
02147 ++k)
02148 {
02149 fprintf(Echo, "%d ", Types[i].class_inf[j].pinlist[k]);
02150 }
02151 fprintf(Echo, "\n");
02152 }
02153 }
02154 fprintf(Echo, "\tis_Fc_frac: %s\n",
02155 (Types[i].is_Fc_frac ? "TRUE" : "FALSE"));
02156 fprintf(Echo, "\tis_Fc_out_full_flex: %s\n",
02157 (Types[i].is_Fc_out_full_flex ? "TRUE" : "FALSE"));
02158 fprintf(Echo, "\tFc_in: %f\n", Types[i].Fc_in);
02159 fprintf(Echo, "\tFc_out: %f\n", Types[i].Fc_out);
02160 fprintf(Echo, "\tmax_subblocks: %d\n", Types[i].max_subblocks);
02161 fprintf(Echo, "\tmax_subblock_inputs: %d\n",
02162 Types[i].max_subblock_inputs);
02163 fprintf(Echo, "\tmax_subblock_outputs: %d\n",
02164 Types[i].max_subblock_outputs);
02165 fprintf(Echo, "\tnum_drivers: %d\n", Types[i].num_drivers);
02166 fprintf(Echo, "\tnum_receivers: %d\n", Types[i].num_receivers);
02167 fprintf(Echo, "\tindex: %d\n", Types[i].index);
02168 fprintf(Echo, "\n");
02169 }
02170 fclose(Echo);
02171 }
02172
02173