From b768fcc3f910eba5fd21359dd508530c51b4342b Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Thu, 22 Jan 2026 12:38:10 -0500 Subject: [PATCH] Beginning to tear apart the extresist code; work in progress and a lot of construction mess. Resolved conflicts after rebasing on master, since both were modifying the list of options to "extract". --- README | 141 +++++++++++--- commands/CmdE.c | 8 +- extract/ExtBasic.c | 22 +++ extract/extract.h | 3 +- extract/extractInt.h | 1 + resis/ResRex.c | 438 +++++++++++++++++++++++-------------------- 6 files changed, 380 insertions(+), 233 deletions(-) diff --git a/README b/README index 2ebd5e13..a382210c 100644 --- a/README +++ b/README @@ -2,33 +2,126 @@ Second major code overhaul of 2026 ----------------------------------------- Implement the planned changes to "extresist": -(1) Remove the .sim format as a requirement. - extresist will get its node list from doing - a standard extraction (extFindNodes() or - ExtFindRegions(), whichever is appropriate. - This should be able to be done as a relatively - simple change, allowing "extresist" to be used +(1) Remove the .sim format as a requirement. extresist will get its node + list from doing a standard extraction (extFindNodes() or + ExtFindRegions(), whichever is appropriate. This should be able to be + done as a relatively simple change, allowing "extresist" to be used without doing "ext2sim" as part of the process. -(2) Move extresist into the "extract" code. - "extresist" will become a command "extract do - extresist" and "ext2spice extresist on|off" - will determine if split nodes and terminals - are kept apart in the final netlist or - aggregated---Exactly as capacitance is done - now. +(2) Move extresist into the "extract" code. "extresist" will become a + command "extract do extresist" and "ext2spice extresist on|off" + will determine if split nodes and terminals are kept apart in the + final netlist or aggregated---Exactly as capacitance is done now. - Need to figure out how "tile junk" client data - and extract client data can exist simultaneously. + Need to figure out how "tile junk" client data and extract client + data can exist simultaneously. - "extresist" will run within "extBasic", being - called on a node after the devices and nodes are - identified; nodes created by ExtFindRegions() - will get sub-divided into more nodes. The - difficult case will be where a single tile gets - multiple nodes (such as where other wires branch - off the tile in the up or down direction). Maybe - this can be done like ClientData for split tiles, - with an indicator bit in ti_body? + "extresist" will run within "extBasic", being called on a node after + the devices and nodes are identified; nodes created by ExtFindRegions() + will get sub-divided into more nodes. The difficult case will be where + a single tile gets multiple nodes (such as where other wires branch off + the tile in the up or down direction). Maybe this can be done like + ClientData for split tiles, with an indicator bit in ti_body? ----------------------------------------------------- +For (1): + + Reading the "nodes" file only creates "node" entries, one per net. + With an ExtFindRegions and ExtLabelRegions (or extFindNodes?) there + should be an equivalent list from which node names, locations, and + types can be taken. This information will be redundant, for now. + + Note that ExtResisForDef() runs extResPrepSubstrate() which is like + extPrepSubstrate(), which is run from extCellFile(). + + So ExtResisForDef() could replace lines 150 to 174 with the ExtBasic + calls to ExtFindRegions(), extFindNodes(), and ExtLabelRegions(). + This is followed by temporary code that creates the tables and lists + that the extresist code uses. Then, run the ResCheckSimNodes() code, + or at least the part for a single node (which is ResRex.c lines 1071 + to 1240) + + Add a ClientData record to a NodeRegion, and extresist can run + by adding "tileJunk" records to the NodeRegion client data, and + leave the region records in place. (done) + + Then need to figure out how to output the data all at once. + + Replace the "extresist" command with "extract do extresist". + EXT_DOEXTRESIST. Maybe later replace "resistance" and make it + equivalent to "extresist", or maybe make "resistance" *be* + DOEXTRESIST and use "lumped" instead of "resistance" (I like + this better). (done) + + "ext2spice extresist on" will then output the netlist exactly as + it appears in the .ext file, while "ext2spice extresist off" will + conglomerate the .tX and .nX sub-nodes and produce what is + hopefully the equivalent of a netlist from a .ext file without + "extract do extresist". + + We keep (maybe) + HashTable ResNodeTable + RDev *ResRDevList + + At issue: Doing it this way might be more convenient, but by + keeping the NodeRegions in place and adding "tileJunk" records, + it's harder to find where the subnets are connected. If the + NodeRegions get replaced, then there are way more regions but, + for example, a transistor terminal node is easily found by + looking at the Region pointer connected to the terminal type. + However, nodes are output by working through the node list and + devices are output by working through the device list, so the + information is readily available. + +Currently the "to-do" work starts at ExtBasic.c line 313. + +Pulled out the central part of ResCheckSimNodes() into "ResProcessNode()". +This allows ExtBasic.c to loop over its own nodeList, prepare the +ResSimNode structure, and then call ResProcessNode() to process a +single network. + +These are all then bypassed: + + CmdExtResist() + ExtResisForDef() + extResPrepSubstrate() + ResReadSim() + ResCheckPorts() + ResCheckSimNodes() + (clean up ResNodeTable and ResRDevList) + +The only one of the bypassed routines which may need to be handled +is "ResCheckPorts()". Possibly the ExtSubtree/ExtHier stuff can be +used in place? The main issue is figuring out where the ports are. +Unlike the original "extresist" method, it should be possible to do +this properly. Punt on it for the moment. + +Try to compile with the separated-out ResProcessNode() routine. +Okay, got that working. + +Now, the hard work: Prepare an extresist node record from ExtBasic.c. +Don't worry about how ClientData records are managed, for now. + +Now, what does ResCleanUpEverything() do? We don't want to destroy +the records until the end. Maybe node regions should be replaced by +subnets here? And the resistors can be kept in a linked list or +hash table to be output along with the devices. + +The issue here is that some tiles can contain multiple sub-nets, +if there are wires branching off. Note, however, that wires can +only branch off of a single rectangle in the north or south directions, +due to the "maximum horizontal stripes" rule. What if subnets within +a tile were handled by splitting the tile, which would only be done +horizontally, and keeping the tiles separate by setting a flag in +ti_body such that a long wire with many branches would be split into +multiple segments with the flag set to 1010101. . ., which allows the +normal tile handling to work. The flags can be cleaned up afterward +and the tiles merged (maybe just erase and repaint the tile)? Note +that this would never happen with split tiles. Probably okay with +contacts? + +Due to the maximum horizontal stripes consideration, does +ResCalcNorthSouth() *ever* get called?? +Okay, a long vertical contact with metal branches on either side +would invalidate my assumption, and yes, ResCalcNorthSouth() would +be called. diff --git a/commands/CmdE.c b/commands/CmdE.c index 83813642..7a67ff91 100644 --- a/commands/CmdE.c +++ b/commands/CmdE.c @@ -931,6 +931,7 @@ cmdExpandFunc( #define DOLABELCHECK 7 #define DOALIASES 8 #define DOUNIQUE 9 +#define DOEXTRESIST 10 #define LENCLEAR 0 #define LENDRIVER 1 @@ -975,10 +976,11 @@ CmdExtract( "coupling extract coupling capacitance", "length compute driver-receiver pathlengths", "local put all generated files in the current directory", - "resistance estimate resistance", + "lumped estimate lumped resistance", "labelcheck check for connections through sticky labels", "aliases output all net name aliases", "unique ensure unique node names during extraction", + "resistance extract resistance", NULL }; static const char * const cmdExtLength[] = @@ -1280,10 +1282,11 @@ CmdExtract( TxPrintf("%s capacitance\n", OPTSET(EXT_DOCAPACITANCE)); TxPrintf("%s coupling\n", OPTSET(EXT_DOCOUPLING)); TxPrintf("%s length\n", OPTSET(EXT_DOLENGTH)); - TxPrintf("%s resistance\n", OPTSET(EXT_DORESISTANCE)); + TxPrintf("%s lumped R\n", OPTSET(EXT_DORESISTANCE)); TxPrintf("%s label check\n", OPTSET(EXT_DOLABELCHECK)); TxPrintf("%s aliases\n", OPTSET(EXT_DOALIASES)); TxPrintf("%s unique\n", OPTSET(EXT_DOUNIQUE)); + TxPrintf("%s resistance\n", OPTSET(EXT_DOEXTRESIST)); return; #undef OPTSET } @@ -1314,6 +1317,7 @@ CmdExtract( case DOLABELCHECK: option = EXT_DOLABELCHECK; break; case DOALIASES: option = EXT_DOALIASES; break; case DOUNIQUE: option = EXT_DOUNIQUE; break; + case DOEXTRESIST: option = EXT_DOEXTRESIST; break; case DOLOCAL: /* "extract do local" and "extract no local" are kept for * backwards compatibility, but now effectively implement diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 3444ddab..f70d863d 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -301,6 +301,28 @@ extBasic(def, outFile) if (!SigInterruptPending && (ExtDoWarn & EXTWARN_DUP) && !isabstract) extFindDuplicateLabels(def, nodeList); + /* + * If full R-C extraction is requested, then run it now. This + * code was previously run as the "extresist" command, but it + * makes more sense to be integral to the extraction process. + * It must be run prior to extFindCoupling() so that coupling + * capacitances are correctly assigned to subnets. + */ + if (!SigInterruptPending && (ExtOptions & EXT_DOEXTRESIST)) + { + ResSimNode *rsimnode; + ResisData resisdata; + int n_ext = 0, n_out = 0; + + for (reg = nodeList; reg && !SigInterruptPending; reg = reg->nreg_next) + { + rsimnode = ResCreateNode(); + ResProcessNode(rsimnode, def, &resisdata, &n_ext, &n_out); + + /* To be completed */ + } + } + /* * Build up table of coupling capacitances (overlap, sidewall). * This comes before extOutputNodes because we may have to adjust diff --git a/extract/extract.h b/extract/extract.h index e0dd2f53..7bd25850 100644 --- a/extract/extract.h +++ b/extract/extract.h @@ -68,13 +68,14 @@ extern const char * const extDevTable[]; #define EXT_DOADJUST 0x001 /* Extract hierarchical adjustments */ #define EXT_DOCAPACITANCE 0x002 /* Extract capacitance */ #define EXT_DOCOUPLING 0x004 /* Extract coupling capacitance */ -#define EXT_DORESISTANCE 0x008 /* Extract resistance */ +#define EXT_DORESISTANCE 0x008 /* Extract lumped resistance */ #define EXT_DOLENGTH 0x010 /* Extract pathlengths */ #define EXT_DOFRINGEHALO 0x020 /* Distributed fringe capacitance */ #define EXT_DOALL 0x03f /* ALL OF THE ABOVE */ #define EXT_DOLABELCHECK 0x040 /* Check for connections by label */ #define EXT_DOALIASES 0x080 /* Output all node aliases */ #define EXT_DOUNIQUE 0x100 /* Force unique nodes during extraction */ +#define EXT_DOEXTRESIST 0x200 /* Do full R-C extraction */ extern int ExtOptions; /* Bitmask of above */ extern char *ExtLocalPath; /* If non-NULL, location to write .ext files */ diff --git a/extract/extractInt.h b/extract/extractInt.h index 23368c2e..ebbb671d 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -209,6 +209,7 @@ typedef struct nreg * in X, then in Y. */ LabelList *nreg_labels; /* See LabRegion for description */ + ClientData nreg_subnet; /* Subnet record generated by extresist */ CapValue nreg_cap; /* Capacitance to ground */ ResValue nreg_resist; /* Resistance estimate */ PerimArea nreg_pa[1]; /* Dummy; each node actually has diff --git a/resis/ResRex.c b/resis/ResRex.c index 9be667d9..c453d0f0 100644 --- a/resis/ResRex.c +++ b/resis/ResRex.c @@ -966,6 +966,223 @@ ResCheckPorts(cellDef) return result; } +/* + *------------------------------------------------------------------------- + * + * ResCreateNode --- + * + * Create a node structure for extresist for the method where + * ResProcessNode() is called from extBasic() as part of the + * "extract" command. + * + * Results: + * Returns the node structure to be passed to ResProcessNode(). + * + * Side effects: + * Memory is allocated for the node structure. + * + *------------------------------------------------------------------------- + */ + +ResSimNode *ResCreateNode() +{ + ResSimNode *node; + + /* To be completed */ + + return node; +} + + +/* + *------------------------------------------------------------------------- + * + * ResProcessNode --- + * + * Do resistance extraction for a single network. + * + * Results: + * 1 if node was processed, 0 otherwise. + * + * Side effects: + * Many. Update the totals for number of nets extracted and + * number of nets output in the pointers in the argument list. + * + *------------------------------------------------------------------------- + */ + +int +ResProcessNode( + ResSimNode *node, /* Node record for network */ + CellDef *celldef, /* Cell def being processed */ + ResisData *resisdata, /* Extraction parameters kept here */ + char *outfile, /* Name of output file */ + int *num_extracted, /* Number of nets extracted so far */ + int *num_output) /* Number of nets output so far */ +{ + HashEntry *he; + devPtr *ptr; + float ftolerance, minRes, cumRes; + float rctol = resisdata->tdiTolerance; + float rthresh = resisdata->rthresh; + int nidx = 1, eidx = 1; /* node & segment counters for geom. */ + + /* Ignore or include specified nodes */ + + if (ResIncludeTable.ht_nEntries > 0) + { + he = HashLookOnly(&ResIncludeTable, node->name); + if (he == NULL) return 0; + } + else + { + he = HashLookOnly(&ResIgnoreTable, node->name); + if (he != NULL) return 0; + } + + /* Has this node been merged away or is it marked as skipped? */ + /* If so, skip it */ + + if ((node->status & (FORWARD | REDUNDANT)) || + ((node->status & SKIP) && + (ResOptionsFlags & ResOpt_ExtractAll) == 0)) + return 0; + + ResCurrentNode = node->name; + ResSortByGate(&node->firstDev); + + /* Find largest SD device connected to node. */ + + minRes = FLT_MAX; + gparams.rg_devloc = (Point *) NULL; + gparams.rg_status = FALSE; + gparams.rg_nodecap = node->capacitance; + + /* The following is only used if there is a drivepoint */ + /* to identify which tile the drivepoint is on. */ + + gparams.rg_ttype = node->rs_ttype; + + for (ptr = node->firstDev; ptr != NULL; ptr = ptr->nextDev) + { + RDev *t1; + RDev *t2; + + if (ptr->terminal == GATE) + { + break; + } + else + { + /* Get cumulative resistance of all devices */ + /* with same connections. */ + + cumRes = ptr->thisDev->resistance; + t1 = ptr->thisDev; + for (; ptr->nextDev != NULL; ptr = ptr->nextDev) + { + t1 = ptr->thisDev; + t2 = ptr->nextDev->thisDev; + if (t1->gate != t2->gate) break; + if ((t1->source != t2->source || t1->drain != t2->drain) && + (t1->source != t2->drain || t1->drain != t2->source)) + break; + + /* Do parallel combination */ + if ((cumRes != 0.0) && (t2->resistance != 0.0)) + cumRes = (cumRes * t2->resistance) / (cumRes + t2->resistance); + else + cumRes = 0; + } + if (minRes > cumRes) + { + minRes = cumRes; + gparams.rg_devloc = &t1->location; + gparams.rg_ttype = t1->rs_ttype; + } + } + } + + /* special handling for FORCE and DRIVELOC labels: */ + /* set minRes = node->minsizeres if it exists, 0 otherwise */ + + if (node->status & (FORCE|DRIVELOC)) + { + if (node->status & MINSIZE) + { + minRes = node->minsizeres; + } + else + { + minRes = 0; + } + if (node->status & DRIVELOC) + { + gparams.rg_devloc = &node->drivepoint; + gparams.rg_status |= DRIVEONLY; + } + if (node->status & PORTNODE) + { + /* The node is a port, not a device, so make */ + /* sure rg_ttype is set accordingly. */ + gparams.rg_ttype = node->rs_ttype; + } + } + if ((gparams.rg_devloc == NULL) && (node->status & FORCE)) + { + TxError("Node %s has force label but no drive point or " + "driving device\n", node->name); + } + if ((minRes == FLT_MAX) || (gparams.rg_devloc == NULL)) + return 1; + + gparams.rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS; + if (minRes > resisdata->rthresh) + ftolerance = minRes; + else + ftolerance = resisdata->rthresh; + + /* + * Is the device resistance greater than the lumped node + * resistance? If so, extract net. + */ + + if ((node->resistance > ftolerance) || (node->status & FORCE) || + (ResOpt_ExtractAll & ResOptionsFlags)) + { + ResFixPoint fp; + + (*num_extracted)++; + if (ResExtractNet(node, &gparams, outfile) != 0) + { + /* On error, don't output this net, but keep going */ + if (node->type == TT_SPACE) + TxPrintf("Note: Substrate node %s not extracted as network.\n", + node->name); + else + TxError("Error in extracting node %s\n", node->name); + } + else + { + ResDoSimplify(ftolerance, rctol, &gparams); + if (ResOptionsFlags & ResOpt_DoLumpFile) + ResWriteLumpFile(node); + + if (gparams.rg_maxres >= ftolerance || + (ResOptionsFlags & ResOpt_ExtractAll)) + { + resNodeNum = 0; + (*num_output) += ResWriteExtFile(celldef, node, rctol, &nidx, &eidx); + } + } +#ifdef PARANOID + ResSanityChecks(node->name, ResResList, ResNodeList, ResDevList); +#endif + ResCleanUpEverything(); + } + return 1; +} + /* *------------------------------------------------------------------------- * @@ -988,15 +1205,10 @@ ResCheckSimNodes(celldef, resisdata) ResisData *resisdata; { ResSimNode *node; - devPtr *ptr; - float ftolerance, minRes, cumRes; - int failed1=0; - int failed3=0; - int total =0; + int numext = 0; /* Number of nets extracted */ + int numout = 0; /* Number of nets output */ + int total = 0; /* Total number of nets processed */ char *outfile = celldef->cd_name; - float rctol = resisdata->tdiTolerance; - float rthresh = resisdata->rthresh; - int nidx = 1, eidx = 1; /* node & segment counters for geom. */ if (ResOptionsFlags & ResOpt_DoExtFile) { @@ -1005,8 +1217,8 @@ ResCheckSimNodes(celldef, resisdata) if (strcmp(ExtLocalPath, ".")) { char *namebuf; - namebuf = alloc = mallocMagic(strlen(ExtLocalPath) + strlen(celldef->cd_name) - + 2); + namebuf = alloc = mallocMagic(strlen(ExtLocalPath) + + strlen(celldef->cd_name) + 2); sprintf(namebuf, "%s/%s", ExtLocalPath, celldef->cd_name); outfile = namebuf; } @@ -1015,17 +1227,13 @@ ResCheckSimNodes(celldef, resisdata) outfile = celldef->cd_name; } else - { ResExtFile = NULL; - } + if (ResOptionsFlags & ResOpt_DoLumpFile) - { ResLumpFile = PaOpen(outfile, "w", ".res.lump", ".", (char *)NULL, (char **)NULL); - } else - { ResLumpFile = NULL; - } + if (ResOptionsFlags & ResOpt_FastHenry) { char *geofilename; @@ -1034,9 +1242,7 @@ ResCheckSimNodes(celldef, resisdata) ResPortIndex = 0; } else - { ResFHFile = NULL; - } if ((ResExtFile == NULL && (ResOptionsFlags & ResOpt_DoExtFile)) || ((ResOptionsFlags & ResOpt_DoLumpFile) && ResLumpFile == NULL) @@ -1052,191 +1258,23 @@ ResCheckSimNodes(celldef, resisdata) */ if (ResExtFile != NULL) - { fprintf(ResExtFile, "scale %d %d %g\n", ExtCurStyle->exts_resistScale, ExtCurStyle->exts_capScale, ExtCurStyle->exts_unitsPerLambda); - } /* * Write reference plane (substrate) definition and end statement * to the FastHenry geometry file. */ if (ResOptionsFlags & ResOpt_FastHenry) - { ResPrintReference(ResFHFile, ResRDevList, celldef); - } for (node = ResOriginalNodes; node != NULL; node=node->nextnode) { - HashEntry *he; - if (SigInterruptPending) break; - - /* Ignore or include specified nodes */ - - if (ResIncludeTable.ht_nEntries > 0) - { - he = HashLookOnly(&ResIncludeTable, node->name); - if (he == NULL) continue; - } - else - { - he = HashLookOnly(&ResIgnoreTable, node->name); - if (he != NULL) continue; - } - - /* Has this node been merged away or is it marked as skipped? */ - /* If so, skip it */ - if ((node->status & (FORWARD | REDUNDANT)) || - ((node->status & SKIP) && - (ResOptionsFlags & ResOpt_ExtractAll) == 0)) - continue; - - ResCurrentNode = node->name; - total++; - - ResSortByGate(&node->firstDev); - - /* Find largest SD device connected to node. */ - - minRes = FLT_MAX; - gparams.rg_devloc = (Point *) NULL; - gparams.rg_status = FALSE; - gparams.rg_nodecap = node->capacitance; - - /* The following is only used if there is a drivepoint */ - /* to identify which tile the drivepoint is on. */ - - gparams.rg_ttype = node->rs_ttype; - - for (ptr = node->firstDev; ptr != NULL; ptr = ptr->nextDev) - { - RDev *t1; - RDev *t2; - - if (ptr->terminal == GATE) - { - break; - } - else - { - /* Get cumulative resistance of all devices */ - /* with same connections. */ - - cumRes = ptr->thisDev->resistance; - t1 = ptr->thisDev; - for (; ptr->nextDev != NULL; ptr = ptr->nextDev) - { - t1 = ptr->thisDev; - t2 = ptr->nextDev->thisDev; - if (t1->gate != t2->gate) break; - if ((t1->source != t2->source || - t1->drain != t2->drain) && - (t1->source != t2->drain || - t1->drain != t2->source)) break; - - /* Do parallel combination */ - if ((cumRes != 0.0) && (t2->resistance != 0.0)) - { - cumRes = (cumRes * t2->resistance) / - (cumRes + t2->resistance); - } - else - { - cumRes = 0; - } - } - if (minRes > cumRes) - { - minRes = cumRes; - gparams.rg_devloc = &t1->location; - gparams.rg_ttype = t1->rs_ttype; - } - } - } - - /* special handling for FORCE and DRIVELOC labels: */ - /* set minRes = node->minsizeres if it exists, 0 otherwise */ - - if (node->status & (FORCE|DRIVELOC)) - { - if (node->status & MINSIZE) - { - minRes = node->minsizeres; - } - else - { - minRes = 0; - } - if (node->status & DRIVELOC) - { - gparams.rg_devloc = &node->drivepoint; - gparams.rg_status |= DRIVEONLY; - } - if (node->status & PORTNODE) - { - /* The node is a port, not a device, so make */ - /* sure rg_ttype is set accordingly. */ - gparams.rg_ttype = node->rs_ttype; - } - } - if ((gparams.rg_devloc == NULL) && (node->status & FORCE)) - { - TxError("Node %s has force label but no drive point or " - "driving device\n", node->name); - } - if ((minRes == FLT_MAX) || (gparams.rg_devloc == NULL)) - { - continue; - } - gparams.rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS; - if (minRes > resisdata->rthresh) - ftolerance = minRes; - else - ftolerance = resisdata->rthresh; - - /* - * Is the device resistance greater than the lumped node - * resistance? If so, extract net. - */ - - if ((node->resistance > ftolerance) || (node->status & FORCE) || - (ResOpt_ExtractAll & ResOptionsFlags)) - { - ResFixPoint fp; - - failed1++; - if (ResExtractNet(node, &gparams, outfile) != 0) - { - /* On error, don't output this net, but keep going */ - if (node->type == TT_SPACE) - TxPrintf("Note: Substrate node %s not extracted as network.\n", - node->name); - else - TxError("Error in extracting node %s\n", node->name); - } - else - { - ResDoSimplify(ftolerance, rctol, &gparams); - if (ResOptionsFlags & ResOpt_DoLumpFile) - { - ResWriteLumpFile(node); - } - if (gparams.rg_maxres >= ftolerance || - (ResOptionsFlags & ResOpt_ExtractAll)) - { - resNodeNum = 0; - failed3 += ResWriteExtFile(celldef, node, rctol, - &nidx, &eidx); - } - } -#ifdef PARANOID - ResSanityChecks(node->name, ResResList, ResNodeList, ResDevList); -#endif - ResCleanUpEverything(); - } + total += ResProcessNode(node, celldef, resisdata, outfile, + &numext, &numout); } /* @@ -1245,9 +1283,7 @@ ResCheckSimNodes(celldef, resisdata) */ if (ResOptionsFlags & ResOpt_DoExtFile) - { ResPrintExtDev(ResExtFile, ResRDevList); - } /* * Write end statement to the FastHenry geometry file. @@ -1280,30 +1316,20 @@ ResCheckSimNodes(celldef, resisdata) /* Output statistics about extraction */ if (total) - { TxPrintf("Total Nets: %d\nNets extracted: " - "%d (%f)\nNets output: %d (%f)\n", total, failed1, - (float)failed1 / (float)total, failed3, - (float)failed3 / (float)total); - } + "%d (%f)\nNets output: %d (%f)\n", total, numext, + (float)numext / (float)total, numout, + (float)numout / (float)total); else - { TxPrintf("Total Nodes: %d\n",total); - } /* close output files */ - if (ResExtFile != NULL) - (void) fclose(ResExtFile); - - if (ResLumpFile != NULL) - (void) fclose(ResLumpFile); - - if (ResFHFile != NULL) - (void) fclose(ResFHFile); + if (ResExtFile != NULL) (void) fclose(ResExtFile); + if (ResLumpFile != NULL) (void) fclose(ResLumpFile); + if (ResFHFile != NULL) (void) fclose(ResFHFile); } - /* *------------------------------------------------------------------------- *