Slowly working through things needed for removing the ".sim"

file dependency of "extresist".  Stopping and committing work
in order to rebase from the master branch.
This commit is contained in:
R. Timothy Edwards 2026-01-27 11:56:47 -05:00
parent 297a05c4ed
commit 76f97c90e5
16 changed files with 420 additions and 824 deletions

68
README
View File

@ -132,3 +132,71 @@ around for the duration of the extraction, and needs to have the
extresist splits on hand for coupling capacitance calculations
and all output. Maybe copy in a simplified form to yet another
ClientData field on a nodeRegion.
So there's another way to go about it:
(1) When running extract, create the device record for extresist
after running transList = ExtFindRegions(). This list does
not change between being created and the transistors being
output.
(2) Create the node record for extresist after running extFindNodes().
(3) With this information, it's possible to run extresist on the
node. Because nodes have all been marked with regions, use
a ClientData record in NodeRegion to store the extresist working
data. Clean up afterward; the NodeRegion records still remain
in place on the tiles.
The simplest approach is just to write the .res.ext annotation file
as before, although with the extresist code being run before the
.ext file is written, it is possible to combine the two. But the
use of .res.ext is a quicker intermediate step that allows the
extresist code to be checked for hierarchical operation, which it
will now be able to do relatively smoothly, as it is not necessary
to create multiple .sim and .node files for each subcircuit.
Trickier: Replace NodeRegions with the subnet regions. One
difficulty here is dealing with multiple subnets in a single tile.
Simplifying the extresist code by removing references to ARIEL
and LAPLACE (which are missing code and so cannot be reinstated
without a lot of guesswork), and removing some apparently nonfunctional
code having to do with events.
To do after finding transistors: What's done in ResReadSim():
Specifically, ResSimDevice() and ResSimSubckt().
ResReadNode() is the only thing needed to be done for nodes.
It calls ResInitializeNode() and sets location and (tile) type.
Everything else in the structure is TBD.
Another issue: The device type is determined by "extract" only
during extOutputDevices. The device type in "devrec" is not
computed until just before the device is output. But. . . is
this really needed by extresist? It was being used by extresist
because the device name is what's in the .sim file.
You know what probably works best?
(1) When nodes are written to the .ext file, save the information
for extresist.
(2) When devices are written to the .ext file, save the information
for extresist.
(3) Run extresist at the end of the cell def's extraction, and write
the .res.ext file as usual. (Later, maybe, get rid of the
.res.ext file and just re-write the annotated .ext file.)
(4) Create a new method for annotated coupling capacitances.
Recompute the coupling and output adjustments (positive for
the new node/terminal nodes, negative for the original node).
Coupling will be recomputed only for nets processed by
extresist. Node substrate capacitance changes will be
recorded in .res.ext (but---I think substrate capacitance is
now unused in the node record, because there is a substrate
node and substrate capacitance is now treated like coupling
to that node; isn't that right?) (and there will be multiple
substrate nodes, as well.)
This can also be done in two steps:
(1) Replace ResReadSim() with ResReadExt() and read back the .ext
file immediately after writing it.
(2) Remove the read-back and just generate the information on the
fly.
This also has the advantage that it can be tested in parts.

View File

@ -37,6 +37,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "commands/commands.h"
#include "database/database.h"
#include "extflat/extflat.h"
#include "extflat/extparse.h"
#include "extflat/EFint.h"
#include "extract/extract.h"
#include "extract/extractInt.h"
@ -45,61 +46,6 @@ 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
/*
* The following table describes the kinds of lines
* that may be read in a .ext file.
*/
typedef enum
{
ABSTRACT, ADJUST, ATTR, CAP, DEVICE, DIST, EQUIV, FET, KILLNODE, MERGE,
NODE, PARAMETERS, PORT, PRIMITIVE, RESISTOR, RESISTCLASS, RNODE, SCALE,
SUBCAP, SUBSTRATE, TECH, TIMESTAMP, USE, VERSION, EXT_STYLE
} Key;
static const struct
{
const char *k_name; /* Name of first token on line */
Key k_key; /* Internal name for token of this type */
int k_mintokens; /* Min total # of tokens on line of this type */
}
keyTable[] =
{
{"abstract", ABSTRACT, 0}, /* defines a LEF-like view */
{"adjust", ADJUST, 4},
{"attr", ATTR, 8},
{"cap", CAP, 4},
{"device", DEVICE, 11}, /* effectively replaces "fet" */
{"distance", DIST, 4},
{"equiv", EQUIV, 3},
{"fet", FET, 12}, /* for backwards compatibility */
{"killnode", KILLNODE, 2},
{"merge", MERGE, 3},
{"node", NODE, 7},
{"parameters", PARAMETERS, 3},
{"port", PORT, 8},
{"primitive", PRIMITIVE, 0}, /* defines a primitive device */
{"resist", RESISTOR, 4},
{"resistclasses", RESISTCLASS, 1},
{"rnode", RNODE, 5},
{"scale", SCALE, 4},
{"subcap", SUBCAP, 3},
{"substrate", SUBSTRATE, 3},
{"tech", TECH, 2},
{"timestamp", TIMESTAMP, 2},
{"use", USE, 9},
{"version", VERSION, 2},
{"style", EXT_STYLE, 2},
{0}
};
/* Data shared with EFerror.c */
char *efReadFileName; /* Name of file currently being read */
int efReadLineNum; /* Current line number in above file */
@ -109,10 +55,6 @@ bool EFSaveLocs; /* If TRUE, save location of merged top-level nodes */
/* Data local to this file */
static bool efReadDef(Def *def, bool dosubckt, bool resist, bool noscale, bool toplevel, bool isspice);
/* atoCap - convert a string to a EFCapValue */
#define atoCap(s) ((EFCapValue)atof(s))
/*
* ----------------------------------------------------------------------------
*

84
extflat/extparse.h Normal file
View File

@ -0,0 +1,84 @@
/*
* extparse.h
*
* Definitions for the .ext file parser. Relocated from EFread.c.
*
* *********************************************************************
* * Copyright (C) 1985, 1990 Regents of the University of California. *
* * Permission to use, copy, modify, and distribute this *
* * software and its documentation for any purpose and without *
* * fee is hereby granted, provided that the above copyright *
* * notice appear in all copies. The University of California *
* * makes no representations about the suitability of this *
* * software for any purpose. It is provided "as is" without *
* * express or implied warranty. Export of this software outside *
* * of the United States of America may require an export license. *
* *********************************************************************
*/
/* 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
/*
* The following table describes the kinds of lines
* that may be read in a .ext file.
*/
typedef enum
{
ABSTRACT, ADJUST, ATTR, CAP, DEVICE, DIST, EQUIV, FET, KILLNODE, MERGE,
NODE, PARAMETERS, PORT, PRIMITIVE, RESISTOR, RESISTCLASS, RNODE, SCALE,
SUBCAP, SUBSTRATE, TECH, TIMESTAMP, USE, VERSION, EXT_STYLE
} Key;
static const struct
{
const char *k_name; /* Name of first token on line */
Key k_key; /* Internal name for token of this type */
int k_mintokens; /* Min total # of tokens on line of this type */
}
keyTable[] =
{
{"abstract", ABSTRACT, 0}, /* defines a LEF-like view */
{"adjust", ADJUST, 4},
{"attr", ATTR, 8},
{"cap", CAP, 4},
{"device", DEVICE, 11}, /* effectively replaces "fet" */
{"distance", DIST, 4},
{"equiv", EQUIV, 3},
{"fet", FET, 12}, /* for backwards compatibility */
{"killnode", KILLNODE, 2},
{"merge", MERGE, 3},
{"node", NODE, 7},
{"parameters", PARAMETERS, 3},
{"port", PORT, 8},
{"primitive", PRIMITIVE, 0}, /* defines a primitive device */
{"resist", RESISTOR, 4},
{"resistclasses", RESISTCLASS, 1},
{"rnode", RNODE, 5},
{"scale", SCALE, 4},
{"subcap", SUBCAP, 3},
{"substrate", SUBSTRATE, 3},
{"tech", TECH, 2},
{"timestamp", TIMESTAMP, 2},
{"use", USE, 9},
{"version", VERSION, 2},
{"style", EXT_STYLE, 2},
{0}
};
/* atoCap - convert a string to a EFCapValue */
#define atoCap(s) ((EFCapValue)atof(s))
extern int efReadLineNum; /* Current line number in the .ext file */

View File

@ -37,6 +37,7 @@ static char sccsid[] = "@(#)ExtBasic.c 4.13 MAGIC (Berkeley) 12/5/85";
#include "utils/malloc.h"
#include "textio/textio.h"
#include "debug/debug.h"
#include "extflat/extparse.h"
#include "extract/extract.h"
#include "extract/extractInt.h"
#include "utils/signals.h"
@ -45,20 +46,7 @@ static char sccsid[] = "@(#)ExtBasic.c 4.13 MAGIC (Berkeley) 12/5/85";
#include "utils/styles.h"
#include "utils/stack.h"
#include "utils/utils.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
#include "resis/resis.h"
/* --------------------- Data local to this file ---------------------- */
@ -301,28 +289,6 @@ extBasic(def, outFile)
if (!SigInterruptPending && (ExtDoWarn & EXTWARN_DUP) && !isabstract)
extFindDuplicateLabels(def, nodeList);
/*
* If full R-C extraction is requested, then run it now. This
* code was previously run as the "extresist" command, but it
* makes more sense to be integral to the extraction process.
* It must be run prior to extFindCoupling() so that coupling
* capacitances are correctly assigned to subnets.
*/
if (!SigInterruptPending && (ExtOptions & EXT_DOEXTRESIST))
{
ResSimNode *rsimnode;
ResisData resisdata;
int n_ext = 0, n_out = 0;
for (reg = nodeList; reg && !SigInterruptPending; reg = reg->nreg_next)
{
rsimnode = ResCreateNode();
ResProcessNode(rsimnode, def, &resisdata, &n_ext, &n_out);
/* To be completed */
}
}
/*
* Build up table of coupling capacitances (overlap, sidewall).
* This comes before extOutputNodes because we may have to adjust
@ -580,6 +546,24 @@ 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);

View File

@ -5,7 +5,7 @@
MODULE = resis
MAGICDIR = ..
SRCS = ResMain.c ResJunct.c ResMakeRes.c ResSimple.c ResPrint.c \
ResReadSim.c ResRex.c ResBasic.c ResMerge.c ResChecks.c \
ResReadExt.c ResRex.c ResBasic.c ResMerge.c ResChecks.c \
ResFract.c ResUtils.c ResDebug.c
include ${MAGICDIR}/defs.mak

View File

@ -112,7 +112,6 @@ ResSanityChecks(nodename, resistorList, nodeList, devlist)
{
int i;
if (dev->rd_status & RES_DEV_PLUG) continue;
reached = FALSE;
for (i = 0; i != dev->rd_nterms; i++)
{

View File

@ -120,7 +120,6 @@ ResPrintDeviceList(fp, list)
int i;
for (; list != NULL; list = list->rd_nextDev)
{
if (list->rd_status & RES_DEV_PLUG) continue;
if (fp == stdout)
TxPrintf("t w %d l %d ", list->rd_width, list->rd_length);
else

View File

@ -41,7 +41,7 @@ int ResTileCount = 0; /* Number of tiles rn_status */
extern ExtRegion *ResFirst();
extern Tile *FindStartTile();
extern int ResEachTile();
extern ResSimNode *ResInitializeNode();
extern ResExtNode *ResInitializeNode();
TileTypeBitMask ResSDTypesBitMask;
TileTypeBitMask ResSubTypesBitMask;
@ -201,13 +201,13 @@ ResMakePortBreakpoints(def)
TileTypeBitMask mask;
HashSearch hs;
HashEntry *entry;
ResSimNode *node;
ResExtNode *node;
int ResAddBreakpointFunc(); /* Forward Declaration */
HashStartSearch(&hs);
while((entry = HashNext(&ResNodeTable,&hs)) != NULL)
{
node = (ResSimNode *)HashGetValue(entry);
node = (ResExtNode *)HashGetValue(entry);
if (node->status & PORTNODE)
{
if (node->rs_ttype <= 0)
@ -281,7 +281,7 @@ ResMakeLabelBreakpoints(def, goodies)
Rect *rect;
TileTypeBitMask mask;
HashEntry *entry;
ResSimNode *node;
ResExtNode *node;
Label *slab;
int ResAddBreakpointFunc(); /* Forward Declaration */
@ -353,7 +353,7 @@ int
ResAddBreakpointFunc(tile, dinfo, node)
Tile *tile;
TileType dinfo; /* (unused) */
ResSimNode *node;
ResExtNode *node;
{
tileJunk *junk;
@ -512,51 +512,6 @@ ResProcessTiles(goodies, origin)
resCurrentNode = NULL;
(void) ResEachTile(startTile, origin);
}
#ifdef ARIEL
else if (ResOptionsFlags & ResOpt_Power)
{
for (fix = ResFixList; fix != NULL; fix = fix->fp_next)
{
Tile *tile = fix->fp_tile;
if (tile == NULL)
{
tile = PlaneGetHint(ResDef->cd_planes[DBPlane(fix->fp_ttype)]);
GOTOPOINT(tile, &(fix->fp_loc));
if (TiGetTypeExact(tile) != TT_SPACE)
{
fix->fp_tile = tile;
}
else
{
tile = NULL;
}
}
if (tile != NULL)
{
int x = fix->fp_loc.p_x;
int y = fix->fp_loc.p_y;
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
InitializeNode(resptr, x, y, RES_NODE_ORIGIN);
resptr->rn_status = TRUE;
resptr->rn_noderes = 0;
ResAddToQueue(resptr, &ResNodeQueue);
fix->fp_node = resptr;
NEWBREAK(resptr, tile, x, y, NULL);
}
}
for (fix = ResFixList; fix != NULL; fix = fix->fp_next)
{
Tile *tile = fix->fp_tile;
if (tile != NULL && (((tileJunk *)TiGetClientPTR(tile)->tj_status &
RES_TILE_DONE) == 0)
{
resCurrentNode = fix->fp_node;
(void) ResEachTile(startile, (Point *)NULL);
}
}
}
#endif
#ifdef PARANOID
else
{
@ -1036,7 +991,7 @@ ResShaveContacts(tile, dinfo, def)
bool
ResExtractNet(node, goodies, cellname)
ResSimNode *node;
ResExtNode *node;
ResGlobalParams *goodies;
char *cellname;
{
@ -1103,11 +1058,6 @@ ResExtractNet(node, goodies, cellname)
DBCellClearDef(ResUse->cu_def);
#ifdef ARIEL
if ((ResOptionsFlags & ResOpt_Power) &&
strcmp(node->name, goodies->rg_name) != 0) continue;
#endif
/* Copy Paint */
scx.scx_area.r_ll.p_x = node->location.p_x - 2;
@ -1239,30 +1189,6 @@ ResExtractNet(node, goodies, cellname)
ResFindNewContactTiles(ResContactList);
ResPreProcessDevices(DevTiles, ResDevList, ResUse->cu_def);
#ifdef LAPLACE
if (ResOptionsFlags & ResOpt_DoLaplace)
{
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
{
Plane *plane = ResUse->cu_def->cd_planes[pNum];
Rect *rect = &ResUse->cu_def->cd_bbox;
Res1d(plane, rect);
}
}
#endif
#ifdef ARIEL
if (ResOptionsFlags & ResOpt_Power)
{
for (fix = startlist; fix != NULL; fix = fix->fp_next)
{
fix->fp_tile = PlaneGetHint(ResUse->cu_def->cd_planes[DBPlane(fix->fp_ttype)]);
GOTOPOINT(fix->fp_tile, &fix->fp_loc);
if (TiGetTypeExact(fix->fp_tile) == TT_SPACE) fix->fp_tile = NULL;
}
}
#endif
/* do extraction */
if (ResProcessTiles(goodies, &startpoint) != 0) return TRUE;
return FALSE;

View File

@ -263,10 +263,6 @@ ResCalcEastWest(tile, pendingList, doneList, resList)
{
resistor->rr_status = RES_EW;
}
#ifdef ARIEL
resistor->rr_csArea = height *
ExtCurStyle->exts_thick[resistor->rr_tt];
#endif
resistor->rr_value =
(float)ExtCurStyle->exts_sheetResist[resistor->rr_tt]
* (float)(p2->br_loc.p_x - p1->br_loc.p_x)
@ -440,10 +436,6 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList)
{
resistor->rr_status = RES_NS;
}
#ifdef ARIEL
resistor->rr_csArea = width
* ExtCurStyle->exts_thick[resistor->rr_tt];
#endif
resistor->rr_value =
(float)ExtCurStyle->exts_sheetResist[resistor->rr_tt]
* (float)(p2->br_loc.p_y - p1->br_loc.p_y)
@ -916,11 +908,6 @@ ResDoContacts(contact, nodes, resList)
resistor->rr_value =
(float)ExtCurStyle->exts_viaResist[contact->cp_type] /
(float)(squaresx * squaresy);
#ifdef ARIEL
resistor->rr_csArea =
(float)ExtCurStyle->exts_thick[contact->cp_type] /
(float)(squaresx * squaresy);
#endif
resistor->rr_tt = contact->cp_type;
resistor->rr_float.rr_area = 0;
resistor->rr_status = 0;

View File

@ -150,14 +150,6 @@ ResFixRes(resptr, resptr2, resptr3, elimResis, newResis)
ASSERT(newResis->rr_value > 0, "series");
newResis->rr_float.rr_area += elimResis->rr_float.rr_area;
#ifdef ARIEL
if (elimResis->rr_csArea && elimResis->rr_csArea < newResis->rr_csArea
|| newResis->rr_csArea == 0)
{
newResis->rr_csArea = elimResis->rr_csArea;
newResis->rr_tt = elimResis->rr_tt;
}
#endif
for (thisREl = resptr3->rn_re; (thisREl != NULL); thisREl = thisREl->re_nextEl)
{
if (thisREl->re_thisEl == elimResis)
@ -206,9 +198,6 @@ ResFixParallel(elimResis, newResis)
newResis->rr_value = 0;
}
newResis->rr_float.rr_area += elimResis->rr_float.rr_area;
#ifdef ARIEL
newResis->rr_csArea += elimResis->rr_csArea;
#endif
ResDeleteResPointer(elimResis->rr_connection1, elimResis);
ResDeleteResPointer(elimResis->rr_connection2, elimResis);
ResEliminateResistor(elimResis, &ResResList);
@ -671,31 +660,16 @@ ResMergeNodes(node1, node2, pendingList, doneList)
workingDev = node2->rn_te;
while (workingDev != NULL)
{
if (workingDev->te_thist->rd_status & RES_DEV_PLUG)
{
ResPlug *plug = (ResPlug *) workingDev->te_thist;
if (plug->rpl_node == node2)
plug->rpl_node = node1;
else
{
TxError("Bad plug node: is (%d %d), should be (%d %d)\n",
plug->rpl_node->rn_loc.p_x, plug->rpl_node->rn_loc.p_y,
node2->rn_loc.p_x, node2->rn_loc.p_y);
plug->rpl_node = NULL;
}
}
else
{
int j;
int j;
for (j = 0; j != workingDev->te_thist->rd_nterms; j++)
if (workingDev->te_thist->rd_terminals[j] == node2)
workingDev->te_thist->rd_terminals[j] = node1;
}
tDev = workingDev;
workingDev = workingDev->te_nextt;
tDev->te_nextt = node1->rn_te;
node1->rn_te = tDev;
for (j = 0; j != workingDev->te_thist->rd_nterms; j++)
if (workingDev->te_thist->rd_terminals[j] == node2)
workingDev->te_thist->rd_terminals[j] = node1;
tDev = workingDev;
workingDev = workingDev->te_nextt;
tDev->te_nextt = node1->rn_te;
node1->rn_te = tDev;
}
/* append junction lists */
@ -749,11 +723,11 @@ ResMergeNodes(node1, node2, pendingList, doneList)
else if ((node2->rn_name != NULL) && (node2->rn_name != node1->rn_name))
{
HashEntry *entry;
ResSimNode *node;
ResExtNode *node;
/* Check if node2 is a port */
entry = HashFind(&ResNodeTable, node2->rn_name);
node = (ResSimNode *)HashGetValue(entry);
node = (ResExtNode *)HashGetValue(entry);
if (node && (node->status & PORTNODE))
node1->rn_name = node2->rn_name;
}

View File

@ -32,7 +32,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#define MAXNAME 1000
#define KV_TO_mV 1000000
extern ResSimNode *ResInitializeNode();
extern ResExtNode *ResInitializeNode();
/*
@ -57,7 +57,7 @@ ResPrintExtRes(outextfile, resistors, nodename)
int nodenum=0;
char newname[MAXNAME];
HashEntry *entry;
ResSimNode *node, *ResInitializeNode();
ResExtNode *node, *ResInitializeNode();
for (; resistors != NULL; resistors = resistors->rr_nextResistor)
{
@ -215,13 +215,13 @@ void
ResPrintExtNode(outextfile, nodelist, node)
FILE *outextfile;
resNode *nodelist;
ResSimNode *node;
ResExtNode *node;
{
char *nodename = node->name;
int nodenum = 0;
char newname[MAXNAME+32], tmpname[MAXNAME], *cp;
HashEntry *entry;
ResSimNode *newnode, *ResInitializeNode();
ResExtNode *newnode, *ResInitializeNode();
bool DoKillNode = TRUE;
bool NeedFix = FALSE;
resNode *snode;
@ -411,14 +411,14 @@ ResPrintFHNodes(fp, nodelist, nodename, nidx, celldef)
else
{
HashEntry *entry;
ResSimNode *simnode;
ResExtNode *simnode;
/* If we process another sim file node while doing this */
/* one, mark it as status "REDUNDANT" so we don't duplicate */
/* the entry. */
entry = HashFind(&ResNodeTable, nodeptr->rn_name);
simnode = (ResSimNode *)HashGetValue(entry);
simnode = (ResExtNode *)HashGetValue(entry);
if (simnode != NULL)
simnode->status |= REDUNDANT;
}

View File

@ -1,12 +1,13 @@
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResReadSim.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResReadExt.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
/*
*-------------------------------------------------------------------------
*
* ResReadSim.c -- Routines to parse .sim files
* ResReadExt.c -- Routines to parse .ext files for information needed
* by extresist.
*
*-------------------------------------------------------------------------
*/
@ -35,8 +36,9 @@ 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 .sim files. */
#define RDEV_LENGTH 4
#define RDEV_WIDTH 5
#define RDEV_DEVX 6
@ -70,163 +72,99 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#define RES_EXT_ATTR_TILE 6
#define RES_EXT_ATTR_TEXT 7
#define MAXTOKEN 1024
#define MAXLINE 40
#define MAXDIGIT 20
ResExtNode *ResInitializeNode();
ResSimNode *ResInitializeNode();
ResSimNode *ResOriginalNodes; /*Linked List of Nodes */
static float resscale=1.0; /* Scale factor */
char RDEV_NOATTR[1]={'0'};
ResFixPoint *ResFixList;
#define nodeinit(n)\
{\
(n)->rn_more = ResNodeList;\
(n)->rn_less = NULL;\
if (ResNodeList)\
ResNodeList->rn_less = n;\
ResNodeList = n;\
(n)->rn_te = NULL;\
(n)->rn_re = NULL;\
(n)->rn_je = NULL;\
(n)->rn_ce = NULL;\
(n)->rn_noderes = RES_INFINITY;\
(n)->location.p_x = MINFINITY;\
(n)->location.p_y = MINFINITY;\
(n)->rn_why = 0;\
(n)->rn_status = TRUE;\
}
/* Forward declarations */
extern void ResSimProcessDrivePoints();
ResExtNode *ResOriginalNodes; /*Linked List of Nodes */
static float resscale = 1.0; /* Scale factor */
char RDEV_NOATTR[1] = {'0'};
ResFixPoint *ResFixList;
/*
*-------------------------------------------------------------------------
*
* ResReadSim--
* ResReadExt--
*
* Results: returns 0 if sim file is correct, 1 if not.
* Results: returns 0 if ext file is correct, 1 if not.
*
* Side Effects:Reads in SimTable and makes a hash table of nodes.
* Side Effects:Reads in ExtTable and makes a hash table of nodes.
*
*-------------------------------------------------------------------------
*/
int
ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
char *simfile;
int (*fetproc)(), (*capproc)(), (*resproc)();
int (*attrproc)(), (*mergeproc)(), (*subproc)();
ResReadExt(char *extfile);
{
char line[MAXLINE][MAXTOKEN];
int result, fettype, extfile;
FILE *fp, *fopen();
char *line = NULL, *argv[128];
int result, fettype, readdrivepoints;
int size = 0;
FILE *fp;
fp = PaOpen(simfile, "r", ".sim", ".", (char *)NULL, (char **)NULL);
fp = PaOpen(extfile, "r", ".ext", EFSearchPath, EFLibPath, (char **)NULL);
if (fp == NULL)
{
TxError("Cannot open file %s%s\n", simfile, ".sim");
TxError("Cannot open file %s%s\n", extfile, ".ext");
return 1;
}
extfile = 0;
readdrivepoints = FALSE;
/* Read in file */
while (gettokens(line, fp) != 0)
/* Read in the file. Makes use of various functions
* from extflat, mostly in EFread.c.
*/
EFSaveLocs = False;
efReadLineNum = 0;
while ((argc = efReadLine(&line, &size, fp, argv)) >= 0)
{
fettype = MINFINITY;
switch(line[0][0])
n = LookupStruct(argv[0], (const LookupTable *)keyTable, sizeof keyTable[0]);
if (n < 0)
{
case '|':
if (strcmp(line[NODEUNITS],"units:") == 0)
{
resscale = (float)atof(line[NODELAMBDA]);
if (resscale == 0.0) resscale = 1.0;
}
result=0;
efReadError("Unrecognized token \"%s\" (ignored)\n", argv[0]);
continue;
}
if (argc < keyTable[n].k_mintokens)
{
efReadError("Not enough tokens for %s line\n", argv[0]);
continue;
}
/* We don't care about most tokens, only DEVICE, NODE, PORT,
* and SUBSTRATE; and MERGE is used to locate drive points.
*/
switch (keyTable[n].k_key)
{
case SCALE:
resscale = (float)atof(argv[1]);
if (resscale == 0.0) resscale = 1.0;
break;
case 'e':
fettype = DBTechNameType("efet");
break;
case 'd':
fettype = DBTechNameType("dfet");
case DEVICE:
ResReadSubckt(argc, argv);
break;
case 'n':
fettype = DBTechNameType("nfet");
case FET:
ResReadDevice(argc, argv);
break;
case 'p':
fettype = DBTechNameType("pfet");
case MERGE:
ResReadDrivePoint(argc, argv);
break;
case 'b':
fettype = DBTechNameType("bnpn");
case NODE:
case SUBSTRATE:
ResReadNode(argc, argv);
break;
case 'C':
if (capproc) result = (*capproc)(line);
case PORT:
ResReadPort(argc, argv);
break;
case 'R':
if (resproc) result = (*resproc)(line);
break;
case '=':
/* Do not merge nodes, as this interferes with */
/* extresist's primary function. */
/* if (mergeproc) result = (*mergeproc)(line); */
break;
case 'A':
if (attrproc)
{
result = (*attrproc)(line[ATTRIBUTENODENAME],
line[ATTRIBUTEVALUE], simfile, &extfile);
}
break;
case 'x':
fettype = DBNumTypes;
break;
case 'D':
case 'c':
case 'r':
case ATTR:
result = ResExtAttribute(curnodename,
argv[1], &readdrivepoints);
break;
default:
/* we expect fclose(fp) and early return to occur below,
* but code path might still modify result (maybe to zero)
* allowing us to loop again, which will then access 'fp'
*/
result = 1;
break;
}
if ((fettype != MINFINITY) && (fettype < 0))
{
TxError("Error in Reading device line of sim file: ");
TxError("Ambiguous or unknown device.\n");
result = 1;
}
else if (fettype == DBNumTypes)
{
result = (*subproc)(line);
}
else if (fettype != MINFINITY)
{
float sheetr;
ExtDevice *devptr;
HashEntry *he;
devptr = ExtCurStyle->exts_device[fettype];
he = HashLookOnly(&devptr->exts_deviceResist, "linear");
if (he != NULL)
sheetr = (ResValue)(spointertype)HashGetValue(he);
else
sheetr = (ResValue)0.0;
result = (*fetproc)(line, sheetr, devptr);
}
if (result != 0)
{
TxError("Error in sim file %s\n", line[0]);
fclose(fp);
return 1;
/* to do: Handle CAP, RESISTOR, maybe others? */
}
}
fclose(fp);
@ -240,112 +178,45 @@ ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
* ResReadNode-- Reads in a node file, puts location of nodes into node
* structures.
*
* Results: returns 0 if nodes file is correct, 1 if not.
* Results: 0 if the node was read correctly, 1 otherwise.
*
* Side Effects:see above
* Side Effects: see above
*
*-------------------------------------------------------------------------
*/
int
ResReadNode(nodefile)
char *nodefile;
ResReadNode(int argc, char *argv[])
{
char line[MAXLINE][MAXTOKEN];
FILE *fp, *fopen();
HashEntry *entry;
ResSimNode *node;
ResExtNode *node;
char *cp;
float lambda;
fp = PaOpen(nodefile, "r", ".nodes", ".", (char *)NULL, (char **)NULL);
if (fp == NULL)
entry = HashFind(&ResNodeTable, line[NODES_NODENAME]);
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]);
if (node->type == -1)
{
TxError("Cannot open file %s%s\n", nodefile, ".nodes");
TxError("Bad tile type name in .ext file for node %s\n",
node->name);
return 1;
}
while (gettokens(line,fp) != 0)
{
entry = HashFind(&ResNodeTable, line[NODES_NODENAME]);
node = ResInitializeNode(entry);
node->location.p_x = atoi(line[NODES_NODEX]);
node->location.p_y = atoi(line[NODES_NODEY]);
#ifdef ARIEL
node->rs_bbox.r_xbot = atoi(line[NODE_BBOX_LL_X]);
node->rs_bbox.r_ybot = atoi(line[NODE_BBOX_LL_Y]);
node->rs_bbox.r_xtop = atoi(line[NODE_BBOX_UR_X]);
node->rs_bbox.r_ytop = atoi(line[NODE_BBOX_UR_Y]);
#endif
if ((cp = strchr(line[NODES_NODETYPE], ';'))) *cp = '\0';
node->type = DBTechNameType(line[NODES_NODETYPE]);
if (node->type == -1)
{
TxError("Bad tile type name in %s.nodes file for node %s\n",
nodefile, node->name);
TxError("Did you use the newest version of ext2sim?\n");
fclose(fp);
return 1;
}
}
fclose(fp);
return 0;
}
/*
*-------------------------------------------------------------------------
*
* getline-- Gets a line from the current input file and breaks it into
* tokens.
*
* Results:returns the number of tokens in the current line
*
* Side Effects: loads up its input line with the tokens.
*
*-------------------------------------------------------------------------
*/
int
gettokens(line, fp)
char line[][MAXTOKEN];
FILE *fp;
{
int i = 0, j = 0;
int c;
while ((c = getc(fp)) != EOF && c != '\n')
{
switch(c)
{
case ' ':
case ' ' :
line[i++][j] = '\0';
j = 0;
break;
default:
line[i][j++] = c;
break;
}
}
if (c == '\n')
{
line[i++][j] = '\0';
j = 0;
}
for (j = i; j < MAXLINE; j++)
line[j][0] = '\0';
return i;
}
/*
*-------------------------------------------------------------------------
*
* ResSimSubckt-- Processes a subcircuit line from a sim file.
* 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 .sim format
* around the device type limitations of the .ext format
* when using extresist.
*
* Results: returns 0 if line was added correctly.
@ -356,7 +227,7 @@ gettokens(line, fp)
*/
int
ResSimSubckt(line)
ResReadSubckt(line)
char line[][MAXTOKEN];
{
RDev *device;
@ -473,7 +344,7 @@ ResSimSubckt(line)
TxError("Device %s has more than 4 ports (not handled).\n", line[i]);
break; /* No method to handle more ports than this */
}
rvalue += ResSimNewNode(line[k], k, device);
rvalue += ResExtNewNode(line[k], k, device);
}
return rvalue;
@ -482,7 +353,7 @@ ResSimSubckt(line)
/*
*-------------------------------------------------------------------------
*
* ResSimDevice-- Processes a device line from a sim file.
* ResReadDevice-- Processes a device line from a ext file.
*
* Results: returns 0 if line was added correctly.
*
@ -492,7 +363,7 @@ ResSimSubckt(line)
*/
int
ResSimDevice(line, rpersquare, devptr)
ResReadDevice(line, rpersquare, devptr)
char line[][MAXTOKEN];
float rpersquare;
ExtDevice *devptr;
@ -554,7 +425,7 @@ ResSimDevice(line, rpersquare, devptr)
device->rs_ttype = extGetDevType(devptr->exts_deviceName);
/* sim attributes look like g=a1,a2 */
/* 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 */
@ -615,9 +486,9 @@ ResSimDevice(line, rpersquare, devptr)
}
ResRDevList = device;
device->layout = NULL;
rvalue = ResSimNewNode(line[GATE], GATE, device) +
ResSimNewNode(line[SOURCE], SOURCE, device) +
ResSimNewNode(line[DRAIN], DRAIN, device);
rvalue = ResExtNewNode(line[GATE], GATE, device) +
ResExtNewNode(line[SOURCE], SOURCE, device) +
ResExtNewNode(line[DRAIN], DRAIN, device);
return rvalue;
}
@ -625,24 +496,24 @@ ResSimDevice(line, rpersquare, devptr)
/*
*-------------------------------------------------------------------------
*
* ResSimNewNode-- Adds a new node to the Node Hash Table.
* 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 ResSimNode
* Side Effects: Allocates a new ResExtNode
*
*-------------------------------------------------------------------------
*/
int
ResSimNewNode(line, type, device)
ResExtNewNode(line, type, device)
char line[];
int type;
RDev *device;
{
HashEntry *entry;
ResSimNode *node;
ResExtNode *node;
devPtr *tptr;
if (line[0] == '\0')
@ -681,25 +552,25 @@ ResSimNewNode(line, type, device)
/*
*-------------------------------------------------------------------------
*
* ResSimCapacitor-- Adds the capacitance from a C line to the appropriate
* ResReadCapacitor-- Adds the capacitance from a C line to the appropriate
* node. Coupling capacitors are added twice, moving the capacitance
* to the substrate.
*
* Results:
* Always return 0
*
* Side Effects: modifies capacitance field of ResSimNode.
* Side Effects: modifies capacitance field of ResExtNode.
*
*-------------------------------------------------------------------------
*/
int
ResSimCapacitor(line)
ResReadCapacitor(line)
char line[][MAXTOKEN];
{
HashEntry *entry1, *entry2;
ResSimNode *node1, *node2;
ResExtNode *node1, *node2;
if (line[COUPLETERMINAL1][0] == 0 || line[COUPLETERMINAL2][0] == 0)
{
@ -752,23 +623,23 @@ ResSimCapacitor(line)
/*
*-------------------------------------------------------------------------
*
* ResSimResistor-- Adds the capacitance from a R line to the appropriate
* 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 ResSimNode
* Side Effects: modifies resistance field of ResExtNode
*
*-------------------------------------------------------------------------
*/
int
ResSimResistor(line)
ResReadResistor(line)
char line[][MAXTOKEN];
{
HashEntry *entry;
ResSimNode *node;
ResExtNode *node;
if (line[RESNODENAME][0] == 0)
{
@ -789,29 +660,30 @@ ResSimResistor(line)
/*
*-------------------------------------------------------------------------
*
* ResSimAttribute--checks to see if a node attribute is a resistance
* ResExtAttribute--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
*
* Results:
* Return 0 to keep search going, 1 to abort
*
* Side Effects: modifies resistance field of ResSimNode
* Side Effects: modifies resistance field of ResExtNode
*
*-------------------------------------------------------------------------
*/
int
ResSimAttribute(aname, avalue, rootname, readextfile)
char *aname, *avalue, *rootname;
int *readextfile;
ResReadAttribute(aname, avalue, readdrivepoints)
char *aname;
char *avalue;
bool *readdrivepoints;
{
HashEntry *entry;
ResSimNode *node;
ResExtNode *node;
char digit[MAXDIGIT];
int i;
static int notwarned=TRUE;
static int notwarned = TRUE;
if (aname[0] == 0)
{
@ -834,18 +706,14 @@ ResSimAttribute(aname, avalue, rootname, readextfile)
else if (strncmp(avalue, "res:force", 9) == 0)
{
if (node->status & SKIP)
{
TxError("Warning: Node %s is both skipped and forced \n", aname);
}
else
{
node->status |= FORCE;
}
}
else if (strncmp(avalue, "res:min=", 8) == 0)
{
node->status |= MINSIZE;
for (i = 0, avalue += 8; *avalue != '\0' && *avalue != ','; avalue++)
for (i = 0, avalue += 8; *avalue != '\0'; avalue++)
{
digit[i++] = *avalue;
}
@ -855,16 +723,14 @@ ResSimAttribute(aname, avalue, rootname, readextfile)
else if (strncmp(avalue, "res:drive", 9) == 0 &&
(ResOptionsFlags & ResOpt_Signal))
{
if (*readextfile == 0)
if (*readdrivepoints == FALSE)
{
ResSimProcessDrivePoints(rootname);
*readextfile = 1;
ResExtProcessDrivePoints(rootname);
*readddrivepoints = TRUE;
}
/* is the attribute in root.ext? */
if (node->drivepoint.p_x != INFINITY)
{
node->status |= DRIVELOC;
}
else
{
if (notwarned)
@ -873,34 +739,22 @@ ResSimAttribute(aname, avalue, rootname, readextfile)
notwarned = FALSE;
}
}
#ifdef ARIEL
else if (strncmp(avalue, "res:fix", 7) == 0 &&
(ResOptionsFlags & ResOpt_Power))
{
if (*readextfile == 0)
{
ResSimProcessFixPoints(rootname);
*readextfile = 1;
}
}
#endif
if ((avalue = strchr(avalue, ',')))
{
ResSimAttribute(aname, avalue + 1, rootname, readextfile);
}
return 0;
}
/*
*-------------------------------------------------------------------------
*
* ResSimProcessDrivePoints -- if the sim file contains a res:drive attribute,
* 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.
*
@ -910,23 +764,14 @@ ResSimAttribute(aname, avalue, rootname, readextfile)
*/
void
ResSimProcessDrivePoints(filename)
char *filename;
ResExtProcessDrivePoints(FILE *fp)
{
char line[MAXLINE][MAXTOKEN];
FILE *fp;
HashEntry *entry;
ResSimNode *node;
ResExtNode *node;
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)
while (gettokens(line, fp) != 0)
{
if (strncmp(line[RES_EXT_ATTR], "attr", 4) != 0 ||
strncmp(line[RES_EXT_ATTR_TEXT], "\"res:drive\"", 11) != 0)
@ -944,11 +789,13 @@ ResSimProcessDrivePoints(filename)
/*
*-------------------------------------------------------------------------
*
* ResSimProcessFixPoints -- if the sim file contains a "res:fix:name" label
* 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.
@ -960,7 +807,7 @@ ResSimProcessDrivePoints(filename)
*/
void
ResSimProcessFixPoints(filename)
ResExtProcessFixPoints(filename)
char *filename;
{
char line[MAXLINE][MAXTOKEN], *label, *c;
@ -1006,72 +853,31 @@ ResSimProcessFixPoints(filename)
/*
*-------------------------------------------------------------------------
*
* ResSimMerge-- Processes = line in sim file
* ResInitializeNode --
* Gets the node corresponding to a given hash table entry. If no
* such node exists, one is created.
*
* Results: Success/Failure
* Results: Returns ResExtNode corresponding to entry.
*
* Side Effects: The forward field of one node is set to point to the
* other node. All of the junkt from the first node is moved to
* the second node.
* Side Effects: May allocate a new ResExtNode.
*
*-------------------------------------------------------------------------
*/
int
ResSimMerge(line)
char line[][MAXTOKEN];
{
ResSimNode *node;
devPtr *ptr;
if ((line[ALIASNAME][0] == '\0') || (line[REALNAME][0] == '\0'))
{
TxError("Bad node alias line\n");
return(1);
}
node = ResInitializeNode(HashFind(&ResNodeTable, line[ALIASNAME]));
node->status |= FORWARD;
node->forward = ResInitializeNode(HashFind(&ResNodeTable, line[REALNAME]));
node->forward->resistance += node->resistance;
node->forward->capacitance += node->capacitance;
while (node->firstDev != NULL)
{
ptr = node->firstDev;
node->firstDev = node->firstDev->nextDev;
ptr->nextDev = node->forward->firstDev;
node->forward->firstDev = ptr;
}
return 0;
}
/*
*-------------------------------------------------------------------------
*
* ResInitializeNode-- Gets the node corresponding to a given hash table
* entry. If no such node exists, one is created.
*
* Results:Returns ResSimNode corresponding to entry.
*
* Side Effects: May allocate a new ResSimNode.
*
*-------------------------------------------------------------------------
*/
ResSimNode *
ResExtNode *
ResInitializeNode(entry)
HashEntry *entry;
{
ResSimNode *node;
ResExtNode *node;
if ((node = (ResSimNode *) HashGetValue(entry)) == NULL)
if ((node = (ResExtNode *) HashGetValue(entry)) == NULL)
{
node = (ResSimNode *)mallocMagic((unsigned)(sizeof(ResSimNode)));
node = (ResExtNode *)mallocMagic((unsigned)(sizeof(ResExtNode)));
HashSetValue(entry, (char *) node);
node->nextnode = ResOriginalNodes;
ResOriginalNodes = node;
node->status = FALSE;
node->forward = (ResSimNode *) NULL;
node->forward = (ResExtNode *) NULL;
node->capacitance = 0;
node->cap_vdd = 0;
node->cap_couple = 0;

View File

@ -31,9 +31,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/tech.h"
#include "textio/txcommands.h"
#include "resis/resis.h"
#ifdef LAPLACE
#include "laplace.h"
#endif
#define INITFLATSIZE 1024
#define MAXNAME 1000
@ -56,22 +53,17 @@ HashTable ResIncludeTable; /* Hash table of nodes to include */
HashTable ResProcessedTable;
/* ResSimNode is a node read in from a sim file */
/* ResExtNode is a node read in from a .ext file */
HashTable ResNodeTable; /* Hash table of sim file nodes */
RDev *ResRDevList; /* Linked list of Sim devices */
HashTable ResNodeTable; /* Hash table of ext file nodes */
RDev *ResRDevList; /* Linked list of Ext devices */
ResGlobalParams gparams; /* Junk passed between */
/* ResCheckSimNodes and */
/* ResCheckExtNodes and */
/* ResExtractNet. */
extern ResSimNode *ResOriginalNodes; /*Linked List of Nodes */
extern ResExtNode *ResOriginalNodes; /*Linked List of Nodes */
int resNodeNum;
#ifdef LAPLACE
int ResOptionsFlags = ResOpt_Simplify | ResOpt_Tdi | ResOpt_DoExtFile
| ResOpt_CacheLaplace;
#else
int ResOptionsFlags = ResOpt_Simplify | ResOpt_Tdi | ResOpt_DoExtFile;
#endif
char *ResCurrentNode;
FILE *ResExtFile;
@ -81,29 +73,9 @@ FILE *ResFHFile;
int ResPortIndex; /* Port ordering to backannotate into magic */
/* external declarations */
extern ResSimNode *ResInitializeNode();
extern ResExtNode *ResInitializeNode();
extern CellUse *CmdGetSelectedCell();
/* 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. */
struct saveList {
Plane *sl_plane;
CellDef *sl_def;
struct saveList *sl_next;
};
/* Structure stores information required to be sent to ExtResisForDef() */
typedef struct
{
float tdiTolerance;
float frequency;
float rthresh;
struct saveList *savePlanes;
CellDef *mainDef;
} ResisData;
/*
*-------------------------------------------------------------------------
*
@ -123,7 +95,7 @@ ExtResisForDef(celldef, resisdata)
HashSearch hs;
HashEntry *entry;
devPtr *tptr, *oldtptr;
ResSimNode *node;
ResExtNode *node;
int result, idx;
char *devname;
Plane *savePlane;
@ -160,10 +132,8 @@ ExtResisForDef(celldef, resisdata)
}
HashInit(&ResNodeTable, INITFLATSIZE, HT_STRINGKEYS);
/* read in .sim file */
result = (ResReadSim(celldef->cd_name,
ResSimDevice, ResSimCapacitor, ResSimResistor,
ResSimAttribute, ResSimMerge, ResSimSubckt) == 0);
/* Read in the .ext file */
result = (ResReadExt(celldef->cd_name) == 0);
/* Clean up the EFDevTypes table */
for (idx = 0; idx < EFDevNumTypes; idx++) freeMagic(EFDevTypes[idx]);
@ -184,7 +154,7 @@ ExtResisForDef(celldef, resisdata)
/* Extract networks for nets that require it. */
if (!(ResOptionsFlags & ResOpt_FastHenry) ||
DBIsSubcircuit(celldef))
ResCheckSimNodes(celldef, resisdata);
ResCheckExtNodes(celldef, resisdata);
if (ResOptionsFlags & ResOpt_Stat)
ResPrintStats((ResGlobalParams *)NULL, "");
@ -195,7 +165,7 @@ ExtResisForDef(celldef, resisdata)
HashStartSearch(&hs);
while((entry = HashNext(&ResNodeTable, &hs)) != NULL)
{
node=(ResSimNode *) HashGetValue(entry);
node=(ResExtNode *) HashGetValue(entry);
tptr = node->firstDev;
if (node == NULL)
{
@ -227,14 +197,13 @@ ExtResisForDef(celldef, resisdata)
/*
*-------------------------------------------------------------------------
*
* CmdExtResis-- reads in sim file and layout, and produces patches to the
* .ext files and .sim files that include resistors.
* CmdExtResis-- reads in ext file and layout, and produces patches to the
* .ext files that include resistors.
*
* Results:
* None.
*
* Side Effects: Produces .res.sim file and .res.ext file for all nets that
* require resistors.
* Side Effects: Produces .res.ext file for all nets that require resistors.
*
*-------------------------------------------------------------------------
*/
@ -281,9 +250,6 @@ CmdExtResis(win, cmd)
"fasthenry [freq] extract subcircuit network geometry into .fh file",
"geometry extract network centerline geometry (experimental)",
"help print this message",
#ifdef LAPLACE
"laplace [on/off] solve Laplace's equation using FEM",
#endif
NULL
};
@ -293,9 +259,6 @@ typedef enum {
RES_SIMP, RES_EXTOUT, RES_LUMPED, RES_SILENT,
RES_SKIP, RES_IGNORE, RES_INCLUDE, RES_BOX, RES_CELL,
RES_BLACKBOX, RES_FASTHENRY, RES_GEOMETRY, RES_HELP,
#ifdef LAPLACE
RES_LAPLACE,
#endif
RES_RUN
} ResOptions;
@ -582,7 +545,7 @@ typedef enum {
CellDef *def;
Rect rect;
int oldoptions;
ResSimNode lnode;
ResExtNode lnode;
if (ToolGetBoxWindow((Rect *) NULL, (int *) NULL) == NULL)
{
@ -598,25 +561,11 @@ typedef enum {
gparams.rg_status = DRIVEONLY;
oldoptions = ResOptionsFlags;
ResOptionsFlags = ResOpt_DoSubstrate | ResOpt_Signal | ResOpt_Box;
#ifdef LAPLACE
ResOptionsFlags |= (oldoptions &
(ResOpt_CacheLaplace | ResOpt_DoLaplace));
LaplaceMatchCount = 0;
LaplaceMissCount = 0;
#endif
lnode.location = rect.r_ll;
lnode.type = tt;
if (ResExtractNet(&lnode, &gparams, NULL) != 0) return;
ResPrintResistorList(stdout, ResResList);
ResPrintDeviceList(stdout, ResRDevList);
#ifdef LAPLACE
if (ResOptionsFlags & ResOpt_DoLaplace)
{
TxPrintf("Laplace solved: %d matched %d\n",
LaplaceMissCount, LaplaceMatchCount);
}
#endif
ResOptionsFlags = oldoptions;
return;
}
@ -634,11 +583,6 @@ typedef enum {
case RES_RUN:
ResOptionsFlags &= ~ResOpt_ExtractAll;
break;
#ifdef LAPLACE
case RES_LAPLACE:
LaplaceParseString(cmd);
return;
#endif
case RES_AMBIG:
TxPrintf("Ambiguous option: %s\n", cmd->tx_argv[1]);
TxFlushOut();
@ -651,10 +595,6 @@ typedef enum {
return;
}
#ifdef LAPLACE
LaplaceMatchCount = 0;
LaplaceMissCount = 0;
#endif
/* turn off undo stuff */
UndoDisable();
@ -666,9 +606,6 @@ typedef enum {
return;
}
ResOptionsFlags |= ResOpt_Signal;
#ifdef ARIEL
ResOptionsFlags &= ~ResOpt_Power;
#endif
resisdata.rthresh = rthresh;
resisdata.tdiTolerance = tdiTolerance;
@ -695,13 +632,6 @@ typedef enum {
/* turn back on undo stuff */
UndoEnable();
#ifdef LAPLACE
if (ResOptionsFlags & ResOpt_DoLaplace)
{
TxPrintf("Laplace solved: %d matched %d\n",
LaplaceMissCount, LaplaceMatchCount);
}
#endif
/* Revert to the original flags in the case of FastHenry or */
/* geometry centerline extraction. */
@ -765,7 +695,7 @@ resPortFunc(scx, lab, tpath, result)
int pclass, puse;
Point portloc;
HashEntry *entry;
ResSimNode *node;
ResExtNode *node;
// Ignore the top level cell
if (scx->scx_use->cu_id == NULL) return 0;
@ -904,7 +834,7 @@ ResCheckPorts(cellDef)
Point portloc;
Label *lab;
HashEntry *entry;
ResSimNode *node;
ResExtNode *node;
int result = 1;
for (lab = cellDef->cd_labels; lab; lab = lab->lab_next)
@ -930,7 +860,7 @@ ResCheckPorts(cellDef)
entry = HashFind(&ResNodeTable, lab->lab_text);
result = 0;
if ((node = (ResSimNode *) HashGetValue(entry)) != NULL)
if ((node = (ResExtNode *) HashGetValue(entry)) != NULL)
{
TxPrintf("Port: name = %s exists, forcing drivepoint\n",
lab->lab_text);
@ -966,34 +896,6 @@ ResCheckPorts(cellDef)
return result;
}
/*
*-------------------------------------------------------------------------
*
* ResCreateNode ---
*
* Create a node structure for extresist for the method where
* ResProcessNode() is called from extBasic() as part of the
* "extract" command.
*
* Results:
* Returns the node structure to be passed to ResProcessNode().
*
* Side effects:
* Memory is allocated for the node structure.
*
*-------------------------------------------------------------------------
*/
ResSimNode *ResCreateNode()
{
ResSimNode *node;
/* To be completed */
return node;
}
/*
*-------------------------------------------------------------------------
*
@ -1013,7 +915,7 @@ ResSimNode *ResCreateNode()
int
ResProcessNode(
ResSimNode *node, /* Node record for network */
ResExtNode *node, /* Node record for network */
CellDef *celldef, /* Cell def being processed */
ResisData *resisdata, /* Extraction parameters kept here */
char *outfile, /* Name of output file */
@ -1186,7 +1088,7 @@ ResProcessNode(
/*
*-------------------------------------------------------------------------
*
* ResCheckSimNodes-- check to see if lumped resistance is greater than the
* ResCheckExtNodes-- check to see if lumped resistance is greater than the
* device resistance; if it is, Extract the net
* resistance. If the maximum point to point resistance
* in the extracted net is still creater than the
@ -1194,17 +1096,17 @@ ResProcessNode(
*
* Results: none
*
* Side Effects: Writes networks to .res.ext and .res.sim files.
* Side Effects: Writes networks to .res.ext files.
*
*-------------------------------------------------------------------------
*/
void
ResCheckSimNodes(celldef, resisdata)
ResCheckExtNodes(celldef, resisdata)
CellDef *celldef;
ResisData *resisdata;
{
ResSimNode *node;
ResExtNode *node;
int numext = 0; /* Number of nets extracted */
int numout = 0; /* Number of nets output */
int total = 0; /* Total number of nets processed */
@ -1339,8 +1241,8 @@ ResCheckSimNodes(celldef, resisdata)
*
* Results:none
*
* Side Effects: Allocates new ResSimNodes. Modifies the terminal connections
* of sim Devices.
* Side Effects: Allocates new ResExtNodes. Modifies the terminal connections
* of ext Devices.
*
*-------------------------------------------------------------------------
*/
@ -1349,7 +1251,7 @@ void
ResFixUpConnections(simDev, layoutDev, simNode, nodename)
RDev *simDev;
resDevice *layoutDev;
ResSimNode *simNode;
ResExtNode *simNode;
char *nodename;
{
@ -1601,7 +1503,7 @@ ResFixDevName(line, type, device, layoutnode)
{
HashEntry *entry;
ResSimNode *node;
ResExtNode *node;
devPtr *tptr;
if (layoutnode->rn_name != NULL)
@ -1757,7 +1659,7 @@ ResSortByGate(DevpointerList)
void
ResWriteLumpFile(node)
ResSimNode *node;
ResExtNode *node;
{
int lumpedres;
@ -1852,7 +1754,7 @@ ResAlignNodes(nodelist, reslist)
int
ResWriteExtFile(celldef, node, rctol, nidx, eidx)
CellDef *celldef;
ResSimNode *node;
ResExtNode *node;
float rctol;
int *nidx, *eidx;
{

View File

@ -383,27 +383,17 @@ ResMoveDevices(node1, node2)
device = devptr->te_thist;
oldptr = devptr;
devptr = devptr->te_nextt;
if (device->rd_status & RES_DEV_PLUG)
{
if (((ResPlug *)(device))->rpl_node == node1)
((ResPlug *)(device))->rpl_node = node2;
else
TxError("Bad node connection in plug\n");
}
if (device->rd_fet_gate == node1)
device->rd_fet_gate = node2;
else if (device->rd_fet_subs == node1)
device->rd_fet_subs = node2;
else if (device->rd_fet_source == node1)
device->rd_fet_source = node2;
else if (device->rd_fet_drain == node1)
device->rd_fet_drain = node2;
else
{
if (device->rd_fet_gate == node1)
device->rd_fet_gate = node2;
else if (device->rd_fet_subs == node1)
device->rd_fet_subs = node2;
else if (device->rd_fet_source == node1)
device->rd_fet_source = node2;
else if (device->rd_fet_drain == node1)
device->rd_fet_drain = node2;
else
TxError("Missing Device connection in squish routines"
TxError("Missing Device connection in squish routines"
" at %d, %d\n", node1->rn_loc.p_x, node1->rn_loc.p_y);
}
oldptr->te_nextt = node2->rn_te;
node2->rn_te = oldptr;
}

View File

@ -140,9 +140,8 @@ resCurrentPrintFunc(node, resistor, filename)
for (workingDev = node->rn_te; workingDev != NULL;
workingDev = workingDev->te_nextt)
{
if ((workingDev->te_thist->rd_status & RES_DEV_PLUG) ||
workingDev->te_thist->rd_gate != node)
i_sum += workingDev->te_thist->rd_i;
if (workingDev->te_thist->rd_gate != node)
i_sum += workingDev->te_thist->rd_i;
}
if (i_sum != 0.0)
{

View File

@ -57,10 +57,6 @@ typedef struct resistor
int rr_cl; /* resistor centerline for geometry */
int rr_width; /* resistor width for geometry */
TileType rr_tt; /* type that composes this */
/* resistor. */
#ifdef ARIEL
int rr_csArea; /* crosssectional area in lamba**2*/
#endif
} resResistor;
#define rr_connection1 rr_node[0]
@ -92,10 +88,6 @@ typedef struct device
int rd_devtype; /* tiletype of device. */
Rect rd_inside; /* 1x1 rectangle inside device */
Tile *rd_tile; /* pointer to a tile in device */
#ifdef ARIEL
float rd_i; /* Current injected from this device */
/* in milliamps */
#endif
} resDevice;
/*
@ -254,7 +246,7 @@ typedef struct resdevtile
/*
Goodies contains random stuff passed between the node extractor
and ResCheckSimNodes. The location of a start tile and the resistive
and ResCheckExtNodes. The location of a start tile and the resistive
tolerance are passed down, while the derived network is passed back.
*/
@ -271,7 +263,28 @@ typedef struct goodstuff
char *rg_name;
} ResGlobalParams;
/* Used in RC delay calculations for Tdi filter */
/* 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. */
struct saveList {
Plane *sl_plane;
CellDef *sl_def;
struct saveList *sl_next;
};
/* Structure stores information required to be sent to ExtResisForDef() */
typedef struct
{
float tdiTolerance;
float frequency;
float rthresh;
struct saveList *savePlanes;
CellDef *mainDef;
} ResisData;
/* Structure used in RC delay calculations for Tdi filter. */
/* Attaches to rn_client field of resNode */
typedef struct rcdelaystuff
@ -281,7 +294,7 @@ typedef struct rcdelaystuff
} RCDelayStuff;
/* ResSim.c type declarations */
/* Type declarations */
typedef struct rdev
{
@ -291,10 +304,10 @@ typedef struct rdev
resDevice *layout; /* pointer to resDevice that */
/* corresponds to RDev */
int status;
struct ressimnode *gate; /* Terminals of transistor. */
struct ressimnode *source;
struct ressimnode *drain;
struct ressimnode *subs; /* Used with subcircuit type only */
struct resextnode *gate; /* Terminals of transistor. */
struct resextnode *source;
struct resextnode *drain;
struct resextnode *subs; /* Used with subcircuit type only */
Point location; /* Location of lower left point of */
/* device. */
float resistance; /* "Resistance" of device. */
@ -305,12 +318,12 @@ typedef struct rdev
char *rs_dattr;
} RDev;
typedef struct ressimnode
typedef struct resextnode
{
struct ressimnode *nextnode; /* next node in OriginalNodes */
struct resextnode *nextnode; /* next node in OriginalNodes */
/* linked list. */
int status;
struct ressimnode *forward; /* If node has been merged, this */
struct resextnode *forward; /* If node has been merged, this */
/* points to the merged node. */
float capacitance; /* capacitance between node and */
/* GND for power connections */
@ -340,7 +353,7 @@ typedef struct ressimnode
tElement *rs_sublist[2]; /* pointers to Gnd and Vdd sub */
/* strate connections,
if they exist */
} ResSimNode;
} ResExtNode;
#define RES_SUB_GND 0
#define RES_SUB_VDD 1
@ -355,40 +368,6 @@ typedef struct devptr
/* is connected to node. */
} devPtr;
/* ResTime.c type declarations */
typedef struct resevent /* Raw event list read in from rsim/tv */
{
int rv_node; /* node number */
int rv_final; /* final value; (0,1, or X) */
int rv_tmin; /* minimum event time in units of 100ps */
int rv_tmax; /* maximum event time in units of 100ps */
float rv_i; /* event current in milliamps */
resDevice *rv_dev; /* device where charge drains */
} ResEvent;
typedef struct reseventcell
{
ResEvent *rl_this;
struct reseventcell *rl_next;
} REcell;
typedef struct rescurrentevent /* processed event used to feed relaxer */
{
struct rescurrentevent *ri_next;
float ri_i;
resDevice *ri_dev;
} ResCurrentEvent;
typedef struct restimebin /* Holds one timestep's worth of Events */
{
struct restimebin *rb_next;
struct restimebin *rb_last;
int rb_start;
int rb_end;
ResCurrentEvent *rb_first;
} ResTimeBin;
typedef struct resfixpoint /* Keeps track of where voltage sources are */
{
struct resfixpoint *fp_next;
@ -400,30 +379,6 @@ typedef struct resfixpoint /* Keeps track of where voltage sources are */
char fp_name[1];
} ResFixPoint;
typedef struct clump
{
unsigned rp_status;
rElement *rp_grouplist;
nElement *rp_nodelist;
rElement *rp_downlist;
rElement *rp_singlelist;
} ResClump;
/* the first two fields of this plug must be the the same as for
resDevice
*/
typedef struct plug
{
float rpl_i; /* current injected through
this plug
*/
int rpl_status; /* status bits for this plug */
struct plug *rpl_next; /* next plug in this bin */
Point rpl_loc; /*location of plug */
int rpl_type; /*type of plug */
resNode *rpl_node; /* this point's node */
} ResPlug;
typedef struct capval
{
float cap[1][2]; /* multipliers telling what portion of capacitance is
@ -458,7 +413,6 @@ typedef struct capval
/* device flags */
#define RES_DEV_SAVE 0x00000001
#define RES_DEV_PLUG 0x00000002
/* flags for tiles */
/* A tile which is part of a substrate region. */
@ -473,11 +427,6 @@ typedef struct capval
#define RES_TILE_MARK 0x10
/*another temporary marking flag */
#define RES_TILE_PUSHED 0x20
/* indicates that tile has unidirectional current flow */
#ifdef LAPLACE
#define RES_TILE_1D 0x40
#define RES_TILE_GDONE 0x80
#endif
/* tree walking flags */
#define RES_LOOP_OK 1
#define RES_NO_LOOP 1
@ -486,7 +435,7 @@ typedef struct capval
#define RES_NO_FLAGS 0
/* ResSim Constants */
/* Constants */
#define FORWARD 0x0000010
#define SKIP 0x0000020
#define FORCE 0x0000040
@ -561,16 +510,9 @@ typedef struct capval
#define ResOpt_Blackbox 0x00010000
#define ResOpt_Dump 0x00020000
#define ResOpt_DoSubstrate 0x00040000
#define ResOpt_GndPlugs 0x00200000
#define ResOpt_VddPlugs 0x00400000
#define ResOpt_CMOS 0x00800000
#define ResOpt_Bipolar 0x01000000
#define ResOpt_Box 0x02000000
#ifdef LAPLACE
#define ResOpt_DoLaplace 0x04000000
#define ResOpt_CacheLaplace 0x08000000
#define ResOpt_Checkpoint 0x80000000
#endif
#define ResOpt_VDisplay 0x10000000
#define ResOpt_IDisplay 0x20000000
@ -579,18 +521,9 @@ typedef struct capval
/* Assorted Variables */
extern RDev *ResRDevList;
extern REcell *ResBigEventList;
extern int ResOptionsFlags;
extern char *ResCurrentNode;
extern ResSimNode *ResOriginalNodes;
#ifdef ARIEL
extern int ResMinEventTime;
extern int ResMaxEventTime;
typedef float ResCapElement[2];
extern ResCapElement *ResCapTableMax;
extern ResCapElement *ResCapTableMin;
extern HashTable ResPlugTable;
#endif
extern ResExtNode *ResOriginalNodes;
extern CellUse *ResUse;
extern CellDef *ResDef;
@ -604,10 +537,10 @@ extern resNode *ResNodeQueue;
extern resNode *ResOriginNode;
extern resNode *resCurrentNode;
extern HashTable ResNodeTable;
extern HashTable ResSimDevTable;
extern HashTable ResExtDevTable;
extern ResFixPoint *ResFixList;
extern int ResTileCount;
extern ResSimNode **ResNodeArray;
extern ResExtNode **ResNodeArray;
extern CellDef *mainDef;
extern TileTypeBitMask ResSDTypesBitMask;
extern TileTypeBitMask ResSubTypesBitMask;
@ -616,24 +549,26 @@ extern TileTypeBitMask ResNoMergeMask[NT];
extern ResGlobalParams gparams;
extern int ResPortIndex;
extern int ResSimDevice();
extern int ResSimCombineParallel();
extern int ResSimCapacitor();
extern int ResSimResistor();
extern int ResSimAttribute();
extern int ResSimMerge();
extern int ResSimSubckt();
/* Routines used by ResReadExt() */
extern int ResReadDevice();
extern int ResReadCapacitor();
extern int ResReadResistor();
extern int ResReadAttribute();
extern int ResReadMerge();
extern int ResReadSubckt();
extern int ResProcessNode();
extern int ResExtCombineParallel();
extern int dbSrConnectStartFunc();
extern int ResEach(),ResAddPlumbing(),ResRemovePlumbing();
extern float ResCalculateChildCapacitance();
extern ResDevTile *DBTreeCopyConnectDCS();
extern Tile *ResFindTile();
extern resDevice *ResImageAddPlug();
extern resDevice *ResGetDevice();
extern tileJunk *resAddField();
extern int ResCheckPorts();
extern int ResCheckBlackbox();
extern void ResCheckSimNodes();
extern void ResCheckExtNodes();
extern void ResSortByGate();
extern void ResFixDevName();
extern void ResWriteLumpFile();
@ -663,9 +598,10 @@ extern void ResPrintResistorList();
extern void ResPrintStats();
extern void ResProcessJunction();
extern int ResReadNode();
extern int ResReadSim();
extern int ResReadExt();
extern void ResRemoveFromQueue();
extern int ResSimNewNode();
extern int ResExtNewNode();
extern void ResExtProcessDrivePoints();
extern int ResWriteExtFile();
extern void ResPrintExtNode();
extern void ResPrintExtRes();