Final work on the first stage of the extresist overhaul. The

"extresist" command continues to work as before.  However, the
method now reads from .ext files instead of .sim files, so
generating ".sim" and ".nodes" files is no longer necessary.
In addition, the core code of "extresist" was put directly into
ExtCell.c so that full R-C extraction can be run using
"extract do resistance" followed by "extract all", without
needing to run "extresist" at all other than to set parameters
(e.g., "extresist tolerance 10").
This commit is contained in:
R. Timothy Edwards 2026-01-28 14:31:38 -05:00
parent 76f97c90e5
commit 57c33c48c7
16 changed files with 687 additions and 841 deletions

View File

@ -35,9 +35,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "dbwind/dbwind.h" /* for DBWclientID */ #include "dbwind/dbwind.h" /* for DBWclientID */
#include "commands/commands.h" /* for module auto-load */ #include "commands/commands.h" /* for module auto-load */
#include "textio/txcommands.h" #include "textio/txcommands.h"
#include "extract/extract.h" /* for extDevTable */
#include "extflat/extflat.h" #include "extflat/extflat.h"
#include "extflat/EFint.h" #include "extflat/EFint.h"
#include "extract/extract.h" /* for extDevTable */
#include "utils/runstats.h" #include "utils/runstats.h"
#include "utils/malloc.h" #include "utils/malloc.h"

View File

@ -41,14 +41,11 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "commands/commands.h" /* for module auto-load */ #include "commands/commands.h" /* for module auto-load */
#include "textio/txcommands.h" #include "textio/txcommands.h"
#include "extflat/extflat.h" #include "extflat/extflat.h"
#include "extflat/EFint.h"
#include "extract/extract.h" /* for extDevTable */ #include "extract/extract.h" /* for extDevTable */
#include "extflat/EFint.h"
#include "utils/runstats.h" #include "utils/runstats.h"
#include "ext2spice/ext2spice.h" #include "ext2spice/ext2spice.h"
/* C99 compat */
#include "extflat/extflat.h"
/* These global values are defined in ext2spice.c */ /* These global values are defined in ext2spice.c */
extern HashTable subcktNameTable; extern HashTable subcktNameTable;
extern DQueue subcktNameQueue; extern DQueue subcktNameQueue;

View File

@ -38,9 +38,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
#include "dbwind/dbwind.h" /* for DBWclientID */ #include "dbwind/dbwind.h" /* for DBWclientID */
#include "commands/commands.h" /* for module auto-load */ #include "commands/commands.h" /* for module auto-load */
#include "textio/txcommands.h" #include "textio/txcommands.h"
#include "extract/extract.h" /* for extDevTable */
#include "extflat/extflat.h" #include "extflat/extflat.h"
#include "extflat/EFint.h" #include "extflat/EFint.h"
#include "extract/extract.h" /* for extDevTable */
#include "utils/runstats.h" #include "utils/runstats.h"
#include "ext2spice/ext2spice.h" #include "ext2spice/ext2spice.h"

View File

@ -34,8 +34,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header$";
#include "tiles/tile.h" #include "tiles/tile.h"
#include "database/database.h" /* for TileType definition */ #include "database/database.h" /* for TileType definition */
#include "extflat/extflat.h" #include "extflat/extflat.h"
#include "extflat/extparse.h"
#include "extflat/EFint.h" #include "extflat/EFint.h"
#include "extract/extract.h" /* for device class list */ #include "extract/extract.h"
#include "extract/extractInt.h" /* for extGetDevType() */ #include "extract/extractInt.h" /* for extGetDevType() */
/* C99 compat */ /* C99 compat */

View File

@ -36,9 +36,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/magic.h" #include "utils/magic.h"
#include "utils/geometry.h" #include "utils/geometry.h"
#include "textio/textio.h" #include "textio/textio.h"
#include "extflat/extparse.h"
extern char *efReadFileName;
extern int efReadLineNum;
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
extern int Tcl_printf(); extern int Tcl_printf();

View File

@ -46,6 +46,14 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
/* C99 compat */ /* C99 compat */
#include "textio/textio.h" #include "textio/textio.h"
#ifndef MAGIC_WRAPPER
/* This must match the definition for extDevTable in extract/ExtBasic.c */
const char * const extDevTable[] = {"fet", "mosfet", "asymmetric", "bjt", "devres",
"devcap", "devcaprev", "vsource", "diode", "pdiode",
"ndiode", "subckt", "rsubckt", "msubckt", "csubckt",
"dsubckt", "veriloga", NULL};
#endif
/* Data shared with EFerror.c */ /* Data shared with EFerror.c */
char *efReadFileName; /* Name of file currently being read */ char *efReadFileName; /* Name of file currently being read */
int efReadLineNum; /* Current line number in above file */ int efReadLineNum; /* Current line number in above file */

View File

@ -27,7 +27,6 @@
#include "extflat/EFtypes.h" /* EFCapValue, HierName, EFPerimArea, EFNode */ #include "extflat/EFtypes.h" /* EFCapValue, HierName, EFPerimArea, EFNode */
#include "extflat/EFint.h" /* Def, HierContext, Connection, Distance, CallArg */ #include "extflat/EFint.h" /* Def, HierContext, Connection, Distance, CallArg */
extern float EFScale; /* Scale factor to multiply all coords by */ extern float EFScale; /* Scale factor to multiply all coords by */
extern char *EFTech; /* Technology of extracted circuit */ extern char *EFTech; /* Technology of extracted circuit */
extern char *EFStyle; /* Extraction style of extracted circuit */ extern char *EFStyle; /* Extraction style of extracted circuit */

View File

@ -16,19 +16,8 @@
* ********************************************************************* * *********************************************************************
*/ */
/* These must be in the order of "known devices" in extract/extract.h. */ #ifndef _MAGIC__EXTFLAT__EXTPARSE_H
/* This table is also used in extract/ExtBasic.c */ #define _MAGIC__EXTFLAT__EXTPARSE_H
/* Note: "fet" refers to the original fet type; "mosfet" refers to the */
/* new type. The main difference is that "fet" records area/perimeter */
/* while "mosfet" records length/width. */
#ifndef MAGIC_WRAPPER
const char * const extDevTable[] = {"fet", "mosfet", "asymmetric", "bjt", "devres",
"devcap", "devcaprev", "vsource", "diode", "pdiode",
"ndiode", "subckt", "rsubckt", "msubckt", "csubckt",
"dsubckt", "veriloga", NULL};
#endif
/* /*
* The following table describes the kinds of lines * The following table describes the kinds of lines
@ -80,5 +69,7 @@ keyTable[] =
/* atoCap - convert a string to a EFCapValue */ /* atoCap - convert a string to a EFCapValue */
#define atoCap(s) ((EFCapValue)atof(s)) #define atoCap(s) ((EFCapValue)atof(s))
extern int efReadLineNum; /* Current line number in the .ext file */ extern int efReadLineNum; /* Current line number in the .ext file */
extern char *efReadFileName; /* Name of current .ext file being read */
#endif /* _MAGIC__EXTFLAT__EXTPARSE_H */

View File

@ -46,7 +46,20 @@ static char sccsid[] = "@(#)ExtBasic.c 4.13 MAGIC (Berkeley) 12/5/85";
#include "utils/styles.h" #include "utils/styles.h"
#include "utils/stack.h" #include "utils/stack.h"
#include "utils/utils.h" #include "utils/utils.h"
#include "resis/resis.h"
/* These must be in the order of "known devices" in extract.h. */
/* Note: "fet" refers to the original fet type; "mosfet" refers to the */
/* new type. The main difference is that "fet" records area/perimeter */
/* while "mosfet" records length/width. */
/* Also: Note that this table is repeated in extflat/EFread.c when */
/* ext2spice/ext2sim are compiled as separate programs (i.e., non-Tcl) */
#ifdef MAGIC_WRAPPER
const char * const extDevTable[] = {"fet", "mosfet", "asymmetric", "bjt", "devres",
"devcap", "devcaprev", "vsource", "diode", "pdiode", "ndiode",
"subckt", "rsubckt", "msubckt", "csubckt", "dsubckt", "veriloga", NULL};
#endif
/* --------------------- Data local to this file ---------------------- */ /* --------------------- Data local to this file ---------------------- */
@ -546,24 +559,6 @@ extBasic(def, outFile)
extOutputDevices(def, transList, outFile); extOutputDevices(def, transList, outFile);
} }
/* Integrated extresist --- Run "extresist" on the cell def just
* extracted and produce an annotation file "<file>.res.ext".
*/
if (ExtOptions & EXT_DOEXTRESIST)
{
ResisData resisdata;
/* These need to be passed to extresist somehow. Most are unused. */
resisdata.rthresh = 0;
resisdata.tdiTolerance = 1;
resisdata.frequency = 10e6;
resisdata.mainDef = def;
resisdata.savePlanes = (struct saveList *)NULL; /* unused */
ExtResisForDef(def, &resisdata);
}
/* Clean up */ /* Clean up */
if (coupleInitialized) if (coupleInitialized)
extCapHashKill(&extCoupleHash); extCapHashKill(&extCoupleHash);
@ -5000,9 +4995,12 @@ extFindNodes(def, clipArea, subonly)
/* If the default substrate type is set, it is used *only* for */ /* If the default substrate type is set, it is used *only* for */
/* isolated substrate regions and does not mark the default */ /* isolated substrate regions and does not mark the default */
/* substrate, so remove it from the list of substrate types. */ /* substrate, so remove it from the list of substrate types. */
/* Note that this is not the case when doing full R-C */
/* extraction. */
if (ExtCurStyle->exts_globSubstrateDefaultType != -1) if (!(ExtOptions & EXT_DOEXTRESIST))
TTMaskClearType(&subsTypesNonSpace, if (ExtCurStyle->exts_globSubstrateDefaultType != -1)
TTMaskClearType(&subsTypesNonSpace,
ExtCurStyle->exts_globSubstrateDefaultType); ExtCurStyle->exts_globSubstrateDefaultType);
pNum = ExtCurStyle->exts_globSubstratePlane; pNum = ExtCurStyle->exts_globSubstratePlane;

View File

@ -39,6 +39,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "debug/debug.h" #include "debug/debug.h"
#include "extract/extract.h" #include "extract/extract.h"
#include "extract/extractInt.h" #include "extract/extractInt.h"
#include "resis/resis.h"
#include "utils/signals.h" #include "utils/signals.h"
#include "utils/stack.h" #include "utils/stack.h"
#include "utils/utils.h" #include "utils/utils.h"
@ -115,6 +116,25 @@ ExtCell(def, outName, doLength)
savePlane = extCellFile(def, f, doLength); savePlane = extCellFile(def, f, doLength);
if (f != NULL) fclose(f); if (f != NULL) fclose(f);
/* Integrated extresist --- Run "extresist" on the cell def just
* extracted and produce an annotation file "<file>.res.ext".
*/
if (ExtOptions & EXT_DOEXTRESIST)
{
ResisData *resisdata = ResInit();
UndoDisable();
ResOptionsFlags |= ResOpt_Signal;
resisdata->mainDef = def;
resisdata->savePlanes = (struct saveList *)NULL; /* unused */
ExtResisForDef(def, resisdata);
UndoEnable();
}
if (extNumErrors > 0 || extNumWarnings > 0) if (extNumErrors > 0 || extNumWarnings > 0)
{ {
TxPrintf("%s:", def->cd_name); TxPrintf("%s:", def->cd_name);
@ -493,7 +513,10 @@ extCellFile(def, f, doLength)
extUniqueCell(def, EXT_UNIQ_TEMP); extUniqueCell(def, EXT_UNIQ_TEMP);
/* Prep any isolated substrate areas */ /* Prep any isolated substrate areas */
saveSub = extPrepSubstrate(def); if (ExtOptions & EXT_DOEXTRESIST)
saveSub = extResPrepSubstrate(def);
else
saveSub = extPrepSubstrate(def);
/* Remove any label markers that were made by a previous extraction */ /* Remove any label markers that were made by a previous extraction */
for (lab = def->cd_labels; lab; lab = lab->lab_next) for (lab = def->cd_labels; lab; lab = lab->lab_next)

View File

@ -273,9 +273,9 @@ ResMakePortBreakpoints(def)
*---------------------------------------------------------------------------- *----------------------------------------------------------------------------
*/ */
void void
ResMakeLabelBreakpoints(def, goodies) ResMakeLabelBreakpoints(def, resisdata)
CellDef *def; CellDef *def;
ResGlobalParams *goodies; ResisData *resisdata;
{ {
Plane *plane; Plane *plane;
Rect *rect; Rect *rect;
@ -294,12 +294,12 @@ ResMakeLabelBreakpoints(def, goodies)
entry = HashFind(&ResNodeTable, slab->lab_text); entry = HashFind(&ResNodeTable, slab->lab_text);
node = ResInitializeNode(entry); node = ResInitializeNode(entry);
/* If the drivepoint position changes and the drivepoint is */ /* If the drivepoint position changes and the drivepoint is */
/* in the "goodies" record, then make sure the tile type in */ /* in the "resisdata" record, then make sure the tile type */
/* "goodies" gets changed to match. */ /* in "resisdata" gets changed to match. */
if (goodies->rg_devloc == &node->drivepoint) if (resisdata->rg_devloc == &node->drivepoint)
goodies->rg_ttype = slab->lab_type; resisdata->rg_ttype = slab->lab_type;
node->drivepoint = slab->lab_rect.r_ll; node->drivepoint = slab->lab_rect.r_ll;
node->rs_bbox = slab->lab_rect; node->rs_bbox = slab->lab_rect;
@ -490,9 +490,9 @@ ResFindNewContactTiles(contacts)
*/ */
int int
ResProcessTiles(goodies, origin) ResProcessTiles(resisdata, origin)
Point *origin; Point *origin;
ResGlobalParams *goodies; ResisData *resisdata;
{ {
Tile *startTile; Tile *startTile;
@ -506,7 +506,7 @@ ResProcessTiles(goodies, origin)
if (ResOptionsFlags & ResOpt_Signal) if (ResOptionsFlags & ResOpt_Signal)
{ {
startTile = FindStartTile(goodies, origin); startTile = FindStartTile(resisdata, origin);
if (startTile == NULL) if (startTile == NULL)
return 1; return 1;
resCurrentNode = NULL; resCurrentNode = NULL;
@ -990,9 +990,9 @@ ResShaveContacts(tile, dinfo, def)
*/ */
bool bool
ResExtractNet(node, goodies, cellname) ResExtractNet(node, resisdata, cellname)
ResExtNode *node; ResExtNode *node;
ResGlobalParams *goodies; ResisData *resisdata;
char *cellname; char *cellname;
{ {
SearchContext scx; SearchContext scx;
@ -1018,8 +1018,8 @@ ResExtractNet(node, goodies, cellname)
/* Pass back network pointers */ /* Pass back network pointers */
goodies->rg_maxres = 0; resisdata->rg_maxres = 0;
goodies->rg_tilecount = 0; resisdata->rg_tilecount = 0;
/* Set up internal stuff if this is the first time through */ /* Set up internal stuff if this is the first time through */
@ -1102,10 +1102,10 @@ ResExtractNet(node, goodies, cellname)
resMakeDevFunc, (ClientData)thisDev); resMakeDevFunc, (ClientData)thisDev);
if (result == 0) if (result == 0)
{ {
TxError("No device of type %s found at location %d,%d\n", TxError("No device of type %s found at location %s, %s\n",
DBTypeLongNameTbl[thisDev->type], DBTypeLongNameTbl[thisDev->type],
tptr->thisDev->location.p_x, DBWPrintValue(tptr->thisDev->location.p_x, (MagWindow*)NULL, TRUE),
tptr->thisDev->location.p_y); DBWPrintValue(tptr->thisDev->location.p_y, (MagWindow*)NULL, FALSE));
freeMagic(thisDev); freeMagic(thisDev);
continue; continue;
} }
@ -1185,12 +1185,12 @@ ResExtractNet(node, goodies, cellname)
/* Finish preprocessing. */ /* Finish preprocessing. */
ResMakePortBreakpoints(ResUse->cu_def); ResMakePortBreakpoints(ResUse->cu_def);
ResMakeLabelBreakpoints(ResUse->cu_def, goodies); ResMakeLabelBreakpoints(ResUse->cu_def, resisdata);
ResFindNewContactTiles(ResContactList); ResFindNewContactTiles(ResContactList);
ResPreProcessDevices(DevTiles, ResDevList, ResUse->cu_def); ResPreProcessDevices(DevTiles, ResDevList, ResUse->cu_def);
/* do extraction */ /* do extraction */
if (ResProcessTiles(goodies, &startpoint) != 0) return TRUE; if (ResProcessTiles(resisdata, &startpoint) != 0) return TRUE;
return FALSE; return FALSE;
} }
@ -1323,10 +1323,9 @@ ResGetTileFunc(tile, dinfo, tpptr)
*/ */
Tile * Tile *
FindStartTile(goodies, SourcePoint) FindStartTile(resisdata, SourcePoint)
ResisData *resisdata;
Point *SourcePoint; Point *SourcePoint;
ResGlobalParams *goodies;
{ {
Point workingPoint; Point workingPoint;
Tile *tile, *tp; Tile *tile, *tp;
@ -1339,39 +1338,39 @@ FindStartTile(goodies, SourcePoint)
/* If the drive point is on a contact, check for the contact residues */ /* If the drive point is on a contact, check for the contact residues */
/* first, then the contact type itself. */ /* first, then the contact type itself. */
if (DBIsContact(goodies->rg_ttype)) if (DBIsContact(resisdata->rg_ttype))
{ {
TileTypeBitMask *rmask = DBResidueMask(goodies->rg_ttype); TileTypeBitMask *rmask = DBResidueMask(resisdata->rg_ttype);
TileType savtype = goodies->rg_ttype; TileType savtype = resisdata->rg_ttype;
TileType rtype; TileType rtype;
for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++) for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++)
if (TTMaskHasType(rmask, rtype)) if (TTMaskHasType(rmask, rtype))
{ {
goodies->rg_ttype = rtype; resisdata->rg_ttype = rtype;
if ((tile = FindStartTile(goodies, SourcePoint)) != NULL) if ((tile = FindStartTile(resisdata, SourcePoint)) != NULL)
{ {
goodies->rg_ttype = savtype; resisdata->rg_ttype = savtype;
return tile; return tile;
} }
} }
goodies->rg_ttype = savtype; resisdata->rg_ttype = savtype;
} }
workingPoint.p_x = goodies->rg_devloc->p_x; workingPoint.p_x = resisdata->rg_devloc->p_x;
workingPoint.p_y = goodies->rg_devloc->p_y; workingPoint.p_y = resisdata->rg_devloc->p_y;
pnum = DBPlane(goodies->rg_ttype); pnum = DBPlane(resisdata->rg_ttype);
/* for drivepoints, we don't have to find a device */ /* for drivepoints, we don't have to find a device */
if (goodies->rg_status & DRIVEONLY) if (resisdata->rg_status & DRIVEONLY)
{ {
tile = PlaneGetHint(ResUse->cu_def->cd_planes[pnum]); tile = PlaneGetHint(ResUse->cu_def->cd_planes[pnum]);
GOTOPOINT(tile, &workingPoint); GOTOPOINT(tile, &workingPoint);
SourcePoint->p_x = workingPoint.p_x; SourcePoint->p_x = workingPoint.p_x;
SourcePoint->p_y = workingPoint.p_y; SourcePoint->p_y = workingPoint.p_y;
if (TiGetTypeExact(tile) == goodies->rg_ttype) if (TiGetTypeExact(tile) == resisdata->rg_ttype)
return tile; return tile;
else else
{ {
@ -1383,18 +1382,19 @@ FindStartTile(goodies, SourcePoint)
if (workingPoint.p_x == LEFT(tile)) if (workingPoint.p_x == LEFT(tile))
{ {
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp)) for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp))
if (TiGetRightType(tp) == goodies->rg_ttype) if (TiGetRightType(tp) == resisdata->rg_ttype)
return(tp); return(tp);
} }
else if (workingPoint.p_y == BOTTOM(tile)) else if (workingPoint.p_y == BOTTOM(tile))
{ {
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp)) for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp))
if (TiGetTopType(tp) == goodies->rg_ttype) if (TiGetTopType(tp) == resisdata->rg_ttype)
return(tp); return(tp);
} }
} }
TxError("Couldn't find wire at %d %d\n", TxError("Couldn't find wire at %s %s\n",
goodies->rg_devloc->p_x, goodies->rg_devloc->p_y); DBWPrintValue(resisdata->rg_devloc->p_x, (MagWindow *)NULL, TRUE),
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow *)NULL, FALSE));
return NULL; return NULL;
} }
@ -1409,15 +1409,17 @@ FindStartTile(goodies, SourcePoint)
t1 = TiGetRightType(tile); t1 = TiGetRightType(tile);
else else
{ {
TxError("Couldn't find device at %d %d\n", TxError("Couldn't find device at %s %s\n",
goodies->rg_devloc->p_x, goodies->rg_devloc->p_y); DBWPrintValue(resisdata->rg_devloc->p_x, (MagWindow *)NULL, TRUE),
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow *)NULL, FALSE));
return(NULL); return(NULL);
} }
} }
else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetType(tile)) == 0) else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetType(tile)) == 0)
{ {
TxError("Couldn't find device at %d %d\n", TxError("Couldn't find device at %s %s\n",
goodies->rg_devloc->p_x, goodies->rg_devloc->p_y); DBWPrintValue(resisdata->rg_devloc->p_x, (MagWindow *)NULL, TRUE),
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow *)NULL, FALSE));
return(NULL); return(NULL);
} }
else else
@ -1708,8 +1710,9 @@ FindStartTile(goodies, SourcePoint)
/* Didn't find a terminal (S/D or substrate) type tile anywhere. Flag an error. */ /* Didn't find a terminal (S/D or substrate) type tile anywhere. Flag an error. */
if (devptr == NULL) if (devptr == NULL)
TxError("Couldn't find a terminal of the device at %d %d\n", TxError("Couldn't find a terminal of the device at %s %s\n",
goodies->rg_devloc->p_x, goodies->rg_devloc->p_y); DBWPrintValue(resisdata->rg_devloc->p_x, (MagWindow*)NULL, TRUE),
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow*)NULL, FALSE));
return((Tile *) NULL); return((Tile *) NULL);
} }

View File

@ -17,6 +17,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "database/database.h" #include "database/database.h"
#include "utils/malloc.h" #include "utils/malloc.h"
#include "textio/textio.h" #include "textio/textio.h"
#include "extflat/extparse.h"
#include "extract/extract.h" #include "extract/extract.h"
#include "extract/extractInt.h" #include "extract/extractInt.h"
#include "windows/windows.h" #include "windows/windows.h"
@ -175,13 +176,13 @@ ResPrintExtDev(outextfile, devices)
fprintf(outextfile, " \"%s\" %d %s", fprintf(outextfile, " \"%s\" %d %s",
devices->gate->name, devices->gate->name,
devices->layout->rd_length * 2, devices->layout->rd_length * 2,
devices->rs_gattr); (*devices->rs_gattr == '\0') ? "0" : devices->rs_gattr);
if (devices->source != NULL) if (devices->source != NULL)
fprintf(outextfile, " \"%s\" %d %s", fprintf(outextfile, " \"%s\" %d %s",
devices->source->name, devices->source->name,
devices->layout->rd_width, devices->layout->rd_width,
devices->rs_sattr); (*devices->rs_sattr == '\0') ? "0" : devices->rs_sattr);
/* Don't write drain values for 2-terminal devices */ /* Don't write drain values for 2-terminal devices */
if (devptr->exts_deviceSDCount > 1) if (devptr->exts_deviceSDCount > 1)
@ -189,7 +190,7 @@ ResPrintExtDev(outextfile, devices)
fprintf(outextfile, " \"%s\" %d %s", fprintf(outextfile, " \"%s\" %d %s",
devices->drain->name, devices->drain->name,
devices->layout->rd_width, devices->layout->rd_width,
devices->rs_dattr); (*devices->rs_dattr == '\0') ? "0" : devices->rs_dattr);
fprintf(outextfile, "\n"); fprintf(outextfile, "\n");
} }
@ -290,6 +291,13 @@ ResPrintExtNode(outextfile, nodelist, node)
if (NeedFix) if (NeedFix)
{ {
if (nodelist == NULL)
{
TxError("Error: Orphaned node \"%s\" not output.\n",
node->name);
return;
}
/* Patch up the output netlist for an orphaned node by /* Patch up the output netlist for an orphaned node by
* creating a zero-valued resistance between it and the * creating a zero-valued resistance between it and the
* first subnode (arbitrary connection). Flag a warning. * first subnode (arbitrary connection). Flag a warning.
@ -316,16 +324,16 @@ ResPrintExtNode(outextfile, nodelist, node)
*/ */
void void
ResPrintStats(goodies, name) ResPrintStats(resisdata, name)
ResGlobalParams *goodies; ResisData *resisdata;
char *name; char *name;
{ {
static int totalnets = 0, totalnodes = 0, totalresistors = 0; static int totalnets = 0, totalnodes = 0, totalresistors = 0;
int nodes, resistors; int nodes, resistors;
resNode *node; resNode *node;
resResistor *res; resResistor *res;
if (goodies == NULL) if (resisdata == NULL)
{ {
TxError("nets:%d nodes:%d resistors:%d\n", TxError("nets:%d nodes:%d resistors:%d\n",
totalnets, totalnodes, totalresistors); totalnets, totalnodes, totalresistors);

File diff suppressed because it is too large Load Diff

View File

@ -57,12 +57,10 @@ HashTable ResProcessedTable;
HashTable ResNodeTable; /* Hash table of ext file nodes */ HashTable ResNodeTable; /* Hash table of ext file nodes */
RDev *ResRDevList; /* Linked list of Ext devices */ RDev *ResRDevList; /* Linked list of Ext devices */
ResGlobalParams gparams; /* Junk passed between */
/* ResCheckExtNodes and */
/* ResExtractNet. */
extern ResExtNode *ResOriginalNodes; /*Linked List of Nodes */
int resNodeNum; int resNodeNum;
extern ResExtNode *ResOriginalNodes; /*Linked List of Nodes */
int ResOptionsFlags = ResOpt_Simplify | ResOpt_Tdi | ResOpt_DoExtFile; int ResOptionsFlags = ResOpt_Simplify | ResOpt_Tdi | ResOpt_DoExtFile;
char *ResCurrentNode; char *ResCurrentNode;
@ -98,27 +96,10 @@ ExtResisForDef(celldef, resisdata)
ResExtNode *node; ResExtNode *node;
int result, idx; int result, idx;
char *devname; char *devname;
Plane *savePlane;
ResRDevList = NULL; ResRDevList = NULL;
ResOriginalNodes = NULL; ResOriginalNodes = NULL;
/* Check if this cell has been processed */
if (HashLookOnly(&ResProcessedTable, celldef->cd_name)) return;
HashFind(&ResProcessedTable, celldef->cd_name);
/* Prepare the substrate for resistance extraction */
savePlane = extResPrepSubstrate(celldef);
if (savePlane != NULL)
{
struct saveList *newsl;
newsl = (struct saveList *)mallocMagic(sizeof(struct saveList));
newsl->sl_plane = savePlane;
newsl->sl_def = celldef;
newsl->sl_next = resisdata->savePlanes;
resisdata->savePlanes = newsl;
}
/* Get device information from the current extraction style */ /* Get device information from the current extraction style */
idx = 0; idx = 0;
while (ExtGetDevInfo(idx++, &devname, NULL, NULL, NULL, NULL, NULL)) while (ExtGetDevInfo(idx++, &devname, NULL, NULL, NULL, NULL, NULL))
@ -139,17 +120,11 @@ ExtResisForDef(celldef, resisdata)
for (idx = 0; idx < EFDevNumTypes; idx++) freeMagic(EFDevTypes[idx]); for (idx = 0; idx < EFDevNumTypes; idx++) freeMagic(EFDevTypes[idx]);
EFDevNumTypes = 0; EFDevNumTypes = 0;
if (result)
/* read in .nodes file */
result = (ResReadNode(celldef->cd_name) == 0);
if (result) if (result)
{ {
/* Check for subcircuit ports */ /* Check for subcircuit ports */
if (ResOptionsFlags & ResOpt_Blackbox) if (ResOptionsFlags & ResOpt_Blackbox)
ResCheckBlackbox(celldef); ResCheckBlackbox(celldef);
else
ResCheckPorts(celldef);
/* Extract networks for nets that require it. */ /* Extract networks for nets that require it. */
if (!(ResOptionsFlags & ResOpt_FastHenry) || if (!(ResOptionsFlags & ResOpt_FastHenry) ||
@ -157,7 +132,7 @@ ExtResisForDef(celldef, resisdata)
ResCheckExtNodes(celldef, resisdata); ResCheckExtNodes(celldef, resisdata);
if (ResOptionsFlags & ResOpt_Stat) if (ResOptionsFlags & ResOpt_Stat)
ResPrintStats((ResGlobalParams *)NULL, ""); ResPrintStats((ResisData *)NULL, "");
} }
/* Clean up */ /* Clean up */
@ -197,13 +172,74 @@ ExtResisForDef(celldef, resisdata)
/* /*
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
* *
* CmdExtResis-- reads in ext file and layout, and produces patches to the * ResInit --
* .ext files that include resistors. *
* Initialize data and hash tables for running "extresist".
*
* Results:
* Returns a pointer to an allocated ResisData structure. This
* structure is static and may be modified by repeated execution
* of "extresist" commands.
*
* Side effects:
* Allocates memory for the ResisData structure.
*
*-------------------------------------------------------------------------
*/
ResisData *
ResInit()
{
static ResisData *resisdata;
static int init = 1; /* Ensure initialization is done only once */
int i;
if (init)
{
resisdata = (ResisData *)mallocMagic(sizeof(ResisData));
for (i = 0; i < NT; i++)
{
TTMaskZero(&(ResCopyMask[i]));
TTMaskSetMask(&ResCopyMask[i], &DBConnectTbl[i]);
}
resisdata->rthresh = 0;
resisdata->tdiTolerance = 1;
resisdata->frequency = 10e6; /* 10 MHz default */
HashInit(&ResIgnoreTable, INITFLATSIZE, HT_STRINGKEYS);
HashInit(&ResIncludeTable, INITFLATSIZE, HT_STRINGKEYS);
init = 0;
}
/* Reset global parameters */
resisdata->rg_ttype = TT_SPACE;
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;
resisdata->rg_name = NULL;
return resisdata;
}
/*
*-------------------------------------------------------------------------
*
* CmdExtResis--
*
* Reads in a .ext file and layout, and produces patches to the
* .ext files that include resistors and subnets.
* *
* Results: * Results:
* None. * None.
* *
* Side Effects: Produces .res.ext file for all nets that require resistors. * Side Effects:
* Produces a .res.ext file with all nets that require subdivision
* into resistive segments.
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -214,12 +250,11 @@ CmdExtResis(win, cmd)
TxCommand *cmd; TxCommand *cmd;
{ {
int i, j, k, option, value, saveFlags; int i, j, k, option, value, saveFlags;
static int init = 1;
static float rthresh, tdiTolerance, fhFrequency;
CellDef *mainDef; CellDef *mainDef;
CellUse *selectedUse; CellUse *selectedUse;
ResisData resisdata; ResisData *resisdata;
Plane *savePlane;
char *endptr; /* for use with strtod() */ char *endptr; /* for use with strtod() */
struct saveList *sl; struct saveList *sl;
@ -262,31 +297,7 @@ typedef enum {
RES_RUN RES_RUN
} ResOptions; } ResOptions;
if (init) resisdata = ResInit();
{
for (i = 0; i < NT; i++)
{
TTMaskZero(&(ResCopyMask[i]));
TTMaskSetMask(&ResCopyMask[i], &DBConnectTbl[i]);
}
rthresh = 0;
tdiTolerance = 1;
fhFrequency = 10e6; /* 10 MHz default */
HashInit(&ResIgnoreTable, INITFLATSIZE, HT_STRINGKEYS);
HashInit(&ResIncludeTable, INITFLATSIZE, HT_STRINGKEYS);
init = 0;
}
/* Initialize ResGlobalParams */
gparams.rg_ttype = TT_SPACE;
gparams.rg_Tdi = 0.0;
gparams.rg_nodecap = 0.0;
gparams.rg_maxres = 0.0;
gparams.rg_bigdevres = 0;
gparams.rg_tilecount = 0;
gparams.rg_status = 0;
gparams.rg_devloc = NULL;
gparams.rg_name = NULL;
option = (cmd->tx_argc > 1) ? Lookup(cmd->tx_argv[1], cmdExtresisCmd) option = (cmd->tx_argc > 1) ? Lookup(cmd->tx_argv[1], cmdExtresisCmd)
: RES_RUN; : RES_RUN;
@ -316,8 +327,8 @@ typedef enum {
ResOptionsFlags |= ResOpt_ExplicitRtol; ResOptionsFlags |= ResOpt_ExplicitRtol;
if (cmd->tx_argc > 2) if (cmd->tx_argc > 2)
{ {
tdiTolerance = MagAtof(cmd->tx_argv[2]); resisdata->tdiTolerance = MagAtof(cmd->tx_argv[2]);
if (tdiTolerance <= 0) if (resisdata->tdiTolerance <= 0)
{ {
TxError("Usage: %s tolerance [value]\n", cmd->tx_argv[0]); TxError("Usage: %s tolerance [value]\n", cmd->tx_argv[0]);
return; return;
@ -326,9 +337,10 @@ typedef enum {
else else
{ {
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewDoubleObj((double)tdiTolerance)); Tcl_SetObjResult(magicinterp,
Tcl_NewDoubleObj((double)resisdata->tdiTolerance));
#else #else
TxPrintf("Tolerance ratio is %g.\n", tdiTolerance); TxPrintf("Tolerance ratio is %g.\n", resisdata->tdiTolerance);
#endif #endif
} }
return; return;
@ -336,8 +348,8 @@ typedef enum {
case RES_THRESH: case RES_THRESH:
if (cmd->tx_argc > 2) if (cmd->tx_argc > 2)
{ {
rthresh = MagAtof(cmd->tx_argv[2]); resisdata->rthresh = MagAtof(cmd->tx_argv[2]);
if (rthresh < 0) if (resisdata->rthresh < 0)
{ {
TxError("Usage: %s threshold [value]\n", cmd->tx_argv[0]); TxError("Usage: %s threshold [value]\n", cmd->tx_argv[0]);
return; return;
@ -346,9 +358,10 @@ typedef enum {
else else
{ {
#ifdef MAGIC_WRAPPER #ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewDoubleObj((double)rthresh)); Tcl_SetObjResult(magicinterp,
Tcl_NewDoubleObj((double)resisdata->rthresh));
#else #else
TxPrintf("Resistance threshold is %g.\n", rthresh); TxPrintf("Resistance threshold is %g.\n", resisdata->rthresh);
#endif #endif
} }
return; return;
@ -371,10 +384,10 @@ typedef enum {
if (endptr == cmd->tx_argv[2]) if (endptr == cmd->tx_argv[2])
{ {
TxError("Cannot parse frequency value. Assuming default\n"); TxError("Cannot parse frequency value. Assuming default\n");
TxError("Frequency = %2.1f Hz\n", fhFrequency); TxError("Frequency = %2.1f Hz\n", resisdata->frequency);
} }
else else
fhFrequency = (float)tmpf; resisdata->frequency = (float)tmpf;
} }
saveFlags = ResOptionsFlags; saveFlags = ResOptionsFlags;
ResOptionsFlags |= ResOpt_FastHenry | ResOpt_ExtractAll; ResOptionsFlags |= ResOpt_FastHenry | ResOpt_ExtractAll;
@ -556,14 +569,14 @@ typedef enum {
if (cmd->tx_argc != 3) return; if (cmd->tx_argc != 3) return;
tt = DBTechNoisyNameType(cmd->tx_argv[2]); tt = DBTechNoisyNameType(cmd->tx_argv[2]);
if (tt <= 0 || ToolGetBox(&def, &rect)== FALSE) return; if (tt <= 0 || ToolGetBox(&def, &rect)== FALSE) return;
gparams.rg_devloc = &rect.r_ll; resisdata->rg_devloc = &rect.r_ll;
gparams.rg_ttype = tt; resisdata->rg_ttype = tt;
gparams.rg_status = DRIVEONLY; resisdata->rg_status = DRIVEONLY;
oldoptions = ResOptionsFlags; oldoptions = ResOptionsFlags;
ResOptionsFlags = ResOpt_DoSubstrate | ResOpt_Signal | ResOpt_Box; ResOptionsFlags = ResOpt_DoSubstrate | ResOpt_Signal | ResOpt_Box;
lnode.location = rect.r_ll; lnode.location = rect.r_ll;
lnode.type = tt; lnode.type = tt;
if (ResExtractNet(&lnode, &gparams, NULL) != 0) return; if (ResExtractNet(&lnode, resisdata, NULL) != 0) return;
ResPrintResistorList(stdout, ResResList); ResPrintResistorList(stdout, ResResList);
ResPrintDeviceList(stdout, ResRDevList); ResPrintDeviceList(stdout, ResRDevList);
ResOptionsFlags = oldoptions; ResOptionsFlags = oldoptions;
@ -607,23 +620,33 @@ typedef enum {
} }
ResOptionsFlags |= ResOpt_Signal; ResOptionsFlags |= ResOpt_Signal;
resisdata.rthresh = rthresh; resisdata->mainDef = mainDef;
resisdata.tdiTolerance = tdiTolerance; resisdata->savePlanes = (struct saveList *)NULL;
resisdata.frequency = fhFrequency;
resisdata.mainDef = mainDef;
resisdata.savePlanes = (struct saveList *)NULL;
/* Do subcircuits (if any) first */ /* Do subcircuits (if any) first */
HashInit(&ResProcessedTable, INITFLATSIZE, HT_STRINGKEYS); HashInit(&ResProcessedTable, INITFLATSIZE, HT_STRINGKEYS);
if (!(ResOptionsFlags & ResOpt_Blackbox)) if (!(ResOptionsFlags & ResOpt_Blackbox))
DBCellEnum(mainDef, resSubcircuitFunc, (ClientData) &resisdata); DBCellEnum(mainDef, resSubcircuitFunc, (ClientData)resisdata);
ExtResisForDef(mainDef, &resisdata); HashFind(&ResProcessedTable, mainDef->cd_name);
/* Prepare the substrate for resistance extraction */
savePlane = extResPrepSubstrate(mainDef);
if (savePlane != NULL)
{
struct saveList *newsl;
newsl = (struct saveList *)mallocMagic(sizeof(struct saveList));
newsl->sl_plane = savePlane;
newsl->sl_def = mainDef;
newsl->sl_next = resisdata->savePlanes;
resisdata->savePlanes = newsl;
}
ExtResisForDef(mainDef, resisdata);
HashKill(&ResProcessedTable); HashKill(&ResProcessedTable);
/* Revert substrate planes */ /* Revert substrate planes */
free_magic1_t mm1 = freeMagic1_init(); free_magic1_t mm1 = freeMagic1_init();
for (sl = resisdata.savePlanes; sl; sl = sl->sl_next) for (sl = resisdata->savePlanes; sl; sl = sl->sl_next)
{ {
ExtRevertSubstrate(sl->sl_def, sl->sl_plane); ExtRevertSubstrate(sl->sl_def, sl->sl_plane);
freeMagic1(&mm1, sl); freeMagic1(&mm1, sl);
@ -664,10 +687,26 @@ resSubcircuitFunc(cellUse, rdata)
CellUse *cellUse; CellUse *cellUse;
ResisData *rdata; ResisData *rdata;
{ {
CellDef *cellDef = cellUse->cu_def; CellDef *cellDef = cellUse->cu_def;
Plane *savePlane;
if (DBIsSubcircuit(cellDef)) if (DBIsSubcircuit(cellDef))
{ {
/* Check if this cell has been processed */
if (HashLookOnly(&ResProcessedTable, cellDef->cd_name)) return 0;
HashFind(&ResProcessedTable, cellDef->cd_name);
/* Prepare the substrate for resistance extraction */
savePlane = extResPrepSubstrate(cellDef);
if (savePlane != NULL)
{
struct saveList *newsl;
newsl = (struct saveList *)mallocMagic(sizeof(struct saveList));
newsl->sl_plane = savePlane;
newsl->sl_def = cellDef;
newsl->sl_next = rdata->savePlanes;
rdata->savePlanes = newsl;
}
ExtResisForDef(cellDef, rdata); ExtResisForDef(cellDef, rdata);
DBCellEnum(cellDef, resSubcircuitFunc, (ClientData)rdata); DBCellEnum(cellDef, resSubcircuitFunc, (ClientData)rdata);
} }
@ -925,7 +964,6 @@ ResProcessNode(
HashEntry *he; HashEntry *he;
devPtr *ptr; devPtr *ptr;
float ftolerance, minRes, cumRes; float ftolerance, minRes, cumRes;
float rctol = resisdata->tdiTolerance;
float rthresh = resisdata->rthresh; float rthresh = resisdata->rthresh;
int nidx = 1, eidx = 1; /* node & segment counters for geom. */ int nidx = 1, eidx = 1; /* node & segment counters for geom. */
@ -956,14 +994,14 @@ ResProcessNode(
/* Find largest SD device connected to node. */ /* Find largest SD device connected to node. */
minRes = FLT_MAX; minRes = FLT_MAX;
gparams.rg_devloc = (Point *) NULL; resisdata->rg_devloc = (Point *) NULL;
gparams.rg_status = FALSE; resisdata->rg_status = FALSE;
gparams.rg_nodecap = node->capacitance; resisdata->rg_nodecap = node->capacitance;
/* The following is only used if there is a drivepoint */ /* The following is only used if there is a drivepoint */
/* to identify which tile the drivepoint is on. */ /* to identify which tile the drivepoint is on. */
gparams.rg_ttype = node->rs_ttype; resisdata->rg_ttype = node->rs_ttype;
for (ptr = node->firstDev; ptr != NULL; ptr = ptr->nextDev) for (ptr = node->firstDev; ptr != NULL; ptr = ptr->nextDev)
{ {
@ -999,8 +1037,8 @@ ResProcessNode(
if (minRes > cumRes) if (minRes > cumRes)
{ {
minRes = cumRes; minRes = cumRes;
gparams.rg_devloc = &t1->location; resisdata->rg_devloc = &t1->location;
gparams.rg_ttype = t1->rs_ttype; resisdata->rg_ttype = t1->rs_ttype;
} }
} }
} }
@ -1020,25 +1058,25 @@ ResProcessNode(
} }
if (node->status & DRIVELOC) if (node->status & DRIVELOC)
{ {
gparams.rg_devloc = &node->drivepoint; resisdata->rg_devloc = &node->drivepoint;
gparams.rg_status |= DRIVEONLY; resisdata->rg_status |= DRIVEONLY;
} }
if (node->status & PORTNODE) if (node->status & PORTNODE)
{ {
/* The node is a port, not a device, so make */ /* The node is a port, not a device, so make */
/* sure rg_ttype is set accordingly. */ /* sure rg_ttype is set accordingly. */
gparams.rg_ttype = node->rs_ttype; resisdata->rg_ttype = node->rs_ttype;
} }
} }
if ((gparams.rg_devloc == NULL) && (node->status & FORCE)) if ((resisdata->rg_devloc == NULL) && (node->status & FORCE))
{ {
TxError("Node %s has force label but no drive point or " TxError("Node %s has force label but no drive point or "
"driving device\n", node->name); "driving device\n", node->name);
} }
if ((minRes == FLT_MAX) || (gparams.rg_devloc == NULL)) if ((minRes == FLT_MAX) || (resisdata->rg_devloc == NULL))
return 1; return 1;
gparams.rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS; resisdata->rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS;
if (minRes > resisdata->rthresh) if (minRes > resisdata->rthresh)
ftolerance = minRes; ftolerance = minRes;
else else
@ -1055,7 +1093,7 @@ ResProcessNode(
ResFixPoint fp; ResFixPoint fp;
(*num_extracted)++; (*num_extracted)++;
if (ResExtractNet(node, &gparams, outfile) != 0) if (ResExtractNet(node, resisdata, outfile) != 0)
{ {
/* On error, don't output this net, but keep going */ /* On error, don't output this net, but keep going */
if (node->type == TT_SPACE) if (node->type == TT_SPACE)
@ -1066,15 +1104,16 @@ ResProcessNode(
} }
else else
{ {
ResDoSimplify(ftolerance, rctol, &gparams); ResDoSimplify(ftolerance, resisdata);
if (ResOptionsFlags & ResOpt_DoLumpFile) if (ResOptionsFlags & ResOpt_DoLumpFile)
ResWriteLumpFile(node); ResWriteLumpFile(node, resisdata);
if (gparams.rg_maxres >= ftolerance || if (resisdata->rg_maxres >= ftolerance ||
(ResOptionsFlags & ResOpt_ExtractAll)) (ResOptionsFlags & ResOpt_ExtractAll))
{ {
resNodeNum = 0; resNodeNum = 0;
(*num_output) += ResWriteExtFile(celldef, node, rctol, &nidx, &eidx); (*num_output) += ResWriteExtFile(celldef, node, resisdata,
&nidx, &eidx);
} }
} }
#ifdef PARANOID #ifdef PARANOID
@ -1658,24 +1697,25 @@ ResSortByGate(DevpointerList)
*/ */
void void
ResWriteLumpFile(node) ResWriteLumpFile(node, resisdata)
ResExtNode *node; ResExtNode *node;
ResisData *resisdata;
{ {
int lumpedres; int lumpedres;
if (ResOptionsFlags & ResOpt_Tdi) if (ResOptionsFlags & ResOpt_Tdi)
{ {
if (gparams.rg_nodecap != 0) if (resisdata->rg_nodecap != 0)
{ {
lumpedres = (int)((gparams.rg_Tdi / gparams.rg_nodecap lumpedres = (int)((resisdata->rg_Tdi / resisdata->rg_nodecap
- (float)(gparams.rg_bigdevres)) / OHMSTOMILLIOHMS); - (float)(resisdata->rg_bigdevres)) / OHMSTOMILLIOHMS);
} }
else else
lumpedres = 0; lumpedres = 0;
} }
else else
{ {
lumpedres = gparams.rg_maxres; lumpedres = resisdata->rg_maxres;
} }
fprintf(ResLumpFile, "R %s %d\n", node->name, lumpedres); fprintf(ResLumpFile, "R %s %d\n", node->name, lumpedres);
} }
@ -1752,35 +1792,37 @@ ResAlignNodes(nodelist, reslist)
*/ */
int int
ResWriteExtFile(celldef, node, rctol, nidx, eidx) ResWriteExtFile(celldef, node, resisdata, nidx, eidx)
CellDef *celldef; CellDef *celldef;
ResExtNode *node; ResExtNode *node;
float rctol; ResisData *resisdata;
int *nidx, *eidx; int *nidx, *eidx;
{ {
float RCdev; float RCdev;
char *cp, newname[MAXNAME]; char *cp, newname[MAXNAME];
devPtr *ptr; devPtr *ptr;
resDevice *layoutDev, *ResGetDevice(); resDevice *layoutDev, *ResGetDevice();
float rctol;
RCdev = gparams.rg_bigdevres * gparams.rg_nodecap; rctol = resisdata->tdiTolerance;
RCdev = resisdata->rg_bigdevres * resisdata->rg_nodecap;
if ((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 * resisdata->rg_Tdi)
{ {
ASSERT(gparams.rg_Tdi != -1, "ResWriteExtFile"); ASSERT(resisdata->rg_Tdi != -1, "ResWriteExtFile");
(void)sprintf(newname,"%s", node->name); (void)sprintf(newname,"%s", node->name);
cp = newname + strlen(newname)-1; cp = newname + strlen(newname)-1;
if (*cp == '!' || *cp == '#') *cp = '\0'; if (*cp == '!' || *cp == '#') *cp = '\0';
if ((rctol + 1) * RCdev < rctol * gparams.rg_Tdi || if ((rctol + 1) * RCdev < rctol * resisdata->rg_Tdi ||
(ResOptionsFlags & ResOpt_Tdi) == 0) (ResOptionsFlags & ResOpt_Tdi) == 0)
{ {
if ((ResOptionsFlags & (ResOpt_RunSilent | ResOpt_Tdi)) == ResOpt_Tdi) if ((ResOptionsFlags & (ResOpt_RunSilent | ResOpt_Tdi)) == ResOpt_Tdi)
{ {
TxPrintf("Adding %s; Tnew = %.2fns, Told = %.2fns\n", TxPrintf("Adding %s; Tnew = %.2fns, Told = %.2fns\n",
node->name, gparams.rg_Tdi / Z_TO_P, RCdev / Z_TO_P); node->name, resisdata->rg_Tdi / Z_TO_P, RCdev / Z_TO_P);
} }
} }
for (ptr = node->firstDev; ptr != NULL; ptr=ptr->nextDev) for (ptr = node->firstDev; ptr != NULL; ptr=ptr->nextDev)

View File

@ -32,7 +32,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/stack.h" #include "utils/stack.h"
#include "utils/tech.h" #include "utils/tech.h"
#include "textio/txcommands.h" #include "textio/txcommands.h"
#include "resis/resis.h" #include "resis/resis.h"
#define MILLIOHMSPEROHM 1000 #define MILLIOHMSPEROHM 1000
@ -842,24 +842,26 @@ ResPruneTree(node, minTdi, nodelist1, nodelist2, resistorlist)
*/ */
int int
ResDoSimplify(tolerance, rctol, goodies) ResDoSimplify(tolerance,resisdata)
float tolerance; float tolerance;
float rctol; ResisData *resisdata;
ResGlobalParams *goodies;
{ {
resNode *node, *slownode; resNode *node, *slownode;
float bigres = 0; float bigres = 0;
float millitolerance; float millitolerance;
float totalcap; float totalcap;
float rctol;
resResistor *res; resResistor *res;
ResSetPathRes(); rctol = resisdata->tdiTolerance;
ResSetPathRes(resisdata);
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);
bigres /= OHMSTOMILLIOHMS; /* convert from milliohms to ohms */ bigres /= OHMSTOMILLIOHMS; /* convert from milliohms to ohms */
goodies->rg_maxres = bigres; resisdata->rg_maxres = bigres;
#ifdef PARANOID #ifdef PARANOID
ResSanityChecks("ExtractSingleNet", ResResList, ResNodeList, ResDevList); ResSanityChecks("ExtractSingleNet", ResResList, ResNodeList, ResDevList);
@ -870,7 +872,7 @@ ResDoSimplify(tolerance, rctol, goodies)
/* we're calculating lumped values so that the capacitance */ /* we're calculating lumped values so that the capacitance */
/* values get calculated correctly. */ /* values get calculated correctly. */
(void) ResDistributeCapacitance(ResNodeList, goodies->rg_nodecap); (void) ResDistributeCapacitance(ResNodeList, resisdata->rg_nodecap);
if (((tolerance > bigres) || ((ResOptionsFlags & ResOpt_Simplify) == 0)) && if (((tolerance > bigres) || ((ResOptionsFlags & ResOpt_Simplify) == 0)) &&
((ResOptionsFlags & ResOpt_DoLumpFile) == 0)) ((ResOptionsFlags & ResOpt_DoLumpFile) == 0))
@ -895,43 +897,48 @@ ResDoSimplify(tolerance, rctol, goodies)
------*/ ------*/
} }
if (ResOptionsFlags & ResOpt_Tdi) if (ResOriginNode == NULL)
{ {
if (goodies->rg_nodecap != -1 && TxError("Error: Network simplification: Failed to to get origin node.\n");
resisdata->rg_Tdi = 0;
}
else if (ResOptionsFlags & ResOpt_Tdi)
{
if ((resisdata->rg_nodecap != -1) &&
(totalcap = ResCalculateChildCapacitance(ResOriginNode)) != -1) (totalcap = ResCalculateChildCapacitance(ResOriginNode)) != -1)
{ {
RCDelayStuff *rc = (RCDelayStuff *) ResNodeList->rn_client; RCDelayStuff *rc = (RCDelayStuff *) ResNodeList->rn_client;
goodies->rg_nodecap = totalcap; resisdata->rg_nodecap = totalcap;
ResCalculateTDi(ResOriginNode, (resResistor *)NULL, ResCalculateTDi(ResOriginNode, (resResistor *)NULL,
goodies->rg_bigdevres); resisdata->rg_bigdevres);
if (rc != (RCDelayStuff *)NULL) if (rc != (RCDelayStuff *)NULL)
goodies->rg_Tdi = rc->rc_Tdi; resisdata->rg_Tdi = rc->rc_Tdi;
else else
goodies->rg_Tdi = 0; resisdata->rg_Tdi = 0;
slownode = ResNodeList; slownode = ResNodeList;
for (node = ResNodeList; node != NULL; node = node->rn_more) for (node = ResNodeList; node != NULL; node = node->rn_more)
{ {
rc = (RCDelayStuff *)node->rn_client; rc = (RCDelayStuff *)node->rn_client;
if ((rc != NULL) && (goodies->rg_Tdi < rc->rc_Tdi)) if ((rc != NULL) && (resisdata->rg_Tdi < rc->rc_Tdi))
{ {
slownode = node; slownode = node;
goodies->rg_Tdi = rc->rc_Tdi; resisdata->rg_Tdi = rc->rc_Tdi;
} }
} }
slownode->rn_status |= RN_MAXTDI; slownode->rn_status |= RN_MAXTDI;
} }
else else
goodies->rg_Tdi = -1; resisdata->rg_Tdi = -1;
} }
else else
goodies->rg_Tdi = 0; resisdata->rg_Tdi = 0;
if ((rctol+1) * goodies->rg_bigdevres * goodies->rg_nodecap > if ((rctol+1) * resisdata->rg_bigdevres * resisdata->rg_nodecap >
rctol * goodies->rg_Tdi && rctol * resisdata->rg_Tdi &&
(ResOptionsFlags & ResOpt_Tdi) && (ResOptionsFlags & ResOpt_Tdi) &&
goodies->rg_Tdi != -1) resisdata->rg_Tdi != -1)
return 0; return 0;
/* Simplify network; resistors are still in milliohms, so use /* Simplify network; resistors are still in milliohms, so use
@ -960,11 +967,11 @@ ResDoSimplify(tolerance, rctol, goodies)
/* have time constants less than the tolerance. */ /* have time constants less than the tolerance. */
if ((ResOptionsFlags & ResOpt_Tdi) && if ((ResOptionsFlags & ResOpt_Tdi) &&
goodies->rg_Tdi != -1 && resisdata->rg_Tdi != -1 &&
rctol != 0) rctol != 0)
{ {
ResPruneTree(ResOriginNode, (rctol + 1) * ResPruneTree(ResOriginNode, (rctol + 1) *
goodies->rg_bigdevres * goodies->rg_nodecap / rctol, resisdata->rg_bigdevres * resisdata->rg_nodecap / rctol,
&ResNodeList, &ResNodeQueue, &ResResList); &ResNodeList, &ResNodeQueue, &ResResList);
} }
ResOriginNode->rn_status &= ~MARKED; ResOriginNode->rn_status &= ~MARKED;
@ -999,7 +1006,7 @@ ResDoSimplify(tolerance, rctol, goodies)
*/ */
void void
ResSetPathRes() ResSetPathRes(ResisData *resisdata)
{ {
HeapEntry he; HeapEntry he;
resNode *node; resNode *node;
@ -1026,7 +1033,15 @@ ResSetPathRes()
} }
if (ResOriginNode == NULL) if (ResOriginNode == NULL)
{ {
resDevice *res = ResGetDevice(gparams.rg_devloc, gparams.rg_ttype); resDevice *res = ResGetDevice(resisdata->rg_devloc, resisdata->rg_ttype);
if (res == (resDevice *)NULL)
{
TxError("Error: No device type %s found at location %s %s\n",
DBTypeLongNameTbl[resisdata->rg_ttype],
DBWPrintValue(resisdata->rg_devloc->p_x, (MagWindow *)NULL, TRUE),
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow *)NULL, FALSE));
return;
}
ResOriginNode = res->rd_fet_source; ResOriginNode = res->rd_fet_source;
ResOriginNode->rn_why = RES_NODE_ORIGIN; ResOriginNode->rn_why = RES_NODE_ORIGIN;
ResOriginNode->rn_noderes = 0; ResOriginNode->rn_noderes = 0;

View File

@ -244,25 +244,6 @@ typedef struct resdevtile
int overlap; int overlap;
} ResDevTile; } ResDevTile;
/*
Goodies contains random stuff passed between the node extractor
and ResCheckExtNodes. The location of a start tile and the resistive
tolerance are passed down, while the derived network is passed back.
*/
typedef struct goodstuff
{
TileType rg_ttype;
float rg_maxres;
float rg_nodecap;
float rg_Tdi;
int rg_bigdevres;
int rg_tilecount;
int rg_status;
Point *rg_devloc;
char *rg_name;
} ResGlobalParams;
/* Linked list structure to use to store the substrate plane from each */ /* Linked list structure to use to store the substrate plane from each */
/* extracted CellDef so that they can be returned to the original after */ /* extracted CellDef so that they can be returned to the original after */
/* extraction. */ /* extraction. */
@ -275,13 +256,31 @@ struct saveList {
/* Structure stores information required to be sent to ExtResisForDef() */ /* Structure stores information required to be sent to ExtResisForDef() */
typedef struct typedef struct resoptions
{ {
/* Global options for extresist */
float tdiTolerance; float tdiTolerance;
float frequency; float frequency;
float rthresh; float rthresh;
struct saveList *savePlanes; struct saveList *savePlanes;
CellDef *mainDef; CellDef *mainDef;
/*
* Various information passed between the node extractor and
* ResCheckExtNodes. The location of a start tile and the resistive
* tolerance are passed down, while the derived network is passed back.
*/
TileType rg_ttype;
float rg_maxres;
float rg_nodecap;
float rg_Tdi;
int rg_bigdevres;
int rg_tilecount;
int rg_status;
Point *rg_devloc;
char *rg_name;
} ResisData; } ResisData;
/* Structure used in RC delay calculations for Tdi filter. */ /* Structure used in RC delay calculations for Tdi filter. */
@ -546,10 +545,10 @@ extern TileTypeBitMask ResSDTypesBitMask;
extern TileTypeBitMask ResSubTypesBitMask; extern TileTypeBitMask ResSubTypesBitMask;
extern HashTable ResDevTable; extern HashTable ResDevTable;
extern TileTypeBitMask ResNoMergeMask[NT]; extern TileTypeBitMask ResNoMergeMask[NT];
extern ResGlobalParams gparams;
extern int ResPortIndex; extern int ResPortIndex;
/* Routines used by ResReadExt() */ /* Routines used by ResReadExt() */
extern ResisData *ResInit();
extern int ResReadDevice(); extern int ResReadDevice();
extern int ResReadCapacitor(); extern int ResReadCapacitor();
extern int ResReadResistor(); extern int ResReadResistor();
@ -576,6 +575,12 @@ extern void ResSortBreaks();
extern Plane *extResPrepSubstrate(); extern Plane *extResPrepSubstrate();
/* C99 compat */ /* C99 compat */
extern void ExtResisForDef(CellDef *celldef, ResisData *resisdata);
extern char *ResExtGetAttribute(char *sptr);
extern int ResReadFET(int argc, char *argv[]);
extern int ResReadPort(int argc, char *argv[]);
extern char *ResExtGetAttribute(char *sptr);
extern void ResAddToQueue(); extern void ResAddToQueue();
extern bool ResCalcTileResistance(); extern bool ResCalcTileResistance();
extern void ResCleanNode(); extern void ResCleanNode();
@ -597,7 +602,7 @@ extern void ResPrintReference();
extern void ResPrintResistorList(); extern void ResPrintResistorList();
extern void ResPrintStats(); extern void ResPrintStats();
extern void ResProcessJunction(); extern void ResProcessJunction();
extern int ResReadNode(); extern ResExtNode *ResReadNode(int argc, char *argv[]);
extern int ResReadExt(); extern int ResReadExt();
extern void ResRemoveFromQueue(); extern void ResRemoveFromQueue();
extern int ResExtNewNode(); extern int ResExtNewNode();