Corrected an error in the original resistor network simplifying
routine that marks resistors in loops to prevent infinite recursion, but later incorrectly eliminates those resistors. Also: Changed the "tolerance" command to affect only the R-C time constant tolerance. Added a "threshold" command option that limits output of small resistors. This can help reduce large networks that are otherwise not reducible by the three methods of reduction (serial, parallel, and delta-wye), but does affect output values (slightly). This will probably need to be revisited at some point.
This commit is contained in:
parent
656b5dbabe
commit
088bb828ac
106
resis/ResRex.c
106
resis/ResRex.c
|
|
@ -96,9 +96,9 @@ struct saveList {
|
||||||
/* Structure stores information required to be sent to ExtResisForDef() */
|
/* Structure stores information required to be sent to ExtResisForDef() */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
float tolerance;
|
|
||||||
float tdiTolerance;
|
float tdiTolerance;
|
||||||
float frequency;
|
float frequency;
|
||||||
|
float rthresh;
|
||||||
struct saveList *savePlanes;
|
struct saveList *savePlanes;
|
||||||
CellDef *mainDef;
|
CellDef *mainDef;
|
||||||
} ResisData;
|
} ResisData;
|
||||||
|
|
@ -118,14 +118,14 @@ ExtResisForDef(celldef, resisdata)
|
||||||
CellDef *celldef;
|
CellDef *celldef;
|
||||||
ResisData *resisdata;
|
ResisData *resisdata;
|
||||||
{
|
{
|
||||||
RDev *oldRDev;
|
RDev *oldRDev;
|
||||||
HashSearch hs;
|
HashSearch hs;
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
devPtr *tptr, *oldtptr;
|
devPtr *tptr, *oldtptr;
|
||||||
ResSimNode *node;
|
ResSimNode *node;
|
||||||
int result, idx;
|
int result, idx;
|
||||||
char *devname;
|
char *devname;
|
||||||
Plane *savePlane;
|
Plane *savePlane;
|
||||||
|
|
||||||
ResRDevList = NULL;
|
ResRDevList = NULL;
|
||||||
ResOriginalNodes = NULL;
|
ResOriginalNodes = NULL;
|
||||||
|
|
@ -150,18 +150,18 @@ ExtResisForDef(celldef, resisdata)
|
||||||
idx = 0;
|
idx = 0;
|
||||||
while (ExtGetDevInfo(idx++, &devname, NULL, NULL, NULL, NULL, NULL))
|
while (ExtGetDevInfo(idx++, &devname, NULL, NULL, NULL, NULL, NULL))
|
||||||
{
|
{
|
||||||
if (idx == TT_MAXTYPES)
|
if (idx == TT_MAXTYPES)
|
||||||
{
|
{
|
||||||
TxError("Error: Ran out of space for device types!\n");
|
TxError("Error: Ran out of space for device types!\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, devname);
|
efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, devname);
|
||||||
}
|
}
|
||||||
|
|
||||||
HashInit(&ResNodeTable, INITFLATSIZE, HT_STRINGKEYS);
|
HashInit(&ResNodeTable, INITFLATSIZE, HT_STRINGKEYS);
|
||||||
/* read in .sim file */
|
/* read in .sim file */
|
||||||
result = (ResReadSim(celldef->cd_name,
|
result = (ResReadSim(celldef->cd_name,
|
||||||
ResSimDevice, ResSimCapacitor, ResSimResistor,
|
ResSimDevice, ResSimCapacitor, ResSimResistor,
|
||||||
ResSimAttribute, ResSimMerge, ResSimSubckt) == 0);
|
ResSimAttribute, ResSimMerge, ResSimSubckt) == 0);
|
||||||
|
|
||||||
/* Clean up the EFDevTypes table */
|
/* Clean up the EFDevTypes table */
|
||||||
|
|
@ -212,7 +212,7 @@ ExtResisForDef(celldef, resisdata)
|
||||||
HashKill(&ResNodeTable);
|
HashKill(&ResNodeTable);
|
||||||
while (ResRDevList != NULL)
|
while (ResRDevList != NULL)
|
||||||
{
|
{
|
||||||
oldRDev = ResRDevList;
|
oldRDev = ResRDevList;
|
||||||
ResRDevList = ResRDevList->nextDev;
|
ResRDevList = ResRDevList->nextDev;
|
||||||
if (oldRDev->layout != NULL)
|
if (oldRDev->layout != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -223,7 +223,6 @@ ExtResisForDef(celldef, resisdata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -241,12 +240,13 @@ ExtResisForDef(celldef, resisdata)
|
||||||
|
|
||||||
void
|
void
|
||||||
CmdExtResis(win, cmd)
|
CmdExtResis(win, cmd)
|
||||||
MagWindow *win;
|
MagWindow *win;
|
||||||
TxCommand *cmd;
|
TxCommand *cmd;
|
||||||
{
|
{
|
||||||
int i, j, k, option, value, saveFlags;
|
int i, j, k, option, value, saveFlags;
|
||||||
static int init = 1;
|
static int init = 1;
|
||||||
static float tolerance, tdiTolerance, fhFrequency;
|
static float rthresh, tdiTolerance, fhFrequency;
|
||||||
|
|
||||||
CellDef *mainDef;
|
CellDef *mainDef;
|
||||||
CellUse *selectedUse;
|
CellUse *selectedUse;
|
||||||
ResisData resisdata;
|
ResisData resisdata;
|
||||||
|
|
@ -264,8 +264,9 @@ CmdExtResis(win, cmd)
|
||||||
|
|
||||||
static char *cmdExtresisCmd[] =
|
static char *cmdExtresisCmd[] =
|
||||||
{
|
{
|
||||||
"tolerance [value] set ratio between resistor and device tol.",
|
|
||||||
"all extract all the nets",
|
"all extract all the nets",
|
||||||
|
"threshold [value] set minimum resistor extraction threshold",
|
||||||
|
"tolerance [value] set ratio between resistor and device tol.",
|
||||||
"simplify [on/off] turn on/off simplification of resistor nets",
|
"simplify [on/off] turn on/off simplification of resistor nets",
|
||||||
"extout [on/off] turn on/off writing of .res.ext file",
|
"extout [on/off] turn on/off writing of .res.ext file",
|
||||||
"lumped [on/off] turn on/off writing of updated lumped resistances",
|
"lumped [on/off] turn on/off writing of updated lumped resistances",
|
||||||
|
|
@ -286,8 +287,9 @@ CmdExtResis(win, cmd)
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RES_BAD=-2, RES_AMBIG, RES_TOL,
|
RES_BAD=-2, RES_AMBIG, RES_ALL,
|
||||||
RES_ALL, RES_SIMP, RES_EXTOUT, RES_LUMPED, RES_SILENT,
|
RES_THRESH, RES_TOL,
|
||||||
|
RES_SIMP, RES_EXTOUT, RES_LUMPED, RES_SILENT,
|
||||||
RES_SKIP, RES_IGNORE, RES_INCLUDE, RES_BOX, RES_CELL,
|
RES_SKIP, RES_IGNORE, RES_INCLUDE, RES_BOX, RES_CELL,
|
||||||
RES_BLACKBOX, RES_FASTHENRY, RES_GEOMETRY, RES_HELP,
|
RES_BLACKBOX, RES_FASTHENRY, RES_GEOMETRY, RES_HELP,
|
||||||
#ifdef LAPLACE
|
#ifdef LAPLACE
|
||||||
|
|
@ -303,7 +305,7 @@ typedef enum {
|
||||||
TTMaskZero(&(ResCopyMask[i]));
|
TTMaskZero(&(ResCopyMask[i]));
|
||||||
TTMaskSetMask(&ResCopyMask[i], &DBConnectTbl[i]);
|
TTMaskSetMask(&ResCopyMask[i], &DBConnectTbl[i]);
|
||||||
}
|
}
|
||||||
tolerance = 1;
|
rthresh = 0;
|
||||||
tdiTolerance = 1;
|
tdiTolerance = 1;
|
||||||
fhFrequency = 10e6; /* 10 MHz default */
|
fhFrequency = 10e6; /* 10 MHz default */
|
||||||
HashInit(&ResIgnoreTable, INITFLATSIZE, HT_STRINGKEYS);
|
HashInit(&ResIgnoreTable, INITFLATSIZE, HT_STRINGKEYS);
|
||||||
|
|
@ -350,13 +352,12 @@ typedef enum {
|
||||||
ResOptionsFlags |= ResOpt_ExplicitRtol;
|
ResOptionsFlags |= ResOpt_ExplicitRtol;
|
||||||
if (cmd->tx_argc > 2)
|
if (cmd->tx_argc > 2)
|
||||||
{
|
{
|
||||||
tolerance = MagAtof(cmd->tx_argv[2]);
|
tdiTolerance = MagAtof(cmd->tx_argv[2]);
|
||||||
if (tolerance <= 0)
|
if (tdiTolerance <= 0)
|
||||||
{
|
{
|
||||||
TxError("Usage: %s tolerance [value]\n", cmd->tx_argv[0]);
|
TxError("Usage: %s tolerance [value]\n", cmd->tx_argv[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tdiTolerance = tolerance;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -368,6 +369,26 @@ typedef enum {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case RES_THRESH:
|
||||||
|
if (cmd->tx_argc > 2)
|
||||||
|
{
|
||||||
|
rthresh = MagAtof(cmd->tx_argv[2]);
|
||||||
|
if (rthresh < 0)
|
||||||
|
{
|
||||||
|
TxError("Usage: %s threshold [value]\n", cmd->tx_argv[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
Tcl_SetObjResult(magicinterp, Tcl_NewDoubleObj((double)rthresh));
|
||||||
|
#else
|
||||||
|
TxPrintf("Resistance threshold is %g.\n", rthresh);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
case RES_ALL:
|
case RES_ALL:
|
||||||
ResOptionsFlags |= ResOpt_ExtractAll;
|
ResOptionsFlags |= ResOpt_ExtractAll;
|
||||||
break;
|
break;
|
||||||
|
|
@ -648,7 +669,7 @@ typedef enum {
|
||||||
ResOptionsFlags &= ~ResOpt_Power;
|
ResOptionsFlags &= ~ResOpt_Power;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
resisdata.tolerance = tolerance;
|
resisdata.rthresh = rthresh;
|
||||||
resisdata.tdiTolerance = tdiTolerance;
|
resisdata.tdiTolerance = tdiTolerance;
|
||||||
resisdata.frequency = fhFrequency;
|
resisdata.frequency = fhFrequency;
|
||||||
resisdata.mainDef = mainDef;
|
resisdata.mainDef = mainDef;
|
||||||
|
|
@ -964,13 +985,13 @@ ResCheckSimNodes(celldef, resisdata)
|
||||||
{
|
{
|
||||||
ResSimNode *node;
|
ResSimNode *node;
|
||||||
devPtr *ptr;
|
devPtr *ptr;
|
||||||
float ftolerance, rctolerance, minRes, cumRes;
|
float ftolerance, minRes, cumRes;
|
||||||
int failed1=0;
|
int failed1=0;
|
||||||
int failed3=0;
|
int failed3=0;
|
||||||
int total =0;
|
int total =0;
|
||||||
char *outfile = celldef->cd_name;
|
char *outfile = celldef->cd_name;
|
||||||
float tol = resisdata->tolerance;
|
|
||||||
float rctol = resisdata->tdiTolerance;
|
float rctol = resisdata->tdiTolerance;
|
||||||
|
float rthresh = resisdata->rthresh;
|
||||||
int nidx = 1, eidx = 1; /* node & segment counters for geom. */
|
int nidx = 1, eidx = 1; /* node & segment counters for geom. */
|
||||||
|
|
||||||
if (ResOptionsFlags & ResOpt_DoExtFile)
|
if (ResOptionsFlags & ResOpt_DoExtFile)
|
||||||
|
|
@ -1166,16 +1187,10 @@ ResCheckSimNodes(celldef, resisdata)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
gparams.rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS;
|
gparams.rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS;
|
||||||
if ((rctol == 0.0) || (tol == 0.0))
|
if (minRes > resisdata->rthresh)
|
||||||
{
|
ftolerance = minRes;
|
||||||
ftolerance = 0.0;
|
|
||||||
rctolerance = 0.0;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
ftolerance = resisdata->rthresh;
|
||||||
ftolerance = minRes / tol;
|
|
||||||
rctolerance = minRes / rctol;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is the device resistance greater than the lumped node
|
* Is the device resistance greater than the lumped node
|
||||||
|
|
@ -1201,11 +1216,10 @@ ResCheckSimNodes(celldef, resisdata)
|
||||||
ResWriteLumpFile(node);
|
ResWriteLumpFile(node);
|
||||||
}
|
}
|
||||||
if (gparams.rg_maxres >= ftolerance ||
|
if (gparams.rg_maxres >= ftolerance ||
|
||||||
gparams.rg_maxres >= rctolerance ||
|
|
||||||
(ResOptionsFlags & ResOpt_ExtractAll))
|
(ResOptionsFlags & ResOpt_ExtractAll))
|
||||||
{
|
{
|
||||||
resNodeNum = 0;
|
resNodeNum = 0;
|
||||||
failed3 += ResWriteExtFile(celldef, node, tol, rctol,
|
failed3 += ResWriteExtFile(celldef, node, rctol,
|
||||||
&nidx, &eidx);
|
&nidx, &eidx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1780,10 +1794,10 @@ ResAlignNodes(nodelist, reslist)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
ResWriteExtFile(celldef, node, tol, rctol, nidx, eidx)
|
ResWriteExtFile(celldef, node, rctol, nidx, eidx)
|
||||||
CellDef *celldef;
|
CellDef *celldef;
|
||||||
ResSimNode *node;
|
ResSimNode *node;
|
||||||
float tol, rctol;
|
float rctol;
|
||||||
int *nidx, *eidx;
|
int *nidx, *eidx;
|
||||||
{
|
{
|
||||||
float RCdev;
|
float RCdev;
|
||||||
|
|
@ -1793,7 +1807,7 @@ ResWriteExtFile(celldef, node, tol, rctol, nidx, eidx)
|
||||||
|
|
||||||
RCdev = gparams.rg_bigdevres * gparams.rg_nodecap;
|
RCdev = gparams.rg_bigdevres * gparams.rg_nodecap;
|
||||||
|
|
||||||
if (tol == 0.0 || (node->status & FORCE) ||
|
if ((node->status & FORCE) ||
|
||||||
(ResOptionsFlags & ResOpt_ExtractAll) ||
|
(ResOptionsFlags & ResOpt_ExtractAll) ||
|
||||||
(ResOptionsFlags & ResOpt_Simplify) == 0 ||
|
(ResOptionsFlags & ResOpt_Simplify) == 0 ||
|
||||||
(rctol + 1) * RCdev < rctol * gparams.rg_Tdi)
|
(rctol + 1) * RCdev < rctol * gparams.rg_Tdi)
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ void ResSetPathRes();
|
||||||
void resPathNode();
|
void resPathNode();
|
||||||
void resPathRes();
|
void resPathRes();
|
||||||
Heap ResistorHeap;
|
Heap ResistorHeap;
|
||||||
int resRemoveLoops = FALSE;
|
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
|
|
||||||
|
|
@ -810,10 +809,12 @@ ResPruneTree(node, minTdi, nodelist1, nodelist2, resistorlist)
|
||||||
{
|
{
|
||||||
currentRes = current->re_thisEl;
|
currentRes = current->re_thisEl;
|
||||||
current = current->re_nextEl;
|
current = current->re_nextEl;
|
||||||
/* if branch points outward, call routine on subtrees */
|
/* Ignore previously found loops */
|
||||||
if (currentRes->rr_connection1 == node)
|
if (!(currentRes->rr_status & RES_TDI_IGNORE))
|
||||||
ResPruneTree(currentRes->rr_connection2, minTdi, nodelist1,
|
/* If branch points outward, call routine on subtrees */
|
||||||
nodelist2, resistorlist);
|
if (currentRes->rr_connection1 == node)
|
||||||
|
ResPruneTree(currentRes->rr_connection2, minTdi, nodelist1,
|
||||||
|
nodelist2, resistorlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We eliminate this branch if:
|
/* We eliminate this branch if:
|
||||||
|
|
@ -863,7 +864,6 @@ ResDoSimplify(tolerance, rctol, goodies)
|
||||||
float totalcap;
|
float totalcap;
|
||||||
resResistor *res;
|
resResistor *res;
|
||||||
|
|
||||||
resRemoveLoops = FALSE;
|
|
||||||
ResSetPathRes();
|
ResSetPathRes();
|
||||||
for (node = ResNodeList; node != NULL; node = node->rn_more)
|
for (node = ResNodeList; node != NULL; node = node->rn_more)
|
||||||
bigres = MAX(bigres, node->rn_noderes);
|
bigres = MAX(bigres, node->rn_noderes);
|
||||||
|
|
@ -893,12 +893,16 @@ ResDoSimplify(tolerance, rctol, goodies)
|
||||||
|
|
||||||
res = res->rr_nextResistor;
|
res = res->rr_nextResistor;
|
||||||
oldres->rr_status &= ~RES_HEAP;
|
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)
|
if (oldres->rr_status & RES_TDI_IGNORE)
|
||||||
{
|
{
|
||||||
ResDeleteResPointer(oldres->rr_node[0], oldres);
|
ResDeleteResPointer(oldres->rr_node[0], oldres);
|
||||||
ResDeleteResPointer(oldres->rr_node[1], oldres);
|
ResDeleteResPointer(oldres->rr_node[1], oldres);
|
||||||
ResEliminateResistor(oldres, &ResResList);
|
ResEliminateResistor(oldres, &ResResList);
|
||||||
}
|
}
|
||||||
|
------*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ResOptionsFlags & ResOpt_Tdi)
|
if (ResOptionsFlags & ResOpt_Tdi)
|
||||||
|
|
@ -1045,7 +1049,12 @@ ResSetPathRes()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
|
* resPathNode ---
|
||||||
*
|
*
|
||||||
|
* Given node "node", add every resistor connected to the node, and
|
||||||
|
* for which the node on the other side has not been processed, to
|
||||||
|
* the heap. Node is marked with FINISHED to prevent going 'round
|
||||||
|
* and 'round loops.
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -1073,6 +1082,18 @@ resPathNode(node)
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
* resPathRes ---
|
||||||
|
*
|
||||||
|
* Given resistor "res" pulled from the heap (in heap order, which
|
||||||
|
* is the highest valued resistor currently in the heap):
|
||||||
|
*
|
||||||
|
* If both ends of the resistor have been processed, then we have
|
||||||
|
* a loop, and should return.
|
||||||
|
*
|
||||||
|
* Otherwise, call resPathNode() on the node of whichever end of
|
||||||
|
* the resistor has not yet been processed, thus continuing through
|
||||||
|
* the path from the origin.
|
||||||
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -1093,12 +1114,7 @@ resPathRes(res)
|
||||||
if (flag0 && flag1)
|
if (flag0 && flag1)
|
||||||
{
|
{
|
||||||
res->rr_status |= RES_TDI_IGNORE;
|
res->rr_status |= RES_TDI_IGNORE;
|
||||||
if (resRemoveLoops)
|
/* Loop found---return without calling resPathNode() */
|
||||||
{
|
|
||||||
ResDeleteResPointer(node0, res);
|
|
||||||
ResDeleteResPointer(node1, res);
|
|
||||||
ResEliminateResistor(res, &ResResList);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (flag0)
|
else if (flag0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue