diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c index 1b7729b3..8da6b054 100644 --- a/extflat/EFbuild.c +++ b/extflat/EFbuild.c @@ -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". diff --git a/extflat/EFflat.c b/extflat/EFflat.c index bbc0ab90..70bdc198 100644 --- a/extflat/EFflat.c +++ b/extflat/EFflat.c @@ -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) {