From c342178458a937750108f71b3fc705c189f40dec Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 29 Oct 2019 09:44:28 -0400 Subject: [PATCH 1/2] Made some changes to the way that ext2spice generates subcircuit ports, to avoid creating ports for node names that are redundant. It would probably be better to avoid creating the redundant node names in the first place; however, I am less certain why these are generated. The incorrect additional ports all have hierarchical names in the cell, which is a sign that they are incorrect, as the cell itself should not have any parents. The level of certainty about this fix is definitely not 100%, but it was tested on a hierarchical analog design, and setting levels of parasitic caps caused new nodes to appear in subcircuits and in no cases did information appear to be lost. --- ext2spice/ext2hier.c | 7 ++++--- ext2spice/ext2spice.c | 39 ++++++++++++++++++++++++--------------- extflat/EFflat.c | 1 + 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 3f660975..9b90f6a3 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1625,6 +1625,10 @@ esMakePorts(hc, cdata) { nn->efnn_node->efnode_flags |= EF_PORT; nn->efnn_port = -1; // Will be sorted later + + // Diagnostic + TxPrintf("Port connection in %s from net %s to net %s (%s)\n", + def->def_name, locname, name, portname); } } @@ -1634,9 +1638,6 @@ esMakePorts(hc, cdata) updef = portdef; } - // Diagnostic - // TxPrintf("Connection in %s to net %s (%s)\n", def->def_name, - // name, portname); } } diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index e2e560f4..03ac5e78 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -1615,7 +1615,7 @@ topVisit(def, doStub) Def *def; bool doStub; { - EFNode *snode; + EFNode *snode, *basenode; EFNodeName *sname, *nodeName; HashSearch hs; HashEntry *he; @@ -1668,7 +1668,9 @@ topVisit(def, doStub) snode = sname->efnn_node; if (snode->efnode_flags & EF_PORT) - if (snode->efnode_name->efnn_port < 0) + { + pname = nodeSpiceName(snode->efnode_name->efnn_hier, &basenode); + if (basenode->efnode_name->efnn_port < 0) { if (tchars > 80) { @@ -1676,11 +1678,13 @@ topVisit(def, doStub) fprintf(esSpiceF, "\n+"); tchars = 1; } - pname = nodeSpiceName(snode->efnode_name->efnn_hier); fprintf(esSpiceF, " %s", pname); tchars += strlen(pname) + 1; - snode->efnode_name->efnn_port = portorder++; + basenode->efnode_name->efnn_port = portorder++; } + if (snode->efnode_name->efnn_hier->hn_parent == NULL) + snode->efnode_name->efnn_port = basenode->efnode_name->efnn_port; + } } } else @@ -1714,7 +1718,7 @@ topVisit(def, doStub) fprintf(esSpiceF, "\n+"); tchars = 1; } - pname = nodeSpiceName(snode->efnode_name->efnn_hier); + pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL); fprintf(esSpiceF, " %s", pname); tchars += strlen(pname) + 1; break; @@ -2771,7 +2775,8 @@ FILE *outf; /* Canonical name */ nn = (EFNodeName *) HashGetValue(he); if (outf) - fprintf(outf, "%s", nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier)); + fprintf(outf, "%s", nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier, + NULL)); /* Mark node as visited */ if ((nodeClient *)nn->efnn_node->efnode_client == (ClientData)NULL) @@ -2982,7 +2987,7 @@ spcdevOutNode(prefix, suffix, name, outf) return 0; } nn = (EFNodeName *) HashGetValue(he); - nname = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier); + nname = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier, NULL); fprintf(outf, " %s", nname); /* Mark node as visited */ @@ -3028,8 +3033,8 @@ spccapVisit(hierName1, hierName2, cap) if (cap <= EFCapThreshold) return 0; - fprintf(esSpiceF, esSpiceCapFormat ,esCapNum++,nodeSpiceName(hierName1), - nodeSpiceName(hierName2), cap); + fprintf(esSpiceF, esSpiceCapFormat ,esCapNum++,nodeSpiceName(hierName1, NULL), + nodeSpiceName(hierName2, NULL), cap); return 0; } @@ -3064,8 +3069,8 @@ spcresistVisit(hierName1, hierName2, res) HierName *hierName2; float res; { - fprintf(esSpiceF, "R%d %s %s %g\n", esResNum++, nodeSpiceName(hierName1), - nodeSpiceName(hierName2), res / 1000.); + fprintf(esSpiceF, "R%d %s %s %g\n", esResNum++, nodeSpiceName(hierName1, NULL), + nodeSpiceName(hierName2, NULL), res / 1000.); return 0; } @@ -3100,7 +3105,7 @@ spcsubVisit(node, res, cap, resstr) if (node->efnode_flags & EF_SUBS_NODE) { hierName = (HierName *) node->efnode_name->efnn_hier; - nsn = nodeSpiceName(hierName); + nsn = nodeSpiceName(hierName, NULL); *resstr = StrDup((char **)NULL, nsn); return 1; } @@ -3150,7 +3155,7 @@ spcnodeVisit(node, res, cap) if (!isConnected && node->efnode_flags & EF_PORT) isConnected = TRUE; hierName = (HierName *) node->efnode_name->efnn_hier; - nsn = nodeSpiceName(hierName); + nsn = nodeSpiceName(hierName, NULL); if (esFormat == SPICE2 || esFormat == HSPICE && strncmp(nsn, "z@", 2)==0 ) { static char ntmp[MAX_STR_SIZE]; @@ -3195,7 +3200,7 @@ nodeVisitDebug(node, res, cap) EFAttr *ap; hierName = (HierName *) node->efnode_name->efnn_hier; - nsn = nodeSpiceName(hierName); + nsn = nodeSpiceName(hierName, NULL); TxError("** %s (%x)\n", nsn, node); printf("\t client.name=%s, client.m_w=%p\n", @@ -3218,23 +3223,27 @@ nodeVisitDebug(node, res, cap) * * Side effects: * Allocates nodeClients for the node. + * Returns the node in the "rnode" pointer, if non-NULL. * * ---------------------------------------------------------------------------- */ static char esTempName[MAX_STR_SIZE]; -char *nodeSpiceName(hname) +char *nodeSpiceName(hname, rnode) HierName *hname; + EFNode **rnode; { EFNodeName *nn; HashEntry *he; EFNode *node; + if (rnode) *rnode = (EFNode *)NULL; he = EFHNLook(hname, (char *) NULL, "nodeName"); if ( he == NULL ) return "errGnd!"; nn = (EFNodeName *) HashGetValue(he); node = nn->efnn_node; + if (rnode) *rnode = node; if ( (nodeClient *) (node->efnode_client) == NULL ) { initNodeClient(node); diff --git a/extflat/EFflat.c b/extflat/EFflat.c index 49087720..bd02d9c9 100644 --- a/extflat/EFflat.c +++ b/extflat/EFflat.c @@ -527,6 +527,7 @@ efAddNodes(hc, stdcell) HashSetValue(he, (char *) newname); newname->efnn_node = newnode; newname->efnn_hier = hierName; + newname->efnn_port = -1; if (newnode->efnode_name) { newname->efnn_next = newnode->efnode_name->efnn_next; From fc86f44bb16da80f37bbca7f286843d66e77d210 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 29 Oct 2019 13:55:28 -0400 Subject: [PATCH 2/2] Again revisited the problem of duplicate nodes. This time, I think I understand the problem, which is that nodes are ordered according to precedence of EFHNBest() within a circuit, but there is no concept of ordering between circuits. So ports end up listing nodes in arbitrary order, and the only way to resolve the order is to use EFHNBest() as is done within a subcircuit. Appears to work for different edge cases tested. --- ext2spice/ext2hier.c | 4 +-- ext2spice/ext2spice.c | 66 +++++++++++++++++++++++++++---------------- 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 9b90f6a3..6f6fc555 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1627,8 +1627,8 @@ esMakePorts(hc, cdata) nn->efnn_port = -1; // Will be sorted later // Diagnostic - TxPrintf("Port connection in %s from net %s to net %s (%s)\n", - def->def_name, locname, name, portname); + // TxPrintf("Port connection in %s from net %s to net %s (%s)\n", + // def->def_name, locname, name, portname); } } diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 03ac5e78..168959cf 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -1372,10 +1372,11 @@ subcktVisit(use, hierName, is_top) EFNode *snode; Def *def = use->use_def; EFNodeName *nodeName; - int portorder, portmax, imp_max, tchars; + int portorder, portmax, portidx, imp_max, tchars; char stmp[MAX_STR_SIZE]; char *instname, *subcktname; DevParam *plist, *pptr; + EFNodeName **nodeList; if (is_top == TRUE) return 0; /* Ignore the top-level cell */ @@ -1467,35 +1468,53 @@ subcktVisit(use, hierName, is_top) /* Port numbers need not start at zero or be contiguous. */ /* They will be printed in numerical order. */ - portorder = 0; - while (portorder <= portmax) - { - for (snode = (EFNode *) def->def_firstn.efnode_next; + nodeList = (EFNodeName **)mallocMagic((portmax + 1) * sizeof(EFNodeName *)); + for (portidx = 0; portidx <= portmax; portidx++) + nodeList[portidx] = (EFNodeName *)NULL; + + for (snode = (EFNode *) def->def_firstn.efnode_next; snode != &def->def_firstn; snode = (EFNode *) snode->efnode_next) - { - if (!(snode->efnode_flags & EF_PORT)) continue; - for (nodeName = snode->efnode_name; nodeName != NULL; + { + if (!(snode->efnode_flags & EF_PORT)) continue; + for (nodeName = snode->efnode_name; nodeName != NULL; nodeName = nodeName->efnn_next) + { + EFNodeName *nn; + HashEntry *he; + char *pname; + + portidx = nodeName->efnn_port; + if (nodeList[portidx] == NULL) { - int portidx = nodeName->efnn_port; - if (portidx == portorder) - { - if (tchars > 80) - { - fprintf(esSpiceF, "\n+"); - tchars = 1; - } - tchars += spcdevOutNode(hierName, nodeName->efnn_hier, - "subcircuit", esSpiceF); - break; - } + nodeList[portidx] = nodeName; + } + else if (EFHNBest(nodeName->efnn_hier, nodeList[portidx]->efnn_hier)) + { + nodeList[portidx] = nodeName; } - if (nodeName != NULL) break; } - portorder++; } + for (portidx = 0; portidx <= portmax; portidx++) + { + nodeName = nodeList[portidx]; + + if (nodeName == NULL) + TxError("No port connection on port %d; need to resolve.\n", portidx); + else + { + if (tchars > 80) + { + fprintf(esSpiceF, "\n+"); + tchars = 1; + } + tchars += spcdevOutNode(hierName, nodeName->efnn_hier, + "subcircuit", esSpiceF); + } + } + freeMagic(nodeList); + /* Look for all implicit substrate connections that are */ /* declared as local node names, and put them last. */ @@ -1682,8 +1701,7 @@ topVisit(def, doStub) tchars += strlen(pname) + 1; basenode->efnode_name->efnn_port = portorder++; } - if (snode->efnode_name->efnn_hier->hn_parent == NULL) - snode->efnode_name->efnn_port = basenode->efnode_name->efnn_port; + snode->efnode_name->efnn_port = basenode->efnode_name->efnn_port; } } }