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.
This commit is contained in:
Tim Edwards 2018-09-26 10:46:55 -04:00
parent b8e6f6c030
commit 0de1c232e4
2 changed files with 192 additions and 35 deletions

View File

@ -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);

View File

@ -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, */