First cut at a method to automatically generate mask hint properties

in a cell to account for the difference between what's in an input
GDS file and what magic would write out itself from the processed
data.  This potentially allows library cells to be read in that
will generate the equivalent mask data as output without resorting
to using GDS file references as properties.  The method is activated
with the new command option "gds maskhints on" and the default is
off.
This commit is contained in:
Tim Edwards
2022-01-20 21:50:13 -05:00
parent 6deb7d4f01
commit c2755a061f
6 changed files with 227 additions and 13 deletions
+1
View File
@@ -310,6 +310,7 @@ cifFlatMaskHints(name, value, mhd)
if (lastval) freeMagic(lastval);
/* Parse through the four values and check if there's more */
while (*vptr && isspace(*vptr)) vptr++;
while (*vptr && !isspace(*vptr)) vptr++;
while (*vptr && isspace(*vptr)) vptr++;
while (*vptr && !isspace(*vptr)) vptr++;
+187
View File
@@ -540,6 +540,40 @@ cifCopyPaintFunc(tile, cifCopyRec)
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* cifMaskHintFunc --
*
* For each tile in the scanned plane, convert the tile into a coordinate
* string by appending the coordinates to the list passed as clientData.
*
* Results:
* Return 0 to keep the search going.
*
* Side effects:
* Allocates memory for and seeds a linked rect entry
*
* ----------------------------------------------------------------------------
*/
int
cifMaskHintFunc(tile, lrecp)
Tile *tile;
LinkedRect **lrecp;
{
Rect r;
LinkedRect *newlr;
newlr = (LinkedRect *)mallocMagic(sizeof(LinkedRect));
newlr->r_next = *lrecp;
(*lrecp) = newlr;
TiToRect(tile, &newlr->r_r);
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@@ -683,6 +717,159 @@ CIFPaintCurrent(filetype)
TiFreePlane(plane);
}
/* If mask hints were requested, then for each GDS/CIF layer in the */
/* input, if the layer has a corresponding output layer and the */
/* output layer has a mask hints operator, then generate the output */
/* plane for that layer, compare to the input plane, and create */
/* mask hint properties to make the output the same as the input. */
if (CalmaMaskHints)
{
int j;
CIFOp *op, newop, subop;
Plane *presult;
TileTypeBitMask genMask;
int *in_out_map;
extern char *(cifReadLayers[MAXCIFRLAYERS]);
TTMaskZero(&genMask);
in_out_map = (int *)mallocMagic(cifNReadLayers * sizeof(int));
for (i = 0; i < cifNReadLayers; i++)
{
/* Does the input layer have a corresponding output layer? */
in_out_map[i] = -1;
for (j = 0; j < CIFCurStyle->cs_nLayers; j++)
{
if (!strcmp(CIFCurStyle->cs_layers[j]->cl_name, cifReadLayers[i]))
{
/* Does the layer have a mask-hints operator? */
for (op = CIFCurStyle->cs_layers[j]->cl_ops; op; op = op->co_next)
if (op->co_opcode == CIFOP_MASKHINTS)
{
TTMaskSetType(&genMask, j);
in_out_map[i] = j;
break;
}
}
if (in_out_map[i] >= 0) break;
}
}
/* Multiply input planes to the same scale as the generated output */
CIFScalePlanes(CIFCurStyle->cs_scaleFactor, 1, cifCurReadPlanes);
/* Generate the output for these layers from the cell contents */
CIFClearPlanes(CIFPlanes);
/* TO-DO: Replace DBAllTypeBits with genMask. Requires that genMask */
/* be expanded to include all dependent layers. */
CIFGen(cifReadCellDef, cifReadCellDef, &TiPlaneRect, CIFPlanes, &DBAllTypeBits,
TRUE, FALSE, FALSE, (ClientData)NULL);
/* Set up double operator for OR and ANDNOT functions */
newop.co_opcode = CIFOP_OR;
newop.co_distance = 0;
newop.co_next = &subop;
newop.co_client = (ClientData)NULL;
TTMaskZero(&newop.co_paintMask);
subop.co_opcode = CIFOP_ANDNOT;
subop.co_distance = 0;
subop.co_next = NULL;
subop.co_client = (ClientData)NULL;
TTMaskZero(&subop.co_paintMask);
for (i = 0; i < cifNReadLayers; i++)
{
LinkedRect *lrec = NULL;
char *propstr = NULL;
char locstr[512];
Plane *tempp;
j = in_out_map[i];
if (j < 0) continue;
TTMaskSetOnlyType(&subop.co_cifMask, j);
/* Replace last layer + 1 on CIFPlanes with input layer i */
tempp = CIFPlanes[CIFCurStyle->cs_nLayers];
TTMaskSetOnlyType(&newop.co_cifMask, CIFCurStyle->cs_nLayers);
CIFPlanes[CIFCurStyle->cs_nLayers] = cifCurReadPlanes[i];
CIFCurStyle->cs_nLayers++;
/* Compute result (i AND-NOT j), which will be all the areas of
* the input on layer i that are not generated by writing output
* layer j.
*/
presult = CIFGenLayer(&newop, &TiPlaneRect, (CellDef *)NULL,
(CellDef *)NULL, CIFPlanes, FALSE, (ClientData)NULL);
/* Scan the resulting plane and generate linked Rect structures for
* each shape found.
*/
DBSrPaintArea((Tile *)NULL, presult, &TiPlaneRect, &CIFSolidBits,
cifMaskHintFunc, (ClientData)&lrec);
if (lrec != NULL)
{
char *propname;
propname = (char *)mallocMagic(11 + strlen(cifReadLayers[i]));
sprintf(propname, "MASKHINTS_%s", cifReadLayers[i]);
propstr = (char *)NULL;
/* Turn all linked Rects into a mask-hints property in the
* target cell.
*/
while (lrec != NULL)
{
char *newstr;
sprintf(locstr, "%d %d %d %d",
lrec->r_r.r_xbot / CIFCurStyle->cs_scaleFactor,
lrec->r_r.r_ybot / CIFCurStyle->cs_scaleFactor,
lrec->r_r.r_xtop / CIFCurStyle->cs_scaleFactor,
lrec->r_r.r_ytop / CIFCurStyle->cs_scaleFactor);
if (propstr == NULL)
{
newstr = (char *)mallocMagic(strlen(locstr) + 1);
sprintf(newstr, "%s", locstr);
}
else
{
newstr = (char *)mallocMagic(strlen(locstr)
+ strlen(propstr) + 2);
sprintf(newstr, "%s %s", propstr, locstr);
freeMagic(propstr);
}
propstr = newstr;
freeMagic(lrec);
lrec = lrec->r_next;
}
/* NOTE: propstr is transferred to the CellDef and should
* not be free'd here.
*/
DBPropPut(cifReadCellDef, propname, propstr);
freeMagic(propname);
}
/* Delete the generated plane */
DBFreePaintPlane(presult);
TiFreePlane(presult);
/* Replace the input plane that was shuffled out */
CIFCurStyle->cs_nLayers--;
CIFPlanes[CIFCurStyle->cs_nLayers] = tempp;
}
/* Free up the planes used to create the output */
CIFClearPlanes(CIFPlanes);
freeMagic((char *)in_out_map);
}
/* Now go through all the current planes and zero them out. */
for (i = 0; i < MAXCIFRLAYERS; i++)