📄 xml_arch.c
字号:
ezxml_t Cur, Next; /* Parse the file */ Cur = ezxml_parse_file(ArchFile); if(NULL == Cur) { printf(ERRTAG "Unable to load architecture file '%s'.\n", ArchFile); } /* Root node should be architecture */ CheckElement(Cur, "architecture"); /* Process layout */ Next = FindElement(Cur, "layout", TRUE); ProcessLayout(Next, arch); FreeNode(Next); /* Process device */ Next = FindElement(Cur, "device", TRUE); ProcessDevice(Next, arch, timing_enabled); FreeNode(Next); /* Process types */ Next = FindElement(Cur, "typelist", TRUE); ProcessTypes(Next, Types, NumTypes, timing_enabled); FreeNode(Next); /* Process switches */ Next = FindElement(Cur, "switchlist", TRUE); ProcessSwitches(Next, &(arch->Switches), &(arch->num_switches), timing_enabled); FreeNode(Next); /* Process segments. This depends on switches */ Next = FindElement(Cur, "segmentlist", TRUE); ProcessSegments(Next, &(arch->Segments), &(arch->num_segments), arch->Switches, arch->num_switches, timing_enabled); FreeNode(Next); /* Release the full XML tree */ FreeNode(Cur);}static voidProcessSegments(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){ int i, j, length; const char *tmp; ezxml_t SubElem; ezxml_t Node; /* Count the number of segs and check they are in fact * of segment elements. */ *NumSegs = CountChildren(Parent, "segment"); /* Alloc segment list */ *Segs = NULL; if(*NumSegs > 0) { *Segs = (struct s_segment_inf *)my_malloc(*NumSegs * sizeof(struct s_segment_inf)); memset(*Segs, 0, (*NumSegs * sizeof(struct s_segment_inf))); } /* Load the segments. */ for(i = 0; i < *NumSegs; ++i) { Node = ezxml_child(Parent, "segment"); /* Get segment length */ length = 1; /* DEFAULT */ tmp = FindProperty(Node, "length", FALSE); if(tmp) { if(strcmp(tmp, "longline") == 0) { (*Segs)[i].longline = TRUE; } else { length = my_atoi(tmp); } } (*Segs)[i].length = length; ezxml_set_attr(Node, "length", NULL); /* Get the frequency */ (*Segs)[i].frequency = 1; /* DEFAULT */ tmp = FindProperty(Node, "freq", FALSE); if(tmp) { (*Segs)[i].frequency = my_atoi(tmp); } ezxml_set_attr(Node, "freq", NULL); /* Get timing info */ (*Segs)[i].Rmetal = 0; /* DEFAULT */ tmp = FindProperty(Node, "Rmetal", timing_enabled); if(tmp) { (*Segs)[i].Rmetal = atof(tmp); } ezxml_set_attr(Node, "Rmetal", NULL); (*Segs)[i].Cmetal = 0; /* DEFAULT */ tmp = FindProperty(Node, "Cmetal", timing_enabled); if(tmp) { (*Segs)[i].Cmetal = atof(tmp); } ezxml_set_attr(Node, "Cmetal", NULL); /* Get the type */ tmp = FindProperty(Node, "type", TRUE); if(0 == strcmp(tmp, "bidir")) { (*Segs)[i].directionality = BI_DIRECTIONAL; } else if(0 == strcmp(tmp, "unidir")) { (*Segs)[i].directionality = UNI_DIRECTIONAL; } else { printf(ERRTAG "Invalid switch type '%s'.\n", tmp); exit(1); } ezxml_set_attr(Node, "type", NULL); /* Get the wire and opin switches, or mux switch if unidir */ if(UNI_DIRECTIONAL == (*Segs)[i].directionality) { SubElem = FindElement(Node, "mux", TRUE); tmp = FindProperty(SubElem, "name", TRUE); /* Match names */ for(j = 0; j < NumSwitches; ++j) { if(0 == strcmp(tmp, Switches[j].name)) { break; /* End loop so j is where we want it */ } } if(j >= NumSwitches) { printf(ERRTAG "'%s' is not a valid mux name.\n", tmp); exit(1); } ezxml_set_attr(SubElem, "name", NULL); FreeNode(SubElem); /* Unidir muxes must have the same switch * for wire and opin fanin since there is * really only the mux in unidir. */ (*Segs)[i].wire_switch = j; (*Segs)[i].opin_switch = j; } else { assert(BI_DIRECTIONAL == (*Segs)[i].directionality); SubElem = FindElement(Node, "wire_switch", TRUE); tmp = FindProperty(SubElem, "name", TRUE); /* Match names */ for(j = 0; j < NumSwitches; ++j) { if(0 == strcmp(tmp, Switches[j].name)) { break; /* End loop so j is where we want it */ } } if(j >= NumSwitches) { printf(ERRTAG "'%s' is not a valid wire_switch name.\n", tmp); exit(1); } (*Segs)[i].wire_switch = j; ezxml_set_attr(SubElem, "name", NULL); FreeNode(SubElem); SubElem = FindElement(Node, "opin_switch", TRUE); tmp = FindProperty(SubElem, "name", TRUE); /* Match names */ for(j = 0; j < NumSwitches; ++j) { if(0 == strcmp(tmp, Switches[j].name)) { break; /* End loop so j is where we want it */ } } if(j >= NumSwitches) { printf(ERRTAG "'%s' is not a valid opin_switch name.\n", tmp); exit(1); } (*Segs)[i].opin_switch = j; ezxml_set_attr(SubElem, "name", NULL); FreeNode(SubElem); } /* Setup the CB list if they give one, otherwise use full */ (*Segs)[i].cb_len = length; (*Segs)[i].cb = (boolean *) my_malloc(length * sizeof(boolean)); for(j = 0; j < length; ++j) { (*Segs)[i].cb[j] = TRUE; } SubElem = FindElement(Node, "cb", FALSE); if(SubElem) { ProcessCB_SB(SubElem, (*Segs)[i].cb, length); FreeNode(SubElem); } /* Setup the SB list if they give one, otherwise use full */ (*Segs)[i].sb_len = (length + 1); (*Segs)[i].sb = (boolean *) my_malloc((length + 1) * sizeof(boolean)); for(j = 0; j < (length + 1); ++j) { (*Segs)[i].sb[j] = TRUE; } SubElem = FindElement(Node, "sb", FALSE); if(SubElem) { ProcessCB_SB(SubElem, (*Segs)[i].sb, (length + 1)); FreeNode(SubElem); } FreeNode(Node); }}static voidProcessCB_SB(INOUT ezxml_t Node, INOUT boolean * list, IN int len){ const char *tmp = NULL; int i; /* Check the type. We only support 'pattern' for now. * Should add frac back eventually. */ tmp = FindProperty(Node, "type", TRUE); if(0 == strcmp(tmp, "pattern")) { i = 0; /* Get the content string */ tmp = Node->txt; while(*tmp) { switch (*tmp) { case ' ': break; case 'T': case '1': if(i >= len) { printf(ERRTAG "CB or SB depopulation is too long. It " "should be (length) symbols for CBs and (length+1) " "symbols for SBs.\n"); exit(1); } list[i] = TRUE; ++i; break; case 'F': case '0': if(i >= len) { printf(ERRTAG "CB or SB depopulation is too long. It " "should be (length) symbols for CBs and (length+1) " "symbols for SBs.\n"); exit(1); } list[i] = FALSE; ++i; break; default: printf(ERRTAG "Invalid character %c in CB or " "SB depopulation list.\n", *tmp); exit(1); } ++tmp; } if(i < len) { printf(ERRTAG "CB or SB depopulation is too short. It " "should be (length) symbols for CBs and (length+1) " "symbols for SBs.\n"); exit(1); } /* Free content string */ ezxml_set_txt(Node, ""); } else { printf(ERRTAG "'%s' is not a valid type for specifying " "cb and sb depopulation.\n", tmp); exit(1); } ezxml_set_attr(Node, "type", NULL);}static voidProcessSwitches(INOUT ezxml_t Parent, OUT struct s_switch_inf **Switches, OUT int *NumSwitches, IN boolean timing_enabled){ int i, j; const char *type_name; const char *switch_name; const char *Prop; boolean has_buf_size; ezxml_t Node; has_buf_size = FALSE; /* Count the children and check they are switches */ *NumSwitches = CountChildren(Parent, "switch"); /* Alloc switch list */ *Switches = NULL; if(*NumSwitches > 0) { *Switches = (struct s_switch_inf *)my_malloc(*NumSwitches * sizeof(struct s_switch_inf)); memset(*Switches, 0, (*NumSwitches * sizeof(struct s_switch_inf))); } /* Load the switches. */ for(i = 0; i < *NumSwitches; ++i) { Node = ezxml_child(Parent, "switch"); switch_name = FindProperty(Node, "name", TRUE); type_name = FindProperty(Node, "type", TRUE); /* Check for switch name collisions */ for(j = 0; j < i; ++j) { if(0 == strcmp((*Switches)[j].name, switch_name)) { printf(ERRTAG "Two switches with the same name '%s' were " "found.\n", switch_name); exit(1); } } (*Switches)[i].name = my_strdup(switch_name); ezxml_set_attr(Node, "name", NULL); /* Figure out the type of switch. */ if(0 == strcmp(type_name, "mux")) { (*Switches)[i].buffered = TRUE; has_buf_size = TRUE; } else if(0 == strcmp(type_name, "pass_trans")) { (*Switches)[i].buffered = FALSE; } else if(0 == strcmp(type_name, "buffer")) { (*Switches)[i].buffered = TRUE; } else { printf(ERRTAG "Invalid switch type '%s'.\n", type_name); exit(1); } ezxml_set_attr(Node, "type", NULL); Prop = FindProperty(Node, "R", timing_enabled); if(Prop != NULL) { (*Switches)[i].R = atof(Prop); ezxml_set_attr(Node, "R", NULL); } Prop = FindProperty(Node, "Cin", timing_enabled); if(Prop != NULL) { (*Switches)[i].Cin = atof(Prop); ezxml_set_attr(Node, "Cin", NULL); } Prop = FindProperty(Node, "Cout", timing_enabled); if(Prop != NULL) { (*Switches)[i].Cout = atof(Prop); ezxml_set_attr(Node, "Cout", NULL); } Prop = FindProperty(Node, "Tdel", timing_enabled); if(Prop != NULL) { (*Switches)[i].Tdel = atof(Prop); ezxml_set_attr(Node, "Tdel", NULL); } Prop = FindProperty(Node, "buf_size", has_buf_size); if(has_buf_size) { (*Switches)[i].buf_size = atof(Prop); ezxml_set_attr(Node, "buf_size", NULL); } Prop = FindProperty(Node, "mux_trans_size", FALSE); if(Prop != NULL) { (*Switches)[i].mux_trans_size = atof(Prop); ezxml_set_attr(Node, "mux_trans_size", NULL); } /* Remove the switch element from parse tree */ FreeNode(Node); }}/* Output the data from architecture data so user can verify it * was interpretted correctly. */ voidEchoArch(IN const char *EchoFile, IN const t_type_descriptor * Types, IN int NumTypes){ int i, j, k; FILE * Echo; Echo = my_fopen(EchoFile, "w"); for(i = 0; i < NumTypes; ++i) { fprintf(Echo, "Type: \"%s\"\n", Types[i].name); fprintf(Echo, "\tcapacity: %d\n", Types[i].capacity); fprintf(Echo, "\theight: %d\n", Types[i].height); if(Types[i].num_pins > 0) { for(j = 0; j < Types[i].height; ++j) { fprintf(Echo, "\tpinloc[%d] TOP LEFT BOTTOM RIGHT:\n", j); for(k = 0; k < Types[i].num_pins; ++k) { fprintf(Echo, "\t\t%d %d %d %d\n", Types[i].pinloc[j][TOP][k], Types[i].pinloc[j][LEFT][k], Types[i].pinloc[j][BOTTOM][k], Types[i].pinloc[j][RIGHT][k]); } } } fprintf(Echo, "\tnum_pins (scaled for capacity): %d\n", Types[i].num_pins); if(Types[i].num_pins > 0) { fprintf(Echo, "\tPins: NAME CLASS IS_GLOBAL\n"); for(j = 0; j < Types[i].num_pins; ++j) { fprintf(Echo, "\t\t%d %d %s\n", j, Types[i].pin_class[j], (Types[i]. is_global_pin[j] ? "TRUE" : "FALSE")); } } fprintf(Echo, "\tnum_class: %d\n", Types[i].num_class); if(Types[i].num_class > 0) { for(j = 0; j < Types[i].num_class; ++j) { switch (Types[i].class_inf[j].type) { case RECEIVER: fprintf(Echo, "\t\tType: RECEIVER\n"); break; case DRIVER: fprintf(Echo, "\t\tType: DRIVER\n"); break; case OPEN: fprintf(Echo, "\t\tType: OPEN\n"); break; default: fprintf(Echo, "\t\tType: UNKNOWN\n"); break; } fprintf(Echo, "\t\t\tnum_pins: %d\n", Types[i].class_inf[j].num_pins); fprintf(Echo, "\t\t\tpins: "); /* No \n */ for(k = 0; k < Types[i].class_inf[j].num_pins; ++k) { fprintf(Echo, "%d ", Types[i].class_inf[j].pinlist[k]); /* No \n */ } fprintf(Echo, "\n"); /* End current line */ } } fprintf(Echo, "\tis_Fc_frac: %s\n", (Types[i].is_Fc_frac ? "TRUE" : "FALSE")); fprintf(Echo, "\tis_Fc_out_full_flex: %s\n", (Types[i].is_Fc_out_full_flex ? "TRUE" : "FALSE")); fprintf(Echo, "\tFc_in: %f\n", Types[i].Fc_in); fprintf(Echo, "\tFc_out: %f\n", Types[i].Fc_out); fprintf(Echo, "\tmax_subblocks: %d\n", Types[i].max_subblocks); fprintf(Echo, "\tmax_subblock_inputs: %d\n", Types[i].max_subblock_inputs); fprintf(Echo, "\tmax_subblock_outputs: %d\n", Types[i].max_subblock_outputs); fprintf(Echo, "\tnum_drivers: %d\n", Types[i].num_drivers); fprintf(Echo, "\tnum_receivers: %d\n", Types[i].num_receivers); fprintf(Echo, "\tindex: %d\n", Types[i].index); fprintf(Echo, "\n"); } fclose(Echo);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -