From f343863ce33c232b60a3af5a79fa58be71918fea Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 24 Nov 2020 15:30:49 -0500 Subject: [PATCH] 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. --- VERSION | 2 +- commands/CmdE.c | 2 +- ext2spice/ext2hier.c | 2 ++ ext2spice/ext2spice.c | 53 +++++++++++++++++++++++++++++++++---------- extract/ExtArray.c | 7 +++++- extract/ExtMain.c | 4 ++-- 6 files changed, 53 insertions(+), 17 deletions(-) diff --git a/VERSION b/VERSION index 1e845493..c11b93ef 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.87 +8.3.88 diff --git a/commands/CmdE.c b/commands/CmdE.c index 683deb3b..cd6265c1 100644 --- a/commands/CmdE.c +++ b/commands/CmdE.c @@ -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 }; diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 3f366cec..332c8fac 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -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; diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 5abbfe43..a1ee2585 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -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 */ diff --git a/extract/ExtArray.c b/extract/ExtArray.c index 7122e1eb..605a6451 100644 --- a/extract/ExtArray.c +++ b/extract/ExtArray.c @@ -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) diff --git a/extract/ExtMain.c b/extract/ExtMain.c index 664435a8..8b8e75f6 100644 --- a/extract/ExtMain.c +++ b/extract/ExtMain.c @@ -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",