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:
parent
5f64c2b3d7
commit
fdee96ede1
13
cif/CIFint.h
13
cif/CIFint.h
|
|
@ -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 */
|
||||||
|
|
|
||||||
241
cif/CIFrdcl.c
241
cif/CIFrdcl.c
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue