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 "commands/commands.h" /* for module auto-load */
#include "textio/txcommands.h"
#include "extract/extract.h" /* for extDevTable */
#include "extflat/extflat.h"
#include "extflat/EFint.h"
#include "extract/extract.h" /* for extDevTable */
#include "utils/runstats.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 "textio/txcommands.h"
#include "extflat/extflat.h"
#include "extflat/EFint.h"
#include "extract/extract.h" /* for extDevTable */
#include "extflat/EFint.h"
#include "utils/runstats.h"
#include "ext2spice/ext2spice.h"
/* C99 compat */
#include "extflat/extflat.h"
/* These global values are defined in ext2spice.c */
extern HashTable subcktNameTable;
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 "commands/commands.h" /* for module auto-load */
#include "textio/txcommands.h"
#include "extract/extract.h" /* for extDevTable */
#include "extflat/extflat.h"
#include "extflat/EFint.h"
#include "extract/extract.h" /* for extDevTable */
#include "utils/runstats.h"
#include "ext2spice/ext2spice.h"

View File

@ -34,8 +34,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header$";
#include "tiles/tile.h"
#include "database/database.h" /* for TileType definition */
#include "extflat/extflat.h"
#include "extflat/extparse.h"
#include "extflat/EFint.h"
#include "extract/extract.h" /* for device class list */
#include "extract/extract.h"
#include "extract/extractInt.h" /* for extGetDevType() */
/* 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/geometry.h"
#include "textio/textio.h"
extern char *efReadFileName;
extern int efReadLineNum;
#include "extflat/extparse.h"
#ifdef MAGIC_WRAPPER
extern int Tcl_printf();

View File

@ -46,6 +46,14 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
/* C99 compat */
#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 */
char *efReadFileName; /* Name of file currently being read */
int efReadLineNum; /* Current line number in above file */

View File

@ -27,7 +27,6 @@
#include "extflat/EFtypes.h" /* EFCapValue, HierName, EFPerimArea, EFNode */
#include "extflat/EFint.h" /* Def, HierContext, Connection, Distance, CallArg */
extern float EFScale; /* Scale factor to multiply all coords by */
extern char *EFTech; /* Technology 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. */
/* This table is also used in extract/ExtBasic.c */
/* 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
#ifndef _MAGIC__EXTFLAT__EXTPARSE_H
#define _MAGIC__EXTFLAT__EXTPARSE_H
/*
* The following table describes the kinds of lines
@ -80,5 +69,7 @@ keyTable[] =
/* atoCap - convert a string to a EFCapValue */
#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/stack.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 ---------------------- */
@ -546,24 +559,6 @@ extBasic(def, 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 */
if (coupleInitialized)
extCapHashKill(&extCoupleHash);
@ -5000,9 +4995,12 @@ extFindNodes(def, clipArea, subonly)
/* If the default substrate type is set, it is used *only* for */
/* isolated substrate regions and does not mark the default */
/* 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)
TTMaskClearType(&subsTypesNonSpace,
if (!(ExtOptions & EXT_DOEXTRESIST))
if (ExtCurStyle->exts_globSubstrateDefaultType != -1)
TTMaskClearType(&subsTypesNonSpace,
ExtCurStyle->exts_globSubstrateDefaultType);
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 "extract/extract.h"
#include "extract/extractInt.h"
#include "resis/resis.h"
#include "utils/signals.h"
#include "utils/stack.h"
#include "utils/utils.h"
@ -115,6 +116,25 @@ ExtCell(def, outName, doLength)
savePlane = extCellFile(def, f, doLength);
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)
{
TxPrintf("%s:", def->cd_name);
@ -493,7 +513,10 @@ extCellFile(def, f, doLength)
extUniqueCell(def, EXT_UNIQ_TEMP);
/* 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 */
for (lab = def->cd_labels; lab; lab = lab->lab_next)

View File

@ -273,9 +273,9 @@ ResMakePortBreakpoints(def)
*----------------------------------------------------------------------------
*/
void
ResMakeLabelBreakpoints(def, goodies)
CellDef *def;
ResGlobalParams *goodies;
ResMakeLabelBreakpoints(def, resisdata)
CellDef *def;
ResisData *resisdata;
{
Plane *plane;
Rect *rect;
@ -294,12 +294,12 @@ ResMakeLabelBreakpoints(def, goodies)
entry = HashFind(&ResNodeTable, slab->lab_text);
node = ResInitializeNode(entry);
/* If the drivepoint position changes and the drivepoint is */
/* in the "goodies" record, then make sure the tile type in */
/* "goodies" gets changed to match. */
/* If the drivepoint position changes and the drivepoint is */
/* in the "resisdata" record, then make sure the tile type */
/* in "resisdata" gets changed to match. */
if (goodies->rg_devloc == &node->drivepoint)
goodies->rg_ttype = slab->lab_type;
if (resisdata->rg_devloc == &node->drivepoint)
resisdata->rg_ttype = slab->lab_type;
node->drivepoint = slab->lab_rect.r_ll;
node->rs_bbox = slab->lab_rect;
@ -490,9 +490,9 @@ ResFindNewContactTiles(contacts)
*/
int
ResProcessTiles(goodies, origin)
Point *origin;
ResGlobalParams *goodies;
ResProcessTiles(resisdata, origin)
Point *origin;
ResisData *resisdata;
{
Tile *startTile;
@ -506,7 +506,7 @@ ResProcessTiles(goodies, origin)
if (ResOptionsFlags & ResOpt_Signal)
{
startTile = FindStartTile(goodies, origin);
startTile = FindStartTile(resisdata, origin);
if (startTile == NULL)
return 1;
resCurrentNode = NULL;
@ -990,9 +990,9 @@ ResShaveContacts(tile, dinfo, def)
*/
bool
ResExtractNet(node, goodies, cellname)
ResExtractNet(node, resisdata, cellname)
ResExtNode *node;
ResGlobalParams *goodies;
ResisData *resisdata;
char *cellname;
{
SearchContext scx;
@ -1018,8 +1018,8 @@ ResExtractNet(node, goodies, cellname)
/* Pass back network pointers */
goodies->rg_maxres = 0;
goodies->rg_tilecount = 0;
resisdata->rg_maxres = 0;
resisdata->rg_tilecount = 0;
/* Set up internal stuff if this is the first time through */
@ -1102,10 +1102,10 @@ ResExtractNet(node, goodies, cellname)
resMakeDevFunc, (ClientData)thisDev);
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],
tptr->thisDev->location.p_x,
tptr->thisDev->location.p_y);
DBWPrintValue(tptr->thisDev->location.p_x, (MagWindow*)NULL, TRUE),
DBWPrintValue(tptr->thisDev->location.p_y, (MagWindow*)NULL, FALSE));
freeMagic(thisDev);
continue;
}
@ -1185,12 +1185,12 @@ ResExtractNet(node, goodies, cellname)
/* Finish preprocessing. */
ResMakePortBreakpoints(ResUse->cu_def);
ResMakeLabelBreakpoints(ResUse->cu_def, goodies);
ResMakeLabelBreakpoints(ResUse->cu_def, resisdata);
ResFindNewContactTiles(ResContactList);
ResPreProcessDevices(DevTiles, ResDevList, ResUse->cu_def);
/* do extraction */
if (ResProcessTiles(goodies, &startpoint) != 0) return TRUE;
if (ResProcessTiles(resisdata, &startpoint) != 0) return TRUE;
return FALSE;
}
@ -1323,10 +1323,9 @@ ResGetTileFunc(tile, dinfo, tpptr)
*/
Tile *
FindStartTile(goodies, SourcePoint)
FindStartTile(resisdata, SourcePoint)
ResisData *resisdata;
Point *SourcePoint;
ResGlobalParams *goodies;
{
Point workingPoint;
Tile *tile, *tp;
@ -1339,39 +1338,39 @@ FindStartTile(goodies, SourcePoint)
/* If the drive point is on a contact, check for the contact residues */
/* first, then the contact type itself. */
if (DBIsContact(goodies->rg_ttype))
if (DBIsContact(resisdata->rg_ttype))
{
TileTypeBitMask *rmask = DBResidueMask(goodies->rg_ttype);
TileType savtype = goodies->rg_ttype;
TileTypeBitMask *rmask = DBResidueMask(resisdata->rg_ttype);
TileType savtype = resisdata->rg_ttype;
TileType rtype;
for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++)
if (TTMaskHasType(rmask, rtype))
{
goodies->rg_ttype = rtype;
if ((tile = FindStartTile(goodies, SourcePoint)) != NULL)
resisdata->rg_ttype = rtype;
if ((tile = FindStartTile(resisdata, SourcePoint)) != NULL)
{
goodies->rg_ttype = savtype;
resisdata->rg_ttype = savtype;
return tile;
}
}
goodies->rg_ttype = savtype;
resisdata->rg_ttype = savtype;
}
workingPoint.p_x = goodies->rg_devloc->p_x;
workingPoint.p_y = goodies->rg_devloc->p_y;
workingPoint.p_x = resisdata->rg_devloc->p_x;
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 */
if (goodies->rg_status & DRIVEONLY)
if (resisdata->rg_status & DRIVEONLY)
{
tile = PlaneGetHint(ResUse->cu_def->cd_planes[pnum]);
GOTOPOINT(tile, &workingPoint);
SourcePoint->p_x = workingPoint.p_x;
SourcePoint->p_y = workingPoint.p_y;
if (TiGetTypeExact(tile) == goodies->rg_ttype)
if (TiGetTypeExact(tile) == resisdata->rg_ttype)
return tile;
else
{
@ -1383,18 +1382,19 @@ FindStartTile(goodies, SourcePoint)
if (workingPoint.p_x == LEFT(tile))
{
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);
}
else if (workingPoint.p_y == BOTTOM(tile))
{
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);
}
}
TxError("Couldn't find wire at %d %d\n",
goodies->rg_devloc->p_x, goodies->rg_devloc->p_y);
TxError("Couldn't find wire at %s %s\n",
DBWPrintValue(resisdata->rg_devloc->p_x, (MagWindow *)NULL, TRUE),
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow *)NULL, FALSE));
return NULL;
}
@ -1409,15 +1409,17 @@ FindStartTile(goodies, SourcePoint)
t1 = TiGetRightType(tile);
else
{
TxError("Couldn't find device at %d %d\n",
goodies->rg_devloc->p_x, goodies->rg_devloc->p_y);
TxError("Couldn't find device at %s %s\n",
DBWPrintValue(resisdata->rg_devloc->p_x, (MagWindow *)NULL, TRUE),
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow *)NULL, FALSE));
return(NULL);
}
}
else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetType(tile)) == 0)
{
TxError("Couldn't find device at %d %d\n",
goodies->rg_devloc->p_x, goodies->rg_devloc->p_y);
TxError("Couldn't find device at %s %s\n",
DBWPrintValue(resisdata->rg_devloc->p_x, (MagWindow *)NULL, TRUE),
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow *)NULL, FALSE));
return(NULL);
}
else
@ -1708,8 +1710,9 @@ FindStartTile(goodies, SourcePoint)
/* Didn't find a terminal (S/D or substrate) type tile anywhere. Flag an error. */
if (devptr == NULL)
TxError("Couldn't find a terminal of the device at %d %d\n",
goodies->rg_devloc->p_x, goodies->rg_devloc->p_y);
TxError("Couldn't find a terminal of the device at %s %s\n",
DBWPrintValue(resisdata->rg_devloc->p_x, (MagWindow*)NULL, TRUE),
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow*)NULL, FALSE));
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 "utils/malloc.h"
#include "textio/textio.h"
#include "extflat/extparse.h"
#include "extract/extract.h"
#include "extract/extractInt.h"
#include "windows/windows.h"
@ -175,13 +176,13 @@ ResPrintExtDev(outextfile, devices)
fprintf(outextfile, " \"%s\" %d %s",
devices->gate->name,
devices->layout->rd_length * 2,
devices->rs_gattr);
(*devices->rs_gattr == '\0') ? "0" : devices->rs_gattr);
if (devices->source != NULL)
fprintf(outextfile, " \"%s\" %d %s",
devices->source->name,
devices->layout->rd_width,
devices->rs_sattr);
(*devices->rs_sattr == '\0') ? "0" : devices->rs_sattr);
/* Don't write drain values for 2-terminal devices */
if (devptr->exts_deviceSDCount > 1)
@ -189,7 +190,7 @@ ResPrintExtDev(outextfile, devices)
fprintf(outextfile, " \"%s\" %d %s",
devices->drain->name,
devices->layout->rd_width,
devices->rs_dattr);
(*devices->rs_dattr == '\0') ? "0" : devices->rs_dattr);
fprintf(outextfile, "\n");
}
@ -290,6 +291,13 @@ ResPrintExtNode(outextfile, nodelist, node)
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
* creating a zero-valued resistance between it and the
* first subnode (arbitrary connection). Flag a warning.
@ -316,16 +324,16 @@ ResPrintExtNode(outextfile, nodelist, node)
*/
void
ResPrintStats(goodies, name)
ResGlobalParams *goodies;
char *name;
ResPrintStats(resisdata, name)
ResisData *resisdata;
char *name;
{
static int totalnets = 0, totalnodes = 0, totalresistors = 0;
int nodes, resistors;
resNode *node;
resResistor *res;
if (goodies == NULL)
if (resisdata == NULL)
{
TxError("nets:%d nodes:%d resistors:%d\n",
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 */
RDev *ResRDevList; /* Linked list of Ext devices */
ResGlobalParams gparams; /* Junk passed between */
/* ResCheckExtNodes and */
/* ResExtractNet. */
extern ResExtNode *ResOriginalNodes; /*Linked List of Nodes */
int resNodeNum;
extern ResExtNode *ResOriginalNodes; /*Linked List of Nodes */
int ResOptionsFlags = ResOpt_Simplify | ResOpt_Tdi | ResOpt_DoExtFile;
char *ResCurrentNode;
@ -98,27 +96,10 @@ ExtResisForDef(celldef, resisdata)
ResExtNode *node;
int result, idx;
char *devname;
Plane *savePlane;
ResRDevList = 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 */
idx = 0;
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]);
EFDevNumTypes = 0;
if (result)
/* read in .nodes file */
result = (ResReadNode(celldef->cd_name) == 0);
if (result)
{
/* Check for subcircuit ports */
if (ResOptionsFlags & ResOpt_Blackbox)
ResCheckBlackbox(celldef);
else
ResCheckPorts(celldef);
/* Extract networks for nets that require it. */
if (!(ResOptionsFlags & ResOpt_FastHenry) ||
@ -157,7 +132,7 @@ ExtResisForDef(celldef, resisdata)
ResCheckExtNodes(celldef, resisdata);
if (ResOptionsFlags & ResOpt_Stat)
ResPrintStats((ResGlobalParams *)NULL, "");
ResPrintStats((ResisData *)NULL, "");
}
/* Clean up */
@ -197,13 +172,74 @@ ExtResisForDef(celldef, resisdata)
/*
*-------------------------------------------------------------------------
*
* CmdExtResis-- reads in ext file and layout, and produces patches to the
* .ext files that include resistors.
* ResInit --
*
* 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:
* 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;
{
int i, j, k, option, value, saveFlags;
static int init = 1;
static float rthresh, tdiTolerance, fhFrequency;
CellDef *mainDef;
CellUse *selectedUse;
ResisData resisdata;
ResisData *resisdata;
Plane *savePlane;
char *endptr; /* for use with strtod() */
struct saveList *sl;
@ -262,31 +297,7 @@ typedef enum {
RES_RUN
} ResOptions;
if (init)
{
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;
resisdata = ResInit();
option = (cmd->tx_argc > 1) ? Lookup(cmd->tx_argv[1], cmdExtresisCmd)
: RES_RUN;
@ -316,8 +327,8 @@ typedef enum {
ResOptionsFlags |= ResOpt_ExplicitRtol;
if (cmd->tx_argc > 2)
{
tdiTolerance = MagAtof(cmd->tx_argv[2]);
if (tdiTolerance <= 0)
resisdata->tdiTolerance = MagAtof(cmd->tx_argv[2]);
if (resisdata->tdiTolerance <= 0)
{
TxError("Usage: %s tolerance [value]\n", cmd->tx_argv[0]);
return;
@ -326,9 +337,10 @@ typedef enum {
else
{
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewDoubleObj((double)tdiTolerance));
Tcl_SetObjResult(magicinterp,
Tcl_NewDoubleObj((double)resisdata->tdiTolerance));
#else
TxPrintf("Tolerance ratio is %g.\n", tdiTolerance);
TxPrintf("Tolerance ratio is %g.\n", resisdata->tdiTolerance);
#endif
}
return;
@ -336,8 +348,8 @@ typedef enum {
case RES_THRESH:
if (cmd->tx_argc > 2)
{
rthresh = MagAtof(cmd->tx_argv[2]);
if (rthresh < 0)
resisdata->rthresh = MagAtof(cmd->tx_argv[2]);
if (resisdata->rthresh < 0)
{
TxError("Usage: %s threshold [value]\n", cmd->tx_argv[0]);
return;
@ -346,9 +358,10 @@ typedef enum {
else
{
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewDoubleObj((double)rthresh));
Tcl_SetObjResult(magicinterp,
Tcl_NewDoubleObj((double)resisdata->rthresh));
#else
TxPrintf("Resistance threshold is %g.\n", rthresh);
TxPrintf("Resistance threshold is %g.\n", resisdata->rthresh);
#endif
}
return;
@ -371,10 +384,10 @@ typedef enum {
if (endptr == cmd->tx_argv[2])
{
TxError("Cannot parse frequency value. Assuming default\n");
TxError("Frequency = %2.1f Hz\n", fhFrequency);
TxError("Frequency = %2.1f Hz\n", resisdata->frequency);
}
else
fhFrequency = (float)tmpf;
resisdata->frequency = (float)tmpf;
}
saveFlags = ResOptionsFlags;
ResOptionsFlags |= ResOpt_FastHenry | ResOpt_ExtractAll;
@ -556,14 +569,14 @@ typedef enum {
if (cmd->tx_argc != 3) return;
tt = DBTechNoisyNameType(cmd->tx_argv[2]);
if (tt <= 0 || ToolGetBox(&def, &rect)== FALSE) return;
gparams.rg_devloc = &rect.r_ll;
gparams.rg_ttype = tt;
gparams.rg_status = DRIVEONLY;
resisdata->rg_devloc = &rect.r_ll;
resisdata->rg_ttype = tt;
resisdata->rg_status = DRIVEONLY;
oldoptions = ResOptionsFlags;
ResOptionsFlags = ResOpt_DoSubstrate | ResOpt_Signal | ResOpt_Box;
lnode.location = rect.r_ll;
lnode.type = tt;
if (ResExtractNet(&lnode, &gparams, NULL) != 0) return;
if (ResExtractNet(&lnode, resisdata, NULL) != 0) return;
ResPrintResistorList(stdout, ResResList);
ResPrintDeviceList(stdout, ResRDevList);
ResOptionsFlags = oldoptions;
@ -607,23 +620,33 @@ typedef enum {
}
ResOptionsFlags |= ResOpt_Signal;
resisdata.rthresh = rthresh;
resisdata.tdiTolerance = tdiTolerance;
resisdata.frequency = fhFrequency;
resisdata.mainDef = mainDef;
resisdata.savePlanes = (struct saveList *)NULL;
resisdata->mainDef = mainDef;
resisdata->savePlanes = (struct saveList *)NULL;
/* Do subcircuits (if any) first */
HashInit(&ResProcessedTable, INITFLATSIZE, HT_STRINGKEYS);
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);
/* Revert substrate planes */
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);
freeMagic1(&mm1, sl);
@ -664,10 +687,26 @@ resSubcircuitFunc(cellUse, rdata)
CellUse *cellUse;
ResisData *rdata;
{
CellDef *cellDef = cellUse->cu_def;
CellDef *cellDef = cellUse->cu_def;
Plane *savePlane;
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);
DBCellEnum(cellDef, resSubcircuitFunc, (ClientData)rdata);
}
@ -925,7 +964,6 @@ ResProcessNode(
HashEntry *he;
devPtr *ptr;
float ftolerance, minRes, cumRes;
float rctol = resisdata->tdiTolerance;
float rthresh = resisdata->rthresh;
int nidx = 1, eidx = 1; /* node & segment counters for geom. */
@ -956,14 +994,14 @@ ResProcessNode(
/* Find largest SD device connected to node. */
minRes = FLT_MAX;
gparams.rg_devloc = (Point *) NULL;
gparams.rg_status = FALSE;
gparams.rg_nodecap = node->capacitance;
resisdata->rg_devloc = (Point *) NULL;
resisdata->rg_status = FALSE;
resisdata->rg_nodecap = node->capacitance;
/* The following is only used if there is a drivepoint */
/* to identify which tile the drivepoint is on. */
gparams.rg_ttype = node->rs_ttype;
resisdata->rg_ttype = node->rs_ttype;
for (ptr = node->firstDev; ptr != NULL; ptr = ptr->nextDev)
{
@ -999,8 +1037,8 @@ ResProcessNode(
if (minRes > cumRes)
{
minRes = cumRes;
gparams.rg_devloc = &t1->location;
gparams.rg_ttype = t1->rs_ttype;
resisdata->rg_devloc = &t1->location;
resisdata->rg_ttype = t1->rs_ttype;
}
}
}
@ -1020,25 +1058,25 @@ ResProcessNode(
}
if (node->status & DRIVELOC)
{
gparams.rg_devloc = &node->drivepoint;
gparams.rg_status |= DRIVEONLY;
resisdata->rg_devloc = &node->drivepoint;
resisdata->rg_status |= DRIVEONLY;
}
if (node->status & PORTNODE)
{
/* The node is a port, not a device, so make */
/* sure rg_ttype is set accordingly. */
gparams.rg_ttype = node->rs_ttype;
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 "
"driving device\n", node->name);
}
if ((minRes == FLT_MAX) || (gparams.rg_devloc == NULL))
if ((minRes == FLT_MAX) || (resisdata->rg_devloc == NULL))
return 1;
gparams.rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS;
resisdata->rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS;
if (minRes > resisdata->rthresh)
ftolerance = minRes;
else
@ -1055,7 +1093,7 @@ ResProcessNode(
ResFixPoint fp;
(*num_extracted)++;
if (ResExtractNet(node, &gparams, outfile) != 0)
if (ResExtractNet(node, resisdata, outfile) != 0)
{
/* On error, don't output this net, but keep going */
if (node->type == TT_SPACE)
@ -1066,15 +1104,16 @@ ResProcessNode(
}
else
{
ResDoSimplify(ftolerance, rctol, &gparams);
ResDoSimplify(ftolerance, resisdata);
if (ResOptionsFlags & ResOpt_DoLumpFile)
ResWriteLumpFile(node);
ResWriteLumpFile(node, resisdata);
if (gparams.rg_maxres >= ftolerance ||
if (resisdata->rg_maxres >= ftolerance ||
(ResOptionsFlags & ResOpt_ExtractAll))
{
resNodeNum = 0;
(*num_output) += ResWriteExtFile(celldef, node, rctol, &nidx, &eidx);
(*num_output) += ResWriteExtFile(celldef, node, resisdata,
&nidx, &eidx);
}
}
#ifdef PARANOID
@ -1658,24 +1697,25 @@ ResSortByGate(DevpointerList)
*/
void
ResWriteLumpFile(node)
ResWriteLumpFile(node, resisdata)
ResExtNode *node;
ResisData *resisdata;
{
int lumpedres;
if (ResOptionsFlags & ResOpt_Tdi)
{
if (gparams.rg_nodecap != 0)
if (resisdata->rg_nodecap != 0)
{
lumpedres = (int)((gparams.rg_Tdi / gparams.rg_nodecap
- (float)(gparams.rg_bigdevres)) / OHMSTOMILLIOHMS);
lumpedres = (int)((resisdata->rg_Tdi / resisdata->rg_nodecap
- (float)(resisdata->rg_bigdevres)) / OHMSTOMILLIOHMS);
}
else
lumpedres = 0;
}
else
{
lumpedres = gparams.rg_maxres;
lumpedres = resisdata->rg_maxres;
}
fprintf(ResLumpFile, "R %s %d\n", node->name, lumpedres);
}
@ -1752,35 +1792,37 @@ ResAlignNodes(nodelist, reslist)
*/
int
ResWriteExtFile(celldef, node, rctol, nidx, eidx)
ResWriteExtFile(celldef, node, resisdata, nidx, eidx)
CellDef *celldef;
ResExtNode *node;
float rctol;
ResisData *resisdata;
int *nidx, *eidx;
{
float RCdev;
char *cp, newname[MAXNAME];
devPtr *ptr;
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) ||
(ResOptionsFlags & ResOpt_ExtractAll) ||
(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);
cp = newname + strlen(newname)-1;
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)
{
if ((ResOptionsFlags & (ResOpt_RunSilent | ResOpt_Tdi)) == ResOpt_Tdi)
{
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)

View File

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

View File

@ -244,25 +244,6 @@ typedef struct resdevtile
int overlap;
} 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 */
/* extracted CellDef so that they can be returned to the original after */
/* extraction. */
@ -275,13 +256,31 @@ struct saveList {
/* Structure stores information required to be sent to ExtResisForDef() */
typedef struct
typedef struct resoptions
{
/* Global options for extresist */
float tdiTolerance;
float frequency;
float rthresh;
struct saveList *savePlanes;
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;
/* Structure used in RC delay calculations for Tdi filter. */
@ -546,10 +545,10 @@ extern TileTypeBitMask ResSDTypesBitMask;
extern TileTypeBitMask ResSubTypesBitMask;
extern HashTable ResDevTable;
extern TileTypeBitMask ResNoMergeMask[NT];
extern ResGlobalParams gparams;
extern int ResPortIndex;
/* Routines used by ResReadExt() */
extern ResisData *ResInit();
extern int ResReadDevice();
extern int ResReadCapacitor();
extern int ResReadResistor();
@ -576,6 +575,12 @@ extern void ResSortBreaks();
extern Plane *extResPrepSubstrate();
/* 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 bool ResCalcTileResistance();
extern void ResCleanNode();
@ -597,7 +602,7 @@ extern void ResPrintReference();
extern void ResPrintResistorList();
extern void ResPrintStats();
extern void ResProcessJunction();
extern int ResReadNode();
extern ResExtNode *ResReadNode(int argc, char *argv[]);
extern int ResReadExt();
extern void ResRemoveFromQueue();
extern int ResExtNewNode();