VPR-6.0

libvpr/read_xml_arch_file.c

Go to the documentation of this file.
00001 #include <string.h>
00002 #include <assert.h>
00003 #include "util.h"
00004 #include "arch_types.h"
00005 #include "ReadLine.h"
00006 #include "ezxml.h"
00007 #include "read_xml_arch_file.h"
00008 #include "read_xml_util.h"
00009 
00010 /* special type indexes, necessary for initialization initialization, everything afterwards
00011    should use the pointers to these type indices*/ 
00012 
00013 #define NUM_MODELS_IN_LIBRARY 4
00014 #define EMPTY_TYPE_INDEX 0
00015 #define IO_TYPE_INDEX 1
00016     enum Fc_type
00017 { FC_ABS, FC_FRAC, FC_FULL };
00018 
00019 /** This identifies the t_type_ptr of an IO block */
00020 static t_type_ptr IO_TYPE = NULL;
00021 
00022 /** This identifies the t_type_ptr of an Empty block */
00023 static t_type_ptr EMPTY_TYPE = NULL;
00024 
00025 /*& This identifies the t_type_ptr of the default logic block */
00026 static t_type_ptr FILL_TYPE = NULL;
00027 
00028 /** Describes the different types of CLBs available */
00029 static struct s_type_descriptor *type_descriptors;
00030 
00031 /* Function prototypes */ 
00032 /*   Populate data */
00033 static void ParseFc(ezxml_t Node,
00034                      enum Fc_type *Fc,
00035                      float *Val);
00036 static void SetupEmptyType();
00037 static void SetupPinLocationsAndPinClasses(ezxml_t Locations,
00038                                t_type_descriptor * Type);
00039 static void SetupGridLocations(ezxml_t Locations,
00040                                 t_type_descriptor * Type);
00041 #if 0
00042 static void SetupTypeTiming(ezxml_t timing,
00043                              t_type_descriptor * Type);
00044 #endif
00045 /*    Process XML hiearchy */
00046 static void ProcessPb_Type(INOUTP ezxml_t Parent, 
00047                                                    t_pb_type * pb_type, 
00048                                                    t_mode * mode);
00049 static void ProcessPb_TypePort(INOUTP ezxml_t Parent, 
00050                                                    t_port * port);
00051 static void ProcessPinToPinAnnotations(ezxml_t parent, 
00052                                                    t_pin_to_pin_annotation *annotation);
00053 static void ProcessInterconnect(INOUTP ezxml_t Parent,
00054                                                    t_mode * mode);
00055 static void ProcessMode(INOUTP ezxml_t Parent,
00056                                                    t_mode * mode);
00057 static void Process_Fc(ezxml_t Fc_in_node,
00058                         ezxml_t Fc_out_node,
00059                         t_type_descriptor * Type);
00060 static void ProcessComplexBlockProps(ezxml_t Node,
00061                               t_type_descriptor * Type);
00062 static void ProcessChanWidthDistr(INOUTP ezxml_t Node,
00063                                    OUTP struct s_arch *arch);
00064 static void ProcessChanWidthDistrDir(INOUTP ezxml_t Node,
00065                                       OUTP t_chan * chan);
00066 static void ProcessModels(INOUTP ezxml_t Node,
00067                            OUTP struct s_arch *arch);
00068 static void ProcessLayout(INOUTP ezxml_t Node,
00069                            OUTP struct s_arch *arch);
00070 static void ProcessDevice(INOUTP ezxml_t Node,
00071                            OUTP struct s_arch *arch,
00072                            INP boolean timing_enabled);
00073 static void alloc_and_load_default_child_for_pb_type(INOUTP t_pb_type *pb_type, char *new_name, t_pb_type *copy);
00074 static void ProcessLutClass(INOUTP t_pb_type *lut_pb_type);
00075 static void ProcessMemoryClass(INOUTP t_pb_type *mem_pb_type);
00076 static void ProcessComplexBlocks(INOUTP ezxml_t Node,
00077                           OUTP t_type_descriptor ** Types,
00078                           OUTP int *NumTypes,
00079                           INP boolean timing_enabled);
00080 static void ProcessSwitches(INOUTP ezxml_t Node,
00081                              OUTP struct s_switch_inf **Switches,
00082                              OUTP int *NumSwitches,
00083                              INP boolean timing_enabled);
00084 static void ProcessSegments(INOUTP ezxml_t Parent,
00085                              OUTP struct s_segment_inf **Segs,
00086                              OUTP int *NumSegs,
00087                              INP struct s_switch_inf *Switches,
00088                              INP int NumSwitches,
00089                              INP boolean timing_enabled);
00090 static void ProcessCB_SB(INOUTP ezxml_t Node,
00091                           INOUTP boolean * list,
00092                           INP int len);
00093 
00094 static void CreateModelLibrary(OUTP struct s_arch *arch);
00095 static void UpdateAndCheckModels(INOUTP struct s_arch *arch);
00096 static void SyncModelsPbTypes(INOUTP struct s_arch *arch, INP t_type_descriptor * Types, INP int NumTypes);
00097 static void AddModelsToPbTypes_rec(INOUTP t_pb_type *pb_type);
00098 static void SyncModelsPbTypes_rec(INOUTP struct s_arch *arch, INP t_pb_type *pb_type);
00099 
00100 static void PrintPb_types_rec(INP FILE * Echo, INP const t_pb_type * pb_type, int level);
00101 
00102 
00103 /** Figures out the Fc type and value for the given node. Unlinks the 
00104  * type and value. */ 
00105 static void
00106 ParseFc(ezxml_t Node, enum Fc_type *Fc, float *Val)
00107 {
00108     const char *Prop;
00109 
00110     Prop = FindProperty(Node, "type", TRUE);
00111     if(0 == strcmp(Prop, "abs"))
00112         {
00113             *Fc = FC_ABS;
00114         }
00115     
00116     else if(0 == strcmp(Prop, "frac"))
00117         {
00118             *Fc = FC_FRAC;
00119         }
00120     
00121     else if(0 == strcmp(Prop, "full"))
00122         {
00123             *Fc = FC_FULL;
00124         }
00125     
00126     else
00127         {
00128             printf(ERRTAG "[LINE %d] Invalid type '%s' for Fc. Only abs, frac " 
00129                         "and full are allowed.\n", Node->line, Prop);
00130             exit(1);
00131         }
00132     switch (*Fc)
00133         {
00134         case FC_FULL:
00135             *Val = 0.0;
00136             break;
00137         case FC_ABS:
00138         case FC_FRAC:
00139             *Val = atof(Node->txt);
00140             ezxml_set_attr(Node, "type", NULL);
00141             ezxml_set_txt(Node, "");
00142             break;
00143         default:
00144             assert(0);
00145         }
00146     
00147         /* Release the property */ 
00148         ezxml_set_attr(Node, "type", NULL);
00149 }
00150 
00151 /** Sets up the pinloc map and pin classes for the type. Unlinks the loc nodes
00152  * from the XML tree.
00153  * Pins and pin classses must already be setup by SetupPinClasses 
00154  */ 
00155 static void
00156 SetupPinLocationsAndPinClasses(ezxml_t Locations, t_type_descriptor * Type)
00157 {
00158     int i, j, k, PinsPerSubtile, Count, Len;
00159         int capacity, pin_count;
00160         int num_class;
00161         const char * Prop;
00162 
00163     ezxml_t Cur, Prev;
00164     char **Tokens, **CurTokens;
00165 
00166         capacity = Type->capacity;
00167 
00168     PinsPerSubtile = Type->num_pins / Type->capacity;
00169 
00170         Prop = FindProperty(Locations, "pattern", TRUE);
00171         if(strcmp(Prop, "spread") == 0) {
00172                 Type->pin_location_distribution = E_SPREAD_PIN_DISTR;
00173         } else if (strcmp(Prop,"custom") == 0) {
00174                 Type->pin_location_distribution = E_CUSTOM_PIN_DISTR;
00175         } else {
00176                 printf(ERRTAG "[LINE %d] %s is an invalid pin location pattern.\n", Locations->line, Prop);
00177                 exit(1);
00178         }
00179         ezxml_set_attr(Locations, "pattern", NULL);
00180     
00181         /* Alloc and clear pin locations */ 
00182         Type->pinloc = (int ***)my_malloc(Type->height * sizeof(int **));
00183         Type->pin_height = (int *)my_calloc(Type->num_pins, sizeof(int));
00184     for(i = 0; i < Type->height; ++i)
00185         {
00186             Type->pinloc[i] = (int **)my_malloc(4 * sizeof(int *));
00187             for(j = 0; j < 4; ++j)
00188                 {
00189                     Type->pinloc[i][j] =
00190                         (int *)my_malloc(Type->num_pins * sizeof(int));
00191                     for(k = 0; k < Type->num_pins; ++k)
00192                         {
00193                             Type->pinloc[i][j][k] = 0;
00194                         }
00195                 }
00196         }
00197 
00198         Type->pin_loc_assignments = (char****) my_malloc(Type->height * sizeof(char***));
00199         Type->num_pin_loc_assignments = (int**) my_malloc(Type->height * sizeof(int*));
00200         for(i = 0; i < Type->height; i++) {
00201                 Type->pin_loc_assignments[i] = (char***) my_calloc(4, sizeof(char**));
00202                 Type->num_pin_loc_assignments[i] = (int*) my_calloc(4, sizeof(int));    
00203         }
00204     
00205         /* Load the pin locations */ 
00206         if(Type->pin_location_distribution == E_CUSTOM_PIN_DISTR) {
00207                 Cur = Locations->child;
00208                 while(Cur)
00209                 {
00210                         CheckElement(Cur, "loc");
00211                     
00212                         /* Get offset */ 
00213                         i = GetIntProperty(Cur, "offset", FALSE, 0);
00214                         if((i < 0) || (i >= Type->height))
00215                         {
00216                                 printf(ERRTAG
00217                                         "[LINE %d] %d is an invalid offset for type '%s'.\n", Cur->line,
00218                                         i, Type->name);
00219                                 exit(1);
00220                         }
00221 
00222                         /* Get side */ 
00223                         Prop = FindProperty(Cur, "side", TRUE);
00224                         if(0 == strcmp(Prop, "left"))
00225                         {
00226                                 j = LEFT;
00227                         }
00228                     
00229                         else if(0 == strcmp(Prop, "top"))
00230                         {
00231                                 j = TOP;
00232                         }
00233                     
00234                         else if(0 == strcmp(Prop, "right"))
00235                         {
00236                                 j = RIGHT;
00237                         }
00238                     
00239                         else if(0 == strcmp(Prop, "bottom"))
00240                         {
00241                                 j = BOTTOM;
00242                         }
00243                     
00244                         else
00245                         {
00246                                 printf(ERRTAG "[LINE %d] '%s' is not a valid side.\n", Cur->line, Prop);
00247                                 exit(1);
00248                         }
00249                         ezxml_set_attr(Cur, "side", NULL);
00250                     
00251                         /* Check location is on perimeter */ 
00252                         if((TOP == j) && (i != (Type->height - 1)))
00253                         {
00254                                 printf(ERRTAG
00255                                         "[LINE %d] Locations are only allowed on large block " 
00256                                         "perimeter. 'top' side should be at offset %d only.\n", Cur->line,
00257                                         (Type->height - 1));
00258                                 exit(1);
00259                         }
00260                         if((BOTTOM == j) && (i != 0))
00261                         {
00262                                 printf(ERRTAG
00263                                         "[LINE %d] Locations are only allowed on large block "
00264                                         "perimeter. 'bottom' side should be at offset 0 only.\n", Cur->line);
00265                                 exit(1);
00266                         }
00267                     
00268                         /* Go through lists of pins */ 
00269                         CountTokensInString(Cur->txt, &Count, &Len);
00270                         Type->num_pin_loc_assignments[i][j] = Count;
00271                         if(Count > 0) 
00272                         {
00273                                 Tokens = GetNodeTokens(Cur);
00274                                 CurTokens = Tokens;
00275                                 Type->pin_loc_assignments[i][j] = (char**) my_calloc(Count, sizeof(char*));
00276                                 for(k = 0; k < Count; k++) {
00277                                         /* Store location assignment */
00278                                         Type->pin_loc_assignments[i][j][k] = my_strdup(*CurTokens);
00279                                                                                     
00280                                         /* Advance through list of pins in this location */ 
00281                                         ++CurTokens;
00282                                 }
00283                                 FreeTokens(&Tokens);
00284                         }
00285                         Prev = Cur;
00286                         Cur = Cur->next;
00287                         FreeNode(Prev);
00288                 }
00289         }
00290 
00291         /* Setup pin classes */
00292         num_class = 0;
00293         for(i = 0; i < Type->pb_type->num_ports; i++) {
00294                 if(Type->pb_type->ports[i].equivalent) {
00295                         num_class += capacity;
00296                 } else {
00297                         num_class += capacity * Type->pb_type->ports[i].num_pins;
00298                 }
00299         }
00300         Type->class_inf = my_calloc(num_class, sizeof(struct s_class));
00301         Type->num_class = num_class;
00302         Type->pin_class = my_malloc(Type->num_pins * sizeof(int) * capacity);
00303         Type->is_global_pin = my_malloc(Type->num_pins * sizeof(boolean) * capacity);
00304         for(i = 0; i < Type->num_pins * capacity; i++) {
00305                 Type->pin_class[i] = OPEN;
00306                 Type->is_global_pin[i] = OPEN;
00307         }
00308 
00309         pin_count = 0;
00310 
00311         /* Equivalent pins share the same class, non-equivalent pins belong to different pin classes */
00312         num_class = 0;
00313         for(i = 0; i < capacity; ++i)
00314         {
00315                 for(j = 0; j < Type->pb_type->num_ports; ++j)
00316                 {
00317                         if(Type->pb_type->ports[j].equivalent) {
00318                                 Type->class_inf[num_class].num_pins = Type->pb_type->ports[j].num_pins;
00319                                 Type->class_inf[num_class].pinlist = 
00320                                         (int *)my_malloc(sizeof(int) * Type->pb_type->ports[j].num_pins);
00321                         }
00322         
00323                         for(k = 0; k < Type->pb_type->ports[j].num_pins; ++k)
00324                         {
00325                                 if(!Type->pb_type->ports[j].equivalent) {
00326                                         Type->class_inf[num_class].num_pins = 1;
00327                                         Type->class_inf[num_class].pinlist = (int *)my_malloc(sizeof(int) * 1);
00328                                         Type->class_inf[num_class].pinlist[0] = pin_count;
00329                                 } else {
00330                                         Type->class_inf[num_class].pinlist[k] = pin_count;
00331                                 }
00332 
00333                                 if(Type->pb_type->ports[j].type == IN_PORT) {
00334                                         Type->class_inf[num_class].type = RECEIVER;
00335                                 } else {
00336                                         assert(Type->pb_type->ports[j].type == OUT_PORT);
00337                                         Type->class_inf[num_class].type = DRIVER;
00338                                 }
00339                                 Type->pin_class[pin_count] = num_class;
00340                                 Type->is_global_pin[pin_count] = Type->pb_type->ports[j].is_clock;
00341                                 pin_count++;
00342 
00343                                 if(!Type->pb_type->ports[j].equivalent) {
00344                                         num_class++;
00345                                 }
00346                         }
00347                         if(Type->pb_type->ports[j].equivalent) {
00348                                 num_class++;
00349                         }
00350                 }
00351         }
00352         assert(num_class == Type->num_class);
00353         assert(pin_count == Type->num_pins);
00354 }
00355 
00356 /** Sets up the grid_loc_def for the type. Unlinks the loc nodes
00357  * from the XML tree. 
00358  */ 
00359 static void
00360 SetupGridLocations(ezxml_t Locations, t_type_descriptor * Type)
00361 {
00362     int i;
00363 
00364     ezxml_t Cur, Prev;
00365     const char *Prop;
00366 
00367     Type->num_grid_loc_def = CountChildren(Locations, "loc", 1);
00368     Type->grid_loc_def = 
00369         (struct s_grid_loc_def *)my_calloc(Type->num_grid_loc_def,
00370                                            sizeof(struct s_grid_loc_def));
00371     
00372         /* Load the pin locations */ 
00373         Cur = Locations->child;
00374     i = 0;
00375     while(Cur)
00376         {
00377             CheckElement(Cur, "loc");
00378             
00379                 /* loc index */ 
00380                 Prop = FindProperty(Cur, "type", TRUE);
00381             if(Prop)
00382                 {
00383                         if(strcmp(Prop, "perimeter") == 0)
00384                         {
00385                             if(Type->num_grid_loc_def != 1)
00386                                 {
00387                                     printf(ERRTAG
00388                                                 "[LINE %d] Another loc specified for perimeter.\n", Cur->line);
00389                                     exit(1);
00390                                 }
00391                             Type->grid_loc_def[i].grid_loc_type = BOUNDARY;
00392                             assert(IO_TYPE == Type); /* IO goes to boundary */
00393                         } else if(strcmp(Prop, "fill") == 0)
00394                         {
00395                             if(Type->num_grid_loc_def != 1 || FILL_TYPE != NULL)
00396                                 {
00397                                     printf(ERRTAG
00398                                                 "[LINE %d] Another loc specified for fill.\n", Cur->line);
00399                                     exit(1);
00400                                 }
00401                             Type->grid_loc_def[i].grid_loc_type = FILL;
00402                             FILL_TYPE = Type;
00403                         }
00404                     else if(strcmp(Prop, "col") == 0)
00405                         {
00406                             Type->grid_loc_def[i].grid_loc_type = COL_REPEAT;
00407                         }
00408                     else if(strcmp(Prop, "rel") == 0)
00409                         {
00410                             Type->grid_loc_def[i].grid_loc_type = COL_REL;
00411                         }
00412                     else
00413                         {
00414                             printf(ERRTAG
00415                                         "[LINE %d] Unknown grid location type '%s' for type '%s'.\n", Cur->line,
00416                                     Prop, Type->name);
00417                             exit(1);
00418                         }
00419                     ezxml_set_attr(Cur, "type", NULL);
00420                 }
00421             Prop = FindProperty(Cur, "start", FALSE);
00422             if(Type->grid_loc_def[i].grid_loc_type == COL_REPEAT)
00423                 {
00424                     if(Prop == NULL)
00425                         {
00426                             printf(ERRTAG
00427                                     "[LINE %d] grid location property 'start' must be specified for grid location type 'col'.\n",
00428                                         Cur->line);
00429                             exit(1);
00430                         }
00431                     Type->grid_loc_def[i].start_col = my_atoi(Prop);
00432                     ezxml_set_attr(Cur, "start", NULL);
00433                 }
00434             else if(Prop != NULL)
00435                 {
00436                     printf(ERRTAG
00437                             "[LINE %d] grid location property 'start' valid for grid location type 'col' only.\n",
00438                                 Cur->line);
00439                     exit(1);
00440                 }
00441             Prop = FindProperty(Cur, "repeat", FALSE);
00442             if(Type->grid_loc_def[i].grid_loc_type == COL_REPEAT)
00443                 {
00444                     if(Prop != NULL)
00445                         {
00446                             Type->grid_loc_def[i].repeat = my_atoi(Prop);
00447                             ezxml_set_attr(Cur, "repeat", NULL);
00448                         }
00449                 }
00450             else if(Prop != NULL)
00451                 {
00452                     printf(ERRTAG
00453                             "[LINE %d] grid location property 'repeat' valid for grid location type 'col' only.\n",
00454                                 Cur->line);
00455                     exit(1);
00456                 }
00457             Prop = FindProperty(Cur, "pos", FALSE);
00458             if(Type->grid_loc_def[i].grid_loc_type == COL_REL)
00459                 {
00460                     if(Prop == NULL)
00461                         {
00462                             printf(ERRTAG
00463                                     "[LINE %d] grid location property 'pos' must be specified for grid location type 'rel'.\n",
00464                                         Cur->line);
00465                             exit(1);
00466                         }
00467                     Type->grid_loc_def[i].col_rel = atof(Prop);
00468                     ezxml_set_attr(Cur, "pos", NULL);
00469                 }
00470             else if(Prop != NULL)
00471                 {
00472                     printf(ERRTAG
00473                             "[LINE %d] grid location property 'pos' valid for grid location type 'rel' only.\n",
00474                                 Cur->line);
00475                     exit(1);
00476                 }
00477 
00478                 Type->grid_loc_def[i].priority = GetIntProperty(Cur, "priority", FALSE, 1);
00479 
00480             Prev = Cur;
00481             Cur = Cur->next;
00482             FreeNode(Prev);
00483             i++;
00484         }
00485 }
00486 
00487 static void
00488 ProcessPinToPinAnnotations(ezxml_t Parent, t_pin_to_pin_annotation *annotation)
00489 {
00490         int i = 0;
00491         const char *Prop;
00492         
00493         if(FindProperty(Parent, "max", FALSE)) {
00494                 i++;
00495         }
00496         if(FindProperty(Parent, "min", FALSE)) {
00497                 i++;
00498         }
00499         if(FindProperty(Parent, "type", FALSE)) {
00500                 i++;
00501         }
00502         if(FindProperty(Parent, "value", FALSE)) {
00503                 i++;
00504         }
00505         if(0 == strcmp(Parent->name, "C_constant") || 0 == strcmp(Parent->name, "C_matrix")) {
00506                 i = 1;
00507         }
00508 
00509         annotation->num_value_prop_pairs = i;
00510         annotation->prop = my_calloc(i, sizeof(int));
00511         annotation->value = my_calloc(i, sizeof(char *));
00512 
00513         i = 0;
00514         if(0 == strcmp(Parent->name, "delay_constant")) {
00515                 annotation->type = (int) E_ANNOT_PIN_TO_PIN_DELAY;
00516                 annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
00517                 Prop = FindProperty(Parent, "max", FALSE);
00518                 if(Prop) {
00519                         annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_MAX;
00520                         annotation->value[i] = my_strdup(Prop);
00521                         ezxml_set_attr(Parent, "max", NULL);
00522                         i++;
00523                 }
00524                 Prop = FindProperty(Parent, "min", FALSE);
00525                 if(Prop) {
00526                         annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_MIN;
00527                         annotation->value[i] = my_strdup(Prop);
00528                         ezxml_set_attr(Parent, "min", NULL);
00529                         i++;
00530                 }
00531                 Prop = FindProperty(Parent, "in_port", TRUE);
00532                 annotation->input_pins = my_strdup(Prop);
00533                 ezxml_set_attr(Parent, "in_port", NULL);
00534                 Prop = FindProperty(Parent, "out_port", TRUE);
00535                 annotation->output_pins = my_strdup(Prop);
00536                 ezxml_set_attr(Parent, "out_port", NULL);
00537         } else if (0 == strcmp(Parent->name, "delay_matrix")) {
00538                 annotation->type = (int) E_ANNOT_PIN_TO_PIN_DELAY;
00539                 annotation->format = E_ANNOT_PIN_TO_PIN_MATRIX;
00540                 Prop = FindProperty(Parent, "type", TRUE);
00541                 annotation->value[i] = my_strdup(Parent->txt);
00542                 ezxml_set_txt(Parent, "");
00543                 if(0 == strcmp(Prop, "max")) {
00544                         annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_MAX;
00545                 } else {
00546                         assert(0 == strcmp(Prop, "min"));
00547                         annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_MIN;
00548                 }
00549                 ezxml_set_attr(Parent, "type", NULL);
00550                 i++;
00551                 Prop = FindProperty(Parent, "in_port", TRUE);
00552                 annotation->input_pins = my_strdup(Prop);
00553                 ezxml_set_attr(Parent, "in_port", NULL);
00554                 Prop = FindProperty(Parent, "out_port", TRUE);
00555                 annotation->output_pins = my_strdup(Prop);
00556                 ezxml_set_attr(Parent, "out_port", NULL);
00557         } else if (0 == strcmp(Parent->name, "C_constant")) {
00558                 annotation->type = (int) E_ANNOT_PIN_TO_PIN_CAPACITANCE;
00559                 annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
00560                 Prop = FindProperty(Parent, "C", TRUE);
00561                 annotation->value[i] = my_strdup(Prop);
00562                 ezxml_set_attr(Parent, "C", NULL);
00563                 annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_CAPACITANCE_C;
00564                 i++;
00565 
00566                 Prop = FindProperty(Parent, "in_port", FALSE);
00567                 annotation->input_pins = my_strdup(Prop);
00568                 ezxml_set_attr(Parent, "in_port", NULL);
00569                 Prop = FindProperty(Parent, "out_port", FALSE);
00570                 annotation->output_pins = my_strdup(Prop);
00571                 ezxml_set_attr(Parent, "out_port", NULL);
00572                 assert(annotation->output_pins != NULL || annotation->input_pins != NULL);
00573         } else if (0 == strcmp(Parent->name, "C_matrix")) {
00574                 annotation->type = (int) E_ANNOT_PIN_TO_PIN_CAPACITANCE;
00575                 annotation->format = E_ANNOT_PIN_TO_PIN_MATRIX;
00576                 annotation->value[i] = my_strdup(Parent->txt);
00577                 ezxml_set_txt(Parent, "");
00578                 annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_CAPACITANCE_C;
00579                 i++;
00580                 Prop = FindProperty(Parent, "in_port", FALSE);
00581                 annotation->input_pins = my_strdup(Prop);
00582                 ezxml_set_attr(Parent, "in_port", NULL);
00583                 Prop = FindProperty(Parent, "out_port", FALSE);
00584                 annotation->output_pins = my_strdup(Prop);
00585                 ezxml_set_attr(Parent, "out_port", NULL);
00586                 assert(annotation->output_pins != NULL || annotation->input_pins != NULL);
00587         } else if (0 == strcmp(Parent->name, "T_setup")) {
00588                 annotation->type = (int) E_ANNOT_PIN_TO_PIN_DELAY;
00589                 annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
00590                 Prop = FindProperty(Parent, "value", TRUE);
00591                 annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_TSETUP;
00592                 annotation->value[i] = my_strdup(Prop);
00593                 ezxml_set_attr(Parent, "value", NULL);
00594                 i++;
00595                 Prop = FindProperty(Parent, "port", TRUE);
00596                 annotation->input_pins = my_strdup(Prop);
00597                 ezxml_set_attr(Parent, "port", NULL);
00598                 Prop = FindProperty(Parent, "clock", TRUE);
00599                 annotation->clock = my_strdup(Prop);
00600                 ezxml_set_attr(Parent, "clock", NULL);
00601         } else if (0 == strcmp(Parent->name, "T_clock_to_Q")) {
00602                 annotation->type = (int) E_ANNOT_PIN_TO_PIN_DELAY;
00603                 annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
00604                 Prop = FindProperty(Parent, "max", FALSE);
00605                 if(Prop) {
00606                         annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_CLOCK_TO_Q_MAX;
00607                         annotation->value[i] = my_strdup(Prop);
00608                         ezxml_set_attr(Parent, "max", NULL);
00609                         i++;
00610                 }
00611                 Prop = FindProperty(Parent, "min", FALSE);
00612                 if(Prop) {
00613                         annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_CLOCK_TO_Q_MIN;
00614                         annotation->value[i] = my_strdup(Prop);
00615                         ezxml_set_attr(Parent, "min", NULL);
00616                         i++;
00617                 }
00618                 
00619                 Prop = FindProperty(Parent, "port", TRUE);
00620                 annotation->input_pins = my_strdup(Prop);
00621                 ezxml_set_attr(Parent, "port", NULL);
00622                 Prop = FindProperty(Parent, "clock", TRUE);
00623                 annotation->clock = my_strdup(Prop);
00624                 ezxml_set_attr(Parent, "clock", NULL);
00625         } else if (0 == strcmp(Parent->name, "T_hold")) {
00626                 annotation->type = (int) E_ANNOT_PIN_TO_PIN_DELAY;
00627                 annotation->format = E_ANNOT_PIN_TO_PIN_CONSTANT;
00628                 Prop = FindProperty(Parent, "value", TRUE);
00629                 annotation->prop[i] = (int) E_ANNOT_PIN_TO_PIN_DELAY_THOLD;
00630                 annotation->value[i] = my_strdup(Prop);
00631                 ezxml_set_attr(Parent, "value", NULL);
00632                 i++;
00633                                 
00634                 Prop = FindProperty(Parent, "port", TRUE);
00635                 annotation->input_pins = my_strdup(Prop);
00636                 ezxml_set_attr(Parent, "port", NULL);
00637                 Prop = FindProperty(Parent, "clock", TRUE);
00638                 annotation->clock = my_strdup(Prop);
00639                 ezxml_set_attr(Parent, "clock", NULL);
00640         } else {
00641                 printf(ERRTAG "[LINE %d] Unknown port type %s in %s in %s", Parent->line,
00642                         Parent->name, Parent->parent->name, Parent->parent->parent->name);
00643                 exit(1);
00644         }
00645         assert (i == annotation->num_value_prop_pairs);
00646 }
00647 
00648 /** Takes in a pb_type, allocates and loads data for it and recurses downwards */
00649 static void ProcessPb_Type(INOUTP ezxml_t Parent, 
00650                                                    t_pb_type * pb_type, 
00651                                                    t_mode * mode) {
00652         int num_ports, i, j, num_annotations;
00653         const char *Prop;
00654         ezxml_t Cur, Prev;
00655         char* class_name;
00656 
00657         pb_type->parent_mode = mode;
00658         if(mode != NULL && mode->parent_pb_type != NULL) {
00659                 pb_type->depth = mode->parent_pb_type->depth + 1;
00660                 Prop = FindProperty(Parent, "name", TRUE);
00661                 pb_type->name = my_strdup(Prop);
00662                 ezxml_set_attr(Parent, "name", NULL);
00663         } else {
00664                 pb_type->depth = 0;
00665                 /* same name as type */
00666         }
00667 
00668         Prop = FindProperty(Parent, "blif_model", FALSE);
00669         pb_type->blif_model = my_strdup(Prop);
00670         ezxml_set_attr(Parent, "blif_model", NULL);
00671 
00672         pb_type->class_type = UNKNOWN_CLASS;
00673         Prop = FindProperty(Parent, "class", FALSE);
00674         class_name = my_strdup(Prop);
00675         
00676         if(class_name) {
00677                 ezxml_set_attr(Parent, "class", NULL);
00678                 if(0 == strcmp(class_name, "lut")) {
00679                         pb_type->class_type = LUT_CLASS;
00680                 } else if(0 == strcmp(class_name, "flipflop")) {
00681                         pb_type->class_type = LATCH_CLASS;
00682                 } else if(0 == strcmp(class_name, "memory")) {
00683                         pb_type->class_type = MEMORY_CLASS;
00684                 } else {
00685                         printf("[LINE %d] Unknown class %s in pb_type %s\n", Parent->line, class_name, pb_type->name);
00686                         exit(1);
00687                 }
00688                 free(class_name);
00689         }
00690         
00691         if(mode == NULL) {
00692                 pb_type->num_pb = 1;
00693         } else {
00694                 pb_type->num_pb = GetIntProperty(Parent, "num_pb", TRUE, 0);
00695         }
00696 
00697         assert(pb_type->num_pb > 0);
00698         num_ports = 0;
00699         num_ports += CountChildren(Parent, "input", 0);
00700         num_ports += CountChildren(Parent, "output", 0);
00701         num_ports += CountChildren(Parent, "clock", 0);
00702         pb_type->ports = my_calloc(num_ports, sizeof(t_port));
00703         pb_type->num_ports = num_ports;
00704         
00705         /* process ports */
00706         j = 0;
00707         for(i = 0; i < 3; i++) {
00708                 if(i == 0) {
00709                         Cur = FindFirstElement(Parent, "input", FALSE);
00710                 } else if (i ==1) {
00711                         Cur = FindFirstElement(Parent, "output", FALSE);
00712                 } else {
00713                         Cur = FindFirstElement(Parent, "clock", FALSE);
00714                 }
00715                 while (Cur != NULL)
00716                 {
00717                         ProcessPb_TypePort(Cur, &pb_type->ports[j]);
00718                         pb_type->ports[j].parent_pb_type = pb_type;
00719                                 
00720                         /* get next iteration */
00721                         Prev = Cur;
00722                         Cur = Cur->next;
00723                         j++;
00724                         FreeNode(Prev);
00725                 }
00726         }
00727         assert(j == num_ports);
00728 
00729         /* Count stats on the number of each type of pin */
00730         pb_type->num_clock_pins = pb_type->num_input_pins = pb_type->num_output_pins = 0;
00731         for(i = 0; i < pb_type->num_ports; i++) {
00732                 if(pb_type->ports[i].type == IN_PORT && pb_type->ports[i].is_clock == FALSE) {
00733                         pb_type->num_input_pins += pb_type->ports[i].num_pins;
00734                 } else if(pb_type->ports[i].type == OUT_PORT) {
00735                         assert(pb_type->ports[i].is_clock == FALSE);
00736                         pb_type->num_output_pins += pb_type->ports[i].num_pins;
00737                 } else {
00738                         assert(pb_type->ports[i].is_clock && pb_type->ports[i].type == IN_PORT);
00739                         pb_type->num_clock_pins += pb_type->ports[i].num_pins;
00740                 }
00741         }
00742 
00743         /* set max_internal_delay if exist */
00744         pb_type->max_internal_delay = UNDEFINED;
00745         Cur = FindElement(Parent, "max_internal_delay", FALSE);
00746         if(Cur) {
00747                 pb_type->max_internal_delay = GetFloatProperty(Cur, "value", TRUE, UNDEFINED);
00748                 FreeNode(Cur);
00749         }
00750         
00751         pb_type->annotations = NULL;
00752         pb_type->num_annotations = 0;
00753         i = 0;
00754         /* Determine if this is a leaf or container pb_type */
00755         if(pb_type->blif_model != NULL) {
00756                 /* Process delay and capacitance annotations */
00757                 num_annotations = 0;
00758                 num_annotations += CountChildren(Parent, "delay_constant", 0);
00759                 num_annotations += CountChildren(Parent, "delay_matrix", 0);
00760                 num_annotations += CountChildren(Parent, "C_constant", 0);
00761                 num_annotations += CountChildren(Parent, "C_matrix", 0);
00762                 num_annotations += CountChildren(Parent, "T_setup", 0);
00763                 num_annotations += CountChildren(Parent, "T_clock_to_Q", 0);
00764                 num_annotations += CountChildren(Parent, "T_hold", 0);
00765 
00766                 pb_type->annotations = my_calloc(num_annotations, sizeof(t_pin_to_pin_annotation));
00767                 pb_type->num_annotations = num_annotations;
00768 
00769                 j = 0;
00770                 Cur = NULL;
00771                 for(i = 0; i < 7; i++) {
00772                         if(i == 0) {
00773                                 Cur = FindFirstElement(Parent, "delay_constant", FALSE);
00774                         } else if (i == 1) {
00775                                 Cur = FindFirstElement(Parent, "delay_matrix", FALSE);
00776                         } else if (i == 2) {
00777                                 Cur = FindFirstElement(Parent, "C_constant", FALSE);
00778                         } else if (i == 3) {
00779                                 Cur = FindFirstElement(Parent, "C_matrix", FALSE);
00780                         } else if (i == 4) {
00781                                 Cur = FindFirstElement(Parent, "T_setup", FALSE);
00782                         } else if (i == 5) {
00783                                 Cur = FindFirstElement(Parent, "T_clock_to_Q", FALSE);
00784                         } else if (i == 6) {
00785                                 Cur = FindFirstElement(Parent, "T_hold", FALSE);
00786                         }
00787                         while (Cur != NULL)
00788                         {
00789                                 ProcessPinToPinAnnotations(Cur, &pb_type->annotations[j]);
00790 
00791                                 /* get next iteration */
00792                                 Prev = Cur;
00793                                 Cur = Cur->next;
00794                                 j++;
00795                                 FreeNode(Prev);
00796                         }
00797                 }
00798                 assert(j == num_annotations);
00799 
00800                 /* leaf pb_type, if special known class, then read class lib otherwise treat as primitive */
00801                 if(pb_type->class_type == LUT_CLASS) {
00802                         ProcessLutClass(pb_type);
00803                 } else if(pb_type->class_type == MEMORY_CLASS) {
00804                         ProcessMemoryClass(pb_type);
00805                 } else {
00806                         /* other leaf pb_type do not have modes */
00807                         pb_type->num_modes = 0;
00808                         assert(CountChildren(Parent, "mode", 0) == 0);
00809                 }
00810         } else {
00811                 /* container pb_type, process modes */
00812                 assert(pb_type->class_type == UNKNOWN_CLASS);
00813                 pb_type->num_modes = CountChildren(Parent, "mode", 0);
00814                 
00815                 if(pb_type->num_modes == 0) {
00816                         /* The pb_type operates in an implied one mode */
00817                         pb_type->num_modes = 1;
00818                         pb_type->modes = my_calloc(pb_type->num_modes, sizeof(t_mode));
00819                         pb_type->modes[i].parent_pb_type = pb_type;                     
00820                         pb_type->modes[i].index = i;
00821                         ProcessMode(Parent, &pb_type->modes[i]);
00822                         i++;
00823                 } else {
00824                         pb_type->modes = my_calloc(pb_type->num_modes, sizeof(t_mode));
00825                 
00826                         Cur = FindFirstElement(Parent, "mode", TRUE);
00827                         while (Cur != NULL)
00828                         {
00829                                 if(0 == strcmp(Cur->name, "mode")) {
00830                                         pb_type->modes[i].parent_pb_type = pb_type;
00831                                         ProcessMode(Cur, &pb_type->modes[i]);
00832                                                         
00833                                         /* get next iteration */
00834                                         Prev = Cur;
00835                                         Cur = Cur->next;
00836                                         i++;
00837                                         FreeNode(Prev);
00838                                 }
00839                         }
00840                 }
00841                 assert(i == pb_type->num_modes);
00842         }   
00843 }
00844 
00845 static void ProcessPb_TypePort(INOUTP ezxml_t Parent, 
00846                                                            t_port * port) {
00847         const char *Prop;
00848         Prop = FindProperty(Parent, "name", TRUE);
00849         port->name = my_strdup(Prop);
00850         ezxml_set_attr(Parent, "name", NULL);
00851 
00852         Prop = FindProperty(Parent, "port_class", FALSE);
00853         port->port_class = my_strdup(Prop);
00854         ezxml_set_attr(Parent, "port_class", NULL);
00855 
00856         port->equivalent = GetBooleanProperty(Parent, "equivalent", FALSE, FALSE);
00857         port->num_pins = GetIntProperty(Parent, "num_pins", TRUE, 0);
00858         
00859         if(0 == strcmp(Parent->name, "input")) {
00860                 port->type = IN_PORT;
00861                 port->is_clock = FALSE;
00862         } else if (0 == strcmp(Parent->name, "output")) {
00863                 port->type = OUT_PORT;
00864                 port->is_clock = FALSE;
00865         } else if (0 == strcmp(Parent->name, "clock")) {
00866                 port->type = IN_PORT;
00867                 port->is_clock = TRUE;
00868         } else {
00869                 printf(ERRTAG "[LINE %d] Unknown port type %s", Parent->line, Parent->name);
00870                 exit(1);
00871         }
00872 }
00873 
00874 static void ProcessInterconnect(INOUTP ezxml_t Parent,
00875                                                                 t_mode * mode) {
00876         int num_interconnect = 0;
00877         int i, j, k, index, num_annotations;
00878         const char *Prop;
00879         ezxml_t Cur, Prev;
00880         ezxml_t Cur2, Prev2;
00881 
00882         num_interconnect += CountChildren(Parent, "complete", 0);
00883         num_interconnect += CountChildren(Parent, "direct", 0);
00884         num_interconnect += CountChildren(Parent, "mux", 0);
00885 
00886         mode->num_interconnect = num_interconnect;
00887         mode->interconnect = my_calloc(num_interconnect, sizeof(t_interconnect));
00888 
00889         i = 0;
00890         for(index = 0; index < 3; index++) {
00891                 if(index == 0) {
00892                         Cur = FindFirstElement(Parent, "complete", FALSE);
00893                 } else if (index == 1) {
00894                         Cur = FindFirstElement(Parent, "direct", FALSE);
00895                 } else { 
00896                         Cur = FindFirstElement(Parent, "mux", FALSE);
00897                 }
00898                 while (Cur != NULL)
00899                 {
00900                         if(0 == strcmp(Cur->name, "complete")) {
00901                                 mode->interconnect[i].type = COMPLETE_INTERC;
00902                         } else if(0 == strcmp(Cur->name, "direct")) {
00903                                 mode->interconnect[i].type = DIRECT_INTERC;
00904                         } else {
00905                                 assert(0 == strcmp(Cur->name, "mux"));
00906                                 mode->interconnect[i].type = MUX_INTERC;
00907                         } 
00908 
00909                         mode->interconnect[i].parent_mode_index = mode->index;
00910                         Prop = FindProperty(Cur, "input", TRUE);
00911                         mode->interconnect[i].input_string = my_strdup(Prop);
00912                         ezxml_set_attr(Cur, "input", NULL);
00913 
00914                         Prop = FindProperty(Cur, "output", TRUE);
00915                         mode->interconnect[i].output_string = my_strdup(Prop);
00916                         ezxml_set_attr(Cur, "output", NULL);
00917 
00918                         Prop = FindProperty(Cur, "name", TRUE);
00919                         mode->interconnect[i].name = my_strdup(Prop);
00920                         ezxml_set_attr(Cur, "name", NULL);
00921 
00922                         /* Process delay and capacitance annotations */
00923                         num_annotations = 0;
00924                         num_annotations += CountChildren(Cur, "delay_constant", 0);
00925                         num_annotations += CountChildren(Cur, "delay_matrix", 0);
00926                         num_annotations += CountChildren(Cur, "C_constant", 0);
00927                         num_annotations += CountChildren(Cur, "C_matrix", 0);
00928 
00929                         mode->interconnect[i].annotations = my_calloc(num_annotations, sizeof(t_pin_to_pin_annotation));
00930                         mode->interconnect[i].num_annotations = num_annotations;
00931 
00932                         k = 0;
00933                         Cur2 = NULL;
00934                         for(j = 0; j < 4; j++) {
00935                                 if(j == 0) {
00936                                         Cur2 = FindFirstElement(Cur, "delay_constant", FALSE);
00937                                 } else if (j == 1) {
00938                                         Cur2 = FindFirstElement(Cur, "delay_matrix", FALSE);
00939                                 } else if (j == 2) {
00940                                         Cur2 = FindFirstElement(Cur, "C_constant", FALSE);
00941                                 } else if (j == 3) {
00942                                         Cur2 = FindFirstElement(Cur, "C_matrix", FALSE);
00943                                 }
00944                                 while (Cur2 != NULL)
00945                                 {
00946                                         ProcessPinToPinAnnotations(Cur2, &(mode->interconnect[i].annotations[k]));
00947 
00948                                         /* get next iteration */
00949                                         Prev2 = Cur2;
00950                                         Cur2 = Cur2->next;
00951                                         k++;
00952                                         FreeNode(Prev2);
00953                                 }
00954                         }
00955                         assert(k == num_annotations);
00956                                         
00957                         /* get next iteration */
00958                         Prev = Cur;
00959                         Cur = Cur->next;
00960                         FreeNode(Prev);
00961                         i++;
00962                 }
00963         }
00964 
00965         assert(i == num_interconnect);
00966 }
00967 
00968 static void ProcessMode(INOUTP ezxml_t Parent,
00969                                                 t_mode * mode) {
00970         int i;
00971         const char *Prop;
00972         ezxml_t Cur, Prev;
00973 
00974         if(0 == strcmp(Parent->name, "pb_type")) {
00975                 /* implied mode */
00976                 mode->name = my_strdup(mode->parent_pb_type->name);
00977         } else {
00978                 Prop = FindProperty(Parent, "name", TRUE);
00979                 mode->name = my_strdup(Prop);
00980                 ezxml_set_attr(Parent, "name", NULL);
00981         }
00982 
00983         mode->num_pb_type_children = CountChildren(Parent, "pb_type", 1);
00984         mode->pb_type_children = my_calloc(mode->num_pb_type_children, sizeof(t_pb_type));
00985 
00986         i = 0;
00987         Cur = FindFirstElement(Parent, "pb_type", TRUE);
00988         while (Cur != NULL)
00989         {
00990                 if(0 == strcmp(Cur->name, "pb_type")) {
00991                         ProcessPb_Type(Cur, &mode->pb_type_children[i], mode);
00992                                         
00993                         /* get next iteration */
00994                         Prev = Cur;
00995                         Cur = Cur->next;
00996                         i++;
00997                         FreeNode(Prev);
00998                 }
00999         }
01000 
01001         Cur = FindElement(Parent, "interconnect", TRUE);
01002         ProcessInterconnect(Cur, mode);
01003         FreeNode(Cur);
01004 }
01005 
01006 /** Takes in the node ptr for the 'fc_in' and 'fc_out' elements and initializes
01007  * the appropriate fields of type. Unlinks the contents of the nodes. 
01008  */ 
01009 static void
01010 Process_Fc(ezxml_t Fc_in_node, ezxml_t Fc_out_node, t_type_descriptor * Type)
01011 {
01012     enum Fc_type Type_in;
01013     enum Fc_type Type_out;
01014 
01015     ParseFc(Fc_in_node, &Type_in, &Type->Fc_in);
01016     ParseFc(Fc_out_node, &Type_out, &Type->Fc_out);
01017     if(FC_FULL == Type_in)
01018         {
01019                 printf(ERRTAG "[LINE %d] 'full' Fc type isn't allowed for Fc_in.\n", Fc_in_node->line);
01020             exit(1);
01021         }
01022     Type->is_Fc_out_full_flex = FALSE;
01023     Type->is_Fc_frac = FALSE;
01024     if(FC_FULL == Type_out)
01025         {
01026             Type->is_Fc_out_full_flex = TRUE;
01027         }
01028     
01029     else if(Type_in != Type_out)
01030         {
01031             printf(ERRTAG
01032                         "[LINE %d] Fc_in and Fc_out must have same type unless Fc_out has type 'full'.\n", Fc_in_node->line);
01033             exit(1);
01034         }
01035     if(FC_FRAC == Type_in)
01036         {
01037             Type->is_Fc_frac = TRUE;
01038         }
01039 }
01040 
01041 /** This processes attributes of the 'type' tag and then unlinks them */ 
01042 static void
01043 ProcessComplexBlockProps(ezxml_t Node, t_type_descriptor * Type)
01044 {
01045     const char *Prop;
01046     
01047         /* Load type name */ 
01048         Prop = FindProperty(Node, "name", TRUE);
01049     Type->name = my_strdup(Prop);
01050     ezxml_set_attr(Node, "name", NULL);
01051     
01052         /* Load properties */
01053         Type->capacity = GetIntProperty(Node, "capacity", FALSE, 1);   /* TODO: Any block with capacity > 1 that is not I/O has not been tested, must test */
01054         Type->height = GetIntProperty(Node, "height", FALSE, 1);    
01055         Type->area = GetFloatProperty(Node, "area", FALSE, UNDEFINED);
01056         
01057 
01058         if(atof(Prop) < 0) {
01059                 printf("[LINE %d] Area for type %s must be non-negative\n", Node->line, Type->name);
01060                 exit(1);
01061         }
01062 }
01063 
01064 /** Takes in node pointing to <models> and loads all the
01065  * child type objects. Unlinks the entire <models> node
01066  * when complete. 
01067  */ 
01068 static void
01069 ProcessModels(INOUTP ezxml_t Node, OUTP struct s_arch *arch)
01070 {
01071         const char *Prop;
01072         ezxml_t child;
01073         ezxml_t p;
01074         ezxml_t junk;
01075         ezxml_t junkp;
01076         t_model *temp;
01077         t_model_ports *tp;
01078         int index;
01079 
01080         index = NUM_MODELS_IN_LIBRARY;
01081 
01082         arch->models = NULL;
01083         child = ezxml_child(Node, "model");
01084         while (child != NULL)
01085         {
01086                 temp = (t_model*)my_calloc(1, sizeof(t_model));
01087                 temp->used = 0;
01088                 temp->inputs = temp->outputs = temp->instances = NULL;
01089                 Prop = FindProperty(child, "name", TRUE);
01090                 temp->name = my_strdup(Prop);
01091                 ezxml_set_attr(child, "name", NULL);
01092                 temp->pb_types = NULL;
01093                 temp->index = index;
01094                 index++;
01095 
01096                 /* Process the inputs */
01097                 p = ezxml_child(child, "input_ports");
01098                 junkp = p;
01099                 if (p == NULL)
01100                         printf(ERRTAG "Required input ports not found for element '%s'.\n", temp->name);
01101 
01102                 p = ezxml_child(p, "port");
01103                 if (p != NULL)
01104                 {
01105                         while (p != NULL)
01106                         {
01107                                 tp = (t_model_ports*)my_calloc(1, sizeof(t_model_ports));
01108                                 Prop = FindProperty(p, "name", TRUE);
01109                                 tp->name = my_strdup(Prop);
01110                                 ezxml_set_attr(p, "name", NULL);
01111                                 tp->size = -1; /* determined later by pb_types */
01112                                 tp->min_size = -1; /* determined later by pb_types */
01113                                 tp->next = temp->inputs;
01114                                 tp->dir = IN_PORT;
01115                                 tp->is_clock = FALSE;
01116                                 Prop = FindProperty(p, "is_clock", FALSE);
01117                                 if(Prop && my_atoi(Prop) != 0) {
01118                                         tp->is_clock = TRUE;
01119                                 }
01120                                 ezxml_set_attr(p, "is_clock", NULL);
01121                                 temp->inputs = tp;
01122                                 junk = p;
01123                                 p = ezxml_next(p);
01124                                 FreeNode(junk);
01125                         }
01126                 }
01127                 else /* No input ports? */
01128                 {
01129                         printf(ERRTAG "Required input ports not found for element '%s'.\n", temp->name);
01130                 }
01131                 FreeNode(junkp);
01132 
01133                 /* Process the outputs */
01134                 p = ezxml_child(child, "output_ports");
01135                 junkp = p;
01136                 if (p == NULL)
01137                         printf(ERRTAG "Required output ports not found for element '%s'.\n", temp->name);
01138 
01139                 p = ezxml_child(p, "port");
01140                 if (p != NULL)
01141                 {
01142                         while (p != NULL)
01143                         {
01144                                 tp = (t_model_ports*)my_calloc(1, sizeof(t_model_ports));
01145                                 Prop = FindProperty(p, "name", TRUE);
01146                                 tp->name = my_strdup(Prop);
01147                                 ezxml_set_attr(p, "name", NULL);
01148                                 tp->size = -1; /* determined later by pb_types */
01149                                 tp->min_size = -1; /* determined later by pb_types */
01150                                 tp->next = temp->outputs;
01151                                 tp->dir = OUT_PORT;
01152                                 temp->outputs = tp;
01153                                 junk = p;
01154                                 p = ezxml_next(p);
01155                                 FreeNode(junk);
01156                         }
01157                 }
01158                 else /* No output ports? */
01159                 {
01160                         printf(ERRTAG "Required output ports not found for element '%s'.\n", temp->name);
01161                 }
01162                 FreeNode(junkp);
01163 
01164                 /* Find the next model */
01165                 temp->next = arch->models;
01166                 arch->models = temp;
01167                 junk = child;
01168                 child = ezxml_next(child);
01169                 FreeNode(junk);
01170         }
01171 
01172         return;
01173 }
01174 
01175 /** Takes in node pointing to <layout> and loads all the
01176  * child type objects. Unlinks the entire <layout> node
01177  * when complete. 
01178  */ 
01179 static void
01180 ProcessLayout(INOUTP ezxml_t Node, OUTP struct s_arch *arch)
01181 {
01182     const char *Prop;
01183 
01184     arch->clb_grid.IsAuto = TRUE;
01185     
01186         /* Load width and height if applicable */ 
01187         Prop = FindProperty(Node, "width", FALSE);
01188     if(Prop != NULL)
01189         {
01190             arch->clb_grid.IsAuto = FALSE;
01191             arch->clb_grid.W = my_atoi(Prop);
01192             ezxml_set_attr(Node, "width", NULL);
01193 
01194                 arch->clb_grid.H = GetIntProperty(Node, "height", TRUE, UNDEFINED);
01195         }
01196     
01197         /* Load aspect ratio if applicable */ 
01198         Prop = FindProperty(Node, "auto", arch->clb_grid.IsAuto);
01199     if(Prop != NULL)
01200         {
01201             if(arch->clb_grid.IsAuto == FALSE)
01202                 {
01203                     printf(ERRTAG
01204                             "Auto-sizing, width and height cannot be specified\n");
01205                 }
01206             arch->clb_grid.Aspect = atof(Prop);
01207             ezxml_set_attr(Node, "auto", NULL);
01208                 if(arch->clb_grid.Aspect <= 0)
01209                 {
01210                     printf(ERRTAG
01211                             "Grid aspect ratio is less than or equal to zero %g\n", arch->clb_grid.Aspect);
01212                 }
01213         }
01214 }
01215 
01216 /** Takes in node pointing to <device> and loads all the
01217  * child type objects. Unlinks the entire <device> node
01218  * when complete. 
01219  */ 
01220 static void
01221 ProcessDevice(INOUTP ezxml_t Node, OUTP struct s_arch *arch,
01222         INP boolean timing_enabled)
01223 {
01224     const char *Prop;
01225     ezxml_t Cur;
01226 
01227     Cur = FindElement(Node, "sizing", TRUE);
01228     arch->R_minW_nmos = GetFloatProperty(Cur, "R_minW_nmos", timing_enabled, 0);
01229     arch->R_minW_pmos = GetFloatProperty(Cur, "R_minW_pmos", timing_enabled, 0);
01230     arch->ipin_mux_trans_size = GetFloatProperty(Cur, "ipin_mux_trans_size", FALSE, 0);
01231     FreeNode(Cur);
01232 
01233     Cur = FindElement(Node, "timing", timing_enabled);
01234     if(Cur != NULL)
01235         {
01236             arch->C_ipin_cblock = GetFloatProperty(Cur, "C_ipin_cblock", FALSE, 0);
01237             arch->T_ipin_cblock = GetFloatProperty(Cur, "T_ipin_cblock", FALSE, 0);
01238             FreeNode(Cur);
01239         }
01240 
01241     Cur = FindElement(Node, "area", TRUE);
01242     arch->grid_logic_tile_area = GetFloatProperty(Cur, "grid_logic_tile_area", FALSE, 0);
01243     FreeNode(Cur);
01244 
01245     Cur = FindElement(Node, "chan_width_distr", FALSE);
01246     if(Cur != NULL)
01247         {
01248             ProcessChanWidthDistr(Cur, arch);
01249             FreeNode(Cur);
01250         }
01251 
01252     Cur = FindElement(Node, "switch_block", TRUE);
01253     Prop = FindProperty(Cur, "type", TRUE);
01254     if(strcmp(Prop, "wilton") == 0)
01255         {
01256             arch->SBType = WILTON;
01257         }
01258     else if(strcmp(Prop, "universal") == 0)
01259         {
01260             arch->SBType = UNIVERSAL;
01261         }
01262     else if(strcmp(Prop, "subset") == 0)
01263         {
01264             arch->SBType = SUBSET;
01265         }
01266     else
01267         {
01268                 printf(ERRTAG "[LINE %d] Unknown property %s for switch block type x\n", Cur->line,
01269                     Prop);
01270             exit(1);
01271         }
01272     ezxml_set_attr(Cur, "type", NULL);
01273 
01274     arch->Fs = GetIntProperty(Cur, "fs", TRUE, 3);
01275 
01276     FreeNode(Cur);
01277 }
01278 
01279 /** Takes in node pointing to <chan_width_distr> and loads all the
01280  * child type objects. Unlinks the entire <chan_width_distr> node
01281  * when complete. 
01282  */ 
01283 static void
01284 ProcessChanWidthDistr(INOUTP ezxml_t Node, OUTP struct s_arch *arch)
01285 {
01286     ezxml_t Cur;
01287 
01288     Cur = FindElement(Node, "io", TRUE);
01289     arch->Chans.chan_width_io = GetFloatProperty(Cur, "width", TRUE, UNDEFINED);
01290     FreeNode(Cur);
01291     Cur = FindElement(Node, "x", TRUE);
01292     ProcessChanWidthDistrDir(Cur, &arch->Chans.chan_x_dist);
01293     FreeNode(Cur);
01294     Cur = FindElement(Node, "y", TRUE);
01295     ProcessChanWidthDistrDir(Cur, &arch->Chans.chan_y_dist);
01296     FreeNode(Cur);
01297 }
01298 
01299 /** Takes in node within <chan_width_distr> and loads all the
01300  * child type objects. Unlinks the entire node when complete. 
01301  */ 
01302 static void
01303 ProcessChanWidthDistrDir(INOUTP ezxml_t Node, OUTP t_chan * chan)
01304 {
01305     const char *Prop;
01306 
01307     boolean hasXpeak, hasWidth, hasDc;
01308     hasXpeak = hasWidth = hasDc = FALSE;
01309     Prop = FindProperty(Node, "distr", TRUE);
01310     if(strcmp(Prop, "uniform") == 0)
01311         {
01312             chan->type = UNIFORM;
01313         }
01314     else if(strcmp(Prop, "gaussian") == 0)
01315         {
01316             chan->type = GAUSSIAN;
01317             hasXpeak = hasWidth = hasDc = TRUE;
01318         }
01319     else if(strcmp(Prop, "pulse") == 0)
01320         {
01321             chan->type = PULSE;
01322             hasXpeak = hasWidth = hasDc = TRUE;
01323         }
01324     else if(strcmp(Prop, "delta") == 0)
01325         {
01326             hasXpeak = hasDc = TRUE;
01327             chan->type = DELTA;
01328         }
01329     else
01330         {
01331                 printf(ERRTAG "[LINE %d] Unknown property %s for chan_width_distr x\n", Node->line,
01332                     Prop);
01333             exit(1);
01334         }
01335     ezxml_set_attr(Node, "distr", NULL);
01336     chan->peak = GetFloatProperty(Node, "peak", TRUE, UNDEFINED);
01337         chan->width = GetFloatProperty(Node, "width", hasWidth, 0);
01338     chan->xpeak = GetFloatProperty(Node, "xpeak", hasXpeak, 0);
01339         chan->dc = GetFloatProperty(Node, "dc", hasDc, 0);
01340 }
01341 
01342 static void
01343 SetupEmptyType()
01344 {
01345     t_type_descriptor * type;
01346     type = &type_descriptors[EMPTY_TYPE->index];
01347     type->name = "<EMPTY>";
01348     type->num_pins = 0;
01349     type->height = 1;
01350     type->capacity = 0;
01351     type->num_drivers = 0;
01352     type->num_receivers = 0;
01353     type->pinloc = NULL;
01354     type->num_class = 0;
01355     type->class_inf = NULL;
01356     type->pin_class = NULL;
01357     type->is_global_pin = NULL;
01358     type->is_Fc_frac = TRUE;
01359     type->is_Fc_out_full_flex = FALSE;
01360     type->Fc_in = 0;
01361     type->Fc_out = 0;
01362         type->pb_type = NULL;
01363         type->area = UNDEFINED;
01364         
01365         /* Used as lost area filler, no definition */ 
01366         type->grid_loc_def = NULL;
01367     type->num_grid_loc_def = 0;
01368 }
01369 
01370 
01371 static void alloc_and_load_default_child_for_pb_type(INOUTP t_pb_type *pb_type, char *new_name, t_pb_type *copy) {
01372         int i, j;
01373         char *dot;
01374         
01375         assert(pb_type->blif_model != NULL);
01376 
01377         copy->name = my_strdup(new_name);
01378         copy->blif_model = my_strdup(pb_type->blif_model);
01379         copy->class_type = pb_type->class_type;
01380         copy->depth = pb_type->depth;
01381         copy->model = pb_type->model;
01382         copy->models_contained = NULL;
01383         copy->modes = NULL;
01384         copy->num_modes = 0;
01385         copy->num_clock_pins = pb_type->num_clock_pins;
01386         copy->num_input_pins = pb_type->num_input_pins;
01387         copy->num_output_pins = pb_type->num_output_pins;
01388         copy->num_pb = 1;
01389         copy->num_ports = pb_type->num_ports;
01390         copy->ports = my_calloc(pb_type->num_ports, sizeof(t_port));
01391         for(i = 0; i < pb_type->num_ports; i++) {
01392                 copy->ports[i].is_clock = pb_type->ports[i].is_clock;
01393                 copy->ports[i].model_port = pb_type->ports[i].model_port;
01394                 copy->ports[i].type = pb_type->ports[i].type;
01395                 copy->ports[i].num_pins = pb_type->ports[i].num_pins;
01396                 copy->ports[i].parent_pb_type = copy;
01397                 copy->ports[i].name = my_strdup(pb_type->ports[i].name);
01398                 copy->ports[i].port_class = my_strdup(pb_type->ports[i].port_class);
01399         }
01400 
01401         copy->max_internal_delay = pb_type->max_internal_delay;
01402         copy->annotations = my_calloc(pb_type->num_annotations, sizeof(t_pin_to_pin_annotation));
01403         copy->num_annotations = pb_type->num_annotations;
01404         for(i = 0; i < copy->num_annotations; i++) {
01405                 copy->annotations[i].clock = my_strdup(pb_type->annotations[i].clock);
01406                 dot = strstr(pb_type->annotations[i].input_pins, ".");
01407                 copy->annotations[i].input_pins = my_malloc(sizeof(char) * (strlen(new_name) + strlen(dot) + 1));
01408                 copy->annotations[i].input_pins[0] = '\0';
01409                 strcat(copy->annotations[i].input_pins, new_name);
01410                 strcat(copy->annotations[i].input_pins, dot);
01411                 if(pb_type->annotations[i].output_pins != NULL) {
01412                 dot = strstr(pb_type->annotations[i].output_pins, ".");
01413                         copy->annotations[i].output_pins = my_malloc(sizeof(char) * (strlen(new_name) + strlen(dot) + 1));
01414                         copy->annotations[i].output_pins[0] = '\0';
01415                         strcat(copy->annotations[i].output_pins, new_name);
01416                         strcat(copy->annotations[i].output_pins, dot);
01417                 } else {
01418                         copy->annotations[i].output_pins = NULL;
01419                 }
01420                 copy->annotations[i].format = pb_type->annotations[i].format;
01421                 copy->annotations[i].type = pb_type->annotations[i].type;
01422                 copy->annotations[i].num_value_prop_pairs = pb_type->annotations[i].num_value_prop_pairs;
01423                 copy->annotations[i].prop = my_malloc(sizeof(int) * pb_type->annotations[i].num_value_prop_pairs);
01424                 copy->annotations[i].value = my_malloc(sizeof(char *) * pb_type->annotations[i].num_value_prop_pairs);
01425                 for(j = 0; j < pb_type->annotations[i].num_value_prop_pairs; j++) {
01426                         copy->annotations[i].prop[j] = pb_type->annotations[i].prop[j];
01427                         copy->annotations[i].value[j] = my_strdup(pb_type->annotations[i].value[j]);
01428                 }
01429         }
01430 }
01431 
01432 /** populate special lut class */
01433 void ProcessLutClass(INOUTP t_pb_type *lut_pb_type) {
01434         char *default_name;
01435         t_port *in_port;
01436         t_port *out_port;
01437         int i, j;
01438         
01439         if(strcmp(lut_pb_type->name, "lut") != 0) {
01440                 default_name = my_strdup("lut");
01441         } else {
01442                 default_name = my_strdup("lut_child");
01443         }
01444         
01445         lut_pb_type->num_modes = 2;
01446         lut_pb_type->modes = my_calloc(lut_pb_type->num_modes, sizeof(t_mode));
01447         
01448         /* First mode, route_through */
01449         lut_pb_type->modes[0].name = my_strdup(lut_pb_type->name);
01450         lut_pb_type->modes[0].parent_pb_type = lut_pb_type;
01451         lut_pb_type->modes[0].num_pb_type_children = 0;
01452         
01453         /* Process interconnect */
01454         /* TODO: add timing annotations to route-through */
01455         assert(lut_pb_type->num_ports == 2);
01456         if(strcmp(lut_pb_type->ports[0].port_class, "lut_in") == 0) {
01457                 assert(strcmp(lut_pb_type->ports[1].port_class, "lut_out") == 0);
01458                 in_port = &lut_pb_type->ports[0];
01459                 out_port = &lut_pb_type->ports[1];
01460         } else {
01461                 assert(strcmp(lut_pb_type->ports[0].port_class, "lut_out") == 0);
01462                 assert(strcmp(lut_pb_type->ports[1].port_class, "lut_in") == 0);
01463                 out_port = &lut_pb_type->ports[0];
01464                 in_port = &lut_pb_type->ports[1];
01465         }
01466         lut_pb_type->modes[0].num_interconnect = 1;
01467         lut_pb_type->modes[0].interconnect = my_calloc(1, sizeof(t_interconnect));
01468         lut_pb_type->modes[0].interconnect[0].name = my_calloc(
01469                                                                                                                 strlen(lut_pb_type->name) + 10,
01470                                                                                                                 sizeof(char));
01471         sprintf(lut_pb_type->modes[0].interconnect[0].name, "complete:%s", lut_pb_type->name);
01472         lut_pb_type->modes[0].interconnect[0].type = COMPLETE_INTERC;
01473         lut_pb_type->modes[0].interconnect[0].input_string = my_calloc(
01474                                                                                                                 strlen(lut_pb_type->name) + 
01475                                                                                                                 strlen(in_port->name) + 2,
01476                                                                                                                 sizeof(char));
01477         sprintf(lut_pb_type->modes[0].interconnect[0].input_string, "%s.%s", 
01478                         lut_pb_type->name, in_port->name);
01479         lut_pb_type->modes[0].interconnect[0].output_string = my_calloc(
01480                                                                                                                 strlen(lut_pb_type->name) + 
01481                                                                                                                 strlen(out_port->name) + 2,
01482                                                                                                                 sizeof(char));
01483         sprintf(lut_pb_type->modes[0].interconnect[0].output_string, "%s.%s", 
01484                         lut_pb_type->name, out_port->name);
01485 
01486         /* Second mode, LUT */
01487         
01488         lut_pb_type->modes[1].name = my_strdup(lut_pb_type->name);
01489         lut_pb_type->modes[1].parent_pb_type = lut_pb_type;
01490         lut_pb_type->modes[1].num_pb_type_children = 1;
01491         lut_pb_type->modes[1].pb_type_children = my_calloc(1, sizeof(t_pb_type));
01492         alloc_and_load_default_child_for_pb_type(lut_pb_type, default_name, lut_pb_type->modes[1].pb_type_children);
01493         /* moved annotations to child so delete old annotations */
01494         for(i = 0; i < lut_pb_type->num_annotations; i++) {
01495                 for(j = 0; j < lut_pb_type->annotations[i].num_value_prop_pairs; j++) {
01496                         free(lut_pb_type->annotations[i].value[j]);
01497                 }
01498                 free(lut_pb_type->annotations[i].value);
01499                 free(lut_pb_type->annotations[i].prop);
01500                 if(lut_pb_type->annotations[i].input_pins) {
01501                         free(lut_pb_type->annotations[i].input_pins);
01502                 }
01503                 if(lut_pb_type->annotations[i].output_pins) {
01504                         free(lut_pb_type->annotations[i].output_pins);
01505                 }
01506                 if(lut_pb_type->annotations[i].clock) {
01507                         free(lut_pb_type->annotations[i].clock);
01508                 }
01509         }
01510         lut_pb_type->num_annotations = 0;
01511         free(lut_pb_type->annotations);
01512         lut_pb_type->annotations = NULL;
01513         lut_pb_type->modes[1].pb_type_children[0].depth = lut_pb_type->depth + 1;
01514         lut_pb_type->modes[1].pb_type_children[0].parent_mode = &lut_pb_type->modes[1];
01515 
01516         /* Process interconnect */
01517         lut_pb_type->modes[1].num_interconnect = 2;
01518         lut_pb_type->modes[1].interconnect = my_calloc(2, sizeof(t_interconnect));
01519         lut_pb_type->modes[1].interconnect[0].name = my_calloc(
01520                                                                                                                 strlen(lut_pb_type->name) + 10,
01521                                                                                                                 sizeof(char));
01522         sprintf(lut_pb_type->modes[1].interconnect[0].name, "complete:%s", lut_pb_type->name);
01523         lut_pb_type->modes[1].interconnect[0].type = COMPLETE_INTERC;
01524         lut_pb_type->modes[1].interconnect[0].input_string = my_calloc(
01525                                                                                                                 strlen(lut_pb_type->name) + 
01526                                                                                                                 strlen(in_port->name) + 2,
01527                                                                                                                 sizeof(char));
01528         sprintf(lut_pb_type->modes[1].interconnect[0].input_string, "%s.%s", 
01529                         lut_pb_type->name, in_port->name);
01530         lut_pb_type->modes[1].interconnect[0].output_string = my_calloc(
01531                                                                                                                 strlen(default_name) + 
01532                                                                                                                 strlen(in_port->name) + 2,
01533                                                                                                                 sizeof(char));
01534         sprintf(lut_pb_type->modes[1].interconnect[0].output_string, "%s.%s", 
01535                         default_name, in_port->name);
01536 
01537         lut_pb_type->modes[1].interconnect[1].name = my_calloc(
01538                                                                                                                 strlen(lut_pb_type->name) + 11,
01539                                                                                                                 sizeof(char));
01540         sprintf(lut_pb_type->modes[1].interconnect[1].name, "complete2:%s", lut_pb_type->name);
01541         
01542         lut_pb_type->modes[1].interconnect[1].type = COMPLETE_INTERC;
01543         lut_pb_type->modes[1].interconnect[1].input_string = my_calloc(
01544                                                                                                                 strlen(default_name) + 
01545                                                                                                                 strlen(lut_pb_type->name) +
01546                                                                                                                 strlen(in_port->name) +
01547                                                                                                                 strlen(out_port->name) + 4,
01548                                                                                                                 sizeof(char));
01549         sprintf(lut_pb_type->modes[1].interconnect[1].input_string, "%s.%s %s.%s", default_name, out_port->name,
01550                 lut_pb_type->name, in_port->name);
01551         lut_pb_type->modes[1].interconnect[1].output_string = my_calloc(
01552                                                                                                                 strlen(lut_pb_type->name) + 
01553                                                                                                                 strlen(out_port->name) + 
01554                                                                                                                 strlen(in_port->name) + 2,
01555                                                                                                                 sizeof(char));
01556         sprintf(lut_pb_type->modes[1].interconnect[1].output_string, "%s.%s", 
01557                         lut_pb_type->name, out_port->name);
01558 
01559         free(default_name);
01560 
01561         free(lut_pb_type->blif_model);
01562         lut_pb_type->blif_model = NULL;
01563         lut_pb_type->model = NULL;
01564 }
01565 
01566 /** populate special memory class */ 
01567 static void ProcessMemoryClass(INOUTP t_pb_type *mem_pb_type) {
01568         char *default_name;
01569         char *input_name, *input_port_name, *output_name, *output_port_name;
01570         int i, j, i_inter, num_pb;
01571 
01572         
01573         if(strcmp(mem_pb_type->name, "memory_slice") != 0) {
01574                 default_name = my_strdup("memory_slice");
01575         } else {
01576                 default_name = my_strdup("memory_slice_1bit");
01577         }
01578         
01579         mem_pb_type->modes = my_calloc(1, sizeof(t_mode));
01580         mem_pb_type->modes[0].name = my_strdup(default_name);
01581         mem_pb_type->modes[0].parent_pb_type = mem_pb_type;
01582 
01583         num_pb = OPEN;
01584         for(i = 0; i < mem_pb_type->num_ports; i++) {
01585                 if(mem_pb_type->ports[i].port_class != NULL && 
01586                    strstr(mem_pb_type->ports[i].port_class, "data") == mem_pb_type->ports[i].port_class) {
01587                         if(num_pb == OPEN) {
01588                                 num_pb = mem_pb_type->ports[i].num_pins;
01589                         } else if (num_pb != mem_pb_type->ports[i].num_pins) {
01590                                 printf(ERRTAG "memory %s has inconsistent number of data bits %d and %d\n", mem_pb_type->name,
01591                                         num_pb, mem_pb_type->ports[i].num_pins);
01592                                 exit(1);
01593                         }
01594                 }
01595         }
01596 
01597         mem_pb_type->modes[0].num_pb_type_children = 1;
01598         mem_pb_type->modes[0].pb_type_children = my_calloc(1, sizeof(t_pb_type));
01599         alloc_and_load_default_child_for_pb_type(mem_pb_type, default_name, &mem_pb_type->modes[0].pb_type_children[0]);
01600         mem_pb_type->modes[0].pb_type_children[0].depth = mem_pb_type->depth + 1;
01601         mem_pb_type->modes[0].pb_type_children[0].parent_mode = &mem_pb_type->modes[0];
01602         mem_pb_type->modes[0].pb_type_children[0].num_pb = num_pb;
01603         
01604         mem_pb_type->num_modes = 1;
01605                 
01606         free(mem_pb_type->blif_model);
01607         mem_pb_type->blif_model = NULL;
01608         mem_pb_type->model = NULL;
01609 
01610         mem_pb_type->modes[0].num_interconnect = mem_pb_type->num_ports * num_pb;
01611         mem_pb_type->modes[0].interconnect = my_calloc(mem_pb_type->modes[0].num_interconnect, sizeof(t_interconnect));
01612 
01613         /* Process interconnect */
01614         i_inter = 0;
01615         for(i = 0; i < mem_pb_type->num_ports; i++) {
01616                 mem_pb_type->modes[0].interconnect[i_inter].type = DIRECT_INTERC;
01617                 input_port_name = mem_pb_type->ports[i].name;
01618                 output_port_name = mem_pb_type->ports[i].name;
01619         
01620                 if(mem_pb_type->ports[i].type == IN_PORT) {
01621                         input_name = mem_pb_type->name;
01622                         output_name = default_name;
01623                 } else {
01624                         input_name = default_name;
01625                         output_name = mem_pb_type->name;
01626                 }
01627 
01628                 if(mem_pb_type->ports[i].port_class != NULL && 
01629                    strstr(mem_pb_type->ports[i].port_class, "data") == mem_pb_type->ports[i].port_class) {
01630 
01631                         mem_pb_type->modes[0].interconnect[i_inter].name = my_calloc(i_inter/10 + 8, sizeof(char));
01632                         sprintf(mem_pb_type->modes[0].interconnect[i_inter].name, "direct%d", i_inter);
01633 
01634            
01635                    if(mem_pb_type->ports[i].type == IN_PORT) {
01636                                 /* force data pins to be one bit wide and update stats */
01637                                 mem_pb_type->modes[0].pb_type_children[0].ports[i].num_pins = 1; 
01638                                 mem_pb_type->modes[0].pb_type_children[0].num_input_pins -= (mem_pb_type->ports[i].num_pins - 1);
01639 
01640 
01641                                 mem_pb_type->modes[0].interconnect[i_inter].input_string = my_calloc(
01642                                                                                                                                         strlen(input_name) + 
01643                                                                                                                                         strlen(input_port_name) + 2,
01644                                                                                                                                         sizeof(char));
01645                                 sprintf(mem_pb_type->modes[0].interconnect[i_inter].input_string, "%s.%s", 
01646                                                 input_name, input_port_name);
01647                                 mem_pb_type->modes[0].interconnect[i_inter].output_string = my_calloc(
01648                                                                                                                                         strlen(output_name) + 
01649                                                                                                                                         strlen(output_port_name) + 2*(6 + num_pb/10),
01650                                                                                                                                         sizeof(char));
01651                                 sprintf(mem_pb_type->modes[0].interconnect[i_inter].output_string, "%s[%d:0].%s", 
01652                                                 output_name, num_pb - 1, output_port_name);
01653                    } else {
01654                             /* force data pins to be one bit wide and update stats */
01655                                 mem_pb_type->modes[0].pb_type_children[0].ports[i].num_pins = 1; 
01656                                 mem_pb_type->modes[0].pb_type_children[0].num_output_pins -= (mem_pb_type->ports[i].num_pins - 1);
01657 
01658                                 mem_pb_type->modes[0].interconnect[i_inter].input_string = my_calloc(
01659                                                                                                                                         strlen(input_name) + 
01660                                                                                                                                         strlen(input_port_name) + 2*(6 + num_pb/10),
01661                                                                                                                                         sizeof(char));
01662                                 sprintf(mem_pb_type->modes[0].interconnect[i_inter].input_string, "%s[%d:0].%s", 
01663                                                 input_name, num_pb - 1, input_port_name);
01664                                 mem_pb_type->modes[0].interconnect[i_inter].output_string = my_calloc(
01665                                                                                                                                         strlen(output_name) + 
01666                                                                                                                                         strlen(output_port_name) + 2,
01667                                                                                                                                         sizeof(char));
01668                                 sprintf(mem_pb_type->modes[0].interconnect[i_inter].output_string, "%s.%s", 
01669                                                 output_name, output_port_name);
01670                    }
01671 
01672                    i_inter++;
01673                 } else {
01674                         for(j = 0; j < num_pb; j++) {                   
01675                                 /* Anything that is not data must be an input */
01676                                 mem_pb_type->modes[0].interconnect[i_inter].name = my_calloc(i_inter/10 + j/10 + 10, sizeof(char));
01677                                 sprintf(mem_pb_type->modes[0].interconnect[i_inter].name, "direct%d_%d", i_inter, j);
01678 
01679                                 if(mem_pb_type->ports[i].type == IN_PORT) {
01680                                         mem_pb_type->modes[0].interconnect[i_inter].type = DIRECT_INTERC;
01681                                         mem_pb_type->modes[0].interconnect[i_inter].input_string = my_calloc(
01682                                                                                                                                                 strlen(input_name) + 
01683                                                                                                                                                 strlen(input_port_name) + 2,
01684                                                                                                                                                 sizeof(char));
01685                                         sprintf(mem_pb_type->modes[0].interconnect[i_inter].input_string, "%s.%s", 
01686                                                         input_name, input_port_name);
01687                                         mem_pb_type->modes[0].interconnect[i_inter].output_string = my_calloc(
01688                                                                                                                                                 strlen(output_name) + 
01689                                                                                                                                                 strlen(output_port_name) + 2*(6 + num_pb/10),
01690                                                                                                                                                 sizeof(char));
01691                                         sprintf(mem_pb_type->modes[0].interconnect[i_inter].output_string, "%s[%d:%d].%s", 
01692                                                         output_name, j, j, output_port_name);
01693                                 } else {
01694                                         mem_pb_type->modes[0].interconnect[i_inter].type = DIRECT_INTERC;
01695                                         mem_pb_type->modes[0].interconnect[i_inter].input_string = my_calloc(
01696                                                                                                                                                 strlen(input_name) + 
01697                                                                                                                                                 strlen(input_port_name) + 2*(6 + num_pb/10),
01698                                                                                                                                                 sizeof(char));
01699                                         sprintf(mem_pb_type->modes[0].interconnect[i_inter].input_string, "%s[%d:%d].%s", 
01700                                                         input_name, j, j, input_port_name);
01701                                         mem_pb_type->modes[0].interconnect[i_inter].output_string = my_calloc(
01702                                                                                                                                                 strlen(output_name) + 
01703                                                                                                                                                 strlen(output_port_name) + 2,
01704                                                                                                                                                 sizeof(char));
01705                                         sprintf(mem_pb_type->modes[0].interconnect[i_inter].output_string, "%s.%s", 
01706                                                         output_name, output_port_name);                                 
01707 
01708                                 }
01709                                 i_inter++;
01710                         }
01711                 }
01712         }
01713         mem_pb_type->modes[0].num_interconnect = i_inter;
01714 
01715         free(default_name);
01716 }
01717 
01718 /** Takes in node pointing to <typelist> and loads all the
01719  * child type objects. Unlinks the entire <typelist> node
01720  * when complete. 
01721  */ 
01722 static void
01723 ProcessComplexBlocks(INOUTP ezxml_t Node, OUTP t_type_descriptor ** Types,
01724         OUTP int *NumTypes, boolean timing_enabled)
01725 {
01726     ezxml_t CurType, Prev;
01727     ezxml_t Cur, Cur2;
01728     t_type_descriptor * Type;
01729         int i;
01730 
01731     
01732         /* Alloc the type list. Need one additional t_type_desctiptors:
01733          * 1: empty psuedo-type 
01734          */ 
01735         *NumTypes = CountChildren(Node, "pb_type", 1) + 1;
01736     *Types = (t_type_descriptor *) 
01737         my_malloc(sizeof(t_type_descriptor) * (*NumTypes));
01738 
01739         type_descriptors = *Types;
01740 
01741     EMPTY_TYPE = &type_descriptors[EMPTY_TYPE_INDEX];
01742     IO_TYPE = &type_descriptors[IO_TYPE_INDEX];
01743     type_descriptors[EMPTY_TYPE_INDEX].index = EMPTY_TYPE_INDEX;
01744     type_descriptors[IO_TYPE_INDEX].index = IO_TYPE_INDEX;
01745     SetupEmptyType();
01746     
01747         /* Process the types */ 
01748         /* 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*/
01749         assert(EMPTY_TYPE_INDEX == 0);
01750         assert(IO_TYPE_INDEX == 1);
01751         i = 1;                  /* Skip over 'empty' type */
01752     CurType = Node->child;
01753     while(CurType)
01754         {
01755             CheckElement(CurType, "pb_type");
01756             
01757                 /* Alias to current type */ 
01758                 Type = &(*Types)[i];
01759             
01760                 /* Parses the properties fields of the type */ 
01761                 ProcessComplexBlockProps(CurType, Type);
01762                 
01763                 /* Load pb_type info */
01764                 Type->pb_type = my_malloc(sizeof(t_pb_type));
01765             Type->pb_type->name = my_strdup(Type->name);
01766                 if(i == IO_TYPE_INDEX) {
01767                         if(strcmp(Type->name, "io") != 0) {
01768                                 printf("First complex block must be named \"io\" and define the inputs and outputs for the FPGA");
01769                                 exit(1);
01770                         }
01771                 }
01772                 ProcessPb_Type(CurType, Type->pb_type, NULL);
01773                 Type->num_pins = Type->capacity * (Type->pb_type->num_input_pins + Type->pb_type->num_output_pins + Type->pb_type->num_clock_pins);
01774                 Type->num_receivers = Type->capacity * Type->pb_type->num_input_pins;
01775                 Type->num_drivers = Type->capacity * Type->pb_type->num_output_pins;
01776                 
01777                 /* Load Fc */ 
01778                 Cur = FindElement(CurType, "fc_in", TRUE);
01779             Cur2 = FindElement(CurType, "fc_out", TRUE);
01780             Process_Fc(Cur, Cur2, Type);
01781             FreeNode(Cur);
01782             FreeNode(Cur2);
01783             
01784                 /* Load pin names and classes and locations */ 
01785             Cur = FindElement(CurType, "pinlocations", TRUE);
01786             SetupPinLocationsAndPinClasses(Cur, Type);
01787             FreeNode(Cur);
01788             Cur = FindElement(CurType, "gridlocations", TRUE);
01789             SetupGridLocations(Cur, Type);
01790             FreeNode(Cur);
01791 #if 0
01792             Cur = FindElement(CurType, "timing", timing_enabled);
01793             if(Cur)
01794                 {
01795                     SetupTypeTiming(Cur, Type);
01796                     FreeNode(Cur);
01797                 }
01798 #endif   
01799             Type->index = i;
01800 
01801                 /* Type fully read */ 
01802                 ++i;
01803             
01804                 /* Free this node and get its next sibling node */ 
01805                 Prev = CurType;
01806             CurType = CurType->next;
01807             FreeNode(Prev);
01808 
01809         }
01810     if(FILL_TYPE == NULL)
01811         {
01812             printf(ERRTAG "grid location type 'fill' must be specified.\n");
01813             exit(1);
01814         }
01815 }
01816 
01817 /** Loads the given architecture file. Currently only 
01818  * handles type information 
01819  */ 
01820 void
01821 XmlReadArch(INP const char *ArchFile, INP boolean timing_enabled,
01822         OUTP struct s_arch *arch, OUTP t_type_descriptor ** Types,
01823         OUTP int *NumTypes)
01824 {
01825     ezxml_t Cur, Next;
01826         const char *Prop;
01827     
01828         /* Parse the file */ 
01829         Cur = ezxml_parse_file(ArchFile);
01830     if(NULL == Cur)
01831         {
01832             printf(ERRTAG "Unable to load architecture file '%s'.\n",
01833                     ArchFile);
01834                 exit(1);
01835         }
01836     
01837         /* Root node should be architecture */ 
01838         CheckElement(Cur, "architecture");
01839         /* TODO: do version processing properly with string delimiting on the . */
01840         Prop = FindProperty(Cur, "version", FALSE);
01841     if(Prop != NULL)
01842         {
01843                 if (atof(Prop) > atof(VPR_VERSION)) {
01844                         printf(WARNTAG "This architecture version is for VPR %f while your current VPR version is " VPR_VERSION ", compatability issues may arise\n",
01845                                 atof(Prop));
01846                 }
01847             ezxml_set_attr(Cur, "version", NULL);
01848         }
01849     
01850         /* Process models */ 
01851         Next = FindElement(Cur, "models", TRUE);
01852         ProcessModels(Next, arch);
01853         FreeNode(Next);
01854         CreateModelLibrary(arch);
01855     
01856         /* Process layout */ 
01857         Next = FindElement(Cur, "layout", TRUE);
01858     ProcessLayout(Next, arch);
01859     FreeNode(Next);
01860     
01861         /* Process device */ 
01862         Next = FindElement(Cur, "device", TRUE);
01863     ProcessDevice(Next, arch, timing_enabled);
01864     FreeNode(Next);
01865     
01866         /* Process types */ 
01867         Next = FindElement(Cur, "complexblocklist", TRUE);
01868     ProcessComplexBlocks(Next, Types, NumTypes, timing_enabled);
01869     FreeNode(Next);
01870     
01871         /* Process switches */ 
01872         Next = FindElement(Cur, "switchlist", TRUE);
01873     ProcessSwitches(Next, &(arch->Switches), &(arch->num_switches),
01874                      timing_enabled);
01875     FreeNode(Next);
01876     
01877         /* Process segments. This depends on switches */ 
01878         Next = FindElement(Cur, "segmentlist", TRUE);
01879     ProcessSegments(Next, &(arch->Segments), &(arch->num_segments),
01880                      arch->Switches, arch->num_switches, timing_enabled);
01881     FreeNode(Next);
01882 
01883         SyncModelsPbTypes(arch, *Types, *NumTypes);
01884         UpdateAndCheckModels(arch);
01885     
01886         /* Release the full XML tree */ 
01887         FreeNode(Cur);
01888 }
01889 
01890 static void
01891 ProcessSegments(INOUTP ezxml_t Parent, OUTP struct s_segment_inf **Segs,
01892         OUTP int *NumSegs, INP struct s_switch_inf *Switches,
01893         INP int NumSwitches, INP boolean timing_enabled)
01894 {
01895     int i, j, length;
01896     const char *tmp;
01897 
01898     ezxml_t SubElem;
01899     ezxml_t Node;
01900     
01901         /* Count the number of segs and check they are in fact
01902          * of segment elements. */ 
01903         *NumSegs = CountChildren(Parent, "segment", 1);
01904     
01905         /* Alloc segment list */ 
01906         *Segs = NULL;
01907     if(*NumSegs > 0)
01908         {
01909             *Segs =
01910                 (struct s_segment_inf *)my_malloc(*NumSegs *
01911                                                    sizeof(struct
01912                                                           s_segment_inf));
01913             memset(*Segs, 0, (*NumSegs * sizeof(struct s_segment_inf)));
01914         }
01915     
01916         /* Load the segments. */ 
01917         for(i = 0; i < *NumSegs; ++i)
01918         {
01919             Node = ezxml_child(Parent, "segment");
01920             
01921                 /* Get segment length */ 
01922                 length = 1;     /* DEFAULT */
01923             tmp = FindProperty(Node, "length", FALSE);
01924             if(tmp)
01925                 {
01926                     if(strcmp(tmp, "longline") == 0)
01927                         {
01928                             (*Segs)[i].longline = TRUE;
01929                         }
01930                     else
01931                         {
01932                             length = my_atoi(tmp);
01933                         }
01934                 }
01935             (*Segs)[i].length = length;
01936             ezxml_set_attr(Node, "length", NULL);
01937             
01938                 /* Get the frequency */ 
01939                 (*Segs)[i].frequency = 1;       /* DEFAULT */
01940             tmp = FindProperty(Node, "freq", FALSE);
01941             if(tmp)
01942                 {
01943                     (*Segs)[i].frequency = (int) (atof(tmp) * MAX_CHANNEL_WIDTH);
01944                 }
01945             ezxml_set_attr(Node, "freq", NULL);
01946             
01947                 /* Get timing info */ 
01948                 (*Segs)[i].Rmetal = GetFloatProperty(Node, "Rmetal", timing_enabled, 0);
01949             (*Segs)[i].Cmetal = GetFloatProperty(Node, "Cmetal", timing_enabled, 0);
01950             
01951                 /* Get the type */ 
01952                 tmp = FindProperty(Node, "type", TRUE);
01953             if(0 == strcmp(tmp, "bidir"))
01954                 {
01955                     (*Segs)[i].directionality = BI_DIRECTIONAL;
01956                 }
01957             
01958             else if(0 == strcmp(tmp, "unidir"))
01959                 {
01960                     (*Segs)[i].directionality = UNI_DIRECTIONAL;
01961                 }
01962             
01963             else
01964                 {
01965                         printf(ERRTAG "[LINE %d] Invalid switch type '%s'.\n", Node->line, tmp);
01966                     exit(1);
01967                 }
01968             ezxml_set_attr(Node, "type", NULL);
01969             
01970                 /* Get the wire and opin switches, or mux switch if unidir */ 
01971                 if(UNI_DIRECTIONAL == (*Segs)[i].directionality)
01972                 {
01973                     SubElem = FindElement(Node, "mux", TRUE);
01974                     tmp = FindProperty(SubElem, "name", TRUE);
01975                     
01976                         /* Match names */ 
01977                         for(j = 0; j < NumSwitches; ++j)
01978                         {
01979                             if(0 == strcmp(tmp, Switches[j].name))
01980                                 {
01981                                     break;      /* End loop so j is where we want it */
01982                                 }
01983                         }
01984                     if(j >= NumSwitches)
01985                         {
01986                                 printf(ERRTAG "[LINE %d] '%s' is not a valid mux name.\n", SubElem->line,
01987                                     tmp);
01988                             exit(1);
01989                         }
01990                     ezxml_set_attr(SubElem, "name", NULL);
01991                     FreeNode(SubElem);
01992                     
01993                         /* Unidir muxes must have the same switch
01994                          * for wire and opin fanin since there is 
01995                          * really only the mux in unidir. */ 
01996                         (*Segs)[i].wire_switch = j;
01997                     (*Segs)[i].opin_switch = j;
01998                 }
01999             
02000             else
02001                 {
02002                     assert(BI_DIRECTIONAL == (*Segs)[i].directionality);
02003                     SubElem = FindElement(Node, "wire_switch", TRUE);
02004                     tmp = FindProperty(SubElem, "name", TRUE);
02005                     
02006                         /* Match names */ 
02007                         for(j = 0; j < NumSwitches; ++j)
02008                         {
02009                             if(0 == strcmp(tmp, Switches[j].name))
02010                                 {
02011                                     break;      /* End loop so j is where we want it */
02012                                 }
02013                         }
02014                     if(j >= NumSwitches)
02015                         {
02016                             printf(ERRTAG
02017                                         "[LINE %d] '%s' is not a valid wire_switch name.\n", SubElem->line,
02018                                     tmp);
02019                             exit(1);
02020                         }
02021                     (*Segs)[i].wire_switch = j;
02022                     ezxml_set_attr(SubElem, "name", NULL);
02023                     FreeNode(SubElem);
02024                     SubElem = FindElement(Node, "opin_switch", TRUE);
02025                     tmp = FindProperty(SubElem, "name", TRUE);
02026                     
02027                         /* Match names */ 
02028                         for(j = 0; j < NumSwitches; ++j)
02029                         {
02030                             if(0 == strcmp(tmp, Switches[j].name))
02031                                 {
02032                                     break;      /* End loop so j is where we want it */
02033                                 }
02034                         }
02035                     if(j >= NumSwitches)
02036                         {
02037                             printf(ERRTAG
02038                                         "[LINE %d] '%s' is not a valid opin_switch name.\n", SubElem->line, 
02039                                     tmp);
02040                             exit(1);
02041                         }
02042                     (*Segs)[i].opin_switch = j;
02043                     ezxml_set_attr(SubElem, "name", NULL);
02044                     FreeNode(SubElem);
02045                 }
02046             
02047                 /* Setup the CB list if they give one, otherwise use full */ 
02048                 (*Segs)[i].cb_len = length;
02049             (*Segs)[i].cb = (boolean *) my_malloc(length * sizeof(boolean));
02050             for(j = 0; j < length; ++j)
02051                 {
02052                     (*Segs)[i].cb[j] = TRUE;
02053                 }
02054             SubElem = FindElement(Node, "cb", FALSE);
02055             if(SubElem)
02056                 {
02057                     ProcessCB_SB(SubElem, (*Segs)[i].cb, length);
02058                     FreeNode(SubElem);
02059                 }
02060             
02061                 /* Setup the SB list if they give one, otherwise use full */ 
02062                 (*Segs)[i].sb_len = (length + 1);
02063             (*Segs)[i].sb =
02064                 (boolean *) my_malloc((length + 1) * sizeof(boolean));
02065             for(j = 0; j < (length + 1); ++j)
02066                 {
02067                     (*Segs)[i].sb[j] = TRUE;
02068                 }
02069             SubElem = FindElement(Node, "sb", FALSE);
02070             if(SubElem)
02071                 {
02072                     ProcessCB_SB(SubElem, (*Segs)[i].sb, (length + 1));
02073                     FreeNode(SubElem);
02074                 }
02075             FreeNode(Node);
02076         }
02077 }
02078 
02079 static void
02080 ProcessCB_SB(INOUTP ezxml_t Node, INOUTP boolean * list, INP int len)
02081 {
02082     const char *tmp = NULL;
02083     int i;
02084     
02085         /* Check the type. We only support 'pattern' for now. 
02086          * Should add frac back eventually. */ 
02087         tmp = FindProperty(Node, "type", TRUE);
02088     if(0 == strcmp(tmp, "pattern"))
02089         {
02090             i = 0;
02091             
02092                 /* Get the content string */ 
02093                 tmp = Node->txt;
02094             while(*tmp)
02095                 {
02096                     switch (*tmp)
02097                         {
02098                         case ' ':
02099                             break;
02100                         case 'T':
02101                         case '1':
02102                             if(i >= len)
02103                                 {
02104                                     printf(ERRTAG
02105                                             "[LINE %d] CB or SB depopulation is too long. It "
02106                                             
02107                                             "should be (length) symbols for CBs and (length+1) "
02108                                              "symbols for SBs.\n", Node->line);
02109                                     exit(1);
02110                                 }
02111                             list[i] = TRUE;
02112                             ++i;
02113                             break;
02114                         case 'F':
02115                         case '0':
02116                             if(i >= len)
02117                                 {
02118                                     printf(ERRTAG
02119                                             "[LINE %d] CB or SB depopulation is too long. It "
02120                                             
02121                                             "should be (length) symbols for CBs and (length+1) "
02122                                                 "symbols for SBs.\n", Node->line);
02123                                     exit(1);
02124                                 }
02125                             list[i] = FALSE;
02126                             ++i;
02127                             break;
02128                         default:
02129                             printf(ERRTAG "[LINE %d] Invalid character %c in CB or " 
02130                                     "SB depopulation list.\n", Node->line,
02131                                         *tmp);
02132                             exit(1);
02133                         }
02134                     ++tmp;
02135                 }
02136             if(i < len)
02137                 {
02138                     printf(ERRTAG "[LINE %d] CB or SB depopulation is too short. It " 
02139                             "should be (length) symbols for CBs and (length+1) "
02140                              "symbols for SBs.\n", Node->line);
02141                     exit(1);
02142                 }
02143             
02144                 /* Free content string */ 
02145                 ezxml_set_txt(Node, "");
02146         }
02147     
02148     else
02149         {
02150             printf(ERRTAG "[LINE %d] '%s' is not a valid type for specifying " 
02151                         "cb and sb depopulation.\n", Node->line, tmp);
02152             exit(1);
02153         }
02154     ezxml_set_attr(Node, "type", NULL);
02155 }
02156 
02157 static void
02158 ProcessSwitches(INOUTP ezxml_t Parent, OUTP struct s_switch_inf **Switches,
02159         OUTP int *NumSwitches, INP boolean timing_enabled)
02160 {
02161     int i, j;
02162     const char *type_name;
02163     const char *switch_name;
02164     
02165     boolean has_buf_size;
02166     ezxml_t Node;
02167     has_buf_size = FALSE;
02168     
02169         /* Count the children and check they are switches */ 
02170         *NumSwitches = CountChildren(Parent, "switch", 1);
02171     
02172         /* Alloc switch list */ 
02173         *Switches = NULL;
02174     if(*NumSwitches > 0)
02175         {
02176             *Switches =
02177                 (struct s_switch_inf *)my_malloc(*NumSwitches *
02178                                                   sizeof(struct
02179                                                          s_switch_inf));
02180             memset(*Switches, 0,
02181                     (*NumSwitches * sizeof(struct s_switch_inf)));
02182         }
02183     
02184         /* Load the switches. */ 
02185         for(i = 0; i < *NumSwitches; ++i)
02186         {
02187             Node = ezxml_child(Parent, "switch");
02188             switch_name = FindProperty(Node, "name", TRUE);
02189             type_name = FindProperty(Node, "type", TRUE);
02190             
02191                 /* Check for switch name collisions */ 
02192                 for(j = 0; j < i; ++j)
02193                 {
02194                     if(0 == strcmp((*Switches)[j].name, switch_name))
02195                         {
02196                             printf(ERRTAG
02197                                     "[LINE %d] Two switches with the same name '%s' were "
02198                                         "found.\n", Node->line, switch_name);
02199                             exit(1);
02200                         }
02201                 }
02202             (*Switches)[i].name = my_strdup(switch_name);
02203             ezxml_set_attr(Node, "name", NULL);
02204             
02205                 /* Figure out the type of switch. */ 
02206                 if(0 == strcmp(type_name, "mux"))
02207                 {
02208                     (*Switches)[i].buffered = TRUE;
02209                     has_buf_size = TRUE;
02210                 }
02211             
02212             else if(0 == strcmp(type_name, "pass_trans"))
02213                 {
02214                     (*Switches)[i].buffered = FALSE;
02215                 }
02216             
02217             else if(0 == strcmp(type_name, "buffer"))
02218                 {
02219                     (*Switches)[i].buffered = TRUE;
02220                 }
02221             
02222             else
02223                 {
02224                         printf(ERRTAG "[LINE %d] Invalid switch type '%s'.\n", Node->line, type_name);
02225                     exit(1);
02226                 }
02227             ezxml_set_attr(Node, "type", NULL);
02228                 (*Switches)[i].R = GetFloatProperty(Node, "R", timing_enabled, 0);
02229             (*Switches)[i].Cin = GetFloatProperty(Node, "Cin", timing_enabled, 0);
02230             (*Switches)[i].Cout = GetFloatProperty(Node, "Cout", timing_enabled, 0);
02231             (*Switches)[i].Tdel = GetFloatProperty(Node, "Tdel", timing_enabled, 0);
02232             (*Switches)[i].buf_size = GetFloatProperty(Node, "buf_size", has_buf_size, 0);
02233             (*Switches)[i].mux_trans_size = GetFloatProperty(Node, "mux_trans_size", FALSE, 1);
02234 
02235                 /* Remove the switch element from parse tree */ 
02236                 FreeNode(Node);
02237         }
02238 }
02239 
02240 
02241 static void CreateModelLibrary(OUTP struct s_arch *arch) {
02242         t_model* model_library;
02243 
02244         model_library = my_calloc(4, sizeof(t_model));
02245         model_library[0].name = my_strdup("input");
02246         model_library[0].index = 0;
02247         model_library[0].inputs = NULL;
02248         model_library[0].instances = NULL;
02249         model_library[0].next = &model_library[1];
02250         model_library[0].outputs = my_calloc(1, sizeof(t_model_ports));
02251         model_library[0].outputs->dir = OUT_PORT;
02252         model_library[0].outputs->name = my_strdup("inpad");
02253         model_library[0].outputs->next = NULL;
02254         model_library[0].outputs->size = 1;
02255         model_library[0].outputs->min_size = 1;
02256         model_library[0].outputs->index = 0;
02257         model_library[0].outputs->is_clock = FALSE;
02258 
02259         model_library[1].name = my_strdup("output");
02260         model_library[1].index = 1;
02261         model_library[1].inputs = my_calloc(1, sizeof(t_model_ports));
02262         model_library[1].inputs->dir = IN_PORT;
02263         model_library[1].inputs->name = my_strdup("outpad");
02264         model_library[1].inputs->next = NULL;
02265         model_library[1].inputs->size = 1;
02266         model_library[1].inputs->min_size = 1;
02267         model_library[1].inputs->index = 0;
02268         model_library[1].inputs->is_clock = FALSE;
02269         model_library[1].instances = NULL;
02270         model_library[1].next = &model_library[2];
02271         model_library[1].outputs = NULL;
02272 
02273         model_library[2].name = my_strdup("latch");
02274         model_library[2].index = 2;
02275         model_library[2].inputs = my_calloc(2, sizeof(t_model_ports));
02276         model_library[2].inputs[0].dir = IN_PORT;
02277         model_library[2].inputs[0].name = my_strdup("D");
02278         model_library[2].inputs[0].next = &model_library[2].inputs[1];
02279         model_library[2].inputs[0].size = 1;
02280         model_library[2].inputs[0].min_size = 1;
02281         model_library[2].inputs[0].index = 0;
02282         model_library[2].inputs[0].is_clock = FALSE;    
02283         model_library[2].inputs[1].dir = IN_PORT;
02284         model_library[2].inputs[1].name = my_strdup("clk");
02285         model_library[2].inputs[1].next = NULL;
02286         model_library[2].inputs[1].size = 1;
02287         model_library[2].inputs[1].min_size = 1;
02288         model_library[2].inputs[1].index = 0;
02289         model_library[2].inputs[1].is_clock = TRUE;     
02290         model_library[2].instances = NULL;
02291         model_library[2].next = &model_library[3];
02292         model_library[2].outputs = my_calloc(1, sizeof(t_model_ports));
02293         model_library[2].outputs->dir = OUT_PORT;
02294         model_library[2].outputs->name = my_strdup("Q");
02295         model_library[2].outputs->next = NULL;
02296         model_library[2].outputs->size = 1;
02297         model_library[2].outputs->min_size = 1;
02298         model_library[2].outputs->index = 0;
02299         model_library[2].outputs->is_clock = FALSE;
02300 
02301         model_library[3].name = my_strdup("names");
02302         model_library[3].index = 3;
02303         model_library[3].inputs = my_calloc(1, sizeof(t_model_ports));
02304         model_library[3].inputs->dir = IN_PORT;
02305         model_library[3].inputs->name = my_strdup("in");
02306         model_library[3].inputs->next = NULL;
02307         model_library[3].inputs->size = 1;
02308         model_library[3].inputs->min_size = 1;
02309         model_library[3].inputs->index = 0;
02310         model_library[3].inputs->is_clock = FALSE;
02311         model_library[3].instances = NULL;
02312         model_library[3].next = NULL;
02313         model_library[3].outputs = my_calloc(1, sizeof(t_model_ports));
02314         model_library[3].outputs->dir = OUT_PORT;
02315         model_library[3].outputs->name = my_strdup("out");
02316         model_library[3].outputs->next = NULL;
02317         model_library[3].outputs->size = 1;
02318         model_library[3].outputs->min_size = 1;
02319         model_library[3].outputs->index = 0;
02320         model_library[3].outputs->is_clock = FALSE;
02321 
02322         arch->model_library = model_library;
02323 }
02324 
02325 static void SyncModelsPbTypes(INOUTP struct s_arch *arch, INP t_type_descriptor * Types, INP int NumTypes) {
02326         int i;
02327         for(i = 0; i < NumTypes; i++) {
02328                 if(Types[i].pb_type != NULL) {
02329                         SyncModelsPbTypes_rec(arch, Types[i].pb_type);
02330                 }
02331         }
02332         for(i = 0; i < NumTypes; i++) {
02333                 if(Types[i].pb_type != NULL) {
02334                         AddModelsToPbTypes_rec(Types[i].pb_type);
02335                 }
02336         }
02337 }
02338 
02339 
02340 static void SyncModelsPbTypes_rec(INOUTP struct s_arch *arch, INOUTP t_pb_type * pb_type) {
02341         int i, j, p;
02342         t_model *model_match_prim, *cur_model;
02343         t_model_ports *model_port;
02344         struct s_linked_vptr *old;
02345         char* blif_model_name;
02346         
02347         boolean found;
02348 
02349         if(pb_type->blif_model != NULL) {               
02350                 
02351                 /* get actual name of subckt */
02352                 if(strstr(pb_type->blif_model, ".subckt ") == pb_type->blif_model) {
02353                         blif_model_name = strchr(pb_type->blif_model, ' ');
02354                 } else {
02355                         blif_model_name = strchr(pb_type->blif_model, '.');
02356                 }
02357                 if(blif_model_name) {
02358                         blif_model_name++; /* get character after the '.' or ' ' */
02359                 } else {
02360                         printf("Unknown blif model %s in pb_type %s\n", pb_type->blif_model, pb_type->name);
02361                 }
02362 
02363                 /* There are two sets of models to consider, the standard library of models and the user defined models */
02364                 if(     (strcmp(blif_model_name, "input") == 0)  ||
02365                         (strcmp(blif_model_name, "output") == 0) ||
02366                         (strcmp(blif_model_name, "names") == 0)  ||
02367                         (strcmp(blif_model_name, "latch") == 0) ) {
02368                         cur_model = arch->model_library;
02369                 } else {
02370                         cur_model = arch->models;
02371                 }
02372 
02373                 /* Determine the logical model to use */
02374                 found = FALSE;  
02375                 model_match_prim = NULL;
02376                 while(cur_model && !found) {
02377                         /* blif model always starts with .subckt so need to skip first 8 characters */
02378                         if(strcmp(blif_model_name, cur_model->name) == 0) {
02379                                 found = TRUE;
02380                                 model_match_prim = cur_model;
02381                         }
02382                         cur_model = cur_model->next;
02383                 }
02384                 if(found != TRUE) {
02385                         printf(ERRTAG "No matching model for pb_type %s\n", pb_type->blif_model);
02386                         exit(1);
02387                 }
02388 
02389 
02390                 pb_type->model = model_match_prim;
02391                 old = model_match_prim->pb_types;
02392                 model_match_prim->pb_types = (struct s_linked_vptr*) my_malloc(sizeof(struct s_linked_vptr));
02393                 model_match_prim->pb_types->next = old;
02394                 model_match_prim->pb_types->data_vptr = pb_type;
02395 
02396                 for(p = 0; p < pb_type->num_ports; p++) {
02397                         found = FALSE;
02398                         /* TODO: Parse error checking - check if INPUT matches INPUT and OUTPUT matches OUTPUT (not yet done) */
02399                         model_port = model_match_prim->inputs;
02400                         while(model_port && !found) {
02401                                 if(strcmp(model_port->name, pb_type->ports[p].name) == 0) {
02402                                         if(model_port->size < pb_type->ports[p].num_pins) {
02403                                                 model_port->size = pb_type->ports[p].num_pins;
02404                                         }
02405                                         if(model_port->min_size > pb_type->ports[p].num_pins || model_port->min_size == -1) {
02406                                                 model_port->min_size = pb_type->ports[p].num_pins;
02407                                         }
02408                                         pb_type->ports[p].model_port = model_port;
02409                                         assert(pb_type->ports[p].type == model_port->dir);
02410                                         assert(pb_type->ports[p].is_clock == model_port->is_clock);
02411                                         found = TRUE;
02412                                 }
02413                                 model_port = model_port->next;
02414                         }
02415                         model_port = model_match_prim->outputs;
02416                         while(model_port && !found) {
02417                                 if(strcmp(model_port->name, pb_type->ports[p].name) == 0) {
02418                                         if(model_port->size < pb_type->ports[p].num_pins) {
02419                                                 model_port->size = pb_type->ports[p].num_pins;                                          
02420                                         }
02421                                         if(model_port->min_size > pb_type->ports[p].num_pins || model_port->min_size == -1) {
02422                                                 model_port->min_size = pb_type->ports[p].num_pins;
02423                                         }
02424                                         pb_type->ports[p].model_port = model_port;
02425                                         assert(pb_type->ports[p].type == model_port->dir);
02426                                         found = TRUE;
02427                                 }
02428                                 model_port = model_port->next;
02429                         }
02430                         if(found != TRUE) {
02431                                 printf(ERRTAG "No matching model port for port %s in pb_type %s\n", pb_type->ports[p].name, pb_type->name);
02432                                 exit(1);
02433                         }
02434                 }
02435         } else {
02436                 for(i = 0; i < pb_type->num_modes; i++) {
02437                         for(j = 0; j < pb_type->modes[i].num_pb_type_children; j++) {
02438                                 SyncModelsPbTypes_rec(arch, &(pb_type->modes[i].pb_type_children[j]));
02439                         }
02440                 }
02441         }
02442 }
02443 
02444 static void AddModelsToPbTypes_rec(INOUTP t_pb_type *pb_type) {
02445         int i, j;
02446         struct s_linked_vptr *child, *curr;
02447 
02448         /* Determine all logical models contained by pb_type */
02449         if(pb_type->num_modes == 0) {
02450                 pb_type->models_contained = my_malloc(sizeof(struct s_linked_vptr));
02451                 pb_type->models_contained->data_vptr = pb_type->model;
02452                 pb_type->models_contained->next = NULL;
02453         } else {
02454                 pb_type->models_contained = NULL;
02455                 for(i = 0; i < pb_type->num_modes; i++) {
02456                         for(j = 0; j < pb_type->modes[i].num_pb_type_children; j++) {
02457                                 AddModelsToPbTypes_rec(&pb_type->modes[i].pb_type_children[j]);
02458                                 child = pb_type->modes[i].pb_type_children[j].models_contained;
02459                                 /* find model in parent that matches with that in child, if not, add to parent */
02460                                 while(child) {
02461                                         curr = pb_type->models_contained;
02462                                         while(curr) {
02463                                                 if(curr->data_vptr == child->data_vptr) {
02464                                                         break;
02465                                                 }
02466                                                 curr = curr->next;
02467                                         }
02468                                         if(curr == NULL) {
02469                                                 curr = my_malloc(sizeof(struct s_linked_vptr));
02470                                                 curr->next = pb_type->models_contained;
02471                                                 curr->data_vptr = child->data_vptr;
02472                                                 pb_type->models_contained = curr;
02473                                         }
02474                                         child = child->next;
02475                                 }
02476                         }
02477                 }
02478         }
02479 }
02480 
02481 static void UpdateAndCheckModels(INOUTP struct s_arch *arch) {
02482         t_model * cur_model;
02483         t_model_ports *port;
02484         int i, j;
02485         cur_model = arch->models;
02486         while(cur_model) {
02487                 if(cur_model->pb_types == NULL) {
02488                         printf("No pb_type found for model %s\n", cur_model->name);
02489                         exit(1);
02490                 }
02491                 port = cur_model->inputs;
02492                 i = 0;
02493                 j = 0;
02494                 while(port) {
02495                         if(port->is_clock) {
02496                                 port->index = i;
02497                                 i++;
02498                         } else {
02499                                 port->index = j;
02500                                 j++;
02501                         }
02502                         port = port->next;
02503                 }
02504                 port = cur_model->outputs;
02505                 i = 0;
02506                 while(port) {
02507                         port->index = i;
02508                         i++;
02509                         port = port->next;
02510                 }
02511                 cur_model = cur_model->next;
02512         }
02513 }
02514 
02515 
02516 /** Output the data from architecture data so user can verify it
02517  * was interpretted correctly.
02518  */ 
02519 void
02520 EchoArch(INP const char *EchoFile, INP const t_type_descriptor * Types,
02521         INP int NumTypes, struct s_arch *arch)
02522 {
02523     int i, j;
02524     FILE * Echo;
02525         t_model * cur_model;
02526         t_model_ports * model_port;
02527         struct s_linked_vptr *cur_vptr;
02528 
02529 
02530     Echo = my_fopen(EchoFile, "w", 0);
02531         cur_model = NULL;
02532 
02533         for( j = 0; j < 2; j++ ) {
02534                 if(j == 0) {
02535                         fprintf(Echo, "Printing user models \n");
02536                         cur_model = arch->models;
02537                 } else if(j == 1) {
02538                         fprintf(Echo, "Printing library models \n");
02539                         cur_model = arch->model_library;
02540                 }
02541                 while(cur_model) {
02542                         fprintf(Echo, "Model: \"%s\"\n", cur_model->name);
02543                         model_port = cur_model->inputs;
02544                         while(model_port) {
02545                                 fprintf(Echo, "\tInput Ports: \"%s\" \"%d\" min_size=\"%d\"\n", model_port->name, model_port->size, model_port->min_size);
02546                                 model_port = model_port->next;
02547                         }
02548                         model_port = cur_model->outputs;
02549                         while(model_port) {
02550                                 fprintf(Echo, "\tOutput Ports: \"%s\" \"%d\" min_size=\"%d\"\n", model_port->name, model_port->size, model_port->min_size);
02551                                 model_port = model_port->next;
02552                         }
02553                         cur_vptr = cur_model->pb_types;
02554                         i = 0;
02555                         while(cur_vptr != NULL) {
02556                                 fprintf(Echo, "\tpb_type %d: \"%s\"\n", i, ((t_pb_type*)cur_vptr->data_vptr)->name);
02557                                 cur_vptr = cur_vptr->next;
02558                                 i++;
02559                         }
02560                         
02561                         cur_model = cur_model->next;
02562                 }
02563         }
02564 
02565     for(i = 0; i < NumTypes; ++i)
02566         {
02567             fprintf(Echo, "Type: \"%s\"\n", Types[i].name);
02568             fprintf(Echo, "\tcapacity: %d\n", Types[i].capacity);
02569             fprintf(Echo, "\theight: %d\n", Types[i].height);
02570             
02571             fprintf(Echo, "\tis_Fc_frac: %s\n",
02572                       (Types[i].is_Fc_frac ? "TRUE" : "FALSE"));
02573             fprintf(Echo, "\tis_Fc_out_full_flex: %s\n",
02574                      (Types[i].is_Fc_out_full_flex ? "TRUE" : "FALSE"));
02575             fprintf(Echo, "\tFc_in: %f\n", Types[i].Fc_in);
02576             fprintf(Echo, "\tFc_out: %f\n", Types[i].Fc_out);
02577 
02578                 
02579             fprintf(Echo, "\tnum_drivers: %d\n", Types[i].num_drivers);
02580             fprintf(Echo, "\tnum_receivers: %d\n", Types[i].num_receivers);
02581                 fprintf(Echo, "\tindex: %d\n", Types[i].index);
02582                 if(Types[i].pb_type) {
02583                         PrintPb_types_rec(Echo, Types[i].pb_type, 2);
02584                 }
02585             fprintf(Echo, "\n");
02586         }
02587     fclose(Echo);
02588 }
02589 
02590 static void
02591 PrintPb_types_rec(INP FILE * Echo, INP const t_pb_type * pb_type, int level)
02592 {
02593         int i, j, k;
02594         char *tabs;
02595 
02596         tabs = my_malloc((level + 1) * sizeof(char));
02597         for(i = 0; i < level; i++) {
02598                 tabs[i] = '\t';
02599         }
02600         tabs[level] = '\0';
02601         
02602         fprintf(Echo, "%spb_type name: %s\n", tabs, pb_type->name);
02603         fprintf(Echo, "%s\tblif_model: %s\n", tabs, pb_type->blif_model);
02604         fprintf(Echo, "%s\tclass_type: %d\n", tabs, pb_type->class_type);
02605         fprintf(Echo, "%s\tnum_modes: %d\n", tabs, pb_type->num_modes);
02606         fprintf(Echo, "%s\tnum_ports: %d\n", tabs, pb_type->num_ports);
02607         for(i = 0; i < pb_type->num_ports; i++) {
02608                 fprintf(Echo, "%s\tport %s type %d num_pins %d\n", tabs,
02609                         pb_type->ports[i].name,
02610                         pb_type->ports[i].type,
02611                         pb_type->ports[i].num_pins);
02612         }
02613         for(i = 0; i < pb_type->num_modes; i++) {
02614                 fprintf(Echo, "%s\tmode %s:\n", tabs, pb_type->modes[i].name);
02615                 for(j = 0; j < pb_type->modes[i].num_pb_type_children; j++) {
02616                         PrintPb_types_rec(Echo, &pb_type->modes[i].pb_type_children[j], level + 2);
02617                 }
02618                 for(j = 0; j < pb_type->modes[i].num_interconnect; j++) {
02619                         fprintf(Echo, "%s\t\tinterconnect %d %s %s\n", tabs, pb_type->modes[i].interconnect[j].type,
02620                                 pb_type->modes[i].interconnect[j].input_string, 
02621                                 pb_type->modes[i].interconnect[j].output_string);
02622                         for(k = 0; k < pb_type->modes[i].interconnect[j].num_annotations; k++) {
02623                                 fprintf(Echo, "%s\t\t\tannotation %s %s %d: %s\n", tabs, pb_type->modes[i].interconnect[j].annotations[k].input_pins,
02624                                         pb_type->modes[i].interconnect[j].annotations[k].output_pins, pb_type->modes[i].interconnect[j].annotations[k].format,
02625                                         pb_type->modes[i].interconnect[j].annotations[k].value[0]);
02626                         }
02627                 }
02628         }
02629         free(tabs);
02630 }
02631 
02632 
02633