diff --git a/VERSION b/VERSION index 807bada7..aa16d4ea 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.258 +8.3.259 diff --git a/calma/CalmaRdcl.c b/calma/CalmaRdcl.c index 7a45a437..cf81d1b1 100644 --- a/calma/CalmaRdcl.c +++ b/calma/CalmaRdcl.c @@ -50,6 +50,7 @@ int calmaNonManhattan; int CalmaFlattenLimit = 10; int NameConvertErrors = 0; bool CalmaRewound = FALSE; +bool CalmaMaskHints = FALSE; extern HashTable calmaDefInitHash; diff --git a/calma/calma.h b/calma/calma.h index de0314f1..0d4aa223 100644 --- a/calma/calma.h +++ b/calma/calma.h @@ -34,6 +34,7 @@ extern bool CalmaAddendum; extern bool CalmaNoDuplicates; extern bool CalmaNoDateStamp; extern bool CalmaUnique; +extern bool CalmaMaskHints; extern bool CalmaMergeTiles; extern bool CalmaFlattenArrays; extern bool CalmaNoDRCCheck; diff --git a/cif/CIFhier.c b/cif/CIFhier.c index ed8538f8..e51d5894 100644 --- a/cif/CIFhier.c +++ b/cif/CIFhier.c @@ -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++; diff --git a/cif/CIFrdcl.c b/cif/CIFrdcl.c index 5a69f0ab..2986e1b7 100644 --- a/cif/CIFrdcl.c +++ b/cif/CIFrdcl.c @@ -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++) diff --git a/commands/CmdCD.c b/commands/CmdCD.c index f9936f49..f937f2a2 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -99,18 +99,19 @@ bool cmdDumpParseArgs(); #define CALMA_LABELS 8 #define CALMA_LIBRARY 9 #define CALMA_LOWER 10 -#define CALMA_MERGE 11 -#define CALMA_NO_STAMP 12 -#define CALMA_NO_DUP 13 -#define CALMA_READ 14 -#define CALMA_READONLY 15 -#define CALMA_RESCALE 16 -#define CALMA_WARNING 17 -#define CALMA_WRITE 18 -#define CALMA_POLYS 19 -#define CALMA_PATHS 20 -#define CALMA_UNDEFINED 21 -#define CALMA_UNIQUE 22 +#define CALMA_MASKHINTS 11 +#define CALMA_MERGE 12 +#define CALMA_NO_STAMP 13 +#define CALMA_NO_DUP 14 +#define CALMA_READ 15 +#define CALMA_READONLY 16 +#define CALMA_RESCALE 17 +#define CALMA_WARNING 18 +#define CALMA_WRITE 19 +#define CALMA_POLYS 20 +#define CALMA_PATHS 21 +#define CALMA_UNDEFINED 22 +#define CALMA_UNIQUE 23 #define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */ @@ -145,6 +146,7 @@ CmdCalma(w, cmd) "labels [yes|no] cause labels to be output when writing GDS-II", "library [yes|no] do not output the top level, only subcells", "lower [yes|no] allow both upper and lower case in labels", + "maskhints [yes|no] generate mask hint properties on input", "merge [yes|no] merge tiles into polygons in the output", "nodatestamp [yes|no] write a zero value creation date stamp", "noduplicates [yes|no] do not read cells that exist before reading GDS", @@ -537,6 +539,28 @@ CmdCalma(w, cmd) CalmaDoLower = (option < 4) ? FALSE : TRUE; return; + case CALMA_MASKHINTS: + if (cmd->tx_argc == 2) + { +#ifdef MAGIC_WRAPPER + Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaMaskHints)); +#else + if (CalmaMaskHints) + TxPrintf("Mask hints generated from GDS input.\n"); + else + TxPrintf("No mask hints generated from GDS input.\n"); +#endif + return; + } + else if (cmd->tx_argc != 3) + goto wrongNumArgs; + + option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo); + if (option < 0) + goto wrongNumArgs; + CalmaMaskHints = (option < 4) ? FALSE : TRUE; + return; + case CALMA_MERGE: if (cmd->tx_argc == 2) {