Compare commits

...
7 Commits
Author SHA1 Message Date
Tim Edwards 4098b7d5fd Completed an unimplemented method that sets missing properties to
the default before comparing instances against each other for
serial/parallel combination.  In particular, this avoids a
failure to serially combine a device with M = 1 vs. a device with
no M declared.
2017-10-12 15:26:29 -04:00
Tim Edwards f860244700 Provide additional output for mismatched serial/parallel networks.
Netgen was incorrectly treating mismatched networks as a missing
set of parameters on whichever device had more property records,
resulting in misleading output.
2017-10-12 14:17:24 -04:00
Tim Edwards 66015511cb Corrected mismatch count, which was prematurely declaring a
mismatch on "M=" even though some conditions pass.
2017-10-12 12:30:33 -04:00
Tim Edwards b3277ca53e Modified reading of SPICE files so that parameters in quotes get
treated monolithically instead of being broken up into separate
tokens according to space characters, which screws up the parameter
parsing.
2017-10-12 12:11:30 -04:00
Tim Edwards 00c2e74524 Merge branch 'master' into work 2017-10-12 10:52:58 -04:00
Tim Edwards bdb8917327 Update at Thu Oct 12 10:52:56 EDT 2017 by tim 2017-10-12 10:52:56 -04:00
Tim Edwards 95bce5dbd6 Corrected another error in the serial combination in which the
attempt to resolve values by combining over serial chains was
attempting to access a property "S" in the component's master
record, which generally won't exist unless it has been explicitly
set in the netlist (which is unlikely since "S" is not a standard
SPICE/CDL parameter like "M").
2017-10-12 10:51:13 -04:00
3 changed files with 202 additions and 22 deletions
+1 -1
View File
@@ -1 +1 @@
1.5.87
1.5.88
+139 -21
View File
@@ -3780,12 +3780,14 @@ void serial_sort(struct objlist *ob1, struct nlist *tp1, int idx1, int run)
if (vl->key == NULL) continue;
if (!strcmp(vl->key, "S"))
sval = vl->value.ival;
kl = (struct property *)HashLookup(vl->key, &(tp1->propdict));
if (kl->merge == MERGE_SER_CRIT)
if (vl->type == PROP_INTEGER)
cval = (double)vl->value.ival;
else
cval = vl->value.dval;
else {
kl = (struct property *)HashLookup(vl->key, &(tp1->propdict));
if (kl && (kl->merge == MERGE_SER_CRIT))
if (vl->type == PROP_INTEGER)
cval = (double)vl->value.ival;
else
cval = vl->value.dval;
}
}
proplist[i].value = (double)sval * cval;
proplist[i].idx = i;
@@ -4224,9 +4226,9 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int serial)
struct property *kl, *m_rec, **plist;
struct valuelist ***vlist, *vl, *vl2, *newvlist;
proplinkptr plink, ptop;
int pcount, p, i, j, pmatch, ival, crit, ctype;
int pcount, p, i, j, k, pmatch, ival, crit, ctype;
double dval;
static struct valuelist nullvl;
static struct valuelist nullvl, dfltvl;
char multiple[2];
int changed = 0;
@@ -4336,9 +4338,37 @@ int PropertyOptimize(struct objlist *ob, struct nlist *tp, int run, int serial)
pmatch++;
continue;
}
// TO-DO: If either value is missing, it takes kl->pdefault
// If either value is missing, it takes kl->pdefault
// and must apply promotions if necessary.
else if (vl == NULL || vl2 == NULL) continue;
else if (vl == NULL || vl2 == NULL) {
if (vl == NULL) {
if (kl->type != vlist[p][j]->type)
PromoteProperty(kl, vl2);
}
else {
if (kl->type != vlist[p][i]->type)
PromoteProperty(kl, vl);
}
vl = &dfltvl;
dfltvl.type = kl->type;
switch (kl->type) {
case PROP_STRING:
dfltvl.value.string = kl->pdefault.string;
break;
case PROP_INTEGER:
dfltvl.value.ival = kl->pdefault.ival;
break;
case PROP_DOUBLE:
case PROP_VALUE:
dfltvl.value.ival = kl->pdefault.ival;
break;
case PROP_EXPRESSION:
dfltvl.value.stack = kl->pdefault.stack;
break;
}
}
// Critical properties can be multiplied up by M (S) and do not
// need to match. May want a more nuanced comparison, though.
@@ -4953,6 +4983,52 @@ PropertyCheckMismatch(struct objlist *tp1, struct nlist *tc1,
}
/*--------------------------------------------------------------*/
/* Dump a description of a device's serial/parallel network */
/*--------------------------------------------------------------*/
void DumpNetwork(struct objlist *ob, int cidx)
{
struct valuelist *vl;
struct objlist *tp;
int i;
for (tp = ob; tp && (tp->type != PROPERTY); tp = tp->next)
if ((tp > ob) && (tp->type == FIRSTPIN))
return;
if (tp == NULL) return;
Fprintf(stdout, "Circuit %d instance %s network:\n", cidx, ob->instance.name);
for (; tp && (tp->type == PROPERTY); tp = tp->next) {
for (i = 0;; i++) {
vl = &(tp->instance.props[i]);
if (vl->type == PROP_ENDLIST) break;
if (!strcmp(vl->key, "_tag")) {
Fprintf(stdout, "%s\n", vl->value.string);
continue;
}
Fprintf(stdout, " %s = ", vl->key);
switch(vl->type) {
case PROP_STRING:
Fprintf(stdout, "%s\n", vl->value.string);
break;
case PROP_INTEGER:
Fprintf(stdout, "%d\n", vl->value.ival);
break;
case PROP_DOUBLE:
case PROP_VALUE:
Fprintf(stdout, "%g\n", vl->value.dval);
break;
case PROP_EXPRESSION:
Fprintf(stdout, "(expression)\n");
break;
}
}
}
}
/*--------------------------------------------------------------*/
/* Compare the properties of two objects. The passed values */
/* ob1 and ob2 are pointers to the first entry (firstpin) of */
@@ -4981,7 +5057,7 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
struct property *kl1, *kl2;
struct valuelist *vl1, *vl2;
int t1type, t2type;
int i, mismatches = 0;
int i, mismatches = 0, checked_one;
int rval = 1;
char *inst1, *inst2;
#ifdef TCL_NETGEN
@@ -5073,8 +5149,18 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
inst2 = ob2->instance.name;
if (*inst2 == '/') inst2++;
checked_one = FALSE;
while(1) {
if (t1type != PROPERTY) {
if ((t1type != PROPERTY) && (checked_one == TRUE)) {
// t2 has more property records than t1, and they did not get
// merged equally by PropertySortAndCombine().
Fprintf(stdout, "Circuit 1 parallel/serial network does not match"
" Circuit 2\n");
DumpNetwork(ob1, 1);
DumpNetwork(ob2, 2);
mismatches++;
}
else if (t1type != PROPERTY) {
// t1 has no properties. See if t2's properties are required
// to be checked. If so, flag t2 instance as unmatched
@@ -5084,13 +5170,24 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
if (vl2 == NULL) continue;
if (vl2->key == NULL) continue;
kl2 = (struct property *)HashLookup(vl2->key, &(tc2->propdict));
if (kl2 != NULL) break; // Property is required
if (kl2 != NULL) {
// Allowed for one instance to be missing "M" or "S".
if (strcasecmp(vl2->key, "M") && strcasecmp(vl2->key, "S"))
break; // Property is required
}
}
if (vl2->type != PROP_ENDLIST) {
mismatches++;
if (do_print) Fprintf(stdout, "Circuit 2 %s instance %s has no"
" property match in circuit 1.\n",
Circuit2->name, inst2);
if (do_print) {
if (vl2 && vl2->key)
Fprintf(stdout, "Circuit 2 %s instance %s property"
" \"%s\" has no match in circuit 1.\n",
Circuit2->name, inst2, vl2->key);
else
Fprintf(stdout, "Circuit 2 %s instance %s has no"
" property match in circuit 1.\n",
Circuit2->name, inst2);
}
#ifdef TCL_NETGEN
if (do_list) {
mpair = PropertyList(NULL, vl2);
@@ -5105,23 +5202,43 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
else
rval = 0;
}
else if ((t2type != PROPERTY) && (checked_one == TRUE)) {
// t1 has more property records than t2, and they did not get
// merged equally by PropertySortAndCombine().
Fprintf(stdout, "Circuit 2 parallel/serial network does not match"
" Circuit 1\n");
DumpNetwork(ob1, 1);
DumpNetwork(ob2, 2);
mismatches++;
}
else if (t2type != PROPERTY) {
// t2 has no properties. See if t1's properties are required
// to be checked. If so, flag t1 instance as unmatched
mismatches++;
for (i = 0;; i++) {
vl1 = &(tp1->instance.props[i]);
if (vl1->type == PROP_ENDLIST) break;
if (vl1 == NULL) continue;
if (vl1->key == NULL) continue;
kl1 = (struct property *)HashLookup(vl1->key, &(tc1->propdict));
if (kl1 != NULL) break; // Property is required
if (kl1 != NULL) {
// Allowed for one instance to be missing "M" or "S".
if (strcasecmp(vl1->key, "M") && strcasecmp(vl1->key, "S"))
break; // Property is required
}
}
if (vl1->type != PROP_ENDLIST) {
if (do_print) Fprintf(stdout, "Circuit 1 %s instance %s has no"
" property match in Circuit 2.\n",
Circuit1->name, inst1);
mismatches++;
if (do_print) {
if (vl1 && vl1->key)
Fprintf(stdout, "Circuit 1 %s instance %s property"
" \"%s\" has no match in circuit 2.\n",
Circuit1->name, inst1, vl1->key);
else
Fprintf(stdout, "Circuit 1 %s instance %s has no"
" property match in circuit 2.\n",
Circuit1->name, inst1);
}
#ifdef TCL_NETGEN
if (do_list) {
mpair = PropertyList(vl1, NULL);
@@ -5171,6 +5288,7 @@ PropertyMatch(struct objlist *ob1, struct objlist *ob2, int do_print,
t1type = (tp1) ? tp1->type : 0;
t2type = (tp2) ? tp2->type : 0;
if ((t1type != PROPERTY) && (t2type != PROPERTY)) break;
checked_one = TRUE;
}
*retval = (rval < 0) ? rval : mismatches;
+62
View File
@@ -193,6 +193,67 @@ static struct filestack *OpenFiles = NULL;
#define TOKEN_DELIMITER " \t\n\r"
/*----------------------------------------------------------------------*/
/* TrimQuoted() --- */
/* Remove spaces from inside single- or double-quoted strings. */
/*----------------------------------------------------------------------*/
void TrimQuoted(char *line)
{
char *qstart, *qend, *lptr;
int slen;
int changed;
/* Single-quoted entries */
changed = TRUE;
lptr = line;
while (changed)
{
changed = FALSE;
qstart = strchr(lptr, '\'');
if (qstart)
{
qend = strchr(qstart + 1, '\'');
if (qend && (qend > qstart)) {
slen = strlen(lptr);
for (lptr = qstart + 1; lptr < qend; lptr++) {
if (*lptr == ' ') {
memmove(lptr, lptr + 1, slen);
qend--;
changed = TRUE;
}
}
lptr++;
}
}
}
/* Double-quoted entries */
changed = TRUE;
lptr = line;
while (changed)
{
changed = FALSE;
qstart = strchr(lptr, '\"');
if (qstart)
{
qend = strchr(qstart + 1, '\"');
if (qend && (qend > qstart)) {
slen = strlen(lptr);
for (lptr = qstart + 1; lptr < qend; lptr++) {
if (*lptr == ' ') {
memmove(lptr, lptr + 1, slen);
qend--;
changed = TRUE;
}
}
lptr++;
}
}
}
}
/*----------------------------------------------------------------------*/
/* GetNextLineNoNewline() */
/* */
@@ -233,6 +294,7 @@ int GetNextLineNoNewline()
}
linenum++;
strcpy(linetok, line);
TrimQuoted(linetok);
nexttok = strtok(linetok, TOKEN_DELIMITER);
return 0;