From fdee96ede1c9430deb97b1c764d47597287bf276 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 21 Dec 2020 15:54:41 -0500 Subject: [PATCH] Started work on a new cifinput operator "compose" that will allow handling derived types with parts split across hierarchy, in a top-down manner that complements the "copyup" operator's bottom- up method. --- cif/CIFint.h | 13 ++- cif/CIFrdcl.c | 241 +++++++++++++++++++++++++++++++++++------------- cif/CIFrdtech.c | 60 +++++++++++- 3 files changed, 245 insertions(+), 69 deletions(-) diff --git a/cif/CIFint.h b/cif/CIFint.h index 88a87bf4..f370cf35 100644 --- a/cif/CIFint.h +++ b/cif/CIFint.h @@ -78,6 +78,13 @@ typedef struct slots_data int sl_start; } SlotsData; +typedef struct compose_data +{ + int cm_numPairs; /* Number of compose pairs */ + TileType *cm_haveType; /* List of types to search for */ + TileType *cm_putType; /* List of types to replace with */ +} ComposeData; + typedef struct cifop { TileTypeBitMask co_paintMask;/* Zero or more paint layers to consider. */ @@ -87,8 +94,8 @@ typedef struct cifop */ int co_distance; /* Grow or shrink distance (if needed). */ ClientData co_client; /* Pointer to a BloatData, SquaresData, - * SlotsData, or BridgeData structure, - * or NULL. + * SlotsData, BridgeData, ComposeData + * structure, or NULL. */ struct cifop *co_next; /* Next in list of operations to perform. */ } CIFOp; @@ -143,6 +150,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_COMPOSE - Added 12/20/20---Composition rules (inverse of "copyup") */ #define CIFOP_AND 1 @@ -168,6 +176,7 @@ typedef struct cifop #define CIFOP_BRIDGE 21 #define CIFOP_BRIDGELIM 22 #define CIFOP_MASKHINTS 23 +#define CIFOP_COMPOSE 24 /* Added by Tim 10/21/2004 */ diff --git a/cif/CIFrdcl.c b/cif/CIFrdcl.c index 02b07f65..1106a68b 100644 --- a/cif/CIFrdcl.c +++ b/cif/CIFrdcl.c @@ -490,6 +490,72 @@ CIFParseStart() return TRUE; } +/* Structures used by cifCheckComposeFunc to pass information about subcells */ + +typedef struct _uselist { + CellUse *cccul_use; + struct _uselist *cccul_next; +} CifCheckComposeUseList; + +typedef struct _cifcheckcomposedata { + ComposeData *cccd_data; + TileTypeBitMask cccd_mask; + Rect cccd_area; + CifCheckComposeUseList cccd_uses; +} CifCheckComposeData; + +/* + * ---------------------------------------------------------------------------- + * + * ---------------------------------------------------------------------------- + */ + +int drcCheckOverlapPaint(use, cccd) + CellUse *use; + CifCheckComposeData *cccd; +{ + int pNum; + + for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++) + XXX WIP XXX +} + +/* + * ---------------------------------------------------------------------------- + * cifCheckComposeFunc --- + * + * Callback function for CIFOP_COMPOSE. It checks children of the + * current edit cell in the area of the tile (transformed to the + * coordinate system of the child of the edit cell) for types in the + * cm_haveType list in the ComposeData pointer (passed in clientData). + * If any are found, then there is an unresolved overlap error. The + * child cell is replaced with a copy, and material in the cm_haveType + * list is replaced with the corresponding material in the cm_putType + * list. + * ---------------------------------------------------------------------------- + */ + +int cifCheckComposeFunc(tile, clientData) + Tile *tile; + ClientData clientData; +{ + CifCheckComposeData *cccd = (CifCheckComposeData *)clientData; + + TiToRect(tile, &cccd->cccd_area); + + cccd->cccd_area.r_xtop = CIFScaleCoord(cccd->cccd_area.r_xtop, COORD_ANY); + cccd->cccd_area.r_xbot = CIFScaleCoord(cccd->cccd_area.r_xbot, COORD_ANY); + cccd->cccd_area.r_ytop = CIFScaleCoord(cccd->cccd_area.r_ytop, COORD_ANY); + cccd->cccd_area.r_ybot = CIFScaleCoord(cccd->cccd_area.r_ybot, COORD_ANY); + + DBSrCellPlaneArea(cifReadCellDef->cd_cellPlane, &rect, + drcCheckOverlapPaint, (ClientData)cccd); + + + XXX WIP XXX + + return 0; +} /* * ---------------------------------------------------------------------------- @@ -582,85 +648,128 @@ CIFPaintCurrent(filetype) if (cifCurReadStyle->crs_layers[i]->crl_flags & CIFR_TEMPLAYER) { - op = cifCurReadStyle->crs_layers[i]->crl_ops; - while (op) - { - if (op->co_opcode == CIFOP_COPYUP) break; - op = op->co_next; - } + int haspaint = 0; - /* Quick check to see if anything was generated */ - /* on this layer. */ + /* Quick check to see if anything was generated on this layer. */ + /* Do this only once, and only if there is an opcode that */ + /* requires it. */ - if (op && (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, - &DBAllButSpaceBits, cifCheckPaintFunc, - (ClientData)NULL) == 1)) - { - /* Copy-up function */ - - int pNum; - Plane *newplane; - Plane **parray; - extern char *(cifReadLayers[MAXCIFRLAYERS]); - - /* NOTE: The condition cd_client == 0 when CDFLATGDS - * indicates that the cell was already in memory when the - * GDS was read. This condition should be properly caught - * and handled. - */ - if ((cifReadCellDef->cd_flags & CDFLATGDS) && - (cifReadCellDef->cd_client != (ClientData)0)) - parray = (Plane **)cifReadCellDef->cd_client; - else + for (op = cifCurReadStyle->crs_layers[i]->crl_ops; op; op = op->co_next) + if ((op->co_opcode == CIFOP_COPYUP) || + (op->co_opcode == CIFOP_BOUNDARY) || + (op->co_opcode == CIFOP_COMPOSE)) { - parray = (Plane **)mallocMagic(MAXCIFRLAYERS * sizeof(Plane *)); - cifReadCellDef->cd_flags |= CDFLATGDS; - cifReadCellDef->cd_flags &= ~CDFLATTENED; - cifReadCellDef->cd_client = (ClientData)parray; - for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) - parray[pNum] = NULL; + haspaint = DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, + &DBAllButSpaceBits, cifCheckPaintFunc, + (ClientData)NULL); + break; } - for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) + for (op = cifCurReadStyle->crs_layers[i]->crl_ops; op; op = op->co_next) + { + if ((op->co_opcode == CIFOP_COPYUP) && (haspaint == 1)) { - if (TTMaskHasType(&op->co_cifMask, pNum)) + /* Handle copy-up function */ + + int pNum; + Plane *newplane; + Plane **parray; + extern char *(cifReadLayers[MAXCIFRLAYERS]); + + /* NOTE: The condition cd_client == 0 when CDFLATGDS + * indicates that the cell was already in memory when the + * GDS was read. This condition should be properly caught + * and handled. + */ + if ((cifReadCellDef->cd_flags & CDFLATGDS) && + (cifReadCellDef->cd_client != (ClientData)0)) + parray = (Plane **)cifReadCellDef->cd_client; + else { - CIFCopyRec cifCopyRec; + parray = (Plane **)mallocMagic(MAXCIFRLAYERS * sizeof(Plane *)); + cifReadCellDef->cd_flags |= CDFLATGDS; + cifReadCellDef->cd_flags &= ~CDFLATTENED; + cifReadCellDef->cd_client = (ClientData)parray; + for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) + parray[pNum] = NULL; + } - newplane = parray[pNum]; - if (newplane == NULL) - { - newplane = DBNewPlane((ClientData) TT_SPACE); - DBClearPaintPlane(newplane); + for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) + { + if (TTMaskHasType(&op->co_cifMask, pNum)) + { + CIFCopyRec cifCopyRec; + + newplane = parray[pNum]; + if (newplane == NULL) + { + newplane = DBNewPlane((ClientData) TT_SPACE); + DBClearPaintPlane(newplane); + } + + cifCopyRec.plane = newplane; + cifCopyRec.trans = NULL; + + DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, + &DBAllButSpaceBits, cifCopyPaintFunc, + &cifCopyRec); + + parray[pNum] = newplane; } - - cifCopyRec.plane = newplane; - cifCopyRec.trans = NULL; - - DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, - &DBAllButSpaceBits, cifCopyPaintFunc, - &cifCopyRec); - - parray[pNum] = newplane; } } - } - else if (op == NULL) - { - /* Handle boundary layer */ - - op = cifCurReadStyle->crs_layers[i]->crl_ops; - while (op) + else if ((op->co_opcode == CIFOP_BOUNDARY) && (haspaint == 1)) { - if (op->co_opcode == CIFOP_BOUNDARY) break; - op = op->co_next; - } - - if (op && (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, - &DBAllButSpaceBits, cifCheckPaintFunc, - (ClientData)NULL) == 1)) + /* Handle boundary function */ DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect, - &CIFSolidBits, cifMakeBoundaryFunc, (ClientData)filetype); + &CIFSolidBits, cifMakeBoundaryFunc, (ClientData)filetype); + } + else if ((op->co_opcode == CIFOP_COMPOSE) && (haspaint == 1)) + { + CifCheckComposeData cccd; + TileType type; + + /* Handle compose function. Search the area under any part */ + /* of the templayer for any types in cm_haveType that */ + /* appear in any subcell of the edit cell. If there are */ + /* any, then make a copy of the subcell and do a type */ + /* replacement of types in cm_haveType with the */ + /* corresponding type in cm_putType. Then replace the */ + /* subcell with the new subcell. */ + + /* The purpose of this function is to resolve derived types */ + /* that are composed of material in two differernt cells. */ + /* It is the inverse of "copyup". In "copyup", a layer in */ + /* a subcell that is part of a derived type is copied up to */ + /* the parent to resolve the derived type. In "compose", a */ + /* layer in the parent cell that is part of a derived type */ + /* is copied into the child cell to resolve the derived */ + /* type. There are distinct situations where each is */ + /* needed, depending on what layer determines the derived */ + /* type. For example, THKOX determines if a transistor is */ + /* low voltage or high voltage. THKOX in a subcell that */ + /* modifies a transistor in the parent cell requires */ + /* "copyup", while THKOX in the parent cell that modifies */ + /* a transistor in a child cell requires "compose". */ + + /* Due to the complexity of duplicating hierarchy, this */ + /* function only looks at cells that are children of the */ + /* edit cell, and does not look further down in the */ + /* hierarchy. This routine could be expanded to handle */ + /* such deep nesting. */ + + cccd.cccd_data = (ComposeData *)op->co_client; + cccd.cccd_area = TiPlaneRect; + + /* Compute type mask for type composing */ + TTMaskZero(&cccd.cccd_mask); + for (i = 0; i < cccd.cccd_data->cm_numPairs; i++) + TTMaskSetType(&cccd.cccd_mask, cccd.cccd_data->cm_haveType[i]); + + DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect, + &CIFSolidBits, cifCheckComposeFunc, + (ClientData)&cccd); + } } /* Swap planes */ diff --git a/cif/CIFrdtech.c b/cif/CIFrdtech.c index d6404d24..0e578cb5 100644 --- a/cif/CIFrdtech.c +++ b/cif/CIFrdtech.c @@ -323,7 +323,20 @@ cifNewReadStyle() if (layer != NULL) { for (op = layer->crl_ops; op != NULL; op = op->co_next) + { + /* CIFOP_COMPOSE is the only cifinput record to */ + /* allocate data in the co_client record. */ + if (op->co_opcode == CIFOP_COMPOSE) + { + ComposeData *comps; + + comps = (ComposeData *)op->co_client; + freeMagic(comps->cm_haveType); + freeMagic(comps->cm_putType); + freeMagic(comps); + } freeMagic((char *)op); + } freeMagic((char *)layer); } } @@ -463,8 +476,9 @@ CIFReadTechLine(sectionName, argc, argv) CIFReadKeep *newStyle, *p; HashEntry *he; CalmaLayerType clt; + ComposeData *comps; int calmaLayers[CALMA_LAYER_MAX], calmaTypes[CALMA_LAYER_MAX]; - int nCalmaLayers, nCalmaTypes, l, t, j; + int nCalmaLayers, nCalmaTypes, l, t, j, i, nTypes; int calmaLabelType = LABEL_TYPE_NONE; if (argc <= 0) return TRUE; @@ -955,6 +969,8 @@ CIFReadTechLine(sectionName, argc, argv) newOp->co_opcode = CIFOP_COPYUP; else if (strcmp(argv[0], "boundary") == 0) newOp->co_opcode = CIFOP_BOUNDARY; + else if (strcmp(argv[0], "compose") == 0) + newOp->co_opcode = CIFOP_COMPOSE; else { TechError("Unknown statement \"%s\".\n", argv[0]); @@ -981,8 +997,50 @@ CIFReadTechLine(sectionName, argc, argv) goto errorReturn; } break; + case CIFOP_COMPOSE: + if ((argc < 2) || ((argc & 1) != 0)) goto wrongNumArgs; + + /* If there were previous compose statements, then merge them */ + if (cifCurReadOp && (cifCurReadOp->co_opcode == CIFOP_COMPOSE)) + { + freeMagic(newOp); + newOp = cifCurReadOp; + + // Create space for new type pairs and copy the existing + // compose records into it. + comps = (ComposeData *)newOp->co_client; + nTypes = comps->cm_numPairs; + comps->cm_numPairs = nTypes + argc >> 1; + newtypes = (TileType *)mallocMagic(comps->cm_numPairs * sizeof(TileType)); + for (i = 0; i < nTypes; i++) newtypes[i] = comps->cm_haveType[i]; + freeMagic(comps->cm_haveType); + comps->cm_haveType = newtypes; + newtypes = (TileType *)mallocMagic(comps->cm_numPairs * sizeof(TileType)); + for (i = 0; i < nTypes; i++) newtypes[i] = comps->cm_putType[i]; + freeMagic(comps->cm_putType); + comps->cm_putType = newtypes; + } + else + { + comps = (ComposeData *)mallocMagic(sizeof(ComposeData)); + nTypes = argc >> 1; + newOp->co_client = (clientData)comps; + comps->cm_haveType = (TileType *)mallocMagic(nTypes * sizeof(TileType)); + comps->cm_putType = (TileType *)mallocMagic(nTypes * sizeof(TileType)); + i = 0; + } + + for (j = 0; j < argc; j += 2) + { + CIFParseReadLayers(argv[j], &comps->cm_haveType[i + j]); + CIFParseReadLayers(argv[j + 1], &comps->cm_putType[i + j + 1]); + } + break; } + /* If there was a merged "compose" record, then we're done. */ + if (cifCurReadOp == newOp) return TRUE; + /* Link the new CIFOp onto the list. */ if (cifCurReadOp == NULL)