mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-08-22 14:17:43 +02:00
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:
@@ -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
@@ -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++)
|
||||
|
||||
Reference in New Issue
Block a user