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:
parent
8b9c47c3ef
commit
999b537f07
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||
/* 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)
|
||||
{
|
||||
if (pNum == ExtCurStyle->exts_globSubstratePlane) continue;
|
||||
|
||||
/* Does the type set of this plane intersect the substrate types? */
|
||||
|
||||
if (TTMaskIntersect(&DBPlaneTypes[pNum], &subsTypesNonSpace))
|
||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||
{
|
||||
if (pNum == ExtCurStyle->exts_globSubstratePlane) continue;
|
||||
|
||||
/* Does the type set of this plane intersect the substrate types? */
|
||||
|
||||
arg.fra_pNum = pNum;
|
||||
if (space_is_substrate)
|
||||
if (TTMaskIntersect(&DBPlaneTypes[pNum], &subsTypesNonSpace))
|
||||
DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum],
|
||||
&TiPlaneRect, &subsTypesNonSpace, extUnInit,
|
||||
extSubsFunc2, (ClientData) &arg);
|
||||
else
|
||||
DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum],
|
||||
&TiPlaneRect, &subsTypesNonSpace, extUnInit,
|
||||
extSubsFunc, (ClientData) &arg);
|
||||
&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,29 +3924,43 @@ extNodeAreaFunc(tile, arg)
|
|||
if (type == TT_SPACE) return 0; /* Should not happen */
|
||||
}
|
||||
|
||||
/* Compute the resistance for the previous region */
|
||||
if (old = (NodeRegion *) arg->fra_region)
|
||||
if (ExtOptions & EXT_DORESISTANCE)
|
||||
extSetResist(old);
|
||||
/* 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. */
|
||||
|
||||
/* Allocate a new node */
|
||||
nclasses = ExtCurStyle->exts_numResistClasses;
|
||||
n = sizeof (NodeRegion) + (sizeof (PerimArea) * (nclasses - 1));
|
||||
reg = (NodeRegion *) mallocMagic((unsigned) n);
|
||||
reg->nreg_labels = (LabelList *) NULL;
|
||||
reg->nreg_cap = (CapValue) 0;
|
||||
reg->nreg_resist = 0;
|
||||
reg->nreg_pnum = DBNumPlanes;
|
||||
reg->nreg_next = (NodeRegion *) NULL;
|
||||
for (n = 0; n < nclasses; n++)
|
||||
reg->nreg_pa[n].pa_perim = reg->nreg_pa[n].pa_area = 0;
|
||||
if ((tile == NULL) || (arg->fra_continue == FALSE))
|
||||
{
|
||||
/* Compute the resistance for the previous region */
|
||||
if (old = (NodeRegion *) arg->fra_region)
|
||||
if (ExtOptions & EXT_DORESISTANCE)
|
||||
extSetResist(old);
|
||||
|
||||
/* Prepend the new node to the region list */
|
||||
reg->nreg_next = (NodeRegion *) arg->fra_region;
|
||||
arg->fra_region = (Region *) reg;
|
||||
/* Allocate a new node */
|
||||
nclasses = ExtCurStyle->exts_numResistClasses;
|
||||
n = sizeof (NodeRegion) + (sizeof (PerimArea) * (nclasses - 1));
|
||||
reg = (NodeRegion *) mallocMagic((unsigned) n);
|
||||
reg->nreg_labels = (LabelList *) NULL;
|
||||
reg->nreg_cap = (CapValue) 0;
|
||||
reg->nreg_resist = 0;
|
||||
reg->nreg_pnum = DBNumPlanes;
|
||||
reg->nreg_next = (NodeRegion *) NULL;
|
||||
for (n = 0; n < nclasses; n++)
|
||||
reg->nreg_pa[n].pa_perim = reg->nreg_pa[n].pa_area = 0;
|
||||
|
||||
/* Used by substrate generating routine */
|
||||
if (tile == NULL) return 1;
|
||||
/* Prepend the new node to the region list */
|
||||
reg->nreg_next = (NodeRegion *) arg->fra_region;
|
||||
arg->fra_region = (Region *) reg;
|
||||
|
||||
/* 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;
|
||||
|
|
|
|||
|
|
@ -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(¬SubMask, &subMask);
|
||||
TTMaskAndMask(¬SubMask, &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, ¬SubMask,
|
||||
&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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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)®ion) == 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;
|
||||
|
|
|
|||
|
|
@ -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,14 +126,150 @@ ExtFindRegions(def, area, mask, connectsTo, uninit, first, each)
|
|||
arg.fra_region = (Region *) NULL;
|
||||
|
||||
SigDisableInterrupts();
|
||||
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);
|
||||
|
||||
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);
|
||||
SigEnableInterrupts();
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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,54 +881,27 @@ 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
|
||||
* with each node), so we don't pass extHierLabEach() to
|
||||
* ExtFindRegions().
|
||||
*/
|
||||
ha->ha_cumFlat.et_nodes =
|
||||
(NodeRegion *) ExtFindRegions(cumUse->cu_def, &TiPlaneRect,
|
||||
&ExtCurStyle->exts_activeTypes,
|
||||
ExtCurStyle->exts_nodeConn,
|
||||
extUnInit, extHierLabFirst, (int (*)()) NULL);
|
||||
ExtLabelRegions(cumUse->cu_def, ExtCurStyle->exts_nodeConn,
|
||||
|
||||
/*
|
||||
* We don't care about the lreg_ll or lreg_pNum for these
|
||||
* nodes (we're only interested in the label list associated
|
||||
* with each node), so we don't pass extHierLabEach() to
|
||||
* ExtFindRegions().
|
||||
*/
|
||||
ha->ha_cumFlat.et_nodes =
|
||||
(NodeRegion *) ExtFindRegions(cumUse->cu_def, &TiPlaneRect,
|
||||
&ExtCurStyle->exts_activeTypes,
|
||||
ExtCurStyle->exts_nodeConn,
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Reference in New Issue