More work on the "extresist" code, this time to revise the way

that "extresist" selects or rejects networks for resistance
extraction.  The "tolerance" value, which nobody (including
myself) seems to understand, is now deprecated, replaced by
a handful of more meaningful options:  "threshold" to set a
lumped resistance estimate threshold to determined whether or
not to extract a network;  "minres" to specify when to prune
small resistors from the resulting tree network, and "mindelay"
to gate the selection and output on the estimated signal
propagation delay.  With these settings, I am much better able
to control the size and complexity of the resulting output.
This commit is contained in:
R. Timothy Edwards 2026-05-29 11:47:01 -04:00
parent 1bcad6a25c
commit 4393d9310a
6 changed files with 271 additions and 259 deletions

View File

@ -1 +1 @@
8.3.653
8.3.654

View File

@ -30,11 +30,31 @@ information.
<BLOCKQUOTE>
where <I>option</I> may be one of the following:
<DL>
<DT> <B>tolerance</B> <I>value</I>
<DD> Set the ratio between resistor and transistor tolerance
for determining when to insert resistance into a network route.
<DT> <B>all</B>
<DD> Extract all the nets.
<DT> <B>threshold</B> [<I>value</I>]
<DD> 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
<B>threshold</B> value is 10000 milliohms (10 ohms). If
<I>value</I> is given, then set the lumped resistance threshold
to <I>value</I> milliohms.
<DT> <B>mindelay</B> [<I>value</I>]
<DD> 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
<B>mindelay</B> value is zero, indicating that delay time is
not used for determining extraction. If <I>value</I> is given,
then set the delay threshold to <I>value</I> picoseconds.
<DT> <B>minres</B> [<I>value</I>]
<DD> With no value given, returns the current absolute resistance
threshold used to prune small resistances from a network when
simplifying, in milliohms. The default <B>minres</B> value
is 1000 milliohms (1 ohm). If <I>value</I> is given, then set
the absolute resistance threshold to <I>value</I> milliohms.
Note that resistances smaller than <I>value</I> may still
appear in the output netlist if the algorithm is unable to
simplify the network around the resistor.
<DT> <B>simplify</B> [<B>on</B>|<B>off</B>]
<DD> Turn on/off simplification of resistor nets.
<DT> <B>extout</B> [<B>on</B>|<B>off</B>]
@ -69,6 +89,8 @@ information.
<TT>.fh</TT> file. If <I>freq</I> is specified, the file will
be customized for <B>fasthenry</B> analysis at the indicated
frequency (in Hz).
<DT> <B>tolerance</B> <I>value</I>
<DD> <I>Deprecated!</I> This option is no longer used by extresist.
<DT> <B>help</B>
<DD> Print help information
</DL>
@ -79,9 +101,9 @@ information.
<BLOCKQUOTE>
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 <B>irsim</B> 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 <I>RC</I> 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 <B>extresist</B> as a standalone command is a multi-step
process. It is first necessary to run <B>extract</B> to get
the initial netlist.
After a <TT>.ext</TT> file has been generated, the
<B>extresist</B> command may be run. The output is
a file <TT>.res.ext</TT> for each cell in the hierarchy.
the initial netlist. After a <TT>.ext</TT> file has been generated,
the <B>extresist</B> command may be run. The output is a file
<TT>.res.ext</TT> for each cell in the hierarchy.
Finally, with the option <B>extresist on</B> set, <B>ext2spice</B>
will generate the final, detailed simulation file. <P>
@ -110,7 +131,42 @@ information.
magic version 8.3.597 an option <B>extract do resistance</B>
that runs the resistance extraction in sequence with the regular
extraction, producing both the <TT>.ext</TT> and <TT>.res.ext</TT>
files.
files. When <B>extract do resistance</B> is used, there is no need
to run <B>extresist</B> as a separate command. However,
<B>extresist</B> may be run prior to <B>extract</B> to set the
options that affect resistance network extraction, such as
<B>extresist threshold</B>, <B>extresist minres</B>, etc. <P>
As of magic version 8.3.653, the <B>extresist tolerance</B> option
is deprecated and has no effect on network resistance extraction.
Instead, extraction is controlled by three main options: <P>
<B>extresist threshold</B> (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 <B>threshold</B> value is set to
10 ohms. <P>
<B>extresist minres</B> (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
<B>minres</B> value is set to 1 ohm. <P>
<B>extresist mindelay</B> (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 <B>mindelay</B>
value is again evaluated against a revised calculation of the
delay to determine if the extracted detailed network should be
output. The default <B>mindelay<B> value is set to 0, indicating
that only the lumped resistance threshold should be used for
determining when to extract a detailed resistance network.
<B>mindelay</B> may be used in place of <B>threshold</B>, or both
may be used together, in which case a network is only extracted
if both <B>threshold</B> and <B>mindelay</B> are exceeded. <P>
More details on using <B>extresist</B> can be found in
<B>magic</B> Tutorial number 8.
@ -134,6 +190,6 @@ information.
<TD> <A HREF=commands.html>Return to command index</A>
</TR>
</TABLE>
<P><I>Last updated:</I> October 4, 2021 at 3:32pm <P>
<P><I>Last updated:</I> May 29, 2026 at 11:33am <P>
</BODY>
</HTML>

View File

@ -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]);

View File

@ -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;
}
/*

View File

@ -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;

View File

@ -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