diff --git a/database/DBcellcopy.c b/database/DBcellcopy.c index 8362240b..722a7b3b 100644 --- a/database/DBcellcopy.c +++ b/database/DBcellcopy.c @@ -342,6 +342,248 @@ DBCellCheckCopyAllPaint(scx, mask, xMask, targetUse, func) DBTreeSrTiles(scx, &locMask, xMask, dbCopyAllPaint, (ClientData) &arg); } +/* Client data structure used by DBCellCopySubstrate() */ + +struct dbCopySubData { + Plane *csd_plane; + TileType csd_subtype; + int csd_pNum; + bool csd_modified; +}; + +/* + *----------------------------------------------------------------------------- + * + * DBCellCopySubstrate -- + * + * This function is used by the extraction code in ExtSubtree.c. + * Paint substrate into the target use. Similar to DBCellCopyAllPaint(), + * but it finds space tiles on the substrate plane and converts them to + * a substrate type in the target, clipped to the cell boundary. This + * allows the extraction to find and record all substrate regions, both + * common (global substrate) and local (isolated substrate), without + * requiring a physical substrate type to be drawn into all cells. + * + * Unlike normal paint copying, this can only be done by painting the + * substrate type over the entire cell area and then erasing all areas + * belonging to not-substrate types in the source. + * + * Returns: + * Nothing. + * + * Side Effects: + * Paints into the targetUse's CellDef. This only happens if two + * conditions are met: + * (1) The techfile has defined "substrate" + * (2) The techfile defines a type corresponding to the substrate + * + * ---------------------------------------------------------------------------- + */ + +void +DBCellCopySubstrate(scx, subType, notSubMask, targetUse) + SearchContext *scx; + TileType subType; /* Substrate paint type */ + TileTypeBitMask *notSubMask; /* Mask of types that are not substrate */ + CellUse *targetUse; +{ + struct dbCopySubData csd; + Plane *tempPlane; + int plane; + Rect rect; + int dbEraseNonSub(); + int dbCopySubFunc(); + + 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); + + /* First paint the substrate type in the temporary plane over the whole cell area */ + DBPaintPlane(tempPlane, &rect, DBStdPaintTbl(subType, plane), + (PaintUndoInfo *)NULL); + + csd.csd_subtype = subType; + csd.csd_plane = tempPlane; + csd.csd_pNum = plane; + + /* Now erase all areas that are non-substrate types in the source */ + /* Note: xMask is always zero, as this is only called from extract routines */ + DBTreeSrTiles(scx, notSubMask, 0, dbEraseNonSub, (ClientData)&csd); + + /* Finally, copy the temp plane contents into the destination */ + csd.csd_plane = targetUse->cu_def->cd_planes[plane]; + DBSrPaintArea((Tile *)NULL, tempPlane, &TiPlaneRect, + &DBAllButSpaceBits, dbCopySubFunc, (ClientData)&csd); + + /* Clean up by removing the temp plane */ + DBFreePaintPlane(tempPlane); + TiFreePlane(tempPlane); +} + +/* Create a canonical substrate. Return the modified plane */ + +Plane * +DBCellCanonicalSubstrate(scx, subType, notSubMask, subShieldMask, targetUse) + SearchContext *scx; + TileType subType; /* Substrate paint type */ + TileTypeBitMask *notSubMask; /* Mask of types that are not substrate */ + TileTypeBitMask *subShieldMask; /* Mask of types that shield substrate */ + CellUse *targetUse; +{ + struct dbCopySubData csd; + Plane *tempPlane; + int plane; + Rect rect; + int dbPaintSubFunc(); + int dbEraseNonSub(); + int dbCopySubFunc(); + + 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; + csd.csd_modified = FALSE; + + /* First paint the substrate type in the temporary plane over the */ + /* area of all substrate shield types. */ + /* Note: xMask is always zero, as this is only called from extract routines */ + DBTreeSrTiles(scx, subShieldMask, 0, dbPaintSubFunc, (ClientData)&csd); + if (csd.csd_modified == FALSE) return NULL; + + /* Now erase all areas that are non-substrate types in the source */ + DBTreeSrTiles(scx, notSubMask, 0, dbEraseNonSub, (ClientData)&csd); + + /* Finally, copy the destination plane contents onto tempPlane */ + DBSrPaintArea((Tile *)NULL, targetUse->cu_def->cd_planes[plane], &TiPlaneRect, + &DBAllButSpaceBits, dbCopySubFunc, (ClientData)&csd); + + return tempPlane; +} + +/* + * Callback function for DBCellCopySubstrate() + * Finds tiles on the substrate plane in the source def that are not the + * substrate type, and erases those areas from the target. + */ + +int +dbEraseNonSub(tile, cxp) + Tile *tile; /* Pointer to tile to erase from target */ + TreeContext *cxp; /* Context from DBTreeSrTiles */ +{ + SearchContext *scx; + Rect sourceRect, targetRect; + Plane *plane; /* Plane of target data */ + TileType type, loctype, subType; + struct dbCopySubData *csd; + int pNum; + + csd = (struct dbCopySubData *)cxp->tc_filter->tf_arg; + plane = csd->csd_plane; + subType = csd->csd_subtype; + pNum = csd->csd_pNum; + + scx = cxp->tc_scx; + + type = TiGetTypeExact(tile); + if (IsSplit(tile)) + { + loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile); + if (loctype == TT_SPACE) return 0; + } + else + loctype = type; + + /* Construct the rect for the tile */ + TITORECT(tile, &sourceRect); + + /* Transform to target coordinates */ + GEOTRANSRECT(&scx->scx_trans, &sourceRect, &targetRect); + + /* Erase the substrate type from the area of this tile in the target plane. */ + return DBNMPaintPlane(plane, loctype, &targetRect, DBStdEraseTbl(subType, pNum), + (PaintUndoInfo *)NULL); +} + +/* + * Callback function for DBCellCopySubstrate() + * Simple paint function to copy substrate paint from a temporary plane into + * a target plane. + */ + +int +dbCopySubFunc(tile, csd) + Tile *tile; /* Pointer to tile to erase from target */ + struct dbCopySubData *csd; /* Client data */ +{ + Rect rect; + int pNum; + TileType type, loctype; + Plane *plane; + + plane = csd->csd_plane; + pNum = csd->csd_pNum; + type = TiGetTypeExact(tile); + if (IsSplit(tile)) + { + loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile); + if (loctype == TT_SPACE) return 0; + } + else + loctype = type; + + /* Construct the rect for the tile */ + TITORECT(tile, &rect); + + return DBNMPaintPlane(plane, type, &rect, DBStdPaintTbl(loctype, pNum), + (PaintUndoInfo *)NULL); +} + +int +dbPaintSubFunc(tile, cxp) + Tile *tile; /* Pointer to source tile with shield type */ + TreeContext *cxp; /* Context from DBTreeSrTiles */ +{ + Rect rect; + int pNum; + TileType type, loctype, subType; + Plane *plane; + struct dbCopySubData *csd; /* Client data */ + + 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, &rect); + csd->csd_modified = TRUE; + + return DBNMPaintPlane(plane, type, &rect, DBStdPaintTbl(subType, pNum), + (PaintUndoInfo *)NULL); +} + /* *----------------------------------------------------------------------------- * diff --git a/database/database.h.in b/database/database.h.in index a8c88e57..b544cbae 100644 --- a/database/database.h.in +++ b/database/database.h.in @@ -819,6 +819,8 @@ extern char *DBPrintUseId(); extern void DBCellCopyPaint(); extern void DBCellCopyAllPaint(); extern void DBCellCheckCopyAllPaint(); +extern void DBCellCopySubstrate(); +extern Plane *DBCellCanonicalSubstrate(); extern void DBCellCopyLabels(); extern void DBCellCopyAllLabels(); extern void DBCellCopyCells(); diff --git a/extract/ExtHard.c b/extract/ExtHard.c index 1cd48c57..f938dedf 100644 --- a/extract/ExtHard.c +++ b/extract/ExtHard.c @@ -484,7 +484,10 @@ extHardFreeAll(def, tReg) /* Free all LabelLists and then the region */ for (ll = reg->treg_labels; ll; ll = ll->ll_next) + { + if (ll->ll_label->lab_flags & LABEL_GENERATE) freeMagic(ll->ll_label); freeMagic((char *) ll); + } freeMagic((char *) reg); } } diff --git a/extract/ExtRegion.c b/extract/ExtRegion.c index 658d272c..17c5c43c 100644 --- a/extract/ExtRegion.c +++ b/extract/ExtRegion.c @@ -127,6 +127,69 @@ ExtFindRegions(def, area, mask, connectsTo, uninit, first, each) return (arg.fra_region); } +/* + * ---------------------------------------------------------------------------- + * ExtFindSubstrateRegions -- + * + * This is a subset of ExtFindRegions that looks only at the substrate + * plane. It is called on the first pass, when only the parent paint + * has been added to the cumulative def. + * + * ---------------------------------------------------------------------------- + */ + +Region * +ExtFindSubstrateRegions(def, area, mask, connectsTo, uninit, first, each) + CellDef *def; /* Cell definition being searched */ + Rect *area; /* Area to search initially for tiles */ + TileTypeBitMask *mask; /* In the initial area search, only visit + * tiles whose types are in this mask. + */ + TileTypeBitMask *connectsTo;/* Connectivity table for determining regions. + * If t1 and t2 are the types of adjacent + * tiles, then t1 and t2 belong to the same + * region iff: + * TTMaskHasType(&connectsTo[t1], t2) + * + * We assume that connectsTo[] is symmetric, + * so this is the same as: + * TTMaskHasType(&connectsTo[t2], t1) + */ + ClientData uninit; /* Contents of a ti_client field indicating + * that the tile has not yet been visited. + */ + Region * (*first)(); /* Applied to first tile in region */ + int (*each)(); /* Applied to each tile in region */ +{ + FindRegion arg; + TileTypeBitMask subMask; + int extRegionAreaFunc(); + + ASSERT(first != NULL, "ExtFindRegions"); + + arg.fra_pNum = ExtCurStyle->exts_globSubstratePlane; + if (arg.fra_pNum < 0) return NULL; + + arg.fra_connectsTo = connectsTo; + arg.fra_def = def; + arg.fra_uninit = uninit; + arg.fra_first = first; + arg.fra_each = each; + arg.fra_region = (Region *) NULL; + + SigDisableInterrupts(); + + TTMaskZero(&subMask); + TTMaskSetMask(&subMask, mask); + TTMaskAndMask(&subMask, &ExtCurStyle->exts_globSubstrateTypes); + + DBSrPaintClient((Tile *) NULL, def->cd_planes[arg.fra_pNum], + area, &subMask, uninit, extRegionAreaFunc, (ClientData) &arg); + SigEnableInterrupts(); + + return (arg.fra_region); +} + /* * ---------------------------------------------------------------------------- * diff --git a/extract/ExtSubtree.c b/extract/ExtSubtree.c index 89b054a8..10aa007b 100644 --- a/extract/ExtSubtree.c +++ b/extract/ExtSubtree.c @@ -170,6 +170,11 @@ extSubtree(parentUse, reg, f) float pdone, plast; SearchContext scx; + TileType subType; + TileTypeBitMask subMask, notSubMask; + Plane *subPlane, *savePlane; + bool hasSubDef = FALSE; + /* Use the display timer to force a 5-second progress check */ GrDisplayStatus = DISPLAY_IN_PROGRESS; SigSetTimer(5); /* Print at 5-second intervals */ @@ -195,6 +200,54 @@ extSubtree(parentUse, reg, f) ha.ha_cumFlat.et_use = extYuseCum; HashInit(&ha.ha_connHash, 32, 0); + /* Determine if substrate copying is required. */ + + hasSubDef = (ExtCurStyle->exts_globSubstratePlane != -1) ? TRUE : FALSE; + if (hasSubDef) + { + /* 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) hasSubDef = FALSE; + } + + /* 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). */ + if (hasSubDef) + { + int pNum; + + scx.scx_trans = GeoIdentityTransform; + scx.scx_area = def->cd_bbox; + scx.scx_use = parentUse; + + subPlane = DBCellCanonicalSubstrate(&scx, subType, ¬SubMask, + &ExtCurStyle->exts_globSubstrateShieldTypes, parentUse); + if (subPlane != NULL) + { + pNum = ExtCurStyle->exts_globSubstratePlane; + savePlane = parentUse->cu_def->cd_planes[pNum]; + parentUse->cu_def->cd_planes[pNum] = subPlane; + } + else + hasSubDef = FALSE; /* CellDef has no isolated substrate regions */ + } + #ifndef exactinteractions /* * Cookie-cutter up def into pieces ExtCurStyle->exts_stepSize by @@ -331,6 +384,17 @@ done: /* Clear the CU_SUB_EXTRACTED flag from all children instances */ DBCellEnum(def, extClearUseFlags, (ClientData)NULL); + + /* Replace the modified substrate plane with the original */ + if (hasSubDef) + { + int pNum; + + pNum = ExtCurStyle->exts_globSubstratePlane; + parentUse->cu_def->cd_planes[pNum] = savePlane; + DBFreePaintPlane(subPlane); + TiFreePlane(subPlane); + } } #ifdef exactinteractions @@ -429,26 +493,30 @@ extSubtreeInteraction(ha) NodeRegion *reg; SearchContext scx; - /* Copy parent paint into ha->ha_cumFlat (which was initially empty) */ scx.scx_trans = GeoIdentityTransform; scx.scx_area = ha->ha_interArea; scx.scx_use = ha->ha_parentUse; + +/* + if (hasSubDef) + DBCellCopySubstrate(&scx, subType, ¬SubMask, ha->ha_cumFlat.et_use); +*/ + /* Copy parent paint into ha->ha_cumFlat */ 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. + * First element on the subtree list will be parent mask info, + * including the full flattened substrate. * Extract nodes and capacitors. Node names come from parent. */ oneFlat = extHierNewOne(); oneDef = oneFlat->et_use->cu_def; +/* + if (hasSubDef) + DBCellCopySubstrate(&scx, subType, ¬SubMask, oneFlat->et_use); +*/ 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)) @@ -569,6 +637,7 @@ extSubtreeInteraction(ha) ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL; extHierFreeLabels(cumDef); DBCellClearDef(cumDef); + } /* @@ -732,6 +801,18 @@ extSubtreeFunc(scx, ha) /* Record information for finding node names the hard way later */ ha->ha_subUse = use; + /* Copy the substrate into the oneFlat target */ +/* + if (ha->ha_subType != -1) + { + newscx.scx_use = ha->ha_cumFlat.et_use; + newscx.scx_area = use->cu_bbox; + GEOCLIP(&newscx.scx_area, &ha->ha_interArea); + newscx.scx_trans = GeoIdentityTransform; + DBCellCopySubstrate(&newscx, ha->ha_subType, ha->ha_notSubMask, oneFlat->et_use); + } +*/ + /* * Yank all array elements of this subcell that lie in the interaction * area. Transform to parent coordinates. Prefix is true, meaning that @@ -743,6 +824,7 @@ extSubtreeFunc(scx, ha) hy.hy_area = &ha->ha_subArea; hy.hy_target = oneFlat->et_use; hy.hy_prefix = TRUE; + (void) DBArraySr(use, &ha->ha_subArea, extHierYankFunc, (ClientData) &hy); /* @@ -767,6 +849,8 @@ extSubtreeFunc(scx, ha) */ if (extFirstPass) { + extFirstPass = FALSE; + // On the first pass, run through et_lookName's label list. // Copy any sticky labels to cumUse->cu_def, so that the labels // can be found even when there is no geometry underneath in @@ -796,7 +880,17 @@ extSubtreeFunc(scx, ha) cumUse->cu_def->cd_labels = newlab; } } - extFirstPass = FALSE; + +/* + ha->ha_cumFlat.et_nodes = + (NodeRegion *) ExtFindSubstrateRegions(cumUse->cu_def, + &TiPlaneRect, + &ExtCurStyle->exts_activeTypes, + ExtCurStyle->exts_nodeConn, + extUnInit, extHierLabFirst, (int (*)()) NULL); + ExtLabelRegions(cumUse->cu_def, ExtCurStyle->exts_nodeConn, + &(ha->ha_cumFlat.et_nodes), &TiPlaneRect); +*/ } else { @@ -861,9 +955,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 */ @@ -1216,7 +1307,6 @@ extSubtreeHardSearch(et, arg) HierExtractArg *ha = arg->hw_ha; ExtTree *oneFlat; - arg->hw_proc = extHardProc; if (et == &ha->ha_cumFlat) { diff --git a/extract/extractInt.h b/extract/extractInt.h index 82d18d51..961aab37 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -1016,6 +1016,7 @@ extern ClientData extUnInit; /* ------------------------- Region finding --------------------------- */ extern Region *ExtFindRegions(); +extern Region *ExtFindSubstrateRegions(); /* Filter functions for ExtFindRegions() */ extern Region *extTransFirst(); extern int extTransEach();