From 999b537f07ba2ddde9b5128057948e8b27534f14 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 9 Apr 2021 19:40:54 -0400 Subject: [PATCH] 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. --- database/DBcellcopy.c | 137 ++++++++++++++ database/database.h.in | 6 +- extflat/EFflat.c | 17 +- extract/ExtArray.c | 57 ------ extract/ExtBasic.c | 393 ++++++++++++++++++++++++----------------- extract/ExtCell.c | 134 +++++++++++++- extract/ExtHard.c | 2 +- extract/ExtHier.c | 280 ++++++++++++++++------------- extract/ExtRegion.c | 154 +++++++++++++++- extract/ExtSubtree.c | 239 +++++++++++++------------ extract/ExtTimes.c | 2 +- extract/ExtUnique.c | 9 +- extract/extractInt.h | 16 +- resis/ResMain.c | 2 +- 14 files changed, 968 insertions(+), 480 deletions(-) diff --git a/database/DBcellcopy.c b/database/DBcellcopy.c index 8362240b..44acf654 100644 --- a/database/DBcellcopy.c +++ b/database/DBcellcopy.c @@ -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); +} + /* *----------------------------------------------------------------------------- * diff --git a/database/database.h.in b/database/database.h.in index a8c88e57..2a1a1db6 100644 --- a/database/database.h.in +++ b/database/database.h.in @@ -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(); diff --git a/extflat/EFflat.c b/extflat/EFflat.c index 463b196e..357a97aa 100644 --- a/extflat/EFflat.c +++ b/extflat/EFflat.c @@ -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 diff --git a/extract/ExtArray.c b/extract/ExtArray.c index 605a6451..4458ac4d 100644 --- a/extract/ExtArray.c +++ b/extract/ExtArray.c @@ -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) { diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index c5e0b1c3..5f46dcd3 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -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; diff --git a/extract/ExtCell.c b/extract/ExtCell.c index 50c80ceb..da8ba056 100644 --- a/extract/ExtCell.c +++ b/extract/ExtCell.c @@ -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(); } diff --git a/extract/ExtHard.c b/extract/ExtHard.c index 1cd48c57..5afca0bc 100644 --- a/extract/ExtHard.c +++ b/extract/ExtHard.c @@ -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) { /* diff --git a/extract/ExtHier.c b/extract/ExtHier.c index 73fa39e6..3cf744ba 100644 --- a/extract/ExtHier.c +++ b/extract/ExtHier.c @@ -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; diff --git a/extract/ExtRegion.c b/extract/ExtRegion.c index 658d272c..cf8cf5be 100644 --- a/extract/ExtRegion.c +++ b/extract/ExtRegion.c @@ -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_pNumcd_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_pNumcd_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); diff --git a/extract/ExtSubtree.c b/extract/ExtSubtree.c index 89b054a8..6c268ddc 100644 --- a/extract/ExtSubtree.c +++ b/extract/ExtSubtree.c @@ -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); -} - - /* * ---------------------------------------------------------------------------- * diff --git a/extract/ExtTimes.c b/extract/ExtTimes.c index c13c5f59..566a05e3 100644 --- a/extract/ExtTimes.c +++ b/extract/ExtTimes.c @@ -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++; diff --git a/extract/ExtUnique.c b/extract/ExtUnique.c index 30776c9c..efc39554 100644 --- a/extract/ExtUnique.c +++ b/extract/ExtUnique.c @@ -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); diff --git a/extract/extractInt.h b/extract/extractInt.h index 82d18d51..4bb4fdf0 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -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 diff --git a/resis/ResMain.c b/resis/ResMain.c index f1e65a47..593b9987 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -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); /*