Major overhaul of the method for extracting the substrate, with the

intent to handle multiple isolated substrate regions.  A previous
version of this was added to the master branch but that method had
too many issues and is being deprecated.  This version is also very
experimental and is a work in progress.
This commit is contained in:
Tim Edwards 2021-04-09 19:40:54 -04:00
parent 8b9c47c3ef
commit 999b537f07
14 changed files with 968 additions and 480 deletions

View File

@ -342,6 +342,143 @@ DBCellCheckCopyAllPaint(scx, mask, xMask, targetUse, func)
DBTreeSrTiles(scx, &locMask, xMask, dbCopyAllPaint, (ClientData) &arg);
}
/* Client data structure used by DBCellGenerateSubstrate() */
struct dbCopySubData {
Plane *csd_plane;
TileType csd_subtype;
int csd_pNum;
};
/*
*-----------------------------------------------------------------------------
*
* DBCellGenerateSubstrate --
*
* This function is used by the extraction code in ExtSubtree.c.
* Paint isolated substrate regions into a new plane structure.
* This is done by first finding all areas of types that shield the
* substrate (such as deep nwell), and copying them into the plane as
* the substrate type; then erase all areas occupied in the source by
* non-substrate types on the substrate plane (such as nwell). The
* remaining non-space areas in the plane are then the isolated substrate
* regions.
*
* Returns:
* The modified plane, so that it can be used by the extraction code
* for making and keeping a record of local substrate regions.
*
* Side Effects:
* All modifications are restricted to the generated plane.
*
* ----------------------------------------------------------------------------
*/
Plane *
DBCellGenerateSubstrate(scx, subType, notSubMask, shieldMask)
SearchContext *scx; /* Contains the source use */
TileType subType; /* Substrate type */
TileTypeBitMask *notSubMask; /* Mask of types that are not substrate */
TileTypeBitMask *shieldMask; /* Mask of types that shield substrate */
{
struct dbCopySubData csd;
Plane *tempPlane;
int plane;
Rect rect;
int dbPaintSubFunc();
int dbEraseNonSubFunc();
GEOTRANSRECT(&scx->scx_trans, &scx->scx_area, &rect);
/* Clip to bounding box of the top level cell */
GEOCLIP(&rect, &scx->scx_use->cu_def->cd_bbox);
plane = DBPlane(subType);
tempPlane = DBNewPlane((ClientData) TT_SPACE);
DBClearPaintPlane(tempPlane);
csd.csd_subtype = subType;
csd.csd_plane = tempPlane;
csd.csd_pNum = plane;
/* Copy the destination plane contents onto tempPlane */
DBTreeSrTiles(scx, shieldMask, 0, dbPaintSubFunc, (ClientData)&csd);
/* Erase all areas that are non-substrate types in the source tree */
DBTreeSrTiles(scx, notSubMask, 0, dbEraseNonSubFunc, (ClientData)&csd);
return tempPlane;
}
int
dbPaintSubFunc(tile, cxp)
Tile *tile; /* Pointer to source tile with substrate shield type */
TreeContext *cxp; /* Context from DBTreeSrTiles */
{
SearchContext *scx;
Rect sourceRect, targetRect;
int pNum;
TileType type, loctype, subType;
Plane *plane;
struct dbCopySubData *csd; /* Client data */
scx = cxp->tc_scx;
csd = (struct dbCopySubData *)cxp->tc_filter->tf_arg;
plane = csd->csd_plane;
pNum = csd->csd_pNum;
subType = csd->csd_subtype;
type = TiGetTypeExact(tile);
if (IsSplit(tile))
{
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
if (loctype == TT_SPACE) return 0;
}
/* Construct the rect for the tile */
TITORECT(tile, &sourceRect);
/* Transform to target coordinates */
GEOTRANSRECT(&scx->scx_trans, &sourceRect, &targetRect);
return DBNMPaintPlane(plane, type, &targetRect, DBStdPaintTbl(subType, pNum),
(PaintUndoInfo *)NULL);
}
int
dbEraseNonSubFunc(tile, cxp)
Tile *tile; /* Pointer to source tile with non-substrate type */
TreeContext *cxp; /* Context from DBTreeSrTiles */
{
SearchContext *scx;
Rect sourceRect, targetRect;
int pNum;
TileType type, loctype, subType;
Plane *plane;
struct dbCopySubData *csd; /* Client data */
scx = cxp->tc_scx;
csd = (struct dbCopySubData *)cxp->tc_filter->tf_arg;
plane = csd->csd_plane;
pNum = csd->csd_pNum;
subType = csd->csd_subtype;
type = TiGetTypeExact(tile);
if (IsSplit(tile))
{
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
if (loctype == TT_SPACE) return 0;
}
/* Construct the rect for the tile */
TITORECT(tile, &sourceRect);
/* Transform to target coordinates */
GEOTRANSRECT(&scx->scx_trans, &sourceRect, &targetRect);
return DBNMPaintPlane(plane, type, &targetRect, DBStdEraseTbl(subType, pNum),
(PaintUndoInfo *)NULL);
}
/*
*-----------------------------------------------------------------------------
*

View File

@ -516,11 +516,6 @@ typedef struct celluse
*/
#define CU_SELECT_NET 0x02
#define CU_SELECT_CHUNK 0x04
/* CU_SUB_EXTRACTED is a temporary flag indicating that the substrate
* of the use has been extracted and the extraction
* does not need to be repeated for this use.
*/
#define CU_SUB_EXTRACTED 0x08
/* Character prefix used to denote a locked cell use in a .mag file */
#define CULOCKCHAR '*'
@ -823,6 +818,7 @@ extern void DBCellCopyLabels();
extern void DBCellCopyAllLabels();
extern void DBCellCopyCells();
extern void DBCellCopyAllCells();
extern Plane *DBCellGenerateSubstrate();
/* Contact image handling */
extern TileType DBPlaneToResidue();

View File

@ -918,9 +918,20 @@ efFlatKills(hc)
}
/*----
* WIP
*----
/*
* ----------------------------------------------------------------------------
*
* efFlatCapsDeviceless ---
*
* Recursively flatten uses that have no active devices.
*
* Results:
* Always return 0
*
* Side effects:
* Adds capacitances to the connectivity tables.
*
* ----------------------------------------------------------------------------
*/
int

View File

@ -69,50 +69,6 @@ void extArrayProcess();
void extArrayAdjust();
void extArrayHardSearch();
#if 0
/*
* ----------------------------------------------------------------------------
* extOutputGeneratedLabels ---
*
* Write to the .ext file output "node" lines for labels generated in
* the parent cell where paint in the subcell is not otherwise
* represented by a node in the parent. These nodes have no material
* in the parent, and therefore have no capacitance or resistance
* associated with them.
*
* ----------------------------------------------------------------------------
*/
void
extOutputGeneratedLabels(parentUse, f)
CellUse *parentUse;
FILE *f;
{
CellDef *parentDef;
Label *lab;
int n;
parentDef = parentUse->cu_def;
while ((lab = parentDef->cd_labels) != NULL)
{
if ((lab->lab_flags & LABEL_GENERATE) == 0) return;
fprintf(f, "node \"%s\" 0 0 %d %d %s",
lab->lab_text, lab->lab_rect.r_xbot,
lab->lab_rect.r_ybot,
DBTypeShortName(lab->lab_type));
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
fprintf(f, " 0 0");
putc('\n', f);
freeMagic(lab);
parentDef->cd_labels = lab->lab_next;
}
}
#endif
/*
* ----------------------------------------------------------------------------
*
@ -169,11 +125,6 @@ extArray(parentUse, f)
scx.scx_area = TiPlaneRect;
(void) DBCellSrArea(&scx, extArrayFunc, (ClientData) &ha);
#if 0
/* Output generated labels and remove them from the parent */
extOutputGeneratedLabels(parentUse, f);
#endif
/* Output connections and node adjustments */
extOutputConns(&ha.ha_connHash, f);
HashKill(&ha.ha_connHash);
@ -605,14 +556,6 @@ extArrayInterFunc(use, trans, x, y, ha)
/* Process connections */
extHierConnections(ha, extArrayPrimary, oneFlat);
/* Process substrate connection */
if (use->cu_xlo == use->cu_xhi)
extHierSubstrate(ha, use, -1, y);
else if (use->cu_ylo == use->cu_yhi)
extHierSubstrate(ha, use, x, -1);
else
extHierSubstrate(ha, use, x, y);
ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL;
if (ExtOptions & EXT_DOADJUST)
{

View File

@ -121,8 +121,9 @@ typedef struct LB1
} LinkedBoundary;
LinkedBoundary **extSpecialBounds; /* Linked Boundary List */
NodeRegion *glob_subsnode = NULL; /* Global substrate node */
NodeRegion *temp_subsnode = NULL; /* Last subsnode found */
Stack *extNodeStack = NULL;
Rect *extNodeClipArea = NULL;
#define EDGENULL(r) ((r)->r_xbot > (r)->r_xtop || (r)->r_ybot > (r)->r_ytop)
@ -205,8 +206,6 @@ extBasic(def, outFile)
bool propfound = FALSE;
bool isabstract = FALSE;
glob_subsnode = (NodeRegion *)NULL;
/*
* Build up a list of the device regions for extOutputDevices()
* below. We're only interested in pointers from each region to
@ -236,6 +235,8 @@ extBasic(def, outFile)
int extFoundFunc();
TileTypeBitMask transPlaneMask;
if (reg->treg_tile == (Tile *)NULL) continue; /* Shouldn't happen */
scontext.scx_use = &dummy;
dummy.cu_def = def;
dummy.cu_id = NULL;
@ -262,8 +263,6 @@ extBasic(def, outFile)
if (!SigInterruptPending)
nodeList = extFindNodes(def, (Rect *) NULL, FALSE);
glob_subsnode = temp_subsnode; // Keep a record of the def's substrate
/* Assign the labels to their associated regions */
if (!SigInterruptPending)
ExtLabelRegions(def, ExtCurStyle->exts_nodeConn, &nodeList, &TiPlaneRect);
@ -298,7 +297,7 @@ extBasic(def, outFile)
if (ExtCurStyle->exts_globSubstratePlane != -1)
if (!SigInterruptPending && (ExtOptions&EXT_DOCOUPLING))
extRelocateSubstrateCoupling(&extCoupleHash, glob_subsnode);
extRelocateSubstrateCoupling(&extCoupleHash, ExtSubsRegionList[0]);
}
/* Output device parameters for any subcircuit devices */
@ -322,7 +321,7 @@ extBasic(def, outFile)
/* Output each node, along with its resistance and capacitance to substrate */
if (!SigInterruptPending)
extOutputNodes(nodeList, outFile, glob_subsnode);
extOutputNodes(nodeList, outFile, ExtSubsRegionList[0]);
/* Output coupling capacitances */
if (!SigInterruptPending && (ExtOptions&EXT_DOCOUPLING) && (!propfound))
@ -635,6 +634,7 @@ extOutputNodes(nodeList, outFile)
int n;
Label *lab;
char *text;
bool foundSub;
/* If this node is a subcircuit port, it gets special treatment. */
/* There may be multiple ports per node. */
@ -667,15 +667,17 @@ extOutputNodes(nodeList, outFile)
}
}
foundSub = FALSE;
for (reg = nodeList; reg && !SigInterruptPending; reg = reg->nreg_next)
{
/* Output the node */
text = extNodeName((LabRegion *) reg);
/* Check if this node is the substrate */
if (reg == glob_subsnode)
if (reg == ExtSubsRegionList[0])
{
fprintf(outFile, "substrate \"%s\" 0 0", text);
foundSub = TRUE;
}
else
{
@ -742,12 +744,49 @@ extOutputNodes(nodeList, outFile)
break;
}
}
if ((foundSub == FALSE) && (ExtCurStyle->exts_globSubstratePlane != -1))
{
if (ExtSubsRegionList[0] == NULL)
{
TileType t;
text = ExtSubsName(NULL);
for (t = TT_TECHDEPBASE; t < DBNumUserLayers; t++)
if (TTMaskHasType(&ExtCurStyle->exts_globSubstrateTypes, t))
break;
if (t == DBNumUserLayers) t = TT_SPACE;
fprintf(outFile, "substrate \"%s\" 0 0 0 0 %s", text,
DBTypeShortName(t));
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
fprintf(outFile, " 0 0");
putc('\n', outFile);
}
else
{
reg = (LabRegion *)ExtSubsRegionList[0];
text = extNodeName((LabRegion *)reg);
fprintf(outFile, "substrate \"%s\" 0 0", text);
fprintf(outFile, " %d %d %s",
reg->nreg_ll.p_x, reg->nreg_ll.p_y,
DBTypeShortName(reg->nreg_type));
/* Output its area and perimeter for each resistivity class */
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
fprintf(outFile, " %"DLONG_PREFIX"d %d", reg->nreg_pa[n].pa_area,
reg->nreg_pa[n].pa_perim);
putc('\n', outFile);
}
}
}
/*
* ---------------------------------------------------------------------
*
* extSubsName --
* ExtSubsName --
*
* Return the name of the substrate node, if the node belongs to
* the substrate region and a global substrate node name has been
@ -764,7 +803,7 @@ extOutputNodes(nodeList, outFile)
*/
char *
extSubsName(node)
ExtSubsName(node)
LabRegion *node;
{
char *subsName;
@ -775,7 +814,7 @@ extSubsName(node)
if (ExtCurStyle->exts_globSubstrateName != NULL)
{
if (node->lreg_ll.p_x <= (MINFINITY + 3))
if ((node == NULL) || (node->lreg_ll.p_x <= (MINFINITY + 3)))
{
if (ExtCurStyle->exts_globSubstrateName[0] == '$' &&
ExtCurStyle->exts_globSubstrateName[1] != '$')
@ -826,7 +865,7 @@ extMakeNodeNumPrint(buf, lreg)
Point *p = &lreg->lreg_ll;
char *subsName;
subsName = extSubsName(lreg);
subsName = ExtSubsName(lreg);
if (subsName != NULL)
strcpy(buf, subsName);
else
@ -1833,14 +1872,14 @@ extOutputDevices(def, transList, outFile)
&ExtCurStyle->exts_globSubstrateShieldTypes,
def, &node, NULL);
}
if ((glob_subsnode == NULL) || (node != NULL)) {
if ((ExtSubsRegionList[0] == NULL) || (node != NULL)) {
/* See if there is another matching device record */
/* with a different terminal type, and try again. */
devptr = extDevFindMatch(devptr, t);
break;
}
else if ((node == NULL) && (glob_subsnode != NULL))
node = glob_subsnode;
else if ((node == NULL) && (ExtSubsRegionList[0] != NULL))
node = ExtSubsRegionList[0];
}
else if (node == NULL) {
/* See if there is another matching device record */
@ -2649,7 +2688,7 @@ extTransTileFunc(tile, pNum, arg)
if (region == (NodeRegion *)NULL)
if (allow_globsubsnode)
region = glob_subsnode;
region = ExtSubsRegionList[0];
extTransRec.tr_subsnode = region;
@ -3140,8 +3179,8 @@ extSpecialPerimFunc(bp, sense)
if (!sense || needSurvey)
{
if (toutside == TT_SPACE)
if (glob_subsnode != NULL)
diffNode = glob_subsnode;
if (ExtSubsRegionList[0] != NULL)
diffNode = ExtSubsRegionList[0];
}
/* Check for terminal on different plane than the device */
@ -3586,7 +3625,7 @@ extTransEach(tile, pNum, arg)
int area = TILEAREA(tile);
if (IsSplit(tile)) area /= 2; /* Split tiles are 1/2 area! */
else if (IsSplit(reg->treg_tile))
else if (reg->treg_tile && IsSplit(reg->treg_tile))
{
/* Avoid setting the region's tile pointer to a split tile */
reg->treg_tile = tile;
@ -3606,6 +3645,79 @@ extTransEach(tile, pNum, arg)
return (0);
}
/*
* ----------------------------------------------------------------------------
*
* ExtTagSubstrate --
*
* Scan the node regions in the isolated substrate plane, and mark the
* client record of each tile with an index unique to that region.
*
* Results:
* None.
*
* Side effects:
* Updates the total number of isolated substrate regions on the
* substrate plane. These regions may be connected together in
* higher planes, but this enumerates all the distinct areas in
* the substrate plane itself.
*
* ----------------------------------------------------------------------------
*/
void
ExtTagSubstrate(def)
CellDef *def; /* Def whose nodes are being found */
{
FindRegion arg;
TileTypeBitMask subTypesNonSpace;
int extSubTagFunc();
/* Initialize the node stack here, used by */
/* extNodeAreaFunc() and extRegionAreaFunc() */
if (extNodeStack == (Stack *)NULL)
extNodeStack = StackNew(64);
/* Clip area shouldn't be used for substrate */
extNodeClipArea = (Rect *)NULL;
if (ExtSubsPlane == NULL) return (NodeRegion *)NULL;
/* Search must not include TT_SPACE; TT_SPACE wil be the global */
/* substrate node by definition. */
TTMaskZero(&subTypesNonSpace);
TTMaskSetMask(&subTypesNonSpace, &ExtCurStyle->exts_globSubstrateTypes);
TTMaskClearType(&subTypesNonSpace, TT_SPACE);
arg.fra_def = def;
arg.fra_region = (Region *) NULL;
arg.fra_pNum = 0; /* Unused, but must be initialized */
SigDisableInterrupts();
DBSrPaintClient((Tile *) NULL, ExtSubsPlane,
&TiPlaneRect, &subTypesNonSpace,
extUnInit, extSubTagFunc, (ClientData) &arg);
SigEnableInterrupts();
}
int
extSubTagFunc(tile, arg)
Tile *tile;
FindRegion *arg;
{
int extNodeAreaFunc();
ExtNumSubs++;
/* Set the client now so that extNodeAreaFunc does not generate a */
/* region for it; it will just use this value. */
tile->ti_client = (ClientData)ExtNumSubs;
arg->fra_first = NULL;
extRegionAreaFunc(tile, arg);
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -3626,9 +3738,6 @@ extTransEach(tile, pNum, arg)
* ----------------------------------------------------------------------------
*/
Stack *extNodeStack = NULL;
Rect *extNodeClipArea = NULL;
NodeRegion *
extFindNodes(def, clipArea, subonly)
CellDef *def; /* Def whose nodes are being found */
@ -3637,43 +3746,29 @@ extFindNodes(def, clipArea, subonly)
*/
bool subonly; /* If true, only find the substrate node, and return */
{
int extNodeAreaFunc();
int extSubsFunc();
int extSubsFunc2();
FindRegion arg;
int pNum, n;
TileTypeBitMask subsTypesNonSpace;
bool space_is_substrate;
int extNodeAreaFunc();
int extSubsFunc();
/* Reset perimeter and area prior to node extraction */
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
extResistArea[n] = extResistPerim[n] = 0;
extNodeClipArea = clipArea;
if (extNodeStack == (Stack *) NULL)
extNodeStack = StackNew(64);
arg.fra_def = def;
arg.fra_region = (Region *) NULL;
arg.fra_uninit = extUnInit;
arg.fra_continue = FALSE;
SigDisableInterrupts();
/* First pass: Find substrate. Collect all tiles belonging */
/* to the substrate and push them onto the stack. Then */
/* call extNodeAreaFunc() on the first of these to generate */
/* a single substrate node. */
/* Refinement: Split search into two parts, one on the */
/* globSubstratePlane and one on all other planes. ONLY */
/* search other planes if TT_SPACE is in the list of */
/* substrate types, and then only consider those types to */
/* be part of the substrate node if they have only space */
/* below them on the globSubstratePlane. This method lets */
/* a single type like "psd" operate on, for example, both */
/* the substrate and an isolated pwell, without implicitly */
/* connecting the isolated pwell to the substrate. */
temp_subsnode = (NodeRegion *)NULL; // Reset for new search
/* Reset isolated substrate region list prior to rebuilding it */
extClearSubsRegionList();
if (TTMaskHasType(&ExtCurStyle->exts_globSubstrateTypes, TT_SPACE))
space_is_substrate = True;
@ -3694,53 +3789,26 @@ extFindNodes(def, clipArea, subonly)
extSubsFunc, (ClientData) &arg);
}
/* If substrate does not define a space type, then all geometry */
/* connecting to the substrate will have been found by scanning */
/* the substrate plane. */
if (space_is_substrate)
{
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
{
if (pNum == ExtCurStyle->exts_globSubstratePlane) continue;
/* Does the type set of this plane intersect the substrate types? */
if (TTMaskIntersect(&DBPlaneTypes[pNum], &subsTypesNonSpace))
{
arg.fra_pNum = pNum;
if (space_is_substrate)
DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum],
&TiPlaneRect, &subsTypesNonSpace, extUnInit,
extSubsFunc2, (ClientData) &arg);
else
if (TTMaskIntersect(&DBPlaneTypes[pNum], &subsTypesNonSpace))
DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum],
&TiPlaneRect, &subsTypesNonSpace, extUnInit,
extSubsFunc, (ClientData) &arg);
}
}
/* If there was a substrate connection, process it and everything */
/* that was connected to it. If not, then create a new node */
/* to represent the substrate. */
if (!StackEmpty(extNodeStack))
{
Tile *tile;
int tilePlaneNum;
POPTILE(tile, tilePlaneNum);
arg.fra_pNum = tilePlaneNum;
extNodeAreaFunc(tile, &arg);
temp_subsnode = (NodeRegion *)arg.fra_region;
}
else if (ExtCurStyle->exts_globSubstratePlane != -1)
{
NodeRegion *loc_subsnode;
extNodeAreaFunc((Tile *)NULL, (FindRegion *)&arg);
loc_subsnode = (NodeRegion *)arg.fra_region;
loc_subsnode->nreg_pnum = ExtCurStyle->exts_globSubstratePlane;
loc_subsnode->nreg_type = TT_SPACE;
loc_subsnode->nreg_ll.p_x = MINFINITY + 3;
loc_subsnode->nreg_ll.p_y = MINFINITY + 3;
loc_subsnode->nreg_labels = NULL;
temp_subsnode = loc_subsnode;
}
if (subonly == TRUE) return ((NodeRegion *) arg.fra_region);
/* Second pass: Find all other nodes */
@ -3766,11 +3834,12 @@ extSubsFunc(tile, arg)
Tile *tile;
FindRegion *arg;
{
int pNum;
Rect tileArea;
TileType type;
TileTypeBitMask *smask;
int extSubsFunc3();
Rect tileArea;
NodeRegion *reg;
TileTypeBitMask extSubsTypesNonSpace;
int result, subTag;
int extSubsFunc2();
if (IsSplit(tile))
{
@ -3779,64 +3848,55 @@ extSubsFunc(tile, arg)
}
/* Run second search in the area of the tile on the substrate plane */
/* to make sure that no shield types are covering this tile. */
/* to get the substrate region that this tile connects to. Then */
/* set the tile region and call extNodeAreaFunc to find the rest of */
/* the node by connectivity. */
TiToRect(tile, &tileArea);
smask = &ExtCurStyle->exts_globSubstrateShieldTypes;
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
if (TTMaskIntersect(&DBPlaneTypes[pNum], smask))
if (DBSrPaintArea((Tile *) NULL, arg->fra_def->cd_planes[pNum],
&tileArea, smask, extSubsFunc3, (ClientData)NULL) != 0)
return (1);
/* Mark this tile as pending and push it */
PUSHTILE(tile, arg->fra_pNum);
/* That's all we do */
return (0);
}
int
extSubsFunc2(tile, arg)
Tile *tile;
FindRegion *arg;
{
int pNum;
Rect tileArea;
TileTypeBitMask *smask;
int extSubsFunc3();
TiToRect(tile, &tileArea);
/* Run second search in the area of the tile on the substrate plane */
/* to make sure that no shield types are covering this tile. */
smask = &ExtCurStyle->exts_globSubstrateShieldTypes;
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
if (TTMaskIntersect(&DBPlaneTypes[pNum], smask))
if (DBSrPaintArea((Tile *) NULL, arg->fra_def->cd_planes[pNum],
&tileArea, smask, extSubsFunc3, (ClientData)NULL) != 0)
return (1);
/* Run third search in the area of the tile on the substrate plane */
/* to make sure that nothing but space is under these tiles. */
pNum = ExtCurStyle->exts_globSubstratePlane;
if (DBSrPaintArea((Tile *) NULL, arg->fra_def->cd_planes[pNum],
&tileArea, &DBAllButSpaceBits,
extSubsFunc3, (ClientData)NULL) == 0)
if (ExtSubsPlane)
{
/* Mark this tile as pending and push it */
PUSHTILE(tile, arg->fra_pNum);
TTMaskZero(&extSubsTypesNonSpace);
TTMaskSetMask(&extSubsTypesNonSpace, &ExtCurStyle->exts_globSubstrateTypes);
TTMaskClearType(&extSubsTypesNonSpace, TT_SPACE);
TiToRect(tile, &tileArea);
result = DBSrPaintArea((Tile *) NULL, ExtSubsPlane, &tileArea,
&extSubsTypesNonSpace, extSubsFunc2, (ClientData)tile);
}
return (0);
else
result = 0;
if (result == 0)
subTag = 0; /* Default (global) substrate node */
else
/* Get the index of the substrate region, set by extSubsFunc2() */
subTag = (int)tile->ti_client;
if (ExtSubsRegionList[subTag] != (Region *)NULL)
{
/* Region has been seen before, so look up the region */
tile->ti_client = (ClientData)ExtSubsRegionList[subTag];
arg->fra_continue = TRUE;
result = extNodeAreaFunc(tile, arg);
}
else
{
/* First time in region, so let extNodeAreaFunc() get a */
/* new region, and update the region list with it. */
tile->ti_client = (ClientData)arg->fra_uninit;
result = extNodeAreaFunc(tile, arg);
ExtSubsRegionList[subTag] = (Region *)tile->ti_client;
}
return result;
}
int
extSubsFunc3(tile)
extSubsFunc2(tile, sourceTile)
Tile *tile;
Tile *sourceTile;
{
/* Set the source tile's client record to the region attached to this tile */
sourceTile->ti_client = tile->ti_client;
/* Stops the search because something that was not space was found */
return 1;
}
@ -3864,6 +3924,14 @@ extNodeAreaFunc(tile, arg)
if (type == TT_SPACE) return 0; /* Should not happen */
}
/* If tile client is not fra_uninit, then extNodeAreaFunc() */
/* was called with the intention of continuing the existing */
/* region. This is used to connect otherwise disconnected */
/* areas that connect through an implicit isolated */
/* substrate region. */
if ((tile == NULL) || (arg->fra_continue == FALSE))
{
/* Compute the resistance for the previous region */
if (old = (NodeRegion *) arg->fra_region)
if (ExtOptions & EXT_DORESISTANCE)
@ -3885,8 +3953,14 @@ extNodeAreaFunc(tile, arg)
reg->nreg_next = (NodeRegion *) arg->fra_region;
arg->fra_region = (Region *) reg;
/* Used by substrate generating routine */
if (tile == NULL) return 1;
/* Passing NULL tile used to allocate a region only */
if (tile == NULL) return 0;
}
else
{
reg = (Region *)tile->ti_client;
arg->fra_region = (Region *) reg;
}
/* Mark this tile as pending and push it */
PUSHTILE(tile, arg->fra_pNum);
@ -3902,6 +3976,7 @@ extNodeAreaFunc(tile, arg)
* been visited in the meantime. If it's still unvisited,
* visit it and process its neighbors.
*/
arg->fra_continue = FALSE;
if (tile->ti_client == (ClientData) reg)
continue;
tile->ti_client = (ClientData) reg;

View File

@ -51,6 +51,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
*/
ClientData extUnInit = (ClientData) CLIENTDEFAULT;
Plane *ExtSubsPlane = NULL; /* Plane with extracted isolated substrate regions */
int ExtNumSubs = 0; /* (Maximum) number of substrate regions */
Region **ExtSubsRegionList; /* List of substrate regions */
/* ------------------------ Data local to this file ------------------- */
@ -61,7 +64,6 @@ FILE *extFileOpen();
void extCellFile();
void extHeader();
/*
* ----------------------------------------------------------------------------
*
@ -219,6 +221,126 @@ extFileOpen(def, file, mode, doLocal, prealfile)
return (PaOpen(name, mode, ".ext", ".", ".", prealfile));
}
/*
* ----------------------------------------------------------------------------
*
* ExtPrepSubstrate ---
*
* Prepare a plane for representing isolated substrate regions. The
* source CellDef is searched for types that shield (i.e., isolate) a
* section of the layout from the global substrate. The tile type that
* represents the substrate is painted into the isolated regions.
*
* The purpose of this method is to deal with the common methodology in
* which the substrate is not represented by any tile type, because no mask
* is defined for the substrate. Typically, an entire cell such as a digital
* standard cell may be placed on the default substrate or in a deep nwell
* region. It is therefore necessary to be able to detect what is underneath
* a cell on the plane representing the substrate to determine if the area is
* the default substrate or an isolated region. If an isolated region, it
* must be painted with a tile type so that the extraction code can tag the
* tiles with a Region and assign it a node. This code creates the substrate
* paint in the isolated regions for the duration of the extration.
*
* Results:
* Returns a Plane structure, with isolated substrate regions filled
* with the substrate tile type. If there are no isolated substrate
* regions, or if a substrate plane or substrate type is not defined
* by the technology, then the routine returns NULL.
*
* Side effects:
* All modifications are limited to the returned plane structure.
*
* ----------------------------------------------------------------------------
*/
Plane *
ExtPrepSubstrate(def)
CellDef *def;
{
SearchContext scx;
CellUse dummy;
TileType subType;
TileTypeBitMask subMask, notSubMask;
Plane *subPlane, *savePlane;
int pNum;
/* Determine if substrate copying is required. */
if (ExtCurStyle->exts_globSubstratePlane == -1) return NULL;
/* Find a type to use for the substrate, and the mask of all types */
/* in the same plane as the substrate that are not connected to the */
/* substrate. If there is not a simple type representing the substrate */
/* then do not attempt to resolve substrate regions. */
TTMaskZero(&subMask);
TTMaskSetMask(&subMask, &ExtCurStyle->exts_globSubstrateTypes);
for (subType = TT_TECHDEPBASE; subType < DBNumUserLayers; subType++)
if (TTMaskHasType(&subMask, subType))
if (DBPlane(subType) == ExtCurStyle->exts_globSubstratePlane)
break;
TTMaskCom2(&notSubMask, &subMask);
TTMaskAndMask(&notSubMask, &DBPlaneTypes[ExtCurStyle->exts_globSubstratePlane]);
if (subType == DBNumUserLayers) return NULL;
/* Generate the full flattened substrate into ha->ha_cumFlat (which */
/* was empty initially). This adds layer geometry for the */
/* substrate in the typical case where the substrate may be space */
/* (implicitly defined substrate). */
scx.scx_trans = GeoIdentityTransform;
scx.scx_area = def->cd_bbox;
scx.scx_use = &dummy;
dummy.cu_def = def;
dummy.cu_id = NULL;
return DBCellGenerateSubstrate(&scx, subType, &notSubMask,
&ExtCurStyle->exts_globSubstrateShieldTypes, def);
}
/*
* ----------------------------------------------------------------------------
*
* ExtFreeSubstrate ---
* Free up the allocated plane of isolated substrate regions.
*
* Returns:
* Nothing.
*
* Side effects:
* The global ExtSubsPlane is destroyed.
* ----------------------------------------------------------------------------
*/
void
ExtFreeSubstrate()
{
if (ExtSubsPlane == (Plane *)NULL) return;
DBFreePaintPlane(ExtSubsPlane);
TiFreePlane(ExtSubsPlane);
ExtSubsPlane = (Plane *)NULL;
ExtNumSubs = 0;
}
/*
* ----------------------------------------------------------------------------
*
* ----------------------------------------------------------------------------
*/
void
extClearSubsRegionList()
{
int i;
for (i = 0; i <= ExtNumSubs; i++)
ExtSubsRegionList[i] = (Region *)NULL;
}
/*
* ----------------------------------------------------------------------------
*
@ -250,12 +372,21 @@ extCellFile(def, f, doLength)
*/
{
NodeRegion *reg;
int i;
UndoDisable();
/* Output the header: timestamp, technology, calls on cell uses */
if (!SigInterruptPending) extHeader(def, f);
/* Generate the reference plane of substrate regions. There is always at */
/* least one (ExtSubsRegionList[0]) corresponding to the global substrate. */
/* Any additional entries are isolated substrate regions. */
ExtSubsPlane = ExtPrepSubstrate(def);
ExtTagSubstrate(def);
ExtSubsRegionList = (Region **)mallocMagic((ExtNumSubs + 1) * sizeof(Region *));
/* Extract the mask information in this cell */
reg = (NodeRegion *) NULL;
if (!SigInterruptPending) reg = extBasic(def, f);
@ -273,6 +404,7 @@ extCellFile(def, f, doLength)
if (!SigInterruptPending && doLength && (ExtOptions & EXT_DOLENGTH))
extLength(extParentUse, f);
ExtFreeSubstrate();
UndoEnable();
}

View File

@ -200,7 +200,7 @@ extHardProc(scx, arg)
*/
labRegList = (TransRegion *) ExtFindRegions(def, &scx->scx_area,
&arg->hw_mask, ExtCurStyle->exts_nodeConn, extUnInit,
extLabFirst, extLabEach);
extLabFirst, extLabEach, FALSE);
if (labRegList)
{
/*

View File

@ -60,99 +60,6 @@ int extHierConnectFunc2();
int extHierConnectFunc3();
Node *extHierNewNode();
/*----------------------------------------------*/
/* extHierSubstrate */
/* */
/* Find the substrate node of a child cell and */
/* make a connection between parent and child */
/* substrates. If either of the substrate */
/* nodes is already in the hash table, then the */
/* table will be updated as necessary. */
/*----------------------------------------------*/
void
extHierSubstrate(ha, use, x, y)
HierExtractArg *ha; // Contains parent def and hash table
CellUse *use; // Child use
int x, y; // Array subscripts, or -1 if not an array
{
NodeRegion *nodeList;
HashTable *table = &ha->ha_connHash;
HashEntry *he;
NodeName *nn;
Node *node1, *node2;
char *name1, *name2, *childname;
CellDef *def;
NodeRegion *extFindNodes();
/* Backwards compatibility with tech files that don't */
/* define a substrate plane or substrate connections. */
if (glob_subsnode == NULL) return;
/* If the substrate has already been extracted for this use */
/* then there is no need to do it again. */
if (use->cu_flags & CU_SUB_EXTRACTED) return;
def = (CellDef *)ha->ha_parentUse->cu_def;
/* Register the name of the parent's substrate */
/* The parent def's substrate node is in glob_subsnode */
name1 = extNodeName(glob_subsnode);
he = HashFind(table, name1);
nn = (NodeName *) HashGetValue(he);
node1 = nn ? nn->nn_node : extHierNewNode(he);
/* Find the child's substrate node */
nodeList = extFindNodes(use->cu_def, (Rect *) NULL, TRUE);
/* Make sure substrate labels are represented */
ExtLabelRegions(use->cu_def, ExtCurStyle->exts_nodeConn, &nodeList,
&TiPlaneRect);
ExtResetTiles(use->cu_def, extUnInit);
name2 = extNodeName(temp_subsnode);
if (x >= 0 && y >= 0)
{
/* Process array information */
childname = mallocMagic(strlen(name2) + strlen(use->cu_id) + 14);
sprintf(childname, "%s[%d,%d]/%s", use->cu_id, y, x, name2);
}
else if (x >= 0 || y >= 0)
{
childname = mallocMagic(strlen(name2) + strlen(use->cu_id) + 9);
sprintf(childname, "%s[%d]/%s", use->cu_id, ((x >= 0) ? x : y),
name2);
}
else
{
childname = mallocMagic(strlen(name2) + strlen(use->cu_id) + 2);
sprintf(childname, "%s/%s", use->cu_id, name2);
}
he = HashFind(table, childname);
nn = (NodeName *) HashGetValue(he);
node2 = nn ? nn->nn_node : extHierNewNode(he);
freeMagic(childname);
if (node1 != node2)
{
/*
* Both sets of names will now point to node1.
*/
for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next)
nn->nn_node = node1;
nn->nn_node = node1;
nn->nn_next = node1->node_names;
node1->node_names = node2->node_names;
freeMagic((char *) node2);
}
freeMagic(nodeList);
}
/*
* ----------------------------------------------------------------------------
*
@ -216,6 +123,7 @@ extHierConnections(ha, cumFlat, oneFlat)
}
/*
* ----------------------------------------------------------------------------
* extHierConnectFunc1 --
*
* Called for each tile 'oneTile' in the ExtTree 'oneFlat' above
@ -226,6 +134,7 @@ extHierConnections(ha, cumFlat, oneFlat)
*
* Side effects:
* None here, but see extHierConnectFunc2().
* ----------------------------------------------------------------------------
*/
int
@ -240,6 +149,8 @@ extHierConnectFunc1(oneTile, ha)
Label *lab, *newlab;
int i;
unsigned n;
int extHierSubsFunc();
int extHierSubConnectFunc();
/*
* Find all tiles that connect to 'srcTile', but in the
@ -278,6 +189,45 @@ extHierConnectFunc1(oneTile, ha)
}
}
/* Where the type connects to substrate, and the substrate region */
/* under the tile is the default (global) substrate, then the tile */
/* will connect to anything in cumDef that is also connected to the */
/* default substrate. This is where a "substrate halo" could be */
/* applied to restrict the distance at which a substrate region is */
/* considered to be connected (but would have to ignore identifier */
/* types like "pwell" that are part of the substrate itself). */
if ((ExtSubsPlane != NULL) &&
TTMaskHasType(&ExtCurStyle->exts_globSubstrateTypes, ha->hierType))
{
Region *region, *saveRegion;
TileTypeBitMask subMaskNonSpace;
TTMaskZero(&subMaskNonSpace);
TTMaskSetMask(&subMaskNonSpace, &ExtCurStyle->exts_globSubstrateTypes);
TTMaskClearType(&subMaskNonSpace, TT_SPACE);
if (DBSrPaintArea((Tile *)NULL, ExtSubsPlane, &r, &subMaskNonSpace,
extHierSubsFunc, (ClientData)&region) == 0)
region = ExtSubsRegionList[0];
/* This tile connects to a substrate region, so search */
/* cumDef for any tile also connected to the same region. */
saveRegion = ha->ha_parentReg;
ha->ha_parentReg = region;
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
{
ha->hierPNumBelow = i;
TTMaskAndMask3(&mask, connected, &DBPlaneTypes[i]);
if (!TTMaskIsZero(&mask))
DBSrPaintArea((Tile *) NULL, cumDef->cd_planes[i],
&TiPlaneRect, &subMaskNonSpace,
extHierSubConnectFunc, (ClientData)ha);
}
ha->ha_parentReg = saveRegion;
}
/* Where labels have been saved from the parent cell, look for any */
/* that are inside the cell boundary and would connect to the tile. */
/* This allows the extractor to catch "sticky" labels that are not */
@ -330,36 +280,42 @@ extHierConnectFunc1(oneTile, ha)
node1->node_names = node2->node_names;
freeMagic((char *) node2);
}
#if 0
/* Copy this label to the parent def with a */
/* special flag, so we can output it as a node */
/* and then delete it. Don't duplicate labels */
/* that are already in the parent. */
for (newlab = ha->ha_parentUse->cu_def->cd_labels;
newlab; newlab = newlab->lab_next)
if (!strcmp(newlab->lab_text, lab->lab_text))
break;
if (newlab == NULL)
{
n = sizeof(Label) + strlen(lab->lab_text)
- sizeof lab->lab_text + 1;
newlab = (Label *)mallocMagic((unsigned)n);
bcopy((char *)lab, (char *)newlab, (int)n);
newlab->lab_next = ha->ha_parentUse->cu_def->cd_labels;
ha->ha_parentUse->cu_def->cd_labels = newlab;
}
#endif
}
}
return (0);
}
/*
* ----------------------------------------------------------------------------
* extHierSubsFunc --
*
* Callback function to find a non-space tile in ExtSubsPlane. If found,
* get the region associated with the tile by lookup in the list
* ExtSubsRegionList.
*
* Results:
* Return 1 to stop the search.
*
* Side effects:
* Fills the Region * value pointed to by regionPtr
*
* ----------------------------------------------------------------------------
*/
int
extHierSubsFunc(tile, regionPtr)
Tile *tile;
Region **regionPtr;
{
int regIdx = (int)tile->ti_client;
if (regIdx > ExtNumSubs) return 0; /* Invalid condition */
*regionPtr = ExtSubsRegionList[regIdx];
return 1;
}
/*
* ----------------------------------------------------------------------------
* extHierConnectFunc2 --
*
* Called once for each tile 'cum' in extHierCumFlat->et_use->cu_def
@ -375,6 +331,7 @@ extHierConnectFunc1(oneTile, ha)
* if the types of ha->hierOneTile and 'cum' connect.
* Otherwise, if the tiles actually overlap (as opposed
* to merely abut), mark it with feedback as an error.
* ----------------------------------------------------------------------------
*/
int
@ -387,7 +344,7 @@ extHierConnectFunc2(cum, ha)
TileType ttype;
HashEntry *he;
NodeName *nn;
char *name;
char *name1, *name2;
Rect r;
/* Compute the overlap area */
@ -414,14 +371,14 @@ extHierConnectFunc2(cum, ha)
if (extConnectsTo(ha->hierType, ttype, ExtCurStyle->exts_nodeConn))
{
name = (*ha->ha_nodename)(cum, ha->hierPNumBelow, extHierCumFlat, ha, TRUE);
he = HashFind(table, name);
name1 = (*ha->ha_nodename)(cum, ha->hierPNumBelow, extHierCumFlat, ha, TRUE);
he = HashFind(table, name1);
nn = (NodeName *) HashGetValue(he);
node1 = nn ? nn->nn_node : extHierNewNode(he);
name = (*ha->ha_nodename)(ha->hierOneTile, ha->hierPNum, extHierOneFlat,
name2 = (*ha->ha_nodename)(ha->hierOneTile, ha->hierPNum, extHierOneFlat,
ha, TRUE);
he = HashFind(table, name);
he = HashFind(table, name2);
nn = (NodeName *) HashGetValue(he);
node2 = nn ? nn->nn_node : extHierNewNode(he);
@ -452,6 +409,8 @@ extHierConnectFunc2(cum, ha)
}
/*
* ----------------------------------------------------------------------------
*
* extHierConnectFunc3 --
*
* Called once for each tile 'cum' in extHierCumFlat->et_use->cu_def
@ -459,6 +418,8 @@ extHierConnectFunc2(cum, ha)
* parent cell that does not necessarily have associated geometry.
* Value passed in ha_oneTile is the label (recast for convenience;
* need to use a union type in HierExtractArg).
*
* ----------------------------------------------------------------------------
*/
int
@ -533,6 +494,80 @@ extHierConnectFunc3(cum, ha)
return (0);
}
/*
* ----------------------------------------------------------------------------
*
* extHierSubConnectFunc --
*
* Called for all tiles 'cum' in extHierCumFlat->et_use->cu_def
* that connect to substrate types. Checks if the tile is marked
* with the substrate region that has been saved in the
* ha->ha_parentReg record. If so, then processes the connection.
* Only one such connection needs to be processed, so return 1 to
* stop the search.
*
* Results:
* Returns 1 always to stop the search, as only one tile
* with the substrate region needs to be processed.
*
* Side Effects:
* Makes a connection between the nodes of the two tiles
* if the types of ha->hierOneTile and 'cum' connect.
*
* ----------------------------------------------------------------------------
*/
int
extHierSubConnectFunc(cum, ha)
Tile *cum; /* Comes from extHierCumFlat->et_use->cu_def */
HierExtractArg *ha; /* Extraction context */
{
HashTable *table = &ha->ha_connHash;
Node *node1, *node2;
TileType ttype;
HashEntry *he;
NodeName *nn;
char *name1, *name2;
/* If Tile "cum" is not marked with the global substrate region, */
/* then ignore it (return 0 to keep the search going) */
if ((NodeRegion *)cum->ti_client != ha->ha_parentReg) return 0;
ttype = TiGetTypeExact(cum);
if (IsSplit(cum))
ttype = (ttype & TT_SIDE) ? SplitRightType(cum) : SplitLeftType(cum);
name1 = (*ha->ha_nodename)(cum, ha->hierPNumBelow, extHierCumFlat, ha, TRUE);
he = HashFind(table, name1);
nn = (NodeName *) HashGetValue(he);
node1 = nn ? nn->nn_node : extHierNewNode(he);
name2 = (*ha->ha_nodename)(ha->hierOneTile, ha->hierPNum, extHierOneFlat,
ha, TRUE);
he = HashFind(table, name2);
nn = (NodeName *) HashGetValue(he);
node2 = nn ? nn->nn_node : extHierNewNode(he);
if (node1 != node2)
{
/*
* Both sets of names will now point to node1.
* We don't need to update node_cap since it
* hasn't been computed yet.
*/
for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next)
nn->nn_node = node1;
nn->nn_node = node1;
nn->nn_next = node1->node_names;
node1->node_names = node2->node_names;
freeMagic((char *) node2);
}
return 1; /* No need to process any other tiles */
}
/*
* ----------------------------------------------------------------------------
*
@ -808,6 +843,7 @@ extHierLabFirst(tile, arg)
new->lreg_next = (LabRegion *) NULL;
new->lreg_labels = (LabelList *) NULL;
new->lreg_pnum = DBNumPlanes;
new->lreg_type = 0;
/* Prepend it to the region list */
new->lreg_next = (LabRegion *) arg->fra_region;

View File

@ -85,7 +85,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
*/
Region *
ExtFindRegions(def, area, mask, connectsTo, uninit, first, each)
ExtFindRegions(def, area, mask, connectsTo, uninit, first, each, subsOnly)
CellDef *def; /* Cell definition being searched */
Rect *area; /* Area to search initially for tiles */
TileTypeBitMask *mask; /* In the initial area search, only visit
@ -106,9 +106,16 @@ ExtFindRegions(def, area, mask, connectsTo, uninit, first, each)
*/
Region * (*first)(); /* Applied to first tile in region */
int (*each)(); /* Applied to each tile in region */
bool subsOnly; /* If TRUE, only find substrate regions */
{
FindRegion arg;
bool space_is_substrate;
TileTypeBitMask subsTypesNonSpace;
int pNum;
int extRegionAreaFunc();
int extRegionSubsFunc();
ASSERT(first != NULL, "ExtFindRegions");
arg.fra_connectsTo = connectsTo;
@ -119,6 +126,60 @@ ExtFindRegions(def, area, mask, connectsTo, uninit, first, each)
arg.fra_region = (Region *) NULL;
SigDisableInterrupts();
TTMaskZero(&subsTypesNonSpace);
TTMaskSetMask(&subsTypesNonSpace, &ExtCurStyle->exts_globSubstrateTypes);
TTMaskClearType(&subsTypesNonSpace, TT_SPACE);
TTMaskAndMask(&subsTypesNonSpace, mask);
/* No need to search the substrate plane unless substrate types are in */
/* the mask passed as argument. */
if (!TTMaskIsZero(&subsTypesNonSpace))
{
/* Like extFindNodes(), first process the substrate plane so that */
/* that connections can be made through isolated substrate regions */
/* or through the global substrate. */
if (TTMaskHasType(&ExtCurStyle->exts_globSubstrateTypes, TT_SPACE))
space_is_substrate = TRUE;
else
space_is_substrate = FALSE;
/* Clear out the isolated substrate region list before rebuilding it */
extClearSubsRegionList();
pNum = ExtCurStyle->exts_globSubstratePlane;
/* Does the type set of this plane intersect the substrate types? */
if (TTMaskIntersect(&DBPlaneTypes[pNum], &subsTypesNonSpace))
{
arg.fra_pNum = pNum;
DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum],
&TiPlaneRect, &subsTypesNonSpace, uninit,
extRegionSubsFunc, (ClientData) &arg);
}
/* If substrate does not define a space type, then all geometry */
/* connecting to the substrate will have been found by scanning */
/* the substrate plane. */
if (space_is_substrate)
{
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
{
if (pNum == ExtCurStyle->exts_globSubstratePlane) continue;
/* Does the type set of this plane intersect the substrate types? */
if (TTMaskIntersect(&DBPlaneTypes[pNum], &subsTypesNonSpace))
DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum],
&TiPlaneRect, &subsTypesNonSpace, uninit,
extRegionSubsFunc, (ClientData) &arg);
}
}
}
if (!subsOnly)
for (arg.fra_pNum=PL_TECHDEPBASE; arg.fra_pNum<DBNumPlanes; arg.fra_pNum++)
(void) DBSrPaintClient((Tile *) NULL, def->cd_planes[arg.fra_pNum],
area, mask, uninit, extRegionAreaFunc, (ClientData) &arg);
@ -127,6 +188,88 @@ ExtFindRegions(def, area, mask, connectsTo, uninit, first, each)
return (arg.fra_region);
}
int
extRegionSubsFunc(tile, arg)
Tile *tile;
FindRegion *arg;
{
TileType type;
Rect tileArea;
NodeRegion *reg;
int result, subTag;
TileTypeBitMask subsNonSpaceTypes;
Region * (*saveFirst)();
int extRegionAreaFunc();
int extRegionSubsFunc2();
if (IsSplit(tile))
{
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
if (type == TT_SPACE) return 0; /* Should not happen */
}
if (ExtSubsPlane != NULL)
{
/* Search for (non-space) substrate types in the substrate region map */
TTMaskZero(&subsNonSpaceTypes);
TTMaskSetMask(&subsNonSpaceTypes, &ExtCurStyle->exts_globSubstrateTypes);
TTMaskClearType(&subsNonSpaceTypes, TT_SPACE);
/* Run second search in the area of the tile on the substrate plane */
/* to get the substrate region that this tile connects to. Then */
/* set the tile region and call extNodeAreaFunc to find the rest of */
/* the node by connectivity. */
TiToRect(tile, &tileArea);
result = DBSrPaintArea((Tile *) NULL, ExtSubsPlane,
&tileArea, &subsNonSpaceTypes,
extRegionSubsFunc2, (ClientData)tile);
}
else
result = 0;
if (result == 0)
subTag = 0; /* Default (global) substrate node */
else
/* Get the index of the substrate region, set by extRegionSubsFunc2() */
subTag = (int)tile->ti_client;
if (ExtSubsRegionList[subTag] != 0)
{
/* Region has been seen before, so look up the region */
tile->ti_client = (ClientData)ExtSubsRegionList[subTag];
/* Clear fra_first so that extRegionAreaFunc doesn't allocate a new */
/* region record, and restore it afterward. */
saveFirst = arg->fra_first;
arg->fra_first = NULL;
result = extRegionAreaFunc(tile, arg);
arg->fra_first = saveFirst;
}
else
{
/* First time in region, so let extRegionAreaFunc() get a */
/* new region, and then update the region list with it. */
tile->ti_client = (ClientData)arg->fra_uninit;
result = extRegionAreaFunc(tile, arg);
ExtSubsRegionList[subTag] = (Region *)tile->ti_client;
}
return result;
}
int
extRegionSubsFunc2(tile, sourceTile)
Tile *tile;
Tile *sourceTile;
{
/* Set the source tile's client record to the region attached to this tile */
sourceTile->ti_client = tile->ti_client;
/* Stops the search because something that was not space was found */
return 1;
}
/*
* ----------------------------------------------------------------------------
*
@ -159,6 +302,9 @@ extRegionAreaFunc(tile, arg)
/* Allocate a new region */
if (arg->fra_first)
(void) (*arg->fra_first)(tile, arg);
else
/* Called for substrate connectivity */
arg->fra_region = (Region *)tile->ti_client;
if (DebugIsSet(extDebugID, extDebAreaEnum))
extShowTile(tile, "area enum", 0);

View File

@ -99,24 +99,118 @@ void extSubtreeHardSearch();
/*
* ----------------------------------------------------------------------------
*
* extClearUseFlags --
* extSubstrateFunc --
*
* Callback function to clear the CU_SUB_EXTRACTED flag from each child
* use of a CellDef.
* Subcells which do not have any interactions with the parent cell
* according to ExtFindInteractions still interact through the
* substrate. For each non-interacting subcell, make a hierarchical
* connection between the global substrate node of the subcell and
* whatever local substrate node of the parent is underneath the
* subcell.
*
* Results:
* Always return 0 to keep the search going, unless the technology
* file does not define a substrate type, in which case it returns
* 1 to stop searching immediately.
*
* Side effects:
* Makes additional entries in the hierarchy connection tables.
*
* ----------------------------------------------------------------------------
*/
int
extClearUseFlags(use, clientData)
CellUse *use;
ClientData clientData;
extSubstrateFunc(scx, ha)
SearchContext *scx;
HierExtractArg *ha;
{
use->cu_flags &= ~CU_SUB_EXTRACTED;
CellUse *use = scx->scx_use;
NodeRegion *subsNodes1, *subsNodes2;
char *name1, *name2;
HashTable *table = &ha->ha_connHash;
HashEntry *he;
NodeName *nn;
Node *node1, *node2;
char childname[4096], *sptr;
/* Backwards compatibility with tech files that don't */
/* define a substrate plane or substrate connections. */
if (ExtCurStyle->exts_globSubstratePlane == -1) return 1;
/* Record information for finding node names the hard way */
ha->ha_subUse = use;
ha->ha_subArea = use->cu_bbox;
GEOCLIP(&ha->ha_subArea, &ha->ha_interArea);
/* WIP */
/* In the parent, there should only be one substrate region in */
/* the area of the child cell, or zero if the parent has no */
/* geometry at all connected to the substrate. */
subsNodes1 =
(NodeRegion *) ExtFindRegions(ha->ha_parentUse->cu_def,
&ha->ha_subArea, &ExtCurStyle->exts_activeTypes,
ExtCurStyle->exts_nodeConn,
extUnInit, extHierLabFirst, (int (*)()) NULL,
TRUE);
if (subsNodes1 == NULL)
name1 = ExtSubsName(NULL);
else
{
ExtLabelRegions(ha->ha_parentUse->cu_def, ExtCurStyle->exts_nodeConn,
&subsNodes1, &TiPlaneRect);
name1 = extNodeName(subsNodes1);
ExtResetTiles(ha->ha_parentUse->cu_def, extUnInit);
}
he = HashFind(table, name1);
nn = (NodeName *) HashGetValue(he);
node1 = (nn) ? nn->nn_node : extHierNewNode(he);
/* In the child, there may be multiple substrate regions but */
/* only the global region connects to the parent. */
subsNodes2 =
(NodeRegion *) ExtFindRegions(use->cu_def, &TiPlaneRect,
&ExtCurStyle->exts_activeTypes,
ExtCurStyle->exts_nodeConn,
extUnInit, extHierLabFirst, (int (*)()) NULL,
TRUE);
if (subsNodes2 == NULL)
name2 = ExtSubsName(NULL);
else
{
ExtLabelRegions(use->cu_def, ExtCurStyle->exts_nodeConn,
&subsNodes2, &TiPlaneRect);
name2 = extNodeName(ExtSubsRegionList[0]);
ExtResetTiles(use->cu_def, extUnInit);
}
sptr = DBPrintUseId(scx, childname, 4096, FALSE);
sprintf(sptr, "/%s", name2);
he = HashFind(table, childname);
nn = (NodeName *) HashGetValue(he);
node2 = (nn) ? nn->nn_node : extHierNewNode(he);
if (node1 != node2)
{
/*
* Both sets of names will now point to node1.
*/
for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next)
nn->nn_node = node1;
nn->nn_node = node1;
nn->nn_next = node1->node_names;
node1->node_names = node2->node_names;
freeMagic((char *)node2);
}
ExtFreeLabRegions(subsNodes1);
ExtFreeLabRegions(subsNodes2);
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -328,9 +422,6 @@ done:
HashKill(&ha.ha_connHash);
GrDisplayStatus = DISPLAY_IDLE;
SigRemoveTimer();
/* Clear the CU_SUB_EXTRACTED flag from all children instances */
DBCellEnum(def, extClearUseFlags, (ClientData)NULL);
}
#ifdef exactinteractions
@ -434,9 +525,6 @@ extSubtreeInteraction(ha)
scx.scx_area = ha->ha_interArea;
scx.scx_use = ha->ha_parentUse;
DBCellCopyPaint(&scx, &DBAllButSpaceBits, 0, ha->ha_cumFlat.et_use);
#ifdef notdef
extCopyPaint(ha->ha_parentUse->cu_def, &ha->ha_interArea, cumDef);
#endif /* notdef */
/*
* First element on the subtree list will be parent mask info.
@ -446,9 +534,6 @@ extSubtreeInteraction(ha)
oneDef = oneFlat->et_use->cu_def;
DBCellCopyPaint(&scx, &DBAllButSpaceBits, 0, oneFlat->et_use);
#ifdef notdef
extCopyPaint(ha->ha_parentUse->cu_def, &ha->ha_interArea, oneDef);
#endif /* notdef */
oneFlat->et_nodes = extFindNodes(oneDef, &ha->ha_clipArea, FALSE);
if ((ExtOptions & (EXT_DOCOUPLING|EXT_DOADJUST))
== (EXT_DOCOUPLING|EXT_DOADJUST))
@ -723,7 +808,7 @@ extSubtreeFunc(scx, ha)
SearchContext newscx;
ExtTree *oneFlat;
HierYank hy;
int x, y;
int x, y, i;
/* Allocate a new ExtTree to hold the flattened, extracted subtree */
oneFlat = extHierNewOne();
@ -796,10 +881,8 @@ extSubtreeFunc(scx, ha)
cumUse->cu_def->cd_labels = newlab;
}
}
extFirstPass = FALSE;
}
else
{
/*
* We don't care about the lreg_ll or lreg_pNum for these
* nodes (we're only interested in the label list associated
@ -810,40 +893,15 @@ extSubtreeFunc(scx, ha)
(NodeRegion *) ExtFindRegions(cumUse->cu_def, &TiPlaneRect,
&ExtCurStyle->exts_activeTypes,
ExtCurStyle->exts_nodeConn,
extUnInit, extHierLabFirst, (int (*)()) NULL);
extUnInit, extHierLabFirst, (int (*)()) NULL,
extFirstPass);
ExtLabelRegions(cumUse->cu_def, ExtCurStyle->exts_nodeConn,
&(ha->ha_cumFlat.et_nodes), &TiPlaneRect);
}
extFirstPass = FALSE;
/* Process connections; this updates ha->ha_connHash */
extHierConnections(ha, &ha->ha_cumFlat, oneFlat);
/* Process substrate connection. All substrates should be */
/* connected together in the cell def, so in the case of an */
/* array, just make sure that the first array entry is */
/* connected. */
if (use->cu_xhi == use->cu_xlo && use->cu_yhi == use->cu_ylo)
extHierSubstrate(ha, use, -1, -1);
else if (use->cu_xhi == use->cu_xlo && use->cu_yhi > use->cu_ylo)
{
for (y = use->cu_ylo; y <= use->cu_yhi; y++)
extHierSubstrate(ha, use, -1, y);
}
else if (use->cu_xhi > use->cu_xlo && use->cu_yhi == use->cu_ylo)
{
for (x = use->cu_xlo; x <= use->cu_xhi; x++)
extHierSubstrate(ha, use, x, -1);
}
else
{
for (x = use->cu_xlo; x <= use->cu_xhi; x++)
for (y = use->cu_ylo; y <= use->cu_yhi; y++)
extHierSubstrate(ha, use, x, y);
}
/* Mark substrate as having been extracted for this use. */
use->cu_flags |= CU_SUB_EXTRACTED;
/* Free the cumulative node list we extracted above */
if (ha->ha_cumFlat.et_nodes)
{
@ -861,9 +919,6 @@ extSubtreeFunc(scx, ha)
newscx.scx_area = ha->ha_subArea;
newscx.scx_trans = GeoIdentityTransform;
DBCellCopyPaint(&newscx, &DBAllButSpaceBits, 0, cumUse);
#ifdef notdef
extCopyPaint(oneFlat->et_use->cu_def, &ha->ha_subArea, cumUse->cu_def);
#endif /* notdef */
extHierCopyLabels(oneFlat->et_use->cu_def, cumUse->cu_def);
/* Prepend this tree to the list of trees we've processed so far */
@ -873,64 +928,6 @@ extSubtreeFunc(scx, ha)
return (2);
}
/*
* ----------------------------------------------------------------------------
*
* extSubstrateFunc
*
* This contains just the part of extSubtreeFunc() dealing with the
* substrate, so that substrate extraction can occur in cells not
* otherwise having extraction interactions, without incurring the
* overhead of all the other items handled by extHierSubtreeFunc().
*
* Results:
* Always returns 2, to avoid further elements in arrays.
*
* ----------------------------------------------------------------------------
*/
int
extSubstrateFunc(scx, ha)
SearchContext *scx;
HierExtractArg *ha;
{
CellUse *use = scx->scx_use;
int x, y;
/* Record information for finding node names the hard way */
ha->ha_subUse = use;
ha->ha_subArea = use->cu_bbox;
GEOCLIP(&ha->ha_subArea, &ha->ha_interArea);
/* Process substrate connection. All substrates should be */
/* connected together in the cell def, so in the case of an */
/* array, just make sure that the first array entry is */
/* connected. */
if (use->cu_xhi == use->cu_xlo && use->cu_yhi == use->cu_ylo)
extHierSubstrate(ha, use, -1, -1);
else if (use->cu_xhi == use->cu_xlo && use->cu_yhi > use->cu_ylo)
{
for (y = use->cu_ylo; y <= use->cu_yhi; y++)
extHierSubstrate(ha, use, -1, y);
}
else if (use->cu_xhi > use->cu_xlo && use->cu_yhi == use->cu_ylo)
{
for (x = use->cu_xlo; x <= use->cu_xhi; x++)
extHierSubstrate(ha, use, x, -1);
}
else
{
for (x = use->cu_xlo; x <= use->cu_xhi; x++)
for (y = use->cu_ylo; y <= use->cu_yhi; y++)
extHierSubstrate(ha, use, x, y);
}
use->cu_flags |= CU_SUB_EXTRACTED;
return (2);
}
/*
* ----------------------------------------------------------------------------
*

View File

@ -353,7 +353,7 @@ extTimesCellFunc(cs)
/* Count the number of transistors */
transList = (TransRegion *) ExtFindRegions(def, &TiPlaneRect,
&ExtCurStyle->exts_deviceMask, ExtCurStyle->exts_deviceConn,
extUnInit, extTransFirst, extTransEach);
extUnInit, extTransFirst, extTransEach, FALSE);
ExtResetTiles(def, extUnInit);
for (tl = transList; tl; tl = tl->treg_next)
cs->cs_fets++;

View File

@ -97,11 +97,17 @@ extUniqueCell(def, option)
TxPrintf("Processing %s\n", def->cd_name);
TxFlush();
/* Generate the reference plane of substrate regions (see extCellFile()) */
ExtSubsPlane = ExtPrepSubstrate(def);
ExtTagSubstrate(def);
ExtSubsRegionList = (Region **)mallocMagic((ExtNumSubs + 1) * sizeof(Region *));
/* Build up a list of nodes and assign them to tiles */
lregList = (LabRegion *) ExtFindRegions(def, &TiPlaneRect,
&ExtCurStyle->exts_activeTypes,
ExtCurStyle->exts_nodeConn,
extUnInit, extHierLabFirst, (int (*)()) NULL);
extUnInit, extHierLabFirst, (int (*)()) NULL,
FALSE);
/* Assign the labels to their associated regions */
ExtLabelRegions(def, ExtCurStyle->exts_nodeConn, &lregList, &TiPlaneRect);
@ -156,6 +162,7 @@ extUniqueCell(def, option)
HashKill(&labelHash);
ExtFreeLabRegions((LabRegion *) lregList);
ExtResetTiles(def, extUnInit);
ExtFreeSubstrate();
if (nwarn)
TxError("%s: %d warnings\n", def->cd_name, nwarn);
return (nwarn);

View File

@ -261,6 +261,7 @@ typedef struct
* region. May be set by fra_first
* and used by fra_each.
*/
bool fra_continue; /* If TRUE, do not make a new node */
} FindRegion;
#define TILEAREA(tp) ((TOP(tp) - BOTTOM(tp)) * (RIGHT(tp) - LEFT(tp)))
@ -959,10 +960,16 @@ typedef struct node
*/
extern ClientData extUnInit;
/*
* Global values pertaining to the substrate region extraction
*/
extern Plane *ExtSubsPlane; /* Plane with extracted isolated substrate regions */
extern int ExtNumSubs; /* (Maximum) number of isolated substrate regions */
extern Region **ExtSubsRegionList; /* List of substrate regions */
#define extGetRegion(tp) ( (tp)->ti_client )
#define extHasRegion(tp,und) ( (tp)->ti_client != (und) )
/* For non-recursive flooding algorithm */
#define VISITPENDING ((ClientData) NULL) /* Marks tiles on stack */
@ -1049,6 +1056,10 @@ extern Tile *extNodeToTile();
/* -------------------- Miscellaneous procedures ---------------------- */
extern char *extNodeName();
extern char *ExtSubsName();
extern Plane *ExtPrepSubstrate();
extern void ExtTagSubstrate();
extern void ExtFreeSubstrate();
extern NodeRegion *extBasic();
extern NodeRegion *extFindNodes();
extern ExtTree *extHierNewOne();
@ -1063,9 +1074,6 @@ extern int extNumWarnings; /* Number warning messages so far */
extern CellUse *extParentUse; /* Dummy use for def being extracted */
extern ClientData extNbrUn; /* Ditto */
extern NodeRegion *glob_subsnode; /* Substrate node for cell def */
extern NodeRegion *temp_subsnode; /* Substrate connection to subcell */
/*
* This is really a (Stack *), but we use the struct tag to avoid
* having to include stack.h in every .c file. Used in the non-recursive

View File

@ -681,7 +681,7 @@ ResExtractNet(startlist,goodies,cellname)
&(ResUse->cu_def->cd_bbox),
&DBAllButSpaceAndDRCBits,
ResConnectWithSD, extUnInit, ResFirst,
ResEach);
ResEach, FALSE);
ExtResetTiles(ResUse->cu_def,extUnInit);
/*