From 0de1c232e4df8eb19b0fcb0f09b9fdc1aab4f4c6 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 26 Sep 2018 10:46:55 -0400 Subject: [PATCH] Corrected property matching so that properties are promoted to type double before sorting (previously, property promotion was being done after parallel sorting). Also, modified the verilog file reading so that parameters and definitions that are numeric are stored as numeric (not string) properties. --- base/netcmp.c | 58 ++++++++++++++++- base/verilog.c | 169 +++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 192 insertions(+), 35 deletions(-) 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, */