Enhancements to cifinput and cifoutput in the tech file: Added

option "labels ... cellid" to handle some vendor files where
apparently to get around the 30-character cell name limit, the
actual cellname is encoded on a text layer.  Added new cifop
"boundary" (no arguments) for cases where a cell abutment box
is encoded on a GDS layer;  this now translates the bounding
box to the FIXED_BBOX property, as is done with the LEF bounding
box.  Also corrected the property set function to free existing
property value allocated memory when overwriting a property with
a new value.
This commit is contained in:
Tim Edwards 2019-06-05 15:03:51 -04:00
parent 8f7db3942c
commit bbf6008363
11 changed files with 117 additions and 25 deletions

View File

@ -57,8 +57,6 @@ extern HashTable calmaDefInitHash;
extern void calmaLayerError(); extern void calmaLayerError();
bool calmaReadPath(); bool calmaReadPath();
typedef enum { LABEL_TYPE_NONE, LABEL_TYPE_TEXT, LABEL_TYPE_PORT } labelType;
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -274,7 +272,6 @@ calmaElementBoundary()
} }
} }
CIFPropRecordPath(cifReadCellDef, pathheadp, FALSE);
rp = CIFPolyToRects(pathheadp, plane, CIFPaintTable, (PaintUndoInfo *)NULL); rp = CIFPolyToRects(pathheadp, plane, CIFPaintTable, (PaintUndoInfo *)NULL);
CIFFreePath(pathheadp); CIFFreePath(pathheadp);
@ -300,7 +297,7 @@ calmaElementBoundary()
rpc.r_ytop /= calmaReadScale1; rpc.r_ytop /= calmaReadScale1;
if ((ciftype >= 0) && if ((ciftype >= 0) &&
((cifCurReadStyle->crs_labelSticky[ciftype] != LABEL_TYPE_NONE))) (cifCurReadStyle->crs_labelSticky[ciftype] != LABEL_TYPE_NONE))
{ {
Label *lab; Label *lab;
TileType type; TileType type;
@ -652,7 +649,7 @@ calmaElementPath()
} }
} }
CIFPropRecordPath(cifReadCellDef, pathheadp, TRUE); CIFPropRecordPath(cifReadCellDef, pathheadp, TRUE, "path");
CIFPaintWirePath(pathheadp, width, CIFPaintWirePath(pathheadp, width,
(pathtype == CALMAPATH_SQUAREFLUSH || pathtype == CALMAPATH_CUSTOM) ? (pathtype == CALMAPATH_SQUAREFLUSH || pathtype == CALMAPATH_CUSTOM) ?
FALSE : TRUE, plane, CIFPaintTable, (PaintUndoInfo *)NULL); FALSE : TRUE, plane, CIFPaintTable, (PaintUndoInfo *)NULL);
@ -715,7 +712,7 @@ calmaElementText()
cifnum = CIFCalmaLayerToCifLayer(layer, textt, cifCurReadStyle); cifnum = CIFCalmaLayerToCifLayer(layer, textt, cifCurReadStyle);
if (cifnum < 0) if (cifnum < 0)
{ {
if(cifCurReadStyle->crs_flags & CRF_IGNORE_UNKNOWNLAYER_LABELS) if (cifCurReadStyle->crs_flags & CRF_IGNORE_UNKNOWNLAYER_LABELS)
type = -1; type = -1;
else { else {
calmaLayerError("Label on unknown layer/datatype", layer, textt); calmaLayerError("Label on unknown layer/datatype", layer, textt);
@ -889,6 +886,12 @@ calmaElementText()
r.r_ll.p_x * cifCurReadStyle->crs_scaleFactor, r.r_ll.p_x * cifCurReadStyle->crs_scaleFactor,
r.r_ll.p_y * cifCurReadStyle->crs_scaleFactor); r.r_ll.p_y * cifCurReadStyle->crs_scaleFactor);
} }
else if (cifCurReadStyle->crs_labelSticky[cifnum] == LABEL_TYPE_CELLID)
{
/* Special handling of label layers marked "cellid" in the techfile. */
/* The actual cellname is the ID string, not the GDS structure name. */
DBCellRenameDef(cifReadCellDef, textbody);
}
else if (type < 0) else if (type < 0)
{ {
calmaReadError("Warning: label \"%s\" at (%d, %d) is on unhandled" calmaReadError("Warning: label \"%s\" at (%d, %d) is on unhandled"

View File

@ -130,6 +130,9 @@ typedef struct
/* Length of record header */ /* Length of record header */
#define CALMAHEADERLENGTH 4 #define CALMAHEADERLENGTH 4
/* Label types */
typedef enum { LABEL_TYPE_NONE, LABEL_TYPE_TEXT, LABEL_TYPE_PORT, LABEL_TYPE_CELLID } labelType;
/* ------------------------- Input macros ----------------------------- */ /* ------------------------- Input macros ----------------------------- */
/* Globals for Calma reading */ /* Globals for Calma reading */

View File

@ -3036,6 +3036,29 @@ CIFGenLayer(op, area, cellDef, temps, clientdata)
} }
break; break;
case CIFOP_BOUNDARY:
cifPlane = curPlane;
/* This function for cifoutput only. cifinput handled separately. */
if (cellDef && (cellDef->cd_flags & CDFIXEDBBOX))
{
char *propvalue;
bool found;
propvalue = (char *)DBPropGet(cellDef, "FIXED_BBOX", &found);
if (!found) break;
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
&bbox.r_xtop, &bbox.r_ytop) != 4) break;
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
bbox.r_xbot *= cifScale;
bbox.r_xtop *= cifScale;
bbox.r_ybot *= cifScale;
bbox.r_ytop *= cifScale;
DBNMPaintPlane(cifPlane, CIF_SOLIDTYPE, &bbox,
CIFPaintTable, (PaintUndoInfo *)NULL);
}
break;
case CIFOP_BBOX: case CIFOP_BBOX:
if (CIFErrorDef == NULL) break; if (CIFErrorDef == NULL) break;
@ -3149,6 +3172,7 @@ CIFGen(cellDef, area, planes, layers, replace, genAllPlanes, clientdata)
CIFErrorLayer = i; CIFErrorLayer = i;
new[i] = CIFGenLayer(CIFCurStyle->cs_layers[i]->cl_ops, new[i] = CIFGenLayer(CIFCurStyle->cs_layers[i]->cl_ops,
&expanded, cellDef, new, clientdata); &expanded, cellDef, new, clientdata);
/* Clean up the non-manhattan geometry in the plane */ /* Clean up the non-manhattan geometry in the plane */
if (CIFUnfracture) DBMergeNMTiles(new[i], &expanded, if (CIFUnfracture) DBMergeNMTiles(new[i], &expanded,
(PaintUndoInfo *)NULL); (PaintUndoInfo *)NULL);

View File

@ -121,6 +121,8 @@ typedef struct cifop
* the cell bounding box. This involves no magic type * the cell bounding box. This involves no magic type
* layers but may itself be acted upon with grow/shrink * layers but may itself be acted upon with grow/shrink
* rules. * rules.
* CIFOP_BOUNDARY - Added 6/5/19---map the FIXED_BBOX property bounding
* box coordinates into CIF layer geometry.
* CIFOP_NET - Added 11/3/08---pull an entire electrical net into * CIFOP_NET - Added 11/3/08---pull an entire electrical net into
* the CIF layer, selectively picking layers. * the CIF layer, selectively picking layers.
* CIFOP_MAXRECT - Reduce all areas to the largest internal fitting * CIFOP_MAXRECT - Reduce all areas to the largest internal fitting
@ -144,9 +146,10 @@ typedef struct cifop
#define CIFOP_ANDNOT 12 #define CIFOP_ANDNOT 12
#define CIFOP_SQUARES_G 13 #define CIFOP_SQUARES_G 13
#define CIFOP_BBOX 14 #define CIFOP_BBOX 14
#define CIFOP_NET 15 #define CIFOP_BOUNDARY 15
#define CIFOP_MAXRECT 16 #define CIFOP_NET 16
#define CIFOP_COPYUP 17 #define CIFOP_MAXRECT 17
#define CIFOP_COPYUP 18
/* Added by Tim 10/21/2004 */ /* Added by Tim 10/21/2004 */
/* The following structure is used to pass information on how to draw /* The following structure is used to pass information on how to draw

View File

@ -559,13 +559,15 @@ cifCopyPaintFunc(tile, cifCopyRec)
int int
CIFPaintCurrent() CIFPaintCurrent()
{ {
extern int cifMakeBoundaryFunc(); /* Forward declaration. */
extern int cifPaintCurrentFunc(); /* Forward declaration. */
Plane *plane, *swapplane; Plane *plane, *swapplane;
int i; int i;
for (i = 0; i < cifCurReadStyle->crs_nLayers; i++) for (i = 0; i < cifCurReadStyle->crs_nLayers; i++)
{ {
TileType type; TileType type;
extern int cifPaintCurrentFunc(); /* Forward declaration. */
CIFOp *op; CIFOp *op;
plane = CIFGenLayer(cifCurReadStyle->crs_layers[i]->crl_ops, plane = CIFGenLayer(cifCurReadStyle->crs_layers[i]->crl_ops,
@ -641,6 +643,23 @@ CIFPaintCurrent()
} }
} }
} }
else if (op == NULL)
{
/* Handle boundary layer */
op = cifCurReadStyle->crs_layers[i]->crl_ops;
while (op)
{
if (op->co_opcode == CIFOP_BOUNDARY) break;
op = op->co_next;
}
if (op && (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
&DBAllButSpaceBits, cifCheckPaintFunc,
(ClientData)NULL) == 1))
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
&CIFSolidBits, cifMakeBoundaryFunc, (ClientData)NULL);
}
/* Swap planes */ /* Swap planes */
swapplane = cifCurReadPlanes[type]; swapplane = cifCurReadPlanes[type];
@ -652,8 +671,8 @@ CIFPaintCurrent()
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect, DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
&CIFSolidBits, cifPaintCurrentFunc, &CIFSolidBits, cifPaintCurrentFunc,
(ClientData)type); (ClientData)type);
} }
/* Recycle the plane, which was dynamically allocated. */ /* Recycle the plane, which was dynamically allocated. */
DBFreePaintPlane(plane); DBFreePaintPlane(plane);
@ -668,9 +687,34 @@ CIFPaintCurrent()
return 0; return 0;
} }
/* Below is the search function invoked for each CIF tile type /* Use CIF layer geometry to define a fixed bounding box for the current cell */
* found for the current layer.
*/ int
cifMakeBoundaryFunc(tile, clientdata)
Tile *tile; /* Tile of CIF information. */
ClientData clientdata; /* Not used */
{
/* It is assumed that there is one rectangle for the boundary. */
/* If there are multiple rectangles defined with the boundary */
/* layer, then the last one defines the FIXED_BBOX property. */
Rect area;
char propertyvalue[128], *storedvalue;
TiToRect(tile, &area);
if (cifReadCellDef->cd_flags & CDFIXEDBBOX)
CIFReadError("Warning: Cell %s boundary was redefined.\n",
cifReadCellDef->cd_name);
sprintf(propertyvalue, "%d %d %d %d",
area.r_xbot, area.r_ybot, area.r_xtop, area.r_ytop);
storedvalue = StrDup((char **)NULL, propertyvalue);
DBPropPut(cifReadCellDef, "FIXED_BBOX", storedvalue);
cifReadCellDef->cd_flags |= CDFIXEDBBOX;
}
/* Paint CIF layer geometry into the current cell def as magic layer "type" */
int int
cifPaintCurrentFunc(tile, type) cifPaintCurrentFunc(tile, type)

View File

@ -234,9 +234,10 @@ CIFParseFlash()
*/ */
void void
CIFPropRecordPath(def, pathheadp, iswire) CIFPropRecordPath(def, pathheadp, iswire, propname)
CellDef *def; CellDef *def;
CIFPath *pathheadp; CIFPath *pathheadp;
char *propname;
{ {
extern float CIFGetOutputScale(); extern float CIFGetOutputScale();
CIFPath *pathp; CIFPath *pathp;
@ -273,7 +274,7 @@ CIFPropRecordPath(def, pathheadp, iswire)
/* Reallocate pathstr to be no larger than needed to hold the path contents */ /* Reallocate pathstr to be no larger than needed to hold the path contents */
StrDup(&pathstr, pathstr); StrDup(&pathstr, pathstr);
DBPropPut(def, "path", (ClientData)pathstr); DBPropPut(def, propname, (ClientData)pathstr);
} }
/* /*

View File

@ -62,9 +62,6 @@ CIFOp *cifCurReadOp; /* Last geometric operation seen. */
void cifReadStyleInit(); void cifReadStyleInit();
void CIFReadLoadStyle(); void CIFReadLoadStyle();
/* Label types used by the "labels" statement option */
typedef enum { LABEL_TYPE_NONE, LABEL_TYPE_TEXT, LABEL_TYPE_PORT } labelType;
/* /*
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* *
@ -858,6 +855,8 @@ CIFReadTechLine(sectionName, argc, argv)
calmaLabelType = LABEL_TYPE_TEXT; calmaLabelType = LABEL_TYPE_TEXT;
else if (!strcmp(argv[2], "port")) else if (!strcmp(argv[2], "port"))
calmaLabelType = LABEL_TYPE_PORT; calmaLabelType = LABEL_TYPE_PORT;
else if (!strncmp(argv[2], "cell", 4))
calmaLabelType = LABEL_TYPE_CELLID;
else else
goto wrongNumArgs; goto wrongNumArgs;
} }
@ -952,6 +951,8 @@ CIFReadTechLine(sectionName, argc, argv)
newOp->co_opcode = CIFOP_SHRINK; newOp->co_opcode = CIFOP_SHRINK;
else if (strcmp(argv[0], "copyup") == 0) else if (strcmp(argv[0], "copyup") == 0)
newOp->co_opcode = CIFOP_COPYUP; newOp->co_opcode = CIFOP_COPYUP;
else if (strcmp(argv[0], "boundary") == 0)
newOp->co_opcode = CIFOP_BOUNDARY;
else else
{ {
TechError("Unknown statement \"%s\".\n", argv[0]); TechError("Unknown statement \"%s\".\n", argv[0]);
@ -967,7 +968,6 @@ CIFReadTechLine(sectionName, argc, argv)
if (argc != 2) goto wrongNumArgs; if (argc != 2) goto wrongNumArgs;
CIFParseReadLayers(argv[1], &newOp->co_cifMask); CIFParseReadLayers(argv[1], &newOp->co_cifMask);
break; break;
case CIFOP_GROW: case CIFOP_GROW:
case CIFOP_GROW_G: case CIFOP_GROW_G:
case CIFOP_SHRINK: case CIFOP_SHRINK:

View File

@ -54,8 +54,8 @@ typedef struct
* the "crl_magicType" should be interpreted as a CIF layer. * the "crl_magicType" should be interpreted as a CIF layer.
*/ */
#define CIFR_SIMPLE 1 #define CIFR_SIMPLE 1
#define CIFR_TEMPLAYER 2 #define CIFR_TEMPLAYER 2
/* The following structure defines a complete CIF read-in style. /* The following structure defines a complete CIF read-in style.
* The constant MAXCIFRLAYERS must be less than TT_MAXTYPES, and * The constant MAXCIFRLAYERS must be less than TT_MAXTYPES, and

View File

@ -104,6 +104,7 @@ cifTechFreeStyle()
case CIFOP_OR: case CIFOP_OR:
case CIFOP_BBOX: case CIFOP_BBOX:
case CIFOP_MAXRECT: case CIFOP_MAXRECT:
case CIFOP_BOUNDARY:
/* These options use co_client to hold a single */ /* These options use co_client to hold a single */
/* integer value, so it is not allocated. */ /* integer value, so it is not allocated. */
break; break;
@ -802,8 +803,7 @@ CIFTechLine(sectionName, argc, argv)
if (CIFCurStyle->cs_status != TECH_PENDING) return TRUE; if (CIFCurStyle->cs_status != TECH_PENDING) return TRUE;
newLayer = NULL; newLayer = NULL;
if ((strcmp(argv[0], "templayer") == 0) if ((strcmp(argv[0], "templayer") == 0) || (strcmp(argv[0], "layer") == 0))
|| (strcmp(argv[0], "layer") == 0))
{ {
if (CIFCurStyle->cs_nLayers == MAXCIFLAYERS) if (CIFCurStyle->cs_nLayers == MAXCIFLAYERS)
{ {
@ -1047,6 +1047,8 @@ CIFTechLine(sectionName, argc, argv)
newOp->co_opcode = CIFOP_NET; newOp->co_opcode = CIFOP_NET;
else if (strcmp(argv[0], "maxrect") == 0) else if (strcmp(argv[0], "maxrect") == 0)
newOp->co_opcode = CIFOP_MAXRECT; newOp->co_opcode = CIFOP_MAXRECT;
else if (strcmp(argv[0], "boundary") == 0)
newOp->co_opcode = CIFOP_BOUNDARY;
else else
{ {
TechError("Unknown statement \"%s\".\n", argv[0]); TechError("Unknown statement \"%s\".\n", argv[0]);
@ -1196,6 +1198,12 @@ bloatCheck:
goto wrongNumArgs; goto wrongNumArgs;
break; break;
case CIFOP_BOUNDARY:
/* CIFOP_BOUNDARY has no arguments */
if (argc != 1)
goto wrongNumArgs;
break;
case CIFOP_SQUARES_G: case CIFOP_SQUARES_G:
case CIFOP_SQUARES: case CIFOP_SQUARES:
@ -1752,6 +1760,7 @@ CIFTechFinal()
{ {
case CIFOP_OR: case CIFOP_OR:
case CIFOP_BBOX: case CIFOP_BBOX:
case CIFOP_BOUNDARY:
case CIFOP_MAXRECT: case CIFOP_MAXRECT:
case CIFOP_NET: case CIFOP_NET:
break; break;
@ -2232,6 +2241,7 @@ CIFTechOutputScale(n, d)
{ {
case CIFOP_OR: case CIFOP_OR:
case CIFOP_BBOX: case CIFOP_BBOX:
case CIFOP_BOUNDARY:
case CIFOP_MAXRECT: case CIFOP_MAXRECT:
case CIFOP_NET: case CIFOP_NET:
break; break;

View File

@ -55,6 +55,7 @@ DBPropPut(cellDef, name, value)
{ {
HashTable *htab; HashTable *htab;
HashEntry *entry; HashEntry *entry;
char *oldvalue;
/* Honor the NOEDIT flag */ /* Honor the NOEDIT flag */
if (cellDef->cd_flags & CDNOEDIT) return; if (cellDef->cd_flags & CDNOEDIT) return;
@ -67,6 +68,8 @@ DBPropPut(cellDef, name, value)
htab = (HashTable *) cellDef->cd_props; htab = (HashTable *) cellDef->cd_props;
entry = HashFind(htab, name); entry = HashFind(htab, name);
oldvalue = (char *)HashGetValue(entry);
if (oldvalue != NULL) freeMagic(oldvalue);
HashSetValue(entry, value); HashSetValue(entry, value);
} }

View File

@ -108,6 +108,7 @@ WireTechLine(sectionName, argc, argv)
return TRUE; return TRUE;
} }
WireUnits = atoi(argv[1]); WireUnits = atoi(argv[1]);
return TRUE;
} }
if (strcmp(argv[0], "contact") != 0) if (strcmp(argv[0], "contact") != 0)