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.
This commit is contained in:
Tim Edwards 2020-12-21 15:54:41 -05:00
parent 5f64c2b3d7
commit fdee96ede1
3 changed files with 245 additions and 69 deletions

View File

@ -78,6 +78,13 @@ typedef struct slots_data
int sl_start; int sl_start;
} SlotsData; } 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 typedef struct cifop
{ {
TileTypeBitMask co_paintMask;/* Zero or more paint layers to consider. */ 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). */ int co_distance; /* Grow or shrink distance (if needed). */
ClientData co_client; /* Pointer to a BloatData, SquaresData, ClientData co_client; /* Pointer to a BloatData, SquaresData,
* SlotsData, or BridgeData structure, * SlotsData, BridgeData, ComposeData
* or NULL. * structure, or NULL.
*/ */
struct cifop *co_next; /* Next in list of operations to perform. */ struct cifop *co_next; /* Next in list of operations to perform. */
} CIFOp; } CIFOp;
@ -143,6 +150,7 @@ typedef struct cifop
* CIFOP_BRIDGE - Added 6/11/20---Bridge across catecorner gaps * 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_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_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 #define CIFOP_AND 1
@ -168,6 +176,7 @@ typedef struct cifop
#define CIFOP_BRIDGE 21 #define CIFOP_BRIDGE 21
#define CIFOP_BRIDGELIM 22 #define CIFOP_BRIDGELIM 22
#define CIFOP_MASKHINTS 23 #define CIFOP_MASKHINTS 23
#define CIFOP_COMPOSE 24
/* Added by Tim 10/21/2004 */ /* Added by Tim 10/21/2004 */

View File

@ -490,6 +490,72 @@ CIFParseStart()
return TRUE; 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) if (cifCurReadStyle->crs_layers[i]->crl_flags & CIFR_TEMPLAYER)
{ {
op = cifCurReadStyle->crs_layers[i]->crl_ops; int haspaint = 0;
while (op)
{
if (op->co_opcode == CIFOP_COPYUP) break;
op = op->co_next;
}
/* Quick check to see if anything was generated */ /* Quick check to see if anything was generated on this layer. */
/* on this layer. */ /* Do this only once, and only if there is an opcode that */
/* requires it. */
if (op && (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, for (op = cifCurReadStyle->crs_layers[i]->crl_ops; op; op = op->co_next)
&DBAllButSpaceBits, cifCheckPaintFunc, if ((op->co_opcode == CIFOP_COPYUP) ||
(ClientData)NULL) == 1)) (op->co_opcode == CIFOP_BOUNDARY) ||
{ (op->co_opcode == CIFOP_COMPOSE))
/* 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
{ {
parray = (Plane **)mallocMagic(MAXCIFRLAYERS * sizeof(Plane *)); haspaint = DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
cifReadCellDef->cd_flags |= CDFLATGDS; &DBAllButSpaceBits, cifCheckPaintFunc,
cifReadCellDef->cd_flags &= ~CDFLATTENED; (ClientData)NULL);
cifReadCellDef->cd_client = (ClientData)parray; break;
for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++)
parray[pNum] = NULL;
} }
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]; for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++)
if (newplane == NULL) {
{ if (TTMaskHasType(&op->co_cifMask, pNum))
newplane = DBNewPlane((ClientData) TT_SPACE); {
DBClearPaintPlane(newplane); 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->co_opcode == CIFOP_BOUNDARY) && (haspaint == 1))
else if (op == NULL)
{
/* Handle boundary layer */
op = cifCurReadStyle->crs_layers[i]->crl_ops;
while (op)
{ {
if (op->co_opcode == CIFOP_BOUNDARY) break; /* Handle boundary function */
op = op->co_next;
}
if (op && (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
&DBAllButSpaceBits, cifCheckPaintFunc,
(ClientData)NULL) == 1))
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect, 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 */ /* Swap planes */

View File

@ -323,7 +323,20 @@ cifNewReadStyle()
if (layer != NULL) if (layer != NULL)
{ {
for (op = layer->crl_ops; op != NULL; op = op->co_next) 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 *)op);
}
freeMagic((char *)layer); freeMagic((char *)layer);
} }
} }
@ -463,8 +476,9 @@ CIFReadTechLine(sectionName, argc, argv)
CIFReadKeep *newStyle, *p; CIFReadKeep *newStyle, *p;
HashEntry *he; HashEntry *he;
CalmaLayerType clt; CalmaLayerType clt;
ComposeData *comps;
int calmaLayers[CALMA_LAYER_MAX], calmaTypes[CALMA_LAYER_MAX]; 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; int calmaLabelType = LABEL_TYPE_NONE;
if (argc <= 0) return TRUE; if (argc <= 0) return TRUE;
@ -955,6 +969,8 @@ CIFReadTechLine(sectionName, argc, argv)
newOp->co_opcode = CIFOP_COPYUP; newOp->co_opcode = CIFOP_COPYUP;
else if (strcmp(argv[0], "boundary") == 0) else if (strcmp(argv[0], "boundary") == 0)
newOp->co_opcode = CIFOP_BOUNDARY; newOp->co_opcode = CIFOP_BOUNDARY;
else if (strcmp(argv[0], "compose") == 0)
newOp->co_opcode = CIFOP_COMPOSE;
else else
{ {
TechError("Unknown statement \"%s\".\n", argv[0]); TechError("Unknown statement \"%s\".\n", argv[0]);
@ -981,8 +997,50 @@ CIFReadTechLine(sectionName, argc, argv)
goto errorReturn; goto errorReturn;
} }
break; 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. */ /* Link the new CIFOp onto the list. */
if (cifCurReadOp == NULL) if (cifCurReadOp == NULL)