Revised the "select intersect" command from the previous commit so

that the behavior is to pare down any existing selection by removing
any parts of it that do not intersect the layer specified on the
command line.  This is generally more useful than the previous
method, as the intended purpose is to intersect a number of layers
against one (e.g., all transistors intersecting deep nwell).
This commit is contained in:
Tim Edwards 2021-03-24 16:57:22 -04:00
parent dd86ecc454
commit e884b5b256
3 changed files with 100 additions and 112 deletions

View File

@ -633,12 +633,72 @@ cmdSelectArea(layers, less, option)
TTMaskClearType(&mask, i);
}
}
if (option == SEL_INTERSECT)
SelectIntersect(&scx, &mask, crec->dbw_bitmask);
else
SelectArea(&scx, &mask, crec->dbw_bitmask);
}
/*
* ----------------------------------------------------------------------------
*
* cmdIntersectArea --
*
* This is a utility procedure used by CmdSelect to do area
* selection itersect.
*
* Results:
* None.
*
* Side effects:
* The selection is pared down to contain only the part of the
* original selection that intersects with the type "layer".
*
* ----------------------------------------------------------------------------
*/
void
cmdIntersectArea(layer)
char *layer; /* The layer to intersect with */
{
TileType ttype;
SearchContext scx;
int windowMask, xMask;
DBWclientRec *crec;
MagWindow *window;
bzero(&scx, sizeof(SearchContext));
window = ToolGetBoxWindow(&scx.scx_area, &windowMask);
if (window == NULL)
{
TxPrintf("The box isn't in a window.\n");
return;
}
/* Since the box may actually be in multiple windows, we have to
* be a bit careful. If the box is only in one window, then there's
* no problem. If it's in more than window, the cursor must
* disambiguate the windows.
*/
xMask = ((DBWclientRec *) window->w_clientData)->dbw_bitmask;
if ((windowMask & ~xMask) != 0)
{
window = CmdGetRootPoint((Point *) NULL, (Rect *) NULL);
xMask = ((DBWclientRec *) window->w_clientData)->dbw_bitmask;
if ((windowMask & xMask) == 0)
{
TxPrintf("The box is in more than one window; use the cursor\n");
TxPrintf("to select the one you want to select from.\n");
return;
}
}
scx.scx_use = (CellUse *) window->w_surfaceID;
scx.scx_trans = GeoIdentityTransform;
crec = (DBWclientRec *) window->w_clientData;
ttype = DBTechNoisyNameType(layer);
SelectIntersect(&scx, ttype, crec->dbw_bitmask);
}
/*
* ----------------------------------------------------------------------------
*
@ -935,10 +995,7 @@ CmdSelect(w, cmd)
case SEL_INTERSECT:
if (cmd->tx_argc > 3) goto usageError;
if (!(more || less)) SelectClear();
if (cmd->tx_argc == 3)
cmdSelectArea(optionArgs[1], less, option);
else cmdSelectArea("*,label,subcell", less, option);
cmdIntersectArea(optionArgs[1]);
return;
/*--------------------------------------------------------------------

View File

@ -1040,12 +1040,13 @@ CmdWhat(w, cmd)
{
Tcl_ListObjAppendElement(magicinterp, paintobj,
Tcl_NewStringObj(DBTypeLongName(i), -1));
Tcl_ListObjAppendElement(magicinterp, paintobj,
paintcellobj);
for (lidp = lid; lidp; lidp = lidp->lid_next)
Tcl_ListObjAppendElement(magicinterp, paintcellobj,
Tcl_NewStringObj(lidp->lid_name, -1));
Tcl_ListObjAppendElement(magicinterp, paintobj,
paintcellobj);
}
while (lid != NULL)

View File

@ -253,37 +253,6 @@ selClearFunc(scx)
else return 2;
}
/* Structure used by selIntersectPaintFunc() */
struct selIntersectData {
Rect *sid_rect;
TileType sid_type;
};
/*
* ----------------------------------------------------------------------------
*
* selDupPaintFunc --
*
* Copy paint from tile area in Select2Def into SelectDef as all types
* in rMask.
*
* ----------------------------------------------------------------------------
*/
int
selDupPaintFunc(tile, rMask)
Tile *tile; /* The tile to get the area to copy paint. */
TileTypeBitMask *rMask; /* Paint types to copy to. */
{
Rect r;
TiToRect(tile, &r);
DBPaintMask(SelectDef, &r, rMask);
return 0; /* Keep the search going. */
}
/*
* ----------------------------------------------------------------------------
*
@ -293,18 +262,15 @@ selDupPaintFunc(tile, rMask)
*/
int
selIntersectPaintFunc2(tile, sid)
selIntersectPaintFunc2(tile, rect)
Tile *tile; /* The tile to copy paint from. */
struct selIntersectData *sid;
Rect *rect; /* Area to clip to */
{
Rect r;
int p;
TiToRect(tile, &r);
GEOCLIP(&r, sid->sid_rect); /* Clip out the intersection area */
DBPaint(Select2Def, &r, sid->sid_type); /* Paint back into Select2Def */
GEOCLIP(&r, rect); /* Clip out the intersection area */
DBPaint(SelectDef, &r, TiGetTypeExact(tile)); /* Paint back into SelectDef */
return 0; /* Keep the search going. */
}
@ -319,26 +285,21 @@ selIntersectPaintFunc2(tile, sid)
*/
int
selIntersectPaintFunc(tile, type)
selIntersectPaintFunc(tile)
Tile *tile; /* The tile to copy paint from. */
TileType type; /* The type of tile to keep */
{
TileTypeBitMask tMask;
Rect r;
int plane;
struct selIntersectData sid;
int pNum;
TiToRect(tile, &r);
TTMaskSetOnlyType(&tMask, type);
plane = DBPlane(type);
sid.sid_type = TiGetTypeExact(tile);
sid.sid_rect = &r;
DBSrPaintArea((Tile *)NULL, Select2Def->cd_planes[plane], &r,
&tMask, selIntersectPaintFunc2, (ClientData)&sid);
for (pNum = 0; pNum < DBNumPlanes; pNum++)
{
DBSrPaintArea((Tile *)NULL, Select2Def->cd_planes[pNum], &r,
&DBAllButSpaceAndDRCBits, selIntersectPaintFunc2,
(ClientData)&r);
}
return 0; /* Keep the search going. */
}
@ -363,15 +324,15 @@ selIntersectPaintFunc(tile, type)
*/
void
SelectIntersect(scx, types, xMask)
SelectIntersect(scx, type, xMask)
SearchContext *scx; /* Describes the area in which material
* is to be selected. The resulting
* coordinates should map to the coordinates
* of EditRootDef. The cell use should be
* the root of a window.
*/
TileTypeBitMask *types; /* Indicates which intersecting layers to
* select. May not include labels or cells.
TileType type; /* Indicates which layer to intersect with
* the current selection.
*/
int xMask; /* Indicates window (or windows) where cells
* must be expanded for their contents to be
@ -382,67 +343,36 @@ SelectIntersect(scx, types, xMask)
TileTypeBitMask tMask, rMask;
TileType s, t;
int plane;
SearchContext scx2;
/* If the source definition is changing, clear the old selection. */
if (SelectRootDef != scx->scx_use->cu_def)
{
if (SelectRootDef != NULL)
SelectClear();
SelectRootDef = scx->scx_use->cu_def;
SelSetDisplay(SelectUse, SelectRootDef);
}
/* The source definition may not change */
if (SelectRootDef != scx->scx_use->cu_def) return;
SelRememberForUndo(TRUE, (CellDef *) NULL, (Rect *) NULL);
/* Select all paint of types in "types" mask and copy into Select2Def */
/* Copy SelectDef contents (paint only) into Select2Def */
DBCellClearDef(Select2Def);
(void) DBCellCopyAllPaint(scx, types, xMask, Select2Use);
scx2.scx_use = SelectUse;
scx2.scx_area = SelectUse->cu_bbox;
GeoTransTrans(&GeoIdentityTransform, &SelectUse->cu_transform, &scx2.scx_trans);
DBCellCopyAllPaint(&scx2, &DBAllButSpaceAndDRCBits, CU_DESCEND_NO_LOCK,
Select2Use);
/* Find the first type in the list. This will be used as the reference */
/* Clear the original selection */
DBCellClearDef(SelectDef);
for (t = 0; t < DBNumUserLayers; t++)
if (TTMaskHasType(types, t))
break;
if (t == DBNumUserLayers) return;
/* Compute the type mask of the reference type */
TTMaskSetOnlyType(&tMask, t);
/* Select all paint of type "type" and copy into SelectDef */
TTMaskSetOnlyType(&tMask, type);
plane = DBPlane(t);
(void) DBCellCopyAllPaint(scx, &tMask, xMask, SelectUse);
/* For each other type in "types", do the following */
/* Scan Select2Def for all geometry inside the area of "type", and */
/* copy back to SelectDef as "type" */
for (s = t + 1; s < DBNumUserLayers; s++)
{
if (TTMaskHasType(types, s))
{
/* Copy the reference paint type from Select2Def into SelectDef */
DBSrPaintArea((Tile *)NULL, Select2Def->cd_planes[plane], &scx->scx_area,
&tMask, selDupPaintFunc, (ClientData)&tMask);
DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[plane],
&scx->scx_area, &tMask, selIntersectPaintFunc, (ClientData)NULL);
/* Erase the reference paint type from Select2Def */
DBEraseMask(Select2Def, &TiPlaneRect, &tMask);
/* Scan Select2Def for all geometry of type s inside the areas of */
/* the reference type, and copy back to Select2Def as the reference */
/* type */
DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[plane],
&scx->scx_area, &tMask, selIntersectPaintFunc, (ClientData)s);
/* Erase the reference paint type from SelectDef */
DBEraseMask(SelectDef, &TiPlaneRect, &tMask);
}
}
/* Copy any remaining paint in the reference layer in Select2Def to */
/* SelectDef as all the intersection types. */
DBSrPaintArea((Tile *)NULL, Select2Def->cd_planes[plane], &scx->scx_area,
&tMask, selDupPaintFunc, (ClientData)types);
SelectDef->cd_types = *types; /* Remember what types were requested */
DBEraseMask(SelectDef, &TiPlaneRect, &tMask);
/* Display the new selection. */