diff --git a/VERSION b/VERSION index ae074d55..23bbf6e6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.653 +8.3.654 diff --git a/doc/html/extresist.html b/doc/html/extresist.html index 9b9d7b13..b69e256b 100644 --- a/doc/html/extresist.html +++ b/doc/html/extresist.html @@ -30,11 +30,31 @@ information.
where option may be one of the following:
-
tolerance value -
Set the ratio between resistor and transistor tolerance - for determining when to insert resistance into a network route.
all
Extract all the nets. +
threshold [value] +
With no value given, returns the current lumped resistance + threshold used to determine if a network will or will not be + analyzed for resistance extraction, in milliohms. The default + threshold value is 10000 milliohms (10 ohms). If + value is given, then set the lumped resistance threshold + to value milliohms. +
mindelay [value] +
With no value given, returns the current delay time threshold + used to determine if a network will or will not be analyzed for + resistance extraction, in picoseconds. The default + mindelay value is zero, indicating that delay time is + not used for determining extraction. If value is given, + then set the delay threshold to value picoseconds. +
minres [value] +
With no value given, returns the current absolute resistance + threshold used to prune small resistances from a network when + simplifying, in milliohms. The default minres value + is 1000 milliohms (1 ohm). If value is given, then set + the absolute resistance threshold to value milliohms. + Note that resistances smaller than value may still + appear in the output netlist if the algorithm is unable to + simplify the network around the resistor.
simplify [on|off]
Turn on/off simplification of resistor nets.
extout [on|off] @@ -69,6 +89,8 @@ information. .fh file. If freq is specified, the file will be customized for fasthenry analysis at the indicated frequency (in Hz). +
tolerance value +
Deprecated! This option is no longer used by extresist.
help
Print help information
@@ -79,9 +101,9 @@ information.
The normal flow through layout extraction into a simulation file treats routes as nonphysical entities, that is, with infinitesimal - impedence through the wires. Extraction for digital simulation - using irsim generates "lumped resistances", a single - resistance per network node that, along with the node capacitance + impedence through the wires. Standard extraction generates "lumped + resistance" values, a single resistance per network node that, along + with the node capacitance to substrate, provides an RC time constant to approximately model the delay from point to point in the network node. The lumped resistance model is inappropriate for analog (i.e., SPICE) @@ -96,10 +118,9 @@ information. Using extresist as a standalone command is a multi-step process. It is first necessary to run extract to get - the initial netlist. - After a .ext file has been generated, the - extresist command may be run. The output is - a file .res.ext for each cell in the hierarchy. + the initial netlist. After a .ext file has been generated, + the extresist command may be run. The output is a file + .res.ext for each cell in the hierarchy. Finally, with the option extresist on set, ext2spice will generate the final, detailed simulation file.

@@ -110,7 +131,42 @@ information. magic version 8.3.597 an option extract do resistance that runs the resistance extraction in sequence with the regular extraction, producing both the .ext and .res.ext - files. + files. When extract do resistance is used, there is no need + to run extresist as a separate command. However, + extresist may be run prior to extract to set the + options that affect resistance network extraction, such as + extresist threshold, extresist minres, etc.

+ + As of magic version 8.3.653, the extresist tolerance option + is deprecated and has no effect on network resistance extraction. + Instead, extraction is controlled by three main options:

+ + extresist threshold (value in milliohms) sets a cutoff for + considering a network for detailed resistance extraction based on + the lumped resistance estimate (see above). For point-to-point + wires, the lumped resistance is approximately equal to the actual + wire resistance. For branching networks, it will generally be an + over-estimate. The default threshold value is set to + 10 ohms.

+ + extresist minres (value in milliohms) sets a cutoff for + individual resistors in the detailed resistor network. Resistors + below this threshold will get pruned out of the network if the + simplification algorithm is able to remove them. The default + minres value is set to 1 ohm.

+ + extresist mindelay (value in picoseconds) sets a cutoff for + considering a network for detailed resistance extraction based on + the end-to-end delay calculated from the lumped resistance + estimate. Once the network has been extracted, the mindelay + value is again evaluated against a revised calculation of the + delay to determine if the extracted detailed network should be + output. The default mindelay value is set to 0, indicating + that only the lumped resistance threshold should be used for + determining when to extract a detailed resistance network. + mindelay may be used in place of threshold, or both + may be used together, in which case a network is only extracted + if both threshold and mindelay are exceeded.

More details on using extresist can be found in magic Tutorial number 8. @@ -134,6 +190,6 @@ information. Return to command index -

Last updated: October 4, 2021 at 3:32pm

+

Last updated: May 29, 2026 at 11:33am

diff --git a/resis/ResReadExt.c b/resis/ResReadExt.c index 9ef92f06..12fc35e4 100644 --- a/resis/ResReadExt.c +++ b/resis/ResReadExt.c @@ -61,6 +61,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #define DEV_PARAM_START 7 #define NODES_NODENAME 1 +#define NODES_NODERES 2 #define NODES_NODEX 4 #define NODES_NODEY 5 #define NODES_NODETYPE 6 @@ -525,6 +526,7 @@ ResReadNode(int argc, char *argv[]) node->location.p_x = atoi(argv[NODES_NODEX]); node->location.p_y = atoi(argv[NODES_NODEY]); node->type = DBTechNameType(argv[NODES_NODETYPE]); + node->resistance = atoi(argv[NODES_NODERES]); if (node->type == -1) { @@ -727,8 +729,6 @@ ResReadDevice(int argc, TileType ttype; HashEntry *entry; ResExtNode *node; - ResValue rpersquare; - float wval; device = (RDev *)mallocMagic((unsigned)(sizeof(RDev))); @@ -757,34 +757,20 @@ ResReadDevice(int argc, device->drain = (ResExtNode *)NULL; device->subs = (ResExtNode *)NULL; - entry = HashLookOnly(&devptr->exts_deviceResist, "linear"); - if (entry != NULL) - rpersquare = (ResValue)(spointertype)HashGetValue(entry); - else - rpersquare = (ResValue)10000.0; /* Default to a sane value */ - - /* For devices, the device width is in the parameter list */ - wval = 0.0; + /* Find the end of parameter arguments */ for (i = DEV_Y; i < argc; i++) { char *eptr; - if ((eptr = strchr(argv[i], '=')) != NULL) - { - if (*argv[i] == 'w') - sscanf(eptr + 1, "%f", &wval); - } - else if (!StrIsInt(argv[i])) - break; + if ((eptr = strchr(argv[i], '=')) == NULL) + if (!StrIsInt(argv[i])) + break; } - if (i == argc) { TxError("Bad device %s: Too few arguments in .ext file\n", argv[DEV_NAME]); return 1; } - else - device->resistance = wval * rpersquare; /* Channel resistance */ /* Find and record the device terminal nodes */ /* Note that this only records up to two terminals matching FET @@ -857,8 +843,6 @@ ResReadFET(int argc, TileType ttype; HashEntry *entry; ResExtNode *node; - ResValue rpersquare; - float area, perim, wval, lval; device = (RDev *)mallocMagic((unsigned)(sizeof(RDev))); @@ -883,20 +867,6 @@ ResReadFET(int argc, device->rs_dattr = RDEV_NOATTR; device->rs_devptr = devptr; - entry = HashLookOnly(&devptr->exts_deviceResist, "linear"); - if (entry != NULL) - rpersquare = (ResValue)(spointertype)HashGetValue(entry); - else - rpersquare = (ResValue)10000.0; /* Default to a sane value */ - - /* For old-style FETs, the width is determined from area and perimeter */ - area = MagAtof(argv[FET_AREA]); - perim = MagAtof(argv[FET_PERIM]); - lval = 0.5 * (perim + sqrt(perim * perim - 4 * area)); - wval = area / lval; - - device->resistance = wval * rpersquare; /* Channel resistance */ - /* Find and record the FET terminal nodes */ entry = HashFind(&ResNodeTable, argv[FET_GATE]); diff --git a/resis/ResRex.c b/resis/ResRex.c index b7e50edb..7f9743cb 100644 --- a/resis/ResRex.c +++ b/resis/ResRex.c @@ -40,7 +40,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ /* giving zeptoseconds (yes, really. Look it up). This constant */ /* converts zeptoseconds to picoseconds. */ -#define Z_TO_P 1e9 +#define Z_TO_P 1e-9 +#define P_TO_Z 1e9 /* Table of nodes to ignore (manually specified) */ @@ -62,7 +63,7 @@ int resNodeNum; extern ResExtNode *ResOriginalNodes; /*Linked List of Nodes */ -int ResOptionsFlags = ResOpt_Simplify | ResOpt_Tdi | ResOpt_DoExtFile; +int ResOptionsFlags = ResOpt_Simplify | ResOpt_DoExtFile; char *ResCurrentNode; FILE *ResExtFile; @@ -213,8 +214,15 @@ ResInit() TTMaskZero(&(ResCopyMask[i])); TTMaskSetMask(&ResCopyMask[i], &DBConnectTbl[i]); } - resisdata->rthresh = 0; - resisdata->tdiTolerance = 1; + + /* Defaults: + * (1) rthresh: Only extract networks with a lumped resistance > 10 ohms + * (2) minres: Prune resistors < 1 ohm when possible + * (3) mindelay: Do not gate extraction based on calculated delay. + */ + resisdata->rthresh = 10000.0; + resisdata->minres = 1000.0; + resisdata->mindelay = 0.0; resisdata->frequency = 10e6; /* 10 MHz default */ HashInit(&ResIgnoreTable, INITFLATSIZE, HT_STRINGKEYS); @@ -227,7 +235,6 @@ ResInit() resisdata->rg_Tdi = 0.0; resisdata->rg_nodecap = 0.0; resisdata->rg_maxres = 0.0; - resisdata->rg_bigdevres = 0; resisdata->rg_tilecount = 0; resisdata->rg_status = 0; resisdata->rg_devloc = NULL; @@ -280,8 +287,10 @@ CmdExtResis(win, cmd) static const char * const cmdExtresisCmd[] = { "all extract all the nets", - "threshold [value] set minimum resistor extraction threshold", - "tolerance [value] set ratio between resistor and device tol.", + "threshold [value] set minimum network resistance threshold (milliohms)", + "minresist [value] set minimum individual resistance threshold (milliohms)", + "mindelay [value] set minimum network delay threshold (picoseconds)", + "tolerance [value] set ratio between resistor and device resistance (deprecated)", "simplify [on/off] turn on/off simplification of resistor nets", "extout [on/off] turn on/off writing of .res.ext file", "lumped [on/off] turn on/off writing of updated lumped resistances", @@ -290,7 +299,7 @@ CmdExtResis(win, cmd) "ignore names don't extract these nets", "include names extract only these nets", "box type extract the signal under the box on layer type", - "cell cellname extract the network for the cell named cellname", + "cell cellname extract the network for the cell named cellname", "blackbox [on/off] treat subcircuits with ports as black boxes", "fasthenry [freq] extract subcircuit network geometry into .fh file", "geometry extract network centerline geometry (experimental)", @@ -301,7 +310,7 @@ CmdExtResis(win, cmd) typedef enum { RES_BAD=-2, RES_AMBIG, RES_ALL, - RES_THRESH, RES_TOL, + RES_THRESH, RES_MINRES, RES_MINDELAY, RES_TOL, RES_SIMP, RES_EXTOUT, RES_LUMPED, RES_SILENT, RES_SKIP, RES_IGNORE, RES_INCLUDE, RES_BOX, RES_CELL, RES_BLACKBOX, RES_FASTHENRY, RES_GEOMETRY, RES_STATS, @@ -334,13 +343,13 @@ typedef enum { switch (option) { - case RES_TOL: + case RES_MINRES: if (cmd->tx_argc > 2) { - resisdata->tdiTolerance = MagAtof(cmd->tx_argv[2]); - if (resisdata->tdiTolerance <= 0) + resisdata->minres = MagAtof(cmd->tx_argv[2]); + if (resisdata->minres < 0) { - TxError("Usage: %s tolerance [value]\n", cmd->tx_argv[0]); + TxError("Usage: %s minres [value]\n", cmd->tx_argv[0]); return; } } @@ -348,14 +357,41 @@ typedef enum { { #ifdef MAGIC_WRAPPER Tcl_SetObjResult(magicinterp, - Tcl_NewDoubleObj((double)resisdata->tdiTolerance)); + Tcl_NewDoubleObj((double)resisdata->minres)); #else - TxPrintf("Tolerance ratio is %g.\n", resisdata->tdiTolerance); + TxPrintf("Minimum network resistance is %g milliohms.\n", + resisdata->minres); #endif } return; - case RES_THRESH: + case RES_MINDELAY: + if (cmd->tx_argc > 2) + { + resisdata->mindelay = MagAtof(cmd->tx_argv[2]) * P_TO_Z; + if (resisdata->mindelay <= 0) + { + TxError("Usage: %s mindelay [value]\n", cmd->tx_argv[0]); + return; + } + } + else + { +#ifdef MAGIC_WRAPPER + Tcl_SetObjResult(magicinterp, + Tcl_NewDoubleObj((double)resisdata->mindelay * Z_TO_P)); +#else + TxPrintf("Minimum network delay is %g picoseconds.\n", + resisdata->mindelay); +#endif + } + return; + + case RES_TOL: + TxError("Note: This option has been deprecated and is unused.\n"); + return; + + case RES_THRESH: if (cmd->tx_argc > 2) { resisdata->rthresh = MagAtof(cmd->tx_argv[2]); @@ -371,23 +407,23 @@ typedef enum { Tcl_SetObjResult(magicinterp, Tcl_NewDoubleObj((double)resisdata->rthresh)); #else - TxPrintf("Resistance threshold is %g.\n", resisdata->rthresh); + TxPrintf("Minimum resistor threshold is %g.\n", resisdata->rthresh); #endif } return; - case RES_ALL: + case RES_ALL: ResOptionsFlags |= ResOpt_ExtractAll; break; - case RES_GEOMETRY: + case RES_GEOMETRY: saveFlags = ResOptionsFlags; ResOptionsFlags |= ResOpt_Geometry | ResOpt_ExtractAll; ResOptionsFlags &= ~(ResOpt_DoExtFile | ResOpt_DoLumpFile - | ResOpt_Simplify | ResOpt_Tdi); + | ResOpt_Simplify); break; - case RES_FASTHENRY: + case RES_FASTHENRY: if (cmd->tx_argc == 3) { double tmpf = strtod(cmd->tx_argv[2], &endptr); @@ -402,7 +438,7 @@ typedef enum { saveFlags = ResOptionsFlags; ResOptionsFlags |= ResOpt_FastHenry | ResOpt_ExtractAll; ResOptionsFlags &= ~(ResOpt_DoExtFile | ResOpt_DoLumpFile - | ResOpt_Simplify | ResOpt_Tdi); + | ResOpt_Simplify); break; case RES_BLACKBOX: @@ -439,10 +475,14 @@ typedef enum { ResOptionsFlags &= ~ResOpt_Stats; } return; + case RES_SIMP: + /* Enable or disable resistor network simplification. Usually + * enabled in conjunction with TDi calculations (see below). + */ if (cmd->tx_argc == 2) { - value = (ResOptionsFlags & (ResOpt_Simplify | ResOpt_Tdi)) ? + value = (ResOptionsFlags & ResOpt_Simplify) ? TRUE : FALSE; TxPrintf("%s\n", onOff[value]); } @@ -451,11 +491,12 @@ typedef enum { value = Lookup(cmd->tx_argv[2], onOff); if (value) - ResOptionsFlags |= ResOpt_Simplify | ResOpt_Tdi; + ResOptionsFlags |= ResOpt_Simplify; else - ResOptionsFlags &= ~(ResOpt_Simplify | ResOpt_Tdi); + ResOptionsFlags &= ~ResOpt_Simplify; } return; + case RES_EXTOUT: if (cmd->tx_argc == 2) { @@ -472,6 +513,7 @@ typedef enum { ResOptionsFlags &= ~ResOpt_DoExtFile; } return; + case RES_LUMPED: if (cmd->tx_argc == 2) { @@ -488,6 +530,7 @@ typedef enum { ResOptionsFlags &= ~ResOpt_DoLumpFile; } return; + case RES_SILENT: if (cmd->tx_argc == 2) { @@ -623,14 +666,17 @@ typedef enum { case RES_RUN: ResOptionsFlags &= ~ResOpt_ExtractAll; break; + case RES_AMBIG: TxPrintf("Ambiguous option: %s\n", cmd->tx_argv[1]); TxFlushOut(); return; + case RES_BAD: TxPrintf("Unknown option: %s\n", cmd->tx_argv[1]); TxFlushOut(); return; + default: return; } @@ -981,8 +1027,6 @@ ResProcessNode( { HashEntry *he; devPtr *ptr; - float ftolerance, minRes, cumRes; - float rthresh = resisdata->rthresh; int nidx = 1, eidx = 1; /* node & segment counters for geom. */ /* Ignore or include specified nodes */ @@ -1009,9 +1053,6 @@ ResProcessNode( ResCurrentNode = node->name; ResSortByGate(&node->devices); - /* Find largest SD device connected to node. */ - - minRes = FLT_MAX; resisdata->rg_devloc = (Point *) NULL; resisdata->rg_status = FALSE; resisdata->rg_nodecap = node->capacitance; @@ -1021,56 +1062,27 @@ ResProcessNode( resisdata->rg_ttype = node->type; + /* Pick the first device connected to node. */ + for (ptr = node->devices; 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; - resisdata->rg_devloc = &t1->location; - resisdata->rg_ttype = t1->rs_ttype; - } + resisdata->rg_devloc = &t1->location; + resisdata->rg_ttype = t1->rs_ttype; + break; } } /* 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; - /* NOTE: This needs to be fixed, as it is assuming that * a node has exactly one drivepoint; this is (probably) * valid for top level cells, but not in general. @@ -1098,25 +1110,33 @@ ResProcessNode( TxError("Node %s has force label but no drive point or " "driving device\n", node->name); } - if ((minRes == FLT_MAX) || (resisdata->rg_devloc == NULL)) + if (resisdata->rg_devloc == NULL) return 1; - resisdata->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. + * Extract the net if: + * 1. The lumped node resistance is greater than the minimum specified AND + * 2. The maximum net delay is greater than the minimum delay specified OR + * 3. "extresist all" has been invoked. + * + * The purpose of (1 AND 2) is to allow the cutoff to be specified either + * by absolute resistance ("extresist threshold") or by effective signal + * propagation delay ("extresist mindelay"). If either one is set to zero, + * it will be ignored, although they can also be used in combination. */ - if ((node->resistance > ftolerance) || (node->status & FORCE) || - (ResOpt_ExtractAll & ResOptionsFlags)) + if ((ResOpt_ExtractAll & ResOptionsFlags) || + ((node->resistance > resisdata->rthresh) && + (node->resistance * node->capacitance > resisdata->mindelay))) { ResFixPoint fp; + /* Diagnostic */ + TxPrintf("Extracting %s (Rnode = %.2fohm ; Rthresh = %.2fohm)\n", + node->name, + node->resistance * MILLIOHMSTOOHMS, + resisdata->rthresh * MILLIOHMSTOOHMS); + (*num_extracted)++; if (ResExtractNet(node, resisdata, outfile) != 0) { @@ -1129,17 +1149,13 @@ ResProcessNode( } else { - ResDoSimplify(ftolerance, resisdata); + ResDoSimplify(resisdata); if (ResOptionsFlags & ResOpt_DoLumpFile) ResWriteLumpFile(node, resisdata); - if (resisdata->rg_maxres >= ftolerance || - (ResOptionsFlags & ResOpt_ExtractAll)) - { - resNodeNum = 0; - (*num_output) += ResWriteExtFile(celldef, node, resisdata, + resNodeNum = 0; + (*num_output) += ResWriteExtFile(celldef, node, resisdata, &nidx, &eidx); - } } #ifdef PARANOID ResSanityChecks(node->name, ResResList, ResNodeList, ResDevList); @@ -1774,12 +1790,12 @@ ResWriteLumpFile(node, resisdata) { int lumpedres; - if (ResOptionsFlags & ResOpt_Tdi) + if (resisdata->mindelay > 0) { if (resisdata->rg_nodecap != 0) { - lumpedres = (int)((resisdata->rg_Tdi / resisdata->rg_nodecap - - (float)(resisdata->rg_bigdevres)) / OHMSTOMILLIOHMS); + lumpedres = (int)((resisdata->rg_Tdi / resisdata->rg_nodecap) / + OHMSTOMILLIOHMS); } else lumpedres = 0; @@ -1869,80 +1885,73 @@ ResWriteExtFile(celldef, node, resisdata, nidx, eidx) ResisData *resisdata; int *nidx, *eidx; { - float RCdev; char *cp, newname[MAXNAME]; devPtr *ptr; resDevice *layoutDev, *ResGetDevice(); - float rctol; ResConnect *driver, *sink; - rctol = resisdata->tdiTolerance; - RCdev = resisdata->rg_bigdevres * resisdata->rg_nodecap; + ASSERT(resisdata->rg_Tdi != -1, "ResWriteExtFile"); - if ((node->status & FORCE) || - (ResOptionsFlags & ResOpt_ExtractAll) || - (ResOptionsFlags & ResOpt_Simplify) == 0 || - (rctol + 1) * RCdev < rctol * resisdata->rg_Tdi) + sprintf(newname, "%s", node->name); + cp = newname + strlen(newname) - 1; + if (*cp == '!' || *cp == '#') *cp = '\0'; + + /* Second cutoff (if mindelay is specified): The original cutoff + * was based on the original lumped resistance estimate from basic + * extraction. Having done full network extraction, there is now + * a refined delay estimate rg_Tdi which may be much lower than + * the original estimate. If the new estimate falls below the + * threshold, then return without outputting the node's network. + */ + if (resisdata->rg_Tdi < resisdata->mindelay) return 0; + + if (!(ResOptionsFlags & ResOpt_RunSilent)) { - ASSERT(resisdata->rg_Tdi != -1, "ResWriteExtFile"); - - sprintf(newname, "%s", node->name); - cp = newname + strlen(newname) - 1; - if (*cp == '!' || *cp == '#') *cp = '\0'; - if ((rctol + 1) * RCdev < rctol * resisdata->rg_Tdi || - (ResOptionsFlags & ResOpt_Tdi) == 0) - { - if ((ResOptionsFlags & (ResOpt_RunSilent | ResOpt_Tdi)) == ResOpt_Tdi) - { - TxPrintf("Adding %s; Tnew = %.2fns, Told = %.2fns\n", - node->name, resisdata->rg_Tdi / Z_TO_P, RCdev / Z_TO_P); - } - } - else - TxPrintf("Adding %s\n", node->name); - - for (ptr = node->devices; ptr != NULL; ptr = ptr->nextDev) - if ((layoutDev = ResGetDevice(&ptr->thisDev->location, - ptr->thisDev->rs_ttype))) - ResFixUpConnections(ptr->thisDev, layoutDev, node, newname); - - /* Copy the node name into a driver connection if no driver connection - * has the original node name (e.g., was a port). All other drivers - * get ".uX" suffixes to distinguish them from internal network nodes - * (".nX"). - */ - for (driver = node->drivepoints; driver != NULL; driver = driver->rc_next) - ResFixUpDrivepoints(driver, node, newname); - - /* Replace downward connections (sinks) with new node names. Node - * names of sinks are given the suffix ".dX" to distinguish them - * from terminals, drivers, and nodes. - */ - for (sink = node->sinkpoints; sink != NULL; sink = sink->rc_next) - ResFixUpSinkpoints(driver, node, newname); - - if (ResOptionsFlags & ResOpt_DoExtFile) - { - ResPrintExtNode(ResExtFile, ResNodeList, node); - ResPrintExtRes(ResExtFile, ResResList, newname); - } - if (ResOptionsFlags & ResOpt_FastHenry) - { - if (ResResList) - ResAlignNodes(ResNodeList, ResResList); - ResPrintFHNodes(ResFHFile, ResNodeList, node->name, nidx, celldef); - ResPrintFHRects(ResFHFile, ResResList, newname, eidx); - } - if (ResOptionsFlags & ResOpt_Geometry) - { - if (ResResList) - ResAlignNodes(ResNodeList, ResResList); - if (ResCreateCenterlines(ResResList, nidx, celldef) < 0) - return 0; - } - return 1; + TxPrintf("Adding %s; (Tnew = %.2fps ; Tmin = %.2fps)\n", + node->name, resisdata->rg_Tdi * Z_TO_P, + resisdata->mindelay * Z_TO_P); } - else return 0; + + for (ptr = node->devices; ptr != NULL; ptr = ptr->nextDev) + if ((layoutDev = ResGetDevice(&ptr->thisDev->location, + ptr->thisDev->rs_ttype))) + ResFixUpConnections(ptr->thisDev, layoutDev, node, newname); + + /* Copy the node name into a driver connection if no driver connection + * has the original node name (e.g., was a port). All other drivers + * get ".uX" suffixes to distinguish them from internal network nodes + * (".nX"). + */ + for (driver = node->drivepoints; driver != NULL; driver = driver->rc_next) + ResFixUpDrivepoints(driver, node, newname); + + /* Replace downward connections (sinks) with new node names. Node + * names of sinks are given the suffix ".dX" to distinguish them + * from terminals, drivers, and nodes. + */ + for (sink = node->sinkpoints; sink != NULL; sink = sink->rc_next) + ResFixUpSinkpoints(driver, node, newname); + + if (ResOptionsFlags & ResOpt_DoExtFile) + { + ResPrintExtNode(ResExtFile, ResNodeList, node); + ResPrintExtRes(ResExtFile, ResResList, newname); + } + if (ResOptionsFlags & ResOpt_FastHenry) + { + if (ResResList) + ResAlignNodes(ResNodeList, ResResList); + ResPrintFHNodes(ResFHFile, ResNodeList, node->name, nidx, celldef); + ResPrintFHRects(ResFHFile, ResResList, newname, eidx); + } + if (ResOptionsFlags & ResOpt_Geometry) + { + if (ResResList) + ResAlignNodes(ResNodeList, ResResList); + if (ResCreateCenterlines(ResResList, nidx, celldef) < 0) + return 0; + } + return 1; } /* diff --git a/resis/ResSimple.c b/resis/ResSimple.c index 62984247..213762d4 100644 --- a/resis/ResSimple.c +++ b/resis/ResSimple.c @@ -178,7 +178,7 @@ ResSimplifyNet(nodelist, biglist, reslist, tolerance) /* other recievers at far end? If so, reschedule other node; * deadlock will be settled from that node. */ - if ((MarkedReceivers+UnMarkedReceivers+NumberOfDrivers == 2) || + if ((MarkedReceivers + UnMarkedReceivers + NumberOfDrivers == 2) || (UnMarkedReceivers == 0 && MarkedReceivers > 1 && resistor2 == resistor1 && PendingReceivers == 0)) { @@ -229,7 +229,7 @@ ResSimplifyNet(nodelist, biglist, reslist, tolerance) * Two resistors in series? Combine them and move devices to * appropriate end. */ - else if (numdrive+numreceive == 2 && (resistor1->rr_value < tolerance && + else if (numdrive + numreceive == 2 && (resistor1->rr_value < tolerance && resistor2->rr_value < tolerance)) { if ((resistor1->rr_status & RES_MARKED) == 0 && @@ -362,7 +362,7 @@ ResSimplifyNet(nodelist, biglist, reslist, tolerance) /* *------------------------------------------------------------------------- * - * ResMoveDevices-- move devices from one node1 to node2 + * ResMoveDevices-- move devices from one node (node1) to anther (node2) * * Results: none * @@ -829,11 +829,11 @@ ResCalculateTDi(node, resistor, resistorvalue) ASSERT(rcd != NULL, "ResCalculateTdi"); if (resistor == NULL) - rcd->rc_Tdi = rcd->rc_Cdownstream*(float)resistorvalue; + rcd->rc_Tdi = rcd->rc_Cdownstream * (float)resistorvalue; else { rcd2 = (RCDelayStuff *)resistor->rr_connection1->rn_client; - ASSERT(rcd2 != NULL,"ResCalculateTdi"); + ASSERT(rcd2 != NULL, "ResCalculateTdi"); rcd->rc_Tdi = rcd->rc_Cdownstream * (float)resistor->rr_value + rcd2->rc_Tdi; } @@ -920,25 +920,21 @@ ResPruneTree(node, minTdi, nodelist1, nodelist2, resistorlist) */ int -ResDoSimplify(tolerance, resisdata) - float tolerance; +ResDoSimplify(resisdata) ResisData *resisdata; { resNode *node, *slownode; - float bigres = 0; - float millitolerance; + float bigres = 0.0; float totalcap; - float rctol; resResistor *res; - rctol = resisdata->tdiTolerance; ResSetPathRes(resisdata); for (node = ResNodeList; node != NULL; node = node->rn_more) - bigres = MAX(bigres, node->rn_noderes); + bigres = MAX(bigres, node->rn_noderes); - bigres /= OHMSTOMILLIOHMS; /* convert from milliohms to ohms */ + bigres /= OHMSTOMILLIOHMS; resisdata->rg_maxres = bigres; #ifdef PARANOID @@ -952,8 +948,8 @@ ResDoSimplify(tolerance, resisdata) (void) ResDistributeCapacitance(ResNodeList, resisdata->rg_nodecap); - if (((tolerance > bigres) || ((ResOptionsFlags & ResOpt_Simplify) == 0)) && - ((ResOptionsFlags & ResOpt_DoLumpFile) == 0)) + if (((ResOptionsFlags & ResOpt_Simplify) == 0) && + ((ResOptionsFlags & ResOpt_DoLumpFile) == 0)) return 0; res = ResResList; @@ -963,16 +959,6 @@ ResDoSimplify(tolerance, resisdata) res = res->rr_nextResistor; oldres->rr_status &= ~RES_HEAP; - - /*------ NOTE: resistors marked with RES_TDI_IGNORE are - * part of loops but should NOT be removed. - if (oldres->rr_status & RES_TDI_IGNORE) - { - ResDeleteResPointer(oldres->rr_node[0], oldres); - ResDeleteResPointer(oldres->rr_node[1], oldres); - ResEliminateResistor(oldres, &ResResList); - } - ------*/ } if (ResNodeAtOrigin == NULL) @@ -980,7 +966,7 @@ ResDoSimplify(tolerance, resisdata) TxError("Error: Network simplification: Failed to to get origin node.\n"); resisdata->rg_Tdi = 0; } - else if (ResOptionsFlags & ResOpt_Tdi) + else if (resisdata->mindelay > 0) { if ((resisdata->rg_nodecap != -1) && (totalcap = ResCalculateChildCapacitance(ResNodeAtOrigin)) != -1) @@ -988,8 +974,7 @@ ResDoSimplify(tolerance, resisdata) RCDelayStuff *rc = (RCDelayStuff *) ResNodeList->rn_client; resisdata->rg_nodecap = totalcap; - ResCalculateTDi(ResNodeAtOrigin, (resResistor *)NULL, - resisdata->rg_bigdevres); + ResCalculateTDi(ResNodeAtOrigin, (resResistor *)NULL, 0); if (rc != (RCDelayStuff *)NULL) resisdata->rg_Tdi = rc->rc_Tdi; else @@ -1013,20 +998,10 @@ ResDoSimplify(tolerance, resisdata) else resisdata->rg_Tdi = 0; - if ((rctol+1) * resisdata->rg_bigdevres * resisdata->rg_nodecap > - rctol * resisdata->rg_Tdi && - (ResOptionsFlags & ResOpt_Tdi) && - resisdata->rg_Tdi != -1) - return 0; - - /* Simplify network; resistors are still in milliohms, so use - * millitolerance. - */ + /* Simplify network */ if (ResOptionsFlags & ResOpt_Simplify) { - millitolerance = tolerance * MILLIOHMSPEROHM; - /* * Start simplification at driver (R=0). Remove it from the done list * and add it to the pending list. Call ResSimplifyNet as long as @@ -1044,16 +1019,18 @@ ResDoSimplify(tolerance, resisdata) /* if Tdi is enabled, prune all branches whose end nodes */ /* have time constants less than the tolerance. */ - if ((ResOptionsFlags & ResOpt_Tdi) && - resisdata->rg_Tdi != -1 && - rctol != 0) - { - ResPruneTree(ResNodeAtOrigin, (rctol + 1) * - resisdata->rg_bigdevres * resisdata->rg_nodecap / rctol, + if ((resisdata->rg_Tdi != -1) && (resisdata->mindelay > 0)) + ResPruneTree(ResNodeAtOrigin, resisdata->mindelay, &ResNodeList, &ResNodeQueue, &ResResList); - } + ResNodeAtOrigin->rn_status &= ~RES_MARKED; - if (ResNodeAtOrigin->rn_less == NULL) + if (ResNodeAtOrigin->rn_less == CLIENTDEFAULT) + { + TxError("ResSimplify: Bad resptr at node %s origin.\n", + ResNodeAtOrigin->rn_name); + return 0; + } + else if (ResNodeAtOrigin->rn_less == NULL) ResNodeList = ResNodeAtOrigin->rn_more; else ResNodeAtOrigin->rn_less->rn_more = ResNodeAtOrigin->rn_more; @@ -1065,13 +1042,14 @@ ResDoSimplify(tolerance, resisdata) ResNodeAtOrigin->rn_less = NULL; ResNodeQueue = ResNodeAtOrigin; while (ResNodeQueue != NULL) - ResSimplifyNet(&ResNodeQueue, &ResNodeList, &ResResList, millitolerance); + ResSimplifyNet(&ResNodeQueue, &ResNodeList, &ResResList, + resisdata->minres); /* - * Call ResScrunchNet to eliminate any remaining under tolerance + * Call ResScrunchNet to eliminate any remaining under-tolerance * resistors. */ - ResScrunchNet(&ResResList, &ResNodeQueue, &ResNodeList, millitolerance); + ResScrunchNet(&ResResList, &ResNodeQueue, &ResNodeList, resisdata->minres); } } return 0; diff --git a/resis/resis.h b/resis/resis.h index aa187b0b..bce681ac 100644 --- a/resis/resis.h +++ b/resis/resis.h @@ -274,9 +274,10 @@ typedef struct resoptions { /* Global options for extresist */ - float tdiTolerance; - float frequency; - float rthresh; + float minres; /* Minimum network resistance to output */ + float mindelay; /* Minimum network delay to output */ + float rthresh; /* Minimum individual resistance */ + float frequency; /* For FastHenry geometry extraction */ struct saveList *savePlanes; CellDef *mainDef; @@ -288,9 +289,8 @@ typedef struct resoptions TileType rg_ttype; float rg_maxres; - float rg_nodecap; - float rg_Tdi; - int rg_bigdevres; + float rg_nodecap; /* Node capacitance */ + float rg_Tdi; /* Node delay */ int rg_tilecount; int rg_status; Point *rg_devloc; @@ -322,7 +322,6 @@ typedef struct rdev struct resextnode *subs; /* Used with subcircuit type only */ Point location; /* Location of lower left point of */ /* device. */ - float resistance; /* "Resistance" of device. */ TileType rs_ttype; /* tile type for device */ ExtDevice *rs_devptr; /* device extraction record */ char *rs_gattr; /* Gate attributes, if any */ @@ -461,6 +460,7 @@ typedef struct capval /* Capacitance table constants */ #define OHMSTOMILLIOHMS 1000 +#define MILLIOHMSTOOHMS 0.001 #define UNTOUCHED 0 #define SERIES 1 @@ -496,8 +496,7 @@ typedef struct capval #define ResOpt_DoLumpFile 0x0008 #define ResOpt_RunSilent 0x0010 #define ResOpt_Stats 0x0020 -#define ResOpt_Tdi 0x0040 -#define ResOpt_Signal 0x0080 +#define ResOpt_Signal 0x0040 #define ResOpt_Geometry 0x0100 #define ResOpt_FastHenry 0x0200 #define ResOpt_Blackbox 0x0300