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",
"unique [option] generate unique names when different nodes\n\
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
};

View File

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

View File

@ -1635,6 +1635,11 @@ subcktUndef(use, hierName, is_top)
* subcircuit, and implicit substrate connections should not be
* 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;
EFNodeName *sname, *nodeName;
HashSearch hs;
HashEntry *he;
HashEntry *he, *hep;
HashTable portNameTable;
int portorder, portmax, tchars;
DevParam *plist, *pptr;
char *instname;
char *subcktname;
char *pname;
HashInit(&portNameTable, 32, HT_STRINGKEYS);
/* SPICE subcircuit names must begin with A-Z. This will also be */
/* enforced when writing X subcircuit calls. */
subcktname = def->def_name;
@ -1698,19 +1706,24 @@ topVisit(def, doStub)
if (snode->efnode_flags & EF_PORT)
{
pname = nodeSpiceName(snode->efnode_name->efnn_hier, &basenode);
if (basenode->efnode_name->efnn_port < 0)
if (HashLookOnly(&portNameTable, pname) == NULL)
{
if (tchars > 80)
hep = HashFind(&portNameTable, pname);
if (basenode->efnode_name->efnn_port < 0)
{
/* Line continuation */
fprintf(esSpiceF, "\n+");
tchars = 1;
if (tchars > 80)
{
/* Line continuation */
fprintf(esSpiceF, "\n+");
tchars = 1;
}
fprintf(esSpiceF, " %s", pname);
tchars += strlen(pname) + 1;
basenode->efnode_name->efnn_port = portorder++;
}
fprintf(esSpiceF, " %s", pname);
tchars += strlen(pname) + 1;
basenode->efnode_name->efnn_port = portorder++;
snode->efnode_name->efnn_port = basenode->efnode_name->efnn_port;
HashSetValue(hep, (ClientData)snode->efnode_name->efnn_port);
}
snode->efnode_name->efnn_port = basenode->efnode_name->efnn_port;
}
}
}
@ -1757,8 +1770,23 @@ topVisit(def, doStub)
}
else
pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL);
fprintf(esSpiceF, " %s", pname);
tchars += strlen(pname) + 1;
if (HashLookOnly(&portNameTable, pname) == NULL)
{
hep = HashFind(&portNameTable, pname);
HashSetValue(hep, (ClientData)nodeName->efnn_port);
fprintf(esSpiceF, " %s", pname);
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;
}
else if (portidx < 0)
@ -1779,6 +1807,7 @@ topVisit(def, doStub)
portorder++;
}
}
HashKill(&portNameTable);
/* Add all implicitly-defined local substrate node names */

View File

@ -606,7 +606,12 @@ extArrayInterFunc(use, trans, x, y, ha)
extHierConnections(ha, extArrayPrimary, oneFlat);
/* Process substrate connection */
extHierSubstrate(ha, use, x, y);
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);
ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL;
if (ExtOptions & EXT_DOADJUST)

View File

@ -51,7 +51,7 @@ extern FILE *extFileOpen();
/*
* See extract.h for the bit flags that may be set in the following.
* 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.
*/
int ExtDoWarn = EXTWARN_DUP|EXTWARN_FETS;
@ -663,7 +663,7 @@ extExtractStack(stack, doExtract, rootDef)
else
{
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" : "");
if (warnings > 0)
TxError("Total of %d warning%s.\n",