diff --git a/base/netcmp.c b/base/netcmp.c index 3d69fe6..c41e5af 100644 --- a/base/netcmp.c +++ b/base/netcmp.c @@ -3865,7 +3865,8 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run) propsort *proplist; struct property *kl; struct valuelist *vl; - int i, p, sval; + int i, p, sval, has_crit = FALSE; + char *subs_crit = NULL; double cval; obn = ob1->next; @@ -3875,6 +3876,14 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run) // value and index. Then sort that list, then use the sorted // indexes to sort the actual property linked list. + // If there is no critical property listed, then it is still better + // to sort on any random property than on no properties. Note that + // this can (and should!) be made better by sorting on *all* + // properties, not just the first. Otherwise, circuit 1 can have, e.g., + // parallel transistors with W=1, L=1 and W=1, L=2 while circuit two + // has W=1, L=2 and W=1, L=1 and property matching will fail because + // sorting was done on W only. + proplist = (propsort *)MALLOC(run * sizeof(propsort)); obp = obn; @@ -3889,17 +3898,62 @@ void parallel_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run) sval = vl->value.ival; kl = (struct property *)HashLookup(vl->key, &(tp1->propdict)); if (kl == NULL) continue; /* Ignored property */ - if (kl->merge == MERGE_ADD_CRIT) + if (kl->merge == MERGE_ADD_CRIT) { + has_crit = TRUE; + if ((vl->type == PROP_STRING || vl->type == PROP_EXPRESSION) && + (kl->type != vl->type)) + PromoteProperty(kl, vl); if (vl->type == PROP_INTEGER) cval = (double)vl->value.ival; + else if (vl->type == PROP_STRING) + /* This is unlikely---no method to merge string properties! */ + cval = (double)vl->value.string[0] + + (double)vl->value.string[1] / 10.0; else cval = vl->value.dval; + } } proplist[i].value = (double)sval * cval; proplist[i].idx = i; proplist[i].ob = obp; obp = obp->next; } + + if (has_crit == FALSE) { + /* If no critical property was specified, then choose the first one found */ + /* and recalculate all the proplist values. */ + sval = 1; + obp = obn; + for (i = 0; i < run; i++) { + for (p = 0;; p++) { + vl = &(obp->instance.props[p]); + if (vl->type == PROP_ENDLIST) break; + if (vl->key == NULL) continue; + if (!strcmp(vl->key, "S")) + sval = vl->value.ival; + kl = (struct property *)HashLookup(vl->key, &(tp1->propdict)); + if (kl == NULL) continue; /* Ignored property */ + if (subs_crit == NULL) + subs_crit = vl->key; + if ((subs_crit != NULL) && !strcmp(vl->key, subs_crit)) { + if ((vl->type == PROP_STRING || vl->type == PROP_EXPRESSION) && + (kl->type != vl->type)) + PromoteProperty(kl, vl); + if (vl->type == PROP_INTEGER) + cval = (double)vl->value.ival; + else if (vl->type == PROP_STRING) + /* In case property is non-numeric, sort by dictionary order */ + cval = (double)vl->value.string[0] + + (double)vl->value.string[1] / 10.0; + else + cval = vl->value.dval; + } + } + proplist[i].value = (double)sval * cval; + obp = obp->next; + } + } + obn = obp; /* Link from last property */ qsort(&proplist[0], run, sizeof(propsort), compsort); diff --git a/base/verilog.c b/base/verilog.c index e305956..de21e14 100644 --- a/base/verilog.c +++ b/base/verilog.c @@ -59,7 +59,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ // See netfile.c for explanation of delimiters. 'X' // separates single-character delimiters from two-character delimiters. -#define VLOG_DELIMITERS ",;:(){}[]=\"X///**/#(" +#define VLOG_DELIMITERS ",;:(){}[]=X///**/#(" #define VLOG_PIN_NAME_DELIMITERS "()X///**/" // Global storage for verilog parameters @@ -127,11 +127,28 @@ int GetBusTok(struct bus *wb) Printf("Unknown definition %s found in array notation.\n", nexttok); } else { - /* Note: all verilog definitions have been saved as PROP_STRING */ - result = sscanf(kl->pdefault.string, "%d", &start); - if (result != 1) { - Printf("Cannot parse first digit from parameter %s value %s\n", + if (kl->type == PROP_STRING) { + result = sscanf(kl->pdefault.string, "%d", &start); + if (result != 1) { + Printf("Cannot parse first digit from parameter %s value %s\n", nexttok, kl->pdefault.string); + return 1; + } + } + else if (kl->type == PROP_INTEGER) { + start = kl->pdefault.ival; + } + else if (kl->type == PROP_DOUBLE) { + start = (int)kl->pdefault.dval; + if ((double)start != kl->pdefault.dval) { + Printf("Cannot parse first digit from parameter %s value %g\n", + nexttok, kl->pdefault.dval); + return 1; + } + } + else { + Printf("Parameter %s has unknown type; don't know how to parse.\n", + nexttok); return 1; } } @@ -147,11 +164,29 @@ int GetBusTok(struct bus *wb) return 1; } else { - result = sscanf(kl->pdefault.string, "%d", &start); - if (result != 1) { - Printf("Parameter %s has value %s that cannot be parsed" + if (kl->type == PROP_STRING) { + result = sscanf(kl->pdefault.string, "%d", &start); + if (result != 1) { + Printf("Parameter %s has value %s that cannot be parsed" " as an integer.\n", nexttok, kl->pdefault.string); - return 1; + return 1; + } + } + else if (kl->type == PROP_INTEGER) { + start = kl->pdefault.ival; + } + else if (kl->type == PROP_DOUBLE) { + start = (int)kl->pdefault.dval; + if ((double)start != kl->pdefault.dval) { + Printf("Parameter %s has value %g that cannot be parsed" + " as an integer.\n", nexttok, kl->pdefault.dval); + return 1; + } + } + else { + Printf("Parameter %s has unknown type; don't know how" + " to parse.\n", nexttok); + return 1; } } } @@ -175,12 +210,29 @@ int GetBusTok(struct bus *wb) Printf("Unknown definition %s found in array notation.\n", nexttok); } else { - /* Note: all verilog definitions have been saved as PROP_STRING */ - result = sscanf(kl->pdefault.string, "%d", &end); - if (result != 1) { - Printf("Cannot parse second digit from parameter %s value %s\n", - nexttok, kl->pdefault.string); - return 1; + if (kl->type == PROP_STRING) { + result = sscanf(kl->pdefault.string, "%d", &end); + if (result != 1) { + Printf("Cannot parse second digit from parameter " + "%s value %s\n", nexttok, kl->pdefault.string); + return 1; + } + } + else if (kl->type == PROP_INTEGER) { + end = kl->pdefault.ival; + } + else if (kl->type == PROP_DOUBLE) { + end = (int)kl->pdefault.dval; + if ((double)end != kl->pdefault.dval) { + Printf("Cannot parse second digit from parameter " + "%s value %g\n", nexttok, kl->pdefault.dval); + return 1; + } + } + else { + Printf("Parameter %s has unknown type; don't know how" + " to parse.\n", nexttok); + return 1; } } } @@ -195,12 +247,30 @@ int GetBusTok(struct bus *wb) return 1; } else { - result = sscanf(kl->pdefault.string, "%d", &end); - if (result != 1) { - Printf("Parameter %s has value %s that cannot be parsed" + if (kl->type == PROP_STRING) { + result = sscanf(kl->pdefault.string, "%d", &end); + if (result != 1) { + Printf("Parameter %s has value %s that cannot be parsed" " as an integer.\n", nexttok, kl->pdefault.string); - return 1; + return 1; + } + } + else if (kl->type == PROP_INTEGER) { + end = kl->pdefault.ival; + } + else if (kl->type == PROP_DOUBLE) { + end = (int)kl->pdefault.dval; + if ((double)end != kl->pdefault.dval) { + Printf("Cannot parse second digit from parameter " + "%s value %g\n", nexttok, kl->pdefault.dval); + return 1; + } + } + else { + Printf("Parameter %s has unknown type; don't know how" + " to parse.\n", nexttok); + return 1; } } } @@ -510,8 +580,9 @@ extern void PopStack(struct cellstack **top); void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr, int blackbox) { - int cdnum = 1, rdnum = 1, i; + int cdnum = 1, rdnum = 1, i, ival; int warnings = 0, hasports, inlined_decls = 0, localcount = 1; + double dval; char devtype, in_module, in_param; char *eqptr, *matchptr; struct keyvalue *kvlist = NULL; @@ -660,7 +731,6 @@ void ReadVerilogFile(char *fname, int filenum, struct cellstack **CellStackPtr, } } else if (match(nexttok, "=")) { - double dval; // The parameter value is the next token. SkipTokComments(VLOG_DELIMITERS); /* get the next token */ @@ -855,15 +925,33 @@ skip_endmodule: kl = NewProperty(); kl->key = strsave(nexttok); kl->idx = 0; - kl->type = PROP_STRING; - kl->slop.dval = 0.0; + kl->merge = MERGE_NONE; SkipTokNoNewline(VLOG_DELIMITERS); - if ((nexttok == NULL) || (nexttok[0] == '\0')) - // Let "`define X" be equivalent to "`define X 1" - kl->pdefault.string = strsave("1"); - else + if ((nexttok == NULL) || (nexttok[0] == '\0')) { + // Let "`define X" be equivalent to "`define X 1". Use integer value. + kl->type = PROP_INTEGER; + kl->pdefault.ival = 1; + kl->slop.ival = 0; + } + else if (ConvertStringToInteger(nexttok, &ival) == 1) { + /* Parameter parses as an integer */ + kl->type = PROP_INTEGER; + kl->pdefault.ival = ival; + kl->slop.ival = 0; // Exact match default + } + else if (ConvertStringToFloat(nexttok, &dval) == 1) { + /* Parameter parses as a floating-point number */ + kl->type = PROP_DOUBLE; + kl->pdefault.dval = dval; + kl->slop.dval = 0.01; // One percent default + } + else { + /* Treat the parameter as a string */ + kl->type = PROP_STRING; kl->pdefault.string = strsave(nexttok); + kl->slop.dval = 0.0; + } HashPtrInstall(kl->key, kl, &verilogdefs); } else if (match(nexttok, "localparam")) { @@ -882,9 +970,23 @@ skip_endmodule: kl = NewProperty(); kl->key = strsave(nexttok); kl->idx = 0; - kl->type = PROP_STRING; - kl->slop.dval = 0.0; - kl->pdefault.string = strsave(eqptr + 1); + kl->merge = MERGE_NONE; + + if (ConvertStringToInteger(eqptr + 1, &ival) == 1) { + kl->type = PROP_INTEGER; + kl->slop.ival = 0; + kl->pdefault.ival = ival; + } + else if (ConvertStringToFloat(eqptr + 1, &dval) == 1) { + kl->type = PROP_DOUBLE; + kl->slop.dval = 0.01; + kl->pdefault.dval = dval; + } + else { + kl->type = PROP_STRING; + kl->slop.dval = 0.0; + kl->pdefault.string = strsave(eqptr + 1); + } HashPtrInstall(nexttok, kl, &verilogparams); } } @@ -1468,11 +1570,12 @@ char *ReadVerilogTop(char *fname, int *fnum, int blackbox) /* Add the pre-defined key "LVS" to verilogdefs */ kl = NewProperty(); + kl->merge = MERGE_NONE; kl->key = strsave("LVS"); kl->idx = 0; - kl->type = PROP_STRING; - kl->slop.dval = 0.0; - kl->pdefault.string = strsave("1"); + kl->type = PROP_INTEGER; + kl->slop.ival = 0; + kl->pdefault.ival = 1; HashPtrInstall(kl->key, kl, &verilogdefs); /* All verilog files should start with a comment line, */