Corrected two annoying errors: (1) SPICE netlist output subcircuits

could have multiple ports of the same name.  This problem had been
worked over before, but there was an indpendent mechanism producing
the same result for a completely different reason, caused by subcells
being much larger than the cookie-cutter extraction method's extraction
regions.  Solved by tracking port names in a hash table and preventing
re-use.  (2) ext2spice was producing "no such node" errors;  like (1)
this had been previously worked on, and like (1) this mechanism was
independent.  Problem came from not passing -1 to extHierSubstrate for
the non-arrayed dimension of a 1-dimensional array.  Also:  Removed
the word "fatal" from extraction error reporting, as nearly all
extraction errors are entirely benign.  This should clear up confusion
among alarmed end-users.
This commit is contained in:
Tim Edwards 2020-11-24 15:30:49 -05:00
parent 0ad9ac91e3
commit f343863ce3
6 changed files with 53 additions and 17 deletions

View File

@ -1 +1 @@
8.3.87 8.3.88

View File

@ -951,7 +951,7 @@ CmdExtract(w, cmd)
"style [stylename] set current extraction parameter style", "style [stylename] set current extraction parameter style",
"unique [option] generate unique names when different nodes\n\ "unique [option] generate unique names when different nodes\n\
have the same name", have the same name",
"warn [ [no] option] enable/disable reporting of non-fatal errors", "warn [ [no] option] enable/disable reporting of non-serious errors",
NULL NULL
}; };

View File

@ -1557,6 +1557,7 @@ devDistJunctHierVisit(hc, dev, scale)
* for each connection to it. Note that this generates an arbitrary * for each connection to it. Note that this generates an arbitrary
* port order for each cell. To have a specific port order, it is * port order for each cell. To have a specific port order, it is
* necessary to generate ports for each cell. * necessary to generate ports for each cell.
*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
@ -1570,6 +1571,7 @@ esMakePorts(hc, cdata)
Use *use; Use *use;
HashEntry *he; HashEntry *he;
EFNodeName *nn; EFNodeName *nn;
char *name, *portname, *tptr, *aptr, *locname; char *name, *portname, *tptr, *aptr, *locname;
int j; int j;

View File

@ -1635,6 +1635,11 @@ subcktUndef(use, hierName, is_top)
* subcircuit, and implicit substrate connections should not be * subcircuit, and implicit substrate connections should not be
* output. * output.
* *
* NOTE: The cookie-cutter method for extraction can result in multiple
* connections to the same port if the net spans multiple extraction regions.
* Because of this, it is necessary to make sure that the same port name is
* not output twice.
*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
@ -1646,13 +1651,16 @@ topVisit(def, doStub)
EFNode *snode, *basenode; EFNode *snode, *basenode;
EFNodeName *sname, *nodeName; EFNodeName *sname, *nodeName;
HashSearch hs; HashSearch hs;
HashEntry *he; HashEntry *he, *hep;
HashTable portNameTable;
int portorder, portmax, tchars; int portorder, portmax, tchars;
DevParam *plist, *pptr; DevParam *plist, *pptr;
char *instname; char *instname;
char *subcktname; char *subcktname;
char *pname; char *pname;
HashInit(&portNameTable, 32, HT_STRINGKEYS);
/* SPICE subcircuit names must begin with A-Z. This will also be */ /* SPICE subcircuit names must begin with A-Z. This will also be */
/* enforced when writing X subcircuit calls. */ /* enforced when writing X subcircuit calls. */
subcktname = def->def_name; subcktname = def->def_name;
@ -1698,6 +1706,9 @@ topVisit(def, doStub)
if (snode->efnode_flags & EF_PORT) if (snode->efnode_flags & EF_PORT)
{ {
pname = nodeSpiceName(snode->efnode_name->efnn_hier, &basenode); pname = nodeSpiceName(snode->efnode_name->efnn_hier, &basenode);
if (HashLookOnly(&portNameTable, pname) == NULL)
{
hep = HashFind(&portNameTable, pname);
if (basenode->efnode_name->efnn_port < 0) if (basenode->efnode_name->efnn_port < 0)
{ {
if (tchars > 80) if (tchars > 80)
@ -1711,6 +1722,8 @@ topVisit(def, doStub)
basenode->efnode_name->efnn_port = portorder++; basenode->efnode_name->efnn_port = portorder++;
} }
snode->efnode_name->efnn_port = basenode->efnode_name->efnn_port; snode->efnode_name->efnn_port = basenode->efnode_name->efnn_port;
HashSetValue(hep, (ClientData)snode->efnode_name->efnn_port);
}
} }
} }
} }
@ -1757,8 +1770,23 @@ topVisit(def, doStub)
} }
else else
pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL); pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL);
if (HashLookOnly(&portNameTable, pname) == NULL)
{
hep = HashFind(&portNameTable, pname);
HashSetValue(hep, (ClientData)nodeName->efnn_port);
fprintf(esSpiceF, " %s", pname); fprintf(esSpiceF, " %s", pname);
tchars += strlen(pname) + 1; tchars += strlen(pname) + 1;
}
else
{
// Node that was unassigned has been found to be
// a repeat (see NOTE at top), so make sure its
// port number is set correctly.
hep = HashFind(&portNameTable, pname);
nodeName->efnn_port = (int)HashGetValue(hep);
}
break; break;
} }
else if (portidx < 0) else if (portidx < 0)
@ -1779,6 +1807,7 @@ topVisit(def, doStub)
portorder++; portorder++;
} }
} }
HashKill(&portNameTable);
/* Add all implicitly-defined local substrate node names */ /* Add all implicitly-defined local substrate node names */

View File

@ -606,6 +606,11 @@ extArrayInterFunc(use, trans, x, y, ha)
extHierConnections(ha, extArrayPrimary, oneFlat); extHierConnections(ha, extArrayPrimary, oneFlat);
/* Process substrate connection */ /* Process substrate connection */
if (use->cu_xlo == use->cu_xhi)
extHierSubstrate(ha, use, -1, y);
else if (use->cu_ylo == use->cu_yhi)
extHierSubstrate(ha, use, x, -1);
else
extHierSubstrate(ha, use, x, y); extHierSubstrate(ha, use, x, y);
ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL; ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL;

View File

@ -51,7 +51,7 @@ extern FILE *extFileOpen();
/* /*
* See extract.h for the bit flags that may be set in the following. * See extract.h for the bit flags that may be set in the following.
* If any are set, the corresponding warnings get generated, leaving * If any are set, the corresponding warnings get generated, leaving
* feedback messages. If this word is zero, only fatal errors are * feedback messages. If this word is zero, only errors are
* reported. * reported.
*/ */
int ExtDoWarn = EXTWARN_DUP|EXTWARN_FETS; int ExtDoWarn = EXTWARN_DUP|EXTWARN_FETS;
@ -663,7 +663,7 @@ extExtractStack(stack, doExtract, rootDef)
else else
{ {
if (fatal > 0) if (fatal > 0)
TxError("Total of %d fatal error%s.\n", TxError("Total of %d error%s (check feedback entries).\n",
fatal, fatal != 1 ? "s" : ""); fatal, fatal != 1 ? "s" : "");
if (warnings > 0) if (warnings > 0)
TxError("Total of %d warning%s.\n", TxError("Total of %d warning%s.\n",