From 57c33c48c774d1b6c23311d1c59dfb4270809fcb Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Wed, 28 Jan 2026 14:31:38 -0500 Subject: [PATCH] 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"). --- ext2sim/ext2sim.c | 2 +- ext2spice/ext2hier.c | 5 +- ext2spice/ext2spice.c | 2 +- extflat/EFbuild.c | 3 +- extflat/EFerr.c | 4 +- extflat/EFread.c | 8 + extflat/extflat.h | 1 - extflat/extparse.h | 19 +- extract/ExtBasic.c | 40 +- extract/ExtCell.c | 25 +- resis/ResMain.c | 95 ++--- resis/ResPrint.c | 22 +- resis/ResReadExt.c | 920 ++++++++++++++++-------------------------- resis/ResRex.c | 266 +++++++----- resis/ResSimple.c | 67 +-- resis/resis.h | 49 ++- 16 files changed, 687 insertions(+), 841 deletions(-) diff --git a/ext2sim/ext2sim.c b/ext2sim/ext2sim.c index bc98475d..d5b96c5a 100644 --- a/ext2sim/ext2sim.c +++ b/ext2sim/ext2sim.c @@ -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" diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 2f6ed027..4a4c54a1 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -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; diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 1e08a484..f494e8d0 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -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" diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c index a9ca61c7..fed2f975 100644 --- a/extflat/EFbuild.c +++ b/extflat/EFbuild.c @@ -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 */ diff --git a/extflat/EFerr.c b/extflat/EFerr.c index c69d3bf5..b5eb511d 100644 --- a/extflat/EFerr.c +++ b/extflat/EFerr.c @@ -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(); diff --git a/extflat/EFread.c b/extflat/EFread.c index 1a7c70fc..e4c2253e 100644 --- a/extflat/EFread.c +++ b/extflat/EFread.c @@ -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 */ diff --git a/extflat/extflat.h b/extflat/extflat.h index 0dc740fc..b85b858c 100644 --- a/extflat/extflat.h +++ b/extflat/extflat.h @@ -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 */ diff --git a/extflat/extparse.h b/extflat/extparse.h index 55944622..a688bde7 100644 --- a/extflat/extparse.h +++ b/extflat/extparse.h @@ -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 */ diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index bda0a076..3aeb18d4 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -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 ".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; diff --git a/extract/ExtCell.c b/extract/ExtCell.c index 26fa5cb9..0cdc396c 100644 --- a/extract/ExtCell.c +++ b/extract/ExtCell.c @@ -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 ".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) diff --git a/resis/ResMain.c b/resis/ResMain.c index dcfc14f7..dc9979e4 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -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); } diff --git a/resis/ResPrint.c b/resis/ResPrint.c index 4f03d9e3..08acf785 100644 --- a/resis/ResPrint.c +++ b/resis/ResPrint.c @@ -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); diff --git a/resis/ResReadExt.c b/resis/ResReadExt.c index b792cffb..5bd5df68 100644 --- a/resis/ResReadExt.c +++ b/resis/ResReadExt.c @@ -19,6 +19,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include #include "utils/magic.h" +#include "utils/main.h" #include "utils/geometry.h" #include "utils/geofast.h" #include "tiles/tile.h" @@ -29,6 +30,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "extract/extract.h" #include "extract/extractInt.h" #include "extflat/extflat.h" +#include "extflat/extparse.h" #include "windows/windows.h" #include "dbwind/dbwind.h" #include "utils/utils.h" @@ -36,50 +38,54 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "textio/txcommands.h" #include "resis/resis.h" -/* constants defining where various fields can be found in .ext files. */ -/* (FIXME---Needs to be changed to positions in .ext files) */ +/* constants defining where various fields can be found in .ext files. */ +/* The value corresponds to the argument number on the list after */ +/* parsing by efReadLine(). */ -#define RDEV_LENGTH 4 -#define RDEV_WIDTH 5 -#define RDEV_DEVX 6 -#define RDEV_DEVY 7 -#define RDEV_ATTR 8 -#define RDEV_NUM_ATTR 3 -#define RESNODENAME 1 -#define NODERESISTANCE 2 -#define COUPLETERMINAL1 1 -#define COUPLETERMINAL2 2 -#define COUPLEVALUE 3 -#define REALNAME 1 -#define ALIASNAME 2 -#define NODES_NODENAME 0 -#define NODES_NODEX 1 -#define NODES_NODEY 2 -#define NODES_NODETYPE 3 -#define NODE_BBOX_LL_X 5 -#define NODE_BBOX_LL_Y 6 -#define NODE_BBOX_UR_X 7 -#define NODE_BBOX_UR_Y 8 -#define NODELAMBDA 2 -#define NODEUNITS 1 -#define ATTRIBUTENODENAME 1 -#define ATTRIBUTEVALUE 2 +#define FET_NAME 1 +#define FET_X 2 +#define FET_Y 3 +#define FET_AREA 4 +#define FET_PERIM 5 +#define FET_SUBS 6 +#define FET_GATE 7 +#define FET_GATE_ATTR 9 +#define FET_SOURCE 10 +#define FET_SOURCE_ATTR 12 +#define FET_DRAIN 13 +#define FET_DRAIN_ATTR 15 + +#define DEV_NAME 2 +#define DEV_X 3 +#define DEV_Y 4 + +#define NODES_NODENAME 1 +#define NODES_NODEX 4 +#define NODES_NODEY 5 +#define NODES_NODETYPE 6 + +#define COUPLETERMINAL1 1 +#define COUPLETERMINAL2 2 +#define COUPLEVALUE 3 -#define RES_EXT_ATTR 0 #define RES_EXT_ATTR_NAME 1 #define RES_EXT_ATTR_X 2 #define RES_EXT_ATTR_Y 3 -#define RES_EXT_ATTR_TILE 6 +#define RES_EXT_ATTR_TYPE 6 #define RES_EXT_ATTR_TEXT 7 -#define MAXTOKEN 1024 -#define MAXLINE 40 +#define PORT_NAME 1 +#define PORT_LLX 3 +#define PORT_LLY 4 +#define PORT_URX 5 +#define PORT_URY 6 +#define PORT_TYPE 7 + #define MAXDIGIT 20 ResExtNode *ResInitializeNode(); ResExtNode *ResOriginalNodes; /*Linked List of Nodes */ -static float resscale = 1.0; /* Scale factor */ char RDEV_NOATTR[1] = {'0'}; ResFixPoint *ResFixList; @@ -96,27 +102,49 @@ ResFixPoint *ResFixList; */ int -ResReadExt(char *extfile); +ResReadExt(char *extfile) { char *line = NULL, *argv[128]; - int result, fettype, readdrivepoints; - int size = 0; + int result, locresult; + int argc, n, size = 0; FILE *fp; + CellDef *dbdef; + ResExtNode *curnode; + + /* Search for the .ext fie in the same way that efReadDef() does. */ fp = PaOpen(extfile, "r", ".ext", EFSearchPath, EFLibPath, (char **)NULL); + if ((fp == NULL) && (dbdef = DBCellLookDef(extfile)) != NULL) + { + char *filepath, *sptr; + + filepath = StrDup((char **)NULL, dbdef->cd_file); + sptr = strrchr(filepath, '/'); + if (sptr) + { + *sptr = '\0'; + fp = PaOpen(extfile, "r", ".ext", filepath, EFLibPath, (char **)NULL); + } + freeMagic(filepath); + } + + /* Try with the standard search path */ + if ((fp == NULL) && (EFSearchPath == NULL)) + fp = PaOpen(extfile, "r", ".ext", Path, EFLibPath, (char **)NULL); + if (fp == NULL) { TxError("Cannot open file %s%s\n", extfile, ".ext"); return 1; } - readdrivepoints = FALSE; /* Read in the file. Makes use of various functions * from extflat, mostly in EFread.c. */ - EFSaveLocs = False; + EFSaveLocs = FALSE; efReadLineNum = 0; + result = 0; while ((argc = efReadLine(&line, &size, fp, argv)) >= 0) { @@ -137,35 +165,33 @@ ResReadExt(char *extfile); */ switch (keyTable[n].k_key) { - case SCALE: - resscale = (float)atof(argv[1]); - if (resscale == 0.0) resscale = 1.0; - break; case DEVICE: - ResReadSubckt(argc, argv); + locresult = ResReadDevice(argc, argv); break; case FET: - ResReadDevice(argc, argv); + locresult = ResReadFET(argc, argv); break; case MERGE: - ResReadDrivePoint(argc, argv); + /* To be completed */ + /* ResReadDrivePoint(argc, argv); */ break; case NODE: case SUBSTRATE: - ResReadNode(argc, argv); + curnode = ResReadNode(argc, argv); break; case PORT: - ResReadPort(argc, argv); + locresult = ResReadPort(argc, argv); break; case ATTR: - result = ResExtAttribute(curnodename, - argv[1], &readdrivepoints); + locresult = ResReadAttribute(curnode, argc, argv); + break; + case CAP: + locresult = ResReadCapacitor(argc, argv); break; default: break; - - /* to do: Handle CAP, RESISTOR, maybe others? */ } + if (locresult == 1) result = 1; } fclose(fp); return(result); @@ -175,10 +201,45 @@ ResReadExt(char *extfile); /* *------------------------------------------------------------------------- * - * ResReadNode-- Reads in a node file, puts location of nodes into node - * structures. + * ResReadNode-- Reads in a node statement, puts location and type of + * node into a node structure. * - * Results: 0 if the node was read correctly, 1 otherwise. + * Results: Pointer to the node record if the node was read correctly, + * NULL otherwise. + * + * Side Effects: see above + * + *------------------------------------------------------------------------- + */ + +ResExtNode * +ResReadNode(int argc, char *argv[]) +{ + HashEntry *entry; + ResExtNode *node; + + entry = HashFind(&ResNodeTable, argv[NODES_NODENAME]); + node = ResInitializeNode(entry); + + node->location.p_x = atoi(argv[NODES_NODEX]); + node->location.p_y = atoi(argv[NODES_NODEY]); + node->type = DBTechNameType(argv[NODES_NODETYPE]); + + if (node->type == -1) + { + TxError("Bad tile type name in .ext file for node %s\n", node->name); + return NULL; + } + return node; +} + +/* + *------------------------------------------------------------------------- + * + * ResReadPort-- Reads in a port statement from the .ext file and sets + * node records accordingly to mark the node as a drivepoint. + * + * Results: 0 if successful and 1 otherwise. * * Side Effects: see above * @@ -186,366 +247,255 @@ ResReadExt(char *extfile); */ int -ResReadNode(int argc, char *argv[]) +ResReadPort(int argc, + char *argv[]) { HashEntry *entry; ResExtNode *node; - char *cp; - float lambda; - entry = HashFind(&ResNodeTable, line[NODES_NODENAME]); + entry = HashFind(&ResNodeTable, argv[PORT_NAME]); node = ResInitializeNode(entry); - node->location.p_x = atoi(line[NODES_NODEX]); - node->location.p_y = atoi(line[NODES_NODEY]); - if ((cp = strchr(line[NODES_NODETYPE], ';'))) *cp = '\0'; - node->type = DBTechNameType(line[NODES_NODETYPE]); + node->drivepoint.p_x = atoi(argv[PORT_LLX]); + node->drivepoint.p_y = atoi(argv[PORT_LLY]); + node->status |= FORCE; + /* To do: Check for multiple ports on a net; each port needs its + * own drivepoint. + */ + node->status |= DRIVELOC | PORTNODE; + node->rs_bbox.r_ll = node->drivepoint; + node->rs_bbox.r_ur.p_x = atoi(argv[PORT_URX]); + node->rs_bbox.r_ur.p_y = atoi(argv[PORT_URY]); + node->rs_ttype = DBTechNoisyNameType(argv[PORT_TYPE]); + node->type = node->rs_ttype; if (node->type == -1) { - TxError("Bad tile type name in .ext file for node %s\n", - node->name); + TxError("Bad tile type name in .ext file for node %s\n", node->name); return 1; } return 0; } +/* + *------------------------------------------------------------------------- + * + * ResNodeAddDevice -- + * + * Given a device and a node which connects to one of its terminals, + * add the device to the node's device list. Device type is one + * of the indexes defined by GATE, SOURCE, or DRAIN (to do: generalize + * this). + * + * Results: + * None. + * + * Side effects: + * Allocates memory for a devPtr, adds to the node's firstDev linked + * list. + * + *------------------------------------------------------------------------- + */ + +void +ResNodeAddDevice(ResExtNode *node, + RDev *device, + int termtype) +{ + devPtr *tptr; + + tptr = (devPtr *)mallocMagic((unsigned)(sizeof(devPtr))); + tptr->thisDev = device; + tptr->nextDev = node->firstDev; + node->firstDev = tptr; + tptr->terminal = termtype; +} + +/* + *------------------------------------------------------------------------- + * + * ResReadDevice-- + * + * Process a "device" line from a ext file. + * + * Results: returns 0 if line was added correctly. + * + * Side Effects: Allocates devicesl + * + *------------------------------------------------------------------------- + */ + +int +ResReadDevice(int argc, + char *argv[]) +{ + RDev *device; + int rvalue, i, j, k; + ExtDevice *devptr; + TileType ttype; + HashEntry *entry; + ResExtNode *node; + + device = (RDev *)mallocMagic((unsigned)(sizeof(RDev))); + + device->resistance = 0; /* Linear resistance from FET line, unused */ + + device->status = FALSE; + device->nextDev = ResRDevList; + + /* Find the device definition record corresponding to the device name */ + devptr = (ExtDevice *)NULL; + for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++) + { + for (devptr = ExtCurStyle->exts_device[ttype]; devptr; + devptr = devptr->exts_next) + if (!strcmp(devptr->exts_deviceName, argv[DEV_NAME])) break; + if (devptr != NULL) break; + } + + device->location.p_x = atoi(argv[DEV_X]); + device->location.p_y = atoi(argv[DEV_Y]); + + device->rs_gattr = RDEV_NOATTR; + device->rs_sattr = RDEV_NOATTR; + device->rs_dattr = RDEV_NOATTR; + device->rs_devptr = devptr; + + device->source = (ResExtNode *)NULL; + device->drain = (ResExtNode *)NULL; + device->subs = (ResExtNode *)NULL; + + /* Pass over parameters and find the next argument */ + for (i = DEV_Y; i < argc; i++) + if (!StrIsInt(argv[i]) && !(strchr(argv[i], '='))) + break; + + if (i == argc) + { + TxError("Bad device %s: Too few arguments in .ext file\n", + argv[DEV_NAME]); + return 1; + } + + /* Find and record the device terminal nodes */ + /* Note that this only records up to two terminals matching FET + * source and drain; it needs to be expanded to include an + * arbitrary number of terminals. + */ + + if (strcmp(argv[i], "None")) + { + entry = HashFind(&ResNodeTable, argv[i]); + device->subs = (ResExtNode *)HashGetValue(entry); + ResNodeAddDevice(device->subs, device, SUBS); + } + i++; + entry = HashFind(&ResNodeTable, argv[i]); + device->gate = (ResExtNode *)HashGetValue(entry); + device->rs_gattr = StrDup((char **)NULL, argv[i + 2]); + ResNodeAddDevice(device->gate, device, GATE); + i += 3; + + if (i < argc - 2) + { + entry = HashFind(&ResNodeTable, argv[i]); + device->source = (ResExtNode *)HashGetValue(entry); + device->rs_sattr = StrDup((char **)NULL, argv[i + 2]); + ResNodeAddDevice(device->source, device, SOURCE); + i += 3; + } + + if (i < argc - 2) + { + entry = HashFind(&ResNodeTable, argv[i]); + device->drain = (ResExtNode *)HashGetValue(entry); + device->rs_dattr = StrDup((char **)NULL, argv[i + 2]); + ResNodeAddDevice(device->drain, device, DRAIN); + i += 3; + } + if (i < argc - 2) + { + TxError("Warning: Device %s has more than 4 ports (not handled).\n", + argv[DEV_NAME]); + } + + device->rs_ttype = extGetDevType(devptr->exts_deviceName); + + ResRDevList = device; + device->layout = NULL; + return 0; +} /* *------------------------------------------------------------------------- * - * ResReadSubckt-- Processes a subcircuit line from a ext file. - * This uses the "user subcircuit" extension defined in - * IRSIM, although it is mostly intended as a way to work - * around the device type limitations of the .ext format - * when using extresist. + * ResReadFET-- Processes a "fet" line from a ext file. * * Results: returns 0 if line was added correctly. * - * Side Effects: Allocates devices and adds nodes to the node hash table. + * Side Effects: Allocates devices. * *------------------------------------------------------------------------- */ int -ResReadSubckt(line) - char line[][MAXTOKEN]; +ResReadFET(int argc, + char *argv[]) { RDev *device; int rvalue, i, j, k; - static int nowarning = TRUE; - float lambda; - TileType ttype = TT_SPACE; - char *lptr = NULL, *wptr = NULL; ExtDevice *devptr; - - device = (RDev *) mallocMagic((unsigned) (sizeof(RDev))); - - device->status = FALSE; - device->nextDev = ResRDevList; - - lambda = (float)ExtCurStyle->exts_unitsPerLambda / resscale; - device->location.p_x = 0; - device->location.p_y = 0; - - device->rs_gattr=RDEV_NOATTR; - device->rs_sattr=RDEV_NOATTR; - device->rs_dattr=RDEV_NOATTR; - - ResRDevList = device; - device->layout = NULL; - device->source = device->drain = device->gate = device->subs = NULL; - - /* The last argument is the name of the device */ - for (i = 1; line[i][0] != '\0'; i++); - i--; - - /* To do: Replace this search with a pre-prepared hash */ - /* table to key off of the device name. */ - for (j = 0; j < EFDevNumTypes; j++) - if (!strcmp(EFDevTypes[j], line[i])) - break; - - /* Read attributes, especially to pick up values for L, W, X, and Y; - * and source and drain area and perimeter, that are critical for use - * by extresist. - */ - for (k = 1; line[k][0] != '\0'; k++) - { - char *eqptr; - eqptr = strchr(line[k], '='); - if (eqptr != NULL) - { - if (k < i) i = k; - eqptr++; - switch (line[k][0]) { - case 'l': - lptr = eqptr; - break; - case 'w': - wptr = eqptr; - break; - case 'x': - device->location.p_x = (int)((float)atof(eqptr) / lambda); - break; - case 'y': - device->location.p_y = (int)((float)atof(eqptr) / lambda); - break; - case 's': - device->rs_sattr = StrDup((char **)NULL, eqptr); - break; - case 'd': - device->rs_dattr = StrDup((char **)NULL, eqptr); - break; - } - } - } - - if (j == EFDevNumTypes) - { - TxError("Failure to find device type %s\n", line[i]); - return 1; - } - ttype = extGetDevType(EFDevTypes[j]); - ASSERT(ttype >= 0, "ttype<0"); - - /* Find the device record that corresponds to the device name */ - for (devptr = ExtCurStyle->exts_device[ttype]; devptr; devptr = devptr->exts_next) - if (!strcmp(devptr->exts_deviceName, EFDevTypes[j])) - break; - - device->rs_devptr = devptr; - device->rs_ttype = ttype; - - if (lptr != NULL && wptr != NULL) - { - HashEntry *he; - float rpersquare; - - he = HashLookOnly(&devptr->exts_deviceResist, "linear"); - if (he != NULL) - rpersquare = (ResValue)(spointertype)HashGetValue(he); - else - rpersquare = (ResValue)0.0; - /* Subcircuit types may not have a length or width value, in which */ - /* case it is zero. Don't induce a divide-by-zero error. */ - if (MagAtof(wptr) == 0) - device->resistance = 0; - else - device->resistance = MagAtof(lptr) * rpersquare/MagAtof(wptr); - } - else - device->resistance = 0; - - rvalue = 0; - for (k = 1; k < i; k++) - { - if (k > SUBS) - { - TxError("Device %s has more than 4 ports (not handled).\n", line[i]); - break; /* No method to handle more ports than this */ - } - rvalue += ResExtNewNode(line[k], k, device); - } - - return rvalue; -} - -/* - *------------------------------------------------------------------------- - * - * ResReadDevice-- Processes a device line from a ext file. - * - * Results: returns 0 if line was added correctly. - * - * Side Effects: Allocates devices and adds nodes to the node hash table. - * - *------------------------------------------------------------------------- - */ - -int -ResReadDevice(line, rpersquare, devptr) - char line[][MAXTOKEN]; - float rpersquare; - ExtDevice *devptr; - -{ - RDev *device; - int rvalue, i, j, k; - char *newattr, tmpattr[MAXTOKEN]; - static int nowarning = TRUE; - float lambda; - ExtDevice *devtest; - - if ((line[RDEV_WIDTH][0] == '\0') || (line[RDEV_LENGTH][0] == '\0')) - { - TxError("error in input file:\n"); - return 1; - } + TileType ttype; + HashEntry *entry; + ResExtNode *node; device = (RDev *)mallocMagic((unsigned)(sizeof(RDev))); - if (nowarning && rpersquare == 0) - { - TxError("Warning: FET resistance not included or " - "set to zero in technology file-\n"); - TxError("All driven nodes will be extracted\n"); - nowarning = FALSE; - } - if (MagAtof(line[RDEV_WIDTH]) != 0) - device->resistance = MagAtof(line[RDEV_LENGTH]) * rpersquare / - MagAtof(line[RDEV_WIDTH]); - else - device->resistance = 0; + + device->resistance = 0; /* Linear resistance from FET line, unused */ device->status = FALSE; device->nextDev = ResRDevList; - /* Check that devptr matches the device name and number of terminals */ - /* Note that this routine is only called for the original "fet" */ - /* types with fixed names, so the names must match and there must */ - /* always be three terminals (two source/drain terminals). */ + /* Find the device definition record corresponding to the device name */ + devptr = (ExtDevice *)NULL; + for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++) + { + for (devptr = ExtCurStyle->exts_device[ttype]; devptr; + devptr = devptr->exts_next) + if (!strcmp(devptr->exts_deviceName, argv[FET_NAME])) break; + if (devptr != NULL) break; + } - if (devptr->exts_deviceSDCount != 2) - for (devtest = devptr->exts_next; devtest; devtest = devtest->exts_next) - if (devtest->exts_deviceSDCount == 2) - { - devptr = devtest; - break; - } - - lambda = (float)ExtCurStyle->exts_unitsPerLambda / resscale; - device->location.p_x = (int)((float)atof(line[RDEV_DEVX]) / lambda); - device->location.p_y = (int)((float)atof(line[RDEV_DEVY]) / lambda); + device->location.p_x = atoi(argv[FET_X]); + device->location.p_y = atoi(argv[FET_Y]); device->rs_gattr=RDEV_NOATTR; device->rs_sattr=RDEV_NOATTR; device->rs_dattr=RDEV_NOATTR; device->rs_devptr = devptr; - device->gate = device->source = device->drain = device->subs = NULL; + /* Find and record the FET terminal nodes */ + + entry = HashFind(&ResNodeTable, argv[FET_GATE]); + device->gate = (ResExtNode *)HashGetValue(entry); + + entry = HashFind(&ResNodeTable, argv[FET_SOURCE]); + device->source = (ResExtNode *)HashGetValue(entry); + + entry = HashFind(&ResNodeTable, argv[FET_DRAIN]); + device->drain = (ResExtNode *)HashGetValue(entry); + + entry = HashFind(&ResNodeTable, argv[FET_SUBS]); + device->subs = (ResExtNode *)HashGetValue(entry); device->rs_ttype = extGetDevType(devptr->exts_deviceName); - /* ext attributes look like g=a1,a2 */ - /* ext attributes are "a1","a2" */ - /* Do conversion from one to the other here */ - /* NOTE: As of version 8.3.366, .ext attributes will end in two */ - /* integer values, not quoted, for device area and perimeter. Do */ - /* not quote them. */ + /* Copy attributes verbatim */ + device->rs_gattr = StrDup((char **)NULL, argv[FET_GATE_ATTR]); + device->rs_sattr = StrDup((char **)NULL, argv[FET_SOURCE_ATTR]); + device->rs_dattr = StrDup((char **)NULL, argv[FET_DRAIN_ATTR]); - for (i = RDEV_ATTR; i < RDEV_ATTR + RDEV_NUM_ATTR; i++) - { - char *cptr, *sptr; - int d1, d2; - - if (line[i][0] == '\0') break; - - sptr = &line[i][2]; /* Start after "s=" or "d=" */ - tmpattr[0] = '\0'; - while ((cptr = strchr(sptr, ',')) != NULL) - { - if (sscanf(sptr, "%d,%d", &d1, &d2) == 2) - { - strcat(tmpattr, sptr); - sptr = NULL; - break; - } - else - { - *cptr = '\0'; - strcat(tmpattr, "\""); - strcat(tmpattr, sptr); - strcat(tmpattr, "\","); - sptr = cptr + 1; - *cptr = ','; - } - } - if (sptr && (strlen(sptr) != 0)) - { - strcat(tmpattr, "\""); - strcat(tmpattr, sptr); - strcat(tmpattr, "\""); - } - - newattr = (char *)mallocMagic(strlen(tmpattr) + 1); - strcpy(newattr, tmpattr); - switch (line[i][0]) - { - case 'g': - device->rs_gattr = newattr; - break; - case 's': - device->rs_sattr = newattr; - break; - case 'd': - device->rs_dattr = newattr; - break; - default: - TxError("Bad fet attribute\n"); - break; - } - } ResRDevList = device; device->layout = NULL; - rvalue = ResExtNewNode(line[GATE], GATE, device) + - ResExtNewNode(line[SOURCE], SOURCE, device) + - ResExtNewNode(line[DRAIN], DRAIN, device); - - return rvalue; -} - -/* - *------------------------------------------------------------------------- - * - * ResExtNewNode-- Adds a new node to the Node Hash Table. - * - * Results: returns zero if node is added correctly, one otherwise. - * - * Side Effects: Allocates a new ResExtNode - * - *------------------------------------------------------------------------- - */ - -int -ResExtNewNode(line, type, device) - char line[]; - int type; - RDev *device; - -{ - HashEntry *entry; - ResExtNode *node; - devPtr *tptr; - - if (line[0] == '\0') - { - TxError("Missing device connection\n"); - return 1; - } - entry = HashFind(&ResNodeTable, line); - node = ResInitializeNode(entry); - tptr = (devPtr *)mallocMagic((unsigned)(sizeof(devPtr))); - tptr->thisDev = device; - tptr->nextDev = node->firstDev; - node->firstDev = tptr; - tptr->terminal = type; - switch(type) - { - case GATE: - device->gate = node; - break; - case SOURCE: - device->source = node; - break; - case DRAIN: - device->drain = node; - break; - case SUBS: - device->subs = node; - break; - default: - TxError("Bad Terminal Specifier\n"); - break; - } return 0; } @@ -565,102 +515,36 @@ ResExtNewNode(line, type, device) */ int -ResReadCapacitor(line) - char line[][MAXTOKEN]; - +ResReadCapacitor(int argc, + char *argv[]) { HashEntry *entry1, *entry2; ResExtNode *node1, *node2; - if (line[COUPLETERMINAL1][0] == 0 || line[COUPLETERMINAL2][0] == 0) - { - TxError("Bad Capacitor\n"); - return(1); - } - entry1 = HashFind(&ResNodeTable, line[COUPLETERMINAL1]); + entry1 = HashFind(&ResNodeTable, argv[COUPLETERMINAL1]); node1 = ResInitializeNode(entry1); + if (ResOptionsFlags & ResOpt_Signal) { - node1->capacitance += MagAtof(line[COUPLEVALUE]); - if (strcmp(line[COUPLETERMINAL2], "GND") == 0 || - strcmp(line[COUPLETERMINAL2], "Vdd") == 0) - { - return 0; - } - entry2 = HashFind(&ResNodeTable, line[COUPLETERMINAL2]); + node1->capacitance += MagAtof(argv[COUPLEVALUE]); + entry2 = HashFind(&ResNodeTable, argv[COUPLETERMINAL2]); node2 = ResInitializeNode(entry2); - node2->capacitance += MagAtof(line[COUPLEVALUE]); + node2->capacitance += MagAtof(argv[COUPLEVALUE]); return 0; } - if (strcmp(line[COUPLETERMINAL2], "GND") == 0) - { - node1->capacitance += MagAtof(line[COUPLEVALUE]); - return 0; - } - if (strcmp(line[COUPLETERMINAL2], "Vdd") == 0) - { - node1->cap_vdd += MagAtof(line[COUPLEVALUE]); - return 0; - } - entry2 = HashFind(&ResNodeTable, line[COUPLETERMINAL2]); + + entry2 = HashFind(&ResNodeTable, argv[COUPLETERMINAL2]); node2 = ResInitializeNode(entry2); - if (strcmp(line[COUPLETERMINAL1], "GND") == 0) - { - node2->capacitance += MagAtof(line[COUPLEVALUE]); - return 0; - } - if (strcmp(line[COUPLETERMINAL1], "Vdd") == 0) - { - node2->cap_vdd += MagAtof(line[COUPLEVALUE]); - return 0; - } - node1->cap_couple += MagAtof(line[COUPLEVALUE]); - node2->cap_couple += MagAtof(line[COUPLEVALUE]); + + node1->cap_couple += MagAtof(argv[COUPLEVALUE]); + node2->cap_couple += MagAtof(argv[COUPLEVALUE]); return 0; } - /* *------------------------------------------------------------------------- * - * ResReadResistor-- Adds the capacitance from a R line to the appropriate - * node. - * - * Results - * Return 0 to keep search going, 1 to abort - * - * Side Effects: modifies resistance field of ResExtNode - * - *------------------------------------------------------------------------- - */ - -int -ResReadResistor(line) - char line[][MAXTOKEN]; -{ - HashEntry *entry; - ResExtNode *node; - - if (line[RESNODENAME][0] == 0) - { - TxError("Bad Resistor\n"); - return 1; - } - entry = HashFind(&ResNodeTable, line[RESNODENAME]); - node = ResInitializeNode(entry); - if (node->resistance != 0) - { - TxError("Duplicate Resistance Entries\n"); - return 1; - } - node->resistance = MagAtof(line[NODERESISTANCE]); - return(0); -} - -/* - *------------------------------------------------------------------------- - * - * ResExtAttribute--checks to see if a node attribute is a resistance + * ResReadAttribute--checks to see if a node attribute is a resistance * attribute. If it is, add it to the correct node's status flag. * Only works with 5.0 1/line attributes * @@ -673,25 +557,18 @@ ResReadResistor(line) */ int -ResReadAttribute(aname, avalue, readdrivepoints) - char *aname; - char *avalue; - bool *readdrivepoints; - +ResReadAttribute(ResExtNode *node, + int argc, + char *argv[]) { - HashEntry *entry; - ResExtNode *node; + char *aname, *avalue; char digit[MAXDIGIT]; int i; static int notwarned = TRUE; - if (aname[0] == 0) - { - TxError("Bad Resistor\n"); - return 1; - } - entry = HashFind(&ResNodeTable, aname); - node = ResInitializeNode(entry); + aname = argv[RES_EXT_ATTR_NAME]; + avalue = argv[RES_EXT_ATTR_TEXT]; + if (strncmp(avalue, "res:skip", 8) == 0) { if (node->status & FORCE) @@ -723,133 +600,14 @@ ResReadAttribute(aname, avalue, readdrivepoints) else if (strncmp(avalue, "res:drive", 9) == 0 && (ResOptionsFlags & ResOpt_Signal)) { - if (*readdrivepoints == FALSE) - { - ResExtProcessDrivePoints(rootname); - *readddrivepoints = TRUE; - } - /* is the attribute in root.ext? */ - if (node->drivepoint.p_x != INFINITY) - node->status |= DRIVELOC; - else - { - if (notwarned) - TxError("Drivepoint for %s not defined in %s.ext; is it " - "defined in a child cell?\n", node->name, rootname); - notwarned = FALSE; - } + node->drivepoint.p_x = atoi(argv[RES_EXT_ATTR_X]); + node->drivepoint.p_y = atoi(argv[RES_EXT_ATTR_Y]); + node->rs_ttype = DBTechNoisyNameType(argv[RES_EXT_ATTR_TYPE]); + node->status |= DRIVELOC; } return 0; } -/* - *------------------------------------------------------------------------- - * - * ResExtProcessDrivePoints -- if the ext file contains a res:drive attribute, - * and we are doing a signal extraction, - * we need to search through the .ext file looking for attr labels that - * contain this text. For efficiency, the .ext file is only parsed when - * the first res:drive is encountered. res:drive labels only work if - * they are in the root cell. - * - * FIXME---The .ext file is being read and this routine should only - * read in additional lines as necessary. - * - * Results: - * None. - * - * Side Effects: - * - *------------------------------------------------------------------------- - */ - -void -ResExtProcessDrivePoints(FILE *fp) -{ - char line[MAXLINE][MAXTOKEN]; - FILE *fp; - HashEntry *entry; - ResExtNode *node; - - while (gettokens(line, fp) != 0) - { - if (strncmp(line[RES_EXT_ATTR], "attr", 4) != 0 || - strncmp(line[RES_EXT_ATTR_TEXT], "\"res:drive\"", 11) != 0) - continue; - - entry = HashFind(&ResNodeTable, line[RES_EXT_ATTR_NAME]); - node = ResInitializeNode(entry); - node->drivepoint.p_x = atoi(line[RES_EXT_ATTR_X]); - node->drivepoint.p_y = atoi(line[RES_EXT_ATTR_Y]); - node->rs_ttype = DBTechNoisyNameType(line[RES_EXT_ATTR_TILE]); - } - fclose(fp); -} - -/* - *------------------------------------------------------------------------- - * - * ResExtProcessFixPoints -- if the ext file contains a "res:fix:name" label - * and we are checking for power supply noise, then we have to - * parse the .ext file looking for the fix label locations. This - * is only done after the first res:fix label is encountered. - * - * (FIXME---This is now all in the .ext file so the information does - * not need to be read twice.) - * - * Results: - * None. - * - * Side Effects: - * For each new name, allocate memory - * - *------------------------------------------------------------------------- - */ - -void -ResExtProcessFixPoints(filename) - char *filename; -{ - char line[MAXLINE][MAXTOKEN], *label, *c; - FILE *fp; - ResFixPoint *thisfix; - - fp = PaOpen(filename, "r", ".ext", (ExtLocalPath == NULL) ? "." : ExtLocalPath, - (char *)NULL, (char **)NULL); - if (fp == NULL) - { - TxError("Cannot open file %s%s\n", filename, ".ext"); - return; - } - while (gettokens(line, fp) != 0) - { - if (strncmp(line[RES_EXT_ATTR], "attr", 4) != 0 || - strncmp(line[RES_EXT_ATTR_TEXT], "\"res:fix", 8) != 0) - continue; - label = line[RES_EXT_ATTR_TEXT]; - label += 8; - if (*label == ':') label++; - if ((c=strrchr(label, '"')) != NULL) *c = '\0'; - else if (*label != '\0') - { - TxError("Bad res:fix attribute label %s\n", - line[RES_EXT_ATTR_TEXT]); - *label ='\0'; - } - thisfix = (ResFixPoint *)mallocMagic((unsigned)(sizeof(ResFixPoint) - + strlen(label))); - thisfix->fp_next = ResFixList; - ResFixList = thisfix; - thisfix->fp_loc.p_x = atoi(line[RES_EXT_ATTR_X]); - thisfix->fp_loc.p_y = atoi(line[RES_EXT_ATTR_Y]); - thisfix->fp_ttype = DBTechNoisyNameType(line[RES_EXT_ATTR_TILE]); - thisfix->fp_tile = NULL; - strcpy(thisfix->fp_name, label); - } - fclose(fp); -} - - /* *------------------------------------------------------------------------- * diff --git a/resis/ResRex.c b/resis/ResRex.c index 6ecc7456..befbb73b 100644 --- a/resis/ResRex.c +++ b/resis/ResRex.c @@ -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) diff --git a/resis/ResSimple.c b/resis/ResSimple.c index 9eed823f..dc362f40 100644 --- a/resis/ResSimple.c +++ b/resis/ResSimple.c @@ -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; diff --git a/resis/resis.h b/resis/resis.h index 1da90a86..ea51b499 100644 --- a/resis/resis.h +++ b/resis/resis.h @@ -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();