Modified the extresist code to handle substrate extraction. Currently
this appears to work correctly but does not yet handle the implicit substrate (space as substrate) or "virtually" isolated substrate regions (which need to be removed for full parasitic extraction).
This commit is contained in:
parent
35a65a9ba1
commit
0bb6ac1fa9
|
|
@ -140,6 +140,37 @@ ResMultiPlaneFunc(tile, tpptr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------------------
|
||||
*
|
||||
* ResSubstrateFunc---
|
||||
*
|
||||
* If device is found overlapping its substrate type, then generate a new
|
||||
* device at the center of the tile and add to ResNodeQueue.
|
||||
*
|
||||
* Results:
|
||||
* Always 0 to keep the search going.
|
||||
*
|
||||
* Side effects:
|
||||
* Adds to ResNodeQueue
|
||||
*
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
ResSubstrateFunc(tile, tpptr)
|
||||
Tile *tile, **tpptr;
|
||||
{
|
||||
Tile *tp = *tpptr;
|
||||
int xj, yj;
|
||||
|
||||
xj = (LEFT(tile) + RIGHT(tile)) / 2;
|
||||
yj = (TOP(tile) + BOTTOM(tile)) / 2;
|
||||
ResNewSubDevice(tp, tile, xj, yj, OTHERPLANE, &ResNodeQueue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -370,6 +401,36 @@ ResEachTile(tile, startpoint)
|
|||
}
|
||||
}
|
||||
|
||||
/* Check for substrate under device */
|
||||
|
||||
if (TTMaskHasType(&ResSubTypesBitMask, t1))
|
||||
{
|
||||
Rect r;
|
||||
int pNum;
|
||||
TileTypeBitMask devMask;
|
||||
|
||||
TiToRect(tile, &r);
|
||||
|
||||
for (pNum = 0; pNum < DBNumPlanes; pNum++)
|
||||
{
|
||||
if (DBTypeOnPlane(t1, pNum)) continue;
|
||||
|
||||
/* NOTE: This is ridiculously inefficient and should be done
|
||||
* in a different way.
|
||||
*/
|
||||
|
||||
TTMaskZero(&devMask);
|
||||
for (t2 = TT_TECHDEPBASE; t2 < DBNumUserLayers; t2++)
|
||||
for (devptr = ExtCurStyle->exts_device[t2]; devptr;
|
||||
devptr = devptr->exts_next)
|
||||
if (TTMaskHasType(&devptr->exts_deviceSubstrateTypes, t1))
|
||||
TTMaskSetType(&devMask, t2);
|
||||
|
||||
DBSrPaintArea((Tile *)NULL, ResUse->cu_def->cd_planes[pNum],
|
||||
&r, &devMask, ResSubstrateFunc, (ClientData)&tile);
|
||||
}
|
||||
}
|
||||
|
||||
tstructs->tj_status |= RES_TILE_DONE;
|
||||
|
||||
resAllPortNodes(tile, &ResNodeQueue);
|
||||
|
|
@ -394,7 +455,7 @@ ResEachTile(tile, startpoint)
|
|||
*/
|
||||
|
||||
int
|
||||
resSubDevFunc(tile,tp)
|
||||
resSubDevFunc(tile, tp)
|
||||
Tile *tile, *tp;
|
||||
{
|
||||
tileJunk *junk = (tileJunk *)(tile->ti_client);
|
||||
|
|
|
|||
|
|
@ -95,6 +95,58 @@ ResNewSDDevice(tile, tp, xj, yj, direction, PendingList)
|
|||
NEWBREAK(resptr, tile, xj, yj, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* ResNewSubDevice -- called when a device is reached via a substrate.
|
||||
*
|
||||
* Results:none
|
||||
*
|
||||
* Side Effects: Makes new node if node hasn't already been created.
|
||||
* Allocates breakpoint in current tile for device.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
ResNewSubDevice(tile, tp, xj, yj, direction, PendingList)
|
||||
Tile *tile, *tp;
|
||||
int xj, yj, direction;
|
||||
resNode **PendingList;
|
||||
{
|
||||
resNode *resptr;
|
||||
resDevice *resDev;
|
||||
tElement *tcell;
|
||||
int newnode;
|
||||
tileJunk *j;
|
||||
|
||||
newnode = FALSE;
|
||||
j = (tileJunk *) tp->ti_client;
|
||||
resDev = j->deviceList;
|
||||
|
||||
if (resDev->rd_fet_subs == (resNode *) NULL)
|
||||
{
|
||||
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
||||
newnode = TRUE;
|
||||
resDev->rd_fet_subs = resptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
resptr = resDev->rd_fet_subs;
|
||||
}
|
||||
|
||||
if (newnode)
|
||||
{
|
||||
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
|
||||
tcell->te_nextt = NULL;
|
||||
tcell->te_thist = j->deviceList;
|
||||
InitializeNode(resptr, xj, yj, RES_NODE_DEVICE);
|
||||
resptr->rn_te = tcell;
|
||||
ResAddToQueue(resptr, PendingList);
|
||||
}
|
||||
NEWBREAK(resptr, tile, xj, yj, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ extern int ResEachTile();
|
|||
extern int ResLaplaceTile();
|
||||
extern ResSimNode *ResInitializeNode();
|
||||
TileTypeBitMask ResSDTypesBitMask;
|
||||
TileTypeBitMask ResSubTypesBitMask;
|
||||
|
||||
extern HashTable ResNodeTable;
|
||||
|
||||
|
|
@ -374,6 +375,21 @@ ResFindNewContactTiles(contacts)
|
|||
for (; contacts != (ResContactPoint *) NULL; contacts = contacts->cp_nextcontact)
|
||||
{
|
||||
DBFullResidueMask(contacts->cp_type, &mask);
|
||||
|
||||
/* Watch for types that connect to the substrate plane or well; */
|
||||
/* e.g., psubstratepdiff connects to nwell but not through a */
|
||||
/* contact. */
|
||||
|
||||
if (ExtCurStyle->exts_globSubstratePlane != -1)
|
||||
{
|
||||
TileTypeBitMask cMask;
|
||||
TTMaskAndMask3(&cMask, &DBConnectTbl[contacts->cp_type],
|
||||
&DBPlaneTypes[ExtCurStyle->exts_globSubstratePlane]);
|
||||
|
||||
if (!TTMaskIsZero(&cMask))
|
||||
TTMaskSetMask(&mask, &cMask);
|
||||
}
|
||||
|
||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||
{
|
||||
tile = ResDef->cd_planes[pNum]->pl_hint;
|
||||
|
|
@ -948,6 +964,7 @@ ResExtractNet(node, goodies, cellname)
|
|||
SEL_DO_LABELS, ResUse);
|
||||
|
||||
TTMaskZero(&ResSDTypesBitMask);
|
||||
TTMaskZero(&ResSubTypesBitMask);
|
||||
|
||||
/* Add devices to ResUse from list in node */
|
||||
DevTiles = NULL;
|
||||
|
|
@ -991,6 +1008,15 @@ ResExtractNet(node, goodies, cellname)
|
|||
devptr = devptr->exts_next)
|
||||
for (i = 0; !TTMaskIsZero(&devptr->exts_deviceSDTypes[i]); i++)
|
||||
TTMaskSetMask(&ResSDTypesBitMask, &devptr->exts_deviceSDTypes[i]);
|
||||
|
||||
/* Add the substrate types to the mask ResSubTypesBitMask */
|
||||
|
||||
for (devptr = ExtCurStyle->exts_device[thisDev->type]; devptr;
|
||||
devptr = devptr->exts_next)
|
||||
TTMaskSetMask(&ResSubTypesBitMask, &devptr->exts_deviceSubstrateTypes);
|
||||
|
||||
/* TT_SPACE should be removed from ResSubTypesBitMask */
|
||||
TTMaskClearType(&ResSubTypesBitMask, TT_SPACE);
|
||||
}
|
||||
DBReComputeBbox(ResUse->cu_def);
|
||||
|
||||
|
|
|
|||
|
|
@ -590,7 +590,7 @@ typedef enum {
|
|||
|
||||
/* Do subcircuits (if any) first */
|
||||
if (!(ResOptionsFlags & ResOpt_Blackbox))
|
||||
(void) DBCellSrDefs(0, resSubcircuitFunc, (ClientData) &resisdata);
|
||||
DBCellEnum(mainDef, resSubcircuitFunc, (ClientData) &resisdata);
|
||||
|
||||
ExtResisForDef(mainDef, &resisdata);
|
||||
|
||||
|
|
@ -617,7 +617,9 @@ typedef enum {
|
|||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* resSubcircuitFunc --
|
||||
* For each encountered cell, call the resistance extractor.
|
||||
* For each encountered cell, call the resistance extractor,
|
||||
* then recursively call resSubcircuitFunc on all children
|
||||
* of the cell.
|
||||
*
|
||||
* Results:
|
||||
* Always return 0 to keep search alive.
|
||||
|
|
@ -633,12 +635,11 @@ resSubcircuitFunc(cellDef, rdata)
|
|||
CellDef *cellDef;
|
||||
ResisData *rdata;
|
||||
{
|
||||
if ((cellDef->cd_flags & CDINTERNAL) == CDINTERNAL)
|
||||
return 0;
|
||||
|
||||
if (cellDef != rdata->mainDef)
|
||||
if (DBIsSubcircuit(cellDef))
|
||||
ExtResisForDef(cellDef, rdata);
|
||||
if (DBIsSubcircuit(cellDef))
|
||||
{
|
||||
ExtResisForDef(cellDef, rdata);
|
||||
DBCellEnum(cellDef, resSubcircuitFunc, (ClientData)rdata);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1202,7 +1203,7 @@ ResFixUpConnections(simDev, layoutDev, simNode, nodename)
|
|||
{
|
||||
static char newname[MAXNAME], oldnodename[MAXNAME];
|
||||
int notdecremented;
|
||||
resNode *gate, *source, *drain;
|
||||
resNode *gate, *source, *drain, *subs;
|
||||
|
||||
/* If we aren't doing output (i.e. this is just a statistical run) */
|
||||
/* don't patch up networks. This cuts down on memory use. */
|
||||
|
|
@ -1244,6 +1245,24 @@ ResFixUpConnections(simDev, layoutDev, simNode, nodename)
|
|||
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
||||
nodename);
|
||||
}
|
||||
if (simDev->subs == simNode)
|
||||
{
|
||||
if ((subs = layoutDev->rd_fet_subs) != NULL)
|
||||
{
|
||||
if (subs->rn_name != NULL && notdecremented)
|
||||
{
|
||||
resNodeNum--;
|
||||
notdecremented = FALSE;
|
||||
}
|
||||
ResFixDevName(newname, SUBS, simDev, subs);
|
||||
subs->rn_name = simDev->subs->name;
|
||||
sprintf(newname, "%s%s%d", nodename, ".t", resNodeNum++);
|
||||
}
|
||||
else
|
||||
TxError("Missing substrate connection of device at (%d %d) on net %s\n",
|
||||
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
||||
nodename);
|
||||
}
|
||||
if (simDev->source == simNode)
|
||||
{
|
||||
if (simDev->drain == simNode)
|
||||
|
|
@ -1423,6 +1442,10 @@ ResFixDevName(line, type, device, layoutnode)
|
|||
node->oldname = device->drain->name;
|
||||
device->drain = node;
|
||||
break;
|
||||
case SUBS:
|
||||
node->oldname = device->subs->name;
|
||||
device->subs = node;
|
||||
break;
|
||||
default:
|
||||
TxError("Bad Terminal Specifier\n");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -395,6 +395,8 @@ ResMoveDevices(node1, node2)
|
|||
{
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -108,6 +108,26 @@ resMultiPlaneTerm(Tile *tile, tileJunk *junk2)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------------------
|
||||
*
|
||||
* resSubstrateTerm --
|
||||
*
|
||||
* Callback function to set a junk field
|
||||
*
|
||||
*--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
resSubstrateTerm(Tile *tile)
|
||||
{
|
||||
tileJunk *Junk;
|
||||
|
||||
Junk = resAddField(tile);
|
||||
Junk->tj_status |= RES_TILE_SUBS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -165,6 +185,7 @@ ResAddPlumbing(tile, arg)
|
|||
Tile *tp1, *tp2, *source;
|
||||
resDevice *resDev;
|
||||
ExtDevice *devptr;
|
||||
TileTypeBitMask locDevSubsMask;
|
||||
|
||||
if (resDevStack == NULL)
|
||||
resDevStack = StackNew(64);
|
||||
|
|
@ -181,7 +202,8 @@ ResAddPlumbing(tile, arg)
|
|||
junk2 = resAddField(tile);
|
||||
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), loctype))
|
||||
{
|
||||
int i, nterms;
|
||||
int i, nterms, pNum;
|
||||
Rect r;
|
||||
|
||||
/* Count SD terminals of the device */
|
||||
nterms = 0;
|
||||
|
|
@ -288,9 +310,6 @@ ResAddPlumbing(tile, arg)
|
|||
/* other plane (in ResUse) */
|
||||
if (source == NULL)
|
||||
{
|
||||
int pNum;
|
||||
Rect r;
|
||||
|
||||
TiToRect(tile, &r);
|
||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||
{
|
||||
|
|
@ -381,6 +400,22 @@ ResAddPlumbing(tile, arg)
|
|||
}
|
||||
}
|
||||
|
||||
/* Find device substrate */
|
||||
|
||||
TTMaskZero(&locDevSubsMask);
|
||||
TTMaskSetMask(&locDevSubsMask, &(devptr->exts_deviceSubstrateTypes));
|
||||
TTMaskClearType(&locDevSubsMask, TT_SPACE);
|
||||
|
||||
TiToRect(tile, &r);
|
||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||
{
|
||||
if (TTMaskIntersect(&DBPlaneTypes[pNum], &locDevSubsMask))
|
||||
DBSrPaintArea((Tile *)NULL,
|
||||
ResUse->cu_def->cd_planes[pNum],
|
||||
&r, &locDevSubsMask,
|
||||
resSubstrateTerm, (ClientData)NULL);
|
||||
}
|
||||
|
||||
/* find rest of device; search for source edges */
|
||||
|
||||
STACKPUSH((ClientData)tile, resDevStack);
|
||||
|
|
|
|||
|
|
@ -461,18 +461,20 @@ typedef struct capval
|
|||
#define RES_DEV_PLUG 0x00000002
|
||||
|
||||
/* flags for tiles */
|
||||
/* A tile which is part of a substrate region. */
|
||||
#define RES_TILE_SUBS 0x01
|
||||
/* A tile which is part of a source/drain region. */
|
||||
#define RES_TILE_SD 0x1
|
||||
#define RES_TILE_SD 0x02
|
||||
/* A tile which is actually a device */
|
||||
#define RES_TILE_DEV 0x2
|
||||
#define RES_TILE_DEV 0x04
|
||||
/* Indicates whether the tile has been processed or not */
|
||||
#define RES_TILE_DONE 0x4
|
||||
#define RES_TILE_DONE 0x08
|
||||
/*a temporary marking flag */
|
||||
#define RES_TILE_MARK 0x8
|
||||
#define RES_TILE_MARK 0x10
|
||||
/* indicates that tile has unidirectional current flow */
|
||||
#ifdef LAPLACE
|
||||
#define RES_TILE_1D 0x10
|
||||
#define RES_TILE_GDONE 0x20
|
||||
#define RES_TILE_1D 0x20
|
||||
#define RES_TILE_GDONE 0x40
|
||||
#endif
|
||||
/* tree walking flags */
|
||||
#define RES_LOOP_OK 1
|
||||
|
|
@ -604,6 +606,7 @@ extern int ResTileCount;
|
|||
extern ResSimNode **ResNodeArray;
|
||||
extern CellDef *mainDef;
|
||||
extern TileTypeBitMask ResSDTypesBitMask;
|
||||
extern TileTypeBitMask ResSubTypesBitMask;
|
||||
extern HashTable ResDevTable;
|
||||
extern TileTypeBitMask ResNoMergeMask[NT];
|
||||
extern ResGlobalParams gparams;
|
||||
|
|
|
|||
Loading…
Reference in New Issue