Reworked the code from the previous commit in a completely different
way. The code as previously written was undermining other code written to avoid long run-times on ext2spice, and didn't solve at least one issue with unnecessary resistor shorts being added to the netlist output. The current solution fixes one underlying problem where a wrongly-placed parenthesis caused the "preferred net name" routine EFHNBest() not to be run, which prevented original node names from being preferred over their suffixed versions created by "extract unique". However, I also added code to EFbuild.c to merge unique nodes when the nodes are not really unique. The problem is caused by "extract unique" operating only on one level of hierarchy and being unable to see where nets may connect through subcircuits. That can be determined from the "merge" statements in the .ext file, and now the EFbuild routines will merge these "false unique" names back into the original net.
This commit is contained in:
parent
bd417aa54b
commit
949ec7672c
|
|
@ -603,33 +603,57 @@ efBuildEquiv(def, nodeName1, nodeName2, resist, isspice)
|
|||
}
|
||||
if (!equalByCase)
|
||||
{
|
||||
if ((EFOutputFlags & EF_SHORT_MASK) != EF_SHORT_NONE)
|
||||
/* If one of the nodes has been generated from the
|
||||
* other by "extract unique", then this is a case where
|
||||
* the "extract unique" algorithm is blind to shorts
|
||||
* through subcell hierarchy and has made a name unique
|
||||
* unnecessarily. In that case, merge the node instead
|
||||
* of generating a short.
|
||||
*/
|
||||
char *uniqstr1, *uniqstr2;
|
||||
bool isuniq;
|
||||
|
||||
uniqstr1 = strstr(nodeName1, "_uq");
|
||||
uniqstr2 = strstr(nodeName2, "_uq");
|
||||
if (uniqstr1) *uniqstr1 = '\0';
|
||||
if (uniqstr2) *uniqstr2 = '\0';
|
||||
isuniq = !strcmp(nodeName1, nodeName2);
|
||||
if (uniqstr1) *uniqstr1 = '_';
|
||||
if (uniqstr2) *uniqstr2 = '_';
|
||||
|
||||
if (!isuniq)
|
||||
{
|
||||
int i;
|
||||
int sdev;
|
||||
char *argv[10], zeroarg[] = "0";
|
||||
if ((EFOutputFlags & EF_SHORT_MASK) != EF_SHORT_NONE)
|
||||
{
|
||||
int i;
|
||||
int sdev;
|
||||
char *argv[10], zeroarg[] = "0";
|
||||
|
||||
if ((EFOutputFlags & EF_SHORT_MASK) == EF_SHORT_R)
|
||||
sdev = DEV_RES;
|
||||
if ((EFOutputFlags & EF_SHORT_MASK) == EF_SHORT_R)
|
||||
sdev = DEV_RES;
|
||||
else
|
||||
sdev = DEV_VOLT;
|
||||
|
||||
for (i = 0; i < 10; i++) argv[i] = zeroarg;
|
||||
argv[0] = StrDup((char **)NULL, "0.0");
|
||||
argv[1] = StrDup((char **)NULL, "dummy");
|
||||
argv[4] = StrDup((char **)NULL, nodeName1);
|
||||
argv[7] = StrDup((char **)NULL, nodeName2);
|
||||
efBuildDevice(def, sdev, "None", &GeoNullRect, 10, argv);
|
||||
freeMagic(argv[0]);
|
||||
freeMagic(argv[1]);
|
||||
freeMagic(argv[4]);
|
||||
freeMagic(argv[7]);
|
||||
return;
|
||||
}
|
||||
else if (!resist)
|
||||
TxError("Warning: Ports \"%s\" and \"%s\" are electrically "
|
||||
"shorted.\n", nodeName1, nodeName2);
|
||||
else
|
||||
sdev = DEV_VOLT;
|
||||
|
||||
for (i = 0; i < 10; i++) argv[i] = zeroarg;
|
||||
argv[0] = StrDup((char **)NULL, "0.0");
|
||||
argv[1] = StrDup((char **)NULL, "dummy");
|
||||
argv[4] = StrDup((char **)NULL, nodeName1);
|
||||
argv[7] = StrDup((char **)NULL, nodeName2);
|
||||
efBuildDevice(def, sdev, "None", &GeoNullRect, 10, argv);
|
||||
freeMagic(argv[0]);
|
||||
freeMagic(argv[1]);
|
||||
freeMagic(argv[4]);
|
||||
freeMagic(argv[7]);
|
||||
return;
|
||||
/* Do not merge the nodes when folding in extresist parasitics */
|
||||
return;
|
||||
}
|
||||
else if (!resist)
|
||||
TxError("Warning: Ports \"%s\" and \"%s\" are electrically shorted.\n",
|
||||
nodeName1, nodeName2);
|
||||
else
|
||||
else if (resist)
|
||||
/* Do not merge the nodes when folding in extresist parasitics */
|
||||
return;
|
||||
}
|
||||
|
|
@ -653,20 +677,6 @@ efBuildEquiv(def, nodeName1, nodeName2, resist, isspice)
|
|||
efReadError("Merged nodes %s and %s\n", nodeName1, nodeName2);
|
||||
lostnode = efNodeMerge(&nn1->efnn_node, &nn2->efnn_node);
|
||||
|
||||
/* Keep the lowest valid port number. This avoids preferring
|
||||
* names generated by "extract unique" over the original port
|
||||
* name.
|
||||
*/
|
||||
if (nn1->efnn_port > 0)
|
||||
{
|
||||
if ((nn2->efnn_port > 0) && (nn2->efnn_port < nn1->efnn_port))
|
||||
nn1->efnn_port = nn2->efnn_port;
|
||||
else
|
||||
nn2->efnn_port = nn1->efnn_port;
|
||||
}
|
||||
else if (nn2->efnn_port > 0)
|
||||
nn1->efnn_port = nn2->efnn_port;
|
||||
|
||||
/* Check if there are any device terminals pointing to the
|
||||
* node that was just removed.
|
||||
*/
|
||||
|
|
@ -1558,7 +1568,25 @@ efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac)
|
|||
unsigned size = sizeof (Connection)
|
||||
+ (efNumResistClasses - 1) * sizeof (EFPerimArea);
|
||||
|
||||
if ((EFOutputFlags & EF_SHORT_MASK) != EF_SHORT_NONE)
|
||||
/* If one of the nodes has been generated from the
|
||||
* other by "extract unique", then this is a case where
|
||||
* the "extract unique" algorithm is blind to shorts
|
||||
* through subcell hierarchy and has made a name unique
|
||||
* unnecessarily. In that case, merge the node instead
|
||||
* of generating a short.
|
||||
*/
|
||||
char *uniqstr1, *uniqstr2;
|
||||
bool isuniq;
|
||||
|
||||
uniqstr1 = strstr(nodeName1, "_uq");
|
||||
uniqstr2 = strstr(nodeName2, "_uq");
|
||||
if (uniqstr1) *uniqstr1 = '\0';
|
||||
if (uniqstr2) *uniqstr2 = '\0';
|
||||
isuniq = !strcmp(nodeName1, nodeName2);
|
||||
if (uniqstr1) *uniqstr1 = '_';
|
||||
if (uniqstr2) *uniqstr2 = '_';
|
||||
|
||||
if (!isuniq && ((EFOutputFlags & EF_SHORT_MASK) != EF_SHORT_NONE))
|
||||
{
|
||||
/* Handle the case where two ports on different nets get merged.
|
||||
* If "extract short resistor" or "extract short voltage" has
|
||||
|
|
@ -1952,10 +1980,9 @@ EFNode *
|
|||
efNodeMerge(node1ptr, node2ptr)
|
||||
EFNode **node1ptr, **node2ptr; /* Pointers to hierarchical nodes */
|
||||
{
|
||||
EFNodeName *nn, *nnlast, *nn1, *nn2;
|
||||
EFNodeName *nn, *nnlast;
|
||||
EFAttr *ap;
|
||||
int n;
|
||||
int keep; /* Which node to keep (1 or 2; 0 = unknown) */
|
||||
EFNode *keeping, *removing;
|
||||
|
||||
/* Sanity check: ignore if same node */
|
||||
|
|
@ -1965,31 +1992,9 @@ efNodeMerge(node1ptr, node2ptr)
|
|||
/*
|
||||
* Keep the node with the greater number of entries, and merge
|
||||
* the node with fewer entries into it.
|
||||
* If one node is a port and the other isn't, keep the port node.
|
||||
* If both nodes are ports, keep the lowest numbered port. Since
|
||||
* ports generated by "extract unique" always have higher numbers,
|
||||
* this will preserve the original name. This is necessary due to
|
||||
* the "blindness" of "extract unique" to ports being merged
|
||||
* through connecting geometry in descendent cells. The unique
|
||||
* suffixes are overused, and ext2spice prunes the unnecessary
|
||||
* entries but needs to preserve the original node name.
|
||||
*/
|
||||
*/
|
||||
|
||||
keep = 0;
|
||||
nn1 = (*node1ptr)->efnode_name;
|
||||
nn2 = (*node2ptr)->efnode_name;
|
||||
if (nn1 && (nn1->efnn_port > 0))
|
||||
{
|
||||
if (nn2 && (nn2->efnn_port > 0) && (nn2->efnn_port < nn1->efnn_port))
|
||||
keep = 2;
|
||||
else
|
||||
keep = 1;
|
||||
}
|
||||
else if (nn2 && nn2->efnn_port > 0)
|
||||
keep = 2;
|
||||
|
||||
if ((keep == 1) || ((keep == 0) &&
|
||||
((*node1ptr)->efnode_num >= (*node2ptr)->efnode_num)))
|
||||
if ((*node1ptr)->efnode_num >= (*node2ptr)->efnode_num)
|
||||
{
|
||||
keeping = *node1ptr;
|
||||
removing = *node2ptr;
|
||||
|
|
@ -2027,7 +2032,7 @@ efNodeMerge(node1ptr, node2ptr)
|
|||
/* Make all EFNodeNames point to "keeping" */
|
||||
if (removing->efnode_name)
|
||||
{
|
||||
bool topportk, topportr;
|
||||
bool topportk, topportr, bestname;
|
||||
|
||||
for (nn = removing->efnode_name; nn; nn = nn->efnn_next)
|
||||
{
|
||||
|
|
@ -2039,9 +2044,9 @@ efNodeMerge(node1ptr, node2ptr)
|
|||
topportr = (removing->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
|
||||
|
||||
/* Concatenate list of EFNodeNames, taking into account precedence */
|
||||
if ((!keeping->efnode_name) || (!topportk && (topportr
|
||||
if ((!keeping->efnode_name) || (!topportk && topportr)
|
||||
|| EFHNBest(removing->efnode_name->efnn_hier,
|
||||
keeping->efnode_name->efnn_hier))))
|
||||
keeping->efnode_name->efnn_hier))
|
||||
{
|
||||
/*
|
||||
* New official name is that of "removing".
|
||||
|
|
|
|||
|
|
@ -562,8 +562,7 @@ efAddNodes(
|
|||
HashSetValue(he, (char *) newname);
|
||||
newname->efnn_node = newnode;
|
||||
newname->efnn_hier = hierName;
|
||||
// keep the port number
|
||||
newname->efnn_port = node->efnode_name->efnn_port;
|
||||
newname->efnn_port = -1;
|
||||
newname->efnn_refc = 0;
|
||||
if (newnode->efnode_name)
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue