Added a new cifinput operator "not-square" that is useful for

differentiating between bar and square contacts on input.  Also:
added handling of the "mask-hints" operator for GDS input as
well as GDS output.  This is a bit more realistic now that the
mask hint properties are handled as scalable integers and not as
character strings.
This commit is contained in:
R. Timothy Edwards 2026-02-26 12:48:00 -05:00
parent 8f684ad5be
commit cb7855235a
6 changed files with 249 additions and 7 deletions

View File

@ -1 +1 @@
8.3.608
8.3.609

View File

@ -4458,14 +4458,16 @@ bridgeErase(
maskBits = DBPlaneTypes[i];
TTMaskAndMask(&maskBits, &brlims->co_paintMask);
if (!TTMaskEqual(&maskBits, &DBZeroTypeBits))
if (DBSrPaintArea((Tile *) NULL, brlims->def->cd_planes[i], area, &brlims->co_paintMask, cifPaintFunc, CIFEraseTable))
if (DBSrPaintArea((Tile *) NULL, brlims->def->cd_planes[i],
area, &brlims->co_paintMask, cifPaintFunc, CIFEraseTable))
return 0;
}
for (t = 0; t < TT_MAXTYPES; t++, temps++)
{
if (TTMaskHasType(&brlims->co_cifMask, t))
if (DBSrPaintArea((Tile *) NULL, *temps, area, &CIFSolidBits, cifPaintFunc, CIFEraseTable))
if (DBSrPaintArea((Tile *) NULL, *temps, area, &CIFSolidBits,
cifPaintFunc, CIFEraseTable))
return 0;
}
@ -4766,6 +4768,106 @@ cifBridgeLimFunc2(
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* cifNotSquareFunc --
*
* Process each tile and remove those which are square and not
* connected to any other tile of the same type. This operator aids
* in the detection of bar contacts to distinguish them from regular
* (square) contact cuts. Because of the special nature of the
* operator, only the negative-sense operator "not-square" is
* implemented, as the positive-sense operator is not especially
* useful (and can be implemented if needed with "not-square" and
* "and-not").
*
* Results:
* None.
*
* Side effects:
* Modifies the CIF planes.
*
* ----------------------------------------------------------------------------
*/
int
cifNotSquareFunc(
Tile *tile,
TileType dinfo,
ClientData clientData) /* (unused) */
{
Tile *tp;
TileType ttype;
Rect area;
int width, height;
bool isolated = TRUE;
if (IsSplit(tile)) return 0; /* Non-Manhattan tiles are never square */
ttype = TiGetType(tile);
if (ttype == TT_SPACE) return 0; /* Don't handle space tiles */
/* Search all four sides of the tile. Tiles are only considered square
* for the purposes of this operator if they are also unconnected to any
* other tile.
*/
/* Top */
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp))
if (TiGetBottomType(tp) == ttype)
{
isolated = FALSE;
break;
}
/* Left */
if (isolated)
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
if (TiGetBottomType(tp) == ttype)
{
isolated = FALSE;
break;
}
/* Bottom */
if (isolated)
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
if (TiGetBottomType(tp) == ttype)
{
isolated = FALSE;
break;
}
/* Right */
if (isolated)
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp))
if (TiGetBottomType(tp) == ttype)
{
isolated = FALSE;
break;
}
TiToRect(tile, &area);
if (isolated)
{
width = area.r_xtop - area.r_xbot;
height = area.r_ytop - area.r_ybot;
if (width == height) return 0; /* Square and isolated */
}
area.r_xbot *= cifScale;
area.r_ybot *= cifScale;
area.r_xtop *= cifScale;
area.r_ytop *= cifScale;
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *)NULL);
CIFTileOps += 1;
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -4779,6 +4881,7 @@ cifBridgeLimFunc2(
* None.
*
* Side effects:
* Modifies the CIF planes.
*
* ----------------------------------------------------------------------------
*/
@ -5396,7 +5499,6 @@ CIFGenLayer(
nextPlane = temp;
break;
case CIFOP_MAXRECT:
cifPlane = curPlane;
@ -5419,6 +5521,19 @@ CIFGenLayer(
nextPlane = temp;
break;
case CIFOP_NOTSQUARE:
DBClearPaintPlane(nextPlane);
cifPlane = nextPlane;
cifScale = 1;
DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect,
&CIFSolidBits, cifNotSquareFunc,
(ClientData)NULL);
temp = curPlane;
curPlane = nextPlane;
nextPlane = temp;
break;
case CIFOP_NET:
if (hier)
{
@ -5533,6 +5648,7 @@ CIFGenLayer(
snprintf(propname, 512, "MASKHINTS_%s", layername);
if (cellDef == (CellDef *)NULL) break;
proprec = DBPropGet(cellDef, propname, &found);
if (!found) break; /* No mask hints available */

View File

@ -145,6 +145,7 @@ typedef struct cifop
* CIFOP_BRIDGE - Added 6/11/20---Bridge across catecorner gaps
* CIFOP_BRIDGELIM - Added 27/07/20---Bridge across catecorner gaps, but with limiting layers
* CIFOP_MASKHINTS - Added 12/14/20---Add geometry from cell properties, if any.
* CIFOP_NOTSQUARE - Added 2/26/26---Keep only geometry which is not square.
*/
#define CIFOP_AND 1
@ -172,6 +173,7 @@ typedef struct cifop
#define CIFOP_BRIDGE 23
#define CIFOP_BRIDGELIM 24
#define CIFOP_MASKHINTS 25
#define CIFOP_NOTSQUARE 26
/* Definitions of bit fields used in the value of co_client for CIFOP_INTERACT */
#define CIFOP_INT_NOT 0x1 /* Inverted sense (not interacting) */

View File

@ -688,6 +688,8 @@ CIFPaintCurrent(
}
else if (op == NULL)
{
LinkedRect *lrec = NULL, *lsrch;
/* Handle boundary layer */
op = cifCurReadStyle->crs_layers[i]->crl_ops;
@ -702,6 +704,115 @@ CIFPaintCurrent(
(ClientData)NULL) == 1))
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
&CIFSolidBits, cifMakeBoundaryFunc, INT2CD(filetype));
/* Handle mask-hints input operator */
op = cifCurReadStyle->crs_layers[i]->crl_ops;
while (op)
{
if (op->co_opcode == CIFOP_MASKHINTS) break;
op = op->co_next;
}
if (op && (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
&DBAllButSpaceBits, cifCheckPaintFunc,
(ClientData)NULL) == 1))
{
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
&CIFSolidBits, cifMaskHintFunc,
(ClientData)&lrec);
if (lrec != NULL)
{
PropertyRecord *proprec, *proporig;
char *propname, *layername;
int proplen, i, savescale;
bool origfound = FALSE;
layername = (char *)op->co_client;
propname = (char *)mallocMagic(11 + strlen(layername));
sprintf(propname, "MASKHINTS_%s", layername);
/* Turn all linked Rects into a mask-hints property in the
* target cell.
*/
proplen = 0;
for (lsrch = lrec; lsrch; lsrch = lsrch->r_next)
proplen += 4;
/* If there is already a mask hint for this layer, then
* prepend to its data.
*/
proporig = DBPropGet(cifReadCellDef, layername, &origfound);
if (origfound) proplen += proporig->prop_len;
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) *
(proplen - 2) * sizeof(int));
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
proprec->prop_len = proplen;
proplen = 0;
while (lrec != NULL)
{
lrec->r_r.r_xtop =
CIFScaleCoord(lrec->r_r.r_xtop, COORD_EXACT);
savescale = cifCurReadStyle->crs_scaleFactor;
lrec->r_r.r_ytop =
CIFScaleCoord(lrec->r_r.r_ytop, COORD_EXACT);
if (savescale != cifCurReadStyle->crs_scaleFactor)
{
lrec->r_r.r_xtop *=
(savescale / cifCurReadStyle->crs_scaleFactor);
savescale = cifCurReadStyle->crs_scaleFactor;
}
lrec->r_r.r_xbot =
CIFScaleCoord(lrec->r_r.r_xbot, COORD_EXACT);
if (savescale != cifCurReadStyle->crs_scaleFactor)
{
lrec->r_r.r_xtop *=
(savescale / cifCurReadStyle->crs_scaleFactor);
lrec->r_r.r_ytop *=
(savescale / cifCurReadStyle->crs_scaleFactor);
savescale = cifCurReadStyle->crs_scaleFactor;
}
lrec->r_r.r_ybot =
CIFScaleCoord(lrec->r_r.r_ybot, COORD_EXACT);
if (savescale != cifCurReadStyle->crs_scaleFactor)
{
lrec->r_r.r_xtop *=
(savescale / cifCurReadStyle->crs_scaleFactor);
lrec->r_r.r_ytop *=
(savescale / cifCurReadStyle->crs_scaleFactor);
lrec->r_r.r_xbot *=
(savescale / cifCurReadStyle->crs_scaleFactor);
}
proprec->prop_value.prop_integer[proplen] =
lrec->r_r.r_xbot;
proprec->prop_value.prop_integer[proplen + 1] =
lrec->r_r.r_ybot;
proprec->prop_value.prop_integer[proplen + 2] =
lrec->r_r.r_xtop;
proprec->prop_value.prop_integer[proplen + 3] =
lrec->r_r.r_ytop;
free_magic1_t mm1 = freeMagic1_init();
freeMagic1(&mm1, lrec);
lrec = lrec->r_next;
freeMagic1_end(&mm1);
proplen += 4;
}
if (origfound)
for (i = 0; i < proporig->prop_len; i++)
proprec->prop_value.prop_integer[proplen++] =
proporig->prop_value.prop_integer[i];
DBPropPut(cifReadCellDef, propname, proprec);
freeMagic(propname);
}
}
}
/* Swap planes */
@ -791,8 +902,6 @@ CIFPaintCurrent(
for (i = 0; i < cifNReadLayers; i++)
{
LinkedRect *lrec = NULL, *lsrch;
char *propstr = NULL;
char locstr[512];
Plane *tempp;
if (!TTMaskHasType(CalmaMaskHints, i)) continue;

View File

@ -324,14 +324,18 @@ cifNewReadStyle(void)
{
/* Destroy old style and free all memory allocated to it */
for (i=0; i<MAXCIFRLAYERS; i+=1)
for (i = 0; i < MAXCIFRLAYERS; i++)
{
layer = cifCurReadStyle->crs_layers[i];
if (layer != NULL)
{
free_magic1_t mm1 = freeMagic1_init();
for (op = layer->crl_ops; op != NULL; op = op->co_next)
{
if (op->co_opcode == CIFOP_MASKHINTS)
freeMagic((char *)op->co_client);
freeMagic1(&mm1, (char *)op);
}
freeMagic1_end(&mm1);
freeMagic((char *)layer);
}
@ -990,6 +994,10 @@ CIFReadTechLine(
newOp->co_opcode = CIFOP_COPYUP;
else if (strcmp(argv[0], "boundary") == 0)
newOp->co_opcode = CIFOP_BOUNDARY;
else if (strcmp(argv[0], "not-square") == 0)
newOp->co_opcode = CIFOP_NOTSQUARE;
else if (strcmp(argv[0], "mask-hints") == 0)
newOp->co_opcode = CIFOP_MASKHINTS;
else
{
TechError("Unknown statement \"%s\".\n", argv[0]);
@ -1016,6 +1024,10 @@ CIFReadTechLine(
goto errorReturn;
}
break;
case CIFOP_MASKHINTS:
if (argc != 2) goto wrongNumArgs;
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
break;
}
/* Link the new CIFOp onto the list. */
@ -1099,6 +1111,7 @@ CIFReadTechFinal(void)
*
* ----------------------------------------------------------------------------
*/
void
CIFReadLoadStyle(
char *stylename)

View File

@ -1117,6 +1117,8 @@ CIFTechLine(
newOp->co_opcode = CIFOP_CLOSE;
else if (strcmp(argv[0], "orthogonal") == 0)
newOp->co_opcode = CIFOP_MANHATTAN;
else if (strcmp(argv[0], "not-square") == 0)
newOp->co_opcode = CIFOP_NOTSQUARE;
else if (strcmp(argv[0], "bridge") == 0)
newOp->co_opcode = CIFOP_BRIDGE;
else if (strcmp(argv[0], "bridge-lim") == 0)