📄 xml_arch.c
字号:
#include <string.h>#include <assert.h>#include "util.h"#include "vpr_types.h"#include "ReadLine.h"#include "ezxml.h"#include "globals.h"#include "xml_arch.h"/* special type indexes, necessary for initialization initialization, everything afterwards should use the pointers to these type indices*/ #define EMPTY_TYPE_INDEX 0#define IO_TYPE_INDEX 1 enum Fc_type{ FC_ABS, FC_FRAC, FC_FULL };/* Function prototypes */ static boolean IsWhitespace(char c);static void CountTokensInString(IN const char *Str, OUT int *Num, OUT int *Len);static char **GetNodeTokens(IN ezxml_t Node);static void CheckElement(IN ezxml_t Node, IN const char *Name);static void CheckText(IN ezxml_t Node);static void FreeNode(INOUT ezxml_t Node);static ezxml_t FindElement(IN ezxml_t Parent, IN const char *Name, IN boolean Required);static const char *FindProperty(IN ezxml_t Parent, IN const char *Name, IN boolean Required);static int CountChildren(IN ezxml_t Node, IN const char *Name);static void ParseFc(ezxml_t Node, enum Fc_type *Fc, float *Val);static void SetupEmptyType();static void SetupClassInf(ezxml_t Classes, t_type_descriptor * Type);static void SetupPinClasses(ezxml_t Classes, t_type_descriptor * Type);static void SetupPinLocations(ezxml_t Locations, t_type_descriptor * Type);static void SetupGridLocations(ezxml_t Locations, t_type_descriptor * Type);static void SetupTypeTiming(ezxml_t timing, t_type_descriptor * Type);static void SetupSubblocksTcomb(ezxml_t timing, t_type_descriptor * Type);static void SetupSubblocksTSeq(ezxml_t timing_seq_in, ezxml_t timing_seq_out, t_type_descriptor * Type);static void Process_Fc(ezxml_t Fc_in_node, ezxml_t Fc_out_node, t_type_descriptor * Type);static void ProcessSubblocks(INOUT ezxml_t Parent, INOUT t_type_descriptor * Type, IN boolean timing_enabled);static void ProcessTypeProps(ezxml_t Node, t_type_descriptor * Type);static void ProcessChanWidthDistr(INOUT ezxml_t Node, OUT struct s_arch *arch);static void ProcessChanWidthDistrDir(INOUT ezxml_t Node, OUT t_chan * chan);static void ProcessLayout(INOUT ezxml_t Node, OUT struct s_arch *arch);static void ProcessDevice(INOUT ezxml_t Node, OUT struct s_arch *arch, IN boolean timing_enabled);static void ProcessIO(INOUT ezxml_t Node, IN boolean timing_enabled);static void ProcessTypes(INOUT ezxml_t Node, OUT t_type_descriptor ** Types, OUT int *NumTypes, IN boolean timing_enabled);static void ProcessSwitches(INOUT ezxml_t Node, OUT struct s_switch_inf **Switches, OUT int *NumSwitches, IN boolean timing_enabled);static void ProcessSegments(INOUT ezxml_t Parent, OUT struct s_segment_inf **Segs, OUT int *NumSegs, IN struct s_switch_inf *Switches, IN int NumSwitches, IN boolean timing_enabled);static void ProcessCB_SB(INOUT ezxml_t Node, INOUT boolean * list, IN int len);/* Returns TRUE if character is whatspace between tokens */ static booleanIsWhitespace(char c){ switch (c) { case ' ': case '\t': case '\r': case '\n': return TRUE; default: return FALSE; }}/* Count tokens and length in all the Text children nodes of current node. */ static voidCountTokensInString(IN const char *Str, OUT int *Num, OUT int *Len){ boolean InToken; *Num = 0; *Len = 0; InToken = FALSE; while(*Str) { if(IsWhitespace(*Str)) { InToken = FALSE; } else { if(!InToken) { ++(*Num); } ++(*Len); InToken = TRUE; } ++Str; /* Advance pointer */ }}/* Returns a token list of the text nodes of a given node. This * unlinks all the text nodes from the document */ static char **GetNodeTokens(IN ezxml_t Node){ int Count, Len; char *Cur, *Dst; boolean InToken; char **Tokens; /* Count the tokens and find length of token data */ CountTokensInString(Node->txt, &Count, &Len); /* Error out if no tokens found */ if(Count < 1) { printf(ERRTAG "Node '%s' on expected text data " "but none was found.\n", Node->name); } Len = (sizeof(char) * Len) + /* Length of actual data */ (sizeof(char) * Count); /* Null terminators */ /* Alloc the pointer list and data list. Count the final * empty string we will use as list terminator */ Tokens = (char **)my_malloc(sizeof(char *) * (Count + 1)); Dst = (char *)my_malloc(sizeof(char) * Len); Count = 0; /* Copy data to tokens */ Cur = Node->txt; InToken = FALSE; while(*Cur) { if(IsWhitespace(*Cur)) { if(InToken) { *Dst = '\0'; ++Dst; } InToken = FALSE; } else { if(!InToken) { Tokens[Count] = Dst; ++Count; } *Dst = *Cur; ++Dst; InToken = TRUE; } ++Cur; } if(InToken) { /* Null term final token */ *Dst = '\0'; ++Dst; } ezxml_set_txt(Node, ""); Tokens[Count] = NULL; /* End of tokens marker is a NULL */ /* Return the list */ return Tokens;}/* Checks the node is an element with name equal to one given */ static voidCheckElement(IN ezxml_t Node, IN const char *Name){ if(0 != strcmp(Node->name, Name)) { printf(ERRTAG "Element '%s' within element '%s' does match expected " "element type of '%s'\n", Node->name, Node->parent->name, Name); exit(1); }}/* Checks that the node has no remaining child nodes or property nodes, * then unlinks the node from the tree which updates pointers and * frees the memory */ static voidFreeNode(INOUT ezxml_t Node){ ezxml_t Cur; char *Txt; /* Shouldn't have unprocessed properties */ if(Node->attr[0]) { printf(ERRTAG "Node '%s' has invalid property %s=\"%s\".\n", Node->name, Node->attr[0], Node->attr[1]); exit(1); } /* Shouldn't have non-whitespace text */ Txt = Node->txt; while(*Txt) { if(!IsWhitespace(*Txt)) { printf(ERRTAG "Node '%s' has unexpected text '%s' within it.\n", Node->name, Node->txt); exit(1); } ++Txt; } /* We shouldn't have child items left */ Cur = Node->child; if(Cur) { printf(ERRTAG "Node '%s' on has invalid child node '%s'.\n", Node->name, Cur->name); exit(1); } /* Now actually unlink and free the node */ ezxml_remove(Node);}/* Finds child element with given name and returns it. Errors out if * more than one instance exists. */ static ezxml_tFindElement(IN ezxml_t Parent, IN const char *Name, IN boolean Required){ ezxml_t Cur; /* Find the first node of correct name */ Cur = ezxml_child(Parent, Name); /* Error out if node isn't found but they required it */ if(Required) { if(NULL == Cur) { printf(ERRTAG "Element '%s' not found within element '%s'.\n", Name, Parent->name); exit(1); } } /* Look at next tag with same name and error out if exists */ if(Cur != NULL && Cur->next) { printf(ERRTAG "Element '%s' found twice within element '%s'.\n", Name, Parent->name); exit(1); } return Cur;}static const char *FindProperty(IN ezxml_t Parent, IN const char *Name, IN boolean Required){ const char *Res; Res = ezxml_attr(Parent, Name); if(Required) { if(NULL == Res) { printf(ERRTAG "Required property '%s' not found for element '%s'.\n", Name, Parent->name); exit(1); } } return Res;}/* Counts number of child elements in a container element. * Name is the name of the child element. * Errors if no occurances found. */ static intCountChildren(IN ezxml_t Node, IN const char *Name){ ezxml_t Cur, sibling; int Count; Count = 0; Cur = Node->child; while(Cur) { if(strcmp(Cur->name, Name) == 0) { ++Count; } sibling = Cur->sibling; Cur = Cur->next; if(Cur == NULL) { Cur = sibling; } } /* Error if no occurances found */ if(Count < 1) { printf(ERRTAG "Expected node '%s' to have " "child elements, but none found.\n", Node->name); exit(1); } return Count;}/* Figures out the Fc type and value for the given node. Unlinks the * type and value. */ static voidParseFc(ezxml_t Node, enum Fc_type *Fc, float *Val){ const char *Prop; Prop = FindProperty(Node, "type", TRUE); if(0 == strcmp(Prop, "abs")) { *Fc = FC_ABS; } else if(0 == strcmp(Prop, "frac")) { *Fc = FC_FRAC; } else if(0 == strcmp(Prop, "full")) { *Fc = FC_FULL; } else { printf(ERRTAG "Invalid type '%s' for Fc. Only abs, frac " "and full are allowed.\n", Prop); exit(1); } switch (*Fc) { case FC_FULL: *Val = 0.0; break; case FC_ABS: case FC_FRAC: *Val = atof(Node->txt); ezxml_set_attr(Node, "type", NULL); ezxml_set_txt(Node, ""); break; default: assert(0); } /* Release the property */ ezxml_set_attr(Node, "type", NULL);}/* Set's up the classinf data of a type and counts the number of * pins the type has. If capacity > 1, we need multiple sets of classes. * This correctly sets num_pins to include all the replicated but * unique pins that give the capacity. */ static voidSetupClassInf(ezxml_t Classes, t_type_descriptor * Type){ int i, k, CurClass, CurPin, NumClassPins; ezxml_t Cur; const char *Prop; /* Alloc class_inf structs */ Type->num_class = Type->capacity * CountChildren(Classes, "class"); Type->class_inf = (t_class *) my_malloc(Type->num_class * sizeof(t_class)); /* Make multiple passes to handle capacity with index increased each pass */ CurPin = 0; CurClass = 0; Type->num_pins = 0; Type->num_drivers = 0; Type->num_receivers = 0; for(i = 0; i < Type->capacity; ++i) { /* Restart the parse tree at each node */ Cur = Classes->child; while(Cur) { CheckElement(Cur, "class"); /* Count the number of pins in this class */ CountTokensInString(Cur->txt, &NumClassPins, &k); Type->num_pins += NumClassPins; /* Alloc class structures */ Type->class_inf[CurClass].num_pins = NumClassPins; Type->class_inf[CurClass].pinlist = (int *)my_malloc(NumClassPins * sizeof(int)); for(k = 0; k < NumClassPins; ++k) { Type->class_inf[CurClass].pinlist[k] = CurPin; ++CurPin; } /* Figure out class type */ Prop = FindProperty(Cur, "type", TRUE); if(0 == strcmp(Prop, "in")) { Type->num_receivers += NumClassPins; Type->class_inf[CurClass].type = RECEIVER; } else if(0 == strcmp(Prop, "out")) { Type->num_drivers += NumClassPins; Type->class_inf[CurClass].type = DRIVER; } else if(0 == strcmp(Prop, "global")) { Type->class_inf[CurClass].type = RECEIVER; } else { printf(ERRTAG "Invalid pin class type '%s'.\n", Prop); exit(1); } ++CurClass; Cur = Cur->next; } }}/* Allocs structures that describe pins and reads pin names. Sets * pin/class mappings. Unliinks the class descriptor nodes from XML. * For capacity > 1 pins and pinclasses are replicated because while * they share the same properties and setup, they are treated as * being unique. */ static voidSetupPinClasses(ezxml_t Classes, t_type_descriptor * Type){ int CurClass, i, j, CurPin, PinsPerSubtile, ClassesPerSubtile; ezxml_t Cur, Prev; const char *Prop; boolean IsGlobal; char **Tokens; int *pin_used = NULL; /* Allocs and sets up the classinf data and counts pins */ SetupClassInf(Classes, Type); PinsPerSubtile = Type->num_pins / Type->capacity; ClassesPerSubtile = Type->num_class / Type->capacity; /* Alloc num_pin sized lists. Replicated pins don't have new names. */ Type->is_global_pin = (boolean *) my_malloc(Type->num_pins * sizeof(boolean)); Type->pin_class = (int *)my_malloc(Type->num_pins * sizeof(int)); pin_used = (int *)my_malloc(Type->num_pins * sizeof(int)); for(i = 0; i < Type->num_pins; ++i) { pin_used[i] = FALSE; } /* Iterate over all pins */ CurClass = 0; Cur = Classes->child; while(Cur) { CheckElement(Cur, "class"); /* Figure out if global class */ IsGlobal = FALSE; Prop = FindProperty(Cur, "type", TRUE); if(0 == strcmp(Prop, "global")) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -