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:
parent
0ad9ac91e3
commit
f343863ce3
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Reference in New Issue