Compare commits
86 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
66faf1d907 | |
|
|
37db9e453b | |
|
|
2d5c4be6dd | |
|
|
a9673e45ae | |
|
|
8f95efc257 | |
|
|
fd12c39c37 | |
|
|
7d9167257a | |
|
|
058b320c3f | |
|
|
fee4b887c0 | |
|
|
04e91d640d | |
|
|
7d9210a3f1 | |
|
|
03bbc544b2 | |
|
|
ee79bba5e4 | |
|
|
15943d0cb1 | |
|
|
7bdd9e1d4f | |
|
|
725c8e9235 | |
|
|
73ffad3802 | |
|
|
037daf1121 | |
|
|
d0ef32de0f | |
|
|
0d9b862c0e | |
|
|
71dc472797 | |
|
|
2929ef583e | |
|
|
ecd6ec56ae | |
|
|
f3478cba7b | |
|
|
ba5154698d | |
|
|
1023461ca5 | |
|
|
197763e46e | |
|
|
cb7855235a | |
|
|
8f684ad5be | |
|
|
f3404f67b7 | |
|
|
cedd64adcb | |
|
|
afca58f162 | |
|
|
95baea1c22 | |
|
|
751757a02c | |
|
|
c32bae1a24 | |
|
|
0c913eca59 | |
|
|
2f00f6d8f1 | |
|
|
9ab7b77dc4 | |
|
|
00c0208f18 | |
|
|
cb30ac369b | |
|
|
7e9b6fb61e | |
|
|
3b1de8ff40 | |
|
|
10a6c8635f | |
|
|
e2292f5d70 | |
|
|
736c507fe8 | |
|
|
c20a267a2b | |
|
|
bad0b67ce8 | |
|
|
727649b308 | |
|
|
4dde62b206 | |
|
|
94edc2a23d | |
|
|
b248f186ec | |
|
|
1656866f41 | |
|
|
99297e33ec | |
|
|
727833fcd3 | |
|
|
feb5d61294 | |
|
|
4b120eb417 | |
|
|
55eadcfb90 | |
|
|
b4f62abb40 | |
|
|
deefe0e3a3 | |
|
|
57c33c48c7 | |
|
|
76f97c90e5 | |
|
|
297a05c4ed | |
|
|
b768fcc3f9 | |
|
|
4943da5ce4 | |
|
|
512400e39f | |
|
|
0cbed6078a | |
|
|
9760ef6d1d | |
|
|
bd13febb72 | |
|
|
81436b75ed | |
|
|
8822f8dce2 | |
|
|
f03003b79f | |
|
|
802c31d16a | |
|
|
308224109f | |
|
|
4d9c7fd7d7 | |
|
|
a55ec49434 | |
|
|
c0dbb2067b | |
|
|
b59708e27a | |
|
|
c0c5e1b5bf | |
|
|
3de9ed9cbf | |
|
|
846c8e0f65 | |
|
|
8bd01f5597 | |
|
|
1cb58e973a | |
|
|
516c9d7635 | |
|
|
d24d52e403 | |
|
|
a93d248a5a | |
|
|
4ccd5a78d1 |
|
|
@ -53,6 +53,7 @@ int calmaNonManhattan;
|
||||||
int CalmaFlattenLimit = 10;
|
int CalmaFlattenLimit = 10;
|
||||||
int NameConvertErrors = 0;
|
int NameConvertErrors = 0;
|
||||||
bool CalmaRewound = FALSE;
|
bool CalmaRewound = FALSE;
|
||||||
|
bool CalmaRecordPaths = FALSE;
|
||||||
TileTypeBitMask *CalmaMaskHints = NULL;
|
TileTypeBitMask *CalmaMaskHints = NULL;
|
||||||
|
|
||||||
extern HashTable calmaDefInitHash;
|
extern HashTable calmaDefInitHash;
|
||||||
|
|
@ -245,7 +246,9 @@ calmaExact(void)
|
||||||
int pNum;
|
int pNum;
|
||||||
Plane *newplane;
|
Plane *newplane;
|
||||||
Plane **parray;
|
Plane **parray;
|
||||||
int gdsCopyPaintFunc(Tile *tile, GDSCopyRec *gdsCopyRec); /* Forward reference */
|
|
||||||
|
/* Forward reference */
|
||||||
|
int gdsCopyPaintFunc(Tile *tile, TileType dinfo, GDSCopyRec *gdsCopyRec);
|
||||||
|
|
||||||
parray = (Plane **)mallocMagic(MAXCIFRLAYERS * sizeof(Plane *));
|
parray = (Plane **)mallocMagic(MAXCIFRLAYERS * sizeof(Plane *));
|
||||||
|
|
||||||
|
|
@ -503,28 +506,33 @@ calmaParseStructure(
|
||||||
|
|
||||||
if (CalmaReadOnly || predefined)
|
if (CalmaReadOnly || predefined)
|
||||||
{
|
{
|
||||||
|
PropertyRecord *proprec;
|
||||||
char cstring[1024];
|
char cstring[1024];
|
||||||
|
|
||||||
/* Writing the file position into a string is slow, but */
|
|
||||||
/* it prevents requiring special handling when printing */
|
|
||||||
/* out the properties. */
|
|
||||||
|
|
||||||
char *fpcopy = (char *)mallocMagic(20);
|
|
||||||
char *fncopy;
|
|
||||||
|
|
||||||
/* Substitute variable for PDK path or ~ for home directory */
|
/* Substitute variable for PDK path or ~ for home directory */
|
||||||
/* the same way that cell references are handled in .mag files. */
|
/* the same way that cell references are handled in .mag files. */
|
||||||
DBPathSubstitute(filename, cstring, cifReadCellDef);
|
DBPathSubstitute(filename, cstring, cifReadCellDef);
|
||||||
fncopy = StrDup(NULL, cstring);
|
|
||||||
sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos);
|
|
||||||
DBPropPut(cifReadCellDef, "GDS_START", (ClientData)fpcopy);
|
|
||||||
|
|
||||||
fpcopy = (char *)mallocMagic(20);
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||||
|
proprec->prop_type = PROPERTY_TYPE_DOUBLE;
|
||||||
|
proprec->prop_len = 1;
|
||||||
|
proprec->prop_value.prop_double[0] = filepos;
|
||||||
|
DBPropPut(cifReadCellDef, "GDS_START", (ClientData)proprec);
|
||||||
|
|
||||||
filepos = FTELL(calmaInputFile);
|
filepos = FTELL(calmaInputFile);
|
||||||
sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos);
|
|
||||||
DBPropPut(cifReadCellDef, "GDS_END", (ClientData)fpcopy);
|
|
||||||
|
|
||||||
DBPropPut(cifReadCellDef, "GDS_FILE", (ClientData)fncopy);
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||||
|
proprec->prop_type = PROPERTY_TYPE_DOUBLE;
|
||||||
|
proprec->prop_len = 1;
|
||||||
|
proprec->prop_value.prop_double[0] = filepos;
|
||||||
|
DBPropPut(cifReadCellDef, "GDS_END", (ClientData)proprec);
|
||||||
|
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) - 7 +
|
||||||
|
strlen(cstring));
|
||||||
|
proprec->prop_type = PROPERTY_TYPE_STRING;
|
||||||
|
proprec->prop_len = 1;
|
||||||
|
strcpy(proprec->prop_value.prop_string, cstring);
|
||||||
|
DBPropPut(cifReadCellDef, "GDS_FILE", (ClientData)proprec);
|
||||||
|
|
||||||
if (predefined)
|
if (predefined)
|
||||||
{
|
{
|
||||||
|
|
@ -751,6 +759,7 @@ calmaParseElement(
|
||||||
int
|
int
|
||||||
calmaEnumFunc(
|
calmaEnumFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
int *plane)
|
int *plane)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -780,8 +789,8 @@ calmaElementSref(
|
||||||
char *filename)
|
char *filename)
|
||||||
{
|
{
|
||||||
int nbytes, rtype, cols, rows, nref, n, i, savescale;
|
int nbytes, rtype, cols, rows, nref, n, i, savescale;
|
||||||
int xlo, ylo, xhi, yhi, xsep, ysep;
|
int xlo, ylo, xhi, yhi, xsep, ysep, angle;
|
||||||
bool madeinst = FALSE;
|
bool madeinst = FALSE, rotated = FALSE;
|
||||||
char *sname = NULL;
|
char *sname = NULL;
|
||||||
bool isArray = FALSE;
|
bool isArray = FALSE;
|
||||||
bool dolookahead = FALSE;
|
bool dolookahead = FALSE;
|
||||||
|
|
@ -789,12 +798,13 @@ calmaElementSref(
|
||||||
Point refarray[3], refunscaled[3], p;
|
Point refarray[3], refunscaled[3], p;
|
||||||
CellUse *use;
|
CellUse *use;
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
int gdsCopyPaintFunc(Tile *tile, GDSCopyRec *gdsCopyRec); /* Forward reference */
|
|
||||||
int gdsHasUses(CellUse *use, ClientData clientdata); /* Forward reference */
|
|
||||||
/* Added by NP */
|
|
||||||
char *useid = NULL, *arraystr = NULL;
|
char *useid = NULL, *arraystr = NULL;
|
||||||
int propAttrType;
|
int propAttrType;
|
||||||
|
|
||||||
|
/* Forward reference */
|
||||||
|
int gdsCopyPaintFunc(Tile *tile, TileType dinfo, GDSCopyRec *gdsCopyRec);
|
||||||
|
int gdsHasUses(CellUse *use, ClientData clientdata);
|
||||||
|
|
||||||
/* Skip CALMA_ELFLAGS, CALMA_PLEX */
|
/* Skip CALMA_ELFLAGS, CALMA_PLEX */
|
||||||
calmaSkipSet(calmaElementIgnore);
|
calmaSkipSet(calmaElementIgnore);
|
||||||
|
|
||||||
|
|
@ -980,17 +990,73 @@ calmaElementSref(
|
||||||
refarray[2].p_x = refarray[2].p_y = 0;
|
refarray[2].p_x = refarray[2].p_y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the array is given an angle, then the meaning of rows and
|
||||||
|
* columns needs to be swapped for the purpose of ignoring
|
||||||
|
* X or Y values in the case of a 1-row or 1-column entry.
|
||||||
|
*/
|
||||||
|
angle = GeoTransAngle(&trans, 0);
|
||||||
|
if ((angle == 90) || (angle == 270) || (angle == -90) || (angle == -270))
|
||||||
|
rotated = TRUE;
|
||||||
|
|
||||||
/* If this is a cell reference, then we scale to magic coordinates
|
/* If this is a cell reference, then we scale to magic coordinates
|
||||||
* and place the cell in the magic database. However, if this is
|
* and place the cell in the magic database. However, if this is
|
||||||
* a cell to be flattened a la "gds flatten", then we keep the GDS
|
* a cell to be flattened a la "gds flatten", then we keep the GDS
|
||||||
* coordinates, and don't scale to the magic database.
|
* coordinates, and don't scale to the magic database.
|
||||||
|
*
|
||||||
|
* NOTE: Scaling everything in the middle or reading array data
|
||||||
|
* and then retroactively adjusting the array data read earlier
|
||||||
|
* is problematic, and probably incorrect.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
for (n = 0; n < nref; n++)
|
||||||
|
{
|
||||||
|
savescale = calmaReadScale1;
|
||||||
|
|
||||||
|
/* If there is only one column, then X data in the 2nd or 3rd
|
||||||
|
* entry is irrelevant. If there is only one row, then Y data
|
||||||
|
* in the 2nd or 3rd entry is irrelevant. Prevent issues caused
|
||||||
|
* by incorrect/uninitialized data in these positions by ignoring
|
||||||
|
* them as needed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((n > 0) && ((!rotated && (rows == 1)) || (rotated && (cols == 1))))
|
||||||
|
{
|
||||||
|
calmaReadX(&refarray[n], 1);
|
||||||
|
calmaSkipBytes(4);
|
||||||
|
refarray[n].p_y = refarray[0].p_y;
|
||||||
|
}
|
||||||
|
else if ((n > 0) && ((!rotated && (cols == 1)) || (rotated && (rows == 1))))
|
||||||
|
{
|
||||||
|
calmaSkipBytes(4);
|
||||||
|
calmaReadY(&refarray[n], 1);
|
||||||
|
refarray[n].p_x = refarray[0].p_x;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
calmaReadPoint(&refarray[n], 1);
|
||||||
|
|
||||||
|
if (savescale != calmaReadScale1)
|
||||||
|
{
|
||||||
|
/* Scale changed, so update previous points read */
|
||||||
|
int newscale = calmaReadScale1 / savescale;
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
refarray[i].p_x *= newscale;
|
||||||
|
refarray[i].p_y *= newscale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FEOF(calmaInputFile))
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (n = 0; n < nref; n++)
|
||||||
|
refunscaled[n] = refarray[n]; // Save for CDFLATGDS cells
|
||||||
|
|
||||||
for (n = 0; n < nref; n++)
|
for (n = 0; n < nref; n++)
|
||||||
{
|
{
|
||||||
savescale = cifCurReadStyle->crs_scaleFactor;
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
||||||
calmaReadPoint(&refarray[n], 1);
|
|
||||||
refunscaled[n] = refarray[n]; // Save for CDFLATGDS cells
|
|
||||||
refarray[n].p_x = CIFScaleCoord(refarray[n].p_x, COORD_EXACT);
|
refarray[n].p_x = CIFScaleCoord(refarray[n].p_x, COORD_EXACT);
|
||||||
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
||||||
{
|
{
|
||||||
|
|
@ -1011,9 +1077,6 @@ calmaElementSref(
|
||||||
}
|
}
|
||||||
refarray[n].p_x *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
refarray[n].p_x *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FEOF(calmaInputFile))
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip remainder */
|
/* Skip remainder */
|
||||||
|
|
@ -1289,27 +1352,28 @@ gdsHasUses(
|
||||||
int
|
int
|
||||||
gdsCopyPaintFunc(
|
gdsCopyPaintFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
GDSCopyRec *gdsCopyRec)
|
GDSCopyRec *gdsCopyRec)
|
||||||
{
|
{
|
||||||
int pNum;
|
int pNum;
|
||||||
TileType dinfo;
|
TileType newdinfo;
|
||||||
Rect sourceRect, targetRect;
|
Rect sourceRect, targetRect;
|
||||||
Transform *trans = gdsCopyRec->trans;
|
Transform *trans = gdsCopyRec->trans;
|
||||||
Plane *plane = gdsCopyRec->plane;
|
Plane *plane = gdsCopyRec->plane;
|
||||||
|
|
||||||
dinfo = TiGetTypeExact(tile);
|
newdinfo = TiGetTypeExact(tile) | dinfo;
|
||||||
|
|
||||||
if (trans)
|
if (trans)
|
||||||
{
|
{
|
||||||
TiToRect(tile, &sourceRect);
|
TiToRect(tile, &sourceRect);
|
||||||
GeoTransRect(trans, &sourceRect, &targetRect);
|
GeoTransRect(trans, &sourceRect, &targetRect);
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
dinfo = DBTransformDiagonal(TiGetTypeExact(tile), trans);
|
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, trans);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
TiToRect(tile, &targetRect);
|
TiToRect(tile, &targetRect);
|
||||||
|
|
||||||
DBNMPaintPlane(plane, dinfo, &targetRect, CIFPaintTable,
|
DBNMPaintPlane(plane, newdinfo, &targetRect, CIFPaintTable,
|
||||||
(PaintUndoInfo *)NULL);
|
(PaintUndoInfo *)NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,8 @@ calmaInputRescale(
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
* calmaReadX ---
|
||||||
|
* calmaReadY ---
|
||||||
* calmaReadPoint ---
|
* calmaReadPoint ---
|
||||||
*
|
*
|
||||||
* Read a point from the input.
|
* Read a point from the input.
|
||||||
|
|
@ -132,11 +134,17 @@ calmaInputRescale(
|
||||||
* encountered, then everything in the GDS planes is rescaled
|
* encountered, then everything in the GDS planes is rescaled
|
||||||
* to match.
|
* to match.
|
||||||
*
|
*
|
||||||
|
* Notes:
|
||||||
|
* This routine has been split into individual X and Y reads so that
|
||||||
|
* array data can be read while ignoring offset information when there
|
||||||
|
* is only one row or column; otherwise, bad or uninitialized data
|
||||||
|
* in the record can cause unnecessary and incorrect scaling.
|
||||||
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
calmaReadPoint(
|
calmaReadX(
|
||||||
Point *p,
|
Point *p,
|
||||||
int iscale)
|
int iscale)
|
||||||
{
|
{
|
||||||
|
|
@ -163,6 +171,15 @@ calmaReadPoint(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p->p_x /= calmaReadScale2;
|
p->p_x /= calmaReadScale2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
calmaReadY(
|
||||||
|
Point *p,
|
||||||
|
int iscale)
|
||||||
|
{
|
||||||
|
int rescale;
|
||||||
|
|
||||||
READI4((p)->p_y);
|
READI4((p)->p_y);
|
||||||
p->p_y *= (calmaReadScale1 * iscale);
|
p->p_y *= (calmaReadScale1 * iscale);
|
||||||
|
|
@ -188,6 +205,15 @@ calmaReadPoint(
|
||||||
p->p_y /= calmaReadScale2;
|
p->p_y /= calmaReadScale2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
calmaReadPoint(
|
||||||
|
Point *p,
|
||||||
|
int iscale)
|
||||||
|
{
|
||||||
|
calmaReadX(p, iscale);
|
||||||
|
calmaReadY(p, iscale);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
|
|
@ -692,7 +718,12 @@ calmaElementPath(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If requested by command option, record the path centerline as a
|
||||||
|
* property of the cell def.
|
||||||
|
*/
|
||||||
|
if (CalmaRecordPaths)
|
||||||
CIFPropRecordPath(cifReadCellDef, pathheadp, TRUE, "path");
|
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);
|
||||||
|
|
|
||||||
|
|
@ -97,10 +97,10 @@ typedef struct {
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
extern int calmaWriteInitFunc(CellDef *def);
|
extern int calmaWriteInitFunc(CellDef *def);
|
||||||
extern int calmaWritePaintFunc(Tile *tile, calmaOutputStruct *cos);
|
extern int calmaWritePaintFunc(Tile *tile, TileType dinfo, calmaOutputStruct *cos);
|
||||||
extern int calmaMergePaintFunc(Tile *tile, calmaOutputStruct *cos);
|
extern int calmaMergePaintFunc(Tile *tile, TileType dinfo, calmaOutputStruct *cos);
|
||||||
extern int calmaWriteUseFunc(CellUse *use, FILE *f);
|
extern int calmaWriteUseFunc(CellUse *use, FILE *f);
|
||||||
extern int calmaPaintLabelFunc(Tile *tile, calmaOutputStruct *cos);
|
extern int calmaPaintLabelFunc(Tile *tile, TileType dinfo, calmaOutputStruct *cos);
|
||||||
extern void calmaWriteContacts(FILE *f);
|
extern void calmaWriteContacts(FILE *f);
|
||||||
extern void calmaDelContacts(void);
|
extern void calmaDelContacts(void);
|
||||||
extern void calmaOutFunc(CellDef *def, FILE *f, const Rect *cliprect);
|
extern void calmaOutFunc(CellDef *def, FILE *f, const Rect *cliprect);
|
||||||
|
|
@ -528,7 +528,7 @@ calmaDumpStructure(
|
||||||
|
|
||||||
/* Is view abstract? */
|
/* Is view abstract? */
|
||||||
DBPropGet(edef, "LEFview", &isAbstract);
|
DBPropGet(edef, "LEFview", &isAbstract);
|
||||||
chklibname = (char *)DBPropGet(edef, "GDS_FILE", &isReadOnly);
|
chklibname = DBPropGetString(edef, "GDS_FILE", &isReadOnly);
|
||||||
|
|
||||||
if (isAbstract && isReadOnly)
|
if (isAbstract && isReadOnly)
|
||||||
{
|
{
|
||||||
|
|
@ -738,7 +738,7 @@ calmaFullDump(
|
||||||
* names in the GDS file do not shadow any names in the database.
|
* names in the GDS file do not shadow any names in the database.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
viewopts = (char *)DBPropGet(def, "LEFview", &isAbstract);
|
viewopts = DBPropGetString(def, "LEFview", &isAbstract);
|
||||||
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
||||||
{
|
{
|
||||||
/* Generate a SHORT name for this cell (else it is easy to run into the
|
/* Generate a SHORT name for this cell (else it is easy to run into the
|
||||||
|
|
@ -918,7 +918,7 @@ calmaProcessDef(
|
||||||
DBPropGet(def, "GDS_END", &hasGDSEnd);
|
DBPropGet(def, "GDS_END", &hasGDSEnd);
|
||||||
DBPropGet(def, "CIFhier", &needHier);
|
DBPropGet(def, "CIFhier", &needHier);
|
||||||
|
|
||||||
filename = (char *)DBPropGet(def, "GDS_FILE", &isReadOnly);
|
filename = DBPropGetString(def, "GDS_FILE", &isReadOnly);
|
||||||
|
|
||||||
/* When used with "calma addendum true", don't output the read-only */
|
/* When used with "calma addendum true", don't output the read-only */
|
||||||
/* cells. This makes the library incomplete and dependent on the */
|
/* cells. This makes the library incomplete and dependent on the */
|
||||||
|
|
@ -1033,13 +1033,12 @@ calmaProcessDef(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
offptr = (char *)DBPropGet(def, "GDS_END", NULL);
|
cval = DBPropGetDouble(def, "GDS_END", NULL);
|
||||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
|
||||||
cellend = (off_t)cval;
|
cellend = (off_t)cval;
|
||||||
offptr = (char *)DBPropGet(def, "GDS_BEGIN", &oldStyle);
|
cval = DBPropGetDouble(def, "GDS_BEGIN", &oldStyle);
|
||||||
if (!oldStyle)
|
if (!oldStyle)
|
||||||
{
|
{
|
||||||
offptr = (char *)DBPropGet(def, "GDS_START", NULL);
|
cval = DBPropGetDouble(def, "GDS_START", NULL);
|
||||||
|
|
||||||
/* Write our own header and string name, to ensure */
|
/* Write our own header and string name, to ensure */
|
||||||
/* that the magic cell name and GDS name match. */
|
/* that the magic cell name and GDS name match. */
|
||||||
|
|
@ -1056,7 +1055,6 @@ calmaProcessDef(
|
||||||
calmaOutStructName(CALMA_STRNAME, def, outf);
|
calmaOutStructName(CALMA_STRNAME, def, outf);
|
||||||
}
|
}
|
||||||
|
|
||||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
|
||||||
cellstart = (off_t)cval;
|
cellstart = (off_t)cval;
|
||||||
|
|
||||||
/* GDS_START has been defined as the start of data after the cell */
|
/* GDS_START has been defined as the start of data after the cell */
|
||||||
|
|
@ -1263,7 +1261,7 @@ calmaOutFunc(
|
||||||
int dbunits;
|
int dbunits;
|
||||||
calmaOutputStruct cos;
|
calmaOutputStruct cos;
|
||||||
bool propfound;
|
bool propfound;
|
||||||
char *propvalue;
|
PropertyRecord *proprec;
|
||||||
|
|
||||||
cos.f = f;
|
cos.f = f;
|
||||||
cos.area = (cliprect == &TiPlaneRect) ? NULL : cliprect;
|
cos.area = (cliprect == &TiPlaneRect) ? NULL : cliprect;
|
||||||
|
|
@ -1323,15 +1321,21 @@ calmaOutFunc(
|
||||||
|
|
||||||
/* Include any fixed bounding box as part of the area to process, */
|
/* Include any fixed bounding box as part of the area to process, */
|
||||||
/* in case the fixed bounding box is larger than the geometry. */
|
/* in case the fixed bounding box is larger than the geometry. */
|
||||||
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
|
proprec = DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
Rect bbox;
|
Rect bbox;
|
||||||
|
|
||||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||||
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
(proprec->prop_len == 4))
|
||||||
|
{
|
||||||
|
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||||
|
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||||
|
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||||
|
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||||
GeoInclude(&bbox, &bigArea);
|
GeoInclude(&bbox, &bigArea);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CIFErrorDef = def;
|
CIFErrorDef = def;
|
||||||
CIFGen(def, def, &bigArea, CIFPlanes, &DBAllTypeBits, TRUE, TRUE, FALSE,
|
CIFGen(def, def, &bigArea, CIFPlanes, &DBAllTypeBits, TRUE, TRUE, FALSE,
|
||||||
|
|
@ -2464,6 +2468,7 @@ calmaProcessBoundary(
|
||||||
int
|
int
|
||||||
calmaMergePaintFunc(
|
calmaMergePaintFunc(
|
||||||
Tile *tile, /* Tile to be written out. */
|
Tile *tile, /* Tile to be written out. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
calmaOutputStruct *cos) /* Information needed by algorithm */
|
calmaOutputStruct *cos) /* Information needed by algorithm */
|
||||||
{
|
{
|
||||||
FILE *f = cos->f;
|
FILE *f = cos->f;
|
||||||
|
|
@ -2494,11 +2499,10 @@ calmaMergePaintFunc(
|
||||||
split_type = -1;
|
split_type = -1;
|
||||||
if (IsSplit(t))
|
if (IsSplit(t))
|
||||||
{
|
{
|
||||||
/* If we use SplitSide, then we need to set it when the */
|
/* If we use TT_SIDE, then we need to set it when the */
|
||||||
/* tile is pushed. Since these are one-or-zero mask layers */
|
/* tile is pushed. Since these are one-or-zero mask layers */
|
||||||
/* I assume it is okay to just check which side is TT_SPACE */
|
/* I assume it is okay to just check which side is TT_SPACE */
|
||||||
|
|
||||||
/* split_type = (SplitSide(t) << 1) | SplitDirection(t); */
|
|
||||||
split_type = SplitDirection(t);
|
split_type = SplitDirection(t);
|
||||||
if (TiGetLeftType(t) == TT_SPACE) split_type |= 2;
|
if (TiGetLeftType(t) == TT_SPACE) split_type |= 2;
|
||||||
num_points = 2;
|
num_points = 2;
|
||||||
|
|
@ -2721,7 +2725,9 @@ right_search:
|
||||||
done_searches:
|
done_searches:
|
||||||
if (intedges == 0)
|
if (intedges == 0)
|
||||||
{
|
{
|
||||||
calmaWritePaintFunc(t, cos);
|
calmaWritePaintFunc(t,
|
||||||
|
(split_type & 2) ? (TileType)TT_SIDE : (TileType)0,
|
||||||
|
cos);
|
||||||
|
|
||||||
/* Although calmaWritePaintFunc is called only on isolated */
|
/* Although calmaWritePaintFunc is called only on isolated */
|
||||||
/* tiles, we may have expanded it. This could use a LOT of */
|
/* tiles, we may have expanded it. This could use a LOT of */
|
||||||
|
|
@ -2791,6 +2797,7 @@ done_searches:
|
||||||
int
|
int
|
||||||
calmaWritePaintFunc(
|
calmaWritePaintFunc(
|
||||||
Tile *tile, /* Tile to be written out. */
|
Tile *tile, /* Tile to be written out. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
calmaOutputStruct *cos) /* File for output and clipping area */
|
calmaOutputStruct *cos) /* File for output and clipping area */
|
||||||
{
|
{
|
||||||
FILE *f = cos->f;
|
FILE *f = cos->f;
|
||||||
|
|
@ -2826,7 +2833,7 @@ calmaWritePaintFunc(
|
||||||
/* Coordinates */
|
/* Coordinates */
|
||||||
calmaOutRH(36, CALMA_XY, CALMA_I4, f);
|
calmaOutRH(36, CALMA_XY, CALMA_I4, f);
|
||||||
|
|
||||||
switch ((SplitSide(tile) << 1) | SplitDirection(tile))
|
switch (((dinfo & TT_SIDE) ? 2 : 0) | SplitDirection(tile))
|
||||||
{
|
{
|
||||||
case 0x0:
|
case 0x0:
|
||||||
calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ybot, f);
|
calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ybot, f);
|
||||||
|
|
@ -3067,6 +3074,7 @@ calmaWriteLabelFunc(
|
||||||
int
|
int
|
||||||
calmaPaintLabelFunc(
|
calmaPaintLabelFunc(
|
||||||
Tile *tile, /* Tile contains area for label. */
|
Tile *tile, /* Tile contains area for label. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
calmaOutputStruct *cos) /* File for output and clipping area */
|
calmaOutputStruct *cos) /* File for output and clipping area */
|
||||||
{
|
{
|
||||||
FILE *f = cos->f;
|
FILE *f = cos->f;
|
||||||
|
|
|
||||||
|
|
@ -107,10 +107,10 @@ typedef struct {
|
||||||
} calmaOutputStructZ;
|
} calmaOutputStructZ;
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
extern int calmaWritePaintFuncZ(Tile *tile, calmaOutputStructZ *cos);
|
extern int calmaWritePaintFuncZ(Tile *tile, TileType dinfo, calmaOutputStructZ *cos);
|
||||||
extern int calmaMergePaintFuncZ(Tile *tile, calmaOutputStructZ *cos);
|
extern int calmaMergePaintFuncZ(Tile *tile, TileType dinfo, calmaOutputStructZ *cos);
|
||||||
extern int calmaWriteUseFuncZ(CellUse *use, gzFile f);
|
extern int calmaWriteUseFuncZ(CellUse *use, gzFile f);
|
||||||
extern int calmaPaintLabelFuncZ(Tile *tile, calmaOutputStructZ *cos);
|
extern int calmaPaintLabelFuncZ(Tile *tile, TileType dinfo, calmaOutputStructZ *cos);
|
||||||
extern void calmaWriteContactsZ(gzFile f);
|
extern void calmaWriteContactsZ(gzFile f);
|
||||||
extern void calmaOutFuncZ(CellDef *def, gzFile f, const Rect *cliprect);
|
extern void calmaOutFuncZ(CellDef *def, gzFile f, const Rect *cliprect);
|
||||||
extern void calmaOutStructNameZ(int type, CellDef *def, gzFile f);
|
extern void calmaOutStructNameZ(int type, CellDef *def, gzFile f);
|
||||||
|
|
@ -508,7 +508,7 @@ calmaDumpStructureZ(
|
||||||
|
|
||||||
/* Is view abstract? */
|
/* Is view abstract? */
|
||||||
DBPropGet(edef, "LEFview", &isAbstract);
|
DBPropGet(edef, "LEFview", &isAbstract);
|
||||||
chklibname = (char *)DBPropGet(edef, "GDS_FILE", &isReadOnly);
|
chklibname = DBPropGetString(edef, "GDS_FILE", &isReadOnly);
|
||||||
|
|
||||||
if (isAbstract && isReadOnly)
|
if (isAbstract && isReadOnly)
|
||||||
{
|
{
|
||||||
|
|
@ -716,7 +716,7 @@ calmaFullDumpZ(
|
||||||
* names in the GDS file do not shadow any names in the database.
|
* names in the GDS file do not shadow any names in the database.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
viewopts = (char *)DBPropGet(def, "LEFview", &isAbstract);
|
viewopts = DBPropGetString(def, "LEFview", &isAbstract);
|
||||||
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
||||||
{
|
{
|
||||||
/* Generate a SHORT name for this cell (else it is easy to run into the
|
/* Generate a SHORT name for this cell (else it is easy to run into the
|
||||||
|
|
@ -870,7 +870,7 @@ calmaProcessDefZ(
|
||||||
DBPropGet(def, "GDS_START", &hasContent);
|
DBPropGet(def, "GDS_START", &hasContent);
|
||||||
DBPropGet(def, "GDS_END", &hasGDSEnd);
|
DBPropGet(def, "GDS_END", &hasGDSEnd);
|
||||||
DBPropGet(def, "CIFhier", &needHier);
|
DBPropGet(def, "CIFhier", &needHier);
|
||||||
filename = (char *)DBPropGet(def, "GDS_FILE", &isReadOnly);
|
filename = DBPropGetString(def, "GDS_FILE", &isReadOnly);
|
||||||
|
|
||||||
/* When used with "calma addendum true", don't output the read-only */
|
/* When used with "calma addendum true", don't output the read-only */
|
||||||
/* cells. This makes the library incomplete and dependent on the */
|
/* cells. This makes the library incomplete and dependent on the */
|
||||||
|
|
@ -985,13 +985,12 @@ calmaProcessDefZ(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
offptr = (char *)DBPropGet(def, "GDS_END", NULL);
|
cval = DBPropGetDouble(def, "GDS_END", NULL);
|
||||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
|
||||||
cellend = (z_off_t)cval;
|
cellend = (z_off_t)cval;
|
||||||
offptr = (char *)DBPropGet(def, "GDS_BEGIN", &oldStyle);
|
cval = DBPropGetDouble(def, "GDS_BEGIN", &oldStyle);
|
||||||
if (!oldStyle)
|
if (!oldStyle)
|
||||||
{
|
{
|
||||||
offptr = (char *)DBPropGet(def, "GDS_START", NULL);
|
cval = DBPropGetDouble(def, "GDS_START", NULL);
|
||||||
|
|
||||||
/* Write our own header and string name, to ensure */
|
/* Write our own header and string name, to ensure */
|
||||||
/* that the magic cell name and GDS name match. */
|
/* that the magic cell name and GDS name match. */
|
||||||
|
|
@ -1008,7 +1007,6 @@ calmaProcessDefZ(
|
||||||
calmaOutStructNameZ(CALMA_STRNAME, def, outf);
|
calmaOutStructNameZ(CALMA_STRNAME, def, outf);
|
||||||
}
|
}
|
||||||
|
|
||||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
|
||||||
cellstart = (z_off_t)cval;
|
cellstart = (z_off_t)cval;
|
||||||
|
|
||||||
/* GDS_START has been defined as the start of data after the cell */
|
/* GDS_START has been defined as the start of data after the cell */
|
||||||
|
|
@ -1186,6 +1184,7 @@ calmaOutFuncZ(
|
||||||
int dbunits;
|
int dbunits;
|
||||||
calmaOutputStructZ cos;
|
calmaOutputStructZ cos;
|
||||||
bool propfound;
|
bool propfound;
|
||||||
|
PropertyRecord *proprec;
|
||||||
char *propvalue;
|
char *propvalue;
|
||||||
extern int compport(const void *one, const void *two); /* Forward declaration */
|
extern int compport(const void *one, const void *two); /* Forward declaration */
|
||||||
|
|
||||||
|
|
@ -1247,15 +1246,21 @@ calmaOutFuncZ(
|
||||||
|
|
||||||
/* Include any fixed bounding box as part of the area to process, */
|
/* Include any fixed bounding box as part of the area to process, */
|
||||||
/* in case the fixed bounding box is larger than the geometry. */
|
/* in case the fixed bounding box is larger than the geometry. */
|
||||||
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
|
proprec = DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
Rect bbox;
|
Rect bbox;
|
||||||
|
|
||||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||||
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
(proprec->prop_len == 4))
|
||||||
|
{
|
||||||
|
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||||
|
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||||
|
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||||
|
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||||
GeoInclude(&bbox, &bigArea);
|
GeoInclude(&bbox, &bigArea);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CIFErrorDef = def;
|
CIFErrorDef = def;
|
||||||
CIFGen(def, def, &bigArea, CIFPlanes, &DBAllTypeBits, TRUE, TRUE, FALSE,
|
CIFGen(def, def, &bigArea, CIFPlanes, &DBAllTypeBits, TRUE, TRUE, FALSE,
|
||||||
|
|
@ -1899,6 +1904,7 @@ calmaProcessBoundaryZ(
|
||||||
int
|
int
|
||||||
calmaMergePaintFuncZ(
|
calmaMergePaintFuncZ(
|
||||||
Tile *tile, /* Tile to be written out. */
|
Tile *tile, /* Tile to be written out. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
calmaOutputStructZ *cos) /* Information needed by algorithm */
|
calmaOutputStructZ *cos) /* Information needed by algorithm */
|
||||||
{
|
{
|
||||||
gzFile f = cos->f;
|
gzFile f = cos->f;
|
||||||
|
|
@ -1929,11 +1935,10 @@ calmaMergePaintFuncZ(
|
||||||
split_type = -1;
|
split_type = -1;
|
||||||
if (IsSplit(t))
|
if (IsSplit(t))
|
||||||
{
|
{
|
||||||
/* If we use SplitSide, then we need to set it when the */
|
/* If we use TT_SIDE, then we need to set it when the */
|
||||||
/* tile is pushed. Since these are one-or-zero mask layers */
|
/* tile is pushed. Since these are one-or-zero mask layers */
|
||||||
/* I assume it is okay to just check which side is TT_SPACE */
|
/* I assume it is okay to just check which side is TT_SPACE */
|
||||||
|
|
||||||
/* split_type = (SplitSide(t) << 1) | SplitDirection(t); */
|
|
||||||
split_type = SplitDirection(t);
|
split_type = SplitDirection(t);
|
||||||
if (TiGetLeftType(t) == TT_SPACE) split_type |= 2;
|
if (TiGetLeftType(t) == TT_SPACE) split_type |= 2;
|
||||||
num_points = 2;
|
num_points = 2;
|
||||||
|
|
@ -2156,7 +2161,9 @@ right_search:
|
||||||
done_searches:
|
done_searches:
|
||||||
if (intedges == 0)
|
if (intedges == 0)
|
||||||
{
|
{
|
||||||
calmaWritePaintFuncZ(t, cos);
|
calmaWritePaintFuncZ(t,
|
||||||
|
(split_type & 2) ? (TileType)TT_SIDE : (TileType)0,
|
||||||
|
cos);
|
||||||
|
|
||||||
/* Although calmaWritePaintFunc is called only on isolated */
|
/* Although calmaWritePaintFunc is called only on isolated */
|
||||||
/* tiles, we may have expanded it. This could use a LOT of */
|
/* tiles, we may have expanded it. This could use a LOT of */
|
||||||
|
|
@ -2226,6 +2233,7 @@ done_searches:
|
||||||
int
|
int
|
||||||
calmaWritePaintFuncZ(
|
calmaWritePaintFuncZ(
|
||||||
Tile *tile, /* Tile to be written out. */
|
Tile *tile, /* Tile to be written out. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
calmaOutputStructZ *cos) /* File for output and clipping area */
|
calmaOutputStructZ *cos) /* File for output and clipping area */
|
||||||
{
|
{
|
||||||
gzFile f = cos->f;
|
gzFile f = cos->f;
|
||||||
|
|
@ -2261,7 +2269,7 @@ calmaWritePaintFuncZ(
|
||||||
/* Coordinates */
|
/* Coordinates */
|
||||||
calmaOutRHZ(36, CALMA_XY, CALMA_I4, f);
|
calmaOutRHZ(36, CALMA_XY, CALMA_I4, f);
|
||||||
|
|
||||||
switch ((SplitSide(tile) << 1) | SplitDirection(tile))
|
switch (((dinfo & TT_SIDE) ? 2 : 0) | SplitDirection(tile))
|
||||||
{
|
{
|
||||||
case 0x0:
|
case 0x0:
|
||||||
calmaOutI4Z(r.r_xbot, f); calmaOutI4Z(r.r_ybot, f);
|
calmaOutI4Z(r.r_xbot, f); calmaOutI4Z(r.r_ybot, f);
|
||||||
|
|
@ -2502,6 +2510,7 @@ calmaWriteLabelFuncZ(
|
||||||
int
|
int
|
||||||
calmaPaintLabelFuncZ(
|
calmaPaintLabelFuncZ(
|
||||||
Tile *tile, /* Tile contains area for label. */
|
Tile *tile, /* Tile contains area for label. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
calmaOutputStructZ *cos) /* File for output and clipping area */
|
calmaOutputStructZ *cos) /* File for output and clipping area */
|
||||||
{
|
{
|
||||||
gzFile f = cos->f;
|
gzFile f = cos->f;
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ extern TileTypeBitMask *CalmaMaskHints;
|
||||||
extern bool CalmaMergeTiles;
|
extern bool CalmaMergeTiles;
|
||||||
extern bool CalmaFlattenArrays;
|
extern bool CalmaFlattenArrays;
|
||||||
extern bool CalmaNoDRCCheck;
|
extern bool CalmaNoDRCCheck;
|
||||||
|
extern bool CalmaRecordPaths;
|
||||||
extern bool CalmaFlattenUses;
|
extern bool CalmaFlattenUses;
|
||||||
extern int CalmaFlattenLimit;
|
extern int CalmaFlattenLimit;
|
||||||
extern float CalmaMagScale;
|
extern float CalmaMagScale;
|
||||||
|
|
@ -81,6 +82,8 @@ extern int calmaProcessDefZ(CellDef *def, gzFile outf, bool do_library);
|
||||||
#endif
|
#endif
|
||||||
extern bool calmaReadI2Record(int type, int *pvalue);
|
extern bool calmaReadI2Record(int type, int *pvalue);
|
||||||
extern bool calmaReadI4Record(int type, int *pvalue);
|
extern bool calmaReadI4Record(int type, int *pvalue);
|
||||||
|
extern void calmaReadX(Point *p, int iscale);
|
||||||
|
extern void calmaReadY(Point *p, int iscale);
|
||||||
extern void calmaReadPoint(Point *p, int iscale);
|
extern void calmaReadPoint(Point *p, int iscale);
|
||||||
extern bool calmaReadR8(double *pd);
|
extern bool calmaReadR8(double *pd);
|
||||||
extern bool calmaReadStampRecord(int type, int *stampptr);
|
extern bool calmaReadStampRecord(int type, int *stampptr);
|
||||||
|
|
|
||||||
600
cif/CIFgen.c
600
cif/CIFgen.c
File diff suppressed because it is too large
Load Diff
211
cif/CIFhier.c
211
cif/CIFhier.c
|
|
@ -209,52 +209,41 @@ typedef struct _maskHintsData
|
||||||
{
|
{
|
||||||
Transform *mh_trans;
|
Transform *mh_trans;
|
||||||
CellDef *mh_def;
|
CellDef *mh_def;
|
||||||
|
Plane *mh_plane;
|
||||||
} MaskHintsData;
|
} MaskHintsData;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* cifMaskHints --
|
* cifCopyMaskHintFunc --
|
||||||
*
|
*
|
||||||
* Copy a mask hint into a target cell by adding it to the
|
* Callback function used by cifFlatMaskHints. Transforms a tile
|
||||||
* property list of the target cell. If the target cell already
|
* from the original plane and paints it into the target plane,
|
||||||
* has the same mask hint key, then the mask hint value is
|
* both of which are properties.
|
||||||
* appended to the property in the target cell def.
|
|
||||||
*
|
*
|
||||||
* Returns:
|
* Results:
|
||||||
* 0 to keep the search going.
|
* Zero to keep the search going.
|
||||||
*
|
*
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* Modifies properties of the target cell def.
|
* Paints geometry into the target plane.
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* DEPRECATED */
|
|
||||||
int
|
int
|
||||||
cifMaskHints(
|
cifCopyMaskHintFunc(Tile *tile,
|
||||||
char *name,
|
TileType dinfo,
|
||||||
char *value,
|
ClientData cdata)
|
||||||
CellDef *targetDef)
|
|
||||||
{
|
{
|
||||||
char *propvalue, *newval;
|
MaskHintsData *mhd = (MaskHintsData *)cdata;
|
||||||
bool propfound;
|
Rect r, newr;
|
||||||
|
|
||||||
if (!strncmp(name, "MASKHINTS_", 10))
|
TiToRect(tile, &r);
|
||||||
{
|
|
||||||
/* Check if name exists already in the flattened cell */
|
/* Transform tile area to coordinates of mhd->mh_plane and paint */
|
||||||
propvalue = (char *)DBPropGet(targetDef, name, &propfound);
|
GeoTransRect(mhd->mh_trans, &r, &newr);
|
||||||
if (propfound)
|
DBPaintPlane(mhd->mh_plane, &newr, CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||||
{
|
|
||||||
/* Append value to the property */
|
|
||||||
newval = mallocMagic(strlen(value) + strlen(propvalue) + 2);
|
|
||||||
sprintf(newval, "%s %s", propvalue, value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
newval = StrDup((char **)NULL, value);
|
|
||||||
|
|
||||||
DBPropPut(targetDef, name, newval);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,8 +253,8 @@ cifMaskHints(
|
||||||
* cifFlatMaskHints --
|
* cifFlatMaskHints --
|
||||||
*
|
*
|
||||||
* Copy a mask hint into a flattened cell by transforming it into the
|
* Copy a mask hint into a flattened cell by transforming it into the
|
||||||
* coordinate system of the flattened cell, and adding it to the
|
* coordinate system of the flattened cell, and painting it into the
|
||||||
* property list of the flattened cell.
|
* property plane of the flattened cell.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* 0 to keep the search going.
|
* 0 to keep the search going.
|
||||||
|
|
@ -279,67 +268,40 @@ cifMaskHints(
|
||||||
int
|
int
|
||||||
cifFlatMaskHints(
|
cifFlatMaskHints(
|
||||||
char *name,
|
char *name,
|
||||||
char *value,
|
PropertyRecord *proprec,
|
||||||
MaskHintsData *mhd)
|
MaskHintsData *mhd)
|
||||||
{
|
{
|
||||||
Rect r, newr;
|
Rect r, newr;
|
||||||
char *vptr, *newval, *lastval, *propvalue;
|
char *vptr, *newval, *lastval, *propvalue;
|
||||||
bool propfound;
|
bool propfound;
|
||||||
int lastlen, numvals;
|
int i, lastlen, numvals;
|
||||||
|
PropertyRecord *newproprec, *oldproprec;
|
||||||
|
Plane *plane;
|
||||||
|
|
||||||
if (!strncmp(name, "MASKHINTS_", 10))
|
if (!strncmp(name, "MASKHINTS_", 10))
|
||||||
{
|
{
|
||||||
newval = (char *)NULL;
|
|
||||||
vptr = value;
|
|
||||||
while (*vptr != '\0')
|
|
||||||
{
|
|
||||||
numvals = sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
|
||||||
&r.r_xtop, &r.r_ytop);
|
|
||||||
if (numvals == 4)
|
|
||||||
{
|
|
||||||
/* Transform rectangle to top level coordinates */
|
|
||||||
GeoTransRect(mhd->mh_trans, &r, &newr);
|
|
||||||
lastval = newval;
|
|
||||||
lastlen = (lastval) ? strlen(lastval) : 0;
|
|
||||||
newval = mallocMagic(40 + lastlen);
|
|
||||||
if (lastval)
|
|
||||||
strcpy(newval, lastval);
|
|
||||||
else
|
|
||||||
*newval = '\0';
|
|
||||||
sprintf(newval + lastlen, "%s%d %d %d %d", (lastval) ? " " : "",
|
|
||||||
newr.r_xbot, newr.r_ybot, newr.r_xtop, newr.r_ytop);
|
|
||||||
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++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TxError("MASKHINTS_%s: Expected 4 values, found only %d\n",
|
|
||||||
name + 10, numvals);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if name exists already in the flattened cell */
|
/* Check if name exists already in the flattened cell */
|
||||||
propvalue = (char *)DBPropGet(mhd->mh_def, name, &propfound);
|
oldproprec = (PropertyRecord *)DBPropGet(mhd->mh_def, name, &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
/* Append newval to the property */
|
ASSERT(oldproprec->prop_value.prop_type == PROPERTY_TYPE_PLANE,
|
||||||
lastval = newval;
|
"cifFlatMaskHints");
|
||||||
newval = mallocMagic(strlen(lastval) + strlen(propvalue) + 2);
|
plane = oldproprec->prop_value.prop_plane;
|
||||||
sprintf(newval, "%s %s", propvalue, lastval);
|
|
||||||
freeMagic(lastval);
|
|
||||||
}
|
}
|
||||||
DBPropPut(mhd->mh_def, name, newval);
|
else
|
||||||
|
{
|
||||||
|
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||||
|
newproprec->prop_len = 0; /* (unused) */
|
||||||
|
newproprec->prop_type = PROPERTY_TYPE_PLANE;
|
||||||
|
plane = DBNewPlane((ClientData)TT_SPACE);
|
||||||
|
newproprec->prop_value.prop_plane = plane;
|
||||||
|
DBPropPut(mhd->mh_def, name, newproprec);
|
||||||
|
}
|
||||||
|
|
||||||
|
mhd->mh_plane = plane;
|
||||||
|
DBSrPaintArea((Tile *)NULL, proprec->prop_value.prop_plane,
|
||||||
|
&TiPlaneRect, &CIFSolidBits,
|
||||||
|
cifCopyMaskHintFunc, (ClientData)mhd);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -350,9 +312,10 @@ cifFlatMaskHints(
|
||||||
* CIFCopyMaskHints --
|
* CIFCopyMaskHints --
|
||||||
*
|
*
|
||||||
* Callback function to copy mask hints from one cell into another.
|
* Callback function to copy mask hints from one cell into another.
|
||||||
|
* (Occasionally called as a standalone function, not as a callback.)
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* None.
|
* Return 0 to keep the search going.
|
||||||
*
|
*
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* May modify properties in the target cell.
|
* May modify properties in the target cell.
|
||||||
|
|
@ -360,7 +323,7 @@ cifFlatMaskHints(
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
int
|
||||||
CIFCopyMaskHints(
|
CIFCopyMaskHints(
|
||||||
SearchContext *scx,
|
SearchContext *scx,
|
||||||
CellDef *targetDef)
|
CellDef *targetDef)
|
||||||
|
|
@ -370,38 +333,9 @@ CIFCopyMaskHints(
|
||||||
CellDef *sourceDef = scx->scx_use->cu_def;
|
CellDef *sourceDef = scx->scx_use->cu_def;
|
||||||
mhd.mh_trans = &scx->scx_trans;
|
mhd.mh_trans = &scx->scx_trans;
|
||||||
mhd.mh_def = targetDef;
|
mhd.mh_def = targetDef;
|
||||||
|
mhd.mh_plane = (Plane *)NULL;
|
||||||
|
|
||||||
DBPropEnum(sourceDef, cifFlatMaskHints, &mhd);
|
DBPropEnum(sourceDef, cifFlatMaskHints, &mhd);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* cifHierCopyMaskHints --
|
|
||||||
*
|
|
||||||
* Callback function to copy mask hints from a subcell into a flattened
|
|
||||||
* cell, which is passed in the clientData record.
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* Always returns 0 to keep the search alive.
|
|
||||||
*
|
|
||||||
* Side effects:
|
|
||||||
* May modify properties in the flattened cell.
|
|
||||||
*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
cifHierCopyMaskHints(
|
|
||||||
SearchContext *scx,
|
|
||||||
ClientData clientData)
|
|
||||||
{
|
|
||||||
MaskHintsData mhd;
|
|
||||||
|
|
||||||
mhd.mh_trans = &scx->scx_trans;
|
|
||||||
mhd.mh_def = (CellDef *)clientData;
|
|
||||||
|
|
||||||
DBPropEnum(scx->scx_use->cu_def, cifFlatMaskHints, &mhd);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -433,15 +367,16 @@ cifHierCopyMaskHints(
|
||||||
int
|
int
|
||||||
cifHierCopyFunc(
|
cifHierCopyFunc(
|
||||||
Tile *tile, /* Pointer to tile to copy. */
|
Tile *tile, /* Pointer to tile to copy. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
TreeContext *cxp) /* Describes context of search, including
|
TreeContext *cxp) /* Describes context of search, including
|
||||||
* transform and client data.
|
* transform and client data.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
TileType type = TiGetTypeExact(tile);
|
TileType type = TiGetTypeExact(tile) | dinfo;
|
||||||
Rect sourceRect, targetRect;
|
Rect sourceRect, targetRect;
|
||||||
int pNum;
|
int pNum;
|
||||||
CellDef *def = (CellDef *) cxp->tc_filter->tf_arg;
|
CellDef *def = (CellDef *) cxp->tc_filter->tf_arg;
|
||||||
int dinfo = 0;
|
TileType newdinfo = 0;
|
||||||
|
|
||||||
/* Ignore tiles in vendor GDS, unless this is specifically */
|
/* Ignore tiles in vendor GDS, unless this is specifically */
|
||||||
/* overridden by the "see-vendor" option. */
|
/* overridden by the "see-vendor" option. */
|
||||||
|
|
@ -457,8 +392,8 @@ cifHierCopyFunc(
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
dinfo = DBTransformDiagonal(type, &cxp->tc_scx->scx_trans);
|
newdinfo = DBTransformDiagonal(type, &cxp->tc_scx->scx_trans);
|
||||||
type = (SplitSide(tile)) ? SplitRightType(tile) :
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile) :
|
||||||
SplitLeftType(tile);
|
SplitLeftType(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -473,7 +408,7 @@ cifHierCopyFunc(
|
||||||
{
|
{
|
||||||
if (DBPaintOnPlane(type, pNum))
|
if (DBPaintOnPlane(type, pNum))
|
||||||
{
|
{
|
||||||
DBNMPaintPlane(def->cd_planes[pNum], dinfo, &targetRect,
|
DBNMPaintPlane(def->cd_planes[pNum], newdinfo, &targetRect,
|
||||||
DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL);
|
DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -525,7 +460,7 @@ cifHierCellFunc(
|
||||||
|
|
||||||
/* Flatten mask hints in the area of interest */
|
/* Flatten mask hints in the area of interest */
|
||||||
CIFCopyMaskHints(scx, CIFComponentDef);
|
CIFCopyMaskHints(scx, CIFComponentDef);
|
||||||
DBTreeSrCells(&newscx, 0, cifHierCopyMaskHints,
|
DBTreeSrCells(&newscx, 0, CIFCopyMaskHints,
|
||||||
(ClientData)CIFComponentDef);
|
(ClientData)CIFComponentDef);
|
||||||
|
|
||||||
/* Set CIFErrorDef to NULL to ignore errors here... these will
|
/* Set CIFErrorDef to NULL to ignore errors here... these will
|
||||||
|
|
@ -562,9 +497,11 @@ cifHierCellFunc(
|
||||||
int
|
int
|
||||||
cifHierErrorFunc(
|
cifHierErrorFunc(
|
||||||
Tile *tile, /* Tile that covers area it shouldn't. */
|
Tile *tile, /* Tile that covers area it shouldn't. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
Rect *checkArea) /* Intersection of this and tile is error. */
|
Rect *checkArea) /* Intersection of this and tile is error. */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
bool side = (dinfo & TT_SIDE) ? TRUE : FALSE;
|
||||||
|
|
||||||
TiToRect(tile, &area);
|
TiToRect(tile, &area);
|
||||||
|
|
||||||
|
|
@ -572,8 +509,8 @@ cifHierErrorFunc(
|
||||||
* space bounds the checkArea.
|
* space bounds the checkArea.
|
||||||
*/
|
*/
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
if (((area.r_xbot == checkArea->r_xbot) && !SplitSide(tile)) ||
|
if (((area.r_xbot == checkArea->r_xbot) && !side) ||
|
||||||
((area.r_xtop == checkArea->r_xtop) && SplitSide(tile)))
|
((area.r_xtop == checkArea->r_xtop) && side))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
GeoClip(&area, checkArea);
|
GeoClip(&area, checkArea);
|
||||||
|
|
@ -604,6 +541,7 @@ cifHierErrorFunc(
|
||||||
int
|
int
|
||||||
cifHierCheckFunc(
|
cifHierCheckFunc(
|
||||||
Tile *tile, /* Tile containing CIF. */
|
Tile *tile, /* Tile containing CIF. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
Plane *plane) /* Plane to check against and modify. */
|
Plane *plane) /* Plane to check against and modify. */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
@ -612,10 +550,10 @@ cifHierCheckFunc(
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
DBSrPaintNMArea((Tile *)NULL, plane, TiGetTypeExact(tile),
|
DBSrPaintNMArea((Tile *)NULL, plane, TiGetTypeExact(tile) | dinfo,
|
||||||
&area, &DBSpaceBits, cifHierErrorFunc, (ClientData) &area);
|
&area, &DBSpaceBits, cifHierErrorFunc, (ClientData) &area);
|
||||||
|
|
||||||
DBNMPaintPlane(plane, TiGetTypeExact(tile), &area, CIFEraseTable,
|
DBNMPaintPlane(plane, TiGetTypeExact(tile) | dinfo, &area, CIFEraseTable,
|
||||||
(PaintUndoInfo *) NULL);
|
(PaintUndoInfo *) NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -651,6 +589,7 @@ cifHierCheckFunc(
|
||||||
int
|
int
|
||||||
cifHierTempCheckFunc(
|
cifHierTempCheckFunc(
|
||||||
Tile *tile, /* Tile containing CIF. */
|
Tile *tile, /* Tile containing CIF. */
|
||||||
|
TileType dinfo, /* Information about split tiles */
|
||||||
Plane *plane) /* Plane to check against and modify. */
|
Plane *plane) /* Plane to check against and modify. */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
@ -658,7 +597,7 @@ cifHierTempCheckFunc(
|
||||||
TiToRect(tile, &area);
|
TiToRect(tile, &area);
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
DBNMPaintPlane(plane, TiGetTypeExact(tile), &area, CIFEraseTable,
|
DBNMPaintPlane(plane, TiGetTypeExact(tile) | dinfo, &area, CIFEraseTable,
|
||||||
(PaintUndoInfo *) NULL);
|
(PaintUndoInfo *) NULL);
|
||||||
else
|
else
|
||||||
DBPaintPlane(plane, &area, CIFEraseTable, (PaintUndoInfo *) NULL);
|
DBPaintPlane(plane, &area, CIFEraseTable, (PaintUndoInfo *) NULL);
|
||||||
|
|
@ -686,6 +625,7 @@ cifHierTempCheckFunc(
|
||||||
int
|
int
|
||||||
cifHierPaintFunc(
|
cifHierPaintFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo, /* Information about split tiles */
|
||||||
Plane *plane) /* Plane in which to paint CIF over tile's
|
Plane *plane) /* Plane in which to paint CIF over tile's
|
||||||
* area.
|
* area.
|
||||||
*/
|
*/
|
||||||
|
|
@ -693,9 +633,9 @@ cifHierPaintFunc(
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
||||||
TiToRect(tile, &area);
|
TiToRect(tile, &area);
|
||||||
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, &area);
|
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, dinfo, &area);
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
DBNMPaintPlane(plane, TiGetTypeExact(tile), &area, CIFPaintTable,
|
DBNMPaintPlane(plane, TiGetTypeExact(tile) | dinfo, &area, CIFPaintTable,
|
||||||
(PaintUndoInfo *) NULL);
|
(PaintUndoInfo *) NULL);
|
||||||
else
|
else
|
||||||
DBPaintPlane(plane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
DBPaintPlane(plane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||||
|
|
@ -848,7 +788,7 @@ CIFGenSubcells(
|
||||||
cifHierCopyFunc, (ClientData) CIFTotalDef);
|
cifHierCopyFunc, (ClientData) CIFTotalDef);
|
||||||
/* Flatten mask hints in the area of interest */
|
/* Flatten mask hints in the area of interest */
|
||||||
CIFCopyMaskHints(&scx, CIFTotalDef);
|
CIFCopyMaskHints(&scx, CIFTotalDef);
|
||||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||||
(ClientData)CIFTotalDef);
|
(ClientData)CIFTotalDef);
|
||||||
|
|
||||||
CIFErrorDef = def;
|
CIFErrorDef = def;
|
||||||
|
|
@ -1026,14 +966,14 @@ cifHierElementFunc(
|
||||||
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
|
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
|
||||||
cifHierCopyFunc, (ClientData) CIFTotalDef);
|
cifHierCopyFunc, (ClientData) CIFTotalDef);
|
||||||
CIFCopyMaskHints(&scx, CIFTotalDef);
|
CIFCopyMaskHints(&scx, CIFTotalDef);
|
||||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||||
(ClientData)CIFTotalDef);
|
(ClientData)CIFTotalDef);
|
||||||
|
|
||||||
DBCellClearDef(CIFComponentDef);
|
DBCellClearDef(CIFComponentDef);
|
||||||
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
|
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
|
||||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||||
(ClientData)CIFComponentDef);
|
(ClientData)CIFComponentDef);
|
||||||
|
|
||||||
CIFErrorDef = (CellDef *) NULL;
|
CIFErrorDef = (CellDef *) NULL;
|
||||||
|
|
@ -1067,6 +1007,7 @@ cifHierElementFunc(
|
||||||
int
|
int
|
||||||
cifGrowSliver(
|
cifGrowSliver(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo, /* Split tile information, needs to be handled */
|
||||||
Rect *area)
|
Rect *area)
|
||||||
{
|
{
|
||||||
int height, width, expand_up, expand_side;
|
int height, width, expand_up, expand_side;
|
||||||
|
|
@ -1127,22 +1068,24 @@ cifGrowSliver(
|
||||||
|
|
||||||
int
|
int
|
||||||
cifHierPaintArrayFunc(
|
cifHierPaintArrayFunc(
|
||||||
Tile *tile)
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
|
ClientData clientdata) /* (unused) */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
int i, j, xbot, xtop;
|
int i, j, xbot, xtop;
|
||||||
|
|
||||||
TiToRect(tile, &area);
|
TiToRect(tile, &area);
|
||||||
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, &area);
|
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, dinfo, &area);
|
||||||
xbot = area.r_xbot;
|
xbot = area.r_xbot;
|
||||||
xtop = area.r_xtop;
|
xtop = area.r_xtop;
|
||||||
for (i=0; i<cifHierYCount; i++)
|
for (i=0; i<cifHierYCount; i++)
|
||||||
{
|
{
|
||||||
for (j=0; j<cifHierXCount; j++)
|
for (j = 0; j < cifHierXCount; j++)
|
||||||
{
|
{
|
||||||
DBPaintPlane(cifHierCurPlane, &area, CIFPaintTable,
|
DBNMPaintPlane(cifHierCurPlane, TiGetTypeExact(tile) | dinfo,
|
||||||
(PaintUndoInfo *) NULL);
|
&area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||||
CIFTileOps += 1;
|
CIFTileOps++;
|
||||||
area.r_xbot += cifHierXSpacing;
|
area.r_xbot += cifHierXSpacing;
|
||||||
area.r_xtop += cifHierXSpacing;
|
area.r_xtop += cifHierXSpacing;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
11
cif/CIFint.h
11
cif/CIFint.h
|
|
@ -145,6 +145,8 @@ 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_NOTSQUARE - Added 2/26/26---Keep only geometry which is not square.
|
||||||
|
* CIFOP_TAGGED - Added 3/11/26---Find geometry attached to the given text label
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CIFOP_AND 1
|
#define CIFOP_AND 1
|
||||||
|
|
@ -172,6 +174,8 @@ typedef struct cifop
|
||||||
#define CIFOP_BRIDGE 23
|
#define CIFOP_BRIDGE 23
|
||||||
#define CIFOP_BRIDGELIM 24
|
#define CIFOP_BRIDGELIM 24
|
||||||
#define CIFOP_MASKHINTS 25
|
#define CIFOP_MASKHINTS 25
|
||||||
|
#define CIFOP_NOTSQUARE 26
|
||||||
|
#define CIFOP_TAGGED 27
|
||||||
|
|
||||||
/* Definitions of bit fields used in the value of co_client for CIFOP_INTERACT */
|
/* Definitions of bit fields used in the value of co_client for CIFOP_INTERACT */
|
||||||
#define CIFOP_INT_NOT 0x1 /* Inverted sense (not interacting) */
|
#define CIFOP_INT_NOT 0x1 /* Inverted sense (not interacting) */
|
||||||
|
|
@ -335,10 +339,9 @@ extern void CIFClearPlanes(Plane **planes);
|
||||||
extern Plane *CIFGenLayer(CIFOp *op, const Rect *area, CellDef *cellDef, CellDef *origDef, Plane *temps[],
|
extern Plane *CIFGenLayer(CIFOp *op, const Rect *area, CellDef *cellDef, CellDef *origDef, Plane *temps[],
|
||||||
bool hier, ClientData clientdata);
|
bool hier, ClientData clientdata);
|
||||||
extern void CIFInitCells(void);
|
extern void CIFInitCells(void);
|
||||||
extern int cifHierCopyFunc(Tile *tile, TreeContext *cxp);
|
extern int cifHierCopyFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
|
||||||
extern int cifHierCopyMaskHints(SearchContext *scx, ClientData clientData);
|
|
||||||
extern void CIFLoadStyle(char *stylename);
|
extern void CIFLoadStyle(char *stylename);
|
||||||
extern void CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef);
|
extern int CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef);
|
||||||
|
|
||||||
/* C99 compat */
|
/* C99 compat */
|
||||||
extern void CIFCoverageLayer(CellDef *rootDef, Rect *area, char *layer, bool dolist);
|
extern void CIFCoverageLayer(CellDef *rootDef, Rect *area, char *layer, bool dolist);
|
||||||
|
|
@ -346,7 +349,7 @@ extern bool CIFWriteFlat(CellDef *rootDef, FILE *f);
|
||||||
extern void CIFScalePlanes(int scalen, int scaled, Plane **planearray);
|
extern void CIFScalePlanes(int scalen, int scaled, Plane **planearray);
|
||||||
extern void CIFInputRescale(int n, int d);
|
extern void CIFInputRescale(int n, int d);
|
||||||
extern int CIFScaleCoord(int cifCoord, int snap_type);
|
extern int CIFScaleCoord(int cifCoord, int snap_type);
|
||||||
extern int cifGrowSliver(Tile *tile, Rect *area);
|
extern int cifGrowSliver(Tile *tile, TileType dinfo, Rect *area);
|
||||||
extern int cifHierElementFunc(CellUse *use, Transform *transform, int x, int y, Rect *checkArea);
|
extern int cifHierElementFunc(CellUse *use, Transform *transform, int x, int y, Rect *checkArea);
|
||||||
extern int cifSquareFunc(Rect *area, CIFOp *op, int *rows, int *columns, Rect *cut);
|
extern int cifSquareFunc(Rect *area, CIFOp *op, int *rows, int *columns, Rect *cut);
|
||||||
extern int cifSquareGridFunc(Rect *area, CIFOp *op, int *rows, int *columns, Rect *cut);
|
extern int cifSquareGridFunc(Rect *area, CIFOp *op, int *rows, int *columns, Rect *cut);
|
||||||
|
|
|
||||||
205
cif/CIFrdcl.c
205
cif/CIFrdcl.c
|
|
@ -505,6 +505,7 @@ CIFParseStart(void)
|
||||||
|
|
||||||
int cifCheckPaintFunc(
|
int cifCheckPaintFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
ClientData clientData)
|
ClientData clientData)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -515,27 +516,28 @@ int cifCheckPaintFunc(
|
||||||
int
|
int
|
||||||
cifCopyPaintFunc(
|
cifCopyPaintFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
CIFCopyRec *cifCopyRec)
|
CIFCopyRec *cifCopyRec)
|
||||||
{
|
{
|
||||||
int pNum;
|
int pNum;
|
||||||
TileType dinfo;
|
TileType newdinfo;
|
||||||
Rect sourceRect, targetRect;
|
Rect sourceRect, targetRect;
|
||||||
Transform *trans = cifCopyRec->trans;
|
Transform *trans = cifCopyRec->trans;
|
||||||
Plane *plane = cifCopyRec->plane;
|
Plane *plane = cifCopyRec->plane;
|
||||||
|
|
||||||
dinfo = TiGetTypeExact(tile);
|
newdinfo = TiGetTypeExact(tile) | dinfo;
|
||||||
|
|
||||||
if (trans)
|
if (trans)
|
||||||
{
|
{
|
||||||
TiToRect(tile, &sourceRect);
|
TiToRect(tile, &sourceRect);
|
||||||
GeoTransRect(trans, &sourceRect, &targetRect);
|
GeoTransRect(trans, &sourceRect, &targetRect);
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
dinfo = DBTransformDiagonal(TiGetTypeExact(tile), trans);
|
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, trans);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
TiToRect(tile, &targetRect);
|
TiToRect(tile, &targetRect);
|
||||||
|
|
||||||
DBNMPaintPlane(plane, dinfo, &targetRect, CIFPaintTable,
|
DBNMPaintPlane(plane, newdinfo, &targetRect, CIFPaintTable,
|
||||||
(PaintUndoInfo *)NULL);
|
(PaintUndoInfo *)NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -561,6 +563,7 @@ cifCopyPaintFunc(
|
||||||
int
|
int
|
||||||
cifMaskHintFunc(
|
cifMaskHintFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo, /* Unused, do not support non-manhattan hints */
|
||||||
LinkedRect **lrecp)
|
LinkedRect **lrecp)
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
@ -597,8 +600,9 @@ int
|
||||||
CIFPaintCurrent(
|
CIFPaintCurrent(
|
||||||
int filetype)
|
int filetype)
|
||||||
{
|
{
|
||||||
extern int cifMakeBoundaryFunc(Tile *tile, ClientData clientdata); /* Forward declaration. */
|
/* Forward declarations. */
|
||||||
extern int cifPaintCurrentFunc(Tile *tile, TileType type); /* Forward declaration. */
|
extern int cifMakeBoundaryFunc(Tile *tile, TileType dinfo, ClientData clientdata);
|
||||||
|
extern int cifPaintCurrentFunc(Tile *tile, TileType dinfo, TileType type);
|
||||||
|
|
||||||
Plane *plane, *swapplane;
|
Plane *plane, *swapplane;
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -609,7 +613,7 @@ CIFPaintCurrent(
|
||||||
CIFOp *op;
|
CIFOp *op;
|
||||||
|
|
||||||
plane = CIFGenLayer(cifCurReadStyle->crs_layers[i]->crl_ops,
|
plane = CIFGenLayer(cifCurReadStyle->crs_layers[i]->crl_ops,
|
||||||
&TiPlaneRect, (CellDef *)NULL, (CellDef *)NULL,
|
&TiPlaneRect, cifReadCellDef, cifReadCellDef,
|
||||||
cifCurReadPlanes, FALSE, (ClientData)NULL);
|
cifCurReadPlanes, FALSE, (ClientData)NULL);
|
||||||
|
|
||||||
/* Generate a paint/erase table, then paint from the CIF
|
/* Generate a paint/erase table, then paint from the CIF
|
||||||
|
|
@ -684,6 +688,8 @@ CIFPaintCurrent(
|
||||||
}
|
}
|
||||||
else if (op == NULL)
|
else if (op == NULL)
|
||||||
{
|
{
|
||||||
|
LinkedRect *lrec = NULL, *lsrch;
|
||||||
|
|
||||||
/* Handle boundary layer */
|
/* Handle boundary layer */
|
||||||
|
|
||||||
op = cifCurReadStyle->crs_layers[i]->crl_ops;
|
op = cifCurReadStyle->crs_layers[i]->crl_ops;
|
||||||
|
|
@ -698,6 +704,102 @@ CIFPaintCurrent(
|
||||||
(ClientData)NULL) == 1))
|
(ClientData)NULL) == 1))
|
||||||
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
|
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
|
||||||
&CIFSolidBits, cifMakeBoundaryFunc, INT2CD(filetype));
|
&CIFSolidBits, cifMakeBoundaryFunc, INT2CD(filetype));
|
||||||
|
|
||||||
|
/* Handle mask-hints input operator */
|
||||||
|
|
||||||
|
op = cifCurReadStyle->crs_layers[i]->crl_ops;
|
||||||
|
while (op)
|
||||||
|
{
|
||||||
|
if (op->co_opcode == CIFOP_MASKHINTS) break;
|
||||||
|
op = op->co_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op && (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
|
||||||
|
&DBAllButSpaceBits, cifCheckPaintFunc,
|
||||||
|
(ClientData)NULL) == 1))
|
||||||
|
{
|
||||||
|
/* (To do: remove the linked Rects and paint directly
|
||||||
|
* into the plane in cifMaskHintFunc())
|
||||||
|
*/
|
||||||
|
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
|
||||||
|
&CIFSolidBits, cifMaskHintFunc,
|
||||||
|
(ClientData)&lrec);
|
||||||
|
|
||||||
|
if (lrec != NULL)
|
||||||
|
{
|
||||||
|
PropertyRecord *proprec, *proporig;
|
||||||
|
char *propname, *layername;
|
||||||
|
int proplen, i, savescale;
|
||||||
|
bool origfound = FALSE;
|
||||||
|
Plane *plane;
|
||||||
|
|
||||||
|
layername = (char *)op->co_client;
|
||||||
|
propname = (char *)mallocMagic(11 + strlen(layername));
|
||||||
|
sprintf(propname, "MASKHINTS_%s", layername);
|
||||||
|
|
||||||
|
/* If there is already a mask hint plane for this layer,
|
||||||
|
* then add to it; otherwise, create a new plane.
|
||||||
|
*/
|
||||||
|
proprec = DBPropGet(cifReadCellDef, layername, &origfound);
|
||||||
|
if (origfound)
|
||||||
|
plane = proprec->prop_value.prop_plane;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(
|
||||||
|
sizeof(PropertyRecord));
|
||||||
|
proprec->prop_type = PROPERTY_TYPE_PLANE;
|
||||||
|
proprec->prop_len = 0; /* (unused) */
|
||||||
|
plane = DBNewPlane((ClientData)TT_SPACE);
|
||||||
|
proprec->prop_value.prop_plane = plane;
|
||||||
|
DBPropPut(cifReadCellDef, propname, proprec);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (lrec != NULL)
|
||||||
|
{
|
||||||
|
lrec->r_r.r_xtop =
|
||||||
|
CIFScaleCoord(lrec->r_r.r_xtop, COORD_EXACT);
|
||||||
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
||||||
|
lrec->r_r.r_ytop =
|
||||||
|
CIFScaleCoord(lrec->r_r.r_ytop, COORD_EXACT);
|
||||||
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
||||||
|
{
|
||||||
|
lrec->r_r.r_xtop *=
|
||||||
|
(savescale / cifCurReadStyle->crs_scaleFactor);
|
||||||
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
||||||
|
}
|
||||||
|
lrec->r_r.r_xbot =
|
||||||
|
CIFScaleCoord(lrec->r_r.r_xbot, COORD_EXACT);
|
||||||
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
||||||
|
{
|
||||||
|
lrec->r_r.r_xtop *=
|
||||||
|
(savescale / cifCurReadStyle->crs_scaleFactor);
|
||||||
|
lrec->r_r.r_ytop *=
|
||||||
|
(savescale / cifCurReadStyle->crs_scaleFactor);
|
||||||
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
||||||
|
}
|
||||||
|
lrec->r_r.r_ybot =
|
||||||
|
CIFScaleCoord(lrec->r_r.r_ybot, COORD_EXACT);
|
||||||
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
||||||
|
{
|
||||||
|
lrec->r_r.r_xtop *=
|
||||||
|
(savescale / cifCurReadStyle->crs_scaleFactor);
|
||||||
|
lrec->r_r.r_ytop *=
|
||||||
|
(savescale / cifCurReadStyle->crs_scaleFactor);
|
||||||
|
lrec->r_r.r_xbot *=
|
||||||
|
(savescale / cifCurReadStyle->crs_scaleFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBPaintPlane(plane, &lrec->r_r, CIFPaintTable,
|
||||||
|
(PaintUndoInfo *)NULL);
|
||||||
|
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
freeMagic1(&mm1, lrec);
|
||||||
|
lrec = lrec->r_next;
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
}
|
||||||
|
freeMagic(propname);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Swap planes */
|
/* Swap planes */
|
||||||
|
|
@ -786,9 +888,7 @@ CIFPaintCurrent(
|
||||||
|
|
||||||
for (i = 0; i < cifNReadLayers; i++)
|
for (i = 0; i < cifNReadLayers; i++)
|
||||||
{
|
{
|
||||||
LinkedRect *lrec = NULL;
|
LinkedRect *lrec = NULL, *lsrch;
|
||||||
char *propstr = NULL;
|
|
||||||
char locstr[512];
|
|
||||||
Plane *tempp;
|
Plane *tempp;
|
||||||
|
|
||||||
if (!TTMaskHasType(CalmaMaskHints, i)) continue;
|
if (!TTMaskHasType(CalmaMaskHints, i)) continue;
|
||||||
|
|
@ -813,53 +913,55 @@ CIFPaintCurrent(
|
||||||
(CellDef *)NULL, CIFPlanes, FALSE, (ClientData)NULL);
|
(CellDef *)NULL, CIFPlanes, FALSE, (ClientData)NULL);
|
||||||
|
|
||||||
/* Scan the resulting plane and generate linked Rect structures for
|
/* Scan the resulting plane and generate linked Rect structures for
|
||||||
* each shape found.
|
* each shape found. (To do: Remove the linked Rects and paint
|
||||||
|
* directly into the plane in cifMaskHintFunc(), which is more
|
||||||
|
* efficient but not hugely so.)
|
||||||
*/
|
*/
|
||||||
DBSrPaintArea((Tile *)NULL, presult, &TiPlaneRect, &CIFSolidBits,
|
DBSrPaintArea((Tile *)NULL, presult, &TiPlaneRect, &CIFSolidBits,
|
||||||
cifMaskHintFunc, (ClientData)&lrec);
|
cifMaskHintFunc, (ClientData)&lrec);
|
||||||
|
|
||||||
if (lrec != NULL)
|
if (lrec != NULL)
|
||||||
{
|
{
|
||||||
|
PropertyRecord *proprec;
|
||||||
|
bool propfound;
|
||||||
char *propname;
|
char *propname;
|
||||||
|
Plane *plane;
|
||||||
|
|
||||||
propname = (char *)mallocMagic(11 + strlen(cifReadLayers[i]));
|
propname = (char *)mallocMagic(11 + strlen(cifReadLayers[i]));
|
||||||
sprintf(propname, "MASKHINTS_%s", cifReadLayers[i]);
|
sprintf(propname, "MASKHINTS_%s", cifReadLayers[i]);
|
||||||
|
|
||||||
propstr = (char *)NULL;
|
/* Paint all linked Rects into a mask-hints property plane
|
||||||
|
* in the target cell.
|
||||||
/* Turn all linked Rects into a mask-hints property in the
|
|
||||||
* target cell.
|
|
||||||
*/
|
*/
|
||||||
while (lrec != NULL)
|
|
||||||
|
proprec = DBPropGet(cifReadCellDef, propname, &propfound);
|
||||||
|
if (!propfound)
|
||||||
{
|
{
|
||||||
char *newstr;
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||||
sprintf(locstr, "%d %d %d %d",
|
proprec->prop_type = PROPERTY_TYPE_PLANE;
|
||||||
lrec->r_r.r_xbot / CIFCurStyle->cs_scaleFactor,
|
proprec->prop_len = 0; /* (unused) */
|
||||||
lrec->r_r.r_ybot / CIFCurStyle->cs_scaleFactor,
|
plane = DBNewPlane((ClientData)TT_SPACE);
|
||||||
lrec->r_r.r_xtop / CIFCurStyle->cs_scaleFactor,
|
proprec->prop_value.prop_plane = plane;
|
||||||
lrec->r_r.r_ytop / CIFCurStyle->cs_scaleFactor);
|
DBPropPut(cifReadCellDef, propname, proprec);
|
||||||
if (propstr == NULL)
|
|
||||||
{
|
|
||||||
newstr = (char *)mallocMagic(strlen(locstr) + 1);
|
|
||||||
sprintf(newstr, "%s", locstr);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
plane = proprec->prop_value.prop_plane;
|
||||||
|
|
||||||
|
while (lrec != NULL)
|
||||||
{
|
{
|
||||||
newstr = (char *)mallocMagic(strlen(locstr)
|
lrec->r_r.r_xbot /= CIFCurStyle->cs_scaleFactor;
|
||||||
+ strlen(propstr) + 2);
|
lrec->r_r.r_ybot /= CIFCurStyle->cs_scaleFactor;
|
||||||
sprintf(newstr, "%s %s", propstr, locstr);
|
lrec->r_r.r_xtop /= CIFCurStyle->cs_scaleFactor;
|
||||||
freeMagic(propstr);
|
lrec->r_r.r_ytop /= CIFCurStyle->cs_scaleFactor;
|
||||||
}
|
|
||||||
propstr = newstr;
|
DBPaintPlane(plane, &lrec->r_r, CIFPaintTable,
|
||||||
|
(PaintUndoInfo *)NULL);
|
||||||
|
|
||||||
free_magic1_t mm1 = freeMagic1_init();
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
freeMagic1(&mm1, lrec);
|
freeMagic1(&mm1, lrec);
|
||||||
lrec = lrec->r_next;
|
lrec = lrec->r_next;
|
||||||
freeMagic1_end(&mm1);
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
/* NOTE: propstr is transferred to the CellDef and should
|
|
||||||
* not be free'd here.
|
|
||||||
*/
|
|
||||||
DBPropPut(cifReadCellDef, propname, propstr);
|
|
||||||
freeMagic(propname);
|
freeMagic(propname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -891,12 +993,14 @@ CIFPaintCurrent(
|
||||||
int
|
int
|
||||||
cifMakeBoundaryFunc(
|
cifMakeBoundaryFunc(
|
||||||
Tile *tile, /* Tile of CIF information. */
|
Tile *tile, /* Tile of CIF information. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
ClientData clientdata) /* Pass the file type (CIF or CALMA) */
|
ClientData clientdata) /* Pass the file type (CIF or CALMA) */
|
||||||
{
|
{
|
||||||
/* It is assumed that there is one rectangle for the boundary. */
|
/* It is assumed that there is one rectangle for the boundary. */
|
||||||
/* If there are multiple rectangles defined with the boundary */
|
/* If there are multiple rectangles defined with the boundary */
|
||||||
/* layer, then the last one defines the FIXED_BBOX property. */
|
/* layer, then the last one defines the FIXED_BBOX property. */
|
||||||
|
|
||||||
|
PropertyRecord *proprec;
|
||||||
Rect area;
|
Rect area;
|
||||||
char propertyvalue[128], *storedvalue;
|
char propertyvalue[128], *storedvalue;
|
||||||
int savescale;
|
int savescale;
|
||||||
|
|
@ -928,19 +1032,24 @@ cifMakeBoundaryFunc(
|
||||||
|
|
||||||
if (cifReadCellDef->cd_flags & CDFIXEDBBOX)
|
if (cifReadCellDef->cd_flags & CDFIXEDBBOX)
|
||||||
{
|
{
|
||||||
char *propvalue;
|
PropertyRecord *proprec;
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
/* Only flag a warning if the redefined boundary was */
|
/* Only flag a warning if the redefined boundary was */
|
||||||
/* different from the original. */
|
/* different from the original. */
|
||||||
|
|
||||||
propvalue = (char *)DBPropGet(cifReadCellDef, "FIXED_BBOX", &found);
|
proprec = DBPropGet(cifReadCellDef, "FIXED_BBOX", &found);
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
Rect bbox;
|
Rect bbox;
|
||||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||||
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
(proprec->prop_len == 4))
|
||||||
{
|
{
|
||||||
|
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||||
|
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||||
|
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||||
|
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||||
|
|
||||||
if ((bbox.r_xbot != area.r_xbot) ||
|
if ((bbox.r_xbot != area.r_xbot) ||
|
||||||
(bbox.r_ybot != area.r_ybot) ||
|
(bbox.r_ybot != area.r_ybot) ||
|
||||||
(bbox.r_xtop != area.r_xtop) ||
|
(bbox.r_xtop != area.r_xtop) ||
|
||||||
|
|
@ -957,10 +1066,15 @@ cifMakeBoundaryFunc(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(propertyvalue, "%d %d %d %d",
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + 2 * sizeof(int));
|
||||||
area.r_xbot, area.r_ybot, area.r_xtop, area.r_ytop);
|
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||||
storedvalue = StrDup((char **)NULL, propertyvalue);
|
proprec->prop_len = 4;
|
||||||
DBPropPut(cifReadCellDef, "FIXED_BBOX", storedvalue);
|
proprec->prop_value.prop_integer[0] = area.r_xbot;
|
||||||
|
proprec->prop_value.prop_integer[1] = area.r_ybot;
|
||||||
|
proprec->prop_value.prop_integer[2] = area.r_xtop;
|
||||||
|
proprec->prop_value.prop_integer[3] = area.r_ytop;
|
||||||
|
|
||||||
|
DBPropPut(cifReadCellDef, "FIXED_BBOX", proprec);
|
||||||
cifReadCellDef->cd_flags |= CDFIXEDBBOX;
|
cifReadCellDef->cd_flags |= CDFIXEDBBOX;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -970,6 +1084,7 @@ cifMakeBoundaryFunc(
|
||||||
int
|
int
|
||||||
cifPaintCurrentFunc(
|
cifPaintCurrentFunc(
|
||||||
Tile *tile, /* Tile of CIF information. */
|
Tile *tile, /* Tile of CIF information. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
TileType type) /* Magic type to be painted. */
|
TileType type) /* Magic type to be painted. */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
@ -1019,7 +1134,7 @@ cifPaintCurrentFunc(
|
||||||
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
|
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
|
||||||
if (DBPaintOnPlane(type, pNum))
|
if (DBPaintOnPlane(type, pNum))
|
||||||
{
|
{
|
||||||
DBNMPaintPlane(cifReadCellDef->cd_planes[pNum], TiGetTypeExact(tile),
|
DBNMPaintPlane(cifReadCellDef->cd_planes[pNum], TiGetTypeExact(tile) | dinfo,
|
||||||
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL);
|
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -244,40 +244,61 @@ CIFPropRecordPath(
|
||||||
{
|
{
|
||||||
extern float CIFGetOutputScale(int convert);
|
extern float CIFGetOutputScale(int convert);
|
||||||
CIFPath *pathp;
|
CIFPath *pathp;
|
||||||
char *pathstr, *sptr;
|
char *namestr = NULL;
|
||||||
int components;
|
int components, i, x, y, mult, pathnum;
|
||||||
float x, y, oscale, mult;
|
PropertyRecord *proprec;
|
||||||
|
bool propfound;
|
||||||
|
|
||||||
oscale = CIFGetOutputScale(1000); /* 1000 for conversion to um */
|
/* If "name" is a property, then append a suffix to it to ensure uniqueness */
|
||||||
if (oscale == 0.0) oscale = 1.0;
|
DBPropGet(def, propname, &propfound);
|
||||||
mult = (iswire == TRUE) ? 0.5 : 1.0;
|
if (propfound)
|
||||||
|
{
|
||||||
|
pathnum = 0;
|
||||||
|
namestr = mallocMagic(strlen(propname) + 10);
|
||||||
|
while (propfound)
|
||||||
|
{
|
||||||
|
sprintf(namestr, "%s_%d", propname, pathnum);
|
||||||
|
DBPropGet(def, namestr, &propfound);
|
||||||
|
pathnum++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pathp = pathheadp;
|
mult = (iswire == TRUE) ? 1 : 0;
|
||||||
components = 0;
|
|
||||||
|
|
||||||
/* Count the number of components in the path */
|
/* Count the number of components in the path */
|
||||||
|
pathp = pathheadp;
|
||||||
|
components = 0;
|
||||||
while (pathp != NULL)
|
while (pathp != NULL)
|
||||||
{
|
{
|
||||||
pathp = pathp->cifp_next;
|
|
||||||
components++;
|
components++;
|
||||||
|
pathp = pathp->cifp_next;
|
||||||
}
|
}
|
||||||
/* Allocate enough space to hold 2 * N points at "infinity" */
|
/* Allocate enough space to hold 2 * N points. */
|
||||||
pathstr = (char *)mallocMagic(components * 40);
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||||
|
((components - 1) * 2) * sizeof(int));
|
||||||
|
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||||
|
proprec->prop_len = components * 2;
|
||||||
|
|
||||||
pathp = pathheadp;
|
pathp = pathheadp;
|
||||||
sptr = pathstr;
|
i = 0;
|
||||||
while (pathp != NULL)
|
while (pathp != NULL)
|
||||||
{
|
{
|
||||||
x = (float)pathp->cifp_x * oscale * mult;
|
x = pathp->cifp_x >> mult;
|
||||||
y = (float)pathp->cifp_y * oscale * mult;
|
y = pathp->cifp_y >> mult;
|
||||||
sprintf(sptr, "%.3f %.3f ", x, y);
|
|
||||||
sptr = sptr + strlen(sptr);
|
proprec->prop_value.prop_integer[i] = x;
|
||||||
|
proprec->prop_value.prop_integer[i + 1] = y;
|
||||||
|
|
||||||
|
i += 2;
|
||||||
pathp = pathp->cifp_next;
|
pathp = pathp->cifp_next;
|
||||||
}
|
}
|
||||||
|
if (namestr)
|
||||||
/* Reallocate pathstr to be no larger than needed to hold the path contents */
|
{
|
||||||
StrDup(&pathstr, pathstr);
|
DBPropPut(def, namestr, proprec);
|
||||||
DBPropPut(def, propname, (ClientData)pathstr);
|
freeMagic(namestr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DBPropPut(def, propname, proprec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -324,14 +324,19 @@ cifNewReadStyle(void)
|
||||||
{
|
{
|
||||||
/* Destroy old style and free all memory allocated to it */
|
/* Destroy old style and free all memory allocated to it */
|
||||||
|
|
||||||
for (i=0; i<MAXCIFRLAYERS; i+=1)
|
for (i = 0; i < MAXCIFRLAYERS; i++)
|
||||||
{
|
{
|
||||||
layer = cifCurReadStyle->crs_layers[i];
|
layer = cifCurReadStyle->crs_layers[i];
|
||||||
if (layer != NULL)
|
if (layer != NULL)
|
||||||
{
|
{
|
||||||
free_magic1_t mm1 = freeMagic1_init();
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (op = layer->crl_ops; op != NULL; op = op->co_next)
|
for (op = layer->crl_ops; op != NULL; op = op->co_next)
|
||||||
|
{
|
||||||
|
if (op->co_opcode == CIFOP_MASKHINTS ||
|
||||||
|
op->co_opcode == CIFOP_TAGGED)
|
||||||
|
freeMagic((char *)op->co_client);
|
||||||
freeMagic1(&mm1, (char *)op);
|
freeMagic1(&mm1, (char *)op);
|
||||||
|
}
|
||||||
freeMagic1_end(&mm1);
|
freeMagic1_end(&mm1);
|
||||||
freeMagic((char *)layer);
|
freeMagic((char *)layer);
|
||||||
}
|
}
|
||||||
|
|
@ -990,6 +995,12 @@ CIFReadTechLine(
|
||||||
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], "not-square") == 0)
|
||||||
|
newOp->co_opcode = CIFOP_NOTSQUARE;
|
||||||
|
else if (strcmp(argv[0], "mask-hints") == 0)
|
||||||
|
newOp->co_opcode = CIFOP_MASKHINTS;
|
||||||
|
else if (strcmp(argv[0], "tagged") == 0)
|
||||||
|
newOp->co_opcode = CIFOP_TAGGED;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TechError("Unknown statement \"%s\".\n", argv[0]);
|
TechError("Unknown statement \"%s\".\n", argv[0]);
|
||||||
|
|
@ -1016,6 +1027,15 @@ CIFReadTechLine(
|
||||||
goto errorReturn;
|
goto errorReturn;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case CIFOP_MASKHINTS:
|
||||||
|
if (argc != 2) goto wrongNumArgs;
|
||||||
|
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
|
||||||
|
break;
|
||||||
|
case CIFOP_TAGGED:
|
||||||
|
if (argc != 3) goto wrongNumArgs;
|
||||||
|
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
|
||||||
|
CIFParseReadLayers(argv[2], &newOp->co_cifMask, TRUE);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Link the new CIFOp onto the list. */
|
/* Link the new CIFOp onto the list. */
|
||||||
|
|
@ -1099,6 +1119,7 @@ CIFReadTechFinal(void)
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
CIFReadLoadStyle(
|
CIFReadLoadStyle(
|
||||||
char *stylename)
|
char *stylename)
|
||||||
|
|
|
||||||
27
cif/CIFsee.c
27
cif/CIFsee.c
|
|
@ -78,6 +78,7 @@ typedef struct {
|
||||||
int
|
int
|
||||||
cifPaintDBFunc(
|
cifPaintDBFunc(
|
||||||
Tile *tile, /* Tile of CIF information. */
|
Tile *tile, /* Tile of CIF information. */
|
||||||
|
TileType dinfo,
|
||||||
PaintLayerData *pld)
|
PaintLayerData *pld)
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
@ -106,7 +107,7 @@ cifPaintDBFunc(
|
||||||
if (DBPaintOnPlane(type, pNum))
|
if (DBPaintOnPlane(type, pNum))
|
||||||
{
|
{
|
||||||
ui.pu_pNum = pNum;
|
ui.pu_pNum = pNum;
|
||||||
DBNMPaintPlane(paintDef->cd_planes[pNum], TiGetTypeExact(tile),
|
DBNMPaintPlane(paintDef->cd_planes[pNum], TiGetTypeExact(tile) | dinfo,
|
||||||
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) &ui);
|
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) &ui);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -167,7 +168,7 @@ CIFPaintLayer(
|
||||||
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
||||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||||
(ClientData)CIFComponentDef);
|
(ClientData)CIFComponentDef);
|
||||||
|
|
||||||
oldCount = DBWFeedbackCount;
|
oldCount = DBWFeedbackCount;
|
||||||
|
|
@ -219,6 +220,7 @@ CIFPaintLayer(
|
||||||
int
|
int
|
||||||
cifSeeFunc(
|
cifSeeFunc(
|
||||||
Tile *tile, /* Tile to be entered as feedback. */
|
Tile *tile, /* Tile to be entered as feedback. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
SeeLayerData *sld) /* Layer and explanation for the feedback. */
|
SeeLayerData *sld) /* Layer and explanation for the feedback. */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
@ -233,10 +235,10 @@ cifSeeFunc(
|
||||||
(float)area.r_ybot / (float)CIFCurStyle->cs_scaleFactor);
|
(float)area.r_ybot / (float)CIFCurStyle->cs_scaleFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (NOTE: Preserve information about the geometry of a diagonal tile) */
|
||||||
DBWFeedbackAdd(&area, sld->text, cifSeeDef, CIFCurStyle->cs_scaleFactor,
|
DBWFeedbackAdd(&area, sld->text, cifSeeDef, CIFCurStyle->cs_scaleFactor,
|
||||||
sld->style |
|
sld->style | ((TiGetTypeExact(tile) | dinfo) &
|
||||||
(TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
|
(TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
|
||||||
/* (preserve information about the geometry of a diagonal tile) */
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -287,7 +289,7 @@ CIFSeeLayer(
|
||||||
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
||||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||||
(ClientData)CIFComponentDef);
|
(ClientData)CIFComponentDef);
|
||||||
|
|
||||||
oldCount = DBWFeedbackCount;
|
oldCount = DBWFeedbackCount;
|
||||||
|
|
@ -438,9 +440,11 @@ CIFCoverageLayer(
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
TileTypeBitMask mask, depend;
|
TileTypeBitMask mask, depend;
|
||||||
float fcover;
|
float fcover;
|
||||||
int cifCoverageFunc(Tile *tile, ClientData *arg);
|
|
||||||
bool doBox = (area != &rootDef->cd_bbox) ? TRUE : FALSE;
|
bool doBox = (area != &rootDef->cd_bbox) ? TRUE : FALSE;
|
||||||
|
|
||||||
|
/* Forward declaration */
|
||||||
|
int cifCoverageFunc(Tile *tile, TileType dinfo, ClientData *arg);
|
||||||
|
|
||||||
/* Check out the CIF layer name. */
|
/* Check out the CIF layer name. */
|
||||||
|
|
||||||
if (!CIFNameToMask(layer, &mask, &depend)) return;
|
if (!CIFNameToMask(layer, &mask, &depend)) return;
|
||||||
|
|
@ -457,7 +461,7 @@ CIFCoverageLayer(
|
||||||
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
||||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||||
(ClientData)CIFComponentDef);
|
(ClientData)CIFComponentDef);
|
||||||
|
|
||||||
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,
|
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,
|
||||||
|
|
@ -500,10 +504,10 @@ CIFCoverageLayer(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TxPrintf("%s Area = %lld CIF units^2\n", doBox ? "Cursor Box" :
|
TxPrintf("%s Area = %"DLONG_PREFIX"d CIF units^2\n", doBox ? "Cursor Box" :
|
||||||
"Cell", btotal);
|
"Cell", btotal);
|
||||||
TxPrintf("Layer Bounding Area = %lld CIF units^2\n", atotal);
|
TxPrintf("Layer Bounding Area = %"DLONG_PREFIX"d CIF units^2\n", atotal);
|
||||||
TxPrintf("Layer Total Area = %lld CIF units^2\n", cstats.coverage);
|
TxPrintf("Layer Total Area = %"DLONG_PREFIX"d CIF units^2\n", cstats.coverage);
|
||||||
TxPrintf("Coverage in %s = %1.1f%%\n", doBox ? "box" :
|
TxPrintf("Coverage in %s = %1.1f%%\n", doBox ? "box" :
|
||||||
"cell", 100.0 * fcover);
|
"cell", 100.0 * fcover);
|
||||||
}
|
}
|
||||||
|
|
@ -512,6 +516,7 @@ CIFCoverageLayer(
|
||||||
int
|
int
|
||||||
cifCoverageFunc(
|
cifCoverageFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
ClientData *arg)
|
ClientData *arg)
|
||||||
{
|
{
|
||||||
coverstats *cstats = (coverstats *)arg;
|
coverstats *cstats = (coverstats *)arg;
|
||||||
|
|
|
||||||
|
|
@ -817,7 +817,7 @@ CIFTechLine(
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
l = strlen(CIFCurStyle->cs_name) - strlen(tptr);
|
l = strlen(CIFCurStyle->cs_name) - strlen(tptr);
|
||||||
if (!strcmp(tptr, CIFCurStyle->cs_name + l))
|
if ((l > 0) && !strcmp(tptr, CIFCurStyle->cs_name + l))
|
||||||
{
|
{
|
||||||
CIFCurStyle->cs_status = TECH_PENDING;
|
CIFCurStyle->cs_status = TECH_PENDING;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
@ -1107,6 +1107,8 @@ CIFTechLine(
|
||||||
newOp->co_opcode = CIFOP_BBOX;
|
newOp->co_opcode = CIFOP_BBOX;
|
||||||
else if (strcmp(argv[0], "net") == 0)
|
else if (strcmp(argv[0], "net") == 0)
|
||||||
newOp->co_opcode = CIFOP_NET;
|
newOp->co_opcode = CIFOP_NET;
|
||||||
|
else if (strcmp(argv[0], "tagged") == 0)
|
||||||
|
newOp->co_opcode = CIFOP_TAGGED;
|
||||||
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)
|
else if (strcmp(argv[0], "boundary") == 0)
|
||||||
|
|
@ -1117,6 +1119,8 @@ CIFTechLine(
|
||||||
newOp->co_opcode = CIFOP_CLOSE;
|
newOp->co_opcode = CIFOP_CLOSE;
|
||||||
else if (strcmp(argv[0], "orthogonal") == 0)
|
else if (strcmp(argv[0], "orthogonal") == 0)
|
||||||
newOp->co_opcode = CIFOP_MANHATTAN;
|
newOp->co_opcode = CIFOP_MANHATTAN;
|
||||||
|
else if (strcmp(argv[0], "not-square") == 0)
|
||||||
|
newOp->co_opcode = CIFOP_NOTSQUARE;
|
||||||
else if (strcmp(argv[0], "bridge") == 0)
|
else if (strcmp(argv[0], "bridge") == 0)
|
||||||
newOp->co_opcode = CIFOP_BRIDGE;
|
newOp->co_opcode = CIFOP_BRIDGE;
|
||||||
else if (strcmp(argv[0], "bridge-lim") == 0)
|
else if (strcmp(argv[0], "bridge-lim") == 0)
|
||||||
|
|
@ -1355,6 +1359,7 @@ bloatCheck:
|
||||||
bloatDone: break;
|
bloatDone: break;
|
||||||
|
|
||||||
case CIFOP_NET:
|
case CIFOP_NET:
|
||||||
|
case CIFOP_TAGGED:
|
||||||
if (argc != 3) goto wrongNumArgs;
|
if (argc != 3) goto wrongNumArgs;
|
||||||
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
|
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
|
||||||
cifParseLayers(argv[2], CIFCurStyle, &newOp->co_paintMask,
|
cifParseLayers(argv[2], CIFCurStyle, &newOp->co_paintMask,
|
||||||
|
|
@ -1669,12 +1674,12 @@ cifComputeRadii(
|
||||||
|
|
||||||
for (op = layer->cl_ops; op != NULL; op = op->co_next)
|
for (op = layer->cl_ops; op != NULL; op = op->co_next)
|
||||||
{
|
{
|
||||||
/* BBOX, NET, and MASKHINTS operators should never be used */
|
/* BBOX, NET, TAGGED, and MASKHINTS operators should never be */
|
||||||
/* hierarchically so ignore any grow/shrink operators that */
|
/* used hierarchically so ignore any grow/shrink operators that */
|
||||||
/* come after them. */
|
/* come after them. */
|
||||||
|
|
||||||
if (op->co_opcode == CIFOP_BBOX || op->co_opcode == CIFOP_NET ||
|
if (op->co_opcode == CIFOP_BBOX || op->co_opcode == CIFOP_NET ||
|
||||||
op->co_opcode == CIFOP_MASKHINTS)
|
op->co_opcode == CIFOP_TAGGED || op->co_opcode == CIFOP_MASKHINTS)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* If CIF layers are used, switch to the max of current
|
/* If CIF layers are used, switch to the max of current
|
||||||
|
|
@ -1986,8 +1991,8 @@ CIFTechFinal(void)
|
||||||
/* Presence of op->co_opcode in CIFOP_OR indicates a copy */
|
/* Presence of op->co_opcode in CIFOP_OR indicates a copy */
|
||||||
/* of the SquaresData pointer from a following operator. */
|
/* of the SquaresData pointer from a following operator. */
|
||||||
/* CIFOP_BBOX and CIFOP_MAXRECT uses the co_client field */
|
/* CIFOP_BBOX and CIFOP_MAXRECT uses the co_client field */
|
||||||
/* as a flag field, while CIFOP_NET and CIFOP_MASKHINTS */
|
/* as a flag field, while CIFOP_NET, CIFOP_MASKHINTS, and */
|
||||||
/* uses it for a string. */
|
/* CIFOP_TAGGED use it for a string. */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (op->co_opcode)
|
switch (op->co_opcode)
|
||||||
|
|
@ -1999,6 +2004,7 @@ CIFTechFinal(void)
|
||||||
case CIFOP_MAXRECT:
|
case CIFOP_MAXRECT:
|
||||||
case CIFOP_MANHATTAN:
|
case CIFOP_MANHATTAN:
|
||||||
case CIFOP_NET:
|
case CIFOP_NET:
|
||||||
|
case CIFOP_TAGGED:
|
||||||
break;
|
break;
|
||||||
case CIFOP_BRIDGELIM:
|
case CIFOP_BRIDGELIM:
|
||||||
case CIFOP_BRIDGE:
|
case CIFOP_BRIDGE:
|
||||||
|
|
@ -2534,6 +2540,7 @@ CIFTechOutputScale(
|
||||||
case CIFOP_MAXRECT:
|
case CIFOP_MAXRECT:
|
||||||
case CIFOP_MANHATTAN:
|
case CIFOP_MANHATTAN:
|
||||||
case CIFOP_NET:
|
case CIFOP_NET:
|
||||||
|
case CIFOP_TAGGED:
|
||||||
case CIFOP_INTERACT:
|
case CIFOP_INTERACT:
|
||||||
break;
|
break;
|
||||||
case CIFOP_BRIDGELIM:
|
case CIFOP_BRIDGELIM:
|
||||||
|
|
@ -2649,8 +2656,8 @@ CIFTechOutputScale(
|
||||||
default:
|
default:
|
||||||
/* op->co_opcode in CIFOP_OR is a pointer copy, */
|
/* op->co_opcode in CIFOP_OR is a pointer copy, */
|
||||||
/* in CIFOP_BBOX and CIFOP_MAXRECT is a flag, */
|
/* in CIFOP_BBOX and CIFOP_MAXRECT is a flag, */
|
||||||
/* and in CIFOP_NET and CIFOP_MASKHINTS is a */
|
/* and in CIFOP_NET, CIFOP_MASKHINTS, and */
|
||||||
/* string. */
|
/* CIFOP_TAGGED is a string. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,8 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
extern int cifWriteInitFunc(CellDef *def);
|
extern int cifWriteInitFunc(CellDef *def);
|
||||||
extern int cifWriteMarkFunc(CellUse *use);
|
extern int cifWriteMarkFunc(CellUse *use);
|
||||||
extern int cifWritePaintFunc(Tile *tile, FILE *f);
|
extern int cifWritePaintFunc(Tile *tile, TileType dinfo, FILE *f);
|
||||||
extern int cifWriteLabelFunc(Tile *tile, FILE *f);
|
extern int cifWriteLabelFunc(Tile *tile, TileType dinfo, FILE *f);
|
||||||
extern int cifWriteUseFunc(CellUse *use, FILE *f);
|
extern int cifWriteUseFunc(CellUse *use, FILE *f);
|
||||||
extern void cifOutPreamble(FILE *outf, CellDef *cell);
|
extern void cifOutPreamble(FILE *outf, CellDef *cell);
|
||||||
extern void cifOut(FILE *outf);
|
extern void cifOut(FILE *outf);
|
||||||
|
|
@ -584,6 +584,7 @@ cifWriteUseFunc(
|
||||||
int
|
int
|
||||||
cifWriteLabelFunc(
|
cifWriteLabelFunc(
|
||||||
Tile *tile, /* Tile to be written out. */
|
Tile *tile, /* Tile to be written out. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
FILE *f) /* File in which to write. */
|
FILE *f) /* File in which to write. */
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
@ -643,6 +644,7 @@ cifWriteLabelFunc(
|
||||||
int
|
int
|
||||||
cifWritePaintFunc(
|
cifWritePaintFunc(
|
||||||
Tile *tile, /* Tile to be written out. */
|
Tile *tile, /* Tile to be written out. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
FILE *f) /* File in which to write. */
|
FILE *f) /* File in which to write. */
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
@ -662,7 +664,7 @@ cifWritePaintFunc(
|
||||||
Point points[5];
|
Point points[5];
|
||||||
int i, np;
|
int i, np;
|
||||||
|
|
||||||
GrClipTriangle(&r, NULL, FALSE, TiGetTypeExact(tile), points, &np);
|
GrClipTriangle(&r, NULL, FALSE, TiGetTypeExact(tile) | dinfo, points, &np);
|
||||||
|
|
||||||
/* Write triangle as a CIF polygon */
|
/* Write triangle as a CIF polygon */
|
||||||
|
|
||||||
|
|
|
||||||
150
commands/CmdAB.c
150
commands/CmdAB.c
|
|
@ -338,14 +338,17 @@ CmdArray(
|
||||||
case ARRAY_WIDTH:
|
case ARRAY_WIDTH:
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *xsepvalue;
|
||||||
for (la = lahead; la != NULL; la = la->ar_next)
|
for (la = lahead; la != NULL; la = la->ar_next)
|
||||||
{
|
{
|
||||||
|
xsepvalue = DBWPrintValue(la->arrayInfo.ar_xsep,
|
||||||
|
w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
if (doList)
|
if (doList)
|
||||||
{
|
{
|
||||||
tobj = Tcl_NewListObj(0, NULL);
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
Tcl_NewIntObj(la->arrayInfo.ar_xsep));
|
Tcl_NewStringObj(xsepvalue, -1));
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -355,7 +358,7 @@ CmdArray(
|
||||||
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
||||||
else
|
else
|
||||||
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
||||||
TxPrintf("x separation %d\n", la->arrayInfo.ar_xsep);
|
TxPrintf("x separation %s\n", xsepvalue);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -374,14 +377,17 @@ CmdArray(
|
||||||
case ARRAY_HEIGHT:
|
case ARRAY_HEIGHT:
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *ysepvalue;
|
||||||
for (la = lahead; la != NULL; la = la->ar_next)
|
for (la = lahead; la != NULL; la = la->ar_next)
|
||||||
{
|
{
|
||||||
|
ysepvalue = DBWPrintValue(la->arrayInfo.ar_ysep,
|
||||||
|
w, FALSE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
if (doList)
|
if (doList)
|
||||||
{
|
{
|
||||||
tobj = Tcl_NewListObj(0, NULL);
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
Tcl_NewIntObj(la->arrayInfo.ar_ysep));
|
Tcl_NewStringObj(ysepvalue, -1));
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -391,7 +397,7 @@ CmdArray(
|
||||||
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
||||||
else
|
else
|
||||||
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
||||||
TxPrintf("y separation %d\n", la->arrayInfo.ar_ysep);
|
TxPrintf("y separation %s\n", ysepvalue);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -410,16 +416,21 @@ CmdArray(
|
||||||
case ARRAY_PITCH:
|
case ARRAY_PITCH:
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *xpitch, *ypitch;
|
||||||
for (la = lahead; la != NULL; la = la->ar_next)
|
for (la = lahead; la != NULL; la = la->ar_next)
|
||||||
{
|
{
|
||||||
|
xpitch = DBWPrintValue(la->arrayInfo.ar_xsep,
|
||||||
|
w, TRUE);
|
||||||
|
ypitch = DBWPrintValue(la->arrayInfo.ar_ysep,
|
||||||
|
w, FALSE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
if (doList)
|
if (doList)
|
||||||
{
|
{
|
||||||
tobj = Tcl_NewListObj(0, NULL);
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
Tcl_NewIntObj(la->arrayInfo.ar_xsep));
|
Tcl_NewStringObj(xpitch, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
Tcl_NewIntObj(la->arrayInfo.ar_ysep));
|
Tcl_NewStringObj(ypitch, -1));
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -429,8 +440,8 @@ CmdArray(
|
||||||
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
||||||
else
|
else
|
||||||
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
||||||
TxPrintf("x separation %d ", la->arrayInfo.ar_xsep);
|
TxPrintf("x separation %s ", xpitch);
|
||||||
TxPrintf("y separation %d\n", la->arrayInfo.ar_ysep);
|
TxPrintf("y separation %s\n", ypitch);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -450,16 +461,21 @@ CmdArray(
|
||||||
case ARRAY_POSITION:
|
case ARRAY_POSITION:
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *xpos, *ypos;
|
||||||
for (la = lahead; la != NULL; la = la->ar_next)
|
for (la = lahead; la != NULL; la = la->ar_next)
|
||||||
{
|
{
|
||||||
|
xpos = DBWPrintValue(la->cellUse->cu_bbox.r_xbot,
|
||||||
|
w, TRUE);
|
||||||
|
ypos = DBWPrintValue(la->cellUse->cu_bbox.r_ybot,
|
||||||
|
w, FALSE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
if (doList)
|
if (doList)
|
||||||
{
|
{
|
||||||
tobj = Tcl_NewListObj(0, NULL);
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
Tcl_NewIntObj(la->cellUse->cu_bbox.r_xbot));
|
Tcl_NewStringObj(xpos, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
Tcl_NewIntObj(la->cellUse->cu_bbox.r_ybot));
|
Tcl_NewStringObj(ypos, -1));
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -469,8 +485,8 @@ CmdArray(
|
||||||
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
||||||
else
|
else
|
||||||
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
||||||
TxPrintf("x=%d ", la->cellUse->cu_bbox.r_xbot);
|
TxPrintf("x=%s ", xpos);
|
||||||
TxPrintf("y=%d\n", la->cellUse->cu_bbox.r_ybot);
|
TxPrintf("y=%s\n", ypos);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -763,8 +779,8 @@ CmdBox(
|
||||||
break;
|
break;
|
||||||
case BOX_EXISTS:
|
case BOX_EXISTS:
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetResult(magicinterp, ToolGetBox(NULL, NULL) ? "1" : "0",
|
Tcl_SetObjResult(magicinterp,
|
||||||
NULL);
|
Tcl_NewBooleanObj(ToolGetBox(NULL, NULL) ? TRUE : FALSE));
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s\n", ToolGetBox(NULL, NULL) ? "True" : "False");
|
TxPrintf("%s\n", ToolGetBox(NULL, NULL) ? "True" : "False");
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -874,13 +890,16 @@ CmdBox(
|
||||||
TxRebuildCommand(cmd);
|
TxRebuildCommand(cmd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (DBWSnapToGrid != DBW_SNAP_USER)
|
else if (DBWUnits != DBW_UNITS_USER)
|
||||||
{
|
{
|
||||||
distancex = cmdParseCoord(w, cmd->tx_argv[3], TRUE, FALSE);
|
distancex = cmdParseCoord(w, cmd->tx_argv[3], TRUE, FALSE);
|
||||||
distancey = distancex;
|
distancey = distancex;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* For user units, the distance may be different in the X and Y
|
||||||
|
* directions for a given value.
|
||||||
|
*/
|
||||||
switch (direction)
|
switch (direction)
|
||||||
{
|
{
|
||||||
case GEO_EAST: case GEO_WEST:
|
case GEO_EAST: case GEO_WEST:
|
||||||
|
|
@ -908,15 +927,14 @@ CmdBox(
|
||||||
case BOX_WIDTH:
|
case BOX_WIDTH:
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
{
|
{
|
||||||
|
char *boxvalues;
|
||||||
|
boxvalues = DBWPrintValue(boxptr->r_xtop - boxptr->r_xbot,
|
||||||
|
w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
char *boxvalues = (char *)Tcl_Alloc(50);
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(boxvalues, -1));
|
||||||
sprintf(boxvalues, "%d",
|
|
||||||
boxptr->r_xtop - boxptr->r_xbot);
|
|
||||||
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s box width is %d\n",
|
TxPrintf("%s box width is %s\n", (refEdit) ? "Edit" : "Root",
|
||||||
(refEdit) ? "Edit" : "Root",
|
boxvalues);
|
||||||
boxptr->r_xtop - boxptr->r_xbot);
|
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -928,15 +946,14 @@ CmdBox(
|
||||||
case BOX_HEIGHT:
|
case BOX_HEIGHT:
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
{
|
{
|
||||||
|
char *boxvalues;
|
||||||
|
boxvalues = DBWPrintValue(boxptr->r_ytop - boxptr->r_ybot,
|
||||||
|
w, FALSE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
char *boxvalues = (char *)Tcl_Alloc(50);
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(boxvalues, -1));
|
||||||
sprintf(boxvalues, "%d",
|
|
||||||
boxptr->r_ytop - boxptr->r_ybot);
|
|
||||||
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s box height is %d\n",
|
TxPrintf("%s box height is %s\n", (refEdit) ? "Edit" : "Root",
|
||||||
(refEdit) ? "Edit" : "Root",
|
boxvalues);
|
||||||
boxptr->r_ytop - boxptr->r_ybot);
|
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -949,16 +966,24 @@ CmdBox(
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
{
|
{
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
char *boxvalues = (char *)Tcl_Alloc(50);
|
Tcl_Obj *tobj;
|
||||||
sprintf(boxvalues, "%d %d",
|
#endif
|
||||||
boxptr->r_xtop - boxptr->r_xbot,
|
char *boxvaluex, *boxvaluey;
|
||||||
boxptr->r_ytop - boxptr->r_ybot);
|
boxvaluex = DBWPrintValue(boxptr->r_xtop - boxptr->r_xbot,
|
||||||
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
w, TRUE);
|
||||||
|
boxvaluey = DBWPrintValue(boxptr->r_ytop - boxptr->r_ybot,
|
||||||
|
w, FALSE);
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvaluex, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvaluey, -1));
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s box size is %d x %d\n",
|
TxPrintf("%s box size is %s x %s\n",
|
||||||
(refEdit) ? "Edit" : "Root",
|
(refEdit) ? "Edit" : "Root",
|
||||||
boxptr->r_xtop - boxptr->r_xbot,
|
boxvaluex, boxvaluey);
|
||||||
boxptr->r_ytop - boxptr->r_ybot);
|
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -973,14 +998,22 @@ CmdBox(
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
{
|
{
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
char *boxvalues = (char *)Tcl_Alloc(50);
|
Tcl_Obj *tobj;
|
||||||
sprintf(boxvalues, "%d %d",
|
#endif
|
||||||
boxptr->r_xbot, boxptr->r_ybot);
|
char *boxvaluex, *boxvaluey;
|
||||||
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
boxvaluex = DBWPrintValue(boxptr->r_xbot, w, TRUE);
|
||||||
|
boxvaluey = DBWPrintValue(boxptr->r_ybot, w, FALSE);
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvaluex, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvaluey, -1));
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s box lower-left corner at (%d, %d)\n",
|
TxPrintf("%s box lower-left corner at (%s, %s)\n",
|
||||||
(refEdit) ? "Edit" : "Root",
|
(refEdit) ? "Edit" : "Root",
|
||||||
boxptr->r_xbot, boxptr->r_ybot);
|
boxvaluex, boxvaluey);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1012,16 +1045,31 @@ CmdBox(
|
||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
{
|
{
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
char *boxvalues = (char *)Tcl_Alloc(50);
|
Tcl_Obj *tobj;
|
||||||
sprintf(boxvalues, "%d %d %d %d",
|
#endif
|
||||||
boxptr->r_xbot, boxptr->r_ybot,
|
char *boxvaluellx, *boxvaluelly;
|
||||||
boxptr->r_xtop, boxptr->r_ytop);
|
char *boxvalueurx, *boxvalueury;
|
||||||
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
|
||||||
|
boxvaluellx = DBWPrintValue(boxptr->r_xbot, w, TRUE);
|
||||||
|
boxvaluelly = DBWPrintValue(boxptr->r_ybot, w, FALSE);
|
||||||
|
boxvalueurx = DBWPrintValue(boxptr->r_xtop, w, TRUE);
|
||||||
|
boxvalueury = DBWPrintValue(boxptr->r_ytop, w, FALSE);
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvaluellx, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvaluelly, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvalueurx, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(boxvalueury, -1));
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s box coordinates (%d, %d) to (%d, %d)\n",
|
TxPrintf("%s box coordinates (%s, %s) to (%s, %s)\n",
|
||||||
(refEdit) ? "Edit" : "Root",
|
(refEdit) ? "Edit" : "Root",
|
||||||
boxptr->r_xbot, boxptr->r_ybot,
|
boxvaluellx, boxvaluelly, boxvalueurx, boxvalueury);
|
||||||
boxptr->r_xtop, boxptr->r_ytop);
|
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -117,12 +117,13 @@ bool cmdDumpParseArgs(char *cmdName, MagWindow *w, TxCommand *cmd, CellUse *dumm
|
||||||
#define CALMA_READ 19
|
#define CALMA_READ 19
|
||||||
#define CALMA_READONLY 20
|
#define CALMA_READONLY 20
|
||||||
#define CALMA_RESCALE 21
|
#define CALMA_RESCALE 21
|
||||||
#define CALMA_WARNING 22
|
#define CALMA_SAVEPATHS 22
|
||||||
#define CALMA_WRITE 23
|
#define CALMA_WARNING 23
|
||||||
#define CALMA_POLYS 24
|
#define CALMA_WRITE 24
|
||||||
#define CALMA_PATHS 25
|
#define CALMA_POLYS 25
|
||||||
#define CALMA_UNDEFINED 26
|
#define CALMA_PATHS 26
|
||||||
#define CALMA_UNIQUE 27
|
#define CALMA_UNDEFINED 27
|
||||||
|
#define CALMA_UNIQUE 28
|
||||||
|
|
||||||
#define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */
|
#define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */
|
||||||
|
|
||||||
|
|
@ -175,6 +176,7 @@ CmdCalma(
|
||||||
" into edit cell",
|
" into edit cell",
|
||||||
"readonly [yes|no] set cell as read-only and generate output from GDS file",
|
"readonly [yes|no] set cell as read-only and generate output from GDS file",
|
||||||
"rescale [yes|no] allow or disallow internal grid subdivision",
|
"rescale [yes|no] allow or disallow internal grid subdivision",
|
||||||
|
"savepaths [yes|no] save path centerlines as cell properties",
|
||||||
"warning [option] set warning information level",
|
"warning [option] set warning information level",
|
||||||
"write file output Calma GDS-II format to \"file\"\n"
|
"write file output Calma GDS-II format to \"file\"\n"
|
||||||
" for the window's root cell",
|
" for the window's root cell",
|
||||||
|
|
@ -738,6 +740,27 @@ CmdCalma(
|
||||||
CalmaSubcellPolygons = (unsigned char)option;
|
CalmaSubcellPolygons = (unsigned char)option;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case CALMA_SAVEPATHS:
|
||||||
|
if (cmd->tx_argc == 2)
|
||||||
|
{
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaRecordPaths));
|
||||||
|
#else
|
||||||
|
TxPrintf("Paths in GDS cells read from input file are%s recorded"
|
||||||
|
" as cell properties.\n",
|
||||||
|
(CalmaRecordPaths) ? " " : " not");
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (cmd->tx_argc != 3)
|
||||||
|
goto wrongNumArgs;
|
||||||
|
|
||||||
|
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
|
||||||
|
if (option < 0)
|
||||||
|
goto wrongNumArgs;
|
||||||
|
CalmaRecordPaths = (option < 4) ? FALSE : TRUE;
|
||||||
|
return;
|
||||||
|
|
||||||
case CALMA_NO_DUP:
|
case CALMA_NO_DUP:
|
||||||
if (cmd->tx_argc == 2)
|
if (cmd->tx_argc == 2)
|
||||||
{
|
{
|
||||||
|
|
@ -1300,7 +1323,7 @@ CmdCellname(
|
||||||
if (cellDef == (CellDef *) NULL)
|
if (cellDef == (CellDef *) NULL)
|
||||||
TxError("Unknown cell %s\n", cellname);
|
TxError("Unknown cell %s\n", cellname);
|
||||||
else
|
else
|
||||||
CmdDoProperty(cellDef, cmd, 3 + ((dolist) ? 1 : 0));
|
CmdDoProperty(cellDef, w, cmd, 3 + ((dolist) ? 1 : 0));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDX_DELETE:
|
case IDX_DELETE:
|
||||||
|
|
@ -2396,8 +2419,10 @@ CmdContact(
|
||||||
CCStruct ccs;
|
CCStruct ccs;
|
||||||
Rect area;
|
Rect area;
|
||||||
LinkedRect *lr = NULL;
|
LinkedRect *lr = NULL;
|
||||||
int cmdContactFunc(Tile *tile, CCStruct *ccs); /* Forward declaration */
|
|
||||||
int cmdContactEraseFunc(Tile *tile, LinkedRect **lr); /* Forward declaration */
|
/* Forward declarations */
|
||||||
|
int cmdContactFunc(Tile *tile, TileType dinfo, CCStruct *ccs);
|
||||||
|
int cmdContactEraseFunc(Tile *tile, TileType dinfo, LinkedRect **lr);
|
||||||
|
|
||||||
windCheckOnlyWindow(&w, DBWclientID);
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
if ((w == (MagWindow *) NULL) || (w->w_client != DBWclientID))
|
if ((w == (MagWindow *) NULL) || (w->w_client != DBWclientID))
|
||||||
|
|
@ -2531,11 +2556,14 @@ CmdContact(
|
||||||
int
|
int
|
||||||
cmdContactFunc(
|
cmdContactFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
CCStruct *ccs)
|
CCStruct *ccs)
|
||||||
{
|
{
|
||||||
TileType stype;
|
TileType stype;
|
||||||
TileTypeBitMask smask;
|
TileTypeBitMask smask;
|
||||||
int cmdContactFunc2(Tile *tile, CCStruct *ccs); /* Forward declaration */
|
|
||||||
|
/* Forward declaration */
|
||||||
|
int cmdContactFunc2(Tile *tile, TileType dinfo, CCStruct *ccs);
|
||||||
|
|
||||||
TiToRect(tile, &ccs->area);
|
TiToRect(tile, &ccs->area);
|
||||||
GeoClip(&ccs->area, &ccs->clip);
|
GeoClip(&ccs->area, &ccs->clip);
|
||||||
|
|
@ -2545,14 +2573,16 @@ cmdContactFunc(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
TTMaskSetOnlyType(&smask, stype);
|
TTMaskSetOnlyType(&smask, stype);
|
||||||
DBSrPaintArea((Tile *) NULL, ccs->rootDef->cd_planes[DBPlane(stype)],
|
DBSrPaintNMArea((Tile *)NULL, ccs->rootDef->cd_planes[DBPlane(stype)],
|
||||||
&ccs->area, &smask, cmdContactFunc2, (ClientData)ccs);
|
TiGetTypeExact(tile) | dinfo, &ccs->area, &smask,
|
||||||
|
cmdContactFunc2, (ClientData)ccs);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cmdContactFunc2(
|
cmdContactFunc2(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
CCStruct *ccs)
|
CCStruct *ccs)
|
||||||
{
|
{
|
||||||
LinkedRect *newlr;
|
LinkedRect *newlr;
|
||||||
|
|
@ -2575,6 +2605,7 @@ cmdContactFunc2(
|
||||||
int
|
int
|
||||||
cmdContactEraseFunc(
|
cmdContactEraseFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
LinkedRect **lr)
|
LinkedRect **lr)
|
||||||
{
|
{
|
||||||
LinkedRect *newlr;
|
LinkedRect *newlr;
|
||||||
|
|
@ -2828,14 +2859,15 @@ CmdCorner(
|
||||||
TileTypeBitMask maskBits;
|
TileTypeBitMask maskBits;
|
||||||
Rect editBox;
|
Rect editBox;
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
extern int cmdCornerFunc(Tile *tile, TreeContext *cxp);
|
|
||||||
bool hasErr = FALSE;
|
bool hasErr = FALSE;
|
||||||
int locargc = cmd->tx_argc;
|
int locargc = cmd->tx_argc;
|
||||||
|
|
||||||
extern int cmdBevelFunc(Tile *tile, TreeContext *cxp);
|
|
||||||
bool dobevel = FALSE;
|
bool dobevel = FALSE;
|
||||||
NMCornerPath cmdPathList;
|
NMCornerPath cmdPathList;
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
extern int cmdCornerFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
|
||||||
|
extern int cmdBevelFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
|
||||||
|
|
||||||
if (cmd->tx_argc < 3 || cmd->tx_argc > 5)
|
if (cmd->tx_argc < 3 || cmd->tx_argc > 5)
|
||||||
{
|
{
|
||||||
TxError("Usage: %s direction1 direction2 [layers]\n",
|
TxError("Usage: %s direction1 direction2 [layers]\n",
|
||||||
|
|
@ -3030,6 +3062,7 @@ CmdCorner(
|
||||||
int
|
int
|
||||||
cmdCornerFunc(
|
cmdCornerFunc(
|
||||||
Tile *tile, /* Tile to fill with. */
|
Tile *tile, /* Tile to fill with. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
TreeContext *cxp) /* Describes state of search. */
|
TreeContext *cxp) /* Describes state of search. */
|
||||||
{
|
{
|
||||||
Rect r1, r2, r3;
|
Rect r1, r2, r3;
|
||||||
|
|
@ -3196,6 +3229,7 @@ AddNewPoint(
|
||||||
int
|
int
|
||||||
cmdBevelFunc(
|
cmdBevelFunc(
|
||||||
Tile *tile, /* Tile to fill with. */
|
Tile *tile, /* Tile to fill with. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
TreeContext *cxp) /* Describes state of search. */
|
TreeContext *cxp) /* Describes state of search. */
|
||||||
{
|
{
|
||||||
Rect r1, r2, r3;
|
Rect r1, r2, r3;
|
||||||
|
|
@ -4585,6 +4619,7 @@ CmdDrc(
|
||||||
int
|
int
|
||||||
cmdDropPaintCell(
|
cmdDropPaintCell(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
TreeContext *cxp)
|
TreeContext *cxp)
|
||||||
{
|
{
|
||||||
CellDef *cellDef = cxp->tc_scx->scx_use->cu_def;
|
CellDef *cellDef = cxp->tc_scx->scx_use->cu_def;
|
||||||
|
|
@ -4593,7 +4628,7 @@ cmdDropPaintCell(
|
||||||
TileType type;
|
TileType type;
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
||||||
if (SplitSide(tile))
|
if (dinfo & TT_SIDE)
|
||||||
type = SplitRightType(tile);
|
type = SplitRightType(tile);
|
||||||
else
|
else
|
||||||
type = SplitLeftType(tile);
|
type = SplitLeftType(tile);
|
||||||
|
|
@ -4626,6 +4661,7 @@ cmdDropPaintCell(
|
||||||
int
|
int
|
||||||
cmdDropFunc(
|
cmdDropFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
ClientData clientData)
|
ClientData clientData)
|
||||||
{
|
{
|
||||||
TileTypeBitMask tMask, *lMask = (TileTypeBitMask *)clientData;
|
TileTypeBitMask tMask, *lMask = (TileTypeBitMask *)clientData;
|
||||||
|
|
@ -4636,7 +4672,7 @@ cmdDropFunc(
|
||||||
scx.scx_use = EditCellUse;
|
scx.scx_use = EditCellUse;
|
||||||
scx.scx_trans = GeoIdentityTransform;
|
scx.scx_trans = GeoIdentityTransform;
|
||||||
|
|
||||||
if (SplitSide(tile))
|
if (dinfo & TT_SIDE)
|
||||||
type = SplitRightType(tile);
|
type = SplitRightType(tile);
|
||||||
else
|
else
|
||||||
type = SplitLeftType(tile);
|
type = SplitLeftType(tile);
|
||||||
|
|
@ -4978,15 +5014,20 @@ cmdDumpParseArgs(
|
||||||
bbox = def->cd_bbox;
|
bbox = def->cd_bbox;
|
||||||
if (def->cd_flags & CDFIXEDBBOX)
|
if (def->cd_flags & CDFIXEDBBOX)
|
||||||
{
|
{
|
||||||
char *propvalue;
|
PropertyRecord *proprec;
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &found);
|
proprec = DBPropGet(def, "FIXED_BBOX", &found);
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||||
&bbox.r_xtop, &bbox.r_ytop) != 4)
|
(proprec->prop_len == 4))
|
||||||
bbox = def->cd_bbox;
|
{
|
||||||
|
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||||
|
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||||
|
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||||
|
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -925,11 +925,14 @@ cmdExpandFunc(
|
||||||
#define DOALL 1
|
#define DOALL 1
|
||||||
#define DOCAPACITANCE 2
|
#define DOCAPACITANCE 2
|
||||||
#define DOCOUPLING 3
|
#define DOCOUPLING 3
|
||||||
#define DOLENGTH 4
|
#define DOEXTRESIST 4
|
||||||
#define DOLOCAL 5
|
#define DOLENGTH 5
|
||||||
#define DORESISTANCE 6
|
#define DOLOCAL 6
|
||||||
#define DOLABELCHECK 7
|
#define DORESISTANCE 7
|
||||||
#define DOALIASES 8
|
#define DOLABELCHECK 8
|
||||||
|
#define DOALIASES 9
|
||||||
|
#define DOUNIQUE 10
|
||||||
|
#define DOEXTRESIST2 11
|
||||||
|
|
||||||
#define LENCLEAR 0
|
#define LENCLEAR 0
|
||||||
#define LENDRIVER 1
|
#define LENDRIVER 1
|
||||||
|
|
@ -972,11 +975,14 @@ CmdExtract(
|
||||||
"all all options",
|
"all all options",
|
||||||
"capacitance extract substrate capacitance",
|
"capacitance extract substrate capacitance",
|
||||||
"coupling extract coupling capacitance",
|
"coupling extract coupling capacitance",
|
||||||
|
"extresist extract resistance",
|
||||||
"length compute driver-receiver pathlengths",
|
"length compute driver-receiver pathlengths",
|
||||||
"local put all generated files in the current directory",
|
"local put all generated files in the current directory",
|
||||||
"resistance estimate resistance",
|
"lumped estimate lumped resistance",
|
||||||
"labelcheck check for connections through sticky labels",
|
"labelcheck check for connections through sticky labels",
|
||||||
"aliases output all net name aliases",
|
"aliases output all net name aliases",
|
||||||
|
"unique ensure unique node names during extraction",
|
||||||
|
"resistance extract resistance (same as \"do extresist\")",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
static const char * const cmdExtLength[] =
|
static const char * const cmdExtLength[] =
|
||||||
|
|
@ -1120,12 +1126,13 @@ CmdExtract(
|
||||||
}
|
}
|
||||||
else if (argc == 2)
|
else if (argc == 2)
|
||||||
{
|
{
|
||||||
|
char *halodisp;
|
||||||
|
halodisp = DBWPrintValue(ExtCurStyle->exts_sideCoupleHalo,
|
||||||
|
w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_Obj *tobj;
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(halodisp, -1));
|
||||||
tobj = Tcl_NewIntObj(ExtCurStyle->exts_sideCoupleHalo);
|
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
|
||||||
#else
|
#else
|
||||||
TxPrintf("Side overlap halo is %d\n", ExtCurStyle->exts_sideCoupleHalo);
|
TxPrintf("Side overlap halo is %s\n", halodisp);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1150,12 +1157,12 @@ CmdExtract(
|
||||||
}
|
}
|
||||||
else if (argc == 2)
|
else if (argc == 2)
|
||||||
{
|
{
|
||||||
|
char *stepdisp;
|
||||||
|
stepdisp = DBWPrintValue(ExtCurStyle->exts_stepSize, w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_Obj *tobj;
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(stepdisp, -1));
|
||||||
tobj = Tcl_NewIntObj(ExtCurStyle->exts_stepSize);
|
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
|
||||||
#else
|
#else
|
||||||
TxPrintf("Extraction step size is %d\n", ExtCurStyle->exts_stepSize);
|
TxPrintf("Extraction step size is %s\n", stepdisp);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1277,9 +1284,11 @@ CmdExtract(
|
||||||
TxPrintf("%s capacitance\n", OPTSET(EXT_DOCAPACITANCE));
|
TxPrintf("%s capacitance\n", OPTSET(EXT_DOCAPACITANCE));
|
||||||
TxPrintf("%s coupling\n", OPTSET(EXT_DOCOUPLING));
|
TxPrintf("%s coupling\n", OPTSET(EXT_DOCOUPLING));
|
||||||
TxPrintf("%s length\n", OPTSET(EXT_DOLENGTH));
|
TxPrintf("%s length\n", OPTSET(EXT_DOLENGTH));
|
||||||
TxPrintf("%s resistance\n", OPTSET(EXT_DORESISTANCE));
|
TxPrintf("%s lumped R\n", OPTSET(EXT_DORESISTANCE));
|
||||||
TxPrintf("%s label check\n", OPTSET(EXT_DOLABELCHECK));
|
TxPrintf("%s label check\n", OPTSET(EXT_DOLABELCHECK));
|
||||||
TxPrintf("%s aliases\n", OPTSET(EXT_DOALIASES));
|
TxPrintf("%s aliases\n", OPTSET(EXT_DOALIASES));
|
||||||
|
TxPrintf("%s unique\n", OPTSET(EXT_DOUNIQUE));
|
||||||
|
TxPrintf("%s resistance (extresist)\n", OPTSET(EXT_DOEXTRESIST));
|
||||||
return;
|
return;
|
||||||
#undef OPTSET
|
#undef OPTSET
|
||||||
}
|
}
|
||||||
|
|
@ -1309,6 +1318,9 @@ CmdExtract(
|
||||||
case DORESISTANCE: option = EXT_DORESISTANCE; break;
|
case DORESISTANCE: option = EXT_DORESISTANCE; break;
|
||||||
case DOLABELCHECK: option = EXT_DOLABELCHECK; break;
|
case DOLABELCHECK: option = EXT_DOLABELCHECK; break;
|
||||||
case DOALIASES: option = EXT_DOALIASES; break;
|
case DOALIASES: option = EXT_DOALIASES; break;
|
||||||
|
case DOUNIQUE: option = EXT_DOUNIQUE; break;
|
||||||
|
case DOEXTRESIST:
|
||||||
|
case DOEXTRESIST2: option = EXT_DOEXTRESIST; break;
|
||||||
case DOLOCAL:
|
case DOLOCAL:
|
||||||
/* "extract do local" and "extract no local" are kept for
|
/* "extract do local" and "extract no local" are kept for
|
||||||
* backwards compatibility, but now effectively implement
|
* backwards compatibility, but now effectively implement
|
||||||
|
|
|
||||||
|
|
@ -102,15 +102,17 @@ struct cmdFPArg
|
||||||
int
|
int
|
||||||
feedPolyFunc(
|
feedPolyFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
struct cmdFPArg *arg)
|
struct cmdFPArg *arg)
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
TiToRect(tile, &area);
|
TiToRect(tile, &area);
|
||||||
|
|
||||||
|
/* (NOTE: Preserve information about the geometry of a diagonal tile) */
|
||||||
DBWFeedbackAdd(&area, arg->text, arg->def, FEEDMAGNIFY,
|
DBWFeedbackAdd(&area, arg->text, arg->def, FEEDMAGNIFY,
|
||||||
arg->style |
|
arg->style |
|
||||||
(TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
|
((TiGetTypeExact(tile) | dinfo) &
|
||||||
/* (preserve information about the geometry of a diagonal tile) */
|
(TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -513,7 +515,9 @@ CmdFill(
|
||||||
TileTypeBitMask maskBits;
|
TileTypeBitMask maskBits;
|
||||||
Rect editBox;
|
Rect editBox;
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
extern int cmdFillFunc(Tile *tile, TreeContext *cxp);
|
|
||||||
|
/* Forward declaration */
|
||||||
|
extern int cmdFillFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
|
||||||
|
|
||||||
if (cmd->tx_argc < 2 || cmd->tx_argc > 3)
|
if (cmd->tx_argc < 2 || cmd->tx_argc > 3)
|
||||||
{
|
{
|
||||||
|
|
@ -603,11 +607,16 @@ CmdFill(
|
||||||
* paint here it may mess up the search. Instead, the procedures
|
* paint here it may mess up the search. Instead, the procedures
|
||||||
* save areas on a list. The list is post-processed to paint the
|
* save areas on a list. The list is post-processed to paint the
|
||||||
* areas once the search is finished.
|
* areas once the search is finished.
|
||||||
|
*
|
||||||
|
* Split tile information is unused because there is no obvious
|
||||||
|
* meaning to "filling" from a split tile, although probably reasonable
|
||||||
|
* methods could be worked out.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
cmdFillFunc(
|
cmdFillFunc(
|
||||||
Tile *tile, /* Tile to fill with. */
|
Tile *tile, /* Tile to fill with. */
|
||||||
|
TileType dinfo, /* Split tile information (unused) */
|
||||||
TreeContext *cxp) /* Describes state of search. */
|
TreeContext *cxp) /* Describes state of search. */
|
||||||
{
|
{
|
||||||
Rect r1, r2;
|
Rect r1, r2;
|
||||||
|
|
@ -1210,7 +1219,7 @@ CmdGetnode(
|
||||||
TxError("Put the cursor in a layout window\n");
|
TxError("Put the cursor in a layout window\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if( is_fast == TRUE )
|
if (is_fast == TRUE)
|
||||||
{
|
{
|
||||||
SimRecomputeSel = TRUE;
|
SimRecomputeSel = TRUE;
|
||||||
SimGetsnode();
|
SimGetsnode();
|
||||||
|
|
@ -1218,7 +1227,8 @@ CmdGetnode(
|
||||||
else
|
else
|
||||||
SimGetnode();
|
SimGetnode();
|
||||||
|
|
||||||
if (SimGetnodeAlias) { /* "erase" the hash table */
|
if (SimGetnodeAlias) /* "erase" the hash table */
|
||||||
|
{
|
||||||
HashKill(&SimGNAliasTbl);
|
HashKill(&SimGNAliasTbl);
|
||||||
HashInit(&SimGNAliasTbl, 120, STRINGS);
|
HashInit(&SimGNAliasTbl, 120, STRINGS);
|
||||||
}
|
}
|
||||||
|
|
@ -1604,7 +1614,7 @@ CmdFindNetProc(
|
||||||
int pnum, xpos, ypos;
|
int pnum, xpos, ypos;
|
||||||
char *xstr, *ystr;
|
char *xstr, *ystr;
|
||||||
bool locvalid = FALSE, usefound = TRUE;
|
bool locvalid = FALSE, usefound = TRUE;
|
||||||
TileType ttype;
|
TileType ttype, dinfo = (TileType)0;
|
||||||
|
|
||||||
scx.scx_use = use;
|
scx.scx_use = use;
|
||||||
scx.scx_trans = GeoIdentityTransform;
|
scx.scx_trans = GeoIdentityTransform;
|
||||||
|
|
@ -1642,6 +1652,7 @@ CmdFindNetProc(
|
||||||
|
|
||||||
if ((xstr = strchr(s, '_')) != NULL)
|
if ((xstr = strchr(s, '_')) != NULL)
|
||||||
{
|
{
|
||||||
|
char *hashpos;
|
||||||
bool isNeg = FALSE;
|
bool isNeg = FALSE;
|
||||||
|
|
||||||
/* The characters up to the leading '_' should match one of the */
|
/* The characters up to the leading '_' should match one of the */
|
||||||
|
|
@ -1685,6 +1696,17 @@ CmdFindNetProc(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Format variant used for node regions where a split tile
|
||||||
|
* occupies the root position of the node but the tile type
|
||||||
|
* belonging to the node is on the right side of the tile,
|
||||||
|
* not at the location encoded into the name. An 'x' is
|
||||||
|
* added before the final hash sign.
|
||||||
|
*/
|
||||||
|
hashpos = strrchr(s, '#');
|
||||||
|
if (hashpos != NULL)
|
||||||
|
if (*(hashpos - 1) == 'r')
|
||||||
|
dinfo = TT_DIAGONAL | TT_SIDE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1707,17 +1729,23 @@ checklocal:
|
||||||
|
|
||||||
if (locvalid == TRUE)
|
if (locvalid == TRUE)
|
||||||
{
|
{
|
||||||
int findTile(Tile *tile, TileType *rtype);
|
int findTile(Tile *tile, TileType dinfo, TileAndDinfo *tad);
|
||||||
CellDef *targetdef = use->cu_def;
|
CellDef *targetdef = use->cu_def;
|
||||||
Plane *plane = targetdef->cd_planes[pnum];
|
Plane *plane = targetdef->cd_planes[pnum];
|
||||||
|
TileAndDinfo tad;
|
||||||
ttype = TT_SPACE; /* revert to space in case of failure */
|
|
||||||
|
|
||||||
/* Find the tile type of the tile at the specified point which */
|
/* Find the tile type of the tile at the specified point which */
|
||||||
/* exists on the plane pnum. */
|
/* exists on the plane pnum. Note that in the case of a split */
|
||||||
|
/* tile region marked with "x" in the name, it does not work to */
|
||||||
|
/* call DBSrPainNMArea() because the diagonal position is not */
|
||||||
|
/* known. findTile() determines the proper type and leaves it */
|
||||||
|
/* in the tad.tad_dinfo record. */
|
||||||
|
|
||||||
|
tad.tad_tile = (Tile *)NULL;
|
||||||
|
tad.tad_dinfo = dinfo;
|
||||||
DBSrPaintArea(NULL, plane, &localrect, &DBAllTypeBits, findTile,
|
DBSrPaintArea(NULL, plane, &localrect, &DBAllTypeBits, findTile,
|
||||||
(ClientData) &ttype);
|
(ClientData) &tad);
|
||||||
|
ttype = tad.tad_dinfo & TT_LEFTMASK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1841,20 +1869,31 @@ CmdGoto(
|
||||||
int
|
int
|
||||||
findTile(
|
findTile(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
TileType *rtype)
|
TileType dinfo, /* (unused) */
|
||||||
|
TileAndDinfo *tad)
|
||||||
{
|
{
|
||||||
TileType ttype;
|
TileType ttype;
|
||||||
|
|
||||||
|
/* Note that since all types are being searched, a split
|
||||||
|
* tile would cause the callback to be called twice. But
|
||||||
|
* this routine will pick the indicated side from the
|
||||||
|
* "tad" structure and return 1 so it does not get called
|
||||||
|
* a second time. The "dinfo" value passed is irrelevant.
|
||||||
|
*/
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
if (SplitSide(tile))
|
if (tad->tad_dinfo & TT_SIDE)
|
||||||
ttype = SplitRightType(tile);
|
ttype = SplitRightType(tile);
|
||||||
else
|
else
|
||||||
ttype = SplitLeftType(tile);
|
ttype = SplitLeftType(tile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ttype = TiGetTypeExact(tile);
|
ttype = TiGetTypeExact(tile);
|
||||||
*rtype = ttype;
|
|
||||||
|
/* Leave the tile type in tad_dinfo before returning */
|
||||||
|
tad->tad_dinfo = ttype;
|
||||||
|
|
||||||
return 1; /* stop search */
|
return 1; /* stop search */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
585
commands/CmdLQ.c
585
commands/CmdLQ.c
|
|
@ -45,9 +45,8 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
||||||
#include "utils/undo.h"
|
#include "utils/undo.h"
|
||||||
#include "select/select.h"
|
#include "select/select.h"
|
||||||
#include "netmenu/netmenu.h"
|
#include "netmenu/netmenu.h"
|
||||||
|
|
||||||
/* C99 compat */
|
|
||||||
#include "cif/cif.h"
|
#include "cif/cif.h"
|
||||||
|
#include "cif/CIFint.h"
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
|
|
||||||
|
|
@ -2296,6 +2295,8 @@ parsepositions:
|
||||||
editDef->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
|
editDef->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PROPERTY_TYPE_COMPAT 4 /* Last entry in cmdPropertyType */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -2319,47 +2320,449 @@ parsepositions:
|
||||||
void
|
void
|
||||||
CmdDoProperty(
|
CmdDoProperty(
|
||||||
CellDef *def,
|
CellDef *def,
|
||||||
|
MagWindow *w,
|
||||||
TxCommand *cmd,
|
TxCommand *cmd,
|
||||||
int argstart)
|
int argstart)
|
||||||
{
|
{
|
||||||
int printPropertiesFunc();
|
PropertyRecord *proprec;
|
||||||
char *value;
|
char *value;
|
||||||
bool propfound;
|
bool propfound, dolist;
|
||||||
|
int proptype, proplen, propvalue, i;
|
||||||
|
dlong dvalue;
|
||||||
int locargc = cmd->tx_argc - argstart + 1;
|
int locargc = cmd->tx_argc - argstart + 1;
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
Tcl_Obj *tobj;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
int printPropertiesFunc();
|
||||||
|
int printPlanePropFunc();
|
||||||
|
|
||||||
|
/* These should match the property codes in database.h.in, except
|
||||||
|
* for "compat" which must come at the end.
|
||||||
|
*/
|
||||||
|
static const char * const cmdPropertyType[] = {
|
||||||
|
"string", "integer", "dimension", "double", "plane", "compat", NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* If the first keyword is "list", then set dolist and increment
|
||||||
|
* the starting argument position.
|
||||||
|
*/
|
||||||
|
dolist = FALSE;
|
||||||
|
if (locargc > 1)
|
||||||
|
{
|
||||||
|
if (!strcmp(cmd->tx_argv[argstart], "list"))
|
||||||
|
{
|
||||||
|
dolist = TRUE;
|
||||||
|
locargc--;
|
||||||
|
argstart++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If a property type is given, parse it and then strip it from
|
||||||
|
* the arguments list.
|
||||||
|
*/
|
||||||
|
if (locargc > 1)
|
||||||
|
{
|
||||||
|
proptype = Lookup(cmd->tx_argv[argstart], cmdPropertyType);
|
||||||
|
if (proptype >= 0)
|
||||||
|
{
|
||||||
|
if (proptype != PROPERTY_TYPE_COMPAT)
|
||||||
|
{
|
||||||
|
locargc--;
|
||||||
|
argstart++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
proptype = PROPERTY_TYPE_STRING; /* default */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
proptype = PROPERTY_TYPE_STRING; /* default */
|
||||||
|
|
||||||
if (locargc == 1)
|
if (locargc == 1)
|
||||||
{
|
{
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
Tcl_Obj *tobj;
|
||||||
|
/* Create an empty list for the interpreter result; the
|
||||||
|
* printPropertiesFunc() function will append values to it.
|
||||||
|
*/
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
|
#endif
|
||||||
/* print all properties and their values */
|
/* print all properties and their values */
|
||||||
DBPropEnum(def, printPropertiesFunc, NULL);
|
DBPropEnum(def, printPropertiesFunc, (ClientData)w);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (locargc == 2)
|
else if (locargc == 2)
|
||||||
{
|
{
|
||||||
/* print the value of the indicated property */
|
/* If the property type was "compat", then give the state of the
|
||||||
value = (char *)DBPropGet(def, cmd->tx_argv[argstart], &propfound);
|
* compatibility flag and return.
|
||||||
if (propfound)
|
*/
|
||||||
|
if (proptype == PROPERTY_TYPE_COMPAT)
|
||||||
|
{
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetResult(magicinterp, value, NULL);
|
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(DBPropCompat));
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s", value);
|
TxPrintf("%s\n", (DBPropCompat == TRUE) ? "True" : "False");
|
||||||
#endif
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print the value of the indicated property */
|
||||||
|
proprec = (PropertyRecord *)DBPropGet(def, cmd->tx_argv[argstart], &propfound);
|
||||||
|
if (propfound)
|
||||||
|
{
|
||||||
|
proptype = proprec->prop_type;
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
switch (proptype)
|
||||||
|
{
|
||||||
|
case PROPERTY_TYPE_STRING:
|
||||||
|
Tcl_SetResult(magicinterp, proprec->prop_value.prop_string, NULL);
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_INTEGER:
|
||||||
|
if (proprec->prop_len == 1)
|
||||||
|
Tcl_SetObjResult(magicinterp,
|
||||||
|
Tcl_NewIntObj(proprec->prop_value.prop_integer[0]));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewIntObj(
|
||||||
|
proprec->prop_value.prop_integer[i]));
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DIMENSION:
|
||||||
|
if (proprec->prop_len == 1)
|
||||||
|
Tcl_SetResult(magicinterp,
|
||||||
|
DBWPrintValue(proprec->prop_value.prop_integer[0],
|
||||||
|
w, TRUE), NULL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj(DBWPrintValue(
|
||||||
|
proprec->prop_value.prop_integer[i], w,
|
||||||
|
((i % 2) == 0) ? TRUE : FALSE), -1));
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_PLANE:
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
||||||
|
proprec->prop_value.prop_plane,
|
||||||
|
&TiPlaneRect, &CIFSolidBits, printPlanePropFunc,
|
||||||
|
(ClientData)tobj);
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DOUBLE:
|
||||||
|
if (proprec->prop_len == 1)
|
||||||
|
Tcl_SetObjResult(magicinterp,
|
||||||
|
Tcl_NewWideIntObj((Tcl_WideInt)
|
||||||
|
proprec->prop_value.prop_double[0]));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewWideIntObj((Tcl_WideInt)
|
||||||
|
proprec->prop_value.prop_double[i]));
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
switch (proptype)
|
||||||
|
{
|
||||||
|
case PROPERTY_TYPE_STRING:
|
||||||
|
TxPrintf("%s\n", proprec->prop_value.prop_string);
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_INTEGER:
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
TxPrintf("%d ", proprec->prop_value.prop_integer[i]);
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DIMENSION:
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
TxPrintf("%s ", DBWPrintValue(
|
||||||
|
proprec->prop_value.prop_integer[i], w,
|
||||||
|
((i % 2) == 0) ? TRUE : FALSE);
|
||||||
|
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_PLANE:
|
||||||
|
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
||||||
|
proprec->prop_value.prop_plane,
|
||||||
|
&TiPlaneRect, &CIFSolidBits, printPlanePropFunc,
|
||||||
|
(ClientData)NULL);
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DOUBLE:
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
TxPrintf( "%"DLONG_PREFIX"d",
|
||||||
|
proprec->prop_value.prop_double[i]);
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
/* If the command was "cellname list property ...", then */
|
/* If the command was "cellname list property ...", then */
|
||||||
/* just return NULL if the property was not found. */
|
/* just return NULL if the property was not found. */
|
||||||
if (strcmp(cmd->tx_argv[1], "list"))
|
if (!dolist)
|
||||||
#endif
|
#endif
|
||||||
TxError("Property name \"%s\" is not defined\n", cmd->tx_argv[1]);
|
TxError("Property name \"%s\" is not defined\n", cmd->tx_argv[argstart]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (locargc == 3)
|
else if (locargc >= 3)
|
||||||
{
|
{
|
||||||
|
/* If the property type was "compat", then set the state of the
|
||||||
|
* compatibility flag and return.
|
||||||
|
*/
|
||||||
|
if (proptype == PROPERTY_TYPE_COMPAT)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
static const char * const cmdPropYesNo[] = {
|
||||||
|
"disable", "no", "false", "off", "0",
|
||||||
|
"enable", "yes", "true", "on", "1", 0 };
|
||||||
|
idx = Lookup(cmd->tx_argv[2], cmdPropYesNo);
|
||||||
|
if (idx < 0)
|
||||||
|
{
|
||||||
|
TxError("Unknown property compat option \"%s\"\n", cmd->tx_argv[2]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DBPropCompat = (idx <= 4) ? FALSE : TRUE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Catch the following known reserved keywords and cast them to the
|
||||||
|
* expected property type. If any property type was already given
|
||||||
|
* to the command, it is overridden. This ensures that the reserved
|
||||||
|
* keyword functions work correctly.
|
||||||
|
*
|
||||||
|
* GDS_START, GDS_END: PROPERTY_TYPE_DOUBLE
|
||||||
|
* MASKHINTS_*: PROPERTY_TYPE_PLANE
|
||||||
|
* FIXED_BBOX: PROPERTY_TYPE_DIMENSION
|
||||||
|
*/
|
||||||
|
if (!strcmp(cmd->tx_argv[argstart], "GDS_START"))
|
||||||
|
proptype = PROPERTY_TYPE_DOUBLE;
|
||||||
|
else if (!strcmp(cmd->tx_argv[argstart], "GDS_END"))
|
||||||
|
proptype = PROPERTY_TYPE_DOUBLE;
|
||||||
|
else if (!strcmp(cmd->tx_argv[argstart], "GDS_FILE"))
|
||||||
|
proptype = PROPERTY_TYPE_STRING;
|
||||||
|
else if (!strcmp(cmd->tx_argv[argstart], "FIXED_BBOX"))
|
||||||
|
proptype = PROPERTY_TYPE_DIMENSION;
|
||||||
|
else if (!strcmp(cmd->tx_argv[argstart], "OBS_BBOX"))
|
||||||
|
proptype = PROPERTY_TYPE_DIMENSION;
|
||||||
|
else if (!strncmp(cmd->tx_argv[argstart], "MASKHINTS_", 10))
|
||||||
|
proptype = PROPERTY_TYPE_PLANE;
|
||||||
|
|
||||||
if (strlen(cmd->tx_argv[argstart + 1]) == 0)
|
if (strlen(cmd->tx_argv[argstart + 1]) == 0)
|
||||||
DBPropPut(def, cmd->tx_argv[argstart], NULL);
|
DBPropPut(def, cmd->tx_argv[argstart], NULL);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
value = StrDup((char **)NULL, cmd->tx_argv[argstart + 1]);
|
if (proptype == PROPERTY_TYPE_STRING)
|
||||||
DBPropPut(def, cmd->tx_argv[argstart], value);
|
{
|
||||||
|
proplen = strlen(cmd->tx_argv[argstart + 1]);
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) -
|
||||||
|
7 + proplen);
|
||||||
|
proprec->prop_type = proptype;
|
||||||
|
proprec->prop_len = proplen;
|
||||||
|
strcpy(proprec->prop_value.prop_string, cmd->tx_argv[argstart + 1]);
|
||||||
|
}
|
||||||
|
else /* All non-string properties */
|
||||||
|
{
|
||||||
|
Plane *plane;
|
||||||
|
Rect r;
|
||||||
|
|
||||||
|
/* Two choices: If locargc == 3 then all values are in one
|
||||||
|
* argument. If locargc > 3, then parse each argument as a
|
||||||
|
* separate value.
|
||||||
|
*/
|
||||||
|
if (locargc > 3)
|
||||||
|
{
|
||||||
|
proplen = locargc - 2;
|
||||||
|
if (proptype == PROPERTY_TYPE_DOUBLE)
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||||
|
(proplen - 1)*sizeof(dlong));
|
||||||
|
else if (proptype == PROPERTY_TYPE_PLANE)
|
||||||
|
{
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||||
|
plane = DBNewPlane((ClientData)TT_SPACE);
|
||||||
|
proprec->prop_value.prop_plane = plane;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||||
|
(proplen - 2)*sizeof(int));
|
||||||
|
proprec->prop_type = proptype;
|
||||||
|
proprec->prop_len = proplen;
|
||||||
|
|
||||||
|
for (i = 1; i < locargc - 1; i++)
|
||||||
|
{
|
||||||
|
if (proptype == PROPERTY_TYPE_INTEGER)
|
||||||
|
{
|
||||||
|
if (sscanf(cmd->tx_argv[argstart + i], "%d",
|
||||||
|
&propvalue) == 1)
|
||||||
|
proprec->prop_value.prop_integer[i - 1] = propvalue;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TxError("Unable to parse value \"%s\" as an integer\n",
|
||||||
|
cmd->tx_argv[argstart + i]);
|
||||||
|
proprec->prop_value.prop_integer[i - 1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (proptype == PROPERTY_TYPE_DOUBLE)
|
||||||
|
{
|
||||||
|
if (sscanf(cmd->tx_argv[argstart + i], "%"DLONG_PREFIX"d",
|
||||||
|
&dvalue) == 1)
|
||||||
|
proprec->prop_value.prop_double[i - 1] = dvalue;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TxError("Unable to parse value \"%s\" as an integer\n",
|
||||||
|
cmd->tx_argv[argstart + i]);
|
||||||
|
proprec->prop_value.prop_double[i - 1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (proptype == PROPERTY_TYPE_PLANE)
|
||||||
|
{
|
||||||
|
propvalue = cmdParseCoord(w, cmd->tx_argv[argstart + i],
|
||||||
|
FALSE, ((i % 2) == 0) ? FALSE : TRUE);
|
||||||
|
switch ((i - 1) % 4)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
r.r_xbot = propvalue;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
r.r_ybot = propvalue;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
r.r_xtop = propvalue;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
r.r_ytop = propvalue;
|
||||||
|
DBPaintPlane(plane, &r, CIFPaintTable,
|
||||||
|
(PaintUndoInfo *)NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* PROPERTY_TYPE_DIMENSION */
|
||||||
|
{
|
||||||
|
propvalue = cmdParseCoord(w, cmd->tx_argv[argstart + i],
|
||||||
|
FALSE, ((i % 2) == 0) ? FALSE : TRUE);
|
||||||
|
proprec->prop_value.prop_integer[i - 1] = propvalue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Make two passes through the argument string, once to get
|
||||||
|
* the valid number of arguments, then again to parse the
|
||||||
|
* values, once the property record has been allocated
|
||||||
|
*/
|
||||||
|
if (proptype == PROPERTY_TYPE_PLANE)
|
||||||
|
{
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||||
|
plane = DBNewPlane((ClientData)TT_SPACE);
|
||||||
|
proprec->prop_value.prop_plane = plane;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = cmd->tx_argv[argstart + 1];
|
||||||
|
for (proplen = 0; *value != '\0'; )
|
||||||
|
{
|
||||||
|
if (isspace(*value) && (*value != '\0')) value++;
|
||||||
|
if (!isspace(*value))
|
||||||
|
{
|
||||||
|
proplen++;
|
||||||
|
while (!isspace(*value) && (*value != '\0')) value++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (proplen > 0)
|
||||||
|
{
|
||||||
|
proprec = (PropertyRecord *)mallocMagic(
|
||||||
|
sizeof(PropertyRecord) +
|
||||||
|
(proplen - 2) * sizeof(int));
|
||||||
|
proprec->prop_type = proptype;
|
||||||
|
proprec->prop_len = proplen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Second pass */
|
||||||
|
value = cmd->tx_argv[argstart + 1];
|
||||||
|
for (proplen = 0; proplen < proprec->prop_len; proplen++)
|
||||||
|
{
|
||||||
|
if (isspace(*value) && (*value != '\0')) value++;
|
||||||
|
if (!isspace(*value))
|
||||||
|
{
|
||||||
|
char *spptr, spchar;
|
||||||
|
/* cmdParseCoord() can only handle one value at a
|
||||||
|
* time, so look ahead and null out the next space
|
||||||
|
* character if there is one.
|
||||||
|
*/
|
||||||
|
spptr = value + 1;
|
||||||
|
while (!isspace(*spptr) && (*spptr != '\0')) spptr++;
|
||||||
|
spchar = *spptr;
|
||||||
|
*spptr = '\0';
|
||||||
|
|
||||||
|
if (proptype == PROPERTY_TYPE_INTEGER)
|
||||||
|
{
|
||||||
|
if (sscanf(value, "%d", &propvalue) != 1)
|
||||||
|
{
|
||||||
|
TxError("Unable to parse integer "
|
||||||
|
"value from \"%s\"\n",
|
||||||
|
value);
|
||||||
|
propvalue = 0;
|
||||||
|
}
|
||||||
|
proprec->prop_value.prop_integer[proplen] = propvalue;
|
||||||
|
}
|
||||||
|
else if (proptype == PROPERTY_TYPE_DOUBLE)
|
||||||
|
{
|
||||||
|
if (sscanf(value, "%"DLONG_PREFIX"d", &dvalue) != 1)
|
||||||
|
{
|
||||||
|
TxError("Unable to parse integer "
|
||||||
|
"value from \"%s\"\n",
|
||||||
|
value);
|
||||||
|
propvalue = 0;
|
||||||
|
}
|
||||||
|
proprec->prop_value.prop_double[proplen] = dvalue;
|
||||||
|
}
|
||||||
|
else if (proptype == PROPERTY_TYPE_PLANE)
|
||||||
|
{
|
||||||
|
propvalue = cmdParseCoord(w, value, FALSE,
|
||||||
|
((proplen % 2) == 0) ? TRUE : FALSE);
|
||||||
|
switch (proplen % 4)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
r.r_xbot = propvalue;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
r.r_ybot = propvalue;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
r.r_xtop = propvalue;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
r.r_ytop = propvalue;
|
||||||
|
DBPaintPlane(plane, &r, CIFPaintTable,
|
||||||
|
(PaintUndoInfo *)NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* PROPERTY_TYPE_DIMENSION */
|
||||||
|
{
|
||||||
|
propvalue = cmdParseCoord(w, value, FALSE,
|
||||||
|
((proplen % 2) == 0) ? TRUE : FALSE);
|
||||||
|
proprec->prop_value.prop_integer[proplen] = propvalue;
|
||||||
|
}
|
||||||
|
*spptr = spchar;
|
||||||
|
while (!isspace(*value) && (*value != '\0')) value++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBPropPut(def, cmd->tx_argv[argstart], proprec);
|
||||||
}
|
}
|
||||||
def->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
|
def->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
|
||||||
}
|
}
|
||||||
|
|
@ -2380,10 +2783,14 @@ CmdDoProperty(
|
||||||
* defined in database/DBprop.c.
|
* defined in database/DBprop.c.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* property [name] [value]
|
* property [string|integer|dimension] [name] [value]
|
||||||
*
|
*
|
||||||
* "name" is a unique string tag for the property, and "value" is its
|
* If the first argument is present, it must be one of the known
|
||||||
* string value.
|
* keywords, and determines the form in which "value" is interpreted and
|
||||||
|
* stored. "name" is a unique string tag for the property. "value" is
|
||||||
|
* the value of the property, which is either a string, integer, or a
|
||||||
|
* list of integers. The difference between an "integer" and a "dimension"
|
||||||
|
* is that all values which are dimensions are scaled with internal units.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* None.
|
* None.
|
||||||
|
|
@ -2410,9 +2817,62 @@ CmdProperty(
|
||||||
else
|
else
|
||||||
def = ((CellUse *) w->w_surfaceID)->cu_def;
|
def = ((CellUse *) w->w_surfaceID)->cu_def;
|
||||||
|
|
||||||
CmdDoProperty(def, cmd, 1);
|
CmdDoProperty(def, w, cmd, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* Callback function for printing values from a Plane property
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
int
|
||||||
|
printPlanePropFunc(
|
||||||
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
|
Tcl_Obj *lobj)
|
||||||
|
{
|
||||||
|
Rect r;
|
||||||
|
MagWindow *w;
|
||||||
|
|
||||||
|
TiToRect(tile, &r);
|
||||||
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
|
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(DBWPrintValue(r.r_xbot, w, TRUE), -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(DBWPrintValue(r.r_ybot, w, FALSE), -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(DBWPrintValue(r.r_xtop, w, TRUE), -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(DBWPrintValue(r.r_ytop, w, FALSE), -1));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int
|
||||||
|
printPlanePropFunc(
|
||||||
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
|
ClientData cdata /* (unused) */
|
||||||
|
{
|
||||||
|
Rect r;
|
||||||
|
MagWindow *w;
|
||||||
|
|
||||||
|
TiToRect(tile, &r)
|
||||||
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
|
|
||||||
|
TxPrintf("%s ", DBWPrintValue(r.r_xbot, w, TRUE);
|
||||||
|
TxPrintf("%s ", DBWPrintValue(r.r_ybot, w, FALSE);
|
||||||
|
TxPrintf("%s ", DBWPrintValue(r.r_xtop, w, TRUE);
|
||||||
|
TxPrintf("%s ", DBWPrintValue(r.r_ytop, w, FALSE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
* Callback function for printing a single property key:value pair
|
* Callback function for printing a single property key:value pair
|
||||||
|
|
@ -2422,27 +2882,84 @@ CmdProperty(
|
||||||
int
|
int
|
||||||
printPropertiesFunc(
|
printPropertiesFunc(
|
||||||
const char *name,
|
const char *name,
|
||||||
ClientData value,
|
PropertyRecord *proprec,
|
||||||
ClientData cdata) /* not used */
|
MagWindow *w)
|
||||||
{
|
{
|
||||||
#ifdef MAGIC_WRAPPER
|
int i;
|
||||||
char *keyvalue;
|
|
||||||
|
|
||||||
if (value == NULL)
|
#ifdef MAGIC_WRAPPER
|
||||||
|
Tcl_Obj *tobj, *lobj;
|
||||||
|
|
||||||
|
tobj = Tcl_GetObjResult(magicinterp);
|
||||||
|
lobj = Tcl_NewListObj(0, NULL);
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewStringObj(name, -1));
|
||||||
|
|
||||||
|
switch (proprec->prop_type)
|
||||||
{
|
{
|
||||||
keyvalue = (char *)mallocMagic(strlen(name) + 4);
|
case PROPERTY_TYPE_STRING:
|
||||||
sprintf(keyvalue, "%s {}", name);
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(proprec->prop_value.prop_string, -1));
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_INTEGER:
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewIntObj(proprec->prop_value.prop_integer[i]));
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DIMENSION:
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(
|
||||||
|
DBWPrintValue(proprec->prop_value.prop_integer[i],
|
||||||
|
w, ((i % 2) == 0) ? TRUE : FALSE), -1));
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_PLANE:
|
||||||
|
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
||||||
|
proprec->prop_value.prop_plane,
|
||||||
|
&TiPlaneRect, &CIFSolidBits, printPlanePropFunc,
|
||||||
|
(ClientData)lobj);
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DOUBLE:
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewWideIntObj(proprec->prop_value.prop_double[i]));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
Tcl_ListObjAppendElement(magicinterp, tobj, lobj);
|
||||||
{
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
keyvalue = (char *)mallocMagic(strlen(name) + strlen((const char *)value) + 2);
|
|
||||||
sprintf(keyvalue, "%s %s", name, (const char *)value);
|
|
||||||
}
|
|
||||||
Tcl_AppendElement(magicinterp, keyvalue);
|
|
||||||
freeMagic(keyvalue);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s = %s\n", name, (const char *)value);
|
switch (proprec->prop_type)
|
||||||
|
{
|
||||||
|
case PROPERTY_TYPE_STRING:
|
||||||
|
TxPrintf("%s = %s\n", name, (const char *)proprec->prop_string);
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_INTEGER:
|
||||||
|
TxPrintf("%s = ", name);
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
TxPrintf("%d ", proprec->prop_integer[i]);
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DIMENSION:
|
||||||
|
TxPrintf("%s = ", name);
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
TxPrintf("%s ", DBWPrintValue(proprec->prop_value.prop_integer[i],
|
||||||
|
w, ((i % 2) == 0) ? TRUE : FALSE);
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_PLANE:
|
||||||
|
TxPrintf("%s = ", name);
|
||||||
|
DBSrPaintArea((Tile *)NULL, proprec->prop_value.prop_plane,
|
||||||
|
&TiPlaneRect, &CIFSolidBits, printPlanePropFunc,
|
||||||
|
(ClientData)NULL);
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
case PROPERTY_TYPE_DOUBLE:
|
||||||
|
TxPrintf("%s = ", name);
|
||||||
|
for (i = 0; i < proprec->prop_len; i++)
|
||||||
|
TxPrintf("%"DLONG_PREFIX"d ", proprec->prop_double[i]);
|
||||||
|
TxPrintf("\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0; /* keep the search alive */
|
return 0; /* keep the search alive */
|
||||||
|
|
|
||||||
109
commands/CmdRS.c
109
commands/CmdRS.c
|
|
@ -1084,25 +1084,33 @@ CmdSelect(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
case SEL_BBOX:
|
case SEL_BBOX:
|
||||||
|
{
|
||||||
|
char *selllx, *sellly, *selurx, *selury;
|
||||||
|
|
||||||
GeoTransRect(&SelectUse->cu_transform, &SelectDef->cd_bbox, &selarea);
|
GeoTransRect(&SelectUse->cu_transform, &SelectDef->cd_bbox, &selarea);
|
||||||
|
|
||||||
|
selllx = DBWPrintValue(selarea.r_xbot, w, TRUE);
|
||||||
|
sellly = DBWPrintValue(selarea.r_ybot, w, FALSE);
|
||||||
|
selurx = DBWPrintValue(selarea.r_xtop, w, TRUE);
|
||||||
|
selury = DBWPrintValue(selarea.r_ytop, w, FALSE);
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
lobj = Tcl_NewListObj(0, NULL);
|
lobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
Tcl_NewIntObj(selarea.r_xbot));
|
Tcl_NewStringObj(selllx, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
Tcl_NewIntObj(selarea.r_ybot));
|
Tcl_NewStringObj(sellly, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
Tcl_NewIntObj(selarea.r_xtop));
|
Tcl_NewStringObj(selurx, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
Tcl_NewIntObj(selarea.r_ytop));
|
Tcl_NewStringObj(selury, -1));
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("Select bounding box: %d %d %d %d\n",
|
TxPrintf("Select bounding box: %s %s %s %s\n",
|
||||||
selarea.r_xbot, selarea.r_ybot,
|
selllx, sellly, selurx, selury);
|
||||||
selarea.r_xtop, selarea.r_ytop);
|
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------
|
/*--------------------------------------------------------------------
|
||||||
* Make a copy of the selection at its present loction but do not
|
* Make a copy of the selection at its present loction but do not
|
||||||
|
|
@ -1985,23 +1993,25 @@ cmdLabelRectFunc(
|
||||||
|
|
||||||
if (rect == NULL)
|
if (rect == NULL)
|
||||||
{
|
{
|
||||||
|
char *labllx, *lablly, *laburx, *labury;
|
||||||
|
|
||||||
|
/* Note: Ideally, the MagWindow pointer should be passed to this function */
|
||||||
|
labllx = DBWPrintValue(label->lab_rect.r_xbot, (MagWindow *)NULL, TRUE);
|
||||||
|
lablly = DBWPrintValue(label->lab_rect.r_ybot, (MagWindow *)NULL, FALSE);
|
||||||
|
laburx = DBWPrintValue(label->lab_rect.r_xtop, (MagWindow *)NULL, TRUE);
|
||||||
|
labury = DBWPrintValue(label->lab_rect.r_ytop, (MagWindow *)NULL, FALSE);
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
lobj = Tcl_GetObjResult(magicinterp);
|
lobj = Tcl_GetObjResult(magicinterp);
|
||||||
pobj = Tcl_NewListObj(0, NULL);
|
pobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(labllx, -1));
|
||||||
Tcl_NewIntObj((double)label->lab_rect.r_xbot));
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(lablly, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(laburx, -1));
|
||||||
Tcl_NewIntObj((double)label->lab_rect.r_ybot));
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(labury, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
|
||||||
Tcl_NewIntObj((double)label->lab_rect.r_xtop));
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
|
||||||
Tcl_NewIntObj((double)label->lab_rect.r_ytop));
|
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%d %d %d %d\n",
|
TxPrintf("%s %s %s %s\n", labllx, lablly, laburx,labury);
|
||||||
label->lab_rect.r_xbot, label->lab_rect.r_ybot,
|
|
||||||
label->lab_rect.r_xtop, label->lab_rect.r_ytop);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (!GEO_SAMERECT(label->lab_rect, *rect))
|
else if (!GEO_SAMERECT(label->lab_rect, *rect))
|
||||||
|
|
@ -2317,11 +2327,13 @@ CmdSetLabel(
|
||||||
{
|
{
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *labsize;
|
||||||
|
|
||||||
|
labsize = DBWPrintValue(DefaultLabel->lab_size, w, FALSE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetObjResult(magicinterp,
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(labsize, -1));
|
||||||
Tcl_NewIntObj(DefaultLabel->lab_size));
|
|
||||||
#else
|
#else
|
||||||
TxPrintf("%d\n", DefaultLabel->lab_size);
|
TxPrintf("%s\n", labsize);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2360,16 +2372,20 @@ CmdSetLabel(
|
||||||
{
|
{
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *laboffx, *laboffy;
|
||||||
|
laboffx = DBWPrintValue(DefaultLabel->lab_offset.p_x, w,
|
||||||
|
TRUE);
|
||||||
|
laboffy = DBWPrintValue(DefaultLabel->lab_offset.p_y, w,
|
||||||
|
FALSE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
lobj = Tcl_NewListObj(0, NULL);
|
lobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
Tcl_NewIntObj(DefaultLabel->lab_offset.p_x));
|
Tcl_NewStringObj(laboffx, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
Tcl_NewIntObj(DefaultLabel->lab_offset.p_y));
|
Tcl_NewStringObj(laboffy, -1));
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%d %d\n", DefaultLabel->lab_offset.p_x,
|
TxPrintf("%s %s\n", laboffx, laboffy);
|
||||||
DefaultLabel->lab_offset.p_y);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2884,16 +2900,39 @@ CmdSnap(
|
||||||
TxPrintf("Usage: snap [internal | lambda | user]\n");
|
TxPrintf("Usage: snap [internal | lambda | user]\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Backwards compatibility: Use of "snap" to set units display and
|
||||||
|
* parsing has been deprecated as of February 2026. However, as this
|
||||||
|
* is rather disruptive to existing scripts which use "snap" to change
|
||||||
|
* the parsing of units, then the following measure is being taken
|
||||||
|
* (for now, anyway): If DBWUnits is set to DBW_UNITS_DEFAULT, then
|
||||||
|
* "snap internal" will set DBWUnits as well as DBWSnapToGrid. If
|
||||||
|
* DBWUnits is changed first (e.g., "units internal"), then "snap" will
|
||||||
|
* affect only the snap grid. The older usage will be accompanied by a
|
||||||
|
* warning message. Note that backwards compatibility is being kept
|
||||||
|
* only in the case of "snap internal", which was commonly used in
|
||||||
|
* scripts to make sure that all units were interpreted as internal
|
||||||
|
* units.
|
||||||
|
*/
|
||||||
|
if ((DBWUnits == DBW_UNITS_DEFAULT) && (n == SNAP_INTERNAL))
|
||||||
|
{
|
||||||
|
DBWUnits = DBW_UNITS_INTERNAL;
|
||||||
|
TxError("Warning: snap setting is also changing units. This usage "
|
||||||
|
"is deprecated\nand may be removed in the future. Use "
|
||||||
|
"\"units\" to change units, and\nchange units before "
|
||||||
|
"setting snap to keep this message from appearing.\n");
|
||||||
|
}
|
||||||
|
|
||||||
switch (n)
|
switch (n)
|
||||||
{
|
{
|
||||||
case SNAP_OFF: case SNAP_INTERNAL:
|
case SNAP_OFF: case SNAP_INTERNAL:
|
||||||
DBWSnapToGrid = DBW_SNAP_INTERNAL;
|
DBWSnapToGrid = DBW_UNITS_INTERNAL;
|
||||||
return;
|
return;
|
||||||
case SNAP_LAMBDA:
|
case SNAP_LAMBDA:
|
||||||
DBWSnapToGrid = DBW_SNAP_LAMBDA;
|
DBWSnapToGrid = DBW_UNITS_LAMBDA;
|
||||||
return;
|
return;
|
||||||
case SNAP_GRID: case SNAP_USER: case SNAP_ON:
|
case SNAP_GRID: case SNAP_USER: case SNAP_ON:
|
||||||
DBWSnapToGrid = DBW_SNAP_USER;
|
DBWSnapToGrid = DBW_UNITS_USER;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2901,21 +2940,19 @@ printit:
|
||||||
if (n == SNAP_LIST) /* list */
|
if (n == SNAP_LIST) /* list */
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetResult(magicinterp,
|
Tcl_SetResult(magicinterp,
|
||||||
(DBWSnapToGrid == DBW_SNAP_INTERNAL) ? "internal" :
|
(DBWSnapToGrid == DBW_UNITS_INTERNAL) ? "internal" :
|
||||||
((DBWSnapToGrid == DBW_SNAP_LAMBDA) ? "lambda" : "user"),
|
((DBWSnapToGrid == DBW_UNITS_LAMBDA) ? "lambda" : "user"),
|
||||||
TCL_VOLATILE);
|
TCL_VOLATILE);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s\n", (DBWSnapToGrid == DBW_SNAP_INTERNAL) ? "internal" :
|
TxPrintf("%s\n", (DBWSnapToGrid == DBW_UNITS_INTERNAL) ? "internal" :
|
||||||
((DBWSnapToGrid == DBW_SNAP_LAMBDA) ? "lambda" : "user"));
|
((DBWSnapToGrid == DBW_UNITS_LAMBDA) ? "lambda" : "user"));
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
TxPrintf("Box is aligned to %s grid\n",
|
TxPrintf("Box is aligned to %s grid\n",
|
||||||
(DBWSnapToGrid == DBW_SNAP_INTERNAL) ? "internal" :
|
(DBWSnapToGrid == DBW_UNITS_INTERNAL) ? "internal" :
|
||||||
((DBWSnapToGrid == DBW_SNAP_LAMBDA) ? "lambda" : "user"));
|
((DBWSnapToGrid == DBW_UNITS_LAMBDA) ? "lambda" : "user"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,22 @@ TileTypeBitMask CmdYMAllButSpace;
|
||||||
* lambda, a suffix of "g" indicates the user grid, and a suffix in metric
|
* lambda, a suffix of "g" indicates the user grid, and a suffix in metric
|
||||||
* notation ("nm", "um", "mm", "cm") indicates natural units. Other valid
|
* notation ("nm", "um", "mm", "cm") indicates natural units. Other valid
|
||||||
* units are "cu" or "centimicrons" for centimicrons, or "microns" for um.
|
* units are "cu" or "centimicrons" for centimicrons, or "microns" for um.
|
||||||
* Units without any suffix are assumed to be in lambda if "snap"
|
* Traditional (backwards-compatible) behavior: Units without any suffix
|
||||||
* (DBWSnapToGrid) is set to lambda, grid units if "snap" is set to the
|
* are assumed to be in lambda if "snap" (DBWSnapToGrid) is set to lambda,
|
||||||
* user grid, and internal units otherwise.
|
* grid units if "snap" is set to the user grid, and internal units otherwise.
|
||||||
|
* Current behavior: Use of the "units" command to set the units to
|
||||||
|
* any value other than "default" causes cmdScaleCoord() to parse any
|
||||||
|
* units provided without an identifying suffix as the units indicted by
|
||||||
|
* the "units" command. Once the "units" command has been issued, the
|
||||||
|
* values are dependent on DBWUnits and not on DBWSnapToGrid.
|
||||||
|
*
|
||||||
|
* Additional behavior from magic version 8.3.596: A single command
|
||||||
|
* option can use simple expressions using '+', '-', '*', and '/'. These
|
||||||
|
* can be passed as a single token, without spaces, or within a string
|
||||||
|
* token deliniated by quotes or braces, per usual Tcl syntax. Unlike
|
||||||
|
* the Tcl "expr" command, this can solve arithmetic expressions of
|
||||||
|
* suffixed values, evaluated independently such that different suffixes
|
||||||
|
* may be used (e.g., "1g + 3um" meaning 1 grid pitch plus 3 microns).
|
||||||
*
|
*
|
||||||
* MagWindow argument w is used only with grid-based snapping, to find
|
* MagWindow argument w is used only with grid-based snapping, to find
|
||||||
* the value of the grid for the given window. In this case, because the
|
* the value of the grid for the given window. In this case, because the
|
||||||
|
|
@ -99,6 +112,13 @@ TileTypeBitMask CmdYMAllButSpace;
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define PARSEOP_NONE 0
|
||||||
|
#define PARSEOP_ADD 1
|
||||||
|
#define PARSEOP_SUB 2
|
||||||
|
#define PARSEOP_MUL 3
|
||||||
|
#define PARSEOP_DIV 4
|
||||||
|
#define PARSEOP_END 5
|
||||||
|
|
||||||
int
|
int
|
||||||
cmdScaleCoord(
|
cmdScaleCoord(
|
||||||
MagWindow *w,
|
MagWindow *w,
|
||||||
|
|
@ -109,45 +129,69 @@ cmdScaleCoord(
|
||||||
{
|
{
|
||||||
char *endptr;
|
char *endptr;
|
||||||
double dval = 0;
|
double dval = 0;
|
||||||
int mscale = 1;
|
int mscale = 1, curunits;
|
||||||
|
int retval, curval, parseop;
|
||||||
DBWclientRec *crec;
|
DBWclientRec *crec;
|
||||||
|
|
||||||
if (*arg == '{') arg++;
|
if (*arg == '{' || *arg == '"') arg++;
|
||||||
while (isspace(*arg)) arg++;
|
while (isspace(*arg) && (*arg != '\0')) arg++;
|
||||||
|
|
||||||
|
parseop = PARSEOP_NONE;
|
||||||
|
retval = 0;
|
||||||
|
while (*arg != '\0')
|
||||||
|
{
|
||||||
dval = strtod(arg, &endptr);
|
dval = strtod(arg, &endptr);
|
||||||
dval *= (double)scale;
|
dval *= (double)scale;
|
||||||
|
mscale = -1;
|
||||||
|
|
||||||
if (endptr == arg)
|
if (endptr == arg)
|
||||||
{
|
{
|
||||||
/* strtod() error condition */
|
/* strtod() error condition */
|
||||||
TxError("Coordinate value cannot be parsed: assuming 0\n");
|
TxError("Coordinate value cannot be parsed: assuming 0\n");
|
||||||
return 0;
|
curval = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ((*endptr == 'l')
|
/* Original behavior was to accept un-suffixed values according to the
|
||||||
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_LAMBDA)))
|
* "snap" setting. This behavior remains in effect until the "units"
|
||||||
|
* command is used, in which case units follow the selected units
|
||||||
|
* value indepedendently of the snap setting.
|
||||||
|
*
|
||||||
|
* Updated 12/24/2026 to handle space-separated values (in which
|
||||||
|
* *endptr may be a space as well as NULL).
|
||||||
|
*/
|
||||||
|
if (DBWUnits == DBW_UNITS_DEFAULT)
|
||||||
|
curunits = DBWSnapToGrid;
|
||||||
|
else
|
||||||
|
curunits = DBWUnits & DBW_UNITS_TYPE_MASK;
|
||||||
|
|
||||||
|
if ((*endptr == 'l')
|
||||||
|
|| (((*endptr == '\0') || isspace(*endptr))
|
||||||
|
&& (curunits == DBW_UNITS_LAMBDA)))
|
||||||
{
|
{
|
||||||
/* lambda or default units */
|
/* lambda or default units */
|
||||||
dval *= (double)DBLambda[1];
|
dval *= (double)DBLambda[1];
|
||||||
dval /= (double)DBLambda[0];
|
dval /= (double)DBLambda[0];
|
||||||
return round(dval);
|
|
||||||
}
|
}
|
||||||
else if ((*endptr == 'i')
|
else if ((*endptr == 'i')
|
||||||
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_INTERNAL)))
|
|| (((*endptr == '\0') || isspace(*endptr))
|
||||||
|
&& (curunits == DBW_UNITS_INTERNAL)))
|
||||||
{
|
{
|
||||||
/* internal units */
|
/* internal units */
|
||||||
return round(dval);
|
|
||||||
}
|
}
|
||||||
else if ((*endptr == 'g')
|
else if ((*endptr == 'g')
|
||||||
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_USER)))
|
|| (((*endptr == '\0') || isspace(*endptr))
|
||||||
|
&& (curunits == DBW_UNITS_USER)))
|
||||||
{
|
{
|
||||||
/* grid units */
|
/* grid units */
|
||||||
if (w == (MagWindow *)NULL)
|
if (w == (MagWindow *)NULL)
|
||||||
{
|
{
|
||||||
windCheckOnlyWindow(&w, DBWclientID);
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
if (w == (MagWindow *)NULL)
|
if (w == (MagWindow *)NULL)
|
||||||
return round(dval); /* Default, if window is unknown */
|
{
|
||||||
|
curval = round(dval); /* Default, if window is unknown */
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
crec = (DBWclientRec *) w->w_clientData;
|
crec = (DBWclientRec *) w->w_clientData;
|
||||||
if (is_x)
|
if (is_x)
|
||||||
|
|
@ -164,9 +208,13 @@ cmdScaleCoord(
|
||||||
if (!is_relative)
|
if (!is_relative)
|
||||||
dval += (double)crec->dbw_gridRect.r_ybot;
|
dval += (double)crec->dbw_gridRect.r_ybot;
|
||||||
}
|
}
|
||||||
return round(dval);
|
|
||||||
}
|
}
|
||||||
else
|
else if (((*endptr == '\0') || isspace(*endptr))
|
||||||
|
&& (curunits == DBW_UNITS_MICRONS))
|
||||||
|
{
|
||||||
|
mscale = 1000;
|
||||||
|
}
|
||||||
|
else if (*endptr != '\0')
|
||||||
{
|
{
|
||||||
/* natural units referred to the current cifoutput style */
|
/* natural units referred to the current cifoutput style */
|
||||||
if (*(endptr + 1) == 'm')
|
if (*(endptr + 1) == 'm')
|
||||||
|
|
@ -186,12 +234,12 @@ cmdScaleCoord(
|
||||||
mscale = 10000000;
|
mscale = 10000000;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
TxError("Unknown metric prefix \"%cm\"; assuming internal units\n",
|
TxError("Unknown metric prefix \"%cm\"; assuming "
|
||||||
*endptr);
|
"internal units\n", *endptr);
|
||||||
return round(dval);
|
mscale = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strcmp(endptr, "u"))
|
else if ((*endptr == 'u') && !isalnum(*(endptr + 1)))
|
||||||
/* Maybe "u" is too ambiguous but it is very commonly used as
|
/* Maybe "u" is too ambiguous but it is very commonly used as
|
||||||
* an abbreviation for "micron".
|
* an abbreviation for "micron".
|
||||||
*/
|
*/
|
||||||
|
|
@ -200,16 +248,76 @@ cmdScaleCoord(
|
||||||
mscale = 1000;
|
mscale = 1000;
|
||||||
else if (!strncmp(endptr, "centimicron", 11) || !strcmp(endptr, "cu"))
|
else if (!strncmp(endptr, "centimicron", 11) || !strcmp(endptr, "cu"))
|
||||||
mscale = 10;
|
mscale = 10;
|
||||||
else if (!isspace(*endptr))
|
else if (!isspace(*endptr) && (*endptr != '+') && (*endptr != '-') &&
|
||||||
|
(*endptr != '*') && (*endptr != '/'))
|
||||||
{
|
{
|
||||||
TxError("Unknown coordinate type \"%s\"; assuming internal units\n",
|
TxError("Unknown coordinate type at \"%s\"; assuming internal units\n",
|
||||||
endptr);
|
endptr);
|
||||||
return round(dval);
|
mscale = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isspace(*endptr))
|
if (mscale != -1)
|
||||||
dval /= CIFGetOutputScale(mscale);
|
dval /= CIFGetOutputScale(mscale);
|
||||||
return round(dval);
|
curval = round(dval);
|
||||||
|
|
||||||
|
switch (parseop)
|
||||||
|
{
|
||||||
|
case PARSEOP_NONE:
|
||||||
|
retval = curval;
|
||||||
|
break;
|
||||||
|
case PARSEOP_ADD:
|
||||||
|
retval += curval;
|
||||||
|
break;
|
||||||
|
case PARSEOP_SUB:
|
||||||
|
retval -= curval;
|
||||||
|
break;
|
||||||
|
case PARSEOP_MUL:
|
||||||
|
retval *= curval;
|
||||||
|
break;
|
||||||
|
case PARSEOP_DIV:
|
||||||
|
retval /= curval;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
parseop = PARSEOP_NONE;
|
||||||
|
while (*endptr != '\0')
|
||||||
|
{
|
||||||
|
switch (*endptr)
|
||||||
|
{
|
||||||
|
case '}':
|
||||||
|
case '"':
|
||||||
|
parseop = PARSEOP_END;
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
parseop = PARSEOP_ADD;
|
||||||
|
endptr++;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
parseop = PARSEOP_SUB;
|
||||||
|
endptr++;
|
||||||
|
break;
|
||||||
|
case '*':
|
||||||
|
parseop = PARSEOP_MUL;
|
||||||
|
endptr++;
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
parseop = PARSEOP_DIV;
|
||||||
|
endptr++;
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
endptr++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Should this flag an error? */
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
if (parseop != PARSEOP_NONE) break;
|
||||||
|
}
|
||||||
|
arg = endptr;
|
||||||
|
while (isspace(*arg) && (*arg != '\0')) arg++;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -653,7 +761,9 @@ cmdSaveCell(
|
||||||
if (!tryRename || (fileName == NULL) || (strcmp(cellDef->cd_name, fileName) == 0))
|
if (!tryRename || (fileName == NULL) || (strcmp(cellDef->cd_name, fileName) == 0))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* Rename the cell */
|
/* Rename the cell, unless fileName is a .tcl file (scripted output) */
|
||||||
|
if ((strlen(fileName) <= 4) || strcmp(fileName + strlen(fileName) - 4, ".tcl"))
|
||||||
|
{
|
||||||
if (!DBCellRenameDef(cellDef, fileName))
|
if (!DBCellRenameDef(cellDef, fileName))
|
||||||
{
|
{
|
||||||
/* This should never happen */
|
/* This should never happen */
|
||||||
|
|
@ -661,6 +771,7 @@ cmdSaveCell(
|
||||||
fileName);
|
fileName);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (EditCellUse && (cellDef == EditCellUse->cu_def))
|
if (EditCellUse && (cellDef == EditCellUse->cu_def))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
227
commands/CmdTZ.c
227
commands/CmdTZ.c
|
|
@ -61,7 +61,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
||||||
|
|
||||||
int
|
int
|
||||||
existFunc(
|
existFunc(
|
||||||
Tile *tile)
|
Tile *tile, /* (unused) */
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
|
ClientData clientdata) /* (unused) */
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -453,15 +455,18 @@ CmdTech(
|
||||||
}
|
}
|
||||||
if (!strncmp(cmd->tx_argv[2], "width", 5))
|
if (!strncmp(cmd->tx_argv[2], "width", 5))
|
||||||
{
|
{
|
||||||
|
char *techwidth;
|
||||||
tresult = DRCGetDefaultLayerWidth(t1);
|
tresult = DRCGetDefaultLayerWidth(t1);
|
||||||
|
techwidth = DBWPrintValue(tresult, w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techwidth, -1));
|
||||||
#else
|
#else
|
||||||
TxPrintf("Minimum width is %d\n", tresult);
|
TxPrintf("Minimum width is %s\n", techwidth);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (!strncmp(cmd->tx_argv[2], "spac", 4))
|
else if (!strncmp(cmd->tx_argv[2], "spac", 4))
|
||||||
{
|
{
|
||||||
|
char *techspace;
|
||||||
if (cmd->tx_argc >= 5)
|
if (cmd->tx_argc >= 5)
|
||||||
{
|
{
|
||||||
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
|
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
|
||||||
|
|
@ -473,14 +478,16 @@ CmdTech(
|
||||||
else
|
else
|
||||||
t2 = t1;
|
t2 = t1;
|
||||||
tresult = DRCGetDefaultLayerSpacing(t1, t2);
|
tresult = DRCGetDefaultLayerSpacing(t1, t2);
|
||||||
|
techspace = DBWPrintValue(tresult, w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techspace, -1));
|
||||||
#else
|
#else
|
||||||
TxPrintf("Minimum spacing is %d\n", tresult);
|
TxPrintf("Minimum spacing is %s\n", techspace);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (!strncmp(cmd->tx_argv[2], "surr", 4))
|
else if (!strncmp(cmd->tx_argv[2], "surr", 4))
|
||||||
{
|
{
|
||||||
|
char *techsurround;
|
||||||
if (cmd->tx_argc >= 5)
|
if (cmd->tx_argc >= 5)
|
||||||
{
|
{
|
||||||
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
|
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
|
||||||
|
|
@ -496,14 +503,17 @@ CmdTech(
|
||||||
}
|
}
|
||||||
|
|
||||||
tresult = DRCGetDefaultLayerSurround(t1, t2);
|
tresult = DRCGetDefaultLayerSurround(t1, t2);
|
||||||
|
techsurround = DBWPrintValue(tresult, w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techsurround, -1));
|
||||||
#else
|
#else
|
||||||
TxPrintf("Minimum surround is %d\n", tresult);
|
TxPrintf("Minimum surround is %s\n", techsurround);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (!strncmp(cmd->tx_argv[2], "direc", 5))
|
else if (!strncmp(cmd->tx_argv[2], "direc", 5))
|
||||||
{
|
{
|
||||||
|
char *techdirec;
|
||||||
|
|
||||||
if (cmd->tx_argc >= 5)
|
if (cmd->tx_argc >= 5)
|
||||||
{
|
{
|
||||||
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
|
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
|
||||||
|
|
@ -519,10 +529,11 @@ CmdTech(
|
||||||
}
|
}
|
||||||
|
|
||||||
tresult = DRCGetDirectionalLayerSurround(t1, t2);
|
tresult = DRCGetDirectionalLayerSurround(t1, t2);
|
||||||
|
techdirec = DBWPrintValue(tresult, w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
|
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techdirec, -1));
|
||||||
#else
|
#else
|
||||||
TxPrintf("Minimum surround (in one orientation) is %d\n", tresult);
|
TxPrintf("Minimum surround (in one orientation) is %s\n", techdirec);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -752,6 +763,182 @@ cmdUnexpandFunc(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* CmdUnits --
|
||||||
|
*
|
||||||
|
* Implement the "units" command.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* units [value] [print|noprint]
|
||||||
|
*
|
||||||
|
* where "value" may be one of "default", "internal", "lambda",
|
||||||
|
* "user" (equivalently "grid"), or "microns".
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* The global variable DBWUnits may be changed, which changes the
|
||||||
|
* behavior of magic when interpreting un-suffixed values or
|
||||||
|
* displaying values.
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* The units behavior was previously dependent on what command was
|
||||||
|
* issued, with results usually being given in internal units, and
|
||||||
|
* with un-suffixed values following the snap behavior. Backwards-
|
||||||
|
* compatible behavior is used on startup or at any time by setting
|
||||||
|
* the units to "default". Otherwise, unit display follows the
|
||||||
|
* given "units" setting.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define UNITS_DEFAULT 0
|
||||||
|
#define UNITS_INTERNAL 1
|
||||||
|
#define UNITS_LAMBDA 2
|
||||||
|
#define UNITS_GRID 3
|
||||||
|
#define UNITS_USER 4
|
||||||
|
#define UNITS_MICRONS 5
|
||||||
|
#define UNITS_LIST 6
|
||||||
|
#define UNITS_PRINT 7
|
||||||
|
#define UNITS_NOPRINT 8
|
||||||
|
|
||||||
|
void
|
||||||
|
CmdUnits(
|
||||||
|
MagWindow *w,
|
||||||
|
TxCommand *cmd)
|
||||||
|
{
|
||||||
|
static const char * const names[] = { "default", "internal", "lambda",
|
||||||
|
"grid", "user", "microns", "list", "print", "noprint", 0 };
|
||||||
|
int idx, n = UNITS_LIST, n2, saveflag;
|
||||||
|
DBWclientRec *crec;
|
||||||
|
|
||||||
|
if (cmd->tx_argc >= 2)
|
||||||
|
{
|
||||||
|
n = Lookup(cmd->tx_argv[1], names);
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
TxPrintf("Usage: units [default | internal | lambda | microns"
|
||||||
|
" | user] [print]\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (DBWUnits != DBW_UNITS_DEFAULT)
|
||||||
|
saveflag = DBWUnits & DBW_UNITS_PRINT_FLAG;
|
||||||
|
else
|
||||||
|
saveflag = -1;
|
||||||
|
|
||||||
|
switch (n)
|
||||||
|
{
|
||||||
|
case UNITS_DEFAULT:
|
||||||
|
DBWUnits = DBW_UNITS_DEFAULT;
|
||||||
|
break;
|
||||||
|
case UNITS_INTERNAL:
|
||||||
|
DBWUnits = DBW_UNITS_INTERNAL;
|
||||||
|
break;
|
||||||
|
case UNITS_LAMBDA:
|
||||||
|
DBWUnits = DBW_UNITS_LAMBDA;
|
||||||
|
break;
|
||||||
|
case UNITS_USER:
|
||||||
|
case UNITS_GRID:
|
||||||
|
DBWUnits = DBW_UNITS_USER;
|
||||||
|
break;
|
||||||
|
case UNITS_MICRONS:
|
||||||
|
DBWUnits = DBW_UNITS_MICRONS;
|
||||||
|
break;
|
||||||
|
case UNITS_PRINT:
|
||||||
|
saveflag = DBW_UNITS_PRINT_FLAG;
|
||||||
|
break;
|
||||||
|
case UNITS_NOPRINT:
|
||||||
|
saveflag = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
TxError("Unrecognized units option %s\n.", cmd->tx_argv[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (n != UNITS_LIST)
|
||||||
|
{
|
||||||
|
if ((cmd->tx_argc == 3) && (n != UNITS_DEFAULT))
|
||||||
|
{
|
||||||
|
n2 = Lookup(cmd->tx_argv[2], names);
|
||||||
|
switch (n2)
|
||||||
|
{
|
||||||
|
case UNITS_PRINT:
|
||||||
|
DBWUnits |= DBW_UNITS_PRINT_FLAG;
|
||||||
|
break;
|
||||||
|
case UNITS_NOPRINT:
|
||||||
|
DBWUnits &= DBW_UNITS_TYPE_MASK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TxError("Unrecognized units option %s\n.", cmd->tx_argv[2]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((n != UNITS_DEFAULT) && (saveflag != -1))
|
||||||
|
{
|
||||||
|
/* Preserve the previous value of the print/noprint flag */
|
||||||
|
DBWUnits &= DBW_UNITS_TYPE_MASK;
|
||||||
|
DBWUnits |= saveflag;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DBWUnits == DBW_UNITS_DEFAULT)
|
||||||
|
idx = UNITS_DEFAULT;
|
||||||
|
else
|
||||||
|
switch (DBWUnits & DBW_UNITS_TYPE_MASK)
|
||||||
|
{
|
||||||
|
case DBW_UNITS_INTERNAL:
|
||||||
|
idx = UNITS_INTERNAL;
|
||||||
|
break;
|
||||||
|
case DBW_UNITS_LAMBDA:
|
||||||
|
idx = UNITS_LAMBDA;
|
||||||
|
break;
|
||||||
|
case DBW_UNITS_USER:
|
||||||
|
idx = UNITS_USER;
|
||||||
|
break;
|
||||||
|
case DBW_UNITS_MICRONS:
|
||||||
|
idx = UNITS_MICRONS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == UNITS_LIST) /* list */
|
||||||
|
{
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
Tcl_Obj *tobj;
|
||||||
|
tobj = Tcl_NewListObj(0, NULL);
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj((char *)names[idx], -1));
|
||||||
|
if (idx != UNITS_DEFAULT)
|
||||||
|
{
|
||||||
|
if (DBWUnits & DBW_UNITS_PRINT_FLAG)
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj("print", 5));
|
||||||
|
else
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||||
|
Tcl_NewStringObj("noprint", 7));
|
||||||
|
}
|
||||||
|
Tcl_SetObjResult(magicinterp, tobj);
|
||||||
|
#else
|
||||||
|
TxPrintf("%s", names[idx]);
|
||||||
|
if (idx != UNITS_DEFAULT)
|
||||||
|
if (DBWUnits & DBW_UNITS_PRINT_FLAG)
|
||||||
|
TxPrintf(" print");
|
||||||
|
TxPrintf("\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (idx == UNITS_DEFAULT)
|
||||||
|
TxPrintf("Reported units follow the snap setting.\n");
|
||||||
|
else if (DBWUnits & DBW_UNITS_PRINT_FLAG)
|
||||||
|
TxPrintf("Values are reported as %s, along with the units.\n", names[idx]);
|
||||||
|
else
|
||||||
|
TxPrintf("Values are reported as %s\n", names[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -839,7 +1026,8 @@ struct linked_id {
|
||||||
|
|
||||||
int
|
int
|
||||||
cmdWhatPrintCell(
|
cmdWhatPrintCell(
|
||||||
Tile *tile,
|
Tile *tile, /* (unused) */
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
TreeContext *cxp)
|
TreeContext *cxp)
|
||||||
{
|
{
|
||||||
struct linked_id **lid = (struct linked_id **)cxp->tc_filter->tf_arg;
|
struct linked_id **lid = (struct linked_id **)cxp->tc_filter->tf_arg;
|
||||||
|
|
@ -894,6 +1082,7 @@ static LabelStore *labelBlockTop, *labelEntry;
|
||||||
int
|
int
|
||||||
cmdFindWhatTileFunc(
|
cmdFindWhatTileFunc(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
ClientData clientData)
|
ClientData clientData)
|
||||||
{
|
{
|
||||||
struct linked_id **lid = (struct linked_id **)clientData;
|
struct linked_id **lid = (struct linked_id **)clientData;
|
||||||
|
|
@ -905,7 +1094,7 @@ cmdFindWhatTileFunc(
|
||||||
scx.scx_use = EditCellUse;
|
scx.scx_use = EditCellUse;
|
||||||
scx.scx_trans = GeoIdentityTransform;
|
scx.scx_trans = GeoIdentityTransform;
|
||||||
|
|
||||||
if (SplitSide(tile))
|
if (dinfo & TT_SIDE)
|
||||||
type = SplitRightType(tile);
|
type = SplitRightType(tile);
|
||||||
else
|
else
|
||||||
type = SplitLeftType(tile);
|
type = SplitLeftType(tile);
|
||||||
|
|
@ -1692,18 +1881,20 @@ CmdWire(
|
||||||
case VALUES:
|
case VALUES:
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *wdisp;
|
||||||
width = WireGetWidth();
|
width = WireGetWidth();
|
||||||
type = WireGetType();
|
type = WireGetType();
|
||||||
|
wdisp = DBWPrintValue(width, w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
lobj = Tcl_NewListObj(0, NULL);
|
lobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
|
||||||
Tcl_NewIntObj(width));
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
Tcl_NewStringObj(DBTypeLongNameTbl[type], -1));
|
Tcl_NewStringObj(DBTypeLongNameTbl[type], -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||||
|
Tcl_NewStringObj(wdisp, -1));
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("Wire layer %s, width %d\n",
|
TxPrintf("Wire layer %s, width %s\n",
|
||||||
DBTypeLongNameTbl[type], width);
|
DBTypeLongNameTbl[type], wdisp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -1728,12 +1919,14 @@ CmdWire(
|
||||||
case WIDTH:
|
case WIDTH:
|
||||||
if (locargc == 2)
|
if (locargc == 2)
|
||||||
{
|
{
|
||||||
|
char *wdisp;
|
||||||
width = WireGetWidth();
|
width = WireGetWidth();
|
||||||
|
wdisp = DBWPrintValue(width, w, TRUE);
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
lobj = Tcl_NewIntObj(width);
|
lobj = Tcl_NewStringObj(wdisp, -1);
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
#else
|
#else
|
||||||
TxPrintf("Wire width is %d\n", width);
|
TxPrintf("Wire width is %s\n", wdisp);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (locargc != 3)
|
else if (locargc != 3)
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,8 @@ CmdExtractTest(
|
||||||
|
|
||||||
int
|
int
|
||||||
tileCountProc(
|
tileCountProc(
|
||||||
Tile *tile,
|
Tile *tile, /* (unused) */
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
int *tcount)
|
int *tcount)
|
||||||
{
|
{
|
||||||
(*tcount)++;
|
(*tcount)++;
|
||||||
|
|
@ -800,11 +801,13 @@ cmdStatsCount(
|
||||||
CellDef *def,
|
CellDef *def,
|
||||||
struct countClient *cc)
|
struct countClient *cc)
|
||||||
{
|
{
|
||||||
int cmdStatsCountTile(Tile *tile, struct cellInfo *ci);
|
|
||||||
int pNum;
|
int pNum;
|
||||||
struct cellInfo *ci;
|
struct cellInfo *ci;
|
||||||
TileType t;
|
TileType t;
|
||||||
|
|
||||||
|
/* Forward declaration */
|
||||||
|
int cmdStatsCountTile(Tile *tile, TileType dinfo, struct cellInfo *ci);
|
||||||
|
|
||||||
if (def->cd_client)
|
if (def->cd_client)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
|
|
@ -829,6 +832,7 @@ cmdStatsCount(
|
||||||
int
|
int
|
||||||
cmdStatsCountTile(
|
cmdStatsCountTile(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
struct cellInfo *ci)
|
struct cellInfo *ci)
|
||||||
{
|
{
|
||||||
TileType type = TiGetType(tile);
|
TileType type = TiGetType(tile);
|
||||||
|
|
@ -1099,17 +1103,18 @@ CmdTsearch(
|
||||||
MagWindow *w,
|
MagWindow *w,
|
||||||
TxCommand *cmd)
|
TxCommand *cmd)
|
||||||
{
|
{
|
||||||
int cmdTsrFunc(Tile *tp);
|
|
||||||
char *RunStats(int flags, struct tms *lastt, struct tms *deltat);
|
|
||||||
char *rstatp;
|
char *rstatp;
|
||||||
static TileTypeBitMask mask;
|
static TileTypeBitMask mask;
|
||||||
static struct tms tlast, tdelta;
|
static struct tms tlast, tdelta;
|
||||||
Rect rtool, rsearch;
|
Rect rtool, rsearch;
|
||||||
/**** Rect *ebox; ****/
|
|
||||||
Plane *plane;
|
Plane *plane;
|
||||||
int i, pNum, count;
|
int i, pNum, count;
|
||||||
int usPerSearch, usPerTile, usPerL2, us, boxarea;
|
int usPerSearch, usPerTile, usPerL2, us, boxarea;
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
int cmdTsrFunc(Tile *tp, TileType dinfo, ClientData clientdata);
|
||||||
|
char *RunStats(int flags, struct tms *lastt, struct tms *deltat);
|
||||||
|
|
||||||
if (cmd->tx_argc < 3 || cmd->tx_argc > 5)
|
if (cmd->tx_argc < 3 || cmd->tx_argc > 5)
|
||||||
{
|
{
|
||||||
TxError("Usage: tsearch plane count [mask [new|mayo]]\n");
|
TxError("Usage: tsearch plane count [mask [new|mayo]]\n");
|
||||||
|
|
@ -1209,7 +1214,9 @@ CmdTsearch(
|
||||||
|
|
||||||
int
|
int
|
||||||
cmdTsrFunc(
|
cmdTsrFunc(
|
||||||
Tile *tp)
|
Tile *tp,
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
|
ClientData clientdata) /* (unused) */
|
||||||
{
|
{
|
||||||
if (cmdTsearchDebug)
|
if (cmdTsearchDebug)
|
||||||
TxPrintf("%lx\n", (intptr_t) tp);
|
TxPrintf("%lx\n", (intptr_t) tp);
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ extern int cmdParseCoord(MagWindow *w, char *arg, bool is_relative, bool is_x);
|
||||||
extern void cmdSaveCell(CellDef *cellDef, char *newName, bool noninteractive, bool tryRename);
|
extern void cmdSaveCell(CellDef *cellDef, char *newName, bool noninteractive, bool tryRename);
|
||||||
extern void CmdInit(void);
|
extern void CmdInit(void);
|
||||||
|
|
||||||
extern void CmdDoProperty(CellDef *def, TxCommand *cmd, int argstart);
|
extern void CmdDoProperty(CellDef *def, MagWindow *w, TxCommand *cmd, int argstart);
|
||||||
extern void CmdPaintEraseButton(MagWindow *w, Point *refPoint, bool isPaint, bool isScreen);
|
extern void CmdPaintEraseButton(MagWindow *w, Point *refPoint, bool isPaint, bool isScreen);
|
||||||
|
|
||||||
#endif /* _MAGIC__COMMANDS__COMMANDS_H */
|
#endif /* _MAGIC__COMMANDS__COMMANDS_H */
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "windows/windows.h"
|
#include "windows/windows.h"
|
||||||
#include "dbwind/dbwind.h"
|
#include "dbwind/dbwind.h"
|
||||||
#include "commands/commands.h"
|
#include "commands/commands.h"
|
||||||
|
|
||||||
/* C99 compat */
|
|
||||||
#include "graphics/graphics.h"
|
#include "graphics/graphics.h"
|
||||||
|
#include "cif/CIFint.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following variable points to the tables currently used for
|
* The following variable points to the tables currently used for
|
||||||
|
|
@ -357,9 +356,43 @@ DBCellCheckCopyAllPaint(scx, mask, xMask, targetUse, func)
|
||||||
struct propUseDefStruct {
|
struct propUseDefStruct {
|
||||||
CellDef *puds_source;
|
CellDef *puds_source;
|
||||||
CellDef *puds_dest;
|
CellDef *puds_dest;
|
||||||
|
Plane *puds_plane; /* Mask hint plane in dest */
|
||||||
Transform *puds_trans; /* Transform from source use to dest */
|
Transform *puds_trans; /* Transform from source use to dest */
|
||||||
|
Rect *puds_area; /* Clip area in source coordinates */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*-----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* dbCopyMaskHintPlaneFunc --
|
||||||
|
*
|
||||||
|
* Translate tiles from a child mask-hint property plane into the
|
||||||
|
* coordinate system of the parent, and paint the mask-hint area
|
||||||
|
* into the mask-hint property plane of the parent.
|
||||||
|
*
|
||||||
|
*-----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
dbCopyMaskHintPlaneFunc(Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
|
struct propUseDefStruct *puds)
|
||||||
|
{
|
||||||
|
Transform *trans = puds->puds_trans;
|
||||||
|
Rect *clip = puds->puds_area;
|
||||||
|
Rect r, rnew;
|
||||||
|
Plane *plane = puds->puds_plane;
|
||||||
|
|
||||||
|
TiToRect(tile, &r);
|
||||||
|
GeoClip(&r, clip);
|
||||||
|
if (!GEO_RECTNULL(&r))
|
||||||
|
{
|
||||||
|
GeoTransRect(trans, &r, &rnew);
|
||||||
|
DBPaintPlane(plane, &rnew, CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-----------------------------------------------------------------------------
|
*-----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -380,63 +413,52 @@ struct propUseDefStruct {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCopyMaskHintsFunc(key, value, puds)
|
dbCopyMaskHintsFunc(key, proprec, puds)
|
||||||
char *key;
|
char *key;
|
||||||
ClientData value;
|
PropertyRecord *proprec;
|
||||||
struct propUseDefStruct *puds;
|
struct propUseDefStruct *puds;
|
||||||
{
|
{
|
||||||
CellDef *dest = puds->puds_dest;
|
CellDef *dest = puds->puds_dest;
|
||||||
Transform *trans = puds->puds_trans;
|
Transform *trans = puds->puds_trans;
|
||||||
char *propstr = (char *)value;
|
Rect *clip = puds->puds_area;
|
||||||
|
PropertyRecord *parentproprec, *newproprec;
|
||||||
char *parentprop, *newvalue, *vptr;
|
char *parentprop, *newvalue, *vptr;
|
||||||
Rect r, rnew;
|
Rect r, rnew;
|
||||||
bool propfound;
|
bool propfound;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
if (!strncmp(key, "MASKHINTS_", 10))
|
if (!strncmp(key, "MASKHINTS_", 10))
|
||||||
{
|
{
|
||||||
char *vptr, *lastval;
|
char *vptr, *lastval;
|
||||||
int lastlen;
|
int lastlen;
|
||||||
|
Plane *plane;
|
||||||
|
|
||||||
/* Append to existing mask hint (if any) */
|
ASSERT(proprec->prop_type == PROPERTY_TYPE_PLANE, "dbCopyMaskHintsFunc");
|
||||||
parentprop = (char *)DBPropGet(dest, key, &propfound);
|
|
||||||
newvalue = (propfound) ? StrDup((char **)NULL, parentprop) : (char *)NULL;
|
|
||||||
|
|
||||||
vptr = propstr;
|
/* Get the existing mask hint plane in the parent cell, and
|
||||||
while (*vptr != '\0')
|
* create it if it does not already exist.
|
||||||
{
|
*/
|
||||||
if (sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
parentproprec = (PropertyRecord *)DBPropGet(dest, key, &propfound);
|
||||||
&r.r_xtop, &r.r_ytop) == 4)
|
|
||||||
{
|
|
||||||
GeoTransRect(trans, &r, &rnew);
|
|
||||||
|
|
||||||
lastval = newvalue;
|
if (propfound)
|
||||||
lastlen = (lastval) ? strlen(lastval) : 0;
|
plane = parentproprec->prop_value.prop_plane;
|
||||||
newvalue = mallocMagic(40 + lastlen);
|
|
||||||
|
|
||||||
if (lastval)
|
|
||||||
strcpy(newvalue, lastval);
|
|
||||||
else
|
else
|
||||||
*newvalue = '\0';
|
{
|
||||||
|
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||||
sprintf(newvalue + lastlen, "%s%d %d %d %d", (lastval) ? " " : "",
|
newproprec->prop_type = PROPERTY_TYPE_PLANE;
|
||||||
rnew.r_xbot, rnew.r_ybot, rnew.r_xtop, rnew.r_ytop);
|
newproprec->prop_len = 0;
|
||||||
if (lastval) freeMagic(lastval);
|
plane = DBNewPlane((ClientData)TT_SPACE);
|
||||||
|
newproprec->prop_value.prop_plane = plane;
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
DBPropPut(dest, key, newproprec);
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
}
|
|
||||||
else break;
|
|
||||||
}
|
|
||||||
if (newvalue)
|
|
||||||
DBPropPut(dest, key, newvalue);
|
|
||||||
}
|
}
|
||||||
|
puds->puds_plane = plane;
|
||||||
|
|
||||||
|
/* Copy the properties from child to parent */
|
||||||
|
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
||||||
|
proprec->prop_value.prop_plane,
|
||||||
|
clip, &CIFSolidBits, dbCopyMaskHintPlaneFunc,
|
||||||
|
(ClientData)puds);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -468,6 +490,7 @@ DBCellCopyMaskHints(child, parent, transform)
|
||||||
puds.puds_source = child->cu_def;
|
puds.puds_source = child->cu_def;
|
||||||
puds.puds_dest = parent;
|
puds.puds_dest = parent;
|
||||||
puds.puds_trans = transform;
|
puds.puds_trans = transform;
|
||||||
|
puds.puds_area = (Rect *)&TiPlaneRect;
|
||||||
DBPropEnum(child->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
|
DBPropEnum(child->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -501,6 +524,7 @@ dbFlatCopyMaskHintsFunc(scx, def)
|
||||||
puds.puds_source = scx->scx_use->cu_def;
|
puds.puds_source = scx->scx_use->cu_def;
|
||||||
puds.puds_dest = def;
|
puds.puds_dest = def;
|
||||||
puds.puds_trans = &scx->scx_trans;
|
puds.puds_trans = &scx->scx_trans;
|
||||||
|
puds.puds_area = &scx->scx_area;
|
||||||
|
|
||||||
DBPropEnum(use->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
|
DBPropEnum(use->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
|
||||||
|
|
||||||
|
|
@ -967,14 +991,15 @@ DBCellGenerateSimpleSubstrate(scx, subType, notSubMask, targetDef)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbEraseSubFunc(tile, cxp)
|
dbEraseSubFunc(tile, dinfo, cxp)
|
||||||
Tile *tile; /* Pointer to source tile with shield type */
|
Tile *tile; /* Pointer to source tile with shield type */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
||||||
{
|
{
|
||||||
SearchContext *scx;
|
SearchContext *scx;
|
||||||
Rect sourceRect, targetRect;
|
Rect sourceRect, targetRect;
|
||||||
int pNum;
|
int pNum;
|
||||||
TileType dinfo, loctype, subType;
|
TileType newdinfo, loctype, subType;
|
||||||
Plane *plane;
|
Plane *plane;
|
||||||
struct dbCopySubData *csd; /* Client data */
|
struct dbCopySubData *csd; /* Client data */
|
||||||
|
|
||||||
|
|
@ -983,13 +1008,14 @@ dbEraseSubFunc(tile, cxp)
|
||||||
plane = csd->csd_plane;
|
plane = csd->csd_plane;
|
||||||
pNum = csd->csd_pNum;
|
pNum = csd->csd_pNum;
|
||||||
subType = csd->csd_subtype;
|
subType = csd->csd_subtype;
|
||||||
dinfo = TiGetTypeExact(tile);
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
if (loctype == TT_SPACE) return 0;
|
if (loctype == TT_SPACE) return 0;
|
||||||
dinfo = DBTransformDiagonal(dinfo, &scx->scx_trans);
|
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, &scx->scx_trans);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
newdinfo = (TileType)0;
|
||||||
|
|
||||||
/* Construct the rect for the tile */
|
/* Construct the rect for the tile */
|
||||||
TITORECT(tile, &sourceRect);
|
TITORECT(tile, &sourceRect);
|
||||||
|
|
@ -999,7 +1025,7 @@ dbEraseSubFunc(tile, cxp)
|
||||||
|
|
||||||
csd->csd_modified = TRUE;
|
csd->csd_modified = TRUE;
|
||||||
|
|
||||||
return DBNMPaintPlane(plane, dinfo, &targetRect, DBStdEraseTbl(subType, pNum),
|
return DBNMPaintPlane(plane, newdinfo, &targetRect, DBStdEraseTbl(subType, pNum),
|
||||||
(PaintUndoInfo *)NULL);
|
(PaintUndoInfo *)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1011,14 +1037,15 @@ dbEraseSubFunc(tile, cxp)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbPaintSubFunc(tile, cxp)
|
dbPaintSubFunc(tile, dinfo, cxp)
|
||||||
Tile *tile; /* Pointer to source tile with shield type */
|
Tile *tile; /* Pointer to source tile with shield type */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
||||||
{
|
{
|
||||||
SearchContext *scx;
|
SearchContext *scx;
|
||||||
Rect sourceRect, targetRect;
|
Rect sourceRect, targetRect;
|
||||||
int pNum;
|
int pNum;
|
||||||
TileType dinfo, loctype, subType;
|
TileType newdinfo, loctype, subType;
|
||||||
Plane *plane;
|
Plane *plane;
|
||||||
struct dbCopySubData *csd; /* Client data */
|
struct dbCopySubData *csd; /* Client data */
|
||||||
|
|
||||||
|
|
@ -1027,13 +1054,14 @@ dbPaintSubFunc(tile, cxp)
|
||||||
plane = csd->csd_plane;
|
plane = csd->csd_plane;
|
||||||
pNum = csd->csd_pNum;
|
pNum = csd->csd_pNum;
|
||||||
subType = csd->csd_subtype;
|
subType = csd->csd_subtype;
|
||||||
dinfo = TiGetTypeExact(tile);
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
if (loctype == TT_SPACE) return 0;
|
if (loctype == TT_SPACE) return 0;
|
||||||
dinfo = DBTransformDiagonal(dinfo, &scx->scx_trans);
|
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, &scx->scx_trans);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
newdinfo = (TileType)0;
|
||||||
|
|
||||||
/* Construct the rect for the tile */
|
/* Construct the rect for the tile */
|
||||||
TITORECT(tile, &sourceRect);
|
TITORECT(tile, &sourceRect);
|
||||||
|
|
@ -1043,7 +1071,7 @@ dbPaintSubFunc(tile, cxp)
|
||||||
|
|
||||||
csd->csd_modified = TRUE;
|
csd->csd_modified = TRUE;
|
||||||
|
|
||||||
return DBNMPaintPlane(plane, dinfo, &targetRect, DBStdPaintTbl(subType, pNum),
|
return DBNMPaintPlane(plane, newdinfo, &targetRect, DBStdPaintTbl(subType, pNum),
|
||||||
(PaintUndoInfo *)NULL);
|
(PaintUndoInfo *)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1056,14 +1084,15 @@ dbPaintSubFunc(tile, cxp)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbEraseNonSub(tile, cxp)
|
dbEraseNonSub(tile, dinfo, cxp)
|
||||||
Tile *tile; /* Pointer to tile to erase from target */
|
Tile *tile; /* Pointer to tile to erase from target */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
||||||
{
|
{
|
||||||
SearchContext *scx;
|
SearchContext *scx;
|
||||||
Rect sourceRect, targetRect;
|
Rect sourceRect, targetRect;
|
||||||
Plane *plane; /* Plane of target data */
|
Plane *plane; /* Plane of target data */
|
||||||
TileType dinfo, loctype, subType;
|
TileType newdinfo, loctype, subType;
|
||||||
struct dbCopySubData *csd;
|
struct dbCopySubData *csd;
|
||||||
int pNum;
|
int pNum;
|
||||||
|
|
||||||
|
|
@ -1074,13 +1103,14 @@ dbEraseNonSub(tile, cxp)
|
||||||
|
|
||||||
scx = cxp->tc_scx;
|
scx = cxp->tc_scx;
|
||||||
|
|
||||||
dinfo = TiGetTypeExact(tile);
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
if (loctype == TT_SPACE) return 0;
|
if (loctype == TT_SPACE) return 0;
|
||||||
dinfo = DBTransformDiagonal(dinfo, &scx->scx_trans);
|
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, &scx->scx_trans);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
newdinfo = (TileType)0;
|
||||||
|
|
||||||
/* Construct the rect for the tile */
|
/* Construct the rect for the tile */
|
||||||
TITORECT(tile, &sourceRect);
|
TITORECT(tile, &sourceRect);
|
||||||
|
|
@ -1089,7 +1119,7 @@ dbEraseNonSub(tile, cxp)
|
||||||
GEOTRANSRECT(&scx->scx_trans, &sourceRect, &targetRect);
|
GEOTRANSRECT(&scx->scx_trans, &sourceRect, &targetRect);
|
||||||
|
|
||||||
/* Erase the substrate type from the area of this tile in the target plane. */
|
/* Erase the substrate type from the area of this tile in the target plane. */
|
||||||
return DBNMPaintPlane(plane, dinfo, &targetRect, DBStdEraseTbl(subType, pNum),
|
return DBNMPaintPlane(plane, newdinfo, &targetRect, DBStdEraseTbl(subType, pNum),
|
||||||
(PaintUndoInfo *)NULL);
|
(PaintUndoInfo *)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1101,8 +1131,9 @@ dbEraseNonSub(tile, cxp)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCopySubFunc(tile, csd)
|
dbCopySubFunc(tile, dinfo, csd)
|
||||||
Tile *tile; /* Pointer to tile to erase from target */
|
Tile *tile; /* Pointer to tile to erase from target */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
struct dbCopySubData *csd; /* Client data */
|
struct dbCopySubData *csd; /* Client data */
|
||||||
{
|
{
|
||||||
Rect rect;
|
Rect rect;
|
||||||
|
|
@ -1112,10 +1143,10 @@ dbCopySubFunc(tile, csd)
|
||||||
|
|
||||||
plane = csd->csd_plane;
|
plane = csd->csd_plane;
|
||||||
pNum = csd->csd_pNum;
|
pNum = csd->csd_pNum;
|
||||||
type = TiGetTypeExact(tile);
|
type = TiGetTypeExact(tile) | dinfo;
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
if (loctype == TT_SPACE) return 0;
|
if (loctype == TT_SPACE) return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1436,8 +1467,9 @@ DBCellCopyLabels(scx, mask, xMask, targetUse, pArea)
|
||||||
***/
|
***/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCopyManhattanPaint(tile, cxp)
|
dbCopyManhattanPaint(tile, dinfo, cxp)
|
||||||
Tile *tile; /* Pointer to tile to copy */
|
Tile *tile; /* Pointer to tile to copy */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
||||||
{
|
{
|
||||||
SearchContext *scx = cxp->tc_scx;
|
SearchContext *scx = cxp->tc_scx;
|
||||||
|
|
@ -1483,8 +1515,9 @@ dbCopyManhattanPaint(tile, cxp)
|
||||||
***/
|
***/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCopyAllPaint(tile, cxp)
|
dbCopyAllPaint(tile, dinfo, cxp)
|
||||||
Tile *tile; /* Pointer to tile to copy */
|
Tile *tile; /* Pointer to tile to copy */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
||||||
{
|
{
|
||||||
SearchContext *scx = cxp->tc_scx;
|
SearchContext *scx = cxp->tc_scx;
|
||||||
|
|
@ -1492,7 +1525,7 @@ dbCopyAllPaint(tile, cxp)
|
||||||
Rect sourceRect, targetRect;
|
Rect sourceRect, targetRect;
|
||||||
PaintUndoInfo ui;
|
PaintUndoInfo ui;
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
TileType type = TiGetTypeExact(tile);
|
TileType type = TiGetTypeExact(tile) | dinfo;
|
||||||
int pNum = cxp->tc_plane;
|
int pNum = cxp->tc_plane;
|
||||||
int result;
|
int result;
|
||||||
TileTypeBitMask *typeMask;
|
TileTypeBitMask *typeMask;
|
||||||
|
|
@ -1505,13 +1538,13 @@ dbCopyAllPaint(tile, cxp)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool splittile = FALSE;
|
bool splittile = FALSE;
|
||||||
TileType dinfo = 0;
|
TileType newdinfo = 0;
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
splittile = TRUE;
|
splittile = TRUE;
|
||||||
dinfo = DBTransformDiagonal(type, &scx->scx_trans);
|
newdinfo = DBTransformDiagonal(type, &scx->scx_trans);
|
||||||
type = (SplitSide(tile)) ? SplitRightType(tile) :
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile) :
|
||||||
SplitLeftType(tile);
|
SplitLeftType(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1571,7 +1604,7 @@ dbCopyAllPaint(tile, cxp)
|
||||||
Rect rrect, orect;
|
Rect rrect, orect;
|
||||||
int np, i, j;
|
int np, i, j;
|
||||||
|
|
||||||
GrClipTriangle(&targetRect, &arg->caa_rect, TRUE, dinfo, points, &np);
|
GrClipTriangle(&targetRect, &arg->caa_rect, TRUE, newdinfo, points, &np);
|
||||||
|
|
||||||
if (np == 0)
|
if (np == 0)
|
||||||
return(0);
|
return(0);
|
||||||
|
|
@ -1600,7 +1633,7 @@ dbCopyAllPaint(tile, cxp)
|
||||||
rrect.r_ybot = points[0].p_y;
|
rrect.r_ybot = points[0].p_y;
|
||||||
rrect.r_ytop = points[2].p_y;
|
rrect.r_ytop = points[2].p_y;
|
||||||
GeoCanonicalRect(&rrect, &targetRect);
|
GeoCanonicalRect(&rrect, &targetRect);
|
||||||
dinfo = 0;
|
newdinfo = 0;
|
||||||
}
|
}
|
||||||
else if (np >= 4) /* Process extra rectangles in the area */
|
else if (np >= 4) /* Process extra rectangles in the area */
|
||||||
{
|
{
|
||||||
|
|
@ -1657,7 +1690,7 @@ topbottom:
|
||||||
|
|
||||||
splitdone:
|
splitdone:
|
||||||
|
|
||||||
result = (*dbCurPaintPlane)(def, pNum, dinfo | type, &targetRect, &ui);
|
result = (*dbCurPaintPlane)(def, pNum, newdinfo | type, &targetRect, &ui);
|
||||||
if ((result != 0) && (arg->caa_func != NULL))
|
if ((result != 0) && (arg->caa_func != NULL))
|
||||||
{
|
{
|
||||||
/* result == 1 used exclusively for DRC off-grid error flagging */
|
/* result == 1 used exclusively for DRC off-grid error flagging */
|
||||||
|
|
|
||||||
|
|
@ -152,10 +152,9 @@ DBCellRename(cellname, newname, doforce)
|
||||||
|
|
||||||
if (doforce && ((celldef->cd_flags & CDVENDORGDS) == CDVENDORGDS))
|
if (doforce && ((celldef->cd_flags & CDVENDORGDS) == CDVENDORGDS))
|
||||||
{
|
{
|
||||||
char *chkgdsfile;
|
|
||||||
bool isReadOnly;
|
bool isReadOnly;
|
||||||
|
|
||||||
chkgdsfile = (char *)DBPropGet(celldef, "GDS_FILE", &isReadOnly);
|
DBPropGet(celldef, "GDS_FILE", &isReadOnly);
|
||||||
/* Note that clearing GDS_FILE will also clear CDVENDORGDS flag */
|
/* Note that clearing GDS_FILE will also clear CDVENDORGDS flag */
|
||||||
if (isReadOnly) DBPropPut(celldef, "GDS_FILE", NULL);
|
if (isReadOnly) DBPropPut(celldef, "GDS_FILE", NULL);
|
||||||
|
|
||||||
|
|
@ -1620,7 +1619,9 @@ dbAbutmentUseFunc(selUse, use, transform, data)
|
||||||
{
|
{
|
||||||
Rect bbox, refbox;
|
Rect bbox, refbox;
|
||||||
Transform *trans;
|
Transform *trans;
|
||||||
|
PropertyRecord *proprec;
|
||||||
char *propvalue;
|
char *propvalue;
|
||||||
|
char *refllx, *reflly, *refurx, *refury;
|
||||||
bool found;
|
bool found;
|
||||||
bool *dolist = (bool *)data;
|
bool *dolist = (bool *)data;
|
||||||
|
|
||||||
|
|
@ -1642,32 +1643,47 @@ dbAbutmentUseFunc(selUse, use, transform, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
trans = &use->cu_transform;
|
trans = &use->cu_transform;
|
||||||
propvalue = (char *)DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
proprec = DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
||||||
if (!found)
|
if (!found)
|
||||||
bbox = use->cu_def->cd_bbox;
|
bbox = use->cu_def->cd_bbox;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||||
&bbox.r_xtop, &bbox.r_ytop) != 4)
|
(proprec->prop_len == 4))
|
||||||
|
{
|
||||||
|
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
||||||
|
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
||||||
|
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
||||||
|
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TxError("Unable to parse the cell's FIXED_BBOX property; using "
|
||||||
|
"the instance bounding box instead.\n");
|
||||||
bbox = use->cu_def->cd_bbox;
|
bbox = use->cu_def->cd_bbox;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
GeoTransRect(trans, &bbox, &refbox);
|
GeoTransRect(trans, &bbox, &refbox);
|
||||||
|
|
||||||
|
/* NOTE: Ideally, the MagWindow pointer should get passed to this routine */
|
||||||
|
refllx = DBWPrintValue(refbox.r_xbot, (MagWindow *)NULL, TRUE);
|
||||||
|
reflly = DBWPrintValue(refbox.r_ybot, (MagWindow *)NULL, FALSE);
|
||||||
|
refurx = DBWPrintValue(refbox.r_xtop, (MagWindow *)NULL, TRUE);
|
||||||
|
refury = DBWPrintValue(refbox.r_ytop, (MagWindow *)NULL, FALSE);
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
if (*dolist)
|
if (*dolist)
|
||||||
{
|
{
|
||||||
pobj = Tcl_NewListObj(0, NULL);
|
pobj = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_xbot));
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(refllx, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_ybot));
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(reflly, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_xtop));
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(refurx, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_ytop));
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(refury, -1));
|
||||||
Tcl_SetObjResult(magicinterp, pobj);
|
Tcl_SetObjResult(magicinterp, pobj);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
TxPrintf("Abutment box: %d %d %d %d\n", refbox.r_xbot, refbox.r_ybot,
|
TxPrintf("Abutment box: %s %s %s %s\n", refllx, reflly, refurx, refury);
|
||||||
refbox.r_xtop, refbox.r_ytop);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,7 @@ DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg
|
||||||
* int
|
* int
|
||||||
* func(tile, cxp)
|
* func(tile, cxp)
|
||||||
* Tile *tile;
|
* Tile *tile;
|
||||||
|
* TileType dinfo;
|
||||||
* TreeContext *cxp;
|
* TreeContext *cxp;
|
||||||
* {
|
* {
|
||||||
* }
|
* }
|
||||||
|
|
@ -416,6 +417,7 @@ dbCellUniqueTileSrFunc(scx, fp)
|
||||||
* int
|
* int
|
||||||
* func(tile, cxp)
|
* func(tile, cxp)
|
||||||
* Tile *tile;
|
* Tile *tile;
|
||||||
|
* TileType dinfo;
|
||||||
* TreeContext *cxp;
|
* TreeContext *cxp;
|
||||||
* {
|
* {
|
||||||
* }
|
* }
|
||||||
|
|
@ -914,8 +916,9 @@ DBSeeTypesAll(rootUse, rootRect, xMask, mask)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbSeeTypesAllSrFunc(tile, cxp)
|
dbSeeTypesAllSrFunc(tile, dinfo, cxp)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
TreeContext *cxp;
|
TreeContext *cxp;
|
||||||
{
|
{
|
||||||
Rect tileRect;
|
Rect tileRect;
|
||||||
|
|
@ -926,7 +929,7 @@ dbSeeTypesAllSrFunc(tile, cxp)
|
||||||
if (GEO_OVERLAP((&tileRect), area))
|
if (GEO_OVERLAP((&tileRect), area))
|
||||||
{
|
{
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
TTMaskSetType(mask, SplitSide(tile) ?
|
TTMaskSetType(mask, (dinfo & TT_SIDE) ?
|
||||||
SplitRightType(tile) : SplitLeftType(tile));
|
SplitRightType(tile) : SplitLeftType(tile));
|
||||||
else
|
else
|
||||||
TTMaskSetType(mask, TiGetType(tile));
|
TTMaskSetType(mask, TiGetType(tile));
|
||||||
|
|
@ -1607,8 +1610,9 @@ dbScalePlane(oldplane, newplane, pnum, scalen, scaled, doCIF)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbTileScaleFunc(tile, scvals)
|
dbTileScaleFunc(tile, dinfo, scvals)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
struct scaleArg *scvals;
|
struct scaleArg *scvals;
|
||||||
{
|
{
|
||||||
TileType type;
|
TileType type;
|
||||||
|
|
@ -1631,10 +1635,10 @@ dbTileScaleFunc(tile, scvals)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
type = TiGetTypeExact(tile);
|
type = TiGetTypeExact(tile) | dinfo;
|
||||||
exact = type;
|
exact = type;
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
DBNMPaintPlane(scvals->ptarget, exact, &targetRect,
|
DBNMPaintPlane(scvals->ptarget, exact, &targetRect,
|
||||||
(
|
(
|
||||||
#ifdef CIF_MODULE
|
#ifdef CIF_MODULE
|
||||||
|
|
@ -1689,8 +1693,9 @@ dbMovePlane(oldplane, newplane, pnum, origx, origy)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbTileMoveFunc(tile, mvvals)
|
dbTileMoveFunc(tile, dinfo, mvvals)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
struct moveArg *mvvals;
|
struct moveArg *mvvals;
|
||||||
{
|
{
|
||||||
TileType type;
|
TileType type;
|
||||||
|
|
@ -1703,12 +1708,12 @@ dbTileMoveFunc(tile, mvvals)
|
||||||
DBMovePoint(&targetRect.r_ll, mvvals->origx, mvvals->origy);
|
DBMovePoint(&targetRect.r_ll, mvvals->origx, mvvals->origy);
|
||||||
DBMovePoint(&targetRect.r_ur, mvvals->origx, mvvals->origy);
|
DBMovePoint(&targetRect.r_ur, mvvals->origx, mvvals->origy);
|
||||||
|
|
||||||
type = TiGetTypeExact(tile);
|
type = TiGetTypeExact(tile) | dinfo;
|
||||||
exact = type;
|
exact = type;
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
DBNMPaintPlane(mvvals->ptarget, exact, &targetRect,
|
DBNMPaintPlane(mvvals->ptarget, exact, &targetRect,
|
||||||
DBStdPaintTbl(type, mvvals->pnum),
|
(mvvals->pnum < 0) ? CIFPaintTable : DBStdPaintTbl(type, mvvals->pnum),
|
||||||
(PaintUndoInfo *)NULL);
|
(PaintUndoInfo *)NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1801,84 +1806,48 @@ typedef struct _cellpropstruct {
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int dbScaleProp(name, value, cps)
|
int dbScaleProp(name, proprec, cps)
|
||||||
char *name;
|
char *name;
|
||||||
char *value;
|
PropertyRecord *proprec;
|
||||||
CellPropStruct *cps;
|
CellPropStruct *cps;
|
||||||
{
|
{
|
||||||
int scalen, scaled;
|
int i, scalen, scaled;
|
||||||
char *newvalue, *vptr;
|
Point p;
|
||||||
Rect r;
|
|
||||||
|
|
||||||
if ((strlen(name) > 5) && !strncmp(name + strlen(name) - 5, "_BBOX", 5))
|
/* Only "dimension" and "plane" type properties get scaled */
|
||||||
{
|
|
||||||
if (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
if (proprec->prop_type == PROPERTY_TYPE_PLANE)
|
||||||
&r.r_xtop, &r.r_ytop) == 4)
|
|
||||||
{
|
{
|
||||||
|
Plane *newplane;
|
||||||
|
newplane = DBNewPlane((ClientData)TT_SPACE);
|
||||||
|
DBClearPaintPlane(newplane);
|
||||||
|
/* Plane index is unused; arbitrarily substitute -1 */
|
||||||
|
dbScalePlane(proprec->prop_value.prop_plane, newplane, -1,
|
||||||
|
scalen, scaled, TRUE);
|
||||||
|
DBFreePaintPlane(proprec->prop_value.prop_plane);
|
||||||
|
TiFreePlane(proprec->prop_value.prop_plane);
|
||||||
|
proprec->prop_value.prop_plane = newplane;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
|
||||||
|
|
||||||
/* Scale numerator held in point X value, */
|
/* Scale numerator held in point X value, */
|
||||||
/* scale denominator held in point Y value */
|
/* scale denominator held in point Y value */
|
||||||
|
|
||||||
scalen = cps->cps_point.p_x;
|
scalen = cps->cps_point.p_x;
|
||||||
scaled = cps->cps_point.p_y;
|
scaled = cps->cps_point.p_y;
|
||||||
|
|
||||||
DBScalePoint(&r.r_ll, scalen, scaled);
|
for (i = 0; i < proprec->prop_len; i += 2)
|
||||||
DBScalePoint(&r.r_ur, scalen, scaled);
|
|
||||||
|
|
||||||
newvalue = (char *)mallocMagic(40);
|
|
||||||
sprintf(newvalue, "%d %d %d %d", r.r_xbot, r.r_ybot,
|
|
||||||
r.r_xtop, r.r_ytop);
|
|
||||||
DBPropPut(cps->cps_def, name, newvalue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!strncmp(name, "MASKHINTS_", 10))
|
|
||||||
{
|
{
|
||||||
char *vptr, *lastval;
|
if ((i + 1) >= proprec->prop_len) break;
|
||||||
int lastlen;
|
|
||||||
|
|
||||||
newvalue = (char *)NULL;
|
p.p_x = proprec->prop_value.prop_integer[i];
|
||||||
vptr = value;
|
p.p_y = proprec->prop_value.prop_integer[i + 1];
|
||||||
while (*vptr != '\0')
|
DBScalePoint(&p, scalen, scaled);
|
||||||
{
|
proprec->prop_value.prop_integer[i] = p.p_x;
|
||||||
if (sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
proprec->prop_value.prop_integer[i + 1] = p.p_y;
|
||||||
&r.r_xtop, &r.r_ytop) == 4)
|
|
||||||
{
|
|
||||||
/* Scale numerator held in point X value, */
|
|
||||||
/* scale denominator held in point Y value */
|
|
||||||
|
|
||||||
scalen = cps->cps_point.p_x;
|
|
||||||
scaled = cps->cps_point.p_y;
|
|
||||||
|
|
||||||
DBScalePoint(&r.r_ll, scalen, scaled);
|
|
||||||
DBScalePoint(&r.r_ur, scalen, scaled);
|
|
||||||
|
|
||||||
lastval = newvalue;
|
|
||||||
lastlen = (lastval) ? strlen(lastval) : 0;
|
|
||||||
newvalue = mallocMagic(40 + lastlen);
|
|
||||||
|
|
||||||
if (lastval)
|
|
||||||
strcpy(newvalue, lastval);
|
|
||||||
else
|
|
||||||
*newvalue = '\0';
|
|
||||||
|
|
||||||
sprintf(newvalue + lastlen, "%s%d %d %d %d", (lastval) ? " " : "",
|
|
||||||
r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop);
|
|
||||||
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++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && !isspace(*vptr)) vptr++;
|
|
||||||
while (*vptr && isspace(*vptr)) vptr++;
|
|
||||||
}
|
|
||||||
else break;
|
|
||||||
}
|
|
||||||
if (newvalue)
|
|
||||||
DBPropPut(cps->cps_def, name, newvalue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0; /* Keep enumerating through properties */
|
return 0; /* Keep enumerating through properties */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1894,33 +1863,47 @@ int dbScaleProp(name, value, cps)
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int dbMoveProp(name, value, cps)
|
int dbMoveProp(name, proprec, cps)
|
||||||
char *name;
|
char *name;
|
||||||
char *value;
|
PropertyRecord *proprec;
|
||||||
CellPropStruct *cps;
|
CellPropStruct *cps;
|
||||||
{
|
{
|
||||||
int origx, origy;
|
int i, origx, origy;
|
||||||
char *newvalue;
|
char *newvalue;
|
||||||
Rect r;
|
Point p;
|
||||||
|
|
||||||
if (((strlen(name) > 5) && !strncmp(name + strlen(name) - 5, "_BBOX", 5))
|
/* Only "dimension" and "plane" type properties get scaled */
|
||||||
|| !strncmp(name, "MASKHINTS_", 10))
|
|
||||||
{
|
if (proprec->prop_type == PROPERTY_TYPE_PLANE)
|
||||||
if (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
|
||||||
&r.r_xtop, &r.r_ytop) == 4)
|
|
||||||
{
|
{
|
||||||
|
Plane *newplane;
|
||||||
|
|
||||||
|
newplane = DBNewPlane((ClientData) TT_SPACE);
|
||||||
|
DBClearPaintPlane(newplane);
|
||||||
|
/* Use plane index -1 to indicate use of CIFPaintTable */
|
||||||
|
dbMovePlane(proprec->prop_value.prop_plane, newplane, -1, origx, origy);
|
||||||
|
DBFreePaintPlane(proprec->prop_value.prop_plane);
|
||||||
|
TiFreePlane(proprec->prop_value.prop_plane);
|
||||||
|
proprec->prop_value.prop_plane = newplane;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
|
||||||
|
|
||||||
origx = cps->cps_point.p_x;
|
origx = cps->cps_point.p_x;
|
||||||
origy = cps->cps_point.p_y;
|
origy = cps->cps_point.p_y;
|
||||||
|
|
||||||
DBMovePoint(&r.r_ll, origx, origy);
|
for (i = 0; i < proprec->prop_len; i += 2)
|
||||||
DBMovePoint(&r.r_ur, origx, origy);
|
{
|
||||||
|
if ((i + 1) >= proprec->prop_len) break;
|
||||||
|
|
||||||
newvalue = (char *)mallocMagic(40);
|
p.p_x = proprec->prop_value.prop_integer[i];
|
||||||
sprintf(newvalue, "%d %d %d %d", r.r_xbot, r.r_ybot,
|
p.p_y = proprec->prop_value.prop_integer[i + 1];
|
||||||
r.r_xtop, r.r_ytop);
|
DBMovePoint(&p, origx, origy);
|
||||||
DBPropPut(cps->cps_def, name, newvalue);
|
proprec->prop_value.prop_integer[i] = p.p_x;
|
||||||
}
|
proprec->prop_value.prop_integer[i + 1] = p.p_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0; /* Keep enumerating through properties */
|
return 0; /* Keep enumerating through properties */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -128,85 +128,6 @@ DBInvTransformDiagonal(oldtype, trans)
|
||||||
return dinfo;
|
return dinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* DBSrConnectOnePlane --
|
|
||||||
*
|
|
||||||
* Search from a starting tile to find all paint that is electrically
|
|
||||||
* connected to that tile in the same plane.
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* 0 is returned if the search finished normally. 1 is returned
|
|
||||||
* if the search was aborted.
|
|
||||||
*
|
|
||||||
* Side effects:
|
|
||||||
* For every paint tile that is electrically connected to the initial
|
|
||||||
* tile, func is called. Func should have the following form:
|
|
||||||
*
|
|
||||||
* int
|
|
||||||
* func(tile, clientData)
|
|
||||||
* Tile *tile;
|
|
||||||
* ClientData clientData;
|
|
||||||
* {
|
|
||||||
* }
|
|
||||||
*
|
|
||||||
* The clientData passed to func is the same one that was passed
|
|
||||||
* to us. Func returns 0 under normal conditions; if it returns
|
|
||||||
* 1 then the search is aborted.
|
|
||||||
*
|
|
||||||
* *** WARNING ***
|
|
||||||
*
|
|
||||||
* Func should not modify any paint during the search, since this
|
|
||||||
* will mess up pointers kept by these procedures and likely cause
|
|
||||||
* a core-dump.
|
|
||||||
*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
DBSrConnectOnePlane(startTile, connect, func, clientData)
|
|
||||||
Tile *startTile; /* Starting tile for search */
|
|
||||||
TileTypeBitMask *connect; /* Pointer to a table indicating what tile
|
|
||||||
* types connect to what other tile types.
|
|
||||||
* Each entry gives a mask of types that
|
|
||||||
* connect to tiles of a given type.
|
|
||||||
*/
|
|
||||||
int (*func)(); /* Function to apply at each connected tile. */
|
|
||||||
ClientData clientData; /* Client data for above function. */
|
|
||||||
|
|
||||||
{
|
|
||||||
struct conSrArg csa;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
result = 0;
|
|
||||||
csa.csa_def = (CellDef *)NULL;
|
|
||||||
csa.csa_bounds = TiPlaneRect;
|
|
||||||
|
|
||||||
/* Pass 1. During this pass the client function gets called. */
|
|
||||||
|
|
||||||
csa.csa_clientFunc = func;
|
|
||||||
csa.csa_clientData = clientData;
|
|
||||||
csa.csa_clientDefault = startTile->ti_client;
|
|
||||||
csa.csa_clear = FALSE;
|
|
||||||
csa.csa_connect = connect;
|
|
||||||
csa.csa_pNum = -1;
|
|
||||||
if (dbSrConnectFunc(startTile, PTR2CD(&csa)) != 0) result = 1;
|
|
||||||
|
|
||||||
/* Pass 2. Don't call any client function, just clear the marks.
|
|
||||||
* Don't allow any interruptions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
SigDisableInterrupts();
|
|
||||||
csa.csa_clientFunc = NULL;
|
|
||||||
csa.csa_clear = TRUE;
|
|
||||||
(void) dbSrConnectFunc(startTile, PTR2CD(&csa));
|
|
||||||
SigEnableInterrupts();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -276,7 +197,7 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
{
|
{
|
||||||
struct conSrArg csa;
|
struct conSrArg csa;
|
||||||
int startPlane, result;
|
int startPlane, result;
|
||||||
Tile *startTile; /* Starting tile for search. */
|
TileAndDinfo start_tad; /* Starting tile and split information */
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
csa.csa_def = def;
|
csa.csa_def = def;
|
||||||
|
|
@ -287,17 +208,18 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
* the tile address and returns.
|
* the tile address and returns.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
startTile = NULL;
|
start_tad.tad_tile = NULL;
|
||||||
|
start_tad.tad_next = NULL; /* unused */
|
||||||
for (startPlane = PL_TECHDEPBASE; startPlane < DBNumPlanes; startPlane++)
|
for (startPlane = PL_TECHDEPBASE; startPlane < DBNumPlanes; startPlane++)
|
||||||
{
|
{
|
||||||
csa.csa_pNum = startPlane;
|
csa.csa_pNum = startPlane;
|
||||||
if (DBSrPaintArea((Tile *) NULL,
|
if (DBSrPaintArea((Tile *) NULL,
|
||||||
def->cd_planes[startPlane], startArea, mask,
|
def->cd_planes[startPlane], startArea, mask,
|
||||||
dbSrConnectStartFunc, PTR2CD(&startTile)) != 0) break;
|
dbSrConnectStartFunc, PTR2CD(&start_tad)) != 0) break;
|
||||||
}
|
}
|
||||||
if (startTile == NULL) return 0;
|
if (start_tad.tad_tile == NULL) return 0;
|
||||||
/* The following lets us call DBSrConnect recursively */
|
/* The following lets us call DBSrConnect recursively */
|
||||||
else if (startTile->ti_client == (ClientData)1) return 0;
|
else if (start_tad.tad_tile->ti_client == (ClientData)1) return 0;
|
||||||
|
|
||||||
/* Pass 1. During this pass the client function gets called. */
|
/* Pass 1. During this pass the client function gets called. */
|
||||||
|
|
||||||
|
|
@ -306,7 +228,8 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
csa.csa_clientDefault = CLIENTDEFAULT;
|
csa.csa_clientDefault = CLIENTDEFAULT;
|
||||||
csa.csa_clear = FALSE;
|
csa.csa_clear = FALSE;
|
||||||
csa.csa_connect = connect;
|
csa.csa_connect = connect;
|
||||||
if (dbSrConnectFunc(startTile, PTR2CD(&csa)) != 0) result = 1;
|
if (dbSrConnectFunc(start_tad.tad_tile, start_tad.tad_dinfo,
|
||||||
|
PTR2CD(&csa)) != 0) result = 1;
|
||||||
|
|
||||||
/* Pass 2. Don't call any client function, just clear the marks.
|
/* Pass 2. Don't call any client function, just clear the marks.
|
||||||
* Don't allow any interruptions.
|
* Don't allow any interruptions.
|
||||||
|
|
@ -315,7 +238,7 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
SigDisableInterrupts();
|
SigDisableInterrupts();
|
||||||
csa.csa_clientFunc = NULL;
|
csa.csa_clientFunc = NULL;
|
||||||
csa.csa_clear = TRUE;
|
csa.csa_clear = TRUE;
|
||||||
(void) dbSrConnectFunc(startTile, PTR2CD(&csa));
|
(void) dbSrConnectFunc(start_tad.tad_tile, start_tad.tad_dinfo, PTR2CD(&csa));
|
||||||
SigEnableInterrupts();
|
SigEnableInterrupts();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -325,11 +248,12 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
int
|
int
|
||||||
dbSrConnectStartFunc(
|
dbSrConnectStartFunc(
|
||||||
Tile *tile, /* This will be the starting tile. */
|
Tile *tile, /* This will be the starting tile. */
|
||||||
ClientData cdata) /* We store tile's address here. */
|
TileType dinfo, /* (unused) */
|
||||||
/* (Tile **pTile) */
|
ClientData cdata) /* We store tile and split info here. */
|
||||||
{
|
{
|
||||||
Tile **pTile = (Tile **)CD2PTR(cdata);
|
TileAndDinfo *tad = (TileAndDinfo *)CD2PTR(cdata);
|
||||||
*pTile = tile;
|
tad->tad_tile = tile;
|
||||||
|
tad->tad_dinfo = dinfo;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -367,7 +291,7 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
{
|
{
|
||||||
struct conSrArg csa;
|
struct conSrArg csa;
|
||||||
int startPlane, result;
|
int startPlane, result;
|
||||||
Tile *startTile; /* Starting tile for search. */
|
TileAndDinfo tad;
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
csa.csa_def = def;
|
csa.csa_def = def;
|
||||||
|
|
@ -378,17 +302,18 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
* the tile address and returns.
|
* the tile address and returns.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
startTile = NULL;
|
tad.tad_tile = NULL;
|
||||||
|
tad.tad_next = NULL; /* unused */
|
||||||
for (startPlane = PL_TECHDEPBASE; startPlane < DBNumPlanes; startPlane++)
|
for (startPlane = PL_TECHDEPBASE; startPlane < DBNumPlanes; startPlane++)
|
||||||
{
|
{
|
||||||
csa.csa_pNum = startPlane;
|
csa.csa_pNum = startPlane;
|
||||||
if (DBSrPaintArea((Tile *) NULL,
|
if (DBSrPaintArea((Tile *) NULL,
|
||||||
def->cd_planes[startPlane], startArea, mask,
|
def->cd_planes[startPlane], startArea, mask,
|
||||||
dbSrConnectStartFunc, PTR2CD(&startTile)) != 0) break;
|
dbSrConnectStartFunc, PTR2CD(&tad)) != 0) break;
|
||||||
}
|
}
|
||||||
if (startTile == NULL) return 0;
|
if (tad.tad_tile == NULL) return 0;
|
||||||
/* The following lets us call DBSrConnect recursively */
|
/* The following lets us call DBSrConnect recursively */
|
||||||
else if (startTile->ti_client == (ClientData)1) return 0;
|
else if (tad.tad_tile->ti_client == (ClientData)1) return 0;
|
||||||
|
|
||||||
/* Pass 1. During this pass the client function gets called. */
|
/* Pass 1. During this pass the client function gets called. */
|
||||||
|
|
||||||
|
|
@ -397,7 +322,7 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
csa.csa_clientDefault = CLIENTDEFAULT;
|
csa.csa_clientDefault = CLIENTDEFAULT;
|
||||||
csa.csa_clear = FALSE;
|
csa.csa_clear = FALSE;
|
||||||
csa.csa_connect = connect;
|
csa.csa_connect = connect;
|
||||||
if (dbSrConnectFunc(startTile, PTR2CD(&csa)) != 0) result = 1;
|
if (dbSrConnectFunc(tad.tad_tile, tad.tad_dinfo, PTR2CD(&csa)) != 0) result = 1;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -420,12 +345,15 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbcFindTileFunc(tile, arg)
|
dbcFindTileFunc(tile, dinfo, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
ClientData arg;
|
ClientData arg;
|
||||||
{
|
{
|
||||||
Tile **tptr = (Tile **)arg;
|
TileAndDinfo *tad = (TileAndDinfo *)arg;
|
||||||
*tptr = tile;
|
|
||||||
|
tad->tad_tile = tile;
|
||||||
|
tad->tad_dinfo = dinfo;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -465,6 +393,7 @@ dbcFindTileFunc(tile, arg)
|
||||||
int
|
int
|
||||||
dbSrConnectFunc(
|
dbSrConnectFunc(
|
||||||
Tile *tile, /* Tile that is connected. */
|
Tile *tile, /* Tile that is connected. */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
ClientData cdata) /* Contains information about the search. */
|
ClientData cdata) /* Contains information about the search. */
|
||||||
/* (struct conSrArg *csa) */
|
/* (struct conSrArg *csa) */
|
||||||
{
|
{
|
||||||
|
|
@ -484,11 +413,13 @@ dbSrConnectFunc(
|
||||||
/* Drop the first entry on the stack */
|
/* Drop the first entry on the stack */
|
||||||
pNum = csa->csa_pNum;
|
pNum = csa->csa_pNum;
|
||||||
STACKPUSH(INT2CD(tile), dbConnectStack);
|
STACKPUSH(INT2CD(tile), dbConnectStack);
|
||||||
|
STACKPUSH(INT2CD(dinfo), dbConnectStack);
|
||||||
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
||||||
|
|
||||||
while (!StackEmpty(dbConnectStack))
|
while (!StackEmpty(dbConnectStack))
|
||||||
{
|
{
|
||||||
pNum = (int)CD2INT(STACKPOP(dbConnectStack));
|
pNum = (int)CD2INT(STACKPOP(dbConnectStack));
|
||||||
|
dinfo = (int)CD2INT(STACKPOP(dbConnectStack));
|
||||||
tile = (Tile *)CD2INT(STACKPOP(dbConnectStack));
|
tile = (Tile *)CD2INT(STACKPOP(dbConnectStack));
|
||||||
if (result == 1) continue;
|
if (result == 1) continue;
|
||||||
|
|
||||||
|
|
@ -522,7 +453,7 @@ dbSrConnectFunc(
|
||||||
|
|
||||||
if (callClient && (csa->csa_clientFunc != NULL))
|
if (callClient && (csa->csa_clientFunc != NULL))
|
||||||
{
|
{
|
||||||
if ((*csa->csa_clientFunc)(tile, pNum, csa->csa_clientData) != 0)
|
if ((*csa->csa_clientFunc)(tile, dinfo, pNum, csa->csa_clientData) != 0)
|
||||||
{
|
{
|
||||||
result = 1;
|
result = 1;
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -536,7 +467,7 @@ dbSrConnectFunc(
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
if (SplitSide(tile))
|
if (dinfo & TT_SIDE)
|
||||||
loctype = SplitRightType(tile);
|
loctype = SplitRightType(tile);
|
||||||
else
|
else
|
||||||
loctype = SplitLeftType(tile);
|
loctype = SplitLeftType(tile);
|
||||||
|
|
@ -547,7 +478,7 @@ dbSrConnectFunc(
|
||||||
|
|
||||||
/* Left side: */
|
/* Left side: */
|
||||||
|
|
||||||
if (IsSplit(tile) && SplitSide(tile)) goto bottomside;
|
if (IsSplit(tile) && (dinfo & TT_SIDE)) goto bottomside;
|
||||||
|
|
||||||
for (t2 = BL(tile); BOTTOM(t2) < tileArea.r_ytop; t2 = RT(t2))
|
for (t2 = BL(tile); BOTTOM(t2) < tileArea.r_ytop; t2 = RT(t2))
|
||||||
{
|
{
|
||||||
|
|
@ -564,9 +495,11 @@ dbSrConnectFunc(
|
||||||
if (t2->ti_client == csa->csa_clientDefault) continue;
|
if (t2->ti_client == csa->csa_clientDefault) continue;
|
||||||
}
|
}
|
||||||
else if (t2->ti_client == (ClientData) 1) continue;
|
else if (t2->ti_client == (ClientData) 1) continue;
|
||||||
if (IsSplit(t2))
|
|
||||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) | TT_SIDE)); /* bit set */
|
|
||||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||||
|
if (IsSplit(t2))
|
||||||
|
STACKPUSH(INT2CD((TileType)TT_SIDE), dbConnectStack);
|
||||||
|
else
|
||||||
|
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||||
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -574,7 +507,7 @@ dbSrConnectFunc(
|
||||||
/* Bottom side: */
|
/* Bottom side: */
|
||||||
|
|
||||||
bottomside:
|
bottomside:
|
||||||
if (IsSplit(tile) && (!(SplitSide(tile) ^ SplitDirection(tile))))
|
if (IsSplit(tile) && ((!((dinfo & TT_SIDE) ? 1 : 0)) ^ SplitDirection(tile)))
|
||||||
goto rightside;
|
goto rightside;
|
||||||
|
|
||||||
for (t2 = LB(tile); LEFT(t2) < tileArea.r_xtop; t2 = TR(t2))
|
for (t2 = LB(tile); LEFT(t2) < tileArea.r_xtop; t2 = TR(t2))
|
||||||
|
|
@ -592,16 +525,17 @@ bottomside:
|
||||||
if (t2->ti_client == csa->csa_clientDefault) continue;
|
if (t2->ti_client == csa->csa_clientDefault) continue;
|
||||||
}
|
}
|
||||||
else if (t2->ti_client == (ClientData) 1) continue;
|
else if (t2->ti_client == (ClientData) 1) continue;
|
||||||
|
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||||
if (IsSplit(t2))
|
if (IsSplit(t2))
|
||||||
{
|
{
|
||||||
if (SplitDirection(t2))
|
if (SplitDirection(t2))
|
||||||
/* bit set */
|
STACKPUSH(INT2CD((TileType)TT_SIDE), dbConnectStack);
|
||||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) | TT_SIDE));
|
|
||||||
else
|
else
|
||||||
/* bit clear */
|
/* bit clear */
|
||||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) & ~TT_SIDE));
|
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||||
}
|
}
|
||||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
else
|
||||||
|
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||||
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -609,7 +543,7 @@ bottomside:
|
||||||
/* Right side: */
|
/* Right side: */
|
||||||
|
|
||||||
rightside:
|
rightside:
|
||||||
if (IsSplit(tile) && !SplitSide(tile)) goto topside;
|
if (IsSplit(tile) && !(dinfo & TT_SIDE)) goto topside;
|
||||||
|
|
||||||
for (t2 = TR(tile); ; t2 = LB(t2))
|
for (t2 = TR(tile); ; t2 = LB(t2))
|
||||||
{
|
{
|
||||||
|
|
@ -626,9 +560,8 @@ rightside:
|
||||||
if (t2->ti_client == csa->csa_clientDefault) goto nextRight;
|
if (t2->ti_client == csa->csa_clientDefault) goto nextRight;
|
||||||
}
|
}
|
||||||
else if (t2->ti_client == (ClientData) 1) goto nextRight;
|
else if (t2->ti_client == (ClientData) 1) goto nextRight;
|
||||||
if (IsSplit(t2))
|
|
||||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) & ~TT_SIDE)); /* bit clear */
|
|
||||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||||
|
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||||
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
||||||
}
|
}
|
||||||
nextRight: if (BOTTOM(t2) <= tileArea.r_ybot) break;
|
nextRight: if (BOTTOM(t2) <= tileArea.r_ybot) break;
|
||||||
|
|
@ -637,7 +570,8 @@ rightside:
|
||||||
/* Top side: */
|
/* Top side: */
|
||||||
topside:
|
topside:
|
||||||
|
|
||||||
if (IsSplit(tile) && (SplitSide(tile) ^ SplitDirection(tile))) goto donesides;
|
if (IsSplit(tile) && (((dinfo & TT_SIDE) ? 1 : 0) ^ SplitDirection(tile)))
|
||||||
|
goto donesides;
|
||||||
|
|
||||||
for (t2 = RT(tile); ; t2 = BL(t2))
|
for (t2 = RT(tile); ; t2 = BL(t2))
|
||||||
{
|
{
|
||||||
|
|
@ -654,16 +588,18 @@ topside:
|
||||||
if (t2->ti_client == csa->csa_clientDefault) goto nextTop;
|
if (t2->ti_client == csa->csa_clientDefault) goto nextTop;
|
||||||
}
|
}
|
||||||
else if (t2->ti_client == (ClientData) 1) goto nextTop;
|
else if (t2->ti_client == (ClientData) 1) goto nextTop;
|
||||||
|
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||||
if (IsSplit(t2))
|
if (IsSplit(t2))
|
||||||
{
|
{
|
||||||
if (SplitDirection(t2))
|
if (SplitDirection(t2))
|
||||||
/* bit clear */
|
/* bit clear */
|
||||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) & ~TT_SIDE));
|
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||||
else
|
else
|
||||||
/* bit set */
|
/* bit set */
|
||||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) | TT_SIDE));
|
STACKPUSH(INT2CD((TileType)TT_SIDE), dbConnectStack);
|
||||||
}
|
}
|
||||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
else
|
||||||
|
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||||
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
||||||
}
|
}
|
||||||
nextTop: if (LEFT(t2) <= tileArea.r_xbot) break;
|
nextTop: if (LEFT(t2) <= tileArea.r_xbot) break;
|
||||||
|
|
@ -682,6 +618,7 @@ donesides:
|
||||||
{
|
{
|
||||||
Rect newArea;
|
Rect newArea;
|
||||||
GEO_EXPAND(&tileArea, 1, &newArea);
|
GEO_EXPAND(&tileArea, 1, &newArea);
|
||||||
|
TileAndDinfo tad;
|
||||||
|
|
||||||
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
|
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -689,18 +626,20 @@ donesides:
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
if (DBSrPaintNMArea((Tile *) NULL, csa->csa_def->cd_planes[i],
|
if (DBSrPaintNMArea((Tile *) NULL, csa->csa_def->cd_planes[i],
|
||||||
TiGetTypeExact(tile), &newArea, connectMask,
|
TiGetTypeExact(tile) | dinfo, &newArea, connectMask,
|
||||||
dbcFindTileFunc, (ClientData)&t2) != 0)
|
dbcFindTileFunc, (ClientData)&tad) != 0)
|
||||||
{
|
{
|
||||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
STACKPUSH(PTR2CD(tad.tad_tile), dbConnectStack);
|
||||||
|
STACKPUSH(INT2CD(tad.tad_dinfo), dbConnectStack);
|
||||||
STACKPUSH(INT2CD(i), dbConnectStack);
|
STACKPUSH(INT2CD(i), dbConnectStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (DBSrPaintArea((Tile *) NULL, csa->csa_def->cd_planes[i],
|
else if (DBSrPaintArea((Tile *) NULL, csa->csa_def->cd_planes[i],
|
||||||
&newArea, connectMask, dbcFindTileFunc,
|
&newArea, connectMask, dbcFindTileFunc,
|
||||||
(ClientData)&t2) != 0)
|
(ClientData)&tad) != 0)
|
||||||
{
|
{
|
||||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
STACKPUSH(PTR2CD(tad.tad_tile), dbConnectStack);
|
||||||
|
STACKPUSH(INT2CD(tad.tad_dinfo), dbConnectStack);
|
||||||
STACKPUSH(INT2CD(i), dbConnectStack);
|
STACKPUSH(INT2CD(i), dbConnectStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -734,8 +673,9 @@ donesides:
|
||||||
/** @typedef cb_database_srpaintnmarea_t */
|
/** @typedef cb_database_srpaintnmarea_t */
|
||||||
/** @typedef cb_database_srpaintarea_t */
|
/** @typedef cb_database_srpaintarea_t */
|
||||||
int
|
int
|
||||||
dbcUnconnectFunc(tile, clientData)
|
dbcUnconnectFunc(tile, dinfo, clientData)
|
||||||
Tile *tile; /* Current tile */
|
Tile *tile; /* Current tile */
|
||||||
|
TileType dinfo; /* Split tile information, unused */
|
||||||
ClientData clientData; /* Unused. */
|
ClientData clientData; /* Unused. */
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -949,8 +889,9 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbcConnectFunc(tile, cx)
|
dbcConnectFunc(tile, dinfo, cx)
|
||||||
Tile *tile; /* Tile found. */
|
Tile *tile; /* Tile found. */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TreeContext *cx; /* Describes context of search. The client
|
TreeContext *cx; /* Describes context of search. The client
|
||||||
* data is a pointer to a conSrArg2 record
|
* data is a pointer to a conSrArg2 record
|
||||||
* containing various required information.
|
* containing various required information.
|
||||||
|
|
@ -963,8 +904,8 @@ dbcConnectFunc(tile, cx)
|
||||||
Rect *srArea;
|
Rect *srArea;
|
||||||
SearchContext *scx = cx->tc_scx;
|
SearchContext *scx = cx->tc_scx;
|
||||||
SearchContext scx2;
|
SearchContext scx2;
|
||||||
TileType loctype = TiGetTypeExact(tile);
|
TileType loctype = TiGetTypeExact(tile) | dinfo;
|
||||||
TileType dinfo = 0;
|
TileType newdinfo = 0;
|
||||||
int retval, i, pNum = cx->tc_plane;
|
int retval, i, pNum = cx->tc_plane;
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
|
|
||||||
|
|
@ -996,8 +937,8 @@ dbcConnectFunc(tile, cx)
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
dinfo = DBTransformDiagonal(loctype, &scx->scx_trans);
|
newdinfo = DBTransformDiagonal(loctype, &scx->scx_trans);
|
||||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
loctype = ((dinfo & TT_SIDE)) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See if the destination cell contains stuff over the whole
|
/* See if the destination cell contains stuff over the whole
|
||||||
|
|
@ -1035,7 +976,7 @@ dbcConnectFunc(tile, cx)
|
||||||
def = csa2->csa2_use->cu_def;
|
def = csa2->csa2_use->cu_def;
|
||||||
retval = 1;
|
retval = 1;
|
||||||
if (DBSrPaintNMArea((Tile *) NULL, def->cd_planes[pNum],
|
if (DBSrPaintNMArea((Tile *) NULL, def->cd_planes[pNum],
|
||||||
dinfo, &newarea, ¬ConnectMask, dbcUnconnectFunc,
|
newdinfo, &newarea, ¬ConnectMask, dbcUnconnectFunc,
|
||||||
(ClientData) NULL) == 0)
|
(ClientData) NULL) == 0)
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
||||||
|
|
@ -1044,7 +985,7 @@ dbcConnectFunc(tile, cx)
|
||||||
* the storage for the current list element.
|
* the storage for the current list element.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DBNMPaintPlane(def->cd_planes[pNum], dinfo,
|
DBNMPaintPlane(def->cd_planes[pNum], newdinfo,
|
||||||
&newarea, DBStdPaintTbl(loctype, pNum),
|
&newarea, DBStdPaintTbl(loctype, pNum),
|
||||||
(PaintUndoInfo *) NULL);
|
(PaintUndoInfo *) NULL);
|
||||||
|
|
||||||
|
|
@ -1061,14 +1002,14 @@ dbcConnectFunc(tile, cx)
|
||||||
|
|
||||||
/* Only extend those sides bordering the diagonal tile */
|
/* Only extend those sides bordering the diagonal tile */
|
||||||
|
|
||||||
if (dinfo & TT_DIAGONAL)
|
if (newdinfo & TT_DIAGONAL)
|
||||||
{
|
{
|
||||||
if (dinfo & TT_SIDE) /* right */
|
if (newdinfo & TT_SIDE) /* right */
|
||||||
newarea.r_xtop += 1;
|
newarea.r_xtop += 1;
|
||||||
else /* left */
|
else /* left */
|
||||||
newarea.r_xbot -= 1;
|
newarea.r_xbot -= 1;
|
||||||
if (((dinfo & TT_SIDE) >> 1)
|
if (((newdinfo & TT_SIDE) >> 1)
|
||||||
== (dinfo & TT_DIRECTION)) /* top */
|
== (newdinfo & TT_DIRECTION)) /* top */
|
||||||
newarea.r_ytop += 1;
|
newarea.r_ytop += 1;
|
||||||
else /* bottom */
|
else /* bottom */
|
||||||
newarea.r_ybot -= 1;
|
newarea.r_ybot -= 1;
|
||||||
|
|
@ -1108,7 +1049,7 @@ dbcConnectFunc(tile, cx)
|
||||||
|
|
||||||
csa2->csa2_list[csa2->csa2_top].area = newarea;
|
csa2->csa2_list[csa2->csa2_top].area = newarea;
|
||||||
csa2->csa2_list[csa2->csa2_top].connectMask = connectMask;
|
csa2->csa2_list[csa2->csa2_top].connectMask = connectMask;
|
||||||
csa2->csa2_list[csa2->csa2_top].dinfo = dinfo;
|
csa2->csa2_list[csa2->csa2_top].dinfo = newdinfo;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
958
database/DBio.c
958
database/DBio.c
File diff suppressed because it is too large
Load Diff
|
|
@ -583,8 +583,9 @@ DBReOrientLabel(cellDef, area, newPos)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbGetLabelArea(tile, area)
|
dbGetLabelArea(tile, dinfo, area)
|
||||||
Tile *tile; /* Tile found. */
|
Tile *tile; /* Tile found. */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
Rect *area; /* Area to be modified. */
|
Rect *area; /* Area to be modified. */
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
@ -1085,14 +1086,15 @@ DBPickLabelLayer(def, lab, doCalma)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbPickFunc1(tile, mask)
|
dbPickFunc1(tile, dinfo, mask)
|
||||||
Tile *tile; /* Tile found. */
|
Tile *tile; /* Tile found. */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TileTypeBitMask *mask; /* Mask to be modified. */
|
TileTypeBitMask *mask; /* Mask to be modified. */
|
||||||
{
|
{
|
||||||
TileType type;
|
TileType type;
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
else
|
else
|
||||||
type = TiGetType(tile);
|
type = TiGetType(tile);
|
||||||
|
|
||||||
|
|
@ -1111,15 +1113,16 @@ dbPickFunc1(tile, mask)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbPickFunc2(tile, mask)
|
dbPickFunc2(tile, dinfo, mask)
|
||||||
Tile *tile; /* Tile found. */
|
Tile *tile; /* Tile found. */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TileTypeBitMask *mask; /* Mask to be modified. */
|
TileTypeBitMask *mask; /* Mask to be modified. */
|
||||||
{
|
{
|
||||||
TileType type;
|
TileType type;
|
||||||
TileTypeBitMask tmp, *rMask;
|
TileTypeBitMask tmp, *rMask;
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
else
|
else
|
||||||
type = TiGetType(tile);
|
type = TiGetType(tile);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -487,8 +487,6 @@ enumerate:
|
||||||
newType = (method == (unsigned char)PAINT_XOR) ?
|
newType = (method == (unsigned char)PAINT_XOR) ?
|
||||||
*resultTbl : resultTbl[oldType];
|
*resultTbl : resultTbl[oldType];
|
||||||
|
|
||||||
if (mergeFlags & MRG_RIGHT)
|
|
||||||
tile = TiNMMergeRight(tile, plane); // was commented out?
|
|
||||||
if (mergeFlags & MRG_LEFT)
|
if (mergeFlags & MRG_LEFT)
|
||||||
TiNMMergeLeft(LB(newtile), plane);
|
TiNMMergeLeft(LB(newtile), plane);
|
||||||
}
|
}
|
||||||
|
|
@ -496,8 +494,6 @@ enumerate:
|
||||||
{
|
{
|
||||||
if (mergeFlags & MRG_LEFT)
|
if (mergeFlags & MRG_LEFT)
|
||||||
TiNMMergeLeft(newtile, plane);
|
TiNMMergeLeft(newtile, plane);
|
||||||
if (mergeFlags & MRG_RIGHT)
|
|
||||||
TiNMMergeRight(LB(tile), plane); // was commented out?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1439,10 +1435,6 @@ DBDiagonalProc(oldtype, dinfo)
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* For purposes of "undo" recording, record which side we just painted */
|
|
||||||
if (dinfo->side)
|
|
||||||
newtype |= TT_SIDE;
|
|
||||||
|
|
||||||
return newtype;
|
return newtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1824,14 +1816,15 @@ nextrect:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbNMEnumFunc(tile, arg)
|
dbNMEnumFunc(tile, dinfo, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
LinkedRect **arg;
|
LinkedRect **arg;
|
||||||
{
|
{
|
||||||
LinkedRect *lr;
|
LinkedRect *lr;
|
||||||
|
|
||||||
/* Ignore the second call to any diagonal---only count once! */
|
/* Ignore the second call to any diagonal---only count once! */
|
||||||
if (IsSplit(tile) && SplitSide(tile)) return 0;
|
if (IsSplit(tile) && (dinfo & TT_SIDE)) return 0;
|
||||||
|
|
||||||
lr = (LinkedRect *) mallocMagic(sizeof(LinkedRect));
|
lr = (LinkedRect *) mallocMagic(sizeof(LinkedRect));
|
||||||
TiToRect(tile, &lr->r_r);
|
TiToRect(tile, &lr->r_r);
|
||||||
|
|
|
||||||
|
|
@ -119,8 +119,9 @@ DBPaint (cellDef, rect, type)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbResolveImages(tile, cellDef)
|
dbResolveImages(tile, dinfo, cellDef)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
CellDef *cellDef;
|
CellDef *cellDef;
|
||||||
{
|
{
|
||||||
Rect rect;
|
Rect rect;
|
||||||
|
|
@ -130,7 +131,7 @@ dbResolveImages(tile, cellDef)
|
||||||
/* Recursive call back to DBPaint---this will ensure that */
|
/* Recursive call back to DBPaint---this will ensure that */
|
||||||
/* all of the planes of the image type are painted. */
|
/* all of the planes of the image type are painted. */
|
||||||
|
|
||||||
DBPaint(cellDef, &rect, TiGetTypeExact(tile));
|
DBPaint(cellDef, &rect, TiGetTypeExact(tile) | dinfo);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,16 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "database/database.h"
|
#include "database/database.h"
|
||||||
#include "utils/malloc.h"
|
#include "utils/malloc.h"
|
||||||
|
|
||||||
|
/* Global variable */
|
||||||
|
|
||||||
|
bool DBPropCompat = TRUE; /* If TRUE, then always save properties to
|
||||||
|
* .mag files as type "string" for backwards
|
||||||
|
* compatibility. If FALSE, then properties
|
||||||
|
* are saved to the .mag file along with their
|
||||||
|
* type. Regardless of the setting, properties
|
||||||
|
* which are reserved keywords are converted
|
||||||
|
* to the best internal representation on input.
|
||||||
|
*/
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -49,14 +59,14 @@ void
|
||||||
DBPropPut(cellDef, name, value)
|
DBPropPut(cellDef, name, value)
|
||||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||||
char *name; /* The name of the property desired. */
|
char *name; /* The name of the property desired. */
|
||||||
ClientData value; /* MUST point to a malloc'ed structure, or NULL.
|
PropertyRecord *value; /* MUST point to a malloc'ed structure, or NULL.
|
||||||
* This will be freed when the CellDef is freed.
|
* This will be freed when the CellDef is freed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
{
|
{
|
||||||
HashTable *htab;
|
HashTable *htab;
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
char *oldvalue;
|
PropertyRecord *oldvalue;
|
||||||
|
|
||||||
/* Honor the NOEDIT flag. Note that the caller always assumes that */
|
/* Honor the NOEDIT flag. Note that the caller always assumes that */
|
||||||
/* the value would be saved in the hash table, so if it is not */
|
/* the value would be saved in the hash table, so if it is not */
|
||||||
|
|
@ -95,12 +105,23 @@ DBPropPut(cellDef, name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = HashFind(htab, name);
|
entry = HashFind(htab, name);
|
||||||
oldvalue = (char *)HashGetValue(entry);
|
oldvalue = (PropertyRecord *)HashGetValue(entry);
|
||||||
if (oldvalue != NULL) freeMagic(oldvalue);
|
/* All properties are allocated as a single block and can just be freed,
|
||||||
if (value == (ClientData)NULL)
|
* except for plane properties, which require freeing the plane.
|
||||||
|
*/
|
||||||
|
if (oldvalue != NULL)
|
||||||
|
{
|
||||||
|
if (oldvalue->prop_type == PROPERTY_TYPE_PLANE)
|
||||||
|
{
|
||||||
|
DBFreePaintPlane(oldvalue->prop_value.prop_plane);
|
||||||
|
TiFreePlane(oldvalue->prop_value.prop_plane);
|
||||||
|
}
|
||||||
|
freeMagic((char *)oldvalue);
|
||||||
|
}
|
||||||
|
if (value == (PropertyRecord *)NULL)
|
||||||
HashRemove(htab, name);
|
HashRemove(htab, name);
|
||||||
else
|
else
|
||||||
HashSetValue(entry, value);
|
HashSetValue(entry, PTR2CD(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
|
|
@ -110,13 +131,13 @@ DBPropPut(cellDef, name, value)
|
||||||
* Get a property from a celldef.
|
* Get a property from a celldef.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* NULL if the property didn't exist, or if the property value was NULL.
|
* NULL if the property didn't exist, or if the property record was NULL.
|
||||||
* Otherwise, ClientData that represents the property.
|
* Otherwise, returns a pointer to the property record.
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ClientData
|
PropertyRecord *
|
||||||
DBPropGet(cellDef, name, found)
|
DBPropGet(cellDef, name, found)
|
||||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||||
char *name; /* The name of the property desired. */
|
char *name; /* The name of the property desired. */
|
||||||
|
|
@ -124,12 +145,12 @@ DBPropGet(cellDef, name, found)
|
||||||
* exists.
|
* exists.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
ClientData result;
|
PropertyRecord *result;
|
||||||
bool haveit;
|
bool haveit;
|
||||||
HashTable *htab;
|
HashTable *htab;
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
|
|
||||||
result = (ClientData) NULL;
|
result = (PropertyRecord *)NULL;
|
||||||
haveit = FALSE;
|
haveit = FALSE;
|
||||||
htab = (HashTable *) cellDef->cd_props;
|
htab = (HashTable *) cellDef->cd_props;
|
||||||
if (htab == (HashTable *) NULL) goto done;
|
if (htab == (HashTable *) NULL) goto done;
|
||||||
|
|
@ -138,7 +159,7 @@ DBPropGet(cellDef, name, found)
|
||||||
if (entry != NULL)
|
if (entry != NULL)
|
||||||
{
|
{
|
||||||
haveit = TRUE;
|
haveit = TRUE;
|
||||||
result = (ClientData) HashGetValue(entry);
|
result = (PropertyRecord *)HashGetValue(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
@ -146,6 +167,109 @@ done:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* DBPropGetString --
|
||||||
|
*
|
||||||
|
* Get a string property from a celldef.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* NULL if the property didn't exist, or if the property record was NULL.
|
||||||
|
* Otherwise, returns a pointer to the property's string record.
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* This is basically the original DBPropGet(), when properties were only
|
||||||
|
* allowed to be strings.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *
|
||||||
|
DBPropGetString(cellDef, name, found)
|
||||||
|
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||||
|
char *name; /* The name of the property desired. */
|
||||||
|
bool *found; /* If not NULL, filled in with TRUE iff the property
|
||||||
|
* exists.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
char *result = NULL;
|
||||||
|
PropertyRecord *proprec;
|
||||||
|
bool haveit;
|
||||||
|
HashTable *htab;
|
||||||
|
HashEntry *entry;
|
||||||
|
|
||||||
|
haveit = FALSE;
|
||||||
|
htab = (HashTable *) cellDef->cd_props;
|
||||||
|
if (htab == (HashTable *) NULL) goto pdone;
|
||||||
|
|
||||||
|
entry = HashLookOnly(htab, name);
|
||||||
|
if (entry != NULL)
|
||||||
|
{
|
||||||
|
proprec = (PropertyRecord *)HashGetValue(entry);
|
||||||
|
if (proprec->prop_type == PROPERTY_TYPE_STRING)
|
||||||
|
{
|
||||||
|
haveit = TRUE;
|
||||||
|
result = proprec->prop_value.prop_string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pdone:
|
||||||
|
if (found != (bool *) NULL) *found = haveit;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* DBPropGetDouble --
|
||||||
|
*
|
||||||
|
* Get a single double-long integer property from a celldef.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* NULL if the property didn't exist, or if the property record was NULL.
|
||||||
|
* Otherwise, returns a pointer to the property's value record.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
dlong
|
||||||
|
DBPropGetDouble(cellDef, name, found)
|
||||||
|
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||||
|
char *name; /* The name of the property desired. */
|
||||||
|
bool *found; /* If not NULL, filled in with TRUE iff the property
|
||||||
|
* exists.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
dlong result = 0;
|
||||||
|
PropertyRecord *proprec;
|
||||||
|
bool haveit;
|
||||||
|
HashTable *htab;
|
||||||
|
HashEntry *entry;
|
||||||
|
|
||||||
|
haveit = FALSE;
|
||||||
|
htab = (HashTable *) cellDef->cd_props;
|
||||||
|
if (htab == (HashTable *) NULL) goto ddone;
|
||||||
|
|
||||||
|
entry = HashLookOnly(htab, name);
|
||||||
|
if (entry != NULL)
|
||||||
|
{
|
||||||
|
proprec = (PropertyRecord *)HashGetValue(entry);
|
||||||
|
if (proprec->prop_type == PROPERTY_TYPE_DOUBLE)
|
||||||
|
{
|
||||||
|
haveit = TRUE;
|
||||||
|
result = proprec->prop_value.prop_double[0];
|
||||||
|
}
|
||||||
|
else if (proprec->prop_type == PROPERTY_TYPE_STRING)
|
||||||
|
{
|
||||||
|
haveit = TRUE;
|
||||||
|
sscanf(proprec->prop_value.prop_string, "%"DLONG_PREFIX"d", &result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ddone:
|
||||||
|
if (found != (bool *) NULL) *found = haveit;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* DBPropEnum --
|
* DBPropEnum --
|
||||||
|
|
@ -168,7 +292,7 @@ DBPropEnum(cellDef, func, cdata)
|
||||||
*
|
*
|
||||||
* int foo(name, value, cdata)
|
* int foo(name, value, cdata)
|
||||||
* char *name;
|
* char *name;
|
||||||
* ClientData value;
|
* PropertyRecord *value;
|
||||||
* ClientData cdata;
|
* ClientData cdata;
|
||||||
* {
|
* {
|
||||||
* -- return 0 to continue,
|
* -- return 0 to continue,
|
||||||
|
|
@ -189,7 +313,7 @@ DBPropEnum(cellDef, func, cdata)
|
||||||
HashStartSearch(&hs);
|
HashStartSearch(&hs);
|
||||||
while ((entry = HashNext(htab, &hs)) != NULL)
|
while ((entry = HashNext(htab, &hs)) != NULL)
|
||||||
{
|
{
|
||||||
res = (*func)(entry->h_key.h_name, (ClientData) entry->h_pointer, cdata);
|
res = (*func)(entry->h_key.h_name, (PropertyRecord *)entry->h_pointer, cdata);
|
||||||
if (res != 0) return res;
|
if (res != 0) return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,296 @@ struct dbCheck
|
||||||
|
|
||||||
int dbCheckMaxHFunc(), dbCheckMaxVFunc();
|
int dbCheckMaxHFunc(), dbCheckMaxVFunc();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* --------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* dbEvalCorner --
|
||||||
|
*
|
||||||
|
* Used by DBTestNMInteract() to determine whether two non-
|
||||||
|
* Manhattan areas have crossing diagonals by evaluating the
|
||||||
|
* corner points of the area of intersection between the two
|
||||||
|
* tiles. This routine finds the distance from a point in
|
||||||
|
* the second triangle to the diagonal of the first, in both
|
||||||
|
* x and y. If the point is below or to the left, the
|
||||||
|
* distance is negative; otherwise the distance is positive.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* 1 for a positive result, -1 for a negative result, and 0
|
||||||
|
* for the same result (point touches the diagonal).
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* --------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
dbEvalCorner(Point *p, // Point to evaluate
|
||||||
|
Rect *rect, // Triangular area bounding rectangle
|
||||||
|
TileType di) // Diagonal information for split rect
|
||||||
|
{
|
||||||
|
dlong D;
|
||||||
|
|
||||||
|
/* D is the distance from a point to the diagonal of the rectangle.
|
||||||
|
* The magnitude is not important. It only matters what the sign
|
||||||
|
* is, so return 1 for positive, -1 for negative, or 0.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (di & TT_DIRECTION)
|
||||||
|
D = (p->p_y - rect->r_ybot) * (rect->r_xtop - rect->r_xbot) -
|
||||||
|
(rect->r_xtop - p->p_x) * (rect->r_ytop - rect->r_ybot);
|
||||||
|
else
|
||||||
|
D = (p->p_y - rect->r_ybot) * (rect->r_xtop - rect->r_xbot) -
|
||||||
|
(p->p_x - rect->r_xbot) * (rect->r_ytop - rect->r_ybot);
|
||||||
|
|
||||||
|
if (D > 0) return 1;
|
||||||
|
if (D < 0) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* --------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* DBTestNMInteract --
|
||||||
|
*
|
||||||
|
* Determine if a tile (t2) interacts with (touches or overlaps)
|
||||||
|
* a triangular area (rect1, with diagonal split information in
|
||||||
|
* di1). Tile t2 may or may not be a split tile. If t2 is
|
||||||
|
* split, then diagonal split information is in di2.
|
||||||
|
*
|
||||||
|
* There are two distinct cases: DBSrPaintNMArea() looks for
|
||||||
|
* tiles that overlap the area of rect1, but extTestNMInteract()
|
||||||
|
* looks for tiles that both overlap or touch (indicating
|
||||||
|
* electrical connectivity between the two). "overlap_only"
|
||||||
|
* distinguishes between the two use cases. Set "overlap_only"
|
||||||
|
* to TRUE for overlap searches, and FALSE for interaction
|
||||||
|
* searches.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
*
|
||||||
|
* If overlap_only is TRUE:
|
||||||
|
* Return TRUE if the indicated areas overlap, FALSE if not.
|
||||||
|
* If overlap_only is FALSE:
|
||||||
|
* Return TRUE if the indicated areas touch or overlap, FALSE if not.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* --------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
DBTestNMInteract(Rect *rect1,
|
||||||
|
TileType tt1,
|
||||||
|
Tile *t2,
|
||||||
|
TileType di2,
|
||||||
|
bool overlap_only)
|
||||||
|
{
|
||||||
|
Rect rect2, r;
|
||||||
|
Point p;
|
||||||
|
int rheight, rwidth, rmax;
|
||||||
|
dlong f1, f2, f3, f4;
|
||||||
|
TileType tt2;
|
||||||
|
int pos, neg, touch, sign;
|
||||||
|
|
||||||
|
TiToRect(t2, &rect2);
|
||||||
|
|
||||||
|
/* Assuming that rect1 is a split area, then check if any part of t2
|
||||||
|
* overlaps the split side of interest in rect1, regardless of whether
|
||||||
|
* t2 is split or not. If there is no overlap, then return FALSE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
rheight = rect1->r_ytop - rect1->r_ybot;
|
||||||
|
rwidth = rect1->r_xtop - rect1->r_xbot;
|
||||||
|
rmax = MAX(rheight, rwidth);
|
||||||
|
|
||||||
|
f1 = (rect2.r_ybot > MINFINITY + 2) ?
|
||||||
|
((dlong)(rect1->r_ytop - rect2.r_ybot) * rwidth) : DLONG_MAX;
|
||||||
|
f2 = (rect2.r_ytop < INFINITY - 2) ?
|
||||||
|
((dlong)(rect2.r_ytop - rect1->r_ybot) * rwidth) : DLONG_MAX;
|
||||||
|
|
||||||
|
if (tt1 & TT_SIDE)
|
||||||
|
{
|
||||||
|
/* Outside-of-triangle check---ignore sub-integer slivers */
|
||||||
|
if (rect2.r_xtop < INFINITY - 2)
|
||||||
|
{
|
||||||
|
f3 = (dlong)(rect1->r_xtop - rect2.r_xtop) * rheight;
|
||||||
|
f3 += rmax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
f3 = DLONG_MIN;
|
||||||
|
if ((tt1 & TT_DIRECTION) ? (f2 < f3) : (f1 < f3))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Outside-of-triangle check---ignore sub-integer slivers */
|
||||||
|
if (rect2.r_xbot > MINFINITY + 2)
|
||||||
|
{
|
||||||
|
f4 = (dlong)(rect2.r_xbot - rect1->r_xbot) * rheight;
|
||||||
|
f4 += rmax;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
f4 = DLONG_MIN;
|
||||||
|
if ((tt1 & TT_DIRECTION) ? (f1 < f4) : (f2 < f4))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If t2 is not split, or its diagonal is the opposite of t1,
|
||||||
|
* or its side is the same as that of t1, then they overlap.
|
||||||
|
*/
|
||||||
|
if (!IsSplit(t2)) return TRUE;
|
||||||
|
|
||||||
|
tt2 = TiGetTypeExact(t2) | di2;
|
||||||
|
|
||||||
|
if ((tt1 & TT_DIRECTION) != (tt2 & TT_DIRECTION)) return TRUE;
|
||||||
|
// if ((tt1 & TT_SIDE) == (tt2 & TT_SIDE)) return TRUE;
|
||||||
|
|
||||||
|
/* Hard case: Same diagonal direction, opposite sides. To determine
|
||||||
|
* overlap, count which of the three points of triangle t2 land on
|
||||||
|
* one side or the other of the rect1 split diagonal. From those
|
||||||
|
* counts, determine if the triangles are overlapping, touching,
|
||||||
|
* or disjoint.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Evaluate the three corners of the rect2 triangle */
|
||||||
|
|
||||||
|
pos = neg = touch = 0;
|
||||||
|
if (!(tt2 & TT_DIRECTION) || !(tt2 & TT_SIDE))
|
||||||
|
{
|
||||||
|
/* Evaluate the lower left corner */
|
||||||
|
sign = dbEvalCorner(&rect2.r_ll, rect1, tt1);
|
||||||
|
if (sign == 1)
|
||||||
|
pos++;
|
||||||
|
else if (sign == -1)
|
||||||
|
neg++;
|
||||||
|
else
|
||||||
|
touch++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(tt2 & TT_DIRECTION) || (tt2 & TT_SIDE))
|
||||||
|
{
|
||||||
|
/* Evaluate the upper right corner */
|
||||||
|
sign = dbEvalCorner(&rect2.r_ur, rect1, tt1);
|
||||||
|
if (sign == 1)
|
||||||
|
pos++;
|
||||||
|
else if (sign == -1)
|
||||||
|
neg++;
|
||||||
|
else
|
||||||
|
touch++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((tt2 & TT_DIRECTION) || !(tt2 & TT_SIDE))
|
||||||
|
{
|
||||||
|
/* Evaluate the upper left corner */
|
||||||
|
p.p_x = rect2.r_xbot;
|
||||||
|
p.p_y = rect2.r_ytop;
|
||||||
|
sign = dbEvalCorner(&p, rect1, tt1);
|
||||||
|
if (sign == 1)
|
||||||
|
pos++;
|
||||||
|
else if (sign == -1)
|
||||||
|
neg++;
|
||||||
|
else
|
||||||
|
touch++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((tt2 & TT_DIRECTION) || (tt2 & TT_SIDE))
|
||||||
|
{
|
||||||
|
/* Evaluate the lower right corner */
|
||||||
|
p.p_x = rect2.r_xtop;
|
||||||
|
p.p_y = rect2.r_ybot;
|
||||||
|
sign = dbEvalCorner(&p, rect1, tt1);
|
||||||
|
if (sign == 1)
|
||||||
|
pos++;
|
||||||
|
else if (sign == -1)
|
||||||
|
neg++;
|
||||||
|
else
|
||||||
|
touch++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If side and direction match, then pos and neg need to be swapped */
|
||||||
|
if (((tt1 & TT_SIDE) && (tt1 & TT_DIRECTION)) ||
|
||||||
|
(!(tt1 & TT_SIDE) && !(tt1 & TT_DIRECTION)))
|
||||||
|
{
|
||||||
|
int temp = neg;
|
||||||
|
neg = pos;
|
||||||
|
pos = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return TRUE or FALSE depending on the values of pos, neg, and
|
||||||
|
* touch, and depending on whether overlap_only is set or not.
|
||||||
|
*/
|
||||||
|
if (pos == 3)
|
||||||
|
return FALSE; /* Fully disjoint */
|
||||||
|
else if (neg == 3)
|
||||||
|
{
|
||||||
|
if ((tt1 & TT_SIDE) != (tt2 & TT_SIDE))
|
||||||
|
return TRUE; /* Fully enclosed */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* This is a trickier situation. Both triangles have
|
||||||
|
* the same TT_SIDE bit, but the triangular area of t2
|
||||||
|
* could still be outside of rect1. Need to check where
|
||||||
|
* the inside corner of rect1 lands with respect to the
|
||||||
|
* t2 diagonal.
|
||||||
|
*/
|
||||||
|
if (((tt1 & TT_SIDE) == 0) && ((tt1 & TT_DIRECTION) != 0))
|
||||||
|
{
|
||||||
|
sign = dbEvalCorner(&rect1->r_ll, &rect2, tt2);
|
||||||
|
}
|
||||||
|
else if (((tt1 & TT_SIDE) == 0) && ((tt1 & TT_DIRECTION) == 0))
|
||||||
|
{
|
||||||
|
p.p_x = rect1->r_ll.p_x;
|
||||||
|
p.p_y = rect1->r_ur.p_y;
|
||||||
|
sign = dbEvalCorner(&p, &rect2, tt2);
|
||||||
|
}
|
||||||
|
else if (((tt1 & TT_SIDE) != 0) && ((tt1 & TT_DIRECTION) == 0))
|
||||||
|
{
|
||||||
|
p.p_x = rect1->r_ur.p_x;
|
||||||
|
p.p_y = rect1->r_ll.p_y;
|
||||||
|
sign = dbEvalCorner(&p, &rect2, tt2);
|
||||||
|
}
|
||||||
|
else /* if (((tt1 & TT_SIDE) != 0) && ((tt1 & TT_DIRECTION) != 0)) */
|
||||||
|
{
|
||||||
|
sign = dbEvalCorner(&rect1->r_ur, &rect2, tt2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Again, if side and direction match, then sign is backwards
|
||||||
|
*/
|
||||||
|
if (((tt2 & TT_SIDE) && (tt2 & TT_DIRECTION)) ||
|
||||||
|
(!(tt2 & TT_SIDE) && !(tt2 & TT_DIRECTION)))
|
||||||
|
sign = -sign;
|
||||||
|
|
||||||
|
if (sign == 1)
|
||||||
|
return FALSE; /* Fully disjoint */
|
||||||
|
else if (sign == -1)
|
||||||
|
return TRUE; /* Fully overlapping */
|
||||||
|
else if (overlap_only)
|
||||||
|
return FALSE; /* Touching but not overlapping */
|
||||||
|
else
|
||||||
|
return TRUE; /* Touching but not overlapping */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (overlap_only)
|
||||||
|
{
|
||||||
|
if ((touch > 0) && (neg + touch == 3))
|
||||||
|
return TRUE; /* Enclosed and touching */
|
||||||
|
else if ((touch > 0) && (pos + touch == 3))
|
||||||
|
return FALSE; /* Unenclosed but touching */
|
||||||
|
else
|
||||||
|
return TRUE; /* Partially overlapping */
|
||||||
|
}
|
||||||
|
else /* overlap_only == FALSE */
|
||||||
|
{
|
||||||
|
if ((touch > 0) && (neg + touch == 3))
|
||||||
|
return TRUE; /* Enclosed and touching */
|
||||||
|
else if ((touch > 0) && (pos + touch == 3))
|
||||||
|
return TRUE; /* Unenclosed but touching */
|
||||||
|
else
|
||||||
|
return TRUE; /* Partially overlapping */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* --------------------------------------------------------------------
|
* --------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -56,6 +346,7 @@ int dbCheckMaxHFunc(), dbCheckMaxVFunc();
|
||||||
* int
|
* int
|
||||||
* func(tile, cdata)
|
* func(tile, cdata)
|
||||||
* Tile *tile;
|
* Tile *tile;
|
||||||
|
* TileType dinfo;
|
||||||
* ClientData cdata;
|
* ClientData cdata;
|
||||||
* {
|
* {
|
||||||
* }
|
* }
|
||||||
|
|
@ -137,147 +428,26 @@ nm_enum:
|
||||||
/* the tile enumeration if it is not. */
|
/* the tile enumeration if it is not. */
|
||||||
/* Watch for calculations involving (M)INFINITY in tile (tp)! */
|
/* Watch for calculations involving (M)INFINITY in tile (tp)! */
|
||||||
|
|
||||||
rheight = rect->r_ytop - rect->r_ybot;
|
|
||||||
rwidth = rect->r_xtop - rect->r_xbot;
|
|
||||||
rmax = MAX(rheight, rwidth);
|
|
||||||
f1 = (BOTTOM(tp) > MINFINITY + 2) ?
|
|
||||||
((dlong)(rect->r_ytop - BOTTOM(tp)) * rwidth) : DLONG_MAX;
|
|
||||||
f2 = (TOP(tp) < INFINITY - 2) ?
|
|
||||||
((dlong)(TOP(tp) - rect->r_ybot) * rwidth) : DLONG_MAX;
|
|
||||||
|
|
||||||
if (ttype & TT_SIDE)
|
|
||||||
{
|
|
||||||
/* Outside-of-triangle check---ignore sub-integer slivers */
|
|
||||||
if (RIGHT(tp) < INFINITY - 2)
|
|
||||||
{
|
|
||||||
f3 = (dlong)(rect->r_xtop - RIGHT(tp)) * rheight;
|
|
||||||
f3 += rmax;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
f3 = DLONG_MIN;
|
|
||||||
if ((ttype & TT_DIRECTION) ? (f2 < f3) : (f1 < f3))
|
|
||||||
goto enum_next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Outside-of-triangle check---ignore sub-integer slivers */
|
|
||||||
if (LEFT(tp) > MINFINITY + 2)
|
|
||||||
{
|
|
||||||
f4 = (dlong)(LEFT(tp) - rect->r_xbot) * rheight;
|
|
||||||
f4 += rmax;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
f4 = DLONG_MIN;
|
|
||||||
if ((ttype & TT_DIRECTION) ? (f1 < f4) : (f2 < f4))
|
|
||||||
goto enum_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Secondary checks---if tile is also non-Manhattan, is */
|
|
||||||
/* either side of it outside the area? If so, restrict it. */
|
|
||||||
/* This check is only necessary if the split directions are */
|
|
||||||
/* the same, so we have to see if either of the neighboring */
|
|
||||||
/* points is also inside the search triangle. */
|
|
||||||
|
|
||||||
ignore_sides = 0;
|
|
||||||
|
|
||||||
if (IsSplit(tp))
|
if (IsSplit(tp))
|
||||||
{
|
{
|
||||||
if (!TTMaskHasType(mask, SplitLeftType(tp)))
|
TileType tpdi = TiGetTypeExact(tp);
|
||||||
ignore_sides |= IGNORE_LEFT;
|
|
||||||
if (!TTMaskHasType(mask, SplitRightType(tp)))
|
|
||||||
ignore_sides |= IGNORE_RIGHT;
|
|
||||||
|
|
||||||
tpt = TiGetTypeExact(tp);
|
if (TTMaskHasType(mask, SplitLeftType(tp)))
|
||||||
if ((tpt & TT_DIRECTION) == (ttype & TT_DIRECTION))
|
if (DBTestNMInteract(rect, ttype, tp, tpdi, TRUE))
|
||||||
{
|
if ((*func)(tp, (TileType)TT_DIAGONAL, arg))
|
||||||
f3 = (LEFT(tp) > MINFINITY + 2) ?
|
return 1;
|
||||||
((dlong)(rect->r_xtop - LEFT(tp)) * rheight) : DLONG_MAX;
|
if (TTMaskHasType(mask, SplitRightType(tp)))
|
||||||
f4 = (RIGHT(tp) < INFINITY - 2) ?
|
if (DBTestNMInteract(rect, ttype, tp, tpdi | TT_SIDE, TRUE))
|
||||||
((dlong)(RIGHT(tp) - rect->r_xbot) * rheight) : DLONG_MAX;
|
if ((*func)(tp, (TileType)TT_DIAGONAL | TT_SIDE, arg))
|
||||||
|
return 1;
|
||||||
if (ttype & TT_SIDE)
|
|
||||||
{
|
|
||||||
/* Ignore sub-integer slivers */
|
|
||||||
if (f4 != DLONG_MAX) f4 -= rmax;
|
|
||||||
if (f3 != DLONG_MAX) f3 += rmax;
|
|
||||||
|
|
||||||
if (ttype & TT_DIRECTION)
|
|
||||||
{
|
|
||||||
if ((f2 < f3) && (f1 > f4))
|
|
||||||
/* Tile bottom left is outside search area */
|
|
||||||
ignore_sides |= IGNORE_LEFT;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((f1 < f3) && (f2 > f4))
|
if (TTMaskHasType(mask, TiGetType(tp)))
|
||||||
/* Tile top left is outside search area */
|
if (DBTestNMInteract(rect, ttype, tp, (TileType)0, TRUE))
|
||||||
ignore_sides |= IGNORE_LEFT;
|
if ((*func)(tp, (TileType)0, arg))
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Ignore sub-integer slivers */
|
|
||||||
if (f4 != DLONG_MAX) f4 += rmax;
|
|
||||||
if (f3 != DLONG_MAX) f3 -= rmax;
|
|
||||||
|
|
||||||
if (ttype & TT_DIRECTION)
|
|
||||||
{
|
|
||||||
if ((f2 > f3) && (f1 < f4))
|
|
||||||
/* Tile top right is outside search area */
|
|
||||||
ignore_sides |= IGNORE_RIGHT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((f1 > f3) && (f2 < f4))
|
|
||||||
/* Tile bottom right is outside search area */
|
|
||||||
ignore_sides |= IGNORE_RIGHT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the tile is larger than the search area or overlaps */
|
|
||||||
/* the search area, we need to check if one of the sides */
|
|
||||||
/* of the tile is disjoint from the search area. */
|
|
||||||
|
|
||||||
rheight = TOP(tp) - BOTTOM(tp);
|
|
||||||
rwidth = RIGHT(tp) - LEFT(tp);
|
|
||||||
rmax = MAX(rheight, rwidth);
|
|
||||||
f1 = (TOP(tp) < INFINITY - 2) ?
|
|
||||||
((dlong)(TOP(tp) - rect->r_ybot) * rwidth) : DLONG_MAX;
|
|
||||||
f2 = (BOTTOM(tp) > MINFINITY + 2) ?
|
|
||||||
((dlong)(rect->r_ytop - BOTTOM(tp)) * rwidth) : DLONG_MAX;
|
|
||||||
f3 = (RIGHT(tp) < INFINITY - 2) ?
|
|
||||||
((dlong)(RIGHT(tp) - rect->r_xtop) * rheight) : DLONG_MAX;
|
|
||||||
f4 = (LEFT(tp) > MINFINITY + 2) ?
|
|
||||||
((dlong)(rect->r_xbot - LEFT(tp)) * rheight) : DLONG_MAX;
|
|
||||||
|
|
||||||
/* ignore sub-integer slivers */
|
|
||||||
if (f4 < DLONG_MAX) f4 += rmax;
|
|
||||||
if (f3 < DLONG_MAX) f3 += rmax;
|
|
||||||
|
|
||||||
if (SplitDirection(tp) ? (f1 < f4) : (f2 < f4))
|
|
||||||
ignore_sides |= IGNORE_LEFT;
|
|
||||||
|
|
||||||
if (SplitDirection(tp) ? (f2 < f3) : (f1 < f3))
|
|
||||||
ignore_sides |= IGNORE_RIGHT;
|
|
||||||
|
|
||||||
/* May call function twice to paint both sides of */
|
|
||||||
/* the split tile, if necessary. */
|
|
||||||
|
|
||||||
if (!(ignore_sides & IGNORE_LEFT))
|
|
||||||
{
|
|
||||||
TiSetBody(tp, INT2CD(tpt & ~TT_SIDE)); /* bit clear */
|
|
||||||
if ((*func)(tp, arg)) return (1);
|
|
||||||
}
|
|
||||||
if (!(ignore_sides & IGNORE_RIGHT))
|
|
||||||
{
|
|
||||||
TiSetBody(tp, INT2CD(tpt | TT_SIDE)); /* bit set */
|
|
||||||
if ((*func)(tp, arg)) return (1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (TTMaskHasType(mask, TiGetType(tp)) && (*func)(tp, arg))
|
|
||||||
return (1);
|
|
||||||
|
|
||||||
enum_next:
|
enum_next:
|
||||||
tpnew = TR(tp);
|
tpnew = TR(tp);
|
||||||
|
|
@ -325,6 +495,7 @@ enum_next:
|
||||||
* int
|
* int
|
||||||
* func(tile, cdata)
|
* func(tile, cdata)
|
||||||
* Tile *tile;
|
* Tile *tile;
|
||||||
|
* TileType dinfo;
|
||||||
* ClientData cdata;
|
* ClientData cdata;
|
||||||
* {
|
* {
|
||||||
* }
|
* }
|
||||||
|
|
@ -416,9 +587,7 @@ enumerate:
|
||||||
(dlong)(rect->r_xbot - LEFT(tp)) * theight : DLONG_MIN;
|
(dlong)(rect->r_xbot - LEFT(tp)) * theight : DLONG_MIN;
|
||||||
if (SplitDirection(tp) ? (f1 > f4) : (f2 > f4))
|
if (SplitDirection(tp) ? (f1 > f4) : (f2 > f4))
|
||||||
{
|
{
|
||||||
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
|
if ((*func)(tp, (TileType)TT_DIAGONAL, arg)) return (1);
|
||||||
& ~TT_SIDE)); /* bit clear */
|
|
||||||
if ((*func)(tp, arg)) return (1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -429,14 +598,12 @@ enumerate:
|
||||||
(dlong)(RIGHT(tp) - rect->r_xtop) * theight : DLONG_MIN;
|
(dlong)(RIGHT(tp) - rect->r_xtop) * theight : DLONG_MIN;
|
||||||
if (SplitDirection(tp) ? (f2 > f3) : (f1 > f3))
|
if (SplitDirection(tp) ? (f2 > f3) : (f1 > f3))
|
||||||
{
|
{
|
||||||
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
|
if ((*func)(tp, (TileType)TT_DIAGONAL | TT_SIDE, arg)) return (1);
|
||||||
| TT_SIDE)); /* bit set */
|
|
||||||
if ((*func)(tp, arg)) return (1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (TTMaskHasType(mask, TiGetType(tp)) && (*func)(tp, arg))
|
if (TTMaskHasType(mask, TiGetType(tp)) && (*func)(tp, (TileType)0, arg))
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
tpnew = TR(tp);
|
tpnew = TR(tp);
|
||||||
|
|
@ -485,6 +652,7 @@ enumerate:
|
||||||
* int
|
* int
|
||||||
* func(tile, cdata)
|
* func(tile, cdata)
|
||||||
* Tile *tile;
|
* Tile *tile;
|
||||||
|
* TileType dinfo;
|
||||||
* ClientData cdata;
|
* ClientData cdata;
|
||||||
* {
|
* {
|
||||||
* }
|
* }
|
||||||
|
|
@ -576,9 +744,7 @@ enumerate:
|
||||||
(dlong)(rect->r_xbot - LEFT(tp)) * (dlong)theight : DLONG_MIN;
|
(dlong)(rect->r_xbot - LEFT(tp)) * (dlong)theight : DLONG_MIN;
|
||||||
if (SplitDirection(tp) ? (f1 > f4) : (f2 > f4))
|
if (SplitDirection(tp) ? (f1 > f4) : (f2 > f4))
|
||||||
{
|
{
|
||||||
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
|
if ((tp->ti_client == client) && (*func)(tp, (TileType)TT_DIAGONAL, arg))
|
||||||
& ~TT_SIDE)); /* bit clear */
|
|
||||||
if ((tp->ti_client == client) && (*func)(tp, arg))
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -590,16 +756,15 @@ enumerate:
|
||||||
(dlong)(RIGHT(tp) - rect->r_xtop) * (dlong)theight : DLONG_MIN;
|
(dlong)(RIGHT(tp) - rect->r_xtop) * (dlong)theight : DLONG_MIN;
|
||||||
if (SplitDirection(tp) ? (f2 > f3) : (f1 > f3))
|
if (SplitDirection(tp) ? (f2 > f3) : (f1 > f3))
|
||||||
{
|
{
|
||||||
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
|
if ((tp->ti_client == client) && (*func)(tp, (TileType)TT_DIAGONAL
|
||||||
| TT_SIDE)); /* bit set */
|
| TT_SIDE, arg))
|
||||||
if ((tp->ti_client == client) && (*func)(tp, arg))
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (TTMaskHasType(mask, TiGetType(tp)) && tp->ti_client == client
|
if (TTMaskHasType(mask, TiGetType(tp)) && tp->ti_client == client
|
||||||
&& (*func)(tp, arg))
|
&& (*func)(tp, (TileType)0, arg))
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
tpnew = TR(tp);
|
tpnew = TR(tp);
|
||||||
|
|
@ -665,7 +830,7 @@ DBResetTilePlane(plane, cdata)
|
||||||
/* Each iteration visits another tile on the LHS of the search area */
|
/* Each iteration visits another tile on the LHS of the search area */
|
||||||
while (TOP(tp) > rect->r_ybot)
|
while (TOP(tp) > rect->r_ybot)
|
||||||
{
|
{
|
||||||
/* Each iteration frees another tile */
|
/* Each iteration resets another tile */
|
||||||
enumerate:
|
enumerate:
|
||||||
tp->ti_client = cdata;
|
tp->ti_client = cdata;
|
||||||
|
|
||||||
|
|
@ -701,6 +866,88 @@ enumerate:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* --------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* DBResetTilePlaneSpecial --
|
||||||
|
*
|
||||||
|
* This routine works like DBResetTilePlane(), but is designed
|
||||||
|
* specifically to be run after extFindNodes() or ExtFindRegions()
|
||||||
|
* to check for split tiles that have an allocated ExtSplitRegion
|
||||||
|
* structure in the ClientData; this needs to be freed before
|
||||||
|
* resetting the ClientData value to "cdata". It is not necessary
|
||||||
|
* to know anything about the ExtSplitRegion structure other than
|
||||||
|
* the condition under which it can be expected to be present,
|
||||||
|
* which is a split tile with neither side having type TT_SPACE.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Resets the ti_client fields of all tiles.
|
||||||
|
*
|
||||||
|
* --------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
DBResetTilePlaneSpecial(plane, cdata)
|
||||||
|
Plane *plane; /* Plane whose tiles are to be reset */
|
||||||
|
ClientData cdata;
|
||||||
|
{
|
||||||
|
Tile *tp, *tpnew;
|
||||||
|
const Rect *rect = &TiPlaneRect;
|
||||||
|
|
||||||
|
/* Start with the leftmost non-infinity tile in the plane */
|
||||||
|
tp = TR(plane->pl_left);
|
||||||
|
|
||||||
|
/* Each iteration visits another tile on the LHS of the search area */
|
||||||
|
while (TOP(tp) > rect->r_ybot)
|
||||||
|
{
|
||||||
|
/* Each iteration resets another tile */
|
||||||
|
enumerate:
|
||||||
|
if (IsSplit(tp))
|
||||||
|
if ((TiGetLeftType(tp) != TT_SPACE) && (TiGetRightType(tp) != TT_SPACE))
|
||||||
|
if (tp->ti_client != cdata)
|
||||||
|
{
|
||||||
|
ASSERT(TiGetBody((Tile *)tp->ti_client) == CLIENTDEFAULT,
|
||||||
|
"DBResetTilePlaneSpecial");
|
||||||
|
freeMagic(tp->ti_client);
|
||||||
|
}
|
||||||
|
|
||||||
|
tp->ti_client = cdata;
|
||||||
|
|
||||||
|
/* Move along to the next tile */
|
||||||
|
tpnew = TR(tp);
|
||||||
|
if (LEFT(tpnew) < rect->r_xtop)
|
||||||
|
{
|
||||||
|
while (BOTTOM(tpnew) >= rect->r_ytop) tpnew = LB(tpnew);
|
||||||
|
if (BOTTOM(tpnew) >= BOTTOM(tp) || BOTTOM(tp) <= rect->r_ybot)
|
||||||
|
{
|
||||||
|
tp = tpnew;
|
||||||
|
goto enumerate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Each iteration returns one tile further to the left */
|
||||||
|
while (LEFT(tp) > rect->r_xbot)
|
||||||
|
{
|
||||||
|
if (BOTTOM(tp) <= rect->r_ybot)
|
||||||
|
return;
|
||||||
|
tpnew = LB(tp);
|
||||||
|
tp = BL(tp);
|
||||||
|
if (BOTTOM(tpnew) >= BOTTOM(tp) || BOTTOM(tp) <= rect->r_ybot)
|
||||||
|
{
|
||||||
|
tp = tpnew;
|
||||||
|
goto enumerate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* At left edge -- walk down to next tile along the left edge */
|
||||||
|
for (tp = LB(tp); RIGHT(tp) <= rect->r_xbot; tp = TR(tp))
|
||||||
|
/* Nothing */;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* --------------------------------------------------------------------
|
* --------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -918,8 +1165,9 @@ DBCheckMaxHStrips(plane, area, proc, cdata)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCheckMaxHFunc(tile, dbc)
|
dbCheckMaxHFunc(tile, dinfo, dbc)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
struct dbCheck *dbc;
|
struct dbCheck *dbc;
|
||||||
{
|
{
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
|
|
@ -1010,8 +1258,9 @@ DBCheckMaxVStrips(plane, area, proc, cdata)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCheckMaxVFunc(tile, dbc)
|
dbCheckMaxVFunc(tile, dinfo, dbc)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
struct dbCheck *dbc;
|
struct dbCheck *dbc;
|
||||||
{
|
{
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
|
|
|
||||||
|
|
@ -303,9 +303,14 @@ typedef struct label
|
||||||
#define PORT_SHAPE_RING 0x1000 /* Port is a ring shape */
|
#define PORT_SHAPE_RING 0x1000 /* Port is a ring shape */
|
||||||
#define PORT_SHAPE_THRU 0x1800 /* Port is a feedthrough shape */
|
#define PORT_SHAPE_THRU 0x1800 /* Port is a feedthrough shape */
|
||||||
|
|
||||||
#define PORT_VISITED 0x2000 /* Bit for checking if a port */
|
#define LABEL_STICKY 0x2000 /* Label does not change layers */
|
||||||
|
#define LABEL_UNIQUE 0x4000 /* Temporary unique label */
|
||||||
|
|
||||||
|
/* The last two flags are never used at the same time and so can share
|
||||||
|
* a flag bit.
|
||||||
|
*/
|
||||||
|
#define PORT_VISITED 0x8000 /* Bit for checking if a port */
|
||||||
/* has been previously visited. */
|
/* has been previously visited. */
|
||||||
#define LABEL_STICKY 0x4000 /* Label does not change layers */
|
|
||||||
#define LABEL_GENERATE 0x8000 /* Auto-generated label */
|
#define LABEL_GENERATE 0x8000 /* Auto-generated label */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -551,6 +556,18 @@ typedef struct diag_info
|
||||||
bool side;
|
bool side;
|
||||||
} DiagInfo;
|
} DiagInfo;
|
||||||
|
|
||||||
|
/* Where search functions need to return a Tile pointer and tile split */
|
||||||
|
/* information, use this structure. Contains a pointer to its own */
|
||||||
|
/* structure type so that it may also be used to create a linked list */
|
||||||
|
/* of tiles including split side information. */
|
||||||
|
|
||||||
|
typedef struct tile_and_dinfo
|
||||||
|
{
|
||||||
|
struct tile_and_dinfo *tad_next;
|
||||||
|
Tile *tad_tile;
|
||||||
|
TileType tad_dinfo;
|
||||||
|
} TileAndDinfo;
|
||||||
|
|
||||||
/* This would normally go in geometry.h except that it uses TileType. */
|
/* This would normally go in geometry.h except that it uses TileType. */
|
||||||
/* Used in selOps.c but also passed back to CmdRS.c for select command. */
|
/* Used in selOps.c but also passed back to CmdRS.c for select command. */
|
||||||
|
|
||||||
|
|
@ -687,6 +704,25 @@ struct conSrArg2
|
||||||
|
|
||||||
#define CSA2_LIST_SIZE 65536 /* Number of entries per list */
|
#define CSA2_LIST_SIZE 65536 /* Number of entries per list */
|
||||||
|
|
||||||
|
/* ------------------------ Properties ------------------------------ */
|
||||||
|
|
||||||
|
/* Note that the property record is a single allocated block large enough
|
||||||
|
* to hold the string or integer list, and can be freed as a single block.
|
||||||
|
* The array bounds, like those of lab_text for labels, are placeholders.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int prop_type; /* See codes below; e.g., PROPERTY_TYPE_STRING */
|
||||||
|
int prop_len; /* String length or number of values */
|
||||||
|
union {
|
||||||
|
char prop_string[8]; /* For PROPERTY_TYPE_STRING */
|
||||||
|
int prop_integer[2]; /* For PROPERTY_TYPE_INTEGER or _DIMENSION */
|
||||||
|
dlong prop_double[1]; /* For PROPERTY_TYPE_DOUBLE */
|
||||||
|
Plane *prop_plane; /* For PROPERTY_TYPE_PLANE */
|
||||||
|
} prop_value;
|
||||||
|
} PropertyRecord;
|
||||||
|
|
||||||
/* -------------- Undo information passed to DBPaintPlane ------------- */
|
/* -------------- Undo information passed to DBPaintPlane ------------- */
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
@ -719,6 +755,14 @@ typedef struct
|
||||||
#define PAINT_MARK 1 /* Mark tiles that are painted */
|
#define PAINT_MARK 1 /* Mark tiles that are painted */
|
||||||
#define PAINT_XOR 2 /* Use with XOR function to prevent double-painting */
|
#define PAINT_XOR 2 /* Use with XOR function to prevent double-painting */
|
||||||
|
|
||||||
|
/* ---------------------- Codes for properties -------------------------*/
|
||||||
|
|
||||||
|
#define PROPERTY_TYPE_STRING 0 /* ASCII string property */
|
||||||
|
#define PROPERTY_TYPE_INTEGER 1 /* Fixed integer property */
|
||||||
|
#define PROPERTY_TYPE_DIMENSION 2 /* Integer property that scales with units */
|
||||||
|
#define PROPERTY_TYPE_DOUBLE 3 /* Double-long integer (for file positions) */
|
||||||
|
#define PROPERTY_TYPE_PLANE 4 /* A tile plane structure */
|
||||||
|
|
||||||
/* -------------------- Exported procedure headers -------------------- */
|
/* -------------------- Exported procedure headers -------------------- */
|
||||||
|
|
||||||
/* Painting/erasing */
|
/* Painting/erasing */
|
||||||
|
|
@ -904,7 +948,9 @@ extern void DBFreePaintPlane();
|
||||||
|
|
||||||
/* Cell properties */
|
/* Cell properties */
|
||||||
extern void DBPropPut();
|
extern void DBPropPut();
|
||||||
extern ClientData DBPropGet();
|
extern PropertyRecord *DBPropGet();
|
||||||
|
extern char *DBPropGetString();
|
||||||
|
extern dlong DBPropGetDouble();
|
||||||
extern int DBPropEnum();
|
extern int DBPropEnum();
|
||||||
extern void DBPropClearAll();
|
extern void DBPropClearAll();
|
||||||
|
|
||||||
|
|
@ -920,9 +966,10 @@ extern int DBArraySr();
|
||||||
extern bool DBNearestLabel();
|
extern bool DBNearestLabel();
|
||||||
extern int DBSrLabelLoc();
|
extern int DBSrLabelLoc();
|
||||||
extern TileType DBTransformDiagonal();
|
extern TileType DBTransformDiagonal();
|
||||||
extern int dbcUnconnectFunc(Tile *tile, ClientData clientData); /* (notused) */
|
extern bool DBTestNMInteract(Rect *rect1, TileType tt1, Tile *t2, TileType di2, bool overlap_only);
|
||||||
extern int dbSrConnectFunc(Tile *tile, ClientData clientData); /* (struct conSrArg *csa) */
|
extern int dbcUnconnectFunc(Tile *tile, TileType dinfo, ClientData clientData); /* (notused) */
|
||||||
extern int dbSrConnectStartFunc(Tile *tile, ClientData clientData); /* cb_database_srpaintarea_t (Tile **pTile) */
|
extern int dbSrConnectFunc(Tile *tile, TileType dinfo, ClientData clientData); /* (struct conSrArg *csa) */
|
||||||
|
extern int dbSrConnectStartFunc(Tile *tile, TileType dinfo, ClientData clientData); /* cb_database_srpaintarea_t (Tile **pTile) */
|
||||||
|
|
||||||
/* C99 compat */
|
/* C99 compat */
|
||||||
extern void DBEraseValid();
|
extern void DBEraseValid();
|
||||||
|
|
@ -969,10 +1016,10 @@ extern int dbIsPrimary();
|
||||||
extern void dbTechMatchResidues();
|
extern void dbTechMatchResidues();
|
||||||
extern void DBUndoInit();
|
extern void DBUndoInit();
|
||||||
extern void DBResetTilePlane();
|
extern void DBResetTilePlane();
|
||||||
|
extern void DBResetTilePlaneSpecial();
|
||||||
extern void DBNewYank();
|
extern void DBNewYank();
|
||||||
extern int DBSrPaintClient();
|
extern int DBSrPaintClient();
|
||||||
extern int DBSrConnect();
|
extern int DBSrConnect();
|
||||||
extern int DBSrConnectOnePlane();
|
|
||||||
extern char *dbFgets();
|
extern char *dbFgets();
|
||||||
extern void DBAdjustLabelsNew();
|
extern void DBAdjustLabelsNew();
|
||||||
extern bool DBScaleValue();
|
extern bool DBScaleValue();
|
||||||
|
|
@ -1001,6 +1048,7 @@ extern int DBLambda[2];
|
||||||
/* -------------------- Exported magic file suffix -------------------- */
|
/* -------------------- Exported magic file suffix -------------------- */
|
||||||
|
|
||||||
extern char *DBSuffix; /* Suffix appended to all Magic cell names */
|
extern char *DBSuffix; /* Suffix appended to all Magic cell names */
|
||||||
|
extern bool DBPropCompat; /* Backwards-compatible properties */
|
||||||
|
|
||||||
/* -------------------- User Interface Stuff -------------------------- */
|
/* -------------------- User Interface Stuff -------------------------- */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ extern void CmdRandom(), CmdSave(), CmdScaleGrid(), CmdSee();
|
||||||
extern void CmdSelect(), CmdSetLabel(), CmdSideways();
|
extern void CmdSelect(), CmdSetLabel(), CmdSideways();
|
||||||
extern void CmdShell(), CmdSnap();
|
extern void CmdShell(), CmdSnap();
|
||||||
extern void CmdStretch(), CmdStraighten();
|
extern void CmdStretch(), CmdStraighten();
|
||||||
extern void CmdTech(), CmdTool(), CmdUnexpand();
|
extern void CmdTech(), CmdTool(), CmdUnexpand(), CmdUnits();
|
||||||
extern void CmdUpsidedown(), CmdWhat(), CmdWire(), CmdWriteall();
|
extern void CmdUpsidedown(), CmdWhat(), CmdWire(), CmdWriteall();
|
||||||
extern void CmdGoto(), CmdFlatten(), CmdXload(), CmdXor();
|
extern void CmdGoto(), CmdFlatten(), CmdXload(), CmdXor();
|
||||||
|
|
||||||
|
|
@ -474,6 +474,9 @@ DBWInitCommands()
|
||||||
WindAddCommand(DBWclientID,
|
WindAddCommand(DBWclientID,
|
||||||
"unexpand unexpand subcells under box",
|
"unexpand unexpand subcells under box",
|
||||||
CmdUnexpand, FALSE);
|
CmdUnexpand, FALSE);
|
||||||
|
WindAddCommand(DBWclientID,
|
||||||
|
"units [type] set type of units parsed and displayed",
|
||||||
|
CmdUnits, FALSE);
|
||||||
WindAddCommand(DBWclientID,
|
WindAddCommand(DBWclientID,
|
||||||
"upsidedown flip selection and box upside down",
|
"upsidedown flip selection and box upside down",
|
||||||
CmdUpsidedown, FALSE);
|
CmdUpsidedown, FALSE);
|
||||||
|
|
|
||||||
|
|
@ -571,8 +571,9 @@ DBWredisplay(w, rootArea, clipArea)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbwPaintFunc(tile, cxp)
|
dbwPaintFunc(tile, dinfo, cxp)
|
||||||
Tile *tile; /* Tile to be redisplayed. */
|
Tile *tile; /* Tile to be redisplayed. */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TreeContext *cxp; /* From DBTreeSrTiles */
|
TreeContext *cxp; /* From DBTreeSrTiles */
|
||||||
{
|
{
|
||||||
SearchContext *scx = cxp->tc_scx;
|
SearchContext *scx = cxp->tc_scx;
|
||||||
|
|
@ -652,7 +653,7 @@ dbwPaintFunc(tile, cxp)
|
||||||
/* whether to render the outline with a fast rectangle- */
|
/* whether to render the outline with a fast rectangle- */
|
||||||
/* drawing routine or to render it segment by segment. */
|
/* drawing routine or to render it segment by segment. */
|
||||||
|
|
||||||
GrBox(dbwWindow, &scx->scx_trans, tile);
|
GrBox(dbwWindow, &scx->scx_trans, tile, dinfo);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1075,8 +1076,10 @@ dbwBBoxFunc(scx)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbwTileFunc(tile)
|
dbwTileFunc(tile, dinfo, clientdata)
|
||||||
Tile *tile; /* A tile to be redisplayed. */
|
Tile *tile; /* A tile to be redisplayed. */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
|
ClientData clientdata; /* (unused) */
|
||||||
{
|
{
|
||||||
Rect r, r2;
|
Rect r, r2;
|
||||||
int xoffset, yoffset;
|
int xoffset, yoffset;
|
||||||
|
|
@ -1113,7 +1116,7 @@ dbwTileFunc(tile)
|
||||||
|
|
||||||
if (dbwSeeTypes)
|
if (dbwSeeTypes)
|
||||||
{
|
{
|
||||||
(void) sprintf(string, "%s",DBTypeShortName(TiGetType(tile)));
|
(void) sprintf(string, "%s", DBTypeShortName(TiGetType(tile)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1129,7 +1132,7 @@ dbwTileFunc(tile)
|
||||||
|
|
||||||
#define XYOFFSET 12
|
#define XYOFFSET 12
|
||||||
|
|
||||||
for (i=0; i<4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
xoffset = 0;
|
xoffset = 0;
|
||||||
yoffset = 0;
|
yoffset = 0;
|
||||||
|
|
@ -1172,13 +1175,13 @@ dbwTileFunc(tile)
|
||||||
yoffset = temp;
|
yoffset = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (dbwWatchTrans.t_a < 0) || (dbwWatchTrans.t_b < 0) )
|
if ((dbwWatchTrans.t_a < 0) || (dbwWatchTrans.t_b < 0))
|
||||||
{
|
{
|
||||||
/* mirror in x */
|
/* mirror in x */
|
||||||
xoffset = -xoffset;
|
xoffset = -xoffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (dbwWatchTrans.t_d < 0) || (dbwWatchTrans.t_e < 0) )
|
if ((dbwWatchTrans.t_d < 0) || (dbwWatchTrans.t_e < 0))
|
||||||
{
|
{
|
||||||
/* mirror in y */
|
/* mirror in y */
|
||||||
yoffset = -yoffset;
|
yoffset = -yoffset;
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,10 @@ DBWFeedbackRedraw(window, plane)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dbwFeedbackAlways1()
|
dbwFeedbackAlways1(
|
||||||
|
Tile *tile, /* (unused) */
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
|
ClientData clientdata) /* (unused) */
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -392,8 +392,9 @@ DBWHLRedrawWind(window)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbwhlEraseFunc(tile, window)
|
dbwhlEraseFunc(tile, dinfo, window)
|
||||||
Tile *tile; /* Tile describing area to be erased. */
|
Tile *tile; /* Tile describing area to be erased. */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
MagWindow *window; /* Window that is being altered. */
|
MagWindow *window; /* Window that is being altered. */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include "tcltk/tclmagic.h"
|
||||||
#include "utils/main.h"
|
#include "utils/main.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
|
|
@ -33,6 +34,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "utils/hash.h"
|
#include "utils/hash.h"
|
||||||
#include "database/database.h"
|
#include "database/database.h"
|
||||||
#include "utils/main.h"
|
#include "utils/main.h"
|
||||||
|
#include "cif/cif.h"
|
||||||
#include "commands/commands.h"
|
#include "commands/commands.h"
|
||||||
#include "dbwind/dbwind.h"
|
#include "dbwind/dbwind.h"
|
||||||
#include "graphics/graphics.h"
|
#include "graphics/graphics.h"
|
||||||
|
|
@ -653,6 +655,311 @@ DBWexit()
|
||||||
return (CmdWarnWrite() == 1);
|
return (CmdWarnWrite() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* dbwValueFormat ---
|
||||||
|
*
|
||||||
|
* Remove unnecessary trailing zeros and decimal from a floating-point
|
||||||
|
* value formatted with "%.Nf" where N is the expected maximum number
|
||||||
|
* of places after the decimal, matching the argument "places".
|
||||||
|
* This makes the "%f" formatting work like "%g" formatting, but
|
||||||
|
* works around the limitation of "%.Ng" that it operates on the number
|
||||||
|
* of significant digits, not the number of decimal places.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* The string "buf" may be altered with a new terminating null character.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
dbwValueFormat(char *buf,
|
||||||
|
int places)
|
||||||
|
{
|
||||||
|
char *p = buf + strlen(buf) - 1;
|
||||||
|
while (p > buf && *p == '0') *p-- = '\0';
|
||||||
|
if (p > buf && *p == '.') *p = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* dbwPrintValue0 --
|
||||||
|
*
|
||||||
|
* Convert a value in internal database units to a string based on
|
||||||
|
* the chosen display units as defined by DBWUnits (which is set
|
||||||
|
* with the "units" command). If DBWUnits has not been changed
|
||||||
|
* since startup, then the behavior is to print the internal units
|
||||||
|
* in string form. If DBWUnits has been set, then the units type
|
||||||
|
* determines how the output is displayed.
|
||||||
|
*
|
||||||
|
* If "is_square" is TRUE, then the value is in units squared, and
|
||||||
|
* scaling is done accordingly. In the case of DBW_UNITS_USER,
|
||||||
|
* where values are in grid multiples, the units for X and Y may
|
||||||
|
* differ, and "is_x" = TRUE indicates a measurement in the X direction,
|
||||||
|
* while false indicase a measurements in the Y direction. Naturally,
|
||||||
|
* if "is_square" is TRUE then "is_x" is ignored. "is_x" is also ignored
|
||||||
|
* for any output units other than user/grid units.
|
||||||
|
*
|
||||||
|
* If "is_cif" is true, then "value" is in CIF database units
|
||||||
|
* (centimicrons, nanometers, or angstroms, according to the
|
||||||
|
* scalefactor line in the tech file), rather than internal units.
|
||||||
|
*
|
||||||
|
* This routine is generally meant to be called as one of the three
|
||||||
|
* variants defined below it: DBWPrintValue(), DBWPrintSqValue(),
|
||||||
|
* or DBWPrintCIFValue().
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* A pointer to a string. To facilitate printing up to four values
|
||||||
|
* (e.g., rectangle coordinates, such as from "box values"), a static
|
||||||
|
* string partitioned into four parts is created in this subroutine,
|
||||||
|
* and the result points to one position in the string, which is cycled
|
||||||
|
* through every four calls to the subroutine. The caller does not
|
||||||
|
* free the returned string.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* NOTE: Prior to the introduction of the "units" command, magic had the
|
||||||
|
* inconsistent behavior that parsed input values on the command line
|
||||||
|
* would be interpreted per the "snap" setting, but output values were
|
||||||
|
* (almost) always given in internal units. This routine keeps the
|
||||||
|
* original behavior backwards-compatible, as inconsistent as it is.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *
|
||||||
|
dbwPrintValue0(int value, /* value to print, in internal units */
|
||||||
|
MagWindow *w, /* current window, for use with grid */
|
||||||
|
bool is_x, /* TRUE if value is an X dimension */
|
||||||
|
bool is_square, /* TRUE if value is a dimension squared */
|
||||||
|
bool is_cif) /* TRUE if value is in centimicrons */
|
||||||
|
{
|
||||||
|
char *result;
|
||||||
|
float oscale, dscale, fvalue;
|
||||||
|
DBWclientRec *crec;
|
||||||
|
int locunits;
|
||||||
|
|
||||||
|
/* This routine is called often, so avoid constant use of malloc and
|
||||||
|
* free by keeping up to four printed results in static memory.
|
||||||
|
*/
|
||||||
|
static char resultstr[128];
|
||||||
|
static unsigned char resultpos = 0;
|
||||||
|
|
||||||
|
result = &resultstr[resultpos];
|
||||||
|
resultpos += 32;
|
||||||
|
resultpos &= 127; /* At 128, cycle back to zero */
|
||||||
|
|
||||||
|
/* CIF database units are centimicrons/nanometers/angstroms as
|
||||||
|
* set by the "scalefactor" line in the tech file. When "is_cif"
|
||||||
|
* is TRUE, then "value" is in these units. Find the conversion
|
||||||
|
* factor to convert "value" to internal units, and then it can
|
||||||
|
* be subsequently converted to lambda, microns, etc.
|
||||||
|
*/
|
||||||
|
if (is_cif == TRUE)
|
||||||
|
dscale = CIFGetScale(100) / CIFGetOutputScale(1000);
|
||||||
|
else
|
||||||
|
dscale = 1.0;
|
||||||
|
|
||||||
|
/* When printing user/grid units, check for a valid window */
|
||||||
|
|
||||||
|
locunits = DBWUnits;
|
||||||
|
if (locunits != DBW_UNITS_DEFAULT) locunits &= DBW_UNITS_TYPE_MASK;
|
||||||
|
|
||||||
|
/* The MagWindow argument is only needed for user units, since the
|
||||||
|
* user grid values are found there. Setting MagWindow to NULL
|
||||||
|
* effectively disables printing values in user grid units, which
|
||||||
|
* then default to internal units.
|
||||||
|
*/
|
||||||
|
if (locunits == DBW_UNITS_USER)
|
||||||
|
{
|
||||||
|
if (w == (MagWindow *)NULL)
|
||||||
|
{
|
||||||
|
windCheckOnlyWindow(&w, DBWclientID);
|
||||||
|
if (w == (MagWindow *)NULL)
|
||||||
|
locunits = DBW_UNITS_DEFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (locunits)
|
||||||
|
{
|
||||||
|
case DBW_UNITS_DEFAULT:
|
||||||
|
snprintf(result, 32, "%d", value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DBW_UNITS_INTERNAL:
|
||||||
|
if (is_cif)
|
||||||
|
{
|
||||||
|
if (is_square)
|
||||||
|
{
|
||||||
|
snprintf(result, 32, "%.6f", value * dscale * dscale);
|
||||||
|
dbwValueFormat(result, 6);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(result, 32, "%.3f", value * dscale);
|
||||||
|
dbwValueFormat(result, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
snprintf(result, 32, "%d", value);
|
||||||
|
if (is_square)
|
||||||
|
{
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 29))
|
||||||
|
strcat(result, "i^2");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 31))
|
||||||
|
strcat(result, "i");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DBW_UNITS_LAMBDA:
|
||||||
|
|
||||||
|
oscale = (float)DBLambda[0];
|
||||||
|
oscale /= (float)DBLambda[1];
|
||||||
|
if (is_square)
|
||||||
|
{
|
||||||
|
fvalue = (float)value * oscale * oscale * dscale * dscale;
|
||||||
|
snprintf(result, 32, "%0.6f", (double)fvalue);
|
||||||
|
dbwValueFormat(result, 6);
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 29))
|
||||||
|
strcat(result, "l^2");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fvalue = (float)value * oscale * dscale;
|
||||||
|
snprintf(result, 32, "%0.3f", (double)fvalue);
|
||||||
|
dbwValueFormat(result, 3);
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 31))
|
||||||
|
strcat(result, "l");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DBW_UNITS_MICRONS:
|
||||||
|
oscale = CIFGetOutputScale(1000);
|
||||||
|
if (is_square)
|
||||||
|
{
|
||||||
|
fvalue = (float)value * oscale * oscale * dscale * dscale;
|
||||||
|
snprintf(result, 32, "%0.6f", (double)fvalue);
|
||||||
|
dbwValueFormat(result, 6);
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 28))
|
||||||
|
strcat(result, "um^2");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fvalue = (float)value * oscale * dscale;
|
||||||
|
snprintf(result, 32, "%0.3f", (double)fvalue);
|
||||||
|
dbwValueFormat(result, 3);
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 30))
|
||||||
|
strcat(result, "um");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DBW_UNITS_USER:
|
||||||
|
if (is_square)
|
||||||
|
{
|
||||||
|
oscale = (float)((crec->dbw_gridRect.r_xtop -
|
||||||
|
crec->dbw_gridRect.r_xbot) *
|
||||||
|
(crec->dbw_gridRect.r_ytop -
|
||||||
|
crec->dbw_gridRect.r_ybot));
|
||||||
|
}
|
||||||
|
else if (is_x)
|
||||||
|
{
|
||||||
|
oscale = (float)(crec->dbw_gridRect.r_xtop -
|
||||||
|
crec->dbw_gridRect.r_xbot);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oscale = (float)(crec->dbw_gridRect.r_ytop -
|
||||||
|
crec->dbw_gridRect.r_ybot);
|
||||||
|
}
|
||||||
|
fvalue = (float)value * oscale * dscale;
|
||||||
|
if (is_square)
|
||||||
|
{
|
||||||
|
fvalue *= dscale;
|
||||||
|
snprintf(result, 32, "%0.6f", (double)fvalue);
|
||||||
|
dbwValueFormat(result, 6);
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 27))
|
||||||
|
strcat(result, "gx*gy");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(result, 32, "%0.3f", (double)fvalue);
|
||||||
|
dbwValueFormat(result, 3);
|
||||||
|
if (is_x)
|
||||||
|
{
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 30))
|
||||||
|
strcat(result, "gx");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((DBWUnits & DBW_UNITS_PRINT_FLAG) && (strlen(result) < 30))
|
||||||
|
strcat(result, "gy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* DBWPrintValue --
|
||||||
|
* DBWPrintSqValue --
|
||||||
|
* DBWPrintCIFValue --
|
||||||
|
* DBWPrintCIFSqValue --
|
||||||
|
*
|
||||||
|
* Convenience functions which call dbwPrintValue0() with specific
|
||||||
|
* fixed arguments, so that the calls are not full of boolean values.
|
||||||
|
* The "is_x" boolean is retained because it is used often.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *
|
||||||
|
DBWPrintValue(int value, /* value to print, in internal units */
|
||||||
|
MagWindow *w, /* current window, for use with grid */
|
||||||
|
bool is_x) /* TRUE if value is an X dimension */
|
||||||
|
{
|
||||||
|
/* Call dbwPrintValue0() with is_square = FALSE and is_cif = FALSE */
|
||||||
|
return dbwPrintValue0(value, w, is_x, FALSE, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
DBWPrintSqValue(int value, /* value to print, in internal units */
|
||||||
|
MagWindow *w) /* current window, for use with grid */
|
||||||
|
{
|
||||||
|
/* Call dbwPrintValue0() with is_square = TRUE and is_cif = FALSE */
|
||||||
|
/* is_x is set to TRUE although it is unused. */
|
||||||
|
return dbwPrintValue0(value, w, TRUE, TRUE, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
DBWPrintCIFValue(int value, /* value to print, in internal units */
|
||||||
|
MagWindow *w, /* current window, for use with grid */
|
||||||
|
bool is_x) /* TRUE if value is an X dimension */
|
||||||
|
{
|
||||||
|
/* Call dbwPrintValue0() with is_square = FALSE and is_cif = TRUE */
|
||||||
|
return dbwPrintValue0(value, w, is_x, FALSE, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
DBWPrintCIFSqValue(int value, /* value to print, in internal units */
|
||||||
|
MagWindow *w) /* current window, for use with grid */
|
||||||
|
{
|
||||||
|
/* Call dbwPrintValue0() with is_square = TRUE and is_cif = TRUE */
|
||||||
|
/* is_x is set to TRUE although it is unused. */
|
||||||
|
return dbwPrintValue0(value, w, TRUE, TRUE, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -65,11 +65,21 @@ typedef struct _crosshairRec {
|
||||||
static CrosshairRec curCrosshair; /* Crosshair position */
|
static CrosshairRec curCrosshair; /* Crosshair position */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the following is DBW_SNAP_USER, the box gets snapped to the user's
|
* If the following is DBW_UNITS_USER, the box gets snapped to the user's
|
||||||
* grid always, instead of snapping to the usual 1x1 grid. If the value
|
* grid always, instead of snapping to the usual 1x1 grid. If the value
|
||||||
* is DBW_SNAP_INTERNAL, the box gets snapped to the internal grid.
|
* is DBW_UNITS_INTERNAL, the box gets snapped to the internal grid.
|
||||||
*/
|
*/
|
||||||
int DBWSnapToGrid = DBW_SNAP_LAMBDA;
|
int DBWSnapToGrid = DBW_UNITS_LAMBDA;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The original behavior with respect to units was that un-suffixed
|
||||||
|
* values follow whatever the snap setting is (DBWSnapToGrid, above).
|
||||||
|
* Current behavior is that the original behavior is followed while
|
||||||
|
* DBWUnits is set to DBW_UNITS_DEFAULT. However, if the "units"
|
||||||
|
* command is given, then displayed and entered units follow that
|
||||||
|
* value independently of the snap setting.
|
||||||
|
*/
|
||||||
|
int DBWUnits = DBW_UNITS_DEFAULT;
|
||||||
|
|
||||||
/* Forward reference: */
|
/* Forward reference: */
|
||||||
|
|
||||||
|
|
@ -82,8 +92,8 @@ extern int DBWToolDraw();
|
||||||
* toolFindPoint --
|
* toolFindPoint --
|
||||||
*
|
*
|
||||||
* Returns the point in root coordinates.
|
* Returns the point in root coordinates.
|
||||||
* If DBWSnapToGrid is DBW_SNAP_USER, pick the nearest point that is
|
* If DBWSnapToGrid is DBW_UNITS_USER, pick the nearest point that is
|
||||||
* aligned with the window's grid. If DBWSnapToGrid is DBW_SNAP_LAMBDA,
|
* aligned with the window's grid. If DBWSnapToGrid is DBW_UNITS_LAMBDA,
|
||||||
* pick the nearest point that is an integer lambda value.
|
* pick the nearest point that is an integer lambda value.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
|
|
@ -120,7 +130,7 @@ toolFindPoint(p, rootPoint, rootArea)
|
||||||
if (!GEO_ENCLOSE(p, &WindCurrentWindow->w_screenArea)) return NULL;
|
if (!GEO_ENCLOSE(p, &WindCurrentWindow->w_screenArea)) return NULL;
|
||||||
|
|
||||||
WindPointToSurface(WindCurrentWindow, p, rootPoint, rootArea);
|
WindPointToSurface(WindCurrentWindow, p, rootPoint, rootArea);
|
||||||
if (DBWSnapToGrid != DBW_SNAP_INTERNAL)
|
if (DBWSnapToGrid != DBW_UNITS_INTERNAL)
|
||||||
ToolSnapToGrid(WindCurrentWindow, rootPoint, rootArea);
|
ToolSnapToGrid(WindCurrentWindow, rootPoint, rootArea);
|
||||||
return WindCurrentWindow;
|
return WindCurrentWindow;
|
||||||
|
|
||||||
|
|
@ -764,7 +774,10 @@ DBWDrawBox(window, plane)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dbwBoxAlways1()
|
dbwBoxAlways1(
|
||||||
|
Tile *tile, /* (unused) */
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
|
ClientData clientdata) /* (unused) */
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -841,8 +854,8 @@ DBWResetBox(CellDef *def)
|
||||||
* Repositions the box by one of its corners.
|
* Repositions the box by one of its corners.
|
||||||
* If the point given to reposition the box is in screen coordinates,
|
* If the point given to reposition the box is in screen coordinates,
|
||||||
* the box corner is snapped to the user's grid (set with the :grid
|
* the box corner is snapped to the user's grid (set with the :grid
|
||||||
* command) if DBWSnapToGrid is DBW_SNAP_USER. If DBWSnapToGrid is
|
* command) if DBWSnapToGrid is DBW_UNITS_USER. If DBWSnapToGrid is
|
||||||
* DBW_SNAP_LAMBDA, the box corner is snapped to the nearest integer
|
* DBW_UNITS_LAMBDA, the box corner is snapped to the nearest integer
|
||||||
* lambda value.
|
* lambda value.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
|
|
@ -945,8 +958,8 @@ ToolMoveBox(corner, point, screenCoords, rootDef)
|
||||||
*
|
*
|
||||||
* If the point given to reposition the box is in screen coordinates,
|
* If the point given to reposition the box is in screen coordinates,
|
||||||
* the box corner is snapped to the user's grid (set with the :grid
|
* the box corner is snapped to the user's grid (set with the :grid
|
||||||
* command) if DBWSnapToGrid is DBW_SNAP_USER. If DBWSnapToGrid is
|
* command) if DBWSnapToGrid is DBW_UNITS_USER. If DBWSnapToGrid is
|
||||||
* DBW_SNAP_LAMBDA, the box corner is snapped to the nearest integer
|
* DBW_UNITS_LAMBDA, the box corner is snapped to the nearest integer
|
||||||
* lambda value.
|
* lambda value.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
|
|
@ -1089,7 +1102,7 @@ ToolSnapToGrid(w, p, rEnclose)
|
||||||
if (crec == NULL || p == NULL)
|
if (crec == NULL || p == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (DBWSnapToGrid == DBW_SNAP_LAMBDA)
|
if (DBWSnapToGrid == DBW_UNITS_LAMBDA)
|
||||||
{
|
{
|
||||||
lr.r_xbot = lr.r_ybot = 0;
|
lr.r_xbot = lr.r_ybot = 0;
|
||||||
lr.r_xtop = DBLambda[1] / DBLambda[0];
|
lr.r_xtop = DBLambda[1] / DBLambda[0];
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ typedef struct DBW1 {
|
||||||
|
|
||||||
extern WindClient DBWclientID;
|
extern WindClient DBWclientID;
|
||||||
extern int DBWSnapToGrid;
|
extern int DBWSnapToGrid;
|
||||||
|
extern int DBWUnits;
|
||||||
|
|
||||||
extern int DBWMaxTechStyles;
|
extern int DBWMaxTechStyles;
|
||||||
extern int DBWMaxTileStyles;
|
extern int DBWMaxTileStyles;
|
||||||
|
|
@ -121,13 +122,17 @@ extern int DBWNumStyles;
|
||||||
extern int RtrPolyWidth, RtrMetalWidth, RtrContactWidth;
|
extern int RtrPolyWidth, RtrMetalWidth, RtrContactWidth;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exported procedure headers for redisplay
|
* Exported procedure headers for redisplay and output
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern int DBWWatchTiles();
|
extern int DBWWatchTiles();
|
||||||
extern void DBWAreaChanged();
|
extern void DBWAreaChanged();
|
||||||
extern void DBWLabelChanged();
|
extern void DBWLabelChanged();
|
||||||
extern void DBWDrawLabel();
|
extern void DBWDrawLabel();
|
||||||
|
extern char *DBWPrintValue(int value, MagWindow *w, bool is_x);
|
||||||
|
extern char *DBWPrintSqValue(int value, MagWindow *w);
|
||||||
|
extern char *DBWPrintCIFValue(int value, MagWindow *w, bool is_x);
|
||||||
|
extern char *DBWPrintCIFSqValue(int value, MagWindow *w);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exported procedures and variables related to the technology file
|
* Exported procedures and variables related to the technology file
|
||||||
|
|
@ -169,14 +174,36 @@ extern void DBWBoxHandler();
|
||||||
#define TOOL_ILG -1
|
#define TOOL_ILG -1
|
||||||
|
|
||||||
/* The following defines are used to indicate which coordinate system
|
/* The following defines are used to indicate which coordinate system
|
||||||
* the cursor box snaps to when moved with mouse clicks (values for
|
* is used when displaying or returning values. By default this is
|
||||||
* DBWSnapToGrid).
|
* set to DBW_UNITS_INTERNAL. From magic version 8.3.595, this is
|
||||||
|
* independently set from "snap". For backwards compatibility,
|
||||||
|
* the value starts as DBW_UNITS_DEFAULT which implements the original
|
||||||
|
* behavior in which the "snap" setting dictates the dispaly units.
|
||||||
|
* Only if set to a non-negative value do the display units operate
|
||||||
|
* independently of the snap setting.
|
||||||
|
*
|
||||||
|
* NOTES:
|
||||||
|
* Lambda units are fixed by the tech file.
|
||||||
|
* Internal units are scalable.
|
||||||
|
* User units are scalable; this can be used, for example, to
|
||||||
|
* set a box position according to multiples of a track
|
||||||
|
* pitch, but is most often used manually with the "g"
|
||||||
|
* (for "grid") suffix; e.g., "move box e 1g"
|
||||||
|
* Micron units are dependent on the specified cifoutput style
|
||||||
|
* and how the tech file defines the scalefactor for it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DBW_SNAP_INTERNAL 0 /* internal units (fine grid) */
|
#define DBW_UNITS_DEFAULT -1 /* backwards-compatible behavior */
|
||||||
#define DBW_SNAP_LAMBDA 1 /* lambda units (coarse grid) */
|
#define DBW_UNITS_INTERNAL 0 /* internal units */
|
||||||
#define DBW_SNAP_USER 2 /* user grid units (user grid) */
|
#define DBW_UNITS_LAMBDA 1 /* lambda units */
|
||||||
#define DBW_SNAP_MICRONS 3 /* micron units */
|
#define DBW_UNITS_USER 2 /* user grid units */
|
||||||
|
#define DBW_UNITS_MICRONS 3 /* micron units */
|
||||||
|
#define DBW_UNITS_TYPE_MASK 3 /* everything but the flag field(s) */
|
||||||
|
#define DBW_UNITS_PRINT_FLAG 4 /* flag used to indicate that
|
||||||
|
* the units should be printed
|
||||||
|
* with the value; e.g.,
|
||||||
|
* "10um" instead of "10".
|
||||||
|
*/
|
||||||
|
|
||||||
/* The following window mask can be used to select all database windows
|
/* The following window mask can be used to select all database windows
|
||||||
* for things like the mask parameter to DBWAreaChanged.
|
* for things like the mask parameter to DBWAreaChanged.
|
||||||
|
|
|
||||||
|
|
@ -334,23 +334,23 @@
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
<TD> <A HREF=undo.html> <B>undo</B></A> </TD>
|
<TD> <A HREF=undo.html> <B>undo</B></A> </TD>
|
||||||
|
<TD> <A HREF=units.html> <B>units</B></A> </TD>
|
||||||
<TD> <A HREF=updatedisplay.html> <B>updatedisplay</B></A> </TD>
|
<TD> <A HREF=updatedisplay.html> <B>updatedisplay</B></A> </TD>
|
||||||
<TD> <A HREF=version.html> <B>version</B></A> </TD>
|
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
|
<TD> <A HREF=version.html> <B>version</B></A> </TD>
|
||||||
<TD> <A HREF=view.html> <B>view</B></A> </TD>
|
<TD> <A HREF=view.html> <B>view</B></A> </TD>
|
||||||
<TD> <A HREF=windowborder.html> <B>windowborder</B></A> </TD>
|
<TD> <A HREF=windowborder.html> <B>windowborder</B></A> </TD>
|
||||||
<TD> <A HREF=windowcaption.html> <B>windowcaption</B></A> </TD>
|
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
|
<TD> <A HREF=windowcaption.html> <B>windowcaption</B></A> </TD>
|
||||||
<TD> <A HREF=windownames.html> <B>windownames</B></A> </TD>
|
<TD> <A HREF=windownames.html> <B>windownames</B></A> </TD>
|
||||||
<TD> <A HREF=windowscrollbars.html> <B>windowscrollbars</B></A> </TD>
|
<TD> <A HREF=windowscrollbars.html> <B>windowscrollbars</B></A> </TD>
|
||||||
<TD> <A HREF=xview.html> <B>xview</B></A> </TD>
|
|
||||||
</TR>
|
</TR>
|
||||||
<TR>
|
<TR>
|
||||||
|
<TD> <A HREF=xview.html> <B>xview</B></A> </TD>
|
||||||
<TD> <A HREF=zoom.html> <B>zoom</B></A> </TD>
|
<TD> <A HREF=zoom.html> <B>zoom</B></A> </TD>
|
||||||
<TD> <A HREF=tk_path_name.html> <I>tk_path_name</I></A> </TD>
|
<TD> <A HREF=tk_path_name.html> <I>tk_path_name</I></A> </TD>
|
||||||
<TD> </TD>
|
|
||||||
</TR>
|
</TR>
|
||||||
</TBODY>
|
</TBODY>
|
||||||
</TABLE>
|
</TABLE>
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,7 @@ techmanager
|
||||||
tool
|
tool
|
||||||
undo
|
undo
|
||||||
unexpand
|
unexpand
|
||||||
|
units
|
||||||
updatedisplay
|
updatedisplay
|
||||||
upsidedown
|
upsidedown
|
||||||
version
|
version
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,11 @@ Circuit netlist extractor
|
||||||
<DL>
|
<DL>
|
||||||
<DT> <B>capacitance</B>
|
<DT> <B>capacitance</B>
|
||||||
<DD> Extract local parasitic capacitance values to substrate
|
<DD> Extract local parasitic capacitance values to substrate
|
||||||
<DT> <B>resistance</B>
|
<DT> <B>coupling</B>
|
||||||
<DD> Extract lumped resistance values. Note that this
|
<DD> Extract the parasitic coupling capacitance between
|
||||||
is <I>not</I> the same as full parasitic resistance.
|
nodes.
|
||||||
|
<DT> <B>lumped</B>
|
||||||
|
<DD> Extract lumped resistance values.
|
||||||
The values extracted are "lumped" resistance and
|
The values extracted are "lumped" resistance and
|
||||||
indicate the value for which the delay through the
|
indicate the value for which the delay through the
|
||||||
net can be computed with R times C, where R is the
|
net can be computed with R times C, where R is the
|
||||||
|
|
@ -55,9 +57,10 @@ Circuit netlist extractor
|
||||||
command. Lumped resistances have no meaning in
|
command. Lumped resistances have no meaning in
|
||||||
SPICE netlists and will only be used when running
|
SPICE netlists and will only be used when running
|
||||||
<B>ext2sim</B> to generate a .sim netlist.
|
<B>ext2sim</B> to generate a .sim netlist.
|
||||||
<DT> <B>coupling</B>
|
Prior to magic version 8.3.597, this option was
|
||||||
<DD> Extract the parasitic coupling capacitance between
|
<B>resistance</B>, but as that was often confused
|
||||||
nodes.
|
with full parasitic resistance extraction, it has
|
||||||
|
been changed.
|
||||||
<DT> <B>length</B>
|
<DT> <B>length</B>
|
||||||
<DD> Extract the length of the shortest path from a driver
|
<DD> Extract the length of the shortest path from a driver
|
||||||
to a receiver, for computing more accurate parasitic
|
to a receiver, for computing more accurate parasitic
|
||||||
|
|
@ -73,7 +76,7 @@ Circuit netlist extractor
|
||||||
array instances, is guaranteed to be strictly positive.
|
array instances, is guaranteed to be strictly positive.
|
||||||
<DT> <B>all</B>
|
<DT> <B>all</B>
|
||||||
<DD> Apply all standard options (does not include options
|
<DD> Apply all standard options (does not include options
|
||||||
"local", "labelcheck", or "aliases").
|
"local", "labelcheck", "aliases", or "resistance").
|
||||||
<DT> <B>local</B>
|
<DT> <B>local</B>
|
||||||
<DD> Write all .ext files to the current working directory.
|
<DD> Write all .ext files to the current working directory.
|
||||||
If not specified, each .ext file will be placed in the
|
If not specified, each .ext file will be placed in the
|
||||||
|
|
@ -99,6 +102,28 @@ Circuit netlist extractor
|
||||||
but will usually just slow down processing by commands
|
but will usually just slow down processing by commands
|
||||||
like "ext2spice" that use the .ext file contents, so it
|
like "ext2spice" that use the .ext file contents, so it
|
||||||
is disabled by default.
|
is disabled by default.
|
||||||
|
<DT> <B>unique</B>
|
||||||
|
<DD> (Added in magic version 8.3.594) This setting replaces
|
||||||
|
the use of the command option "extract unique". Instead
|
||||||
|
of changing labels in the design, unique labels are
|
||||||
|
generated for the duration of the extraction, and then
|
||||||
|
reverted back to the original text. The "extract unique"
|
||||||
|
command option is maintained for backwards compatibility.
|
||||||
|
Note the difference: "extract unique" is a command that
|
||||||
|
runs immediately, and cannot be undone;
|
||||||
|
"extract do unique" is an option setting for "extract".
|
||||||
|
<DT> <B>resistance</B>
|
||||||
|
<DD> (Added in magic version 8.3.597) This setting replaces
|
||||||
|
the use of the standalone command "extresist". The
|
||||||
|
effect is the same: Magic performs full R-C extraction,
|
||||||
|
generating a <TT>.res.ext</TT> file that annotates the
|
||||||
|
existing <TT>.ext</TT> file (see the "extresist" command
|
||||||
|
documentation). The "extresist" command options can
|
||||||
|
still be used to set options such as tolerance for the
|
||||||
|
R-C extraction.
|
||||||
|
Note that prior to magic version 8.3.597, this option
|
||||||
|
name would produce the lumped resistance approximation
|
||||||
|
(see <B>lumped</B>, above).
|
||||||
</DL>
|
</DL>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
These options (except for "local") determine how much
|
These options (except for "local") determine how much
|
||||||
|
|
@ -213,7 +238,9 @@ Circuit netlist extractor
|
||||||
<I>Warning:</I> This operation immediately modifies the
|
<I>Warning:</I> This operation immediately modifies the
|
||||||
existing layout in preparation for extraction. Label
|
existing layout in preparation for extraction. Label
|
||||||
modifications are permanent, and cannot be undone. All
|
modifications are permanent, and cannot be undone. All
|
||||||
cells in the hierarchy may potentially be modified. <BR>
|
cells in the hierarchy may potentially be modified. To avoid
|
||||||
|
this issue, use the "extract do unique" option instead (see
|
||||||
|
above). <BR>
|
||||||
<DT> <B>warn</B> [[<B>no</B>] <I>option</I>]
|
<DT> <B>warn</B> [[<B>no</B>] <I>option</I>]
|
||||||
<DD> Enable/disable reporting of non-fatal errors, where <I>option</I>
|
<DD> Enable/disable reporting of non-fatal errors, where <I>option</I>
|
||||||
may be one of the following:
|
may be one of the following:
|
||||||
|
|
|
||||||
|
|
@ -92,17 +92,25 @@ information.
|
||||||
The <B>extresist</B> command provides a method for generating
|
The <B>extresist</B> command provides a method for generating
|
||||||
a more detailed model of resistance, in which long network
|
a more detailed model of resistance, in which long network
|
||||||
routes and branching routes are replaced with resistor devices
|
routes and branching routes are replaced with resistor devices
|
||||||
and device networks. <P>
|
and device networks. This is known as "full R-C extraction". <P>
|
||||||
|
|
||||||
Using <B>extresist</B> is a multi-step process. It is first
|
Using <B>extresist</B> as a standalone command is a multi-step
|
||||||
necessary to run both <B>extract</B> and <B>ext2sim</B> to get
|
process. It is first necessary to run <B>extract</B> to get
|
||||||
the initial netlist (with lumped, not detailed, resistances).
|
the initial netlist.
|
||||||
After a <TT>.sim</TT> file has been generated, the
|
After a <TT>.ext</TT> file has been generated, the
|
||||||
<B>extresist all</B> command may be run. The output is
|
<B>extresist</B> command may be run. The output is
|
||||||
a file <TT>.res.ext</TT> for each cell in the hierarchy.
|
a file <TT>.res.ext</TT> for each cell in the hierarchy.
|
||||||
Finally, with the option <B>extresist on</B> set,
|
Finally, with the option <B>extresist on</B> set, <B>ext2spice</B>
|
||||||
<B>ext2sim</B> or <B>ext2spice</B> will generate the final,
|
will generate the final, detailed simulation file. <P>
|
||||||
detailed simulation file. <P>
|
|
||||||
|
Prior to magic version 8.3.597, it was also necessary to run
|
||||||
|
<B>ext2sim labels on</B> and <B>ext2sim</B> to write out a
|
||||||
|
<TT>.sim</TT> and a <TT>.node</TT> file before running
|
||||||
|
<B>extresist</B>. This is no longer necessary. There is since
|
||||||
|
magic version 8.3.597 an option <B>extract do resistance</B>
|
||||||
|
that runs the resistance extraction in sequence with the regular
|
||||||
|
extraction, producing both the <TT>.ext</TT> and <TT>.res.ext</TT>
|
||||||
|
files.
|
||||||
|
|
||||||
More details on using <B>extresist</B> can be found in
|
More details on using <B>extresist</B> can be found in
|
||||||
<B>magic</B> Tutorial number 8.
|
<B>magic</B> Tutorial number 8.
|
||||||
|
|
@ -117,6 +125,7 @@ information.
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<A HREF=extract.html><B>extract</B></A> <BR>
|
<A HREF=extract.html><B>extract</B></A> <BR>
|
||||||
<A HREF=ext2sim.html><B>ext2sim</B></A> <BR>
|
<A HREF=ext2sim.html><B>ext2sim</B></A> <BR>
|
||||||
|
<A HREF=ext2spice.html><B>ext2spice</B></A> <BR>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<P><IMG SRC=graphics/line1.gif><P>
|
<P><IMG SRC=graphics/line1.gif><P>
|
||||||
|
|
|
||||||
|
|
@ -182,6 +182,13 @@ Read GDSII input or generate GDSII output.
|
||||||
than to subsplit the internal grid to such a fine value.
|
than to subsplit the internal grid to such a fine value.
|
||||||
The "<B>cif limit</B>" function may also be used to limit
|
The "<B>cif limit</B>" function may also be used to limit
|
||||||
grid subdivision to a minimum value.
|
grid subdivision to a minimum value.
|
||||||
|
<DT> <B>savepaths</B> [<B>yes</B>|<B>no</B>]
|
||||||
|
<DD> When reading paths from a GDS file, record the centerline of
|
||||||
|
the path as a property in the cell. The default behavior is
|
||||||
|
<B>no</B>. If no argument is given, then return the status
|
||||||
|
of the <B>savepaths</B> option. The first path property is
|
||||||
|
named "<TT>path</TT>", followed by "<TT>path_0</TT>" and
|
||||||
|
increasing the suffix index for each individual path read.
|
||||||
<DT> <B>unique</B> [<B>yes</B>|<B>no</B>]
|
<DT> <B>unique</B> [<B>yes</B>|<B>no</B>]
|
||||||
<DD> When reading a GDS file, this option forces magic to rename
|
<DD> When reading a GDS file, this option forces magic to rename
|
||||||
cell definitions in the database when a cell of the same name
|
cell definitions in the database when a cell of the same name
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,50 @@ Place a label in the layout
|
||||||
to another layer. <P>
|
to another layer. <P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<B>Attribute labels:</B> <P>
|
||||||
|
A handful of labels are referred to as "attribute" labels. These
|
||||||
|
label types are placed on devices and affect how the device is
|
||||||
|
extracted. <P>
|
||||||
|
|
||||||
|
A label that is placed inside a device (e.g., a MOSFET gate) which
|
||||||
|
ends with the character "<B>^</B>" is a <I>gate attribute</I>. A
|
||||||
|
gate attribute in the form of "<I>name</I><B>=</B><I>value</I><B>^</B>"
|
||||||
|
specifies an extra parameter to be passed to the device in addition
|
||||||
|
to the standard parameters calculated for that device. This is used
|
||||||
|
to capture parameters which cannot easily be inferred from the layout.
|
||||||
|
For example, an RF device model might be distinguished from a non-RF
|
||||||
|
device model by a parameter such as <B>rfmode=1</B>. Whether or not
|
||||||
|
a device is intended for RF use is not easily guessed from the layout,
|
||||||
|
and so "tagging" the gate with the parameter allows the correct model
|
||||||
|
parameters to be used for the device. <P>
|
||||||
|
|
||||||
|
A gate attribute that is not in the form of a parameter will be used
|
||||||
|
as the device's instance index in the netlist; e.g., a label of
|
||||||
|
"<B>1^</B>" on a MOSFET gate extracted as a MOSFET device would be an
|
||||||
|
entry "<B>M1</B>" in the netlist. This can be used to better track
|
||||||
|
device indexes between a schematic and layout. <P>
|
||||||
|
|
||||||
|
A label that is placed on the <I>edge</I> a device, specificlly a
|
||||||
|
MOSFET gate, and which ends with the character "<B>$</B>", is a
|
||||||
|
<I>terminal attribute</I>. The only terminal attributes recognized
|
||||||
|
by magic are <B>S$</B> and <B>D$</B>, which specify which side of the
|
||||||
|
gate is to be considered the source and which is to be considered the
|
||||||
|
drain. Generally, MOSFET devices are symmetric, and their use in a
|
||||||
|
simulation does not depend on which side is in the position of the
|
||||||
|
"source" and which is in the position of the "drain". To the extent
|
||||||
|
that it matters, the terminal attributes can be used to ensure that
|
||||||
|
the source and drain connections appear in the netlist in their
|
||||||
|
intended orientation. <P>
|
||||||
|
|
||||||
|
Labels ending with "<B>@</B>" are <I>node attributes</I>. There is
|
||||||
|
currently no functional application for node attributes. When one
|
||||||
|
is applied, it will appear in the output netlist in a SPICE comment
|
||||||
|
line indicating the node and attribute. This could be used, say,
|
||||||
|
by a post-processing script, but as it is in a comment line, it has
|
||||||
|
no impact on simulation or LVS.
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H3>Implementation Notes:</H3>
|
<H3>Implementation Notes:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<B>label</B> is implemented as a built-in command in <B>magic</B>.
|
<B>label</B> is implemented as a built-in command in <B>magic</B>.
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,13 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
|
|
||||||
<H3>Usage:</H3>
|
<H3>Usage:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<B>property</B> [<I>key</I> [<I>value</I>]] <BR><BR>
|
<B>property</B> [<I>list</I>] [<I>type</I>] [<I>key</I> [<I>value</I>]] <BR>
|
||||||
|
or
|
||||||
|
<B>property</B> [<B>compat</B>] [<B>true</B>|<B>false</B>] <BR><BR>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
where <I>key</I> and <I>value</I> are any text strings.
|
where <I>key</I> and <I>value</I> are any text strings. <BR>
|
||||||
|
<I>type</I> may be one of <B>string</B>, <B>integer</B>,
|
||||||
|
<B>dimension</B>, or <B>double</B>.
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
|
@ -45,11 +49,64 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
with the key is returned. With both arguments, the string
|
with the key is returned. With both arguments, the string
|
||||||
<I>value</I> is associated with the string <I>key</I> as a
|
<I>value</I> is associated with the string <I>key</I> as a
|
||||||
property of the cell. If <I>key</I> is an existing key, then
|
property of the cell. If <I>key</I> is an existing key, then
|
||||||
its original value will be overwritten.
|
its original value will be overwritten. <P>
|
||||||
|
|
||||||
|
By default, properties are interpreted as verbatim string values,
|
||||||
|
with exceptions for the reserved types (see below). To force the
|
||||||
|
values of the property to be interpreted as a specific type, use
|
||||||
|
the <I>type</I> option. <P>
|
||||||
|
|
||||||
|
The <B>property compat</B> setting determines how properties are
|
||||||
|
written out to a .mag file. The default setting is <B>true</B>
|
||||||
|
(backwards compatibility mode), which writes all properties as
|
||||||
|
type "<TT>string</TT>". Properties which are reserved names
|
||||||
|
(see below) will be converted to the best type when reading the
|
||||||
|
.mag file. However, if the user wants to create a property that
|
||||||
|
is handled differently than a string (namely, to be a dimensional
|
||||||
|
value that scales), then comptability mode should be turned off. <P>
|
||||||
|
|
||||||
|
If the argument <I>list</I> is given as the first argument, and
|
||||||
|
<I>value</I> is not present, then if the property <I>key</I>
|
||||||
|
does not exist, then the command will return a NULL object to the
|
||||||
|
interpreter instead of printing an error message. This is the
|
||||||
|
"quiet" version of the command preferred for scripts that want to
|
||||||
|
query whether or not a specific property exists.
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
Property names reserved by and used by magic:
|
Types are interpreted as follows:
|
||||||
|
<DL>
|
||||||
|
<DT> <B>string</B> type:
|
||||||
|
<DD> The property value is a character string. Character strings
|
||||||
|
may contain spaces, but if so, then the string should be quoted
|
||||||
|
or in braces, per Tcl syntax.
|
||||||
|
<DT> <B>integer</I> type:
|
||||||
|
<DD> The property value is an integer value or a list of integer
|
||||||
|
values. The values are not considered to be measurements and
|
||||||
|
do not scale. Multiple values may be passed on the command
|
||||||
|
line as additional arguments, or the set of values may be
|
||||||
|
given as a list.
|
||||||
|
<DT> <B>dimension</I> type:
|
||||||
|
<DD> The property value is an integer value or a list of integer
|
||||||
|
values. The values are considered to be (linear) dimensional
|
||||||
|
measurements and therefore scale with the database internal
|
||||||
|
units. They are interpreted as having the values currently
|
||||||
|
specified for <B>units</B>, and display back in the same
|
||||||
|
units. Multiple values may be passed on the command line as
|
||||||
|
additional arguments, or the set of values may be given as a
|
||||||
|
list.
|
||||||
|
<DT> <B>double</I> type:
|
||||||
|
<DD> The property value is a double-wide (64-bit) integer value or
|
||||||
|
a list of double-wide integer values. The values are not
|
||||||
|
considered to be measurements and do not scale. Multiple
|
||||||
|
values may be passed on the command line as additional arguments,
|
||||||
|
or the set of values may be given as a list.
|
||||||
|
</DL>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
Property names reserved by and used by magic (types are <B>string</B>
|
||||||
|
unless otherwise noted):
|
||||||
<DL>
|
<DL>
|
||||||
<DT> <B>GDS_FILE</B>
|
<DT> <B>GDS_FILE</B>
|
||||||
<DD> The value is the name of a GDS file which contains the mask
|
<DD> The value is the name of a GDS file which contains the mask
|
||||||
|
|
@ -60,12 +117,14 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
<DD> If a <B>GDS_FILE</B> is defined, then this value indicates the
|
<DD> If a <B>GDS_FILE</B> is defined, then this value indicates the
|
||||||
byte position of the start of mask data for this cell definition
|
byte position of the start of mask data for this cell definition
|
||||||
in the file. If set to value <B>0</B>, then the file will be
|
in the file. If set to value <B>0</B>, then the file will be
|
||||||
searched for the data bounds.
|
searched for the data bounds. This property is always of type
|
||||||
|
<B>double</B>.
|
||||||
<DT> <B>GDS_END</B>
|
<DT> <B>GDS_END</B>
|
||||||
<DD> If a <B>GDS_FILE</B> is defined, then this value indicates the
|
<DD> If a <B>GDS_FILE</B> is defined, then this value indicates the
|
||||||
byte position of the end of mask data for this cell definition
|
byte position of the end of mask data for this cell definition
|
||||||
in the file. If <B>GDS_START</B> is set to <B>0</B>, then this
|
in the file. If <B>GDS_START</B> is set to <B>0</B>, then this
|
||||||
property may be omitted.
|
property may be omitted. This property is always of type
|
||||||
|
<B>double</B>.
|
||||||
<DT> <B>LEFview</B>
|
<DT> <B>LEFview</B>
|
||||||
<DD> If set to <B>TRUE</B>, this cell is an abstract view such as that
|
<DD> If set to <B>TRUE</B>, this cell is an abstract view such as that
|
||||||
obtained from a LEF macro, and should not be used for extraction
|
obtained from a LEF macro, and should not be used for extraction
|
||||||
|
|
@ -97,6 +156,8 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
corresponding to the abutment box of the cell, in magic's internal
|
corresponding to the abutment box of the cell, in magic's internal
|
||||||
units. The abutment box is automatically read from LEF files, but
|
units. The abutment box is automatically read from LEF files, but
|
||||||
may be defined for any file and can be used for placement alignment.
|
may be defined for any file and can be used for placement alignment.
|
||||||
|
This property is always of type <B>dimension</B> and must contain
|
||||||
|
exactly four values.
|
||||||
<DT> <B>OBS_BBOX</B>
|
<DT> <B>OBS_BBOX</B>
|
||||||
<DD> This property value is a space-sparated list of four integer values
|
<DD> This property value is a space-sparated list of four integer values
|
||||||
corresponding to a bounding box to be used when generating a LEF
|
corresponding to a bounding box to be used when generating a LEF
|
||||||
|
|
@ -104,7 +165,8 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
will be entirely covered in obstruction layers (unless cut-outs
|
will be entirely covered in obstruction layers (unless cut-outs
|
||||||
are required to accommodate pins). Any set-back applied by the
|
are required to accommodate pins). Any set-back applied by the
|
||||||
"lef write -hide <value>" option will be applied to this obstruction
|
"lef write -hide <value>" option will be applied to this obstruction
|
||||||
box.
|
box. This property is always of type <B>dimension</B> and must
|
||||||
|
contain exactly four values.
|
||||||
<DT> <B>flatten</B>
|
<DT> <B>flatten</B>
|
||||||
<DD> This property is used in conjunction with the "flatten -doproperty"
|
<DD> This property is used in conjunction with the "flatten -doproperty"
|
||||||
command option and marks the cell for flattening. Cells without
|
command option and marks the cell for flattening. Cells without
|
||||||
|
|
@ -146,7 +208,8 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
always generate mask layer <I>type</I> in the specified rectangle
|
always generate mask layer <I>type</I> in the specified rectangle
|
||||||
area when writing GDS or CIF output. <I>type</I> may be a templayer,
|
area when writing GDS or CIF output. <I>type</I> may be a templayer,
|
||||||
such that <I>type</I> could be defined as the absence of a mask layer,
|
such that <I>type</I> could be defined as the absence of a mask layer,
|
||||||
for example.
|
for example. This property is always of type <B>dimension</B> and
|
||||||
|
must have a multiple of four values.
|
||||||
</DL>
|
</DL>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
|
@ -157,6 +220,11 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
the cell definition structure.
|
the cell definition structure.
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3>See Also:</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<A HREF=units.html><B>units</B></A> <BR>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<P><IMG SRC=graphics/line1.gif><P>
|
<P><IMG SRC=graphics/line1.gif><P>
|
||||||
<TABLE BORDER=0>
|
<TABLE BORDER=0>
|
||||||
<TR>
|
<TR>
|
||||||
|
|
|
||||||
|
|
@ -39,21 +39,15 @@ in the selected grid.
|
||||||
feature size, and <B>user</B>, based on the value given by the
|
feature size, and <B>user</B>, based on the value given by the
|
||||||
user to the <B>grid</B> command. <P>
|
user to the <B>grid</B> command. <P>
|
||||||
|
|
||||||
In addition to changing the behavior of the box to mouse
|
Historically, in addition to changing the behavior of the box
|
||||||
button events, the <B>snap</B> command also changes the way
|
to mouse button events, the <B>snap</B> command also changed
|
||||||
that <A HREF=distance.html>distance measurements</A> are
|
the way that <A HREF=distance.html>distance measurements</A>
|
||||||
interpreted in commands that take distance arguments, such
|
are interpreted in commands that take distance arguments.
|
||||||
as <B>move</B>, <B>copy</B>, and <B>stretch</B>. An integer
|
This behavior remains the default for backwards compatibility.
|
||||||
number with no other identifying units is interpreted as a
|
The <B>units</B> command overrides this behavior and allows
|
||||||
measurement in the current snap grid. All other measurements
|
<B>snap</B> to control only the box positioning behavior,
|
||||||
must have an identifying unit: <B>i</B> for internal units,
|
independently of how unsuffixed values are parsed by the
|
||||||
<B>l</B> for lambda units, and <B>g</B> for user grid units
|
interpreter. <P>
|
||||||
(as well as the usual metric units). Even when <B>snap</B>
|
|
||||||
is set to the larger lambda or user grids, it is possible to
|
|
||||||
move the cursor box to finer grid positions from the command
|
|
||||||
line. See the reference page on
|
|
||||||
<A HREF=distance.html>distance measures</A> for a complete
|
|
||||||
description of distance values. <P>
|
|
||||||
|
|
||||||
<B>snap</B> with no arguments returns the current snap grid
|
<B>snap</B> with no arguments returns the current snap grid
|
||||||
type. <P>
|
type. <P>
|
||||||
|
|
@ -80,6 +74,7 @@ in the selected grid.
|
||||||
|
|
||||||
<H3>See Also:</H3>
|
<H3>See Also:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
|
<A HREF=units.html><B>units</B></A> <BR>
|
||||||
<A HREF=grid.html><B>grid</B></A> <BR>
|
<A HREF=grid.html><B>grid</B></A> <BR>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<STYLE type="text/css">
|
||||||
|
H1 {color: black }
|
||||||
|
H2 {color: maroon }
|
||||||
|
H3 {color: #007090 }
|
||||||
|
A.head:link {color: #0060a0 }
|
||||||
|
A.head:visited {color: #3040c0 }
|
||||||
|
A.head:active {color: white }
|
||||||
|
A.head:hover {color: yellow }
|
||||||
|
A.red:link {color: red }
|
||||||
|
A.red:visited {color: maroon }
|
||||||
|
A.red:active {color: yellow }
|
||||||
|
</STYLE>
|
||||||
|
</HEAD>
|
||||||
|
<TITLE>Magic-8.3 Command Reference</TITLE>
|
||||||
|
<BODY BACKGROUND=graphics/blpaper.gif>
|
||||||
|
<H1> <IMG SRC=graphics/magic_title8_3.png ALT="Magic VLSI Layout Tool Version 8.3">
|
||||||
|
<IMG SRC=graphics/magic_OGL_sm.gif ALIGN="top" ALT="*"> </H1>
|
||||||
|
|
||||||
|
<H2>units</H2>
|
||||||
|
<HR>
|
||||||
|
Cause distance measurements to be interpreted by default (with no
|
||||||
|
suffix provied) as measurments of the selected units, and also cause
|
||||||
|
distance measurements to be printed in the selected units.
|
||||||
|
<HR>
|
||||||
|
|
||||||
|
<H3>Usage:</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<B>units</B> [<B>internal</B>|<B>lambda</B>|<B>user</B>|<B>grid</B>|<B>microns</B>|<B>default</B>] [<B>print</B>|</B>noprint</B>] <BR>
|
||||||
|
or <BR>
|
||||||
|
<B>units</B> [<B>list</B>] <BR><BR>
|
||||||
|
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3>Summary:</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
The <B>units</B> command causes printed measurements to be
|
||||||
|
given in the selected units. The possible unit types are
|
||||||
|
<B>internal</B>, the size of the internal database units,
|
||||||
|
<B>lambda</B>, the lambda grid based on the technology minimum
|
||||||
|
feature size, <B>user</B> (or <B>grid</B>), based on the
|
||||||
|
value given by the user to the <B>grid</B> command, or
|
||||||
|
<B>microns</B>, which are physical units dependent on the
|
||||||
|
CIF or GDS output scaling as defined in the technology file. <P>
|
||||||
|
|
||||||
|
The <B>units</B> command also changes the way
|
||||||
|
that <A HREF=distance.html>distance measurements</A> are
|
||||||
|
interpreted in commands that take distance arguments, such
|
||||||
|
as <B>move</B>, <B>copy</B>, and <B>stretch</B>. An integer
|
||||||
|
number with no other identifying units is interpreted as a
|
||||||
|
measurement in the current units type. All other measurements
|
||||||
|
must have an identifying unit: <B>i</B> for internal units,
|
||||||
|
<B>l</B> for lambda units, and <B>g</B> for user grid units,
|
||||||
|
as well as the usual metric units such as <B>um</B> for
|
||||||
|
microns, <B>nm</B> for nanometers, and so forth. See the
|
||||||
|
reference page on <A HREF=distance.html>distance measures</A>
|
||||||
|
for a complete description of distance values. <P>
|
||||||
|
|
||||||
|
For printed units, the additional argument <B>print</B>
|
||||||
|
causes the units to be printed along with the value; e.g.,
|
||||||
|
"<B>1.0um</B>." This is the usual setting for interactive
|
||||||
|
use. The argument <B>noprint</B> suppresses the unit name,
|
||||||
|
which is appropriate for scripted use, when the value may
|
||||||
|
be passed to arithmetic expressions to be evaluated by the
|
||||||
|
interpreter. <P>
|
||||||
|
|
||||||
|
<B>units</B> with no arguments returns the current units type.
|
||||||
|
<B>units list</B> returns the current units type as a Tcl list
|
||||||
|
of two items; the first item is the units type, and the second
|
||||||
|
item is <B>print</B> or <B>noprint</B>, indicating whether units
|
||||||
|
suffixes are printed with the values. <P>
|
||||||
|
|
||||||
|
Historically, values parsed from the command line were interpreted
|
||||||
|
according to the <B>snap</B> setting. On startup, this behavior
|
||||||
|
remains in effect for backwards compatibility until overridden
|
||||||
|
with a <B>units</B> command. The command <B>units default</B>
|
||||||
|
reverts back to the original behavior. Once the <B>units</B>
|
||||||
|
default type is overridden, the <B>snap</B> behavior is controlled
|
||||||
|
independently of <B>units</B>. <P>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3>Implementation Notes:</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<B>units</B> is implemented as a built-in command in <B>magic</B>.
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<H3>See Also:</H3>
|
||||||
|
<BLOCKQUOTE>
|
||||||
|
<A HREF=grid.html><B>grid</B></A> <BR>
|
||||||
|
<A HREF=snap.html><B>snap</B></A> <BR>
|
||||||
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
<P><IMG SRC=graphics/line1.gif><P>
|
||||||
|
<TABLE BORDER=0>
|
||||||
|
<TR>
|
||||||
|
<TD> <A HREF=commands.html>Return to command index</A>
|
||||||
|
</TR>
|
||||||
|
</TABLE>
|
||||||
|
<P><I>Last updated:</I> March 7, 2020 at 1:06pm <P>
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
||||||
|
|
@ -45,10 +45,12 @@ view [get|bbox|llx lly urx ury]
|
||||||
center and scale the screen view of the layout window to fit the layout. <P>
|
center and scale the screen view of the layout window to fit the layout. <P>
|
||||||
|
|
||||||
<B>view bbox</B> returns the bounding box dimensions of the layout,
|
<B>view bbox</B> returns the bounding box dimensions of the layout,
|
||||||
in the coordinate system of the layout. <P>
|
in the coordinate system of the layout (according to the units
|
||||||
|
set by the "units" command). <P>
|
||||||
|
|
||||||
<B>view get</B> returns the coordinates of the screen limits in
|
<B>view get</B> returns the coordinates of the screen limits in
|
||||||
the coordinate system of the layout (internal database units). <P>
|
the coordinate system of the layout (according to the units set
|
||||||
|
by the "units" command). <P>
|
||||||
|
|
||||||
<B>view</B> <I>llx lly urx ury</I> sets the view so that the
|
<B>view</B> <I>llx lly urx ury</I> sets the view so that the
|
||||||
corners of the screen are at the indicated positions in the
|
corners of the screen are at the indicated positions in the
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ extern int drcArrayYankFunc(), drcArrayOverlapFunc();
|
||||||
static DRCCookie drcArrayCookie = {
|
static DRCCookie drcArrayCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ {0} }, { {0} },
|
{ {0} }, { {0} },
|
||||||
0, 0, 0,
|
0, DRC_EXCEPTION_NONE, 0, 0,
|
||||||
DRC_ARRAY_OVERLAP_TAG,
|
DRC_ARRAY_OVERLAP_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
|
||||||
160
drc/DRCbasic.c
160
drc/DRCbasic.c
|
|
@ -27,6 +27,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h> // for memcpy()
|
#include <string.h> // for memcpy()
|
||||||
#include <math.h> // for sqrt() for diagonal check
|
#include <math.h> // for sqrt() for diagonal check
|
||||||
|
|
||||||
|
#include "tcltk/tclmagic.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "tiles/tile.h"
|
#include "tiles/tile.h"
|
||||||
|
|
@ -36,7 +38,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "utils/signals.h"
|
#include "utils/signals.h"
|
||||||
#include "utils/maxrect.h"
|
#include "utils/maxrect.h"
|
||||||
#include "utils/malloc.h"
|
#include "utils/malloc.h"
|
||||||
|
#include "utils/undo.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
|
#include "cif/CIFint.h"
|
||||||
|
|
||||||
int dbDRCDebug = 0;
|
int dbDRCDebug = 0;
|
||||||
|
|
||||||
|
|
@ -48,7 +52,7 @@ int dbDRCDebug = 0;
|
||||||
static DRCCookie drcOverlapCookie = {
|
static DRCCookie drcOverlapCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ {0} }, { {0} },
|
{ {0} }, { {0} },
|
||||||
0, 0, 0,
|
0, DRC_EXCEPTION_NONE, 0, 0,
|
||||||
DRC_OVERLAP_TAG,
|
DRC_OVERLAP_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
@ -62,7 +66,33 @@ extern MaxRectsData *drcCanonicalMaxwidth();
|
||||||
/*
|
/*
|
||||||
*-----------------------------------------------------------------------
|
*-----------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* drcCifPointToSegment
|
* drcFoundOneFunc --
|
||||||
|
*
|
||||||
|
* Simple callback for a plane search on a mask-hint plane inside
|
||||||
|
* a DRC check area.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* Return 1 always, indicating that a tile has been found in the
|
||||||
|
* DRC search area, and the search can end.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
*-----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
drcFoundOneFunc(Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
|
ClientData cdata)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*-----------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* drcCifPointToSegment --
|
||||||
*
|
*
|
||||||
* Euclidean-distance point-to-segment distance (squared)
|
* Euclidean-distance point-to-segment distance (squared)
|
||||||
* calculation (borrowed from XCircuit)
|
* calculation (borrowed from XCircuit)
|
||||||
|
|
@ -140,8 +170,9 @@ drcCifPointToSegment(px, py, s1x, s1y, s2x, s2y)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
areaCheck(tile, arg)
|
areaCheck(tile, dinfo, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
struct drcClientData *arg;
|
struct drcClientData *arg;
|
||||||
{
|
{
|
||||||
Rect rect; /* Area where error is to be recorded. */
|
Rect rect; /* Area where error is to be recorded. */
|
||||||
|
|
@ -195,7 +226,7 @@ areaCheck(tile, arg)
|
||||||
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && !SplitDirection(tile) && !SplitSide(tile))
|
else if (IsSplit(tile) && !SplitDirection(tile) && !(dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
||||||
arg->dCD_constraint->r_ytop - sdist,
|
arg->dCD_constraint->r_ytop - sdist,
|
||||||
|
|
@ -210,7 +241,7 @@ areaCheck(tile, arg)
|
||||||
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && SplitDirection(tile) && SplitSide(tile))
|
else if (IsSplit(tile) && SplitDirection(tile) && (dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
||||||
arg->dCD_constraint->r_ytop - sdist,
|
arg->dCD_constraint->r_ytop - sdist,
|
||||||
|
|
@ -226,7 +257,7 @@ areaCheck(tile, arg)
|
||||||
+ sdist - rect.r_ytop) >= 0)
|
+ sdist - rect.r_ytop) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && SplitDirection(tile) && !SplitSide(tile))
|
else if (IsSplit(tile) && SplitDirection(tile) && !(dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
||||||
arg->dCD_constraint->r_ybot + sdist,
|
arg->dCD_constraint->r_ybot + sdist,
|
||||||
|
|
@ -242,7 +273,7 @@ areaCheck(tile, arg)
|
||||||
+ sdist - rect.r_ytop) >= 0)
|
+ sdist - rect.r_ytop) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && !SplitDirection(tile) && SplitSide(tile))
|
else if (IsSplit(tile) && !SplitDirection(tile) && (dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
||||||
arg->dCD_constraint->r_ybot + sdist,
|
arg->dCD_constraint->r_ybot + sdist,
|
||||||
|
|
@ -306,8 +337,9 @@ areaCheck(tile, arg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
areaNMReject(tile, arg)
|
areaNMReject(tile, dinfo, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
ClientData *arg;
|
ClientData *arg;
|
||||||
{
|
{
|
||||||
Tile *checktile = (Tile *)arg;
|
Tile *checktile = (Tile *)arg;
|
||||||
|
|
@ -337,8 +369,9 @@ areaNMReject(tile, arg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
areaNMCheck(tile, arg)
|
areaNMCheck(tile, dinfo, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
struct drcClientData *arg;
|
struct drcClientData *arg;
|
||||||
{
|
{
|
||||||
Rect rect; /* Area where error is to be recorded. */
|
Rect rect; /* Area where error is to be recorded. */
|
||||||
|
|
@ -375,7 +408,8 @@ areaNMCheck(tile, arg)
|
||||||
|
|
||||||
TTMaskSetOnlyType(&mask, TiGetLeftType(tile));
|
TTMaskSetOnlyType(&mask, TiGetLeftType(tile));
|
||||||
TTMaskSetType(&mask, TiGetRightType(tile));
|
TTMaskSetType(&mask, TiGetRightType(tile));
|
||||||
if (DBSrPaintNMArea((Tile *)tile, (Plane *)NULL, dinfo, arg->dCD_rlist,
|
if (DBSrPaintNMArea((Tile *)tile, (Plane *)NULL,
|
||||||
|
TiGetTypeExact(tile) | dinfo, arg->dCD_rlist,
|
||||||
&mask, areaNMReject, (ClientData)tile) == 0)
|
&mask, areaNMReject, (ClientData)tile) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -464,6 +498,13 @@ DRCBasicCheck (celldef, checkRect, clipRect, function, cdata)
|
||||||
DBResetTilePlane(celldef->cd_planes[planeNum], DRC_UNPROCESSED);
|
DBResetTilePlane(celldef->cd_planes[planeNum], DRC_UNPROCESSED);
|
||||||
(void) DBSrPaintArea ((Tile *) NULL, celldef->cd_planes[planeNum],
|
(void) DBSrPaintArea ((Tile *) NULL, celldef->cd_planes[planeNum],
|
||||||
checkRect, &DBAllTypeBits, drcTile, (ClientData) &arg);
|
checkRect, &DBAllTypeBits, drcTile, (ClientData) &arg);
|
||||||
|
|
||||||
|
#ifdef MAGIC_WRAPPER
|
||||||
|
/* Execute pending Tcl events, so the DRC process doesn't block. */
|
||||||
|
UndoEnable();
|
||||||
|
while (Tcl_DoOneEvent(TCL_DONT_WAIT));
|
||||||
|
UndoDisable();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
drcCifCheck(&arg);
|
drcCifCheck(&arg);
|
||||||
if (arg.dCD_rlist != NULL) freeMagic(arg.dCD_rlist);
|
if (arg.dCD_rlist != NULL) freeMagic(arg.dCD_rlist);
|
||||||
|
|
@ -492,8 +533,9 @@ DRCBasicCheck (celldef, checkRect, clipRect, function, cdata)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcTile (tile, arg)
|
drcTile (tile, dinfo, arg)
|
||||||
Tile *tile; /* Tile being examined */
|
Tile *tile; /* Tile being examined */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
struct drcClientData *arg;
|
struct drcClientData *arg;
|
||||||
{
|
{
|
||||||
DRCCookie *cptr; /* Current design rule on list */
|
DRCCookie *cptr; /* Current design rule on list */
|
||||||
|
|
@ -533,7 +575,7 @@ drcTile (tile, arg)
|
||||||
/* DRC searches only one direction on regular tiles, the split */
|
/* DRC searches only one direction on regular tiles, the split */
|
||||||
/* tiles are only processed for one of the two cases. */
|
/* tiles are only processed for one of the two cases. */
|
||||||
|
|
||||||
if (IsSplit(tile) && !SplitSide(tile))
|
if (IsSplit(tile) && !(dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
int deltax, deltay;
|
int deltax, deltay;
|
||||||
TileType tt, to;
|
TileType tt, to;
|
||||||
|
|
@ -555,7 +597,7 @@ drcTile (tile, arg)
|
||||||
{
|
{
|
||||||
int deltax, deltay, w, h;
|
int deltax, deltay, w, h;
|
||||||
double r;
|
double r;
|
||||||
TileType dinfo, dsplit;
|
TileType newdinfo, dsplit;
|
||||||
|
|
||||||
/* Work to be done: Handle triggering rules for non-Manhattan */
|
/* Work to be done: Handle triggering rules for non-Manhattan */
|
||||||
/* edges; especially important for the wide-spacing rule. */
|
/* edges; especially important for the wide-spacing rule. */
|
||||||
|
|
@ -605,7 +647,7 @@ drcTile (tile, arg)
|
||||||
|
|
||||||
if (SplitDirection(tile) == 0) deltay = -deltay;
|
if (SplitDirection(tile) == 0) deltay = -deltay;
|
||||||
|
|
||||||
dinfo = TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION);
|
newdinfo = TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION);
|
||||||
if (!(cptr->drcc_flags & DRC_REVERSE))
|
if (!(cptr->drcc_flags & DRC_REVERSE))
|
||||||
{
|
{
|
||||||
/* Forward case is behind the triangle */
|
/* Forward case is behind the triangle */
|
||||||
|
|
@ -613,19 +655,19 @@ drcTile (tile, arg)
|
||||||
deltay = -deltay;
|
deltay = -deltay;
|
||||||
|
|
||||||
/* Split side changes in the reverse case */
|
/* Split side changes in the reverse case */
|
||||||
dinfo |= TT_SIDE;
|
newdinfo |= TT_SIDE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The area to check is bounded between the diagonals of
|
/* The area to check is bounded between the diagonals of
|
||||||
* tile and errRect (which is the tile area, offset).
|
* tile and errRect (which is the tile area, offset).
|
||||||
* Pass errRect and dinfo to areaNMCheck using the
|
* Pass errRect and newdinfo to areaNMCheck using the
|
||||||
* ClientData structure arg->dCD_rlist and arg->dCD_entries,
|
* ClientData structure arg->dCD_rlist and arg->dCD_entries,
|
||||||
* which are not used by areaNMCheck.
|
* which are not used by areaNMCheck.
|
||||||
*/
|
*/
|
||||||
arg->dCD_rlist = (Rect *)mallocMagic(sizeof(Rect));
|
arg->dCD_rlist = (Rect *)mallocMagic(sizeof(Rect));
|
||||||
*(arg->dCD_rlist) = errRect;
|
*(arg->dCD_rlist) = errRect;
|
||||||
arg->dCD_entries = dinfo;
|
arg->dCD_entries = newdinfo;
|
||||||
if (dinfo & TT_SIDE)
|
if (newdinfo & TT_SIDE)
|
||||||
arg->dCD_entries &= ~TT_SIDE;
|
arg->dCD_entries &= ~TT_SIDE;
|
||||||
else
|
else
|
||||||
arg->dCD_entries |= TT_SIDE;
|
arg->dCD_entries |= TT_SIDE;
|
||||||
|
|
@ -637,7 +679,7 @@ drcTile (tile, arg)
|
||||||
errRect.r_ytop += deltay;
|
errRect.r_ytop += deltay;
|
||||||
|
|
||||||
DBSrPaintNMArea((Tile *) NULL,
|
DBSrPaintNMArea((Tile *) NULL,
|
||||||
arg->dCD_celldef->cd_planes[cptr->drcc_plane], dinfo,
|
arg->dCD_celldef->cd_planes[cptr->drcc_plane], newdinfo,
|
||||||
&errRect, &tmpMask, areaNMCheck, (ClientData) arg);
|
&errRect, &tmpMask, areaNMCheck, (ClientData) arg);
|
||||||
|
|
||||||
arg->dCD_entries = 0;
|
arg->dCD_entries = 0;
|
||||||
|
|
@ -722,6 +764,43 @@ drcTile (tile, arg)
|
||||||
for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL;
|
for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL;
|
||||||
cptr = cptr->drcc_next)
|
cptr = cptr->drcc_next)
|
||||||
{
|
{
|
||||||
|
/* Handle rule exceptions and exemptions */
|
||||||
|
if (cptr->drcc_exception != (char)DRC_EXCEPTION_NONE)
|
||||||
|
{
|
||||||
|
PropertyRecord *proprec;
|
||||||
|
bool propfound, isinside = FALSE;
|
||||||
|
char *name;
|
||||||
|
char idx = cptr->drcc_exception;
|
||||||
|
if (idx < 0) idx = -idx - 1;
|
||||||
|
name = DRCCurStyle->DRCExceptionList[idx];
|
||||||
|
|
||||||
|
/* Is there any exception area defined? */
|
||||||
|
proprec = DBPropGet(arg->dCD_celldef, name, &propfound);
|
||||||
|
|
||||||
|
/* If an exception area exists, is the error edge inside? */
|
||||||
|
if (propfound)
|
||||||
|
{
|
||||||
|
Rect redge;
|
||||||
|
|
||||||
|
redge.r_xbot = redge.r_xtop = edgeX;
|
||||||
|
redge.r_ybot = edgeBot;
|
||||||
|
redge.r_ytop = edgeTop;
|
||||||
|
|
||||||
|
if (DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
||||||
|
proprec->prop_value.prop_plane,
|
||||||
|
&redge, &CIFSolidBits, drcFoundOneFunc,
|
||||||
|
(ClientData)NULL) == 1)
|
||||||
|
isinside = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exemption rules are ignored if the edge is inside
|
||||||
|
* an exception area. Exception rules are ignored if
|
||||||
|
* the edge is outside an exception area.
|
||||||
|
*/
|
||||||
|
if (!isinside && (cptr->drcc_exception >= 0)) continue;
|
||||||
|
if (isinside && (cptr->drcc_exception < 0)) continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */
|
/* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */
|
||||||
/* the code above for non-Manhattan shapes and do not */
|
/* the code above for non-Manhattan shapes and do not */
|
||||||
/* need to be processed again. */
|
/* need to be processed again. */
|
||||||
|
|
@ -1131,6 +1210,49 @@ drcTile (tile, arg)
|
||||||
for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL;
|
for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL;
|
||||||
cptr = cptr->drcc_next)
|
cptr = cptr->drcc_next)
|
||||||
{
|
{
|
||||||
|
/* Handle rule exceptions and exemptions */
|
||||||
|
if (cptr->drcc_exception != (char)DRC_EXCEPTION_NONE)
|
||||||
|
{
|
||||||
|
PropertyRecord *proprec;
|
||||||
|
bool propfound, isinside = FALSE;
|
||||||
|
char *name;
|
||||||
|
char idx = cptr->drcc_exception;
|
||||||
|
if (idx < 0) idx = -idx - 1;
|
||||||
|
name = DRCCurStyle->DRCExceptionList[idx];
|
||||||
|
|
||||||
|
/* Is there any exception area defined? */
|
||||||
|
proprec = DBPropGet(arg->dCD_celldef, name, &propfound);
|
||||||
|
|
||||||
|
/* Quickest case: Rule is an exception but there are no
|
||||||
|
* exception areas.
|
||||||
|
*/
|
||||||
|
if ((!propfound) && (cptr->drcc_exception >= 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* If an exception area exists, is the error edge inside? */
|
||||||
|
if (propfound)
|
||||||
|
{
|
||||||
|
Rect redge;
|
||||||
|
|
||||||
|
redge.r_ybot = redge.r_ytop = edgeY;
|
||||||
|
redge.r_xbot = edgeLeft;
|
||||||
|
redge.r_xtop = edgeRight;
|
||||||
|
|
||||||
|
if (DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
||||||
|
proprec->prop_value.prop_plane,
|
||||||
|
&redge, &CIFSolidBits, drcFoundOneFunc,
|
||||||
|
(ClientData)NULL) == 1)
|
||||||
|
isinside = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exemption rules are ignored if the edge is inside
|
||||||
|
* an exception area. Exception rules are ignored if
|
||||||
|
* the edge is outside an exception area.
|
||||||
|
*/
|
||||||
|
if (isinside && (cptr->drcc_exception < 0)) continue;
|
||||||
|
if (!isinside && (cptr->drcc_exception >= 0)) continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */
|
/* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */
|
||||||
/* the code above for non-Manhattan shapes and do not */
|
/* the code above for non-Manhattan shapes and do not */
|
||||||
/* need to be processed again. */
|
/* need to be processed again. */
|
||||||
|
|
|
||||||
18
drc/DRCcif.c
18
drc/DRCcif.c
|
|
@ -603,8 +603,9 @@ drcCifCheck(arg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcCifTile (tile, arg)
|
drcCifTile (tile, dinfo, arg)
|
||||||
Tile *tile; /* Tile being examined */
|
Tile *tile; /* Tile being examined */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
struct drcClientData *arg;
|
struct drcClientData *arg;
|
||||||
{
|
{
|
||||||
DRCCookie *cptr; /* Current design rule on list */
|
DRCCookie *cptr; /* Current design rule on list */
|
||||||
|
|
@ -628,7 +629,7 @@ drcCifTile (tile, arg)
|
||||||
/* check. */
|
/* check. */
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
if (SplitSide(tile))
|
if (dinfo & TT_SIDE)
|
||||||
goto tbcheck;
|
goto tbcheck;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -826,7 +827,7 @@ tbcheck:
|
||||||
/* bottom check. */
|
/* bottom check. */
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
if (SplitSide(tile) == SplitDirection(tile))
|
if (((dinfo & TT_SIDE) ? 1 : 0) == SplitDirection(tile))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1031,8 +1032,9 @@ tbcheck:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
areaCifCheck(tile, arg)
|
areaCifCheck(tile, dinfo, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
struct drcClientData *arg;
|
struct drcClientData *arg;
|
||||||
{
|
{
|
||||||
Rect rect; /* Area where error is to be recorded. */
|
Rect rect; /* Area where error is to be recorded. */
|
||||||
|
|
@ -1085,7 +1087,7 @@ areaCifCheck(tile, arg)
|
||||||
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && !SplitDirection(tile) && !SplitSide(tile))
|
else if (IsSplit(tile) && !SplitDirection(tile) && !(dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
||||||
arg->dCD_constraint->r_ytop - sdist,
|
arg->dCD_constraint->r_ytop - sdist,
|
||||||
|
|
@ -1100,7 +1102,7 @@ areaCifCheck(tile, arg)
|
||||||
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && SplitDirection(tile) && SplitSide(tile))
|
else if (IsSplit(tile) && SplitDirection(tile) && (dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
||||||
arg->dCD_constraint->r_ytop - sdist,
|
arg->dCD_constraint->r_ytop - sdist,
|
||||||
|
|
@ -1116,7 +1118,7 @@ areaCifCheck(tile, arg)
|
||||||
+ sdist - cifrect.r_ytop) >= 0)
|
+ sdist - cifrect.r_ytop) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && SplitDirection(tile) && !SplitSide(tile))
|
else if (IsSplit(tile) && SplitDirection(tile) && !(dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
||||||
arg->dCD_constraint->r_ybot + sdist,
|
arg->dCD_constraint->r_ybot + sdist,
|
||||||
|
|
@ -1132,7 +1134,7 @@ areaCifCheck(tile, arg)
|
||||||
+ sdist - cifrect.r_ytop) >= 0)
|
+ sdist - cifrect.r_ytop) >= 0)
|
||||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||||
return 0;
|
return 0;
|
||||||
else if (IsSplit(tile) && !SplitDirection(tile) && SplitSide(tile))
|
else if (IsSplit(tile) && !SplitDirection(tile) && (dinfo & TT_SIDE))
|
||||||
{
|
{
|
||||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
||||||
arg->dCD_constraint->r_ybot + sdist,
|
arg->dCD_constraint->r_ybot + sdist,
|
||||||
|
|
|
||||||
|
|
@ -639,8 +639,9 @@ checkDone:
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
int
|
int
|
||||||
drcCheckTile(tile, arg)
|
drcCheckTile(tile, dinfo, arg)
|
||||||
Tile * tile; /* tile in DRC_CHECK plane */
|
Tile *tile; /* Tile in DRC_CHECK plane */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
ClientData arg; /* Not used. */
|
ClientData arg; /* Not used. */
|
||||||
{
|
{
|
||||||
Rect square; /* Square area of the checkerboard
|
Rect square; /* Square area of the checkerboard
|
||||||
|
|
@ -767,13 +768,15 @@ drcCheckTile(tile, arg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcXorFunc(tile)
|
drcXorFunc(tile, dinfo, clientdata)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
|
ClientData clientdata;
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
||||||
TiToRect(tile, &area);
|
TiToRect(tile, &area);
|
||||||
DBPaintPlane(drcDisplayPlane, &area, drcXorTable, (PaintUndoInfo *) NULL);
|
DBNMPaintPlane(drcDisplayPlane, dinfo, &area, drcXorTable, (PaintUndoInfo *) NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -782,14 +785,15 @@ drcXorFunc(tile)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcPutBackFunc(tile, cellDef)
|
drcPutBackFunc(tile, dinfo, cellDef)
|
||||||
Tile *tile; /* Error tile, from drcTempPlane. */
|
Tile *tile; /* Error tile, from drcTempPlane. */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
CellDef *cellDef; /* Celldef in which to paint error. */
|
CellDef *cellDef; /* Celldef in which to paint error. */
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
||||||
TiToRect(tile, &area);
|
TiToRect(tile, &area);
|
||||||
DBPaintPlane(cellDef->cd_planes[PL_DRC_ERROR], &area,
|
DBNMPaintPlane(cellDef->cd_planes[PL_DRC_ERROR], dinfo, &area,
|
||||||
DBStdPaintTbl(TiGetType(tile), PL_DRC_ERROR),
|
DBStdPaintTbl(TiGetType(tile), PL_DRC_ERROR),
|
||||||
(PaintUndoInfo *) NULL);
|
(PaintUndoInfo *) NULL);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -816,8 +820,9 @@ drcPutBackFunc(tile, cellDef)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcIncludeArea(tile, rect)
|
drcIncludeArea(tile, dinfo, rect)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
Rect *rect; /* Rectangle in which to record total area. */
|
Rect *rect; /* Rectangle in which to record total area. */
|
||||||
{
|
{
|
||||||
Rect dum;
|
Rect dum;
|
||||||
|
|
|
||||||
|
|
@ -468,8 +468,9 @@ drcCheckRectSize(starttile, arg, cptr)
|
||||||
|
|
||||||
int
|
int
|
||||||
MaxRectsExclude(
|
MaxRectsExclude(
|
||||||
Tile *tile,
|
Tile *tile, /* (unused) */
|
||||||
ClientData clientdata)
|
TileType dinfo, /* (unused) */
|
||||||
|
ClientData clientdata) /* (unused) */
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -184,9 +184,9 @@ drcSubstitute (cptr)
|
||||||
DRCCookie * cptr; /* Design rule violated */
|
DRCCookie * cptr; /* Design rule violated */
|
||||||
{
|
{
|
||||||
static char *why_out = NULL;
|
static char *why_out = NULL;
|
||||||
char *whyptr, *sptr, *wptr;
|
char *whyptr, *sptr, *wptr, *vptr;
|
||||||
int subscnt = 0, whylen;
|
int subscnt = 0, whylen, saveunits;
|
||||||
float oscale, value;
|
float value;
|
||||||
extern float CIFGetOutputScale();
|
extern float CIFGetOutputScale();
|
||||||
|
|
||||||
whyptr = DRCCurStyle->DRCWhyList[cptr->drcc_tag];
|
whyptr = DRCCurStyle->DRCWhyList[cptr->drcc_tag];
|
||||||
|
|
@ -203,10 +203,14 @@ drcSubstitute (cptr)
|
||||||
why_out = (char *)mallocMagic(whylen * sizeof(char));
|
why_out = (char *)mallocMagic(whylen * sizeof(char));
|
||||||
strcpy(why_out, whyptr);
|
strcpy(why_out, whyptr);
|
||||||
|
|
||||||
if (cptr->drcc_flags & DRC_CIFRULE)
|
/* For backwards compatibility: If the units are set to "default",
|
||||||
oscale = CIFGetScale(100); /* 100 = microns to centimicrons */
|
* then print the DRC value in microns, with units, which is how
|
||||||
else
|
* the output was previously presented.
|
||||||
oscale = CIFGetOutputScale(1000); /* 1000 for conversion to um */
|
*/
|
||||||
|
saveunits = DBWUnits;
|
||||||
|
if (saveunits == DBW_UNITS_DEFAULT)
|
||||||
|
DBWUnits = DBW_UNITS_MICRONS | DBW_UNITS_PRINT_FLAG;
|
||||||
|
|
||||||
wptr = why_out;
|
wptr = why_out;
|
||||||
|
|
||||||
while ((sptr = strchr(whyptr, '%')) != NULL)
|
while ((sptr = strchr(whyptr, '%')) != NULL)
|
||||||
|
|
@ -218,21 +222,29 @@ drcSubstitute (cptr)
|
||||||
switch (*(sptr + 1))
|
switch (*(sptr + 1))
|
||||||
{
|
{
|
||||||
case 'd':
|
case 'd':
|
||||||
/* Replace with "dist" value in microns */
|
if (cptr->drcc_flags & DRC_CIFRULE)
|
||||||
value = (float)cptr->drcc_dist * oscale;
|
vptr = DBWPrintCIFValue(cptr->drcc_dist, (MagWindow *)NULL, TRUE);
|
||||||
snprintf(wptr, 20, "%01.3gum", value);
|
else
|
||||||
|
vptr = DBWPrintValue(cptr->drcc_dist, (MagWindow *)NULL, TRUE);
|
||||||
|
snprintf(wptr, 20, "%s", vptr);
|
||||||
wptr += strlen(wptr);
|
wptr += strlen(wptr);
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
/* Replace with "cdist" value in microns */
|
/* Replace with "cdist" value in microns */
|
||||||
value = (float)cptr->drcc_cdist * oscale;
|
if (cptr->drcc_flags & DRC_CIFRULE)
|
||||||
snprintf(wptr, 20, "%01.3gum", value);
|
vptr = DBWPrintCIFValue(cptr->drcc_cdist, (MagWindow *)NULL, TRUE);
|
||||||
|
else
|
||||||
|
vptr = DBWPrintValue(cptr->drcc_cdist, (MagWindow *)NULL, TRUE);
|
||||||
|
snprintf(wptr, 20, "%s", vptr);
|
||||||
wptr += strlen(wptr);
|
wptr += strlen(wptr);
|
||||||
break;
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
/* Replace with "cdist" value in microns squared */
|
/* Replace with "cdist" value in microns squared */
|
||||||
value = (float)cptr->drcc_cdist * oscale * oscale;
|
if (cptr->drcc_flags & DRC_CIFRULE)
|
||||||
snprintf(wptr, 20, "%01.4gum^2", value);
|
vptr = DBWPrintCIFSqValue(cptr->drcc_cdist, (MagWindow *)NULL);
|
||||||
|
else
|
||||||
|
vptr = DBWPrintSqValue(cptr->drcc_cdist, (MagWindow *)NULL);
|
||||||
|
snprintf(wptr, 20, "%s", vptr);
|
||||||
wptr += strlen(wptr);
|
wptr += strlen(wptr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -245,6 +257,7 @@ drcSubstitute (cptr)
|
||||||
/* copy remainder of string (including trailing null) */
|
/* copy remainder of string (including trailing null) */
|
||||||
strncpy(wptr, whyptr, strlen(whyptr) + 1);
|
strncpy(wptr, whyptr, strlen(whyptr) + 1);
|
||||||
|
|
||||||
|
DBWUnits = saveunits;
|
||||||
return why_out;
|
return why_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -425,6 +438,8 @@ drcListallError (celldef, rect, cptr, scx)
|
||||||
}
|
}
|
||||||
if (drcsave == DRCErrorCount)
|
if (drcsave == DRCErrorCount)
|
||||||
{
|
{
|
||||||
|
char *rllx, *rlly, *rurx, *rury;
|
||||||
|
|
||||||
DRCErrorCount += 1;
|
DRCErrorCount += 1;
|
||||||
h = HashFind(&DRCErrorTable, drcSubstitute(cptr));
|
h = HashFind(&DRCErrorTable, drcSubstitute(cptr));
|
||||||
lobj = (Tcl_Obj *) HashGetValue(h);
|
lobj = (Tcl_Obj *) HashGetValue(h);
|
||||||
|
|
@ -433,10 +448,15 @@ drcListallError (celldef, rect, cptr, scx)
|
||||||
|
|
||||||
pobj = Tcl_NewListObj(0, NULL);
|
pobj = Tcl_NewListObj(0, NULL);
|
||||||
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_xbot));
|
rllx = DBWPrintValue(r.r_xbot, (MagWindow *)NULL, TRUE);
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_ybot));
|
rlly = DBWPrintValue(r.r_ybot, (MagWindow *)NULL, FALSE);
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_xtop));
|
rurx = DBWPrintValue(r.r_xtop, (MagWindow *)NULL, TRUE);
|
||||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_ytop));
|
rury = DBWPrintValue(r.r_ytop, (MagWindow *)NULL, FALSE);
|
||||||
|
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(rllx, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(rlly, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(rurx, -1));
|
||||||
|
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(rury, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
||||||
|
|
||||||
HashSetValue(h, lobj);
|
HashSetValue(h, lobj);
|
||||||
|
|
@ -957,8 +977,9 @@ drcCountFunc(scx, dupTable)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drcCountFunc2(tile, countptr)
|
drcCountFunc2(tile, dinfo, countptr)
|
||||||
Tile *tile; /* Tile found in error plane. */
|
Tile *tile; /* Tile found in error plane. */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
int *countptr; /* Address of count word. */
|
int *countptr; /* Address of count word. */
|
||||||
{
|
{
|
||||||
if (TiGetType(tile) != (TileType) TT_SPACE) (*countptr)++;
|
if (TiGetType(tile) != (TileType) TT_SPACE) (*countptr)++;
|
||||||
|
|
@ -1106,8 +1127,9 @@ drcFindFunc(scx, finddata)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drcFindFunc2(tile, finddata)
|
drcFindFunc2(tile, dinfo, finddata)
|
||||||
Tile *tile; /* Tile in error plane. */
|
Tile *tile; /* Tile in error plane. */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
Sindx *finddata; /* Information about error to find */
|
Sindx *finddata; /* Information about error to find */
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ static ClientData drcSubClientData; /* To be passed to error function. */
|
||||||
static DRCCookie drcSubcellCookie = {
|
static DRCCookie drcSubcellCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ {0} }, { {0} },
|
{ {0} }, { {0} },
|
||||||
0, 0, 0,
|
0, DRC_EXCEPTION_NONE, 0, 0,
|
||||||
DRC_SUBCELL_OVERLAP_TAG,
|
DRC_SUBCELL_OVERLAP_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
@ -65,7 +65,7 @@ static DRCCookie drcSubcellCookie = {
|
||||||
static DRCCookie drcInSubCookie = {
|
static DRCCookie drcInSubCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ {0} }, { {0} },
|
{ {0} }, { {0} },
|
||||||
0, 0, 0,
|
0, DRC_EXCEPTION_NONE, 0, 0,
|
||||||
DRC_IN_SUBCELL_TAG,
|
DRC_IN_SUBCELL_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
@ -79,7 +79,7 @@ static DRCCookie drcInSubCookie = {
|
||||||
static DRCCookie drcOffGridCookie = {
|
static DRCCookie drcOffGridCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ {0} }, { {0} },
|
{ {0} }, { {0} },
|
||||||
0, 0, 0,
|
0, DRC_EXCEPTION_NONE, 0, 0,
|
||||||
DRC_OFFGRID_TAG,
|
DRC_OFFGRID_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
@ -158,8 +158,9 @@ drcFindOtherCells(use, dlu)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcSubCopyErrors(tile, cxp)
|
drcSubCopyErrors(tile, dinfo, cxp)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
TreeContext *cxp;
|
TreeContext *cxp;
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
|
|
@ -317,7 +318,9 @@ drcSubcellFunc(subUse, dsa)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcAlwaysOne()
|
drcAlwaysOne(Tile *tile,
|
||||||
|
TileType dinfo,
|
||||||
|
ClientData clientdata)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -419,7 +422,6 @@ DRCFindInteractions(def, area, radius, interaction)
|
||||||
CellUse *use;
|
CellUse *use;
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
Rect searchArea, intArea;
|
Rect searchArea, intArea;
|
||||||
int flags;
|
|
||||||
struct drcSubcellArg dsa;
|
struct drcSubcellArg dsa;
|
||||||
struct drcLinkedUse *curDLU;
|
struct drcLinkedUse *curDLU;
|
||||||
|
|
||||||
|
|
@ -492,8 +494,6 @@ DRCFindInteractions(def, area, radius, interaction)
|
||||||
/* If errors are being propagated up from child to parent, */
|
/* If errors are being propagated up from child to parent, */
|
||||||
/* then the interaction area is always valid. */
|
/* then the interaction area is always valid. */
|
||||||
|
|
||||||
if (!(flags & PROPAGATE_FLAG))
|
|
||||||
{
|
|
||||||
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
|
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
|
||||||
{
|
{
|
||||||
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[i],
|
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[i],
|
||||||
|
|
@ -509,7 +509,6 @@ DRCFindInteractions(def, area, radius, interaction)
|
||||||
scx.scx_area = intArea;
|
scx.scx_area = intArea;
|
||||||
if (DBTreeSrCells(&scx, 0, drcSubCheckPaint, (ClientData) &use) == 0)
|
if (DBTreeSrCells(&scx, 0, drcSubCheckPaint, (ClientData) &use) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/* OK, no more excuses, there's really an interaction area here. */
|
/* OK, no more excuses, there's really an interaction area here. */
|
||||||
|
|
||||||
|
|
@ -540,8 +539,9 @@ DRCFindInteractions(def, area, radius, interaction)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcExactOverlapCheck(tile, arg)
|
drcExactOverlapCheck(tile, dinfo, arg)
|
||||||
Tile *tile; /* Tile to check. */
|
Tile *tile; /* Tile to check. */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
struct drcClientData *arg; /* How to detect and process errors. */
|
struct drcClientData *arg; /* How to detect and process errors. */
|
||||||
{
|
{
|
||||||
Rect rect;
|
Rect rect;
|
||||||
|
|
@ -579,8 +579,9 @@ drcExactOverlapCheck(tile, arg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
drcExactOverlapTile(tile, cxp)
|
drcExactOverlapTile(tile, dinfo, cxp)
|
||||||
Tile *tile; /* Tile that must overlap exactly. */
|
Tile *tile; /* Tile that must overlap exactly. */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
TreeContext *cxp; /* Tells how to translate out of subcell.
|
TreeContext *cxp; /* Tells how to translate out of subcell.
|
||||||
* The client data must be a drcClientData
|
* The client data must be a drcClientData
|
||||||
* record, and the caller must have filled
|
* record, and the caller must have filled
|
||||||
|
|
@ -825,6 +826,7 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
|
||||||
*/
|
*/
|
||||||
subArea = *erasebox;
|
subArea = *erasebox;
|
||||||
GeoClip(&subArea, &cliparea);
|
GeoClip(&subArea, &cliparea);
|
||||||
|
if (GEO_RECTNULL(&subArea)) continue;
|
||||||
GEO_EXPAND(&subArea, DRCTechHalo, &intArea);
|
GEO_EXPAND(&subArea, DRCTechHalo, &intArea);
|
||||||
|
|
||||||
errorSaveType = DRCErrorType;
|
errorSaveType = DRCErrorType;
|
||||||
|
|
|
||||||
198
drc/DRCtech.c
198
drc/DRCtech.c
|
|
@ -72,6 +72,12 @@ static int drcRulesOptimized = 0;
|
||||||
|
|
||||||
static int DRCtag = 0;
|
static int DRCtag = 0;
|
||||||
|
|
||||||
|
/* Keep track of what rule exemption or exception is in effect
|
||||||
|
* while reading the DRC tech file section.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static char drcCurException = (char)DRC_EXCEPTION_NONE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forward declarations.
|
* Forward declarations.
|
||||||
*/
|
*/
|
||||||
|
|
@ -79,6 +85,7 @@ int drcWidth(), drcSpacing(), drcEdge(), drcNoOverlap();
|
||||||
int drcExactOverlap(), drcExtend();
|
int drcExactOverlap(), drcExtend();
|
||||||
int drcSurround(), drcRectOnly(), drcOverhang();
|
int drcSurround(), drcRectOnly(), drcOverhang();
|
||||||
int drcStepSize(), drcOption(), drcOffGrid();
|
int drcStepSize(), drcOption(), drcOffGrid();
|
||||||
|
int drcException(), drcExemption();
|
||||||
int drcMaxwidth(), drcArea(), drcRectangle(), drcAngles();
|
int drcMaxwidth(), drcArea(), drcRectangle(), drcAngles();
|
||||||
int drcCifSetStyle(), drcCifWidth(), drcCifSpacing();
|
int drcCifSetStyle(), drcCifWidth(), drcCifSpacing();
|
||||||
int drcCifMaxwidth(), drcCifArea();
|
int drcCifMaxwidth(), drcCifArea();
|
||||||
|
|
@ -301,6 +308,12 @@ drcTechFreeStyle()
|
||||||
/* Clear the Why string list */
|
/* Clear the Why string list */
|
||||||
freeMagic(DRCCurStyle->DRCWhyList);
|
freeMagic(DRCCurStyle->DRCWhyList);
|
||||||
|
|
||||||
|
/* Clear the exception list */
|
||||||
|
for (i = 0; i < DRCCurStyle->DRCExceptionSize; i++)
|
||||||
|
freeMagic(DRCCurStyle->DRCExceptionList[i]);
|
||||||
|
if (DRCCurStyle->DRCExceptionList != (char **)NULL)
|
||||||
|
freeMagic(DRCCurStyle->DRCExceptionList);
|
||||||
|
|
||||||
freeMagic(DRCCurStyle);
|
freeMagic(DRCCurStyle);
|
||||||
DRCCurStyle = NULL;
|
DRCCurStyle = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -384,6 +397,60 @@ drcWhyCreate(whystring)
|
||||||
return DRCCurStyle->DRCWhySize;
|
return DRCCurStyle->DRCWhySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* drcExceptionCreate --
|
||||||
|
*
|
||||||
|
* Create an entry for a DRC rule exception/exemption type, if it does
|
||||||
|
* not already exist.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* The index of the exception (which is a signed character).
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Adds to the DRCExceptionList if "name" has not been used before.
|
||||||
|
* Calls StrDup() and increments DRCExceptionSize.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
char
|
||||||
|
drcExceptionCreate(name)
|
||||||
|
char *name;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char **newlist;
|
||||||
|
|
||||||
|
/* NOTE: DRCExceptionList has "MASKHINTS_" prepended to the names */
|
||||||
|
for (i = 0; i < DRCCurStyle->DRCExceptionSize; i++)
|
||||||
|
if (!strcmp(name, DRCCurStyle->DRCExceptionList[i] + 10))
|
||||||
|
return (char)i;
|
||||||
|
|
||||||
|
if (i > 127)
|
||||||
|
{
|
||||||
|
/* I would be shocked if this code ever got executed. */
|
||||||
|
TxError("Error: Too many rule exceptions! Limit is 127.\n");
|
||||||
|
return (char)DRC_EXCEPTION_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a new list that is one entry longer than the old list.
|
||||||
|
* This is not elegant but there will never be more than a handful
|
||||||
|
* of exceptions in a rule deck.
|
||||||
|
*/
|
||||||
|
newlist = (char **)mallocMagic((i + 1) * sizeof(char *));
|
||||||
|
for (i = 0; i < DRCCurStyle->DRCExceptionSize; i++)
|
||||||
|
newlist[i] = DRCCurStyle->DRCExceptionList[i];
|
||||||
|
|
||||||
|
/* The rule deck does not have the "MASKHINTS_" prefix on the name */
|
||||||
|
newlist[i] = (char *)mallocMagic(strlen(name) + 11);
|
||||||
|
sprintf(newlist[i], "MASKHINTS_%s", name);
|
||||||
|
DRCCurStyle->DRCExceptionSize++;
|
||||||
|
if (DRCCurStyle->DRCExceptionList != (char **)NULL)
|
||||||
|
freeMagic(DRCCurStyle->DRCExceptionList);
|
||||||
|
DRCCurStyle->DRCExceptionList = newlist;
|
||||||
|
return (char)i;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -571,6 +638,8 @@ DRCTechStyleInit()
|
||||||
DRCCurStyle->DRCStepSize = 0;
|
DRCCurStyle->DRCStepSize = 0;
|
||||||
DRCCurStyle->DRCFlags = (char)0;
|
DRCCurStyle->DRCFlags = (char)0;
|
||||||
DRCCurStyle->DRCWhySize = 0;
|
DRCCurStyle->DRCWhySize = 0;
|
||||||
|
DRCCurStyle->DRCExceptionList = (char **)NULL;
|
||||||
|
DRCCurStyle->DRCExceptionSize = 0;
|
||||||
|
|
||||||
HashInit(&DRCWhyErrorTable, 16, HT_STRINGKEYS);
|
HashInit(&DRCWhyErrorTable, 16, HT_STRINGKEYS);
|
||||||
|
|
||||||
|
|
@ -663,6 +732,7 @@ DRCTechStyleInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
drcCifInit();
|
drcCifInit();
|
||||||
|
drcCurException = (char)DRC_EXCEPTION_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -955,6 +1025,7 @@ drcCifAssign(cookie, dist, next, mask, corner, tag, cdist, flags, planeto, plane
|
||||||
(cookie)->drcc_plane = planeto;
|
(cookie)->drcc_plane = planeto;
|
||||||
(cookie)->drcc_mod = 0;
|
(cookie)->drcc_mod = 0;
|
||||||
(cookie)->drcc_cmod = 0;
|
(cookie)->drcc_cmod = 0;
|
||||||
|
(cookie)->drcc_exception = drcCurException;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is like drcCifAssign, but checks for bad plane numbers in planeto and
|
// This is like drcCifAssign, but checks for bad plane numbers in planeto and
|
||||||
|
|
@ -1031,50 +1102,37 @@ DRCTechAddRule(sectionName, argc, argv)
|
||||||
int (*rk_proc)(); /* Procedure implementing this keyword */
|
int (*rk_proc)(); /* Procedure implementing this keyword */
|
||||||
const char *rk_err; /* Error message */
|
const char *rk_err; /* Error message */
|
||||||
} ruleKeys[] = {
|
} ruleKeys[] = {
|
||||||
{"angles", 4, 4, drcAngles,
|
{"angles", 4, 4, drcAngles, "layers 45|90 why"},
|
||||||
"layers 45|90 why"},
|
|
||||||
{"edge", 8, 10, drcEdge,
|
{"edge", 8, 10, drcEdge,
|
||||||
"layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"},
|
"layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"},
|
||||||
{"edge4way", 8, 10, drcEdge,
|
{"edge4way", 8, 10, drcEdge,
|
||||||
"layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"},
|
"layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"},
|
||||||
{"exact_overlap", 2, 2, drcExactOverlap,
|
{"exact_overlap", 2, 2, drcExactOverlap, "layers"},
|
||||||
"layers"},
|
{"exception", 2, 2, drcException, "name"},
|
||||||
|
{"exemption", 2, 2, drcExemption, "name"},
|
||||||
{"extend", 5, 6, drcExtend,
|
{"extend", 5, 6, drcExtend,
|
||||||
"layers1 layers2 distance [option] why"},
|
"layers1 layers2 distance [option] why"},
|
||||||
{"no_overlap", 3, 3, drcNoOverlap,
|
{"no_overlap", 3, 3, drcNoOverlap, "layers1 layers2"},
|
||||||
"layers1 layers2"},
|
{"option", 2, 2, drcOption, "option_name option_value"},
|
||||||
{"option", 2, 2, drcOption,
|
{"overhang", 5, 5, drcOverhang, "layers1 layers2 distance why"},
|
||||||
"option_name option_value"},
|
{"rect_only", 3, 3, drcRectOnly, "layers why"},
|
||||||
{"overhang", 5, 5, drcOverhang,
|
|
||||||
"layers1 layers2 distance why"},
|
|
||||||
{"rect_only", 3, 3, drcRectOnly,
|
|
||||||
"layers why"},
|
|
||||||
{"spacing", 6, 7, drcSpacing,
|
{"spacing", 6, 7, drcSpacing,
|
||||||
"layers1 layers2 separation [layers3] adjacency why"},
|
"layers1 layers2 separation [layers3] adjacency why"},
|
||||||
{"stepsize", 2, 2, drcStepSize,
|
{"stepsize", 2, 2, drcStepSize, "step_size"},
|
||||||
"step_size"},
|
|
||||||
{"surround", 6, 7, drcSurround,
|
{"surround", 6, 7, drcSurround,
|
||||||
"layers1 layers2 distance presence why"},
|
"layers1 layers2 distance presence why"},
|
||||||
{"width", 4, 5, drcWidth,
|
{"width", 4, 5, drcWidth, "layers width why"},
|
||||||
"layers width why"},
|
|
||||||
{"widespacing", 7, 8, drcSpacing,
|
{"widespacing", 7, 8, drcSpacing,
|
||||||
"layers1 width layers2 separation adjacency why"},
|
"layers1 width layers2 separation adjacency why"},
|
||||||
{"area", 5, 5, drcArea,
|
{"area", 5, 5, drcArea, "layers area horizon why"},
|
||||||
"layers area horizon why"},
|
{"off_grid", 4, 4, drcOffGrid, "layers pitch why"},
|
||||||
{"off_grid", 4, 4, drcOffGrid,
|
{"maxwidth", 4, 6, drcMaxwidth, "layers maxwidth bends why"},
|
||||||
"layers pitch why"},
|
{"cifstyle", 2, 2, drcCifSetStyle, "cif_style"},
|
||||||
{"maxwidth", 4, 6, drcMaxwidth,
|
{"cifwidth", 4, 4, drcCifWidth, "layers width why"},
|
||||||
"layers maxwidth bends why"},
|
|
||||||
{"cifstyle", 2, 2, drcCifSetStyle,
|
|
||||||
"cif_style"},
|
|
||||||
{"cifwidth", 4, 4, drcCifWidth,
|
|
||||||
"layers width why"},
|
|
||||||
{"cifspacing", 6, 6, drcCifSpacing,
|
{"cifspacing", 6, 6, drcCifSpacing,
|
||||||
"layers1 layers2 separation adjacency why"},
|
"layers1 layers2 separation adjacency why"},
|
||||||
{"cifarea", 5, 5, drcCifArea,
|
{"cifarea", 5, 5, drcCifArea, "layers area horizon why"},
|
||||||
"layers area horizon why"},
|
{"cifmaxwidth", 5, 5, drcCifMaxwidth, "layers maxwidth bends why"},
|
||||||
{"cifmaxwidth", 5, 5, drcCifMaxwidth,
|
|
||||||
"layers maxwidth bends why"},
|
|
||||||
{"rectangle", 5, 5, drcRectangle,
|
{"rectangle", 5, 5, drcRectangle,
|
||||||
"layers maxwidth [even|odd|any] why"},
|
"layers maxwidth [even|odd|any] why"},
|
||||||
{0}
|
{0}
|
||||||
|
|
@ -1695,7 +1753,7 @@ drcMaxwidth(argc, argv)
|
||||||
if (PlaneMaskHasPlane(pmask2, plane2))
|
if (PlaneMaskHasPlane(pmask2, plane2))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (plane2 == plane)
|
if (PlaneMaskHasPlane(pmask, plane2))
|
||||||
TechError("Warning: Exclude types for \"maxwidth\" are on the "
|
TechError("Warning: Exclude types for \"maxwidth\" are on the "
|
||||||
"same plane and so cannot be checked.\n");
|
"same plane and so cannot be checked.\n");
|
||||||
}
|
}
|
||||||
|
|
@ -3634,6 +3692,83 @@ drcRectangle(argc, argv)
|
||||||
return maxwidth;
|
return maxwidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* drcException, drcExemption --
|
||||||
|
*
|
||||||
|
* Process a DRC exception declaration
|
||||||
|
* This is of the form:
|
||||||
|
*
|
||||||
|
* exception exception_name|none
|
||||||
|
* or
|
||||||
|
* exemption exemption_name|none
|
||||||
|
*
|
||||||
|
* e.g,
|
||||||
|
*
|
||||||
|
* exception SRAM
|
||||||
|
* exemption SRAM
|
||||||
|
*
|
||||||
|
* The exception_name or exemption_name is the suffix part of a MASKHINTS_*
|
||||||
|
* property name; e.g., the name SRAM corresponds to a property called
|
||||||
|
* MASKHINTS_SRAM. This declaration is followed by a block of DRC rules
|
||||||
|
* that are subject to the exception or the exemption. An exception is the
|
||||||
|
* opposite of an exemption: If a rule is excepted, then the rule applies
|
||||||
|
* within areas delineated by bounding boxes defined by the
|
||||||
|
* MASKHINTS_<exception_name> property. If a rule is exempted, then the
|
||||||
|
* rule applies only outside of areas delineated by bounding boxes defined
|
||||||
|
* by the MASKHINTS_<exemption_name> property. The block of rules subject
|
||||||
|
* to the exemption or exception ends with another exception or exemption
|
||||||
|
* declaration. If the following rules are not to be excepted or exempted
|
||||||
|
* at all, then use "exception none" or "exemption none".
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* Returns 0.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Updates drcCurException. drcCurException is zero or positive for
|
||||||
|
* exceptions and negative for exemptions. The index can be
|
||||||
|
* recovered from a negative value by negating it and subtracting 1.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
drcException(argc, argv)
|
||||||
|
int argc;
|
||||||
|
char *argv[];
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (DRCCurStyle == NULL) return 0;
|
||||||
|
|
||||||
|
/* Assume that argc must be 2 because the parser insists upon it */
|
||||||
|
|
||||||
|
if (!strcmp(argv[1], "none"))
|
||||||
|
drcCurException = (char)DRC_EXCEPTION_NONE;
|
||||||
|
else
|
||||||
|
drcCurException = drcExceptionCreate(argv[1]);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
drcExemption(argc, argv)
|
||||||
|
int argc;
|
||||||
|
char *argv[];
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (DRCCurStyle == NULL) return 0;
|
||||||
|
|
||||||
|
/* Assume that argc must be 2 because the parser insists upon it */
|
||||||
|
|
||||||
|
if (!strcmp(argv[1], "none"))
|
||||||
|
drcCurException = (char)DRC_EXCEPTION_NONE;
|
||||||
|
else
|
||||||
|
drcCurException = -(drcExceptionCreate(argv[1])) - 1;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -4119,6 +4254,7 @@ drcTechFinalStyle(style)
|
||||||
if (dp->drcc_dist > next->drcc_dist) continue;
|
if (dp->drcc_dist > next->drcc_dist) continue;
|
||||||
if (dp->drcc_cdist > next->drcc_cdist) continue;
|
if (dp->drcc_cdist > next->drcc_cdist) continue;
|
||||||
if (dp->drcc_plane != next->drcc_plane) continue;
|
if (dp->drcc_plane != next->drcc_plane) continue;
|
||||||
|
if (dp->drcc_exception != next->drcc_exception) continue;
|
||||||
if (dp->drcc_flags & DRC_REVERSE)
|
if (dp->drcc_flags & DRC_REVERSE)
|
||||||
{
|
{
|
||||||
if (!(next->drcc_flags & DRC_REVERSE)) continue;
|
if (!(next->drcc_flags & DRC_REVERSE)) continue;
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ typedef struct drccookie
|
||||||
TileTypeBitMask drcc_mask; /* Legal types on RHS */
|
TileTypeBitMask drcc_mask; /* Legal types on RHS */
|
||||||
TileTypeBitMask drcc_corner; /* Types that trigger corner check */
|
TileTypeBitMask drcc_corner; /* Types that trigger corner check */
|
||||||
unsigned short drcc_flags; /* Miscellaneous flags, see below. */
|
unsigned short drcc_flags; /* Miscellaneous flags, see below. */
|
||||||
|
char drcc_exception; /* Index to list of exceptions */
|
||||||
int drcc_edgeplane; /* Plane of edge */
|
int drcc_edgeplane; /* Plane of edge */
|
||||||
int drcc_plane; /* Index of plane on which to check
|
int drcc_plane; /* Index of plane on which to check
|
||||||
* legal types. */
|
* legal types. */
|
||||||
|
|
@ -91,6 +92,9 @@ typedef struct drccookie
|
||||||
#define DRC_UNPROCESSED CLIENTDEFAULT
|
#define DRC_UNPROCESSED CLIENTDEFAULT
|
||||||
#define DRC_PROCESSED 1
|
#define DRC_PROCESSED 1
|
||||||
|
|
||||||
|
/* drcc_exception defaults to -128 (0x80) meaning no exceptions/exemptions */
|
||||||
|
#define DRC_EXCEPTION_NONE (char)0x80
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Background DRC (DRC Idle proc) for Tcl-based Magic
|
* Background DRC (DRC Idle proc) for Tcl-based Magic
|
||||||
*/
|
*/
|
||||||
|
|
@ -177,6 +181,8 @@ typedef struct drcstyle
|
||||||
unsigned short DRCFlags; /* Option flags */
|
unsigned short DRCFlags; /* Option flags */
|
||||||
char **DRCWhyList; /* Indexed list of "why" text strings */
|
char **DRCWhyList; /* Indexed list of "why" text strings */
|
||||||
int DRCWhySize; /* Length of DRCWhyList */
|
int DRCWhySize; /* Length of DRCWhyList */
|
||||||
|
char **DRCExceptionList; /* Indexed list of DRC exceptions */
|
||||||
|
int DRCExceptionSize; /* Length of DRCExceptionList */
|
||||||
PaintResultType DRCPaintTable[NP][NT][NT];
|
PaintResultType DRCPaintTable[NP][NT][NT];
|
||||||
} DRCStyle;
|
} DRCStyle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
||||||
#include "dbwind/dbwind.h" /* for DBWclientID */
|
#include "dbwind/dbwind.h" /* for DBWclientID */
|
||||||
#include "commands/commands.h" /* for module auto-load */
|
#include "commands/commands.h" /* for module auto-load */
|
||||||
#include "textio/txcommands.h"
|
#include "textio/txcommands.h"
|
||||||
|
#include "extract/extract.h" /* for extDevTable */
|
||||||
#include "extflat/extflat.h"
|
#include "extflat/extflat.h"
|
||||||
#include "extflat/EFint.h"
|
#include "extflat/EFint.h"
|
||||||
#include "extract/extract.h" /* for extDevTable */
|
|
||||||
#include "utils/runstats.h"
|
#include "utils/runstats.h"
|
||||||
#include "utils/malloc.h"
|
#include "utils/malloc.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,14 +41,11 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
||||||
#include "commands/commands.h" /* for module auto-load */
|
#include "commands/commands.h" /* for module auto-load */
|
||||||
#include "textio/txcommands.h"
|
#include "textio/txcommands.h"
|
||||||
#include "extflat/extflat.h"
|
#include "extflat/extflat.h"
|
||||||
#include "extflat/EFint.h"
|
|
||||||
#include "extract/extract.h" /* for extDevTable */
|
#include "extract/extract.h" /* for extDevTable */
|
||||||
|
#include "extflat/EFint.h"
|
||||||
#include "utils/runstats.h"
|
#include "utils/runstats.h"
|
||||||
#include "ext2spice/ext2spice.h"
|
#include "ext2spice/ext2spice.h"
|
||||||
|
|
||||||
/* C99 compat */
|
|
||||||
#include "extflat/extflat.h"
|
|
||||||
|
|
||||||
/* These global values are defined in ext2spice.c */
|
/* These global values are defined in ext2spice.c */
|
||||||
extern HashTable subcktNameTable;
|
extern HashTable subcktNameTable;
|
||||||
extern DQueue subcktNameQueue;
|
extern DQueue subcktNameQueue;
|
||||||
|
|
@ -242,20 +239,9 @@ spcHierWriteParams(
|
||||||
|
|
||||||
/* Write all requested parameters to the subcircuit call. */
|
/* Write all requested parameters to the subcircuit call. */
|
||||||
|
|
||||||
bool checkme = FALSE;
|
|
||||||
|
|
||||||
if ((!strcmp(EFDevTypes[dev->dev_type], "pfet_06v0_dss")) ||
|
|
||||||
(!strcmp(EFDevTypes[dev->dev_type], "nfet_06v0_dss")))
|
|
||||||
{
|
|
||||||
checkme = TRUE;
|
|
||||||
TxPrintf("Diagnostic: Parameter list for %s\n", EFDevTypes[dev->dev_type]);
|
|
||||||
}
|
|
||||||
|
|
||||||
plist = efGetDeviceParams(EFDevTypes[dev->dev_type]);
|
plist = efGetDeviceParams(EFDevTypes[dev->dev_type]);
|
||||||
while (plist != NULL)
|
while (plist != NULL)
|
||||||
{
|
{
|
||||||
if (checkme) TxPrintf("Plist entry %s %s\n", plist->parm_name, plist->parm_type);
|
|
||||||
|
|
||||||
switch (plist->parm_type[0])
|
switch (plist->parm_type[0])
|
||||||
{
|
{
|
||||||
case 'a':
|
case 'a':
|
||||||
|
|
@ -356,7 +342,6 @@ spcHierWriteParams(
|
||||||
// Check for device length vs. terminal length
|
// Check for device length vs. terminal length
|
||||||
if (plist->parm_type[1] == '\0' || plist->parm_type[1] == '0')
|
if (plist->parm_type[1] == '\0' || plist->parm_type[1] == '0')
|
||||||
{
|
{
|
||||||
if (checkme) TxPrintf("Handling entry l or l0\n");
|
|
||||||
fprintf(esSpiceF, " %s=", plist->parm_name);
|
fprintf(esSpiceF, " %s=", plist->parm_name);
|
||||||
if (esScale < 0)
|
if (esScale < 0)
|
||||||
fprintf(esSpiceF, "%g", l * scale);
|
fprintf(esSpiceF, "%g", l * scale);
|
||||||
|
|
@ -371,10 +356,8 @@ spcHierWriteParams(
|
||||||
{
|
{
|
||||||
/* l1, l2, etc. used to indicate the length of the terminal */
|
/* l1, l2, etc. used to indicate the length of the terminal */
|
||||||
/* Find value in dev_params */
|
/* Find value in dev_params */
|
||||||
if (checkme) TxPrintf("Handling entry l1 or l2\n");
|
|
||||||
for (dparam = dev->dev_params; dparam; dparam = dparam->parm_next)
|
for (dparam = dev->dev_params; dparam; dparam = dparam->parm_next)
|
||||||
{
|
{
|
||||||
if (checkme) TxPrintf("Checking dev_params entry %s\n", dparam->parm_name);
|
|
||||||
if ((strlen(dparam->parm_name) > 2) &&
|
if ((strlen(dparam->parm_name) > 2) &&
|
||||||
(dparam->parm_name[0] == 'l') &&
|
(dparam->parm_name[0] == 'l') &&
|
||||||
(dparam->parm_name[1] == plist->parm_type[1]) &&
|
(dparam->parm_name[1] == plist->parm_type[1]) &&
|
||||||
|
|
@ -383,8 +366,6 @@ spcHierWriteParams(
|
||||||
int dval;
|
int dval;
|
||||||
if (sscanf(&dparam->parm_name[3], "%d", &dval) == 1)
|
if (sscanf(&dparam->parm_name[3], "%d", &dval) == 1)
|
||||||
{
|
{
|
||||||
if (checkme) TxPrintf("Handling dev_params entry %s (to be "
|
|
||||||
"culled at end)\n", dparam->parm_name);
|
|
||||||
fprintf(esSpiceF, " %s=", plist->parm_name);
|
fprintf(esSpiceF, " %s=", plist->parm_name);
|
||||||
if (esScale < 0)
|
if (esScale < 0)
|
||||||
fprintf(esSpiceF, "%g", dval * scale);
|
fprintf(esSpiceF, "%g", dval * scale);
|
||||||
|
|
@ -653,7 +634,7 @@ subcktHierVisit(
|
||||||
|
|
||||||
if (hasports || is_top)
|
if (hasports || is_top)
|
||||||
return subcktVisit(use, hierName, is_top);
|
return subcktVisit(use, hierName, is_top);
|
||||||
else if (def->def_flags & DEF_NODEVICES)
|
else if ((def->def_flags & DEF_NODEVICES) && (!isStub))
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return subcktVisit(use, hierName, is_top);
|
return subcktVisit(use, hierName, is_top);
|
||||||
|
|
@ -1107,6 +1088,7 @@ spcdevHierVisit(
|
||||||
|
|
||||||
if (!has_model)
|
if (!has_model)
|
||||||
{
|
{
|
||||||
|
fprintf(esSpiceF, " ");
|
||||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||||
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
|
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
|
||||||
}
|
}
|
||||||
|
|
@ -1157,6 +1139,7 @@ spcdevHierVisit(
|
||||||
|
|
||||||
if (!has_model)
|
if (!has_model)
|
||||||
{
|
{
|
||||||
|
fprintf(esSpiceF, " ");
|
||||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||||
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
|
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
||||||
#include "dbwind/dbwind.h" /* for DBWclientID */
|
#include "dbwind/dbwind.h" /* for DBWclientID */
|
||||||
#include "commands/commands.h" /* for module auto-load */
|
#include "commands/commands.h" /* for module auto-load */
|
||||||
#include "textio/txcommands.h"
|
#include "textio/txcommands.h"
|
||||||
|
#include "extract/extract.h" /* for extDevTable */
|
||||||
#include "extflat/extflat.h"
|
#include "extflat/extflat.h"
|
||||||
#include "extflat/EFint.h"
|
#include "extflat/EFint.h"
|
||||||
#include "extract/extract.h" /* for extDevTable */
|
|
||||||
#include "utils/runstats.h"
|
#include "utils/runstats.h"
|
||||||
|
|
||||||
#include "ext2spice/ext2spice.h"
|
#include "ext2spice/ext2spice.h"
|
||||||
|
|
@ -1689,23 +1689,43 @@ subcktVisit(
|
||||||
HashStartSearch(&hs);
|
HashStartSearch(&hs);
|
||||||
while ((he = HashNext(&def->def_nodes, &hs)))
|
while ((he = HashNext(&def->def_nodes, &hs)))
|
||||||
{
|
{
|
||||||
|
bool found = FALSE;
|
||||||
|
|
||||||
sname = (EFNodeName *) HashGetValue(he);
|
sname = (EFNodeName *) HashGetValue(he);
|
||||||
if (sname == NULL) continue;
|
if (sname == NULL) continue;
|
||||||
snode = sname->efnn_node;
|
snode = sname->efnn_node;
|
||||||
|
|
||||||
if ((snode == NULL) || !(snode->efnode_flags & EF_PORT)) continue;
|
if ((snode == NULL) || !(snode->efnode_flags & EF_PORT)) continue;
|
||||||
|
|
||||||
|
portidx = snode->efnode_name->efnn_port;
|
||||||
|
|
||||||
|
if (portidx >= 0)
|
||||||
|
{
|
||||||
|
if (nodeList[portidx] == NULL)
|
||||||
|
{
|
||||||
|
nodeList[portidx] = snode->efnode_name;
|
||||||
|
found = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Normally there should be a port associated with snode, but
|
||||||
|
* if not, go looking for one in the node name aliases.
|
||||||
|
*/
|
||||||
for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next)
|
for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next)
|
||||||
{
|
{
|
||||||
|
if (found == TRUE) break;
|
||||||
|
|
||||||
portidx = nodeName->efnn_port;
|
portidx = nodeName->efnn_port;
|
||||||
if (portidx < 0) continue;
|
if (portidx < 0) continue;
|
||||||
if (nodeList[portidx] == NULL)
|
if (nodeList[portidx] == NULL)
|
||||||
{
|
{
|
||||||
nodeList[portidx] = nodeName;
|
nodeList[portidx] = nodeName;
|
||||||
|
found = TRUE;
|
||||||
}
|
}
|
||||||
else if (EFHNBest(nodeName->efnn_hier, nodeList[portidx]->efnn_hier))
|
else if (EFHNBest(nodeName->efnn_hier, nodeList[portidx]->efnn_hier))
|
||||||
{
|
{
|
||||||
nodeList[portidx] = nodeName;
|
nodeList[portidx] = nodeName;
|
||||||
|
found = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1932,6 +1952,7 @@ topVisit(
|
||||||
{
|
{
|
||||||
char stmp[MAX_STR_SIZE];
|
char stmp[MAX_STR_SIZE];
|
||||||
int portidx;
|
int portidx;
|
||||||
|
bool found = FALSE;
|
||||||
|
|
||||||
sname = (EFNodeName *) HashGetValue(he);
|
sname = (EFNodeName *) HashGetValue(he);
|
||||||
if (sname == NULL) continue; /* Should not happen */
|
if (sname == NULL) continue; /* Should not happen */
|
||||||
|
|
@ -1939,33 +1960,68 @@ topVisit(
|
||||||
snode = sname->efnn_node;
|
snode = sname->efnn_node;
|
||||||
if ((!snode) || (!(snode->efnode_flags & EF_PORT))) continue;
|
if ((!snode) || (!(snode->efnode_flags & EF_PORT))) continue;
|
||||||
|
|
||||||
|
/* Found a node which is also a port */
|
||||||
|
|
||||||
|
portidx = snode->efnode_name->efnn_port;
|
||||||
|
if (portidx >= 0)
|
||||||
|
{
|
||||||
|
if (sorted_ports[portidx] == NULL)
|
||||||
|
{
|
||||||
|
if ((def->def_flags & DEF_ABSTRACT))
|
||||||
|
{
|
||||||
|
EFHNSprintf(stmp, sname->efnn_hier);
|
||||||
|
pname = stmp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL);
|
||||||
|
|
||||||
|
hep = HashLookOnly(&portNameTable, pname);
|
||||||
|
if (hep == (HashEntry *)NULL)
|
||||||
|
{
|
||||||
|
hep = HashFind(&portNameTable, pname);
|
||||||
|
HashSetValue(hep, (ClientData)(pointertype)portidx);
|
||||||
|
sorted_ports[portidx] = StrDup((char **)NULL, pname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Node that was unassigned has been found to be
|
||||||
|
* a repeat (see NOTE at top), so make sure its
|
||||||
|
* port number is set correctly.
|
||||||
|
*/
|
||||||
|
snode->efnode_name->efnn_port = (int)(pointertype)HashGetValue(hep);
|
||||||
|
}
|
||||||
|
found = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(def->def_flags & DEF_ABSTRACT))
|
||||||
|
heh = HashLookOnly(&efNodeHashTable, (char *)snode->efnode_name->efnn_hier);
|
||||||
|
|
||||||
|
/* Might need to check here for a port that was optimized out? */
|
||||||
|
|
||||||
|
/* If snode is flagged as a port but no port number was found, then
|
||||||
|
* check the all of the node's name entries to see if any of them has
|
||||||
|
* a port number.
|
||||||
|
*/
|
||||||
|
|
||||||
for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next)
|
for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next)
|
||||||
{
|
{
|
||||||
|
if (found == TRUE) break;
|
||||||
portidx = nodeName->efnn_port;
|
portidx = nodeName->efnn_port;
|
||||||
if (portidx < 0) continue;
|
if (portidx < 0) continue;
|
||||||
|
|
||||||
/* Check if the same hierName is recorded in the flattened/optimized
|
|
||||||
* def's efNodeHashTable. If not, then it has been optimized out
|
|
||||||
* and should be removed from the port list.
|
|
||||||
*/
|
|
||||||
if (def->def_flags & DEF_ABSTRACT)
|
if (def->def_flags & DEF_ABSTRACT)
|
||||||
|
{
|
||||||
heh = HashLookOnly(&efNodeHashTable, (char *)nodeName->efnn_hier);
|
heh = HashLookOnly(&efNodeHashTable, (char *)nodeName->efnn_hier);
|
||||||
else
|
|
||||||
heh = HashLookOnly(&efNodeHashTable,
|
|
||||||
(char *)snode->efnode_name->efnn_hier);
|
|
||||||
|
|
||||||
/* If view is abstract, rely on the given port name, not
|
/* If view is abstract, rely on the given port name, not
|
||||||
* the node. Otherwise, artifacts of the abstract view
|
* the node. Otherwise, artifacts of the abstract view
|
||||||
* may cause nodes to be merged and the names lost.
|
* may cause nodes to be merged and the names lost.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (def->def_flags & DEF_ABSTRACT)
|
|
||||||
{
|
|
||||||
EFHNSprintf(stmp, nodeName->efnn_hier);
|
EFHNSprintf(stmp, nodeName->efnn_hier);
|
||||||
pname = stmp;
|
pname = stmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL);
|
|
||||||
pname = nodeSpiceName(nodeName->efnn_hier, NULL);
|
pname = nodeSpiceName(nodeName->efnn_hier, NULL);
|
||||||
|
|
||||||
if (heh == (HashEntry *)NULL) /* pname now resolved for log output */
|
if (heh == (HashEntry *)NULL) /* pname now resolved for log output */
|
||||||
|
|
@ -1983,7 +2039,10 @@ topVisit(
|
||||||
hep = HashFind(&portNameTable, pname);
|
hep = HashFind(&portNameTable, pname);
|
||||||
HashSetValue(hep, (ClientData)(pointertype)nodeName->efnn_port);
|
HashSetValue(hep, (ClientData)(pointertype)nodeName->efnn_port);
|
||||||
if (sorted_ports[portidx] == NULL)
|
if (sorted_ports[portidx] == NULL)
|
||||||
|
{
|
||||||
sorted_ports[portidx] = StrDup((char **)NULL, pname);
|
sorted_ports[portidx] = StrDup((char **)NULL, pname);
|
||||||
|
found = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -3081,6 +3140,7 @@ spcdevVisit(
|
||||||
|
|
||||||
if (!has_model)
|
if (!has_model)
|
||||||
{
|
{
|
||||||
|
fprintf(esSpiceF, " ");
|
||||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||||
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
|
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
|
||||||
}
|
}
|
||||||
|
|
@ -3127,6 +3187,7 @@ spcdevVisit(
|
||||||
|
|
||||||
if (!has_model)
|
if (!has_model)
|
||||||
{
|
{
|
||||||
|
fprintf(esSpiceF, " ");
|
||||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||||
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
|
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
|
||||||
}
|
}
|
||||||
|
|
@ -3314,12 +3375,15 @@ spcdevSubstrate(
|
||||||
/* Canonical name */
|
/* Canonical name */
|
||||||
nn = (EFNodeName *) HashGetValue(he);
|
nn = (EFNodeName *) HashGetValue(he);
|
||||||
if (outf)
|
if (outf)
|
||||||
fprintf(outf, "%s", nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier,
|
{
|
||||||
NULL));
|
const char *spicename;
|
||||||
|
spicename = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier, NULL);
|
||||||
|
fprintf(outf, "%s", spicename);
|
||||||
|
}
|
||||||
|
|
||||||
/* Create node client if it doesn't exist */
|
/* Create node client if it doesn't exist */
|
||||||
if ((nodeClient *)nn->efnn_node->efnode_client == (nodeClient *)NULL)
|
if ((nodeClient *)nn->efnn_node->efnode_client == (nodeClient *)NULL)
|
||||||
initNodeClientHier(nn->efnn_node);
|
initNodeClient(nn->efnn_node);
|
||||||
|
|
||||||
/* Mark node as visited (set bit one higher than number of resist classes) */
|
/* Mark node as visited (set bit one higher than number of resist classes) */
|
||||||
if (esDistrJunct)
|
if (esDistrJunct)
|
||||||
|
|
|
||||||
|
|
@ -754,8 +754,9 @@ antennacheckVisit(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
areaMarkFunc(tile, ams)
|
areaMarkFunc(tile, dinfo, ams)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
AntennaMarkStruct *ams;
|
AntennaMarkStruct *ams;
|
||||||
{
|
{
|
||||||
Rect rect;
|
Rect rect;
|
||||||
|
|
@ -778,8 +779,9 @@ areaMarkFunc(tile, ams)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
areaAccumFunc(tile, gdas)
|
areaAccumFunc(tile, dinfo, gdas)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
GateDiffAccumStruct *gdas;
|
GateDiffAccumStruct *gdas;
|
||||||
{
|
{
|
||||||
Rect *rect = &(gdas->r);
|
Rect *rect = &(gdas->r);
|
||||||
|
|
@ -788,7 +790,7 @@ areaAccumFunc(tile, gdas)
|
||||||
|
|
||||||
/* Avoid double-counting the area of contacts */
|
/* Avoid double-counting the area of contacts */
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
type = SplitSide(tile) ? SplitRightType(tile) : SplitLeftType(tile);
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
else
|
else
|
||||||
type = TiGetType(tile);
|
type = TiGetType(tile);
|
||||||
|
|
||||||
|
|
@ -798,6 +800,7 @@ areaAccumFunc(tile, gdas)
|
||||||
|
|
||||||
TiToRect(tile, rect);
|
TiToRect(tile, rect);
|
||||||
area = (dlong)(rect->r_xtop - rect->r_xbot) * (dlong)(rect->r_ytop - rect->r_ybot);
|
area = (dlong)(rect->r_xtop - rect->r_xbot) * (dlong)(rect->r_ytop - rect->r_ybot);
|
||||||
|
if (IsSplit(tile)) area /= 2;
|
||||||
gdas->accum += area;
|
gdas->accum += area;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -816,8 +819,9 @@ areaAccumFunc(tile, gdas)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
antennaAccumFunc(tile, aaptr)
|
antennaAccumFunc(tile, dinfo, aaptr)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* Not used, but should be handled */
|
||||||
AntennaAccumStruct *aaptr;
|
AntennaAccumStruct *aaptr;
|
||||||
{
|
{
|
||||||
Rect *rect = &(aaptr->r);
|
Rect *rect = &(aaptr->r);
|
||||||
|
|
@ -1003,6 +1007,7 @@ antennaAccumFunc(tile, aaptr)
|
||||||
TiToRect(tile, rect);
|
TiToRect(tile, rect);
|
||||||
area = (dlong)(rect->r_xtop - rect->r_xbot)
|
area = (dlong)(rect->r_xtop - rect->r_xbot)
|
||||||
* (dlong)(rect->r_ytop - rect->r_ybot);
|
* (dlong)(rect->r_ytop - rect->r_ybot);
|
||||||
|
if (IsSplit(tile)) area /= 2;
|
||||||
|
|
||||||
typeareas[type] += area;
|
typeareas[type] += area;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header$";
|
||||||
#include "tiles/tile.h"
|
#include "tiles/tile.h"
|
||||||
#include "database/database.h" /* for TileType definition */
|
#include "database/database.h" /* for TileType definition */
|
||||||
#include "extflat/extflat.h"
|
#include "extflat/extflat.h"
|
||||||
|
#include "extflat/extparse.h"
|
||||||
#include "extflat/EFint.h"
|
#include "extflat/EFint.h"
|
||||||
#include "extract/extract.h" /* for device class list */
|
#include "extract/extract.h"
|
||||||
#include "extract/extractInt.h" /* for extGetDevType() */
|
#include "extract/extractInt.h" /* for extGetDevType() */
|
||||||
|
|
||||||
/* C99 compat */
|
/* C99 compat */
|
||||||
|
|
@ -647,8 +648,21 @@ efBuildEquiv(def, nodeName1, nodeName2, resist, isspice)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!resist)
|
else if (!resist)
|
||||||
|
{
|
||||||
|
char *uptr1, *uptr2;
|
||||||
|
|
||||||
|
/* Do not generate an error message if one or both node names
|
||||||
|
* is made by "extract unique".
|
||||||
|
*/
|
||||||
|
if ((uptr1 = strstr(nodeName1, "_uq")) != 0) *uptr1 = '\0';
|
||||||
|
if ((uptr2 = strstr(nodeName2, "_uq")) != 0) *uptr2 = '\0';
|
||||||
|
if ((uptr1 == NULL && uptr2 == NULL) ||
|
||||||
|
strcmp(nodeName1, nodeName2))
|
||||||
TxError("Warning: Ports \"%s\" and \"%s\" are electrically "
|
TxError("Warning: Ports \"%s\" and \"%s\" are electrically "
|
||||||
"shorted.\n", nodeName1, nodeName2);
|
"shorted.\n", nodeName1, nodeName2);
|
||||||
|
if (uptr1) *uptr1 = '_';
|
||||||
|
if (uptr2) *uptr2 = '_';
|
||||||
|
}
|
||||||
else
|
else
|
||||||
/* Do not merge the nodes when folding in extresist parasitics */
|
/* Do not merge the nodes when folding in extresist parasitics */
|
||||||
return;
|
return;
|
||||||
|
|
@ -860,13 +874,13 @@ efBuildDevice(
|
||||||
const Rect *r, /* Coordinates of 1x1 rectangle entirely inside device */
|
const Rect *r, /* Coordinates of 1x1 rectangle entirely inside device */
|
||||||
int argc, /* Size of argv */
|
int argc, /* Size of argv */
|
||||||
char *argv[]) /* Tokens for the rest of the dev line.
|
char *argv[]) /* Tokens for the rest of the dev line.
|
||||||
* Starts with the last two position values, used to
|
* Starts after the four device coordinate arguments.
|
||||||
* hash the device record. The next arguments depend
|
* The next arguments (0, 1, or 2) depend on the type of
|
||||||
* on the type of device. The rest are taken in groups
|
* device, followed by optional parameters. The rest are
|
||||||
* of 3, one for each terminal. Each group of 3 consists
|
* taken in groups of 3, one for each terminal. Each
|
||||||
* of the node name to which the terminal connects, the
|
* group of 3 consists of the node name to which the
|
||||||
* length of the terminal, and an attribute list (or the
|
* terminal connects, the length of the terminal, and
|
||||||
* token 0).
|
* an attribute list (or the token 0).
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
int n, nterminals, pn;
|
int n, nterminals, pn;
|
||||||
|
|
@ -878,7 +892,7 @@ efBuildDevice(
|
||||||
int dev_type;
|
int dev_type;
|
||||||
char ptype, *pptr, **av;
|
char ptype, *pptr, **av;
|
||||||
char devhash[64];
|
char devhash[64];
|
||||||
int argstart = 1; /* start of terminal list in argv[] */
|
int termstart;
|
||||||
bool hasModel = strcmp(type, "None") ? TRUE : FALSE;
|
bool hasModel = strcmp(type, "None") ? TRUE : FALSE;
|
||||||
|
|
||||||
int area, perim; /* Total area, perimeter of primary type (i.e., channel) */
|
int area, perim; /* Total area, perimeter of primary type (i.e., channel) */
|
||||||
|
|
@ -893,24 +907,40 @@ efBuildDevice(
|
||||||
devtmp.dev_width = 0;
|
devtmp.dev_width = 0;
|
||||||
devtmp.dev_params = NULL;
|
devtmp.dev_params = NULL;
|
||||||
|
|
||||||
|
termstart = 1; /* Start of terminal list in argv[]; this is a default
|
||||||
|
* value if none of the cases below applies. The value
|
||||||
|
* of termstart does not initially account for parameter
|
||||||
|
* entries (<param>=<value>) but is adjusted as the
|
||||||
|
* parameters are parsed. The first terminal may be an
|
||||||
|
* (optional) substrate which is determined by whether
|
||||||
|
* the number of remaining arguments is divisible by 3
|
||||||
|
* or not.
|
||||||
|
*/
|
||||||
switch (class)
|
switch (class)
|
||||||
{
|
{
|
||||||
case DEV_FET:
|
case DEV_FET:
|
||||||
case DEV_MOSFET:
|
case DEV_MOSFET:
|
||||||
case DEV_ASYMMETRIC:
|
case DEV_ASYMMETRIC:
|
||||||
|
/* Terminals start after L and W values, substrate, and parameters */
|
||||||
|
termstart = 3;
|
||||||
|
break;
|
||||||
case DEV_BJT:
|
case DEV_BJT:
|
||||||
argstart = 3;
|
/* Terminals start after L and W values, plus parameters */
|
||||||
|
termstart = 2;
|
||||||
break;
|
break;
|
||||||
case DEV_DIODE:
|
case DEV_DIODE:
|
||||||
case DEV_NDIODE:
|
case DEV_NDIODE:
|
||||||
case DEV_PDIODE:
|
case DEV_PDIODE:
|
||||||
argstart = 0;
|
/* Terminals start immediately after parameters */
|
||||||
|
termstart = 0;
|
||||||
break;
|
break;
|
||||||
case DEV_RES:
|
case DEV_RES:
|
||||||
case DEV_CAP:
|
case DEV_CAP:
|
||||||
case DEV_CAPREV:
|
case DEV_CAPREV:
|
||||||
if (hasModel)
|
if (hasModel)
|
||||||
argstart = 2;
|
/* Terminals start after L and W values, plus parameters */
|
||||||
|
termstart = 2;
|
||||||
|
/* Otherwise, terminals start after device value, plus parameters */
|
||||||
break;
|
break;
|
||||||
case DEV_SUBCKT:
|
case DEV_SUBCKT:
|
||||||
case DEV_VERILOGA:
|
case DEV_VERILOGA:
|
||||||
|
|
@ -918,13 +948,14 @@ efBuildDevice(
|
||||||
case DEV_RSUBCKT:
|
case DEV_RSUBCKT:
|
||||||
case DEV_CSUBCKT:
|
case DEV_CSUBCKT:
|
||||||
case DEV_DSUBCKT:
|
case DEV_DSUBCKT:
|
||||||
argstart = 0;
|
/* Terminals start immediately after parameters */
|
||||||
|
termstart = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
devp = efGetDeviceParams(type);
|
devp = efGetDeviceParams(type);
|
||||||
|
|
||||||
/* Parse initial arguments for parameters */
|
/* Parse initial arguments for parameters */
|
||||||
while ((pptr = strchr(argv[argstart], '=')) != NULL)
|
while ((pptr = strchr(argv[termstart], '=')) != NULL)
|
||||||
{
|
{
|
||||||
/* If the parameter is in the parameter list "devp", then save
|
/* If the parameter is in the parameter list "devp", then save
|
||||||
* the value as appropriate. If not, then the entire phrase
|
* the value as appropriate. If not, then the entire phrase
|
||||||
|
|
@ -936,7 +967,7 @@ efBuildDevice(
|
||||||
|
|
||||||
*pptr = '\0';
|
*pptr = '\0';
|
||||||
for (sparm = devp; sparm; sparm = sparm->parm_next)
|
for (sparm = devp; sparm; sparm = sparm->parm_next)
|
||||||
if (!strncasecmp(sparm->parm_type, argv[argstart], 2))
|
if (!strncasecmp(sparm->parm_type, argv[termstart], 2))
|
||||||
break;
|
break;
|
||||||
*pptr = '=';
|
*pptr = '=';
|
||||||
if (sparm == NULL)
|
if (sparm == NULL)
|
||||||
|
|
@ -944,18 +975,18 @@ efBuildDevice(
|
||||||
/* Copy the whole string into dev_params */
|
/* Copy the whole string into dev_params */
|
||||||
/* (parm_type and parm_scale records are not used) */
|
/* (parm_type and parm_scale records are not used) */
|
||||||
newparm = (DevParam *)mallocMagic(sizeof(DevParam));
|
newparm = (DevParam *)mallocMagic(sizeof(DevParam));
|
||||||
newparm->parm_name = StrDup((char **)NULL, argv[argstart]);
|
newparm->parm_name = StrDup((char **)NULL, argv[termstart]);
|
||||||
newparm->parm_next = devtmp.dev_params;
|
newparm->parm_next = devtmp.dev_params;
|
||||||
devtmp.dev_params = newparm;
|
devtmp.dev_params = newparm;
|
||||||
argstart++;
|
termstart++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pptr++;
|
pptr++;
|
||||||
switch(*argv[argstart])
|
switch(*argv[termstart])
|
||||||
{
|
{
|
||||||
case 'a':
|
case 'a':
|
||||||
if ((pptr - argv[argstart]) == 2)
|
if ((pptr - argv[termstart]) == 2)
|
||||||
devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
|
devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
|
||||||
* locScale * locScale);
|
* locScale * locScale);
|
||||||
else
|
else
|
||||||
|
|
@ -963,7 +994,7 @@ efBuildDevice(
|
||||||
/* Check for a0, a1, a2, ... If a0, handle like "a".
|
/* Check for a0, a1, a2, ... If a0, handle like "a".
|
||||||
* Otherwise, don't handle it here.
|
* Otherwise, don't handle it here.
|
||||||
*/
|
*/
|
||||||
pn = *(argv[argstart] + 1) - '0';
|
pn = *(argv[termstart] + 1) - '0';
|
||||||
if (pn == 0)
|
if (pn == 0)
|
||||||
devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
|
devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
|
||||||
* locScale * locScale);
|
* locScale * locScale);
|
||||||
|
|
@ -971,21 +1002,21 @@ efBuildDevice(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
if ((pptr - argv[argstart]) == 2)
|
if ((pptr - argv[termstart]) == 2)
|
||||||
devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale);
|
devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Check for p0, p1, p2, ... If p0, handle like "p".
|
/* Check for p0, p1, p2, ... If p0, handle like "p".
|
||||||
* Otherwise, don't handle it here.
|
* Otherwise, don't handle it here.
|
||||||
*/
|
*/
|
||||||
pn = *(argv[argstart] + 1) - '0';
|
pn = *(argv[termstart] + 1) - '0';
|
||||||
if (pn == 0)
|
if (pn == 0)
|
||||||
devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale);
|
devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
if ((pptr - argv[argstart]) == 2)
|
if ((pptr - argv[termstart]) == 2)
|
||||||
devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
|
devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -995,14 +1026,14 @@ efBuildDevice(
|
||||||
* values like "a1, a2, ..." or "p1, p2, ...".
|
* values like "a1, a2, ..." or "p1, p2, ...".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pn = *(argv[argstart] + 1) - '0';
|
pn = *(argv[termstart] + 1) - '0';
|
||||||
if (pn == 0)
|
if (pn == 0)
|
||||||
devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
|
devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Copy the whole string into dev_params */
|
/* Copy the whole string into dev_params */
|
||||||
newparm = (DevParam *)mallocMagic(sizeof(DevParam));
|
newparm = (DevParam *)mallocMagic(sizeof(DevParam));
|
||||||
newparm->parm_name = StrDup((char **)NULL, argv[argstart]);
|
newparm->parm_name = StrDup((char **)NULL, argv[termstart]);
|
||||||
newparm->parm_next = devtmp.dev_params;
|
newparm->parm_next = devtmp.dev_params;
|
||||||
devtmp.dev_params = newparm;
|
devtmp.dev_params = newparm;
|
||||||
}
|
}
|
||||||
|
|
@ -1010,7 +1041,28 @@ efBuildDevice(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'w':
|
case 'w':
|
||||||
|
if ((pptr - argv[termstart]) == 2)
|
||||||
devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale);
|
devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Check for w0, w1, w2, ... If w0, handle like "w".
|
||||||
|
* Otherwise, save it verbatim like an unknown parameter,
|
||||||
|
* because its value will not be calculated from terminal
|
||||||
|
* values like "a1, a2, ..." or "p1, p2, ...".
|
||||||
|
*/
|
||||||
|
|
||||||
|
pn = *(argv[termstart] + 1) - '0';
|
||||||
|
if (pn == 0)
|
||||||
|
devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Copy the whole string into dev_params */
|
||||||
|
newparm = (DevParam *)mallocMagic(sizeof(DevParam));
|
||||||
|
newparm->parm_name = StrDup((char **)NULL, argv[termstart]);
|
||||||
|
newparm->parm_next = devtmp.dev_params;
|
||||||
|
devtmp.dev_params = newparm;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
devtmp.dev_cap = (float)atof(pptr);
|
devtmp.dev_cap = (float)atof(pptr);
|
||||||
|
|
@ -1019,7 +1071,7 @@ efBuildDevice(
|
||||||
devtmp.dev_res = (float)atof(pptr);
|
devtmp.dev_res = (float)atof(pptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
argstart++;
|
termstart++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for optional substrate node */
|
/* Check for optional substrate node */
|
||||||
|
|
@ -1027,6 +1079,7 @@ efBuildDevice(
|
||||||
{
|
{
|
||||||
case DEV_RES:
|
case DEV_RES:
|
||||||
case DEV_CAP:
|
case DEV_CAP:
|
||||||
|
case DEV_BJT:
|
||||||
case DEV_CAPREV:
|
case DEV_CAPREV:
|
||||||
case DEV_RSUBCKT:
|
case DEV_RSUBCKT:
|
||||||
case DEV_CSUBCKT:
|
case DEV_CSUBCKT:
|
||||||
|
|
@ -1037,22 +1090,22 @@ efBuildDevice(
|
||||||
case DEV_DIODE:
|
case DEV_DIODE:
|
||||||
case DEV_NDIODE:
|
case DEV_NDIODE:
|
||||||
case DEV_PDIODE:
|
case DEV_PDIODE:
|
||||||
n = argc - argstart;
|
n = argc - termstart;
|
||||||
if ((n % 3) == 1)
|
if ((n % 3) == 1)
|
||||||
{
|
{
|
||||||
if (strncmp(argv[argstart], "None", 4) != 0)
|
if (strncmp(argv[termstart], "None", 4) != 0)
|
||||||
devtmp.dev_subsnode = efBuildDevNode(def, argv[argstart], TRUE);
|
devtmp.dev_subsnode = efBuildDevNode(def, argv[termstart], TRUE);
|
||||||
|
|
||||||
argstart++;
|
termstart++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Between argstart and argc, we should only have terminal triples */
|
/* Between termstart and argc, we should only have terminal triples */
|
||||||
if (((argc - argstart) % 3) != 0)
|
if (((argc - termstart) % 3) != 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
nterminals = (argc - argstart) / 3;
|
nterminals = (argc - termstart) / 3;
|
||||||
|
|
||||||
dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, type);
|
dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, type);
|
||||||
|
|
||||||
|
|
@ -1215,17 +1268,17 @@ efBuildDevice(
|
||||||
case DEV_ASYMMETRIC:
|
case DEV_ASYMMETRIC:
|
||||||
case DEV_BJT:
|
case DEV_BJT:
|
||||||
/* "None" in the place of the substrate name means substrate is ignored */
|
/* "None" in the place of the substrate name means substrate is ignored */
|
||||||
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
if ((termstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
||||||
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
||||||
break;
|
break;
|
||||||
case DEV_RES:
|
case DEV_RES:
|
||||||
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
if ((termstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
||||||
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case DEV_CAP:
|
case DEV_CAP:
|
||||||
case DEV_CAPREV:
|
case DEV_CAPREV:
|
||||||
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
if ((termstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
||||||
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
@ -1235,7 +1288,7 @@ efBuildDevice(
|
||||||
#define TERM_PERIM 1
|
#define TERM_PERIM 1
|
||||||
#define TERM_ATTRS 2
|
#define TERM_ATTRS 2
|
||||||
|
|
||||||
for (av = &argv[argstart], n = 0; n < nterminals; n++, av += 3)
|
for (av = &argv[termstart], n = 0; n < nterminals; n++, av += 3)
|
||||||
{
|
{
|
||||||
term = &newdev->dev_terms[n];
|
term = &newdev->dev_terms[n];
|
||||||
term->dterm_node = efBuildDevNode(def, av[TERM_NAME], FALSE);
|
term->dterm_node = efBuildDevNode(def, av[TERM_NAME], FALSE);
|
||||||
|
|
@ -2063,7 +2116,7 @@ efNodeMerge(node1ptr, node2ptr)
|
||||||
/* Make all EFNodeNames point to "keeping" */
|
/* Make all EFNodeNames point to "keeping" */
|
||||||
if (removing->efnode_name)
|
if (removing->efnode_name)
|
||||||
{
|
{
|
||||||
bool topportk, topportr, bestname;
|
bool topportk, topportr, bestname, swapnames;
|
||||||
|
|
||||||
for (nn = removing->efnode_name; nn; nn = nn->efnn_next)
|
for (nn = removing->efnode_name; nn; nn = nn->efnn_next)
|
||||||
{
|
{
|
||||||
|
|
@ -2074,10 +2127,31 @@ efNodeMerge(node1ptr, node2ptr)
|
||||||
topportk = (keeping->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
|
topportk = (keeping->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
|
||||||
topportr = (removing->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
|
topportr = (removing->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
|
||||||
|
|
||||||
/* Concatenate list of EFNodeNames, taking into account precedence */
|
/* The node "keeping" is being kept, but we need to decide which
|
||||||
if ((!keeping->efnode_name) || (!topportk && topportr)
|
* node name of the two will be the node name of "keeping". If
|
||||||
|| EFHNBest(removing->efnode_name->efnn_hier,
|
* "keeping" has the best node name, then we're good; otherwise,
|
||||||
keeping->efnode_name->efnn_hier))
|
* we need to copy the name from "removing" to "keeping".
|
||||||
|
*
|
||||||
|
* Order of precedence:
|
||||||
|
* 1) If one node does not have a name, then use the name of the other.
|
||||||
|
* 2) If one node is a port and the other isn't, then use the port name.
|
||||||
|
* 3) Use the one with the preferred lexigraphical order according to
|
||||||
|
* EFHNBest().
|
||||||
|
*/
|
||||||
|
if ((!keeping->efnode_name) && (removing->efnode_name))
|
||||||
|
swapnames = TRUE;
|
||||||
|
else if ((keeping->efnode_name) && (!removing->efnode_name))
|
||||||
|
swapnames = FALSE;
|
||||||
|
else if (!topportk && topportr)
|
||||||
|
swapnames = TRUE;
|
||||||
|
else if (topportk && !topportr)
|
||||||
|
swapnames = FALSE;
|
||||||
|
else
|
||||||
|
swapnames = EFHNBest(removing->efnode_name->efnn_hier,
|
||||||
|
keeping->efnode_name->efnn_hier);
|
||||||
|
|
||||||
|
/* Concatenate list of EFNodeNames */
|
||||||
|
if (swapnames)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* New official name is that of "removing".
|
* New official name is that of "removing".
|
||||||
|
|
@ -2164,6 +2238,14 @@ efNodeMerge(node1ptr, node2ptr)
|
||||||
if (removing->efnode_flags & EF_SUBS_NODE)
|
if (removing->efnode_flags & EF_SUBS_NODE)
|
||||||
keeping->efnode_flags |= EF_SUBS_NODE;
|
keeping->efnode_flags |= EF_SUBS_NODE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If "removing" has the EF_GLOB_SUBS_NODE flag set, then copy the
|
||||||
|
* port record in the flags to "keeping".
|
||||||
|
*/
|
||||||
|
if (removing->efnode_flags & EF_GLOB_SUBS_NODE)
|
||||||
|
keeping->efnode_flags |= EF_GLOB_SUBS_NODE;
|
||||||
|
|
||||||
|
/* If EFSaveLocs is set, then merge any disjoint segments from
|
||||||
/* If EFSaveLocs is set, then merge any disjoint segments from
|
/* If EFSaveLocs is set, then merge any disjoint segments from
|
||||||
* removing to keeping.
|
* removing to keeping.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
|
#include "extflat/extparse.h"
|
||||||
extern char *efReadFileName;
|
|
||||||
extern int efReadLineNum;
|
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
extern int Tcl_printf();
|
extern int Tcl_printf();
|
||||||
|
|
|
||||||
|
|
@ -61,15 +61,17 @@ int efFlatGlobHash(HierName *);
|
||||||
bool efFlatGlobCmp(HierName *, HierName *);
|
bool efFlatGlobCmp(HierName *, HierName *);
|
||||||
char *efFlatGlobCopy(HierName *);
|
char *efFlatGlobCopy(HierName *);
|
||||||
void efFlatGlobError(EFNodeName *nameGlob, EFNodeName *nameFlat);
|
void efFlatGlobError(EFNodeName *nameGlob, EFNodeName *nameFlat);
|
||||||
int efAddNodes(HierContext *hc, bool stdcell);
|
int efAddNodes(HierContext *hc, int flags);
|
||||||
int efAddConns(HierContext *hc, bool doWarn);
|
int efAddConns(HierContext *hc, int flags);
|
||||||
int efAddOneConn(HierContext *hc, char *name1, char *name2, Connection *conn, bool doWarn);
|
int efAddOneConn(HierContext *hc, char *name1, char *name2, Connection *conn, int flags);
|
||||||
|
|
||||||
/* Flags passed to efFlatNode() */
|
/* Flags passed to efFlatNode() */
|
||||||
|
|
||||||
#define FLATNODE_STDCELL 0x01
|
#define FLATNODE_STDCELL 0x01
|
||||||
#define FLATNODE_DOWARN 0x02
|
#define FLATNODE_DOWARN 0x02
|
||||||
#define FLATNODE_NOABSTRACT 0x04
|
#define FLATNODE_NOABSTRACT 0x04
|
||||||
|
#define FLATNODE_HIER 0x08
|
||||||
|
#define FLATNODE_CHILD 0x10
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -216,7 +218,7 @@ EFFlatBuildOneLevel(def, flags)
|
||||||
efFlatRootUse.use_def = efFlatRootDef;
|
efFlatRootUse.use_def = efFlatRootDef;
|
||||||
|
|
||||||
/* Record all nodes down the hierarchy from here */
|
/* Record all nodes down the hierarchy from here */
|
||||||
flatnodeflags = 0; /* No FLATNODE_DOWARN */
|
flatnodeflags = FLATNODE_HIER; /* No FLATNODE_DOWARN */
|
||||||
efFlatNodes(&efFlatContext, INT2CD(flatnodeflags));
|
efFlatNodes(&efFlatContext, INT2CD(flatnodeflags));
|
||||||
|
|
||||||
/* Expand all subcells that contain connectivity information but */
|
/* Expand all subcells that contain connectivity information but */
|
||||||
|
|
@ -320,9 +322,7 @@ efFlatNodes(hc, clientData)
|
||||||
ClientData clientData;
|
ClientData clientData;
|
||||||
{
|
{
|
||||||
int flags = (int)CD2INT(clientData);
|
int flags = (int)CD2INT(clientData);
|
||||||
|
int hierflags = 0;
|
||||||
bool stdcell = (flags & FLATNODE_STDCELL) ? TRUE : FALSE;
|
|
||||||
bool doWarn = (flags & FLATNODE_DOWARN) ? TRUE : FALSE;
|
|
||||||
|
|
||||||
if (flags & FLATNODE_NOABSTRACT)
|
if (flags & FLATNODE_NOABSTRACT)
|
||||||
{
|
{
|
||||||
|
|
@ -332,13 +332,19 @@ efFlatNodes(hc, clientData)
|
||||||
def->def_name);
|
def->def_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) efHierSrUses(hc, efFlatNodes, clientData);
|
/* If called with FLATNODE_HIER set, then set the FLATNODE_CHILD
|
||||||
|
* flag while calling efHierSrUses(), to prevent efAddNodes() from
|
||||||
|
* duplicating the capacitance of nodes in child cells.
|
||||||
|
*/
|
||||||
|
|
||||||
|
hierflags = flags | ((flags & FLATNODE_HIER) ? FLATNODE_CHILD : 0);
|
||||||
|
(void) efHierSrUses(hc, efFlatNodes, INT2CD(hierflags));
|
||||||
|
|
||||||
/* Add all our own nodes to the table */
|
/* Add all our own nodes to the table */
|
||||||
efAddNodes(hc, stdcell);
|
efAddNodes(hc, flags);
|
||||||
|
|
||||||
/* Process our own connections and adjustments */
|
/* Process our own connections and adjustments */
|
||||||
(void) efAddConns(hc, doWarn);
|
(void) efAddConns(hc, flags);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
@ -386,11 +392,11 @@ efFlatNodesStdCell(hc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add all our own nodes to the table */
|
/* Add all our own nodes to the table */
|
||||||
efAddNodes(hc, TRUE);
|
efAddNodes(hc, (int)FLATNODE_STDCELL);
|
||||||
|
|
||||||
/* Process our own connections and adjustments */
|
/* Process our own connections and adjustments */
|
||||||
if (!(hc->hc_use->use_def->def_flags & DEF_SUBCIRCUIT))
|
if (!(hc->hc_use->use_def->def_flags & DEF_SUBCIRCUIT))
|
||||||
(void) efAddConns(hc, TRUE);
|
(void) efAddConns(hc, (int)FLATNODE_DOWARN);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
@ -413,10 +419,10 @@ efFlatNodesDeviceless(hc, cdata)
|
||||||
if ((HashGetNumEntries(&hc->hc_use->use_def->def_devs) == 0) && (newcount == 0))
|
if ((HashGetNumEntries(&hc->hc_use->use_def->def_devs) == 0) && (newcount == 0))
|
||||||
{
|
{
|
||||||
/* Add all our own nodes to the table */
|
/* Add all our own nodes to the table */
|
||||||
efAddNodes(hc, TRUE);
|
efAddNodes(hc, (int)FLATNODE_STDCELL);
|
||||||
|
|
||||||
/* Process our own connections and adjustments */
|
/* Process our own connections and adjustments */
|
||||||
efAddConns(hc, TRUE);
|
efAddConns(hc, (int)FLATNODE_DOWARN);
|
||||||
|
|
||||||
/* Mark this definition as having no devices, so it will not be visited */
|
/* Mark this definition as having no devices, so it will not be visited */
|
||||||
hc->hc_use->use_def->def_flags |= DEF_NODEVICES;
|
hc->hc_use->use_def->def_flags |= DEF_NODEVICES;
|
||||||
|
|
@ -455,7 +461,7 @@ efFlatNodesDeviceless(hc, cdata)
|
||||||
int
|
int
|
||||||
efAddNodes(
|
efAddNodes(
|
||||||
HierContext *hc,
|
HierContext *hc,
|
||||||
bool stdcell)
|
int flags)
|
||||||
{
|
{
|
||||||
Def *def = hc->hc_use->use_def;
|
Def *def = hc->hc_use->use_def;
|
||||||
EFNodeName *nn, *newname, *oldname;
|
EFNodeName *nn, *newname, *oldname;
|
||||||
|
|
@ -465,6 +471,8 @@ efAddNodes(
|
||||||
HierName *hierName;
|
HierName *hierName;
|
||||||
int size, asize;
|
int size, asize;
|
||||||
HashEntry *he;
|
HashEntry *he;
|
||||||
|
bool stdcell = (flags & FLATNODE_STDCELL) ? TRUE : FALSE;
|
||||||
|
bool is_child = (flags & FLATNODE_CHILD) ? TRUE : FALSE;
|
||||||
bool is_subcircuit = (def->def_flags & DEF_SUBCIRCUIT) ? TRUE : FALSE;
|
bool is_subcircuit = (def->def_flags & DEF_SUBCIRCUIT) ? TRUE : FALSE;
|
||||||
|
|
||||||
size = sizeof (EFNode) + (efNumResistClasses-1) * sizeof (EFPerimArea);
|
size = sizeof (EFNode) + (efNumResistClasses-1) * sizeof (EFPerimArea);
|
||||||
|
|
@ -503,12 +511,15 @@ efAddNodes(
|
||||||
// If called with "hierarchy on", all local node caps and adjustments
|
// If called with "hierarchy on", all local node caps and adjustments
|
||||||
// have been output and should be ignored.
|
// have been output and should be ignored.
|
||||||
|
|
||||||
newnode->efnode_cap = (!stdcell) ? node->efnode_cap : (EFCapValue)0.0;
|
if (!stdcell && !is_child)
|
||||||
|
newnode->efnode_cap = node->efnode_cap;
|
||||||
|
else
|
||||||
|
newnode->efnode_cap = (EFCapValue)0.0;
|
||||||
newnode->efnode_client = (ClientData) NULL;
|
newnode->efnode_client = (ClientData) NULL;
|
||||||
newnode->efnode_flags = node->efnode_flags;
|
newnode->efnode_flags = node->efnode_flags;
|
||||||
newnode->efnode_type = node->efnode_type;
|
newnode->efnode_type = node->efnode_type;
|
||||||
newnode->efnode_num = 1;
|
newnode->efnode_num = 1;
|
||||||
if (!stdcell)
|
if (!stdcell && !is_child)
|
||||||
bcopy((char *) node->efnode_pa, (char *) newnode->efnode_pa,
|
bcopy((char *) node->efnode_pa, (char *) newnode->efnode_pa,
|
||||||
efNumResistClasses * sizeof (EFPerimArea));
|
efNumResistClasses * sizeof (EFPerimArea));
|
||||||
else
|
else
|
||||||
|
|
@ -601,7 +612,7 @@ efAddNodes(
|
||||||
int
|
int
|
||||||
efAddConns(
|
efAddConns(
|
||||||
HierContext *hc,
|
HierContext *hc,
|
||||||
bool doWarn)
|
int flags)
|
||||||
{
|
{
|
||||||
Connection *conn;
|
Connection *conn;
|
||||||
|
|
||||||
|
|
@ -614,9 +625,9 @@ efAddConns(
|
||||||
{
|
{
|
||||||
/* Special case for speed when no array info is present */
|
/* Special case for speed when no array info is present */
|
||||||
if (conn->conn_1.cn_nsubs == 0)
|
if (conn->conn_1.cn_nsubs == 0)
|
||||||
efAddOneConn(hc, conn->conn_name1, conn->conn_name2, conn, doWarn);
|
efAddOneConn(hc, conn->conn_name1, conn->conn_name2, conn, flags);
|
||||||
else
|
else
|
||||||
efHierSrArray(hc, conn, efAddOneConn, INT2CD(doWarn));
|
efHierSrArray(hc, conn, efAddOneConn, INT2CD(flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
@ -648,18 +659,23 @@ efAddOneConn(
|
||||||
char *name1, /* These are strings, not HierNames */
|
char *name1, /* These are strings, not HierNames */
|
||||||
char *name2,
|
char *name2,
|
||||||
Connection *conn,
|
Connection *conn,
|
||||||
bool doWarn)
|
int flags)
|
||||||
{
|
{
|
||||||
HashEntry *he1, *he2;
|
HashEntry *he1, *he2;
|
||||||
EFNode *node, *newnode;
|
EFNode *node, *newnode;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
bool doWarn = (flags & FLATNODE_DOWARN) ? TRUE : FALSE;
|
||||||
|
bool doHier = (flags & FLATNODE_HIER) ? TRUE : FALSE;
|
||||||
|
|
||||||
he1 = EFHNLook(hc->hc_hierName, name1, (doWarn) ? "connect(1)" : NULL);
|
he1 = EFHNLook(hc->hc_hierName, name1, (doWarn) ? "connect(1)" : NULL);
|
||||||
if (he1 == NULL)
|
if (he1 == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Adjust the resistance and capacitance of its corresponding node */
|
|
||||||
node = ((EFNodeName *) HashGetValue(he1))->efnn_node;
|
node = ((EFNodeName *) HashGetValue(he1))->efnn_node;
|
||||||
|
|
||||||
|
/* Adjust the resistance and capacitance of its corresponding node */
|
||||||
|
|
||||||
node->efnode_cap += conn->conn_cap;
|
node->efnode_cap += conn->conn_cap;
|
||||||
for (n = 0; n < efNumResistClasses; n++)
|
for (n = 0; n < efNumResistClasses; n++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,12 @@ extern void efHNRecord();
|
||||||
* variables cause nets named VDD and GND to become globals, which was
|
* variables cause nets named VDD and GND to become globals, which was
|
||||||
* not intended.
|
* not intended.
|
||||||
*
|
*
|
||||||
|
* Updated 1/2026: Also seems like a bad idea to treat the suffix "!"
|
||||||
|
* automatically as a global. By removing this, a global pin must be
|
||||||
|
* manually declared by putting it in the "globals" array variable.
|
||||||
|
* When not compiled with Tcl/Tk support, the original behavior is
|
||||||
|
* implemented.
|
||||||
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* TRUE if the name is a global.
|
* TRUE if the name is a global.
|
||||||
*
|
*
|
||||||
|
|
@ -99,12 +105,10 @@ EFHNIsGlob(hierName)
|
||||||
char *retstr;
|
char *retstr;
|
||||||
retstr = (char *)Tcl_GetVar2(magicinterp, "globals", hierName->hn_name,
|
retstr = (char *)Tcl_GetVar2(magicinterp, "globals", hierName->hn_name,
|
||||||
TCL_GLOBAL_ONLY);
|
TCL_GLOBAL_ONLY);
|
||||||
if (retstr != NULL) return TRUE;
|
return (retstr != NULL) ? TRUE : FALSE;
|
||||||
|
#else
|
||||||
// retstr = (char *)Tcl_GetVar(magicinterp, hierName->hn_name, TCL_GLOBAL_ONLY);
|
|
||||||
// if (retstr != NULL) return TRUE;
|
|
||||||
#endif
|
|
||||||
return hierName->hn_name[strlen(hierName->hn_name) - 1] == '!';
|
return hierName->hn_name[strlen(hierName->hn_name) - 1] == '!';
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -520,13 +524,22 @@ EFHNBest(hierName1, hierName2)
|
||||||
|
|
||||||
last1 = hierName1->hn_name[strlen(hierName1->hn_name) - 1];
|
last1 = hierName1->hn_name[strlen(hierName1->hn_name) - 1];
|
||||||
last2 = hierName2->hn_name[strlen(hierName2->hn_name) - 1];
|
last2 = hierName2->hn_name[strlen(hierName2->hn_name) - 1];
|
||||||
|
|
||||||
if (last1 != '!' || last2 != '!')
|
if (last1 != '!' || last2 != '!')
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
|
/* NOTE (Jan. 31, 2026): The handling of trailing "!" as a global
|
||||||
|
* is at best incorrect; the node output should not consider the
|
||||||
|
* ancestor hierarchy, but it does. I am disabling the check here,
|
||||||
|
* and treating all names as local. It could be reinstated, but
|
||||||
|
* I think global names are just a bad idea altogether.
|
||||||
|
*/
|
||||||
/* Prefer global over local names */
|
/* Prefer global over local names */
|
||||||
if (last1 == '!') return TRUE;
|
if (last1 == '!') return TRUE;
|
||||||
if (last2 == '!') return FALSE;
|
if (last2 == '!') return FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Neither name is global, so chose label over generated name */
|
/* Neither name is global, so choose label over generated name */
|
||||||
if (last1 != '#' && last2 == '#') return TRUE;
|
if (last1 != '#' && last2 == '#') return TRUE;
|
||||||
if (last1 == '#' && last2 != '#') return FALSE;
|
if (last1 == '#' && last2 != '#') return FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "commands/commands.h"
|
#include "commands/commands.h"
|
||||||
#include "database/database.h"
|
#include "database/database.h"
|
||||||
#include "extflat/extflat.h"
|
#include "extflat/extflat.h"
|
||||||
|
#include "extflat/extparse.h"
|
||||||
#include "extflat/EFint.h"
|
#include "extflat/EFint.h"
|
||||||
#include "extract/extract.h"
|
#include "extract/extract.h"
|
||||||
#include "extract/extractInt.h"
|
#include "extract/extractInt.h"
|
||||||
|
|
@ -53,53 +54,6 @@ const char * const extDevTable[] = {"fet", "mosfet", "asymmetric", "bjt", "devre
|
||||||
"dsubckt", "veriloga", NULL};
|
"dsubckt", "veriloga", NULL};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* The following table describes the kinds of lines
|
|
||||||
* that may be read in a .ext file.
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
ABSTRACT, ADJUST, ATTR, CAP, DEVICE, DIST, EQUIV, FET, KILLNODE, MERGE,
|
|
||||||
NODE, PARAMETERS, PORT, PRIMITIVE, RESISTOR, RESISTCLASS, RNODE, SCALE,
|
|
||||||
SUBCAP, SUBSTRATE, TECH, TIMESTAMP, USE, VERSION, EXT_STYLE
|
|
||||||
} Key;
|
|
||||||
|
|
||||||
static const struct
|
|
||||||
{
|
|
||||||
const char *k_name; /* Name of first token on line */
|
|
||||||
Key k_key; /* Internal name for token of this type */
|
|
||||||
int k_mintokens; /* Min total # of tokens on line of this type */
|
|
||||||
}
|
|
||||||
keyTable[] =
|
|
||||||
{
|
|
||||||
{"abstract", ABSTRACT, 0}, /* defines a LEF-like view */
|
|
||||||
{"adjust", ADJUST, 4},
|
|
||||||
{"attr", ATTR, 8},
|
|
||||||
{"cap", CAP, 4},
|
|
||||||
{"device", DEVICE, 11}, /* effectively replaces "fet" */
|
|
||||||
{"distance", DIST, 4},
|
|
||||||
{"equiv", EQUIV, 3},
|
|
||||||
{"fet", FET, 12}, /* for backwards compatibility */
|
|
||||||
{"killnode", KILLNODE, 2},
|
|
||||||
{"merge", MERGE, 3},
|
|
||||||
{"node", NODE, 7},
|
|
||||||
{"parameters", PARAMETERS, 3},
|
|
||||||
{"port", PORT, 8},
|
|
||||||
{"primitive", PRIMITIVE, 0}, /* defines a primitive device */
|
|
||||||
{"resist", RESISTOR, 4},
|
|
||||||
{"resistclasses", RESISTCLASS, 1},
|
|
||||||
{"rnode", RNODE, 5},
|
|
||||||
{"scale", SCALE, 4},
|
|
||||||
{"subcap", SUBCAP, 3},
|
|
||||||
{"substrate", SUBSTRATE, 3},
|
|
||||||
{"tech", TECH, 2},
|
|
||||||
{"timestamp", TIMESTAMP, 2},
|
|
||||||
{"use", USE, 9},
|
|
||||||
{"version", VERSION, 2},
|
|
||||||
{"style", EXT_STYLE, 2},
|
|
||||||
{0}
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Data shared with EFerror.c */
|
/* Data shared with EFerror.c */
|
||||||
char *efReadFileName; /* Name of file currently being read */
|
char *efReadFileName; /* Name of file currently being read */
|
||||||
int efReadLineNum; /* Current line number in above file */
|
int efReadLineNum; /* Current line number in above file */
|
||||||
|
|
@ -109,10 +63,6 @@ bool EFSaveLocs; /* If TRUE, save location of merged top-level nodes */
|
||||||
/* Data local to this file */
|
/* Data local to this file */
|
||||||
static bool efReadDef(Def *def, bool dosubckt, bool resist, bool noscale, bool toplevel, bool isspice);
|
static bool efReadDef(Def *def, bool dosubckt, bool resist, bool noscale, bool toplevel, bool isspice);
|
||||||
|
|
||||||
/* atoCap - convert a string to a EFCapValue */
|
|
||||||
#define atoCap(s) ((EFCapValue)atof(s))
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@
|
||||||
#include "extflat/EFtypes.h" /* EFCapValue, HierName, EFPerimArea, EFNode */
|
#include "extflat/EFtypes.h" /* EFCapValue, HierName, EFPerimArea, EFNode */
|
||||||
#include "extflat/EFint.h" /* Def, HierContext, Connection, Distance, CallArg */
|
#include "extflat/EFint.h" /* Def, HierContext, Connection, Distance, CallArg */
|
||||||
|
|
||||||
|
|
||||||
extern float EFScale; /* Scale factor to multiply all coords by */
|
extern float EFScale; /* Scale factor to multiply all coords by */
|
||||||
extern char *EFTech; /* Technology of extracted circuit */
|
extern char *EFTech; /* Technology of extracted circuit */
|
||||||
extern char *EFStyle; /* Extraction style of extracted circuit */
|
extern char *EFStyle; /* Extraction style of extracted circuit */
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* extparse.h
|
||||||
|
*
|
||||||
|
* Definitions for the .ext file parser. Relocated from EFread.c.
|
||||||
|
*
|
||||||
|
* *********************************************************************
|
||||||
|
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
||||||
|
* * Permission to use, copy, modify, and distribute this *
|
||||||
|
* * software and its documentation for any purpose and without *
|
||||||
|
* * fee is hereby granted, provided that the above copyright *
|
||||||
|
* * notice appear in all copies. The University of California *
|
||||||
|
* * makes no representations about the suitability of this *
|
||||||
|
* * software for any purpose. It is provided "as is" without *
|
||||||
|
* * express or implied warranty. Export of this software outside *
|
||||||
|
* * of the United States of America may require an export license. *
|
||||||
|
* *********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MAGIC__EXTFLAT__EXTPARSE_H
|
||||||
|
#define _MAGIC__EXTFLAT__EXTPARSE_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following table describes the kinds of lines
|
||||||
|
* that may be read in a .ext file.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ABSTRACT, ADJUST, ATTR, CAP, DEVICE, DIST, EQUIV, FET, KILLNODE, MERGE,
|
||||||
|
NODE, PARAMETERS, PORT, PRIMITIVE, RESISTOR, RESISTCLASS, RNODE, SCALE,
|
||||||
|
SUBCAP, SUBSTRATE, TECH, TIMESTAMP, USE, VERSION, EXT_STYLE
|
||||||
|
} Key;
|
||||||
|
|
||||||
|
static const struct
|
||||||
|
{
|
||||||
|
const char *k_name; /* Name of first token on line */
|
||||||
|
Key k_key; /* Internal name for token of this type */
|
||||||
|
int k_mintokens; /* Min total # of tokens on line of this type */
|
||||||
|
}
|
||||||
|
keyTable[] =
|
||||||
|
{
|
||||||
|
{"abstract", ABSTRACT, 0}, /* defines a LEF-like view */
|
||||||
|
{"adjust", ADJUST, 4},
|
||||||
|
{"attr", ATTR, 8},
|
||||||
|
{"cap", CAP, 4},
|
||||||
|
{"device", DEVICE, 11}, /* effectively replaces "fet" */
|
||||||
|
{"distance", DIST, 4},
|
||||||
|
{"equiv", EQUIV, 3},
|
||||||
|
{"fet", FET, 12}, /* for backwards compatibility */
|
||||||
|
{"killnode", KILLNODE, 2},
|
||||||
|
{"merge", MERGE, 3},
|
||||||
|
{"node", NODE, 7},
|
||||||
|
{"parameters", PARAMETERS, 3},
|
||||||
|
{"port", PORT, 8},
|
||||||
|
{"primitive", PRIMITIVE, 0}, /* defines a primitive device */
|
||||||
|
{"resist", RESISTOR, 4},
|
||||||
|
{"resistclasses", RESISTCLASS, 1},
|
||||||
|
{"rnode", RNODE, 5},
|
||||||
|
{"scale", SCALE, 4},
|
||||||
|
{"subcap", SUBCAP, 3},
|
||||||
|
{"substrate", SUBSTRATE, 3},
|
||||||
|
{"tech", TECH, 2},
|
||||||
|
{"timestamp", TIMESTAMP, 2},
|
||||||
|
{"use", USE, 9},
|
||||||
|
{"version", VERSION, 2},
|
||||||
|
{"style", EXT_STYLE, 2},
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* atoCap - convert a string to a EFCapValue */
|
||||||
|
#define atoCap(s) ((EFCapValue)atof(s))
|
||||||
|
|
||||||
|
extern int efReadLineNum; /* Current line number in the .ext file */
|
||||||
|
extern char *efReadFileName; /* Name of current .ext file being read */
|
||||||
|
|
||||||
|
#endif /* _MAGIC__EXTFLAT__EXTPARSE_H */
|
||||||
|
|
@ -713,14 +713,15 @@ extArrayNodeName(np, ha, et1, et2)
|
||||||
ExtTree *et1, *et2;
|
ExtTree *et1, *et2;
|
||||||
{
|
{
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
|
TileType dinfo;
|
||||||
|
|
||||||
tp = extNodeToTile(np, et1);
|
tp = extNodeToTile(np, et1, &dinfo);
|
||||||
if (tp && TiGetType(tp) != TT_SPACE && extHasRegion(tp, extUnInit))
|
if (tp && TiGetType(tp) != TT_SPACE && extHasRegion(tp, CLIENTDEFAULT))
|
||||||
return (extArrayTileToNode(tp, np->nreg_pnum, et1, ha, TRUE));
|
return (extArrayTileToNode(tp, dinfo, np->nreg_pnum, et1, ha, TRUE));
|
||||||
|
|
||||||
tp = extNodeToTile(np, et2);
|
tp = extNodeToTile(np, et2, &dinfo);
|
||||||
if (tp && TiGetType(tp) != TT_SPACE && extHasRegion(tp, extUnInit))
|
if (tp && TiGetType(tp) != TT_SPACE && extHasRegion(tp, CLIENTDEFAULT))
|
||||||
return (extArrayTileToNode(tp, np->nreg_pnum, et2, ha, TRUE));
|
return (extArrayTileToNode(tp, dinfo, np->nreg_pnum, et2, ha, TRUE));
|
||||||
|
|
||||||
return ("(none)");
|
return ("(none)");
|
||||||
}
|
}
|
||||||
|
|
@ -768,8 +769,9 @@ extArrayNodeName(np, ha, et1, et2)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
extArrayTileToNode(tp, pNum, et, ha, doHard)
|
extArrayTileToNode(tp, dinfo, pNum, et, ha, doHard)
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
|
TileType dinfo;
|
||||||
int pNum;
|
int pNum;
|
||||||
ExtTree *et;
|
ExtTree *et;
|
||||||
HierExtractArg *ha;
|
HierExtractArg *ha;
|
||||||
|
|
@ -791,15 +793,15 @@ extArrayTileToNode(tp, pNum, et, ha, doHard)
|
||||||
LabRegion *reg;
|
LabRegion *reg;
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
||||||
if (extHasRegion(tp, extUnInit))
|
if (extHasRegion(tp, CLIENTDEFAULT))
|
||||||
{
|
{
|
||||||
reg = (LabRegion *) extGetRegion(tp);
|
reg = (LabRegion *) ExtGetRegion(tp, dinfo);
|
||||||
if (reg->lreg_labels)
|
if (reg->lreg_labels)
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!DebugIsSet(extDebugID, extDebNoHard))
|
if (!DebugIsSet(extDebugID, extDebNoHard))
|
||||||
if ((reg = (LabRegion *) extArrayHardNode(tp, pNum, def, ha)))
|
if ((reg = (LabRegion *) extArrayHardNode(tp, dinfo, pNum, def, ha)))
|
||||||
goto found;
|
goto found;
|
||||||
|
|
||||||
/* Blew it */
|
/* Blew it */
|
||||||
|
|
@ -934,17 +936,23 @@ extArrayRange(dstp, lo, hi, prevRange, followRange)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
LabRegion *
|
LabRegion *
|
||||||
extArrayHardNode(tp, pNum, def, ha)
|
extArrayHardNode(tp, dinfo, pNum, def, ha)
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
|
TileType dinfo;
|
||||||
int pNum;
|
int pNum;
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
HierExtractArg *ha;
|
HierExtractArg *ha;
|
||||||
{
|
{
|
||||||
TileType type = TiGetType(tp);
|
TileType type;
|
||||||
char labelBuf[4096];
|
char labelBuf[4096];
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
HardWay arg;
|
HardWay arg;
|
||||||
|
|
||||||
|
if (IsSplit(tp))
|
||||||
|
type = (dinfo & TT_SIDE) ? TiGetRightType(tp) : TiGetLeftType(tp);
|
||||||
|
else
|
||||||
|
type = TiGetType(tp);
|
||||||
|
|
||||||
arg.hw_ha = ha;
|
arg.hw_ha = ha;
|
||||||
arg.hw_label = (Label *) NULL;
|
arg.hw_label = (Label *) NULL;
|
||||||
arg.hw_mask = DBPlaneTypes[pNum];
|
arg.hw_mask = DBPlaneTypes[pNum];
|
||||||
|
|
@ -971,7 +979,7 @@ extArrayHardNode(tp, pNum, def, ha)
|
||||||
LabRegion *lreg;
|
LabRegion *lreg;
|
||||||
LabelList *ll;
|
LabelList *ll;
|
||||||
|
|
||||||
lreg = (LabRegion *) extGetRegion(tp);
|
lreg = (LabRegion *) ExtGetRegion(tp, dinfo);
|
||||||
ll = (LabelList *) mallocMagic((unsigned) (sizeof (LabelList)));
|
ll = (LabelList *) mallocMagic((unsigned) (sizeof (LabelList)));
|
||||||
lreg->lreg_labels = ll;
|
lreg->lreg_labels = ll;
|
||||||
ll->ll_next = (LabelList *) NULL;
|
ll->ll_next = (LabelList *) NULL;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -46,20 +46,10 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "utils/main.h"
|
#include "utils/main.h"
|
||||||
#include "utils/undo.h"
|
#include "utils/undo.h"
|
||||||
|
|
||||||
/* --------------------------- Global data ---------------------------- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Value normally present in ti_client to indicate tiles that have not
|
|
||||||
* been marked with their associated region.
|
|
||||||
*/
|
|
||||||
ClientData extUnInit = (ClientData) CLIENTDEFAULT;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------ Data local to this file ------------------- */
|
/* ------------------------ Data local to this file ------------------- */
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
int extOutputUsesFunc();
|
int extOutputUsesFunc();
|
||||||
FILE *extFileOpen();
|
|
||||||
|
|
||||||
Plane* extCellFile();
|
Plane* extCellFile();
|
||||||
void extHeader();
|
void extHeader();
|
||||||
|
|
@ -105,7 +95,7 @@ ExtCell(def, outName, doLength)
|
||||||
if (def->cd_flags & CDNOEXTRACT)
|
if (def->cd_flags & CDNOEXTRACT)
|
||||||
return extPrepSubstrate(def);
|
return extPrepSubstrate(def);
|
||||||
|
|
||||||
f = extFileOpen(def, outName, "w", &filename);
|
f = ExtFileOpen(def, outName, "w", &filename);
|
||||||
|
|
||||||
TxPrintf("Extracting %s into %s:\n", def->cd_name, filename);
|
TxPrintf("Extracting %s into %s:\n", def->cd_name, filename);
|
||||||
|
|
||||||
|
|
@ -141,7 +131,7 @@ ExtCell(def, outName, doLength)
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* extFileOpen --
|
* ExtFileOpen --
|
||||||
*
|
*
|
||||||
* Open the .ext file corresponding to a .mag file.
|
* Open the .ext file corresponding to a .mag file.
|
||||||
* If def->cd_file is non-NULL, the .ext file is just def->cd_file with
|
* If def->cd_file is non-NULL, the .ext file is just def->cd_file with
|
||||||
|
|
@ -159,7 +149,7 @@ ExtCell(def, outName, doLength)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FILE *
|
FILE *
|
||||||
extFileOpen(def, file, mode, prealfile)
|
ExtFileOpen(def, file, mode, prealfile)
|
||||||
CellDef *def; /* Cell whose .ext file is to be written */
|
CellDef *def; /* Cell whose .ext file is to be written */
|
||||||
char *file; /* If non-NULL, open 'name'.ext; otherwise,
|
char *file; /* If non-NULL, open 'name'.ext; otherwise,
|
||||||
* derive filename from 'def' as described
|
* derive filename from 'def' as described
|
||||||
|
|
@ -495,7 +485,16 @@ extCellFile(def, f, doLength)
|
||||||
|
|
||||||
UndoDisable();
|
UndoDisable();
|
||||||
|
|
||||||
|
/* If "extract do unique" was specified, then make labels in the
|
||||||
|
* cell unique.
|
||||||
|
*/
|
||||||
|
if (ExtOptions & EXT_DOUNIQUE)
|
||||||
|
extUniqueCell(def, EXT_UNIQ_TEMP);
|
||||||
|
|
||||||
/* Prep any isolated substrate areas */
|
/* Prep any isolated substrate areas */
|
||||||
|
if (ExtOptions & EXT_DOEXTRESIST)
|
||||||
|
saveSub = extResPrepSubstrate(def);
|
||||||
|
else
|
||||||
saveSub = extPrepSubstrate(def);
|
saveSub = extPrepSubstrate(def);
|
||||||
|
|
||||||
/* Remove any label markers that were made by a previous extraction */
|
/* Remove any label markers that were made by a previous extraction */
|
||||||
|
|
@ -517,7 +516,7 @@ extCellFile(def, f, doLength)
|
||||||
|
|
||||||
/* Clean up from basic extraction */
|
/* Clean up from basic extraction */
|
||||||
if (reg) ExtFreeLabRegions((LabRegion *) reg);
|
if (reg) ExtFreeLabRegions((LabRegion *) reg);
|
||||||
ExtResetTiles(def, extUnInit);
|
ExtResetTiles(def, CLIENTDEFAULT);
|
||||||
|
|
||||||
/* Final pass: extract length information if desired */
|
/* Final pass: extract length information if desired */
|
||||||
if (!SigInterruptPending && doLength && (ExtOptions & EXT_DOLENGTH))
|
if (!SigInterruptPending && doLength && (ExtOptions & EXT_DOLENGTH))
|
||||||
|
|
@ -595,7 +594,7 @@ extHeader(def, f)
|
||||||
/* are to be passed to instances of the cell */
|
/* are to be passed to instances of the cell */
|
||||||
/* (created by defining property "parameter") */
|
/* (created by defining property "parameter") */
|
||||||
|
|
||||||
propvalue = (char *)DBPropGet(def, "parameter", &propfound);
|
propvalue = DBPropGetString(def, "parameter", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
// Use device parameter table to store the cell def parameters,
|
// Use device parameter table to store the cell def parameters,
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ typedef struct _ecs {
|
||||||
|
|
||||||
typedef struct _ecpls {
|
typedef struct _ecpls {
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
int plane_of_tile;
|
int plane_of_tile;
|
||||||
int plane_checked;
|
int plane_checked;
|
||||||
} extCoupleStruct;
|
} extCoupleStruct;
|
||||||
|
|
@ -311,8 +312,9 @@ extOutputCoupling(table, outFile)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extBasicOverlap(tile, ecs)
|
extBasicOverlap(tile, dinfo, ecs)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
extCapStruct *ecs;
|
extCapStruct *ecs;
|
||||||
{
|
{
|
||||||
int thisType;
|
int thisType;
|
||||||
|
|
@ -325,7 +327,7 @@ extBasicOverlap(tile, ecs)
|
||||||
extCoupleStruct ecpls;
|
extCoupleStruct ecpls;
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
thisType = (SplitSide(tile)) ? SplitRightType(tile) :
|
thisType = ((dinfo & TT_SIDE)) ? SplitRightType(tile) :
|
||||||
SplitLeftType(tile);
|
SplitLeftType(tile);
|
||||||
else
|
else
|
||||||
thisType = TiGetTypeExact(tile);
|
thisType = TiGetTypeExact(tile);
|
||||||
|
|
@ -344,6 +346,7 @@ extBasicOverlap(tile, ecs)
|
||||||
}
|
}
|
||||||
|
|
||||||
ecpls.tile = tile;
|
ecpls.tile = tile;
|
||||||
|
ecpls.dinfo = dinfo;
|
||||||
ecpls.plane_of_tile = thisPlane;
|
ecpls.plane_of_tile = thisPlane;
|
||||||
|
|
||||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||||
|
|
@ -410,8 +413,9 @@ struct sideoverlap
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
extAddOverlap(tbelow, ecpls)
|
extAddOverlap(tbelow, dinfo, ecpls)
|
||||||
Tile *tbelow;
|
Tile *tbelow;
|
||||||
|
TileType dinfo; /* unused, but needs to be handled */
|
||||||
extCoupleStruct *ecpls;
|
extCoupleStruct *ecpls;
|
||||||
{
|
{
|
||||||
int extSubtractOverlap(), extSubtractOverlap2();
|
int extSubtractOverlap(), extSubtractOverlap2();
|
||||||
|
|
@ -430,8 +434,8 @@ extAddOverlap(tbelow, ecpls)
|
||||||
/* subtract off any substrate (area) capacitance previously added */
|
/* subtract off any substrate (area) capacitance previously added */
|
||||||
/* (Correction made 4/29/04 by Tim from a tip by Jeff Sondeen). */
|
/* (Correction made 4/29/04 by Tim from a tip by Jeff Sondeen). */
|
||||||
|
|
||||||
rabove = (NodeRegion *) extGetRegion(tabove);
|
rabove = (NodeRegion *) ExtGetRegion(tabove, ecpls->dinfo);
|
||||||
rbelow = (NodeRegion *) extGetRegion(tbelow);
|
rbelow = (NodeRegion *) ExtGetRegion(tbelow, dinfo);
|
||||||
|
|
||||||
/* Quick check on validity of tile's ti_client record */
|
/* Quick check on validity of tile's ti_client record */
|
||||||
if (rbelow == (NodeRegion *)CLIENTDEFAULT) return 0;
|
if (rbelow == (NodeRegion *)CLIENTDEFAULT) return 0;
|
||||||
|
|
@ -448,8 +452,16 @@ extAddOverlap(tbelow, ecpls)
|
||||||
}
|
}
|
||||||
ov.o_area = (ov.o_clip.r_ytop - ov.o_clip.r_ybot)
|
ov.o_area = (ov.o_clip.r_ytop - ov.o_clip.r_ybot)
|
||||||
* (ov.o_clip.r_xtop - ov.o_clip.r_xbot);
|
* (ov.o_clip.r_xtop - ov.o_clip.r_xbot);
|
||||||
ta = TiGetType(tabove);
|
|
||||||
tb = TiGetType(tbelow);
|
if (IsSplit(tabove))
|
||||||
|
ta = (ecpls->dinfo & TT_SIDE) ? TiGetRightType(tabove) : TiGetLeftType(tabove);
|
||||||
|
else
|
||||||
|
ta = TiGetTypeExact(tabove);
|
||||||
|
|
||||||
|
if (IsSplit(tbelow))
|
||||||
|
tb = (dinfo & TT_SIDE) ? TiGetRightType(tbelow) : TiGetLeftType(tbelow);
|
||||||
|
else
|
||||||
|
tb = TiGetTypeExact(tbelow);
|
||||||
|
|
||||||
/* Revert any contacts to their residues */
|
/* Revert any contacts to their residues */
|
||||||
|
|
||||||
|
|
@ -539,8 +551,9 @@ extAddOverlap(tbelow, ecpls)
|
||||||
/* Simple overlap. The area of overlap is subtracted from ov->o_area */
|
/* Simple overlap. The area of overlap is subtracted from ov->o_area */
|
||||||
|
|
||||||
int
|
int
|
||||||
extSubtractOverlap(tile, ov)
|
extSubtractOverlap(tile, dinfo, ov)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
struct overlap *ov;
|
struct overlap *ov;
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
@ -549,6 +562,7 @@ extSubtractOverlap(tile, ov)
|
||||||
TITORECT(tile, &r);
|
TITORECT(tile, &r);
|
||||||
GEOCLIP(&r, &ov->o_clip);
|
GEOCLIP(&r, &ov->o_clip);
|
||||||
area = (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot);
|
area = (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot);
|
||||||
|
if (IsSplit(tile)) area /= 2;
|
||||||
if (area > 0)
|
if (area > 0)
|
||||||
ov->o_area -= area;
|
ov->o_area -= area;
|
||||||
|
|
||||||
|
|
@ -561,10 +575,12 @@ extSubtractOverlap(tile, ov)
|
||||||
/* shielding plane. */
|
/* shielding plane. */
|
||||||
|
|
||||||
int
|
int
|
||||||
extSubtractOverlap2(tile, ov)
|
extSubtractOverlap2(tile, dinfo, ov)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
struct overlap *ov;
|
struct overlap *ov;
|
||||||
{
|
{
|
||||||
|
TileType ttype;
|
||||||
struct overlap ovnew;
|
struct overlap ovnew;
|
||||||
int area, pNum;
|
int area, pNum;
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
@ -574,9 +590,16 @@ extSubtractOverlap2(tile, ov)
|
||||||
area = (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot);
|
area = (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot);
|
||||||
if (area <= 0)
|
if (area <= 0)
|
||||||
return (0);
|
return (0);
|
||||||
|
if (IsSplit(tile))
|
||||||
|
{
|
||||||
|
area /= 2;
|
||||||
|
ttype = (dinfo & TT_SIDE) ? TiGetRightType(tile) : TiGetLeftType(tile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ttype = TiGetTypeExact(tile);
|
||||||
|
|
||||||
/* This tile shields everything below */
|
/* This tile shields everything below */
|
||||||
if (TTMaskHasType(&ov->o_tmask, TiGetType(tile)))
|
if (TTMaskHasType(&ov->o_tmask, ttype))
|
||||||
{
|
{
|
||||||
ov->o_area -= area;
|
ov->o_area -= area;
|
||||||
return (0);
|
return (0);
|
||||||
|
|
@ -614,8 +637,9 @@ extSubtractOverlap2(tile, ov)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extSubtractSideOverlap(tile, sov)
|
extSubtractSideOverlap(tile, dinfo, sov)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
struct sideoverlap *sov;
|
struct sideoverlap *sov;
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
@ -691,24 +715,31 @@ extSubtractSideOverlap(tile, sov)
|
||||||
/* shielding plane. */
|
/* shielding plane. */
|
||||||
|
|
||||||
int
|
int
|
||||||
extSubtractSideOverlap2(tile, sov)
|
extSubtractSideOverlap2(tile, dinfo, sov)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
struct sideoverlap *sov;
|
struct sideoverlap *sov;
|
||||||
{
|
{
|
||||||
|
TileType ttype;
|
||||||
struct sideoverlap sovnew;
|
struct sideoverlap sovnew;
|
||||||
int area, pNum;
|
int area, pNum;
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
||||||
|
if (IsSplit(tile))
|
||||||
|
ttype = (dinfo & TT_SIDE) ? TiGetRightType(tile) : TiGetLeftType(tile);
|
||||||
|
else
|
||||||
|
ttype = TiGetTypeExact(tile);
|
||||||
|
|
||||||
TITORECT(tile, &r);
|
TITORECT(tile, &r);
|
||||||
GEOCLIP(&r, &sov->so_clip);
|
GEOCLIP(&r, &sov->so_clip);
|
||||||
area = (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot);
|
area = (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot);
|
||||||
if (area <= 0)
|
if (area <= 0) return (0);
|
||||||
return (0);
|
if (IsSplit(tile)) area /= 2;
|
||||||
|
|
||||||
/* This tile shields everything below */
|
/* This tile shields everything below */
|
||||||
if (TTMaskHasType(&sov->so_tmask, TiGetType(tile)))
|
if (TTMaskHasType(&sov->so_tmask, ttype))
|
||||||
{
|
{
|
||||||
extSubtractSideOverlap(tile, sov);
|
extSubtractSideOverlap(tile, dinfo, sov);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -764,15 +795,250 @@ extSubtractSideOverlap2(tile, sov)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extBasicCouple(tile, ecs)
|
extBasicCouple(tile, dinfo, ecs)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
extCapStruct *ecs;
|
extCapStruct *ecs;
|
||||||
{
|
{
|
||||||
(void) extEnumTilePerim(tile, &ExtCurStyle->exts_sideEdges[TiGetType(tile)],
|
TileType ttype;
|
||||||
|
|
||||||
|
if (IsSplit(tile))
|
||||||
|
ttype = (dinfo & TT_SIDE) ? TiGetRightType(tile) : TiGetLeftType(tile);
|
||||||
|
else
|
||||||
|
ttype = TiGetTypeExact(tile);
|
||||||
|
|
||||||
|
(void) extEnumTilePerim(tile, dinfo, &ExtCurStyle->exts_sideEdges[ttype],
|
||||||
ecs->plane, extAddCouple, (ClientData) ecs);
|
ecs->plane, extAddCouple, (ClientData) ecs);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* extGetBoundaryTypes ---
|
||||||
|
*
|
||||||
|
* Return the tile types of the boundary inside and outside type in the
|
||||||
|
* argument pointers. The routine takes care of deciding if either side
|
||||||
|
* of the boundary is a split tile, and choosing the correct type based
|
||||||
|
* on the direction of the boundary.
|
||||||
|
*
|
||||||
|
* Result:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* The tile types are passed by pointer reference in the arguments.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
extGetBoundaryTypes(Boundary *bp,
|
||||||
|
TileType *tin,
|
||||||
|
TileType *tout)
|
||||||
|
{
|
||||||
|
TileType loctin, loctout;
|
||||||
|
|
||||||
|
if (IsSplit(bp->b_inside))
|
||||||
|
{
|
||||||
|
switch (bp->b_direction)
|
||||||
|
{
|
||||||
|
case BD_LEFT:
|
||||||
|
loctin = TiGetLeftType(bp->b_inside);
|
||||||
|
break;
|
||||||
|
case BD_RIGHT:
|
||||||
|
loctin = TiGetRightType(bp->b_inside);
|
||||||
|
break;
|
||||||
|
case BD_TOP:
|
||||||
|
loctin = TiGetTopType(bp->b_inside);
|
||||||
|
break;
|
||||||
|
case BD_BOTTOM:
|
||||||
|
loctin = TiGetBottomType(bp->b_inside);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
loctin = TiGetTypeExact(bp->b_inside);
|
||||||
|
|
||||||
|
if (IsSplit(bp->b_outside))
|
||||||
|
{
|
||||||
|
switch (bp->b_direction)
|
||||||
|
{
|
||||||
|
case BD_LEFT:
|
||||||
|
loctout = TiGetRightType(bp->b_outside);
|
||||||
|
break;
|
||||||
|
case BD_RIGHT:
|
||||||
|
loctout = TiGetLeftType(bp->b_outside);
|
||||||
|
break;
|
||||||
|
case BD_TOP:
|
||||||
|
loctout = TiGetBottomType(bp->b_outside);
|
||||||
|
break;
|
||||||
|
case BD_BOTTOM:
|
||||||
|
loctout = TiGetTopType(bp->b_outside);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
loctout = TiGetTypeExact(bp->b_outside);
|
||||||
|
|
||||||
|
*tin = loctin;
|
||||||
|
*tout = loctout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* extGetBoundaryTypes2 ---
|
||||||
|
*
|
||||||
|
* Similar to extGetBoundaryTypes(), but where the tiles for which we
|
||||||
|
* want to get the tile type are not necessarily the ones in the boundary
|
||||||
|
* record; the boundary just provides the direction that determines which
|
||||||
|
* side the tile type is on, in the case of a split tile.
|
||||||
|
*
|
||||||
|
* Result:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* The tile types are passed by pointer reference in the arguments.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
extGetBoundaryTypes2(int bdir,
|
||||||
|
Tile *tbin,
|
||||||
|
Tile *tbout,
|
||||||
|
TileType *tin,
|
||||||
|
TileType *tout)
|
||||||
|
{
|
||||||
|
TileType loctin, loctout;
|
||||||
|
|
||||||
|
if (IsSplit(tbin))
|
||||||
|
{
|
||||||
|
switch (bdir)
|
||||||
|
{
|
||||||
|
case BD_LEFT:
|
||||||
|
loctin = TiGetLeftType(tbin);
|
||||||
|
break;
|
||||||
|
case BD_RIGHT:
|
||||||
|
loctin = TiGetRightType(tbin);
|
||||||
|
break;
|
||||||
|
case BD_TOP:
|
||||||
|
loctin = TiGetTopType(tbin);
|
||||||
|
break;
|
||||||
|
case BD_BOTTOM:
|
||||||
|
loctin = TiGetBottomType(tbin);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
loctin = TiGetTypeExact(tbin);
|
||||||
|
|
||||||
|
if (IsSplit(tbout))
|
||||||
|
{
|
||||||
|
switch (bdir)
|
||||||
|
{
|
||||||
|
case BD_LEFT:
|
||||||
|
loctout = TiGetRightType(tbout);
|
||||||
|
break;
|
||||||
|
case BD_RIGHT:
|
||||||
|
loctout = TiGetLeftType(tbout);
|
||||||
|
break;
|
||||||
|
case BD_TOP:
|
||||||
|
loctout = TiGetBottomType(tbout);
|
||||||
|
break;
|
||||||
|
case BD_BOTTOM:
|
||||||
|
loctout = TiGetTopType(tbout);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
loctout = TiGetTypeExact(tbout);
|
||||||
|
|
||||||
|
*tin = loctin;
|
||||||
|
*tout = loctout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* extGetBoundaryRegions ---
|
||||||
|
*
|
||||||
|
* Given a boundary direction and two tiles, one on the boundary inside
|
||||||
|
* and one on the boundary outside, find the two node regions associated
|
||||||
|
* with the facing sides of the two tiles.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* The tile types are passed by pointer reference in the arguments.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
extGetBoundaryRegions(int bdir,
|
||||||
|
Tile *tbin,
|
||||||
|
Tile *tbout,
|
||||||
|
NodeRegion **rinptr,
|
||||||
|
NodeRegion **routptr)
|
||||||
|
{
|
||||||
|
NodeRegion *locrin, *locrout;
|
||||||
|
|
||||||
|
if (IsSplit(tbin))
|
||||||
|
{
|
||||||
|
switch (bdir)
|
||||||
|
{
|
||||||
|
case BD_LEFT:
|
||||||
|
locrin = (NodeRegion *)ExtGetRegion(tbin, (TileType)0);
|
||||||
|
break;
|
||||||
|
case BD_RIGHT:
|
||||||
|
locrin = (NodeRegion *)ExtGetRegion(tbin, (TileType)TT_SIDE);
|
||||||
|
break;
|
||||||
|
case BD_TOP:
|
||||||
|
locrin = (NodeRegion *)ExtGetRegion(tbin,
|
||||||
|
TiGetTypeExact(tbin) & TT_DIRECTION ?
|
||||||
|
(TileType)TT_SIDE : (TileType)0);
|
||||||
|
break;
|
||||||
|
case BD_BOTTOM:
|
||||||
|
locrin = (NodeRegion *)ExtGetRegion(tbin,
|
||||||
|
TiGetTypeExact(tbin) & TT_DIRECTION ?
|
||||||
|
(TileType)0 : (TileType)TT_SIDE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
locrin = (NodeRegion *)ExtGetRegion(tbin, (TileType)0);
|
||||||
|
|
||||||
|
if (IsSplit(tbout))
|
||||||
|
{
|
||||||
|
switch (bdir)
|
||||||
|
{
|
||||||
|
case BD_LEFT:
|
||||||
|
locrout = (NodeRegion *)ExtGetRegion(tbout, (TileType)TT_SIDE);
|
||||||
|
break;
|
||||||
|
case BD_RIGHT:
|
||||||
|
locrout = (NodeRegion *)ExtGetRegion(tbout, (TileType)0);
|
||||||
|
break;
|
||||||
|
case BD_TOP:
|
||||||
|
locrout = (NodeRegion *)ExtGetRegion(tbout,
|
||||||
|
TiGetTypeExact(tbin) & TT_DIRECTION ?
|
||||||
|
(TileType)0 : (TileType)TT_SIDE);
|
||||||
|
break;
|
||||||
|
case BD_BOTTOM:
|
||||||
|
locrout = (NodeRegion *)ExtGetRegion(tbout,
|
||||||
|
TiGetTypeExact(tbin) & TT_DIRECTION ?
|
||||||
|
(TileType)TT_SIDE : (TileType)0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
locrout = (NodeRegion *)ExtGetRegion(tbout, (TileType)0);
|
||||||
|
|
||||||
|
*rinptr = locrin;
|
||||||
|
*routptr = locrout;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -808,7 +1074,7 @@ extAddCouple(bp, ecs)
|
||||||
Boundary *bp; /* Boundary being considered */
|
Boundary *bp; /* Boundary being considered */
|
||||||
extCapStruct *ecs;
|
extCapStruct *ecs;
|
||||||
{
|
{
|
||||||
TileType tin = TiGetType(bp->b_inside), tout = TiGetType(bp->b_outside);
|
TileType tin, tout;
|
||||||
int pNum;
|
int pNum;
|
||||||
PlaneMask pMask;
|
PlaneMask pMask;
|
||||||
Boundary bpCopy;
|
Boundary bpCopy;
|
||||||
|
|
@ -816,6 +1082,21 @@ extAddCouple(bp, ecs)
|
||||||
extSidewallStruct esws;
|
extSidewallStruct esws;
|
||||||
int distFringe;
|
int distFringe;
|
||||||
|
|
||||||
|
/* Non-Manhattan boundaries are not handled. This is
|
||||||
|
* future work to be done.
|
||||||
|
*/
|
||||||
|
switch (bp->b_direction)
|
||||||
|
{
|
||||||
|
case BD_NW:
|
||||||
|
case BD_NE:
|
||||||
|
case BD_SW:
|
||||||
|
case BD_SE:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the types on the inside and outside of the boundary */
|
||||||
|
extGetBoundaryTypes(bp, &tin, &tout);
|
||||||
|
|
||||||
/* Check here for a zero exts_sideCoupleOtherEdges mask.
|
/* Check here for a zero exts_sideCoupleOtherEdges mask.
|
||||||
* that handles cases such as FET types not being declared in
|
* that handles cases such as FET types not being declared in
|
||||||
* defaultperimeter, as the edge between poly and FET will be
|
* defaultperimeter, as the edge between poly and FET will be
|
||||||
|
|
@ -905,7 +1186,7 @@ extAddCouple(bp, ecs)
|
||||||
extSideBottom, bp, &esws);
|
extSideBottom, bp, &esws);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return (0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -936,9 +1217,10 @@ extRemoveSubcap(bp, clip, esws)
|
||||||
|
|
||||||
if (!esws->fringe_halo) return;
|
if (!esws->fringe_halo) return;
|
||||||
|
|
||||||
ta = TiGetType(bp->b_inside);
|
/* Get the types on the inside and outside of the boundary */
|
||||||
tb = TiGetType(bp->b_outside);
|
extGetBoundaryTypes(bp, &ta, &tb);
|
||||||
rbp = (NodeRegion *)extGetRegion(bp->b_inside);
|
|
||||||
|
rbp = (NodeRegion *)ExtGetRegion(bp->b_inside, (TileType)0);
|
||||||
|
|
||||||
if (bp->b_segment.r_xtop == bp->b_segment.r_xbot)
|
if (bp->b_segment.r_xtop == bp->b_segment.r_xbot)
|
||||||
length = bp->b_segment.r_ytop - bp->b_segment.r_ybot;
|
length = bp->b_segment.r_ytop - bp->b_segment.r_ybot;
|
||||||
|
|
@ -1007,6 +1289,14 @@ extFindOverlap(tp, area, esws)
|
||||||
TileType tin = TiGetType(bp->b_inside);
|
TileType tin = TiGetType(bp->b_inside);
|
||||||
TileType tout = TiGetType(bp->b_outside);
|
TileType tout = TiGetType(bp->b_outside);
|
||||||
|
|
||||||
|
/* Get residues
|
||||||
|
* (Note: Isn't it better to include contacts in the tables?)
|
||||||
|
*/
|
||||||
|
if (DBIsContact(tin))
|
||||||
|
tin = DBPlaneToResidue(tin, esws->plane_of_boundary);
|
||||||
|
if (DBIsContact(tout))
|
||||||
|
tout = DBPlaneToResidue(tout, esws->plane_of_boundary);
|
||||||
|
|
||||||
pMask = ExtCurStyle->exts_sideOverlapOtherPlanes[tin][tout];
|
pMask = ExtCurStyle->exts_sideOverlapOtherPlanes[tin][tout];
|
||||||
extOverlapDef = esws->def;
|
extOverlapDef = esws->def;
|
||||||
|
|
||||||
|
|
@ -1055,13 +1345,14 @@ extFindOverlap(tp, area, esws)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extSideOverlapHalo(tp, esws)
|
extSideOverlapHalo(tp, dinfo, esws)
|
||||||
Tile *tp; /* Overlapped tile */
|
Tile *tp; /* Overlapped tile */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
extSidewallStruct *esws; /* Overlapping edge and plane information */
|
extSidewallStruct *esws; /* Overlapping edge and plane information */
|
||||||
{
|
{
|
||||||
Boundary *bp = esws->bp; /* Overlapping edge */
|
Boundary *bp = esws->bp; /* Overlapping edge */
|
||||||
NodeRegion *rtp = (NodeRegion *) extGetRegion(tp);
|
NodeRegion *rtp = (NodeRegion *) ExtGetRegion(tp, dinfo);
|
||||||
NodeRegion *rbp = (NodeRegion *) extGetRegion(bp->b_inside);
|
NodeRegion *rbp = (NodeRegion *) ExtGetRegion(bp->b_inside, (TileType)0);
|
||||||
TileType ta, tb;
|
TileType ta, tb;
|
||||||
Rect tpr;
|
Rect tpr;
|
||||||
struct sideoverlap sov;
|
struct sideoverlap sov;
|
||||||
|
|
@ -1076,7 +1367,10 @@ extSideOverlapHalo(tp, esws)
|
||||||
|
|
||||||
/* Nothing to do for space tiles, so just return. */
|
/* Nothing to do for space tiles, so just return. */
|
||||||
/* (TO DO: Make sure TT_SPACE is removed from all exts_sideOverlapOtherTypes */
|
/* (TO DO: Make sure TT_SPACE is removed from all exts_sideOverlapOtherTypes */
|
||||||
tb = TiGetType(tp);
|
if (IsSplit(tp))
|
||||||
|
tb = (dinfo & TT_SIDE) ? TiGetRightType(tp) : TiGetLeftType(tp);
|
||||||
|
else
|
||||||
|
tb = TiGetTypeExact(tp);
|
||||||
if (tb == TT_SPACE) return (0);
|
if (tb == TT_SPACE) return (0);
|
||||||
|
|
||||||
/* Get the area of the coupling tile, and clip to the fringe area */
|
/* Get the area of the coupling tile, and clip to the fringe area */
|
||||||
|
|
@ -1152,7 +1446,7 @@ extSideOverlapHalo(tp, esws)
|
||||||
if (!PlaneMaskHasPlane(e->ec_pmask, esws->plane_checked)) continue;
|
if (!PlaneMaskHasPlane(e->ec_pmask, esws->plane_checked)) continue;
|
||||||
|
|
||||||
/* Does this rule "e" include the tile we found? */
|
/* Does this rule "e" include the tile we found? */
|
||||||
if (TTMaskHasType(&e->ec_near, TiGetType(tp)))
|
if (TTMaskHasType(&e->ec_near, tb))
|
||||||
{
|
{
|
||||||
/* We have a possible capacitor, but are the tiles shielded from
|
/* We have a possible capacitor, but are the tiles shielded from
|
||||||
* each other part of the way?
|
* each other part of the way?
|
||||||
|
|
@ -1282,13 +1576,14 @@ extSideOverlapHalo(tp, esws)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extSideOverlap(tp, esws)
|
extSideOverlap(tp, dinfo, esws)
|
||||||
Tile *tp; /* Overlapped tile */
|
Tile *tp; /* Overlapped tile */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
extSidewallStruct *esws; /* Overlapping edge and plane information */
|
extSidewallStruct *esws; /* Overlapping edge and plane information */
|
||||||
{
|
{
|
||||||
Boundary *bp = esws->bp; /* Overlapping edge */
|
Boundary *bp = esws->bp; /* Overlapping edge */
|
||||||
NodeRegion *rtp = (NodeRegion *) extGetRegion(tp);
|
NodeRegion *rtp = (NodeRegion *) ExtGetRegion(tp, dinfo);
|
||||||
NodeRegion *rbp = (NodeRegion *) extGetRegion(bp->b_inside);
|
NodeRegion *rbp = (NodeRegion *) ExtGetRegion(bp->b_inside, (TileType)0);
|
||||||
TileType ta, tb;
|
TileType ta, tb;
|
||||||
Rect tpr;
|
Rect tpr;
|
||||||
struct overlap ov;
|
struct overlap ov;
|
||||||
|
|
@ -1301,7 +1596,10 @@ extSideOverlap(tp, esws)
|
||||||
|
|
||||||
/* Nothing to do for space tiles, so just return. */
|
/* Nothing to do for space tiles, so just return. */
|
||||||
/* (TO DO: Make sure TT_SPACE is removed from all exts_sideOverlapOtherTypes */
|
/* (TO DO: Make sure TT_SPACE is removed from all exts_sideOverlapOtherTypes */
|
||||||
tb = TiGetType(tp);
|
if (IsSplit(tp))
|
||||||
|
tb = (dinfo & TT_SIDE) ? TiGetRightType(tp) : TiGetLeftType(tp);
|
||||||
|
else
|
||||||
|
tb = TiGetTypeExact(tp);
|
||||||
if (tb == TT_SPACE) return (0);
|
if (tb == TT_SPACE) return (0);
|
||||||
|
|
||||||
if (bp->b_segment.r_xtop == bp->b_segment.r_xbot)
|
if (bp->b_segment.r_xtop == bp->b_segment.r_xbot)
|
||||||
|
|
@ -1336,7 +1634,7 @@ extSideOverlap(tp, esws)
|
||||||
if (!PlaneMaskHasPlane(e->ec_pmask, esws->plane_checked)) continue;
|
if (!PlaneMaskHasPlane(e->ec_pmask, esws->plane_checked)) continue;
|
||||||
|
|
||||||
/* Does this rule "e" include the tile we found? */
|
/* Does this rule "e" include the tile we found? */
|
||||||
if (TTMaskHasType(&e->ec_near, TiGetType(tp)))
|
if (TTMaskHasType(&e->ec_near, tb))
|
||||||
{
|
{
|
||||||
/* We have a possible capacitor, but are the tiles shielded from
|
/* We have a possible capacitor, but are the tiles shielded from
|
||||||
* each other part of the way?
|
* each other part of the way?
|
||||||
|
|
@ -1478,11 +1776,7 @@ extWalkTop(area, mask, func, bp, esws)
|
||||||
tp = tile;
|
tp = tile;
|
||||||
while (RIGHT(tp) > area->r_xbot)
|
while (RIGHT(tp) > area->r_xbot)
|
||||||
{
|
{
|
||||||
if (IsSplit(tp))
|
ttype = TiGetBottomType(tp);
|
||||||
ttype = (SplitSide(tp)) ? SplitRightType(tp) : SplitLeftType(tp);
|
|
||||||
else
|
|
||||||
ttype = TiGetTypeExact(tp);
|
|
||||||
|
|
||||||
if (TTMaskHasType(mask, ttype))
|
if (TTMaskHasType(mask, ttype))
|
||||||
{
|
{
|
||||||
bool lookLeft, lookRight;
|
bool lookLeft, lookRight;
|
||||||
|
|
@ -1590,11 +1884,7 @@ extWalkBottom(area, mask, func, bp, esws)
|
||||||
tp = tile;
|
tp = tile;
|
||||||
while (LEFT(tp) < area->r_xtop)
|
while (LEFT(tp) < area->r_xtop)
|
||||||
{
|
{
|
||||||
if (IsSplit(tp))
|
ttype = TiGetTopType(tp);
|
||||||
ttype = (SplitSide(tp)) ? SplitRightType(tp) : SplitLeftType(tp);
|
|
||||||
else
|
|
||||||
ttype = TiGetTypeExact(tp);
|
|
||||||
|
|
||||||
if (TTMaskHasType(mask, ttype))
|
if (TTMaskHasType(mask, ttype))
|
||||||
{
|
{
|
||||||
bool lookLeft, lookRight;
|
bool lookLeft, lookRight;
|
||||||
|
|
@ -1702,11 +1992,7 @@ extWalkRight(area, mask, func, bp, esws)
|
||||||
tp = tile;
|
tp = tile;
|
||||||
while (TOP(tp) > area->r_ybot)
|
while (TOP(tp) > area->r_ybot)
|
||||||
{
|
{
|
||||||
if (IsSplit(tp))
|
ttype = TiGetLeftType(tp);
|
||||||
ttype = (SplitSide(tp)) ? SplitRightType(tp) : SplitLeftType(tp);
|
|
||||||
else
|
|
||||||
ttype = TiGetTypeExact(tp);
|
|
||||||
|
|
||||||
if (TTMaskHasType(mask, ttype))
|
if (TTMaskHasType(mask, ttype))
|
||||||
{
|
{
|
||||||
bool lookDown, lookUp;
|
bool lookDown, lookUp;
|
||||||
|
|
@ -1814,11 +2100,7 @@ extWalkLeft(area, mask, func, bp, esws)
|
||||||
tp = tile;
|
tp = tile;
|
||||||
while (BOTTOM(tp) < area->r_ytop)
|
while (BOTTOM(tp) < area->r_ytop)
|
||||||
{
|
{
|
||||||
if (IsSplit(tp))
|
ttype = TiGetRightType(tp);
|
||||||
ttype = (SplitSide(tp)) ? SplitRightType(tp) : SplitLeftType(tp);
|
|
||||||
else
|
|
||||||
ttype = TiGetTypeExact(tp);
|
|
||||||
|
|
||||||
if (TTMaskHasType(mask, ttype))
|
if (TTMaskHasType(mask, ttype))
|
||||||
{
|
{
|
||||||
bool lookDown, lookUp;
|
bool lookDown, lookUp;
|
||||||
|
|
@ -1917,11 +2199,13 @@ extSideLeft(tpfar, bp, esws)
|
||||||
Boundary *bp;
|
Boundary *bp;
|
||||||
extSidewallStruct *esws;
|
extSidewallStruct *esws;
|
||||||
{
|
{
|
||||||
NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside);
|
NodeRegion *rinside, *rfar;
|
||||||
NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar);
|
|
||||||
Tile *tpnear;
|
Tile *tpnear;
|
||||||
|
|
||||||
if (rfar != (NodeRegion *) extUnInit && rfar != rinside)
|
/* Get the regions associated with bp->b_inside and tpfar */
|
||||||
|
extGetBoundaryRegions(bp->b_direction, bp->b_inside, tpfar, &rinside, &rfar);
|
||||||
|
|
||||||
|
if (rfar != (NodeRegion *)CLIENTDEFAULT && rfar != rinside)
|
||||||
{
|
{
|
||||||
int sep = bp->b_segment.r_xbot - RIGHT(tpfar);
|
int sep = bp->b_segment.r_xbot - RIGHT(tpfar);
|
||||||
int limit = MAX(bp->b_segment.r_ybot, BOTTOM(tpfar));
|
int limit = MAX(bp->b_segment.r_ybot, BOTTOM(tpfar));
|
||||||
|
|
@ -1931,8 +2215,8 @@ extSideLeft(tpfar, bp, esws)
|
||||||
{
|
{
|
||||||
int overlap = MIN(TOP(tpnear), start) - MAX(BOTTOM(tpnear), limit);
|
int overlap = MIN(TOP(tpnear), start) - MAX(BOTTOM(tpnear), limit);
|
||||||
if (overlap > 0)
|
if (overlap > 0)
|
||||||
extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep,
|
extSideCommon(rinside, rfar, tpnear, tpfar, bp->b_direction,
|
||||||
esws->extCoupleList);
|
overlap, sep, esws->extCoupleList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1967,11 +2251,13 @@ extSideRight(tpfar, bp, esws)
|
||||||
Boundary *bp;
|
Boundary *bp;
|
||||||
extSidewallStruct *esws;
|
extSidewallStruct *esws;
|
||||||
{
|
{
|
||||||
NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside);
|
NodeRegion *rinside, *rfar;
|
||||||
NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar);
|
|
||||||
Tile *tpnear;
|
Tile *tpnear;
|
||||||
|
|
||||||
if (rfar != (NodeRegion *) extUnInit && rfar != rinside)
|
/* Get the regions associated with bp->b_inside and tpfar */
|
||||||
|
extGetBoundaryRegions(bp->b_direction, bp->b_inside, tpfar, &rinside, &rfar);
|
||||||
|
|
||||||
|
if (rfar != (NodeRegion *) CLIENTDEFAULT && rfar != rinside)
|
||||||
{
|
{
|
||||||
int sep = LEFT(tpfar) - bp->b_segment.r_xtop;
|
int sep = LEFT(tpfar) - bp->b_segment.r_xtop;
|
||||||
int limit = MIN(bp->b_segment.r_ytop, TOP(tpfar));
|
int limit = MIN(bp->b_segment.r_ytop, TOP(tpfar));
|
||||||
|
|
@ -1981,8 +2267,8 @@ extSideRight(tpfar, bp, esws)
|
||||||
{
|
{
|
||||||
int overlap = MIN(TOP(tpnear), limit) - MAX(BOTTOM(tpnear), start);
|
int overlap = MIN(TOP(tpnear), limit) - MAX(BOTTOM(tpnear), start);
|
||||||
if (overlap > 0)
|
if (overlap > 0)
|
||||||
extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep,
|
extSideCommon(rinside, rfar, tpnear, tpfar, bp->b_direction,
|
||||||
esws->extCoupleList);
|
overlap, sep, esws->extCoupleList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2017,11 +2303,13 @@ extSideTop(tpfar, bp, esws)
|
||||||
Boundary *bp;
|
Boundary *bp;
|
||||||
extSidewallStruct *esws;
|
extSidewallStruct *esws;
|
||||||
{
|
{
|
||||||
NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside);
|
NodeRegion *rinside, *rfar;
|
||||||
NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar);
|
|
||||||
Tile *tpnear;
|
Tile *tpnear;
|
||||||
|
|
||||||
if (rfar != (NodeRegion *) extUnInit && rfar != rinside)
|
/* Get the regions associated with bp->b_inside and tpfar */
|
||||||
|
extGetBoundaryRegions(bp->b_direction, bp->b_inside, tpfar, &rinside, &rfar);
|
||||||
|
|
||||||
|
if (rfar != (NodeRegion *) CLIENTDEFAULT && rfar != rinside)
|
||||||
{
|
{
|
||||||
int sep = BOTTOM(tpfar) - bp->b_segment.r_ytop;
|
int sep = BOTTOM(tpfar) - bp->b_segment.r_ytop;
|
||||||
int limit = MIN(bp->b_segment.r_xtop, RIGHT(tpfar));
|
int limit = MIN(bp->b_segment.r_xtop, RIGHT(tpfar));
|
||||||
|
|
@ -2031,8 +2319,8 @@ extSideTop(tpfar, bp, esws)
|
||||||
{
|
{
|
||||||
int overlap = MIN(RIGHT(tpnear), limit) - MAX(LEFT(tpnear), start);
|
int overlap = MIN(RIGHT(tpnear), limit) - MAX(LEFT(tpnear), start);
|
||||||
if (overlap > 0)
|
if (overlap > 0)
|
||||||
extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep,
|
extSideCommon(rinside, rfar, tpnear, tpfar, bp->b_direction,
|
||||||
esws->extCoupleList);
|
overlap, sep, esws->extCoupleList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2067,11 +2355,13 @@ extSideBottom(tpfar, bp, esws)
|
||||||
Boundary *bp;
|
Boundary *bp;
|
||||||
extSidewallStruct *esws;
|
extSidewallStruct *esws;
|
||||||
{
|
{
|
||||||
NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside);
|
NodeRegion *rinside, *rfar;
|
||||||
NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar);
|
|
||||||
Tile *tpnear;
|
Tile *tpnear;
|
||||||
|
|
||||||
if (rfar != (NodeRegion *) extUnInit && rfar != rinside)
|
/* Get the regions associated with bp->b_inside and tpfar */
|
||||||
|
extGetBoundaryRegions(bp->b_direction, bp->b_inside, tpfar, &rinside, &rfar);
|
||||||
|
|
||||||
|
if (rfar != (NodeRegion *) CLIENTDEFAULT && rfar != rinside)
|
||||||
{
|
{
|
||||||
int sep = bp->b_segment.r_ybot - TOP(tpfar);
|
int sep = bp->b_segment.r_ybot - TOP(tpfar);
|
||||||
int limit = MAX(bp->b_segment.r_xbot, LEFT(tpfar));
|
int limit = MAX(bp->b_segment.r_xbot, LEFT(tpfar));
|
||||||
|
|
@ -2081,8 +2371,8 @@ extSideBottom(tpfar, bp, esws)
|
||||||
{
|
{
|
||||||
int overlap = MIN(RIGHT(tpnear), start) - MAX(LEFT(tpnear), limit);
|
int overlap = MIN(RIGHT(tpnear), start) - MAX(LEFT(tpnear), limit);
|
||||||
if (overlap > 0)
|
if (overlap > 0)
|
||||||
extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep,
|
extSideCommon(rinside, rfar, tpnear, tpfar, bp->b_direction,
|
||||||
esws->extCoupleList);
|
overlap, sep, esws->extCoupleList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2096,7 +2386,7 @@ extSideBottom(tpfar, bp, esws)
|
||||||
*
|
*
|
||||||
* Perform the actual update to the hash table entry for
|
* Perform the actual update to the hash table entry for
|
||||||
* the regions 'rinside' and 'rfar'. We assume that neither
|
* the regions 'rinside' and 'rfar'. We assume that neither
|
||||||
* 'rinside' nor 'rfar' are extUnInit, and further that they
|
* 'rinside' nor 'rfar' are CLIENTDEFAULT, and further that they
|
||||||
* are not equal.
|
* are not equal.
|
||||||
*
|
*
|
||||||
* Walk along the rules in extCoupleList, applying the appropriate
|
* Walk along the rules in extCoupleList, applying the appropriate
|
||||||
|
|
@ -2113,20 +2403,24 @@ extSideBottom(tpfar, bp, esws)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep, extCoupleList)
|
extSideCommon(rinside, rfar, tpnear, tpfar, bdir, overlap, sep, extCoupleList)
|
||||||
NodeRegion *rinside, *rfar; /* Both must be valid */
|
NodeRegion *rinside, *rfar; /* Both must be valid */
|
||||||
Tile *tpnear, *tpfar; /* Tiles on near and far side of edge */
|
Tile *tpnear, *tpfar; /* Tiles on near and far side of edge */
|
||||||
|
int bdir; /* Boundary direction */
|
||||||
int overlap, sep; /* Overlap of this edge with original one,
|
int overlap, sep; /* Overlap of this edge with original one,
|
||||||
* and distance between the two.
|
* and distance between the two.
|
||||||
*/
|
*/
|
||||||
EdgeCap *extCoupleList; /* List of sidewall capacitance rules */
|
EdgeCap *extCoupleList; /* List of sidewall capacitance rules */
|
||||||
{
|
{
|
||||||
TileType near = TiGetType(tpnear), far = TiGetType(tpfar);
|
TileType near, far;
|
||||||
HashEntry *he;
|
HashEntry *he;
|
||||||
EdgeCap *e;
|
EdgeCap *e;
|
||||||
CoupleKey ck;
|
CoupleKey ck;
|
||||||
CapValue cap;
|
CapValue cap;
|
||||||
|
|
||||||
|
/* Get the tile types of tpnear and tpfar */
|
||||||
|
extGetBoundaryTypes2(bdir, tpnear, tpfar, &near, &far);
|
||||||
|
|
||||||
if (rinside < rfar) ck.ck_1 = rinside, ck.ck_2 = rfar;
|
if (rinside < rfar) ck.ck_1 = rinside, ck.ck_2 = rfar;
|
||||||
else ck.ck_1 = rfar, ck.ck_2 = rinside;
|
else ck.ck_1 = rfar, ck.ck_2 = rinside;
|
||||||
he = HashFind(extCoupleHashPtr, (char *) &ck);
|
he = HashFind(extCoupleHashPtr, (char *) &ck);
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,9 @@ bool extHardSetLabel();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ExtRegion *
|
ExtRegion *
|
||||||
extLabFirst(tile, arg)
|
extLabFirst(tile, dinfo, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
FindRegion *arg;
|
FindRegion *arg;
|
||||||
{
|
{
|
||||||
TransRegion *reg;
|
TransRegion *reg;
|
||||||
|
|
@ -82,6 +83,11 @@ extLabFirst(tile, arg)
|
||||||
reg->treg_pnum = DBNumPlanes;
|
reg->treg_pnum = DBNumPlanes;
|
||||||
reg->treg_area = DBNumPlanes;
|
reg->treg_area = DBNumPlanes;
|
||||||
reg->treg_tile = tile;
|
reg->treg_tile = tile;
|
||||||
|
reg->treg_dinfo = dinfo;
|
||||||
|
|
||||||
|
/* Setting treg_pnum to DBNumPlanes ensures that treg_ll and treg_type
|
||||||
|
* will be set for identifying the node when extSetNodeNum() is called.
|
||||||
|
*/
|
||||||
|
|
||||||
/* Prepend it to the region list */
|
/* Prepend it to the region list */
|
||||||
reg->treg_next = (TransRegion *) arg->fra_region;
|
reg->treg_next = (TransRegion *) arg->fra_region;
|
||||||
|
|
@ -91,25 +97,16 @@ extLabFirst(tile, arg)
|
||||||
|
|
||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
int
|
int
|
||||||
extLabEach(tile, pNum, arg)
|
extLabEach(tile, dinfo, pNum, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
int pNum;
|
int pNum;
|
||||||
FindRegion *arg;
|
FindRegion *arg;
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Avoid setting the region's tile pointer to a split tile if we can */
|
|
||||||
/*
|
|
||||||
if (IsSplit(reg->treg_tile) && !IsSplit(tile))
|
|
||||||
{
|
|
||||||
reg->treg_tile = tile;
|
|
||||||
reg->treg_area = pNum;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
TransRegion *reg = (TransRegion *) arg->fra_region;
|
TransRegion *reg = (TransRegion *) arg->fra_region;
|
||||||
|
|
||||||
if (reg->treg_area == DBNumPlanes) reg->treg_area = pNum;
|
if (reg->treg_area == DBNumPlanes) reg->treg_area = pNum;
|
||||||
extSetNodeNum((LabRegion *)reg, pNum, tile);
|
extSetNodeNum((LabRegion *)reg, pNum, tile, dinfo);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,7 +169,7 @@ extHardProc(scx, arg)
|
||||||
CellDef *def = scx->scx_use->cu_def;
|
CellDef *def = scx->scx_use->cu_def;
|
||||||
TransRegion *reg;
|
TransRegion *reg;
|
||||||
TransRegion *labRegList;
|
TransRegion *labRegList;
|
||||||
LabelList *subList;
|
LabelList *subList = NULL;
|
||||||
char *savenext;
|
char *savenext;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
|
@ -203,7 +200,7 @@ extHardProc(scx, arg)
|
||||||
* single child.
|
* single child.
|
||||||
*/
|
*/
|
||||||
labRegList = (TransRegion *) ExtFindRegions(def, &scx->scx_area,
|
labRegList = (TransRegion *) ExtFindRegions(def, &scx->scx_area,
|
||||||
&arg->hw_mask, ExtCurStyle->exts_nodeConn, extUnInit,
|
&arg->hw_mask, ExtCurStyle->exts_nodeConn,
|
||||||
extLabFirst, extLabEach);
|
extLabFirst, extLabEach);
|
||||||
if (labRegList)
|
if (labRegList)
|
||||||
{
|
{
|
||||||
|
|
@ -240,7 +237,8 @@ extHardProc(scx, arg)
|
||||||
*/
|
*/
|
||||||
if (ExtCurStyle->exts_globSubstrateDefaultType != -1)
|
if (ExtCurStyle->exts_globSubstrateDefaultType != -1)
|
||||||
for (reg = labRegList; reg; reg = reg->treg_next)
|
for (reg = labRegList; reg; reg = reg->treg_next)
|
||||||
if (TTMaskHasType(&ExtCurStyle->exts_globSubstrateTypes, reg->treg_type))
|
if (TTMaskHasType(&ExtCurStyle->exts_globSubstrateTypes,
|
||||||
|
reg->treg_type & TT_LEFTMASK))
|
||||||
if (reg->treg_pnum != ExtCurStyle->exts_globSubstratePlane)
|
if (reg->treg_pnum != ExtCurStyle->exts_globSubstratePlane)
|
||||||
{
|
{
|
||||||
reg->treg_labels = subList;
|
reg->treg_labels = subList;
|
||||||
|
|
@ -261,6 +259,7 @@ extHardProc(scx, arg)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
success:
|
success:
|
||||||
|
if (subList != NULL) freeMagic(subList);
|
||||||
extHardFreeAll(def, labRegList);
|
extHardFreeAll(def, labRegList);
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
|
||||||
|
|
@ -338,7 +337,7 @@ extHardSetLabel(scx, reg, arg)
|
||||||
tp = PlaneGetHint(scx->scx_use->cu_def->cd_planes[pNum]);
|
tp = PlaneGetHint(scx->scx_use->cu_def->cd_planes[pNum]);
|
||||||
GOTOPOINT(tp, &r.r_ll);
|
GOTOPOINT(tp, &r.r_ll);
|
||||||
PlaneSetHint(scx->scx_use->cu_def->cd_planes[pNum], tp);
|
PlaneSetHint(scx->scx_use->cu_def->cd_planes[pNum], tp);
|
||||||
if ((TransRegion *)extGetRegion(tp) == reg)
|
if ((TransRegion *)ExtGetRegion(tp, (TileType)0) == reg)
|
||||||
{
|
{
|
||||||
/* found an OK point */
|
/* found an OK point */
|
||||||
r.r_ur.p_x =r.r_ll.p_x+1;
|
r.r_ur.p_x =r.r_ll.p_x+1;
|
||||||
|
|
@ -347,7 +346,7 @@ extHardSetLabel(scx, reg, arg)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GOTOPOINT(tp, &r.r_ur);
|
GOTOPOINT(tp, &r.r_ur);
|
||||||
if ((TransRegion *)extGetRegion(tp) == reg)
|
if ((TransRegion *)ExtGetRegion(tp, (TileType)0) == reg)
|
||||||
{
|
{
|
||||||
r.r_ll = r.r_ur;
|
r.r_ll = r.r_ur;
|
||||||
}
|
}
|
||||||
|
|
@ -493,17 +492,17 @@ extHardFreeAll(def, tReg)
|
||||||
arg.fra_connectsTo = ExtCurStyle->exts_nodeConn;
|
arg.fra_connectsTo = ExtCurStyle->exts_nodeConn;
|
||||||
arg.fra_def = def;
|
arg.fra_def = def;
|
||||||
arg.fra_each = (int (*)()) NULL;
|
arg.fra_each = (int (*)()) NULL;
|
||||||
arg.fra_region = (ExtRegion *) extUnInit;
|
arg.fra_region = (ExtRegion *) CLIENTDEFAULT;
|
||||||
|
|
||||||
free_magic1_t mm1 = freeMagic1_init();
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (reg = tReg; reg; reg = reg->treg_next)
|
for (reg = tReg; reg; reg = reg->treg_next)
|
||||||
{
|
{
|
||||||
/* Reset all ti_client fields to extUnInit */
|
/* Reset all ti_client fields to CLIENTDEFAULT */
|
||||||
arg.fra_uninit = (ClientData) reg;
|
arg.fra_uninit = (ClientData) reg;
|
||||||
if (reg->treg_tile)
|
if (reg->treg_tile)
|
||||||
{
|
{
|
||||||
arg.fra_pNum = reg->treg_area;
|
arg.fra_pNum = reg->treg_area;
|
||||||
ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg);
|
ExtFindNeighbors(reg->treg_tile, reg->treg_dinfo, arg.fra_pNum, &arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free all LabelLists and then the region */
|
/* Free all LabelLists and then the region */
|
||||||
|
|
|
||||||
|
|
@ -60,34 +60,93 @@ int extHierConnectFunc2();
|
||||||
int extHierConnectFunc3();
|
int extHierConnectFunc3();
|
||||||
Node *extHierNewNode();
|
Node *extHierNewNode();
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
/*
|
||||||
/* extHierSubShieldFunc -- */
|
*----------------------------------------------------------------------
|
||||||
/* */
|
*
|
||||||
/* Simple callback function for extHierSubstrate() that halts the */
|
* extTestNMInteract --
|
||||||
/* search if any substrate shield type is found in the search area */
|
*
|
||||||
/* */
|
* Determine if two tiles overlap, including split tiles. Since
|
||||||
/*----------------------------------------------------------------------*/
|
* this is a much more complicated check than the simple overlap
|
||||||
|
* of two rectangular tiles, it is assumed that at least tile t1
|
||||||
|
* is a split tile, and does not check for simple rectangular
|
||||||
|
* overlap. The insideness test is the same used by
|
||||||
|
* DBSrPaintNMArea(), but in the context of extHierConnectFunc,
|
||||||
|
* the two tiles are already known, so just run the equations.
|
||||||
|
* Because this test is for electrical connectivity, touching
|
||||||
|
* shapes are equivalent to overlapping shapes.
|
||||||
|
*
|
||||||
|
* The information about which side of a triangular tile is to
|
||||||
|
* be checked for overlap is in the "dinfo" argument corresponding
|
||||||
|
* to the tile. If the tile is not a split tile, then "dinfo" is
|
||||||
|
* ignored.
|
||||||
|
*
|
||||||
|
* Tile t1 is always a split tile. Tile t2 may be a simple Manhattan
|
||||||
|
* tile, in which case the possibility that t2 has "infinite" width
|
||||||
|
* or height must be considered.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* TRUE if the tiles overlap or touch, FALSE if not.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
*----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool extTestNMInteract(Tile *t1, TileType di1, Tile *t2, TileType di2)
|
||||||
|
{
|
||||||
|
Rect rect1;
|
||||||
|
TileType tt1;
|
||||||
|
|
||||||
|
/* Turn the first tile into a Rect and a TileType containing
|
||||||
|
* the information about both diagonal and split side, and
|
||||||
|
* then call the function DBTestNMInteract() which is used by
|
||||||
|
* DBSrPaintNMArea() to determine interaction between non-
|
||||||
|
* Manhattan areas. Note that DBTestNMInteract() is called
|
||||||
|
* with the overlap_only flag set to FALSE because this should
|
||||||
|
* test for shapes either overlapping *or* touching.
|
||||||
|
*/
|
||||||
|
|
||||||
|
TiToRect(t1, &rect1);
|
||||||
|
tt1 = TiGetTypeExact(t1) | di1;
|
||||||
|
|
||||||
|
return DBTestNMInteract(&rect1, tt1, t2, di2, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*----------------------------------------------------------------------
|
||||||
|
* extHierSubShieldFunc --
|
||||||
|
*
|
||||||
|
* Simple callback function for extHierSubstrate() that halts the
|
||||||
|
* search if any substrate shield type is found in the search area
|
||||||
|
*
|
||||||
|
*----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extHierSubShieldFunc(tile)
|
extHierSubShieldFunc(tile, dinfo, clientdata)
|
||||||
Tile *tile;
|
Tile *tile; /* (unused) */
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
|
ClientData clientdata; /* (unused) */
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------*/
|
/*
|
||||||
/* extHierSubstrate -- */
|
*----------------------------------------------------------------------
|
||||||
/* */
|
* extHierSubstrate --
|
||||||
/* Find the substrate node of a child cell and make a connection */
|
*
|
||||||
/* between parent and child substrates. If either of the */
|
* Find the substrate node of a child cell and make a connection
|
||||||
/* substrate nodes is already in the hash table, then the table */
|
* between parent and child substrates. If either of the
|
||||||
/* will be updated as necessary. */
|
* substrate nodes is already in the hash table, then the table
|
||||||
/* */
|
* will be updated as necessary.
|
||||||
/* This function also determines if a child cell's substrate is */
|
*
|
||||||
/* isolated by a substrate shield type, in which case no merge is */
|
* This function also determines if a child cell's substrate is
|
||||||
/* done. */
|
* isolated by a substrate shield type, in which case no merge is
|
||||||
/* */
|
* done.
|
||||||
/*----------------------------------------------------------------------*/
|
*
|
||||||
|
*----------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
extHierSubstrate(ha, use, x, y)
|
extHierSubstrate(ha, use, x, y)
|
||||||
|
|
@ -124,6 +183,7 @@ extHierSubstrate(ha, use, x, y)
|
||||||
/* The parent def's substrate node is in glob_subsnode */
|
/* The parent def's substrate node is in glob_subsnode */
|
||||||
|
|
||||||
name1 = extNodeName(glob_subsnode);
|
name1 = extNodeName(glob_subsnode);
|
||||||
|
if (*name1 == '(' && !strcmp(name1, "(none)")) return; /* Don't process "(none)" nodes! */
|
||||||
he = HashFind(table, name1);
|
he = HashFind(table, name1);
|
||||||
nn = (NodeName *) HashGetValue(he);
|
nn = (NodeName *) HashGetValue(he);
|
||||||
node1 = nn ? nn->nn_node : extHierNewNode(he);
|
node1 = nn ? nn->nn_node : extHierNewNode(he);
|
||||||
|
|
@ -132,7 +192,7 @@ extHierSubstrate(ha, use, x, y)
|
||||||
nodeList = extFindNodes(use->cu_def, (Rect *) NULL, TRUE);
|
nodeList = extFindNodes(use->cu_def, (Rect *) NULL, TRUE);
|
||||||
if (nodeList == NULL)
|
if (nodeList == NULL)
|
||||||
{
|
{
|
||||||
ExtResetTiles(use->cu_def, extUnInit);
|
ExtResetTiles(use->cu_def, CLIENTDEFAULT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,7 +232,7 @@ extHierSubstrate(ha, use, x, y)
|
||||||
extHierSubShieldFunc, (ClientData)NULL) != 0)
|
extHierSubShieldFunc, (ClientData)NULL) != 0)
|
||||||
{
|
{
|
||||||
freeMagic(nodeList);
|
freeMagic(nodeList);
|
||||||
ExtResetTiles(use->cu_def, extUnInit);
|
ExtResetTiles(use->cu_def, CLIENTDEFAULT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -181,7 +241,7 @@ extHierSubstrate(ha, use, x, y)
|
||||||
/* Make sure substrate labels are represented */
|
/* Make sure substrate labels are represented */
|
||||||
ExtLabelRegions(use->cu_def, ExtCurStyle->exts_nodeConn, &nodeList,
|
ExtLabelRegions(use->cu_def, ExtCurStyle->exts_nodeConn, &nodeList,
|
||||||
&TiPlaneRect);
|
&TiPlaneRect);
|
||||||
ExtResetTiles(use->cu_def, extUnInit);
|
ExtResetTiles(use->cu_def, CLIENTDEFAULT);
|
||||||
|
|
||||||
name2 = extNodeName(temp_subsnode);
|
name2 = extNodeName(temp_subsnode);
|
||||||
|
|
||||||
|
|
@ -294,8 +354,8 @@ extHierConnections(ha, cumFlat, oneFlat)
|
||||||
if (!(lab->lab_flags & LABEL_STICKY)) continue;
|
if (!(lab->lab_flags & LABEL_STICKY)) continue;
|
||||||
|
|
||||||
r = lab->lab_rect;
|
r = lab->lab_rect;
|
||||||
|
if (!GEO_TOUCH(&r, &ha->ha_subArea)) continue;
|
||||||
GEOCLIP(&r, &ha->ha_subArea);
|
GEOCLIP(&r, &ha->ha_subArea);
|
||||||
if (GEO_RECTNULL(&r)) continue;
|
|
||||||
|
|
||||||
cumDef = cumFlat->et_use->cu_def;
|
cumDef = cumFlat->et_use->cu_def;
|
||||||
connected = &DBConnectTbl[lab->lab_type];
|
connected = &DBConnectTbl[lab->lab_type];
|
||||||
|
|
@ -325,8 +385,9 @@ extHierConnections(ha, cumFlat, oneFlat)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extHierConnectFunc1(oneTile, ha)
|
extHierConnectFunc1(oneTile, dinfo, ha)
|
||||||
Tile *oneTile; /* Comes from 'oneFlat' in extHierConnections */
|
Tile *oneTile; /* Comes from 'oneFlat' in extHierConnections */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
HierExtractArg *ha; /* Extraction context */
|
HierExtractArg *ha; /* Extraction context */
|
||||||
{
|
{
|
||||||
CellDef *cumDef = extHierCumFlat->et_use->cu_def;
|
CellDef *cumDef = extHierCumFlat->et_use->cu_def;
|
||||||
|
|
@ -347,12 +408,16 @@ extHierConnectFunc1(oneTile, ha)
|
||||||
|
|
||||||
if (IsSplit(oneTile))
|
if (IsSplit(oneTile))
|
||||||
{
|
{
|
||||||
rtype = ha->hierType;
|
/* For split tiles, move the tile type to lower (right side) field
|
||||||
ha->hierType = (rtype & TT_SIDE) ? SplitRightType(oneTile) :
|
* but retain the TT_SIDE bit, to indicate which side of hierOneTile
|
||||||
|
* is the connected side.
|
||||||
|
*/
|
||||||
|
ha->hierType = (dinfo & TT_SIDE) ? SplitRightType(oneTile) :
|
||||||
SplitLeftType(oneTile);
|
SplitLeftType(oneTile);
|
||||||
|
ha->hierType |= (dinfo & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE));
|
||||||
}
|
}
|
||||||
|
|
||||||
connected = &(ExtCurStyle->exts_nodeConn[ha->hierType]);
|
connected = &(ExtCurStyle->exts_nodeConn[ha->hierType & TT_LEFTMASK]);
|
||||||
TITORECT(oneTile, &r);
|
TITORECT(oneTile, &r);
|
||||||
GEOCLIP(&r, &ha->ha_subArea);
|
GEOCLIP(&r, &ha->ha_subArea);
|
||||||
r.r_xbot--, r.r_ybot--, r.r_xtop++, r.r_ytop++;
|
r.r_xbot--, r.r_ybot--, r.r_xtop++, r.r_ytop++;
|
||||||
|
|
@ -364,7 +429,7 @@ extHierConnectFunc1(oneTile, ha)
|
||||||
{
|
{
|
||||||
if (IsSplit(oneTile))
|
if (IsSplit(oneTile))
|
||||||
DBSrPaintNMArea((Tile *) NULL, cumDef->cd_planes[i],
|
DBSrPaintNMArea((Tile *) NULL, cumDef->cd_planes[i],
|
||||||
rtype, &r,
|
ha->hierType, &r,
|
||||||
((i == ha->hierPNum) ? &ExtCurStyle->exts_activeTypes
|
((i == ha->hierPNum) ? &ExtCurStyle->exts_activeTypes
|
||||||
: connected), extHierConnectFunc2, (ClientData) ha);
|
: connected), extHierConnectFunc2, (ClientData) ha);
|
||||||
else
|
else
|
||||||
|
|
@ -412,8 +477,9 @@ extHierConnectFunc1(oneTile, ha)
|
||||||
nn = (NodeName *) HashGetValue(he);
|
nn = (NodeName *) HashGetValue(he);
|
||||||
node1 = nn ? nn->nn_node : extHierNewNode(he);
|
node1 = nn ? nn->nn_node : extHierNewNode(he);
|
||||||
|
|
||||||
name = (*ha->ha_nodename)(ha->hierOneTile, ha->hierPNum,
|
name = (*ha->ha_nodename)(ha->hierOneTile, ha->hierType, ha->hierPNum,
|
||||||
extHierOneFlat, ha, TRUE);
|
extHierOneFlat, ha, TRUE);
|
||||||
|
if (*name == '(' && !strcmp(name, "(none)")) return 0; /* Don't process "(none)" nodes! */
|
||||||
he = HashFind(table, name);
|
he = HashFind(table, name);
|
||||||
nn = (NodeName *) HashGetValue(he);
|
nn = (NodeName *) HashGetValue(he);
|
||||||
node2 = nn ? nn->nn_node : extHierNewNode(he);
|
node2 = nn ? nn->nn_node : extHierNewNode(he);
|
||||||
|
|
@ -475,8 +541,9 @@ extHierConnectFunc1(oneTile, ha)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extHierConnectFunc2(cum, ha)
|
extHierConnectFunc2(cum, dinfo, ha)
|
||||||
Tile *cum; /* Comes from extHierCumFlat->et_use->cu_def */
|
Tile *cum; /* Comes from extHierCumFlat->et_use->cu_def */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
HierExtractArg *ha; /* Extraction context */
|
HierExtractArg *ha; /* Extraction context */
|
||||||
{
|
{
|
||||||
HashTable *table = &ha->ha_connHash;
|
HashTable *table = &ha->ha_connHash;
|
||||||
|
|
@ -496,7 +563,22 @@ extHierConnectFunc2(cum, ha)
|
||||||
/* If the tiles don't even touch, they don't connect */
|
/* If the tiles don't even touch, they don't connect */
|
||||||
if (r.r_xtop < r.r_xbot || r.r_ytop < r.r_ybot
|
if (r.r_xtop < r.r_xbot || r.r_ytop < r.r_ybot
|
||||||
|| (r.r_xtop == r.r_xbot && r.r_ytop == r.r_ybot))
|
|| (r.r_xtop == r.r_xbot && r.r_ytop == r.r_ybot))
|
||||||
return (0);
|
return 0;
|
||||||
|
|
||||||
|
/* If either tile is a split tile, then check if the areas of
|
||||||
|
* interest overlap. The first argument to extTestNMInteract()
|
||||||
|
* must be a split tile.
|
||||||
|
*/
|
||||||
|
if (IsSplit(cum))
|
||||||
|
{
|
||||||
|
if (!extTestNMInteract(cum, dinfo, ha->hierOneTile, ha->hierType))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (IsSplit(ha->hierOneTile))
|
||||||
|
{
|
||||||
|
if (!extTestNMInteract(ha->hierOneTile, ha->hierType, cum, dinfo))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only make a connection if the types of 'ha->hierOneTile' and 'cum'
|
* Only make a connection if the types of 'ha->hierOneTile' and 'cum'
|
||||||
|
|
@ -507,17 +589,19 @@ extHierConnectFunc2(cum, ha)
|
||||||
ttype = TiGetTypeExact(cum);
|
ttype = TiGetTypeExact(cum);
|
||||||
|
|
||||||
if (IsSplit(cum))
|
if (IsSplit(cum))
|
||||||
ttype = (ttype & TT_SIDE) ? SplitRightType(cum) : SplitLeftType(cum);
|
ttype = (dinfo & TT_SIDE) ? SplitRightType(cum) : SplitLeftType(cum);
|
||||||
|
|
||||||
if (extConnectsTo(ha->hierType, ttype, ExtCurStyle->exts_nodeConn))
|
if (extConnectsTo(ha->hierType & TT_LEFTMASK, ttype, ExtCurStyle->exts_nodeConn))
|
||||||
{
|
{
|
||||||
name1 = (*ha->ha_nodename)(cum, ha->hierPNumBelow, extHierCumFlat, ha, TRUE);
|
name1 = (*ha->ha_nodename)(cum, dinfo, ha->hierPNumBelow, extHierCumFlat, ha, TRUE);
|
||||||
|
if (*name1 == '(' && !strcmp(name1, "(none)")) return 0; /* Don't process "(none)" nodes! */
|
||||||
he = HashFind(table, name1);
|
he = HashFind(table, name1);
|
||||||
nn = (NodeName *) HashGetValue(he);
|
nn = (NodeName *) HashGetValue(he);
|
||||||
node1 = nn ? nn->nn_node : extHierNewNode(he);
|
node1 = nn ? nn->nn_node : extHierNewNode(he);
|
||||||
|
|
||||||
name2 = (*ha->ha_nodename)(ha->hierOneTile, ha->hierPNum, extHierOneFlat,
|
name2 = (*ha->ha_nodename)(ha->hierOneTile, ha->hierType, ha->hierPNum,
|
||||||
ha, TRUE);
|
extHierOneFlat, ha, TRUE);
|
||||||
|
if (*name2 == '(' && !strcmp(name2, "(none)")) return 0; /* Don't process "(none)" nodes! */
|
||||||
he = HashFind(table, name2);
|
he = HashFind(table, name2);
|
||||||
nn = (NodeName *) HashGetValue(he);
|
nn = (NodeName *) HashGetValue(he);
|
||||||
node2 = nn ? nn->nn_node : extHierNewNode(he);
|
node2 = nn ? nn->nn_node : extHierNewNode(he);
|
||||||
|
|
@ -562,7 +646,7 @@ extHierConnectFunc2(cum, ha)
|
||||||
|
|
||||||
snprintf(message, sizeof(message),
|
snprintf(message, sizeof(message),
|
||||||
"Illegal overlap between %s and %s (types do not connect)",
|
"Illegal overlap between %s and %s (types do not connect)",
|
||||||
DBTypeLongNameTbl[ha->hierType], DBTypeLongNameTbl[ttype]);
|
DBTypeLongNameTbl[ha->hierType & TT_LEFTMASK], DBTypeLongNameTbl[ttype]);
|
||||||
|
|
||||||
extNumErrors++;
|
extNumErrors++;
|
||||||
if (!DebugIsSet(extDebugID, extDebNoFeedback))
|
if (!DebugIsSet(extDebugID, extDebNoFeedback))
|
||||||
|
|
@ -584,8 +668,9 @@ extHierConnectFunc2(cum, ha)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extHierConnectFunc3(cum, ha)
|
extHierConnectFunc3(cum, dinfo, ha)
|
||||||
Tile *cum; /* Comes from extHierCumFlat->et_use->cu_def */
|
Tile *cum; /* Comes from extHierCumFlat->et_use->cu_def */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
HierExtractArg *ha; /* Extraction context */
|
HierExtractArg *ha; /* Extraction context */
|
||||||
{
|
{
|
||||||
HashTable *table = &ha->ha_connHash;
|
HashTable *table = &ha->ha_connHash;
|
||||||
|
|
@ -616,16 +701,19 @@ extHierConnectFunc3(cum, ha)
|
||||||
ttype = TiGetTypeExact(cum);
|
ttype = TiGetTypeExact(cum);
|
||||||
|
|
||||||
if (IsSplit(cum))
|
if (IsSplit(cum))
|
||||||
ttype = (ttype & TT_SIDE) ? SplitRightType(cum) : SplitLeftType(cum);
|
ttype = (dinfo & TT_SIDE) ? SplitRightType(cum) : SplitLeftType(cum);
|
||||||
|
|
||||||
if (extConnectsTo(ha->hierType, ttype, ExtCurStyle->exts_nodeConn))
|
if (extConnectsTo(ha->hierType & TT_LEFTMASK, ttype, ExtCurStyle->exts_nodeConn))
|
||||||
{
|
{
|
||||||
name1 = (*ha->ha_nodename)(cum, ha->hierPNumBelow, extHierCumFlat, ha, TRUE);
|
name1 = (*ha->ha_nodename)(cum, ha->hierType, ha->hierPNumBelow,
|
||||||
|
extHierCumFlat, ha, TRUE);
|
||||||
|
if (*name1 == '(' && !strcmp(name1, "(none)")) return 0; /* Don't process "(none)" nodes! */
|
||||||
he = HashFind(table, name1);
|
he = HashFind(table, name1);
|
||||||
nn = (NodeName *) HashGetValue(he);
|
nn = (NodeName *) HashGetValue(he);
|
||||||
node1 = nn ? nn->nn_node : extHierNewNode(he);
|
node1 = nn ? nn->nn_node : extHierNewNode(he);
|
||||||
|
|
||||||
name2 = lab->lab_text;
|
name2 = lab->lab_text;
|
||||||
|
if (*name2 == '(' && !strcmp(name2, "(none)")) return 0; /* Don't process "(none)" nodes! */
|
||||||
he = HashFind(table, name2);
|
he = HashFind(table, name2);
|
||||||
nn = (NodeName *) HashGetValue(he);
|
nn = (NodeName *) HashGetValue(he);
|
||||||
node2 = nn ? nn->nn_node : extHierNewNode(he);
|
node2 = nn ? nn->nn_node : extHierNewNode(he);
|
||||||
|
|
@ -670,7 +758,7 @@ extHierConnectFunc3(cum, ha)
|
||||||
|
|
||||||
snprintf(message, sizeof(message),
|
snprintf(message, sizeof(message),
|
||||||
"Illegal overlap between %s and %s (types do not connect)",
|
"Illegal overlap between %s and %s (types do not connect)",
|
||||||
DBTypeLongNameTbl[ha->hierType], DBTypeLongNameTbl[ttype]);
|
DBTypeLongNameTbl[ha->hierType & TT_LEFTMASK], DBTypeLongNameTbl[ttype]);
|
||||||
|
|
||||||
extNumErrors++;
|
extNumErrors++;
|
||||||
if (!DebugIsSet(extDebugID, extDebNoFeedback))
|
if (!DebugIsSet(extDebugID, extDebNoFeedback))
|
||||||
|
|
@ -771,18 +859,20 @@ extHierAdjustments(ha, cumFlat, oneFlat, lookFlat)
|
||||||
*/
|
*/
|
||||||
for (np = oneFlat->et_nodes; np; np = np->nreg_next)
|
for (np = oneFlat->et_nodes; np; np = np->nreg_next)
|
||||||
{
|
{
|
||||||
|
TileType dinfo;
|
||||||
|
|
||||||
/* Ignore orphaned nodes (non-Manhattan shards outside the clip box) */
|
/* Ignore orphaned nodes (non-Manhattan shards outside the clip box) */
|
||||||
if (np->nreg_pnum == DBNumPlanes) continue;
|
if (np->nreg_pnum == DBNumPlanes) continue;
|
||||||
|
|
||||||
tp = extNodeToTile(np, lookFlat);
|
tp = extNodeToTile(np, lookFlat, &dinfo);
|
||||||
|
|
||||||
/* Ignore regions that do not participate in extraction */
|
/* Ignore regions that do not participate in extraction */
|
||||||
if (!extHasRegion(tp, extUnInit)) continue;
|
if (!extHasRegion(tp, CLIENTDEFAULT)) continue;
|
||||||
|
|
||||||
/* Ignore substrate nodes (failsafe: should not happen) */
|
/* Ignore substrate nodes (failsafe: should not happen) */
|
||||||
if (TiGetTypeExact(tp) == TT_SPACE) continue;
|
if (TiGetTypeExact(tp) == TT_SPACE) continue;
|
||||||
|
|
||||||
if (tp && (name = (*ha->ha_nodename)(tp, np->nreg_pnum, lookFlat, ha, FALSE))
|
if (tp && (name = (*ha->ha_nodename)(tp, dinfo, np->nreg_pnum, lookFlat, ha, FALSE))
|
||||||
&& (he = HashLookOnly(&ha->ha_connHash, name))
|
&& (he = HashLookOnly(&ha->ha_connHash, name))
|
||||||
&& (nn = (NodeName *) HashGetValue(he)))
|
&& (nn = (NodeName *) HashGetValue(he)))
|
||||||
{
|
{
|
||||||
|
|
@ -946,8 +1036,9 @@ extHierNewNode(he)
|
||||||
|
|
||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
ExtRegion *
|
ExtRegion *
|
||||||
extHierLabFirst(tile, arg)
|
extHierLabFirst(tile, dinfo, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
FindRegion *arg;
|
FindRegion *arg;
|
||||||
{
|
{
|
||||||
LabRegion *new;
|
LabRegion *new;
|
||||||
|
|
@ -966,15 +1057,16 @@ extHierLabFirst(tile, arg)
|
||||||
|
|
||||||
/*ARGSUSED*/
|
/*ARGSUSED*/
|
||||||
int
|
int
|
||||||
extHierLabEach(tile, pNum, arg)
|
extHierLabEach(tile, dinfo, pNum, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
int pNum;
|
int pNum;
|
||||||
FindRegion *arg;
|
FindRegion *arg;
|
||||||
{
|
{
|
||||||
LabRegion *reg;
|
LabRegion *reg;
|
||||||
|
|
||||||
reg = (LabRegion *) arg->fra_region;
|
reg = (LabRegion *) arg->fra_region;
|
||||||
extSetNodeNum(reg, pNum, tile);
|
extSetNodeNum(reg, pNum, tile, dinfo);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -270,8 +270,9 @@ extInterSubtreeElement(use, trans, x, y, r)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extInterSubtreeTile(tile, cxp)
|
extInterSubtreeTile(tile, dinfo, cxp)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
TreeContext *cxp;
|
TreeContext *cxp;
|
||||||
{
|
{
|
||||||
SearchContext newscx;
|
SearchContext newscx;
|
||||||
|
|
|
||||||
|
|
@ -434,8 +434,9 @@ extLengthYank(use, labList)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extLengthLabels(tile, rootUse)
|
extLengthLabels(tile, dinfo, rootUse)
|
||||||
Tile *tile; /* Some tile in extPathDef */
|
Tile *tile; /* Some tile in extPathDef */
|
||||||
|
TileType dinfo; /* Split tile information (unused) */
|
||||||
CellUse *rootUse; /* The original root cell */
|
CellUse *rootUse; /* The original root cell */
|
||||||
{
|
{
|
||||||
char name[MAXNAMESIZE];
|
char name[MAXNAMESIZE];
|
||||||
|
|
@ -727,8 +728,9 @@ extPathResetClient(tile)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extPathPairFunc(tile, epa)
|
extPathPairFunc(tile, dinfo, epa)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; // Unused
|
||||||
struct extPathArg *epa;
|
struct extPathArg *epa;
|
||||||
{
|
{
|
||||||
Point startPoint;
|
Point startPoint;
|
||||||
|
|
@ -909,8 +911,9 @@ extPathFlood(tile, p, distance, epa)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
extPathFloodFunc(dstTile, epfa)
|
extPathFloodFunc(dstTile, dinfo, epfa)
|
||||||
Tile *dstTile;
|
Tile *dstTile;
|
||||||
|
TileType dinfo; // Unused
|
||||||
struct extPathFloodArg *epfa;
|
struct extPathFloodArg *epfa;
|
||||||
{
|
{
|
||||||
Rect srcRect, dstRect;
|
Rect srcRect, dstRect;
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
#include "extract/extract.h"
|
#include "extract/extract.h"
|
||||||
#include "extract/extractInt.h"
|
#include "extract/extractInt.h"
|
||||||
|
#include "resis/resis.h"
|
||||||
#include "utils/signals.h"
|
#include "utils/signals.h"
|
||||||
#include "utils/stack.h"
|
#include "utils/stack.h"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
|
|
@ -43,9 +44,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "utils/main.h"
|
#include "utils/main.h"
|
||||||
#include "utils/undo.h"
|
#include "utils/undo.h"
|
||||||
|
|
||||||
/* Imports from elsewhere in this module */
|
|
||||||
extern FILE *extFileOpen();
|
|
||||||
|
|
||||||
/* ------------------------ Exported variables ------------------------ */
|
/* ------------------------ Exported variables ------------------------ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -83,16 +81,6 @@ typedef struct _linkedDef {
|
||||||
struct _linkedDef *ld_next;
|
struct _linkedDef *ld_next;
|
||||||
} LinkedDef;
|
} LinkedDef;
|
||||||
|
|
||||||
/* Linked list structure to use to store the substrate plane from each */
|
|
||||||
/* extracted CellDef so that they can be returned to the original after */
|
|
||||||
/* extraction. */
|
|
||||||
|
|
||||||
struct saveList {
|
|
||||||
Plane *sl_plane;
|
|
||||||
CellDef *sl_def;
|
|
||||||
struct saveList *sl_next;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Stack of defs pending extraction */
|
/* Stack of defs pending extraction */
|
||||||
Stack *extDefStack;
|
Stack *extDefStack;
|
||||||
|
|
||||||
|
|
@ -209,9 +197,10 @@ extIsUsedFunc(use, clientData)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extEnumFunc(tile, plane)
|
extEnumFunc(tile, dinfo, clientdata)
|
||||||
Tile *tile;
|
Tile *tile; /* (unused) */
|
||||||
int *plane;
|
TileType dinfo; /* (unused) */
|
||||||
|
ClientData clientdata; /* (unused) */
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -605,7 +594,7 @@ extParents(use, doExtract)
|
||||||
extDefParentFunc(use->cu_def);
|
extDefParentFunc(use->cu_def);
|
||||||
|
|
||||||
/* Now extract all the cells we just found */
|
/* Now extract all the cells we just found */
|
||||||
extExtractStack(extDefStack, doExtract, (CellDef *) NULL);
|
extExtractStack(extDefStack, doExtract, (CellDef *)NULL);
|
||||||
StackFree(extDefStack);
|
StackFree(extDefStack);
|
||||||
|
|
||||||
/* Replace any modified substrate planes in use->cu_def's children */
|
/* Replace any modified substrate planes in use->cu_def's children */
|
||||||
|
|
@ -687,7 +676,7 @@ ExtParentArea(use, changedArea, doExtract)
|
||||||
extDefParentAreaFunc(use->cu_def, use->cu_def, (CellUse *) NULL, &area);
|
extDefParentAreaFunc(use->cu_def, use->cu_def, (CellUse *) NULL, &area);
|
||||||
|
|
||||||
/* Now extract all the cells we just found */
|
/* Now extract all the cells we just found */
|
||||||
extExtractStack(extDefStack, doExtract, (CellDef *) NULL);
|
extExtractStack(extDefStack, doExtract, (CellDef *)NULL);
|
||||||
StackFree(extDefStack);
|
StackFree(extDefStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -805,12 +794,30 @@ ExtractOneCell(def, outName, doLength)
|
||||||
|
|
||||||
savePlane = ExtCell(def, outName, doLength);
|
savePlane = ExtCell(def, outName, doLength);
|
||||||
|
|
||||||
/* Restore all modified substrate planes */
|
/* Run full R-C extraction if specified in options */
|
||||||
|
|
||||||
|
if (ExtOptions & EXT_DOEXTRESIST)
|
||||||
|
{
|
||||||
|
ResisData *resisdata = ResInit();
|
||||||
|
|
||||||
|
UndoDisable();
|
||||||
|
|
||||||
|
ResOptionsFlags |= ResOpt_Signal;
|
||||||
|
resisdata->mainDef = def;
|
||||||
|
resisdata->savePlanes = (struct saveList *)NULL; /* unused */
|
||||||
|
|
||||||
|
ExtResisForDef(def, resisdata);
|
||||||
|
|
||||||
|
UndoEnable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore all modified substrate planes and modified labels */
|
||||||
|
|
||||||
if (savePlane != NULL) ExtRevertSubstrate(def, savePlane);
|
if (savePlane != NULL) ExtRevertSubstrate(def, savePlane);
|
||||||
free_magic1_t mm1 = freeMagic1_init();
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (; sl; sl = sl->sl_next)
|
for (; sl; sl = sl->sl_next)
|
||||||
{
|
{
|
||||||
|
if (EXT_DOUNIQUE) ExtRevertUniqueCell(sl->sl_def);
|
||||||
ExtRevertSubstrate(sl->sl_def, sl->sl_plane);
|
ExtRevertSubstrate(sl->sl_def, sl->sl_plane);
|
||||||
freeMagic1(&mm1, sl);
|
freeMagic1(&mm1, sl);
|
||||||
}
|
}
|
||||||
|
|
@ -854,7 +861,10 @@ extContainsCellFunc(
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
extContainsPaintFunc()
|
extContainsPaintFunc(
|
||||||
|
Tile *tile, /* (unused) */
|
||||||
|
TileType dinfo, /* (unused) */
|
||||||
|
ClientData clientdata) /* (unused) */
|
||||||
{
|
{
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
@ -940,7 +950,7 @@ extTimestampMisMatch(def)
|
||||||
|
|
||||||
doLocal = (ExtLocalPath == NULL) ? FALSE : TRUE;
|
doLocal = (ExtLocalPath == NULL) ? FALSE : TRUE;
|
||||||
|
|
||||||
extFile = extFileOpen(def, (char *) NULL, "r", (char **) NULL);
|
extFile = ExtFileOpen(def, (char *) NULL, "r", (char **) NULL);
|
||||||
if (extFile == NULL)
|
if (extFile == NULL)
|
||||||
return (TRUE);
|
return (TRUE);
|
||||||
|
|
||||||
|
|
@ -986,10 +996,18 @@ extExtractStack(stack, doExtract, rootDef)
|
||||||
bool first = TRUE;
|
bool first = TRUE;
|
||||||
Plane *savePlane;
|
Plane *savePlane;
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
|
LinkedDef *savelist = NULL, *revlist = NULL, *newld;
|
||||||
struct saveList *newsl, *sl = (struct saveList *)NULL;
|
struct saveList *newsl, *sl = (struct saveList *)NULL;
|
||||||
|
|
||||||
while ((def = (CellDef *) StackPop(stack)))
|
while ((def = (CellDef *) StackPop(stack)))
|
||||||
{
|
{
|
||||||
|
if (ExtOptions & EXT_DOEXTRESIST)
|
||||||
|
{
|
||||||
|
newld = (LinkedDef *)mallocMagic(sizeof(LinkedDef));
|
||||||
|
newld->ld_def = def;
|
||||||
|
newld->ld_next = savelist;
|
||||||
|
savelist = newld;
|
||||||
|
}
|
||||||
def->cd_client = (ClientData) 0;
|
def->cd_client = (ClientData) 0;
|
||||||
if (!SigInterruptPending)
|
if (!SigInterruptPending)
|
||||||
{
|
{
|
||||||
|
|
@ -1004,6 +1022,8 @@ extExtractStack(stack, doExtract, rootDef)
|
||||||
newsl->sl_next = sl;
|
newsl->sl_next = sl;
|
||||||
sl = newsl;
|
sl = newsl;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
def->cd_flags &= ~CDNOEXTRACT;
|
||||||
|
|
||||||
errorcnt += extNumErrors;
|
errorcnt += extNumErrors;
|
||||||
warnings += extNumWarnings;
|
warnings += extNumWarnings;
|
||||||
|
|
@ -1015,13 +1035,55 @@ extExtractStack(stack, doExtract, rootDef)
|
||||||
TxFlush();
|
TxFlush();
|
||||||
first = FALSE;
|
first = FALSE;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
def->cd_flags &= ~CDNOEXTRACT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Replace any modified substrate planes */
|
/* Now that all cells have been processed, run full R-C extraction */
|
||||||
|
if (ExtOptions & EXT_DOEXTRESIST)
|
||||||
|
{
|
||||||
|
ResisData *resisdata = ResInit();
|
||||||
|
LinkedDef *srchld, *nextld;
|
||||||
|
|
||||||
|
UndoDisable();
|
||||||
|
|
||||||
|
/* Reverse the linked list from top-down to bottom-up */
|
||||||
|
srchld = savelist;
|
||||||
|
while (srchld != NULL)
|
||||||
|
{
|
||||||
|
nextld = srchld->ld_next;
|
||||||
|
srchld->ld_next = revlist;
|
||||||
|
revlist = srchld;
|
||||||
|
srchld = nextld;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reprocess the list and call "extresist" for each cell def */
|
||||||
|
srchld = revlist;
|
||||||
|
while (srchld != NULL)
|
||||||
|
{
|
||||||
|
nextld = srchld->ld_next;
|
||||||
|
def = srchld->ld_def;
|
||||||
|
|
||||||
|
ResOptionsFlags |= ResOpt_Signal;
|
||||||
|
resisdata->mainDef = def;
|
||||||
|
resisdata->savePlanes = (struct saveList *)NULL; /* unused */
|
||||||
|
|
||||||
|
TxPrintf("Processing cell %s for resistance extraction.\n", def->cd_name);
|
||||||
|
ExtResisForDef(def, resisdata);
|
||||||
|
|
||||||
|
freeMagic(srchld);
|
||||||
|
srchld = nextld;
|
||||||
|
}
|
||||||
|
UndoEnable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Replace any modified substrate planes and modified labels */
|
||||||
free_magic1_t mm1 = freeMagic1_init();
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (; sl; sl = sl->sl_next)
|
for (; sl; sl = sl->sl_next)
|
||||||
{
|
{
|
||||||
|
if (EXT_DOUNIQUE) ExtRevertUniqueCell(sl->sl_def);
|
||||||
|
|
||||||
ExtRevertSubstrate(sl->sl_def, sl->sl_plane);
|
ExtRevertSubstrate(sl->sl_def, sl->sl_plane);
|
||||||
sl->sl_def->cd_flags &= ~CDNOEXTRACT;
|
sl->sl_def->cd_flags &= ~CDNOEXTRACT;
|
||||||
freeMagic1(&mm1, sl);
|
freeMagic1(&mm1, sl);
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
* the value VISITPENDING in its ti_client field.
|
* the value VISITPENDING in its ti_client field.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Used for communicating with extNbrPushFunc */
|
|
||||||
ClientData extNbrUn;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -74,41 +71,44 @@ ClientData extNbrUn;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
ExtFindNeighbors(tile, tilePlaneNum, arg)
|
ExtFindNeighbors(tile, dinfo, tilePlaneNum, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
int tilePlaneNum;
|
int tilePlaneNum;
|
||||||
FindRegion *arg;
|
FindRegion *arg;
|
||||||
{
|
{
|
||||||
TileTypeBitMask *connTo = arg->fra_connectsTo;
|
TileTypeBitMask *connTo = arg->fra_connectsTo;
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
TileType type, t;
|
TileType type, t, tpdinfo;
|
||||||
TileTypeBitMask *mask;
|
TileTypeBitMask *mask;
|
||||||
Rect biggerArea;
|
Rect biggerArea;
|
||||||
int pNum, tilesfound;
|
int pNum, tilesfound;
|
||||||
PlaneMask pMask;
|
PlaneMask pMask;
|
||||||
PlaneAndArea pla;
|
PlaneAndArea pla;
|
||||||
|
ClientData extNbrUn = arg->fra_uninit;
|
||||||
|
|
||||||
tilesfound = 0;
|
tilesfound = 0;
|
||||||
|
|
||||||
extNbrUn = arg->fra_uninit;
|
|
||||||
if (extNodeStack == (Stack *) NULL)
|
if (extNodeStack == (Stack *) NULL)
|
||||||
extNodeStack = StackNew(64);
|
extNodeStack = StackNew(64);
|
||||||
|
|
||||||
/* Mark this tile as pending and push it */
|
/* Mark this tile as pending and push it */
|
||||||
PUSHTILE(tile, tilePlaneNum);
|
PUSHTILE(tile, dinfo, tilePlaneNum);
|
||||||
|
|
||||||
while (!StackEmpty(extNodeStack))
|
while (!StackEmpty(extNodeStack))
|
||||||
{
|
{
|
||||||
POPTILE(tile, tilePlaneNum);
|
POPTILE(tile, dinfo, tilePlaneNum);
|
||||||
|
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
type = (SplitSide(tile)) ? SplitRightType(tile):
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile):
|
||||||
SplitLeftType(tile);
|
SplitLeftType(tile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
type = TiGetTypeExact(tile);
|
type = TiGetTypeExact(tile);
|
||||||
|
|
||||||
|
ASSERT(type != TT_SPACE, "ExtFindNeighbors");
|
||||||
|
|
||||||
mask = &connTo[type];
|
mask = &connTo[type];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -117,23 +117,27 @@ ExtFindNeighbors(tile, tilePlaneNum, arg)
|
||||||
* been visited in the meantime. If it's still unvisited,
|
* been visited in the meantime. If it's still unvisited,
|
||||||
* visit it and process its neighbors.
|
* visit it and process its neighbors.
|
||||||
*/
|
*/
|
||||||
if (TiGetClientPTR(tile) == arg->fra_region)
|
|
||||||
|
if (ExtGetRegion(tile, dinfo) == arg->fra_region)
|
||||||
continue;
|
continue;
|
||||||
TiSetClientPTR(tile, arg->fra_region);
|
|
||||||
|
ExtSetRegion(tile, dinfo, arg->fra_region);
|
||||||
|
|
||||||
tilesfound++;
|
tilesfound++;
|
||||||
if (DebugIsSet(extDebugID, extDebNeighbor))
|
if (DebugIsSet(extDebugID, extDebNeighbor))
|
||||||
extShowTile(tile, "neighbor", 1);
|
extShowTile(tile, "neighbor", 1);
|
||||||
|
|
||||||
/* Top */
|
/* Top */
|
||||||
topside:
|
topside:
|
||||||
if (IsSplit(tile) && (SplitSide(tile) ^ SplitDirection(tile))) goto leftside;
|
if (IsSplit(tile) && ((dinfo & TT_SIDE) ? 1 : 0) ^ SplitDirection(tile))
|
||||||
|
goto leftside;
|
||||||
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp))
|
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp))
|
||||||
{
|
{
|
||||||
if (IsSplit(tp))
|
if (IsSplit(tp))
|
||||||
{
|
{
|
||||||
t = SplitBottomType(tp);
|
t = SplitBottomType(tp);
|
||||||
// if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
tpdinfo = SplitDirection(tp) ? (TileType)0 : (TileType)TT_SIDE;
|
||||||
if (TiGetClientPTR(tp) != arg->fra_region && TTMaskHasType(mask, t))
|
if (ExtGetRegion(tp, tpdinfo) == CD2PTR(extNbrUn) && TTMaskHasType(mask, t))
|
||||||
{
|
{
|
||||||
PUSHTILEBOTTOM(tp, tilePlaneNum);
|
PUSHTILEBOTTOM(tp, tilePlaneNum);
|
||||||
}
|
}
|
||||||
|
|
@ -143,21 +147,21 @@ topside:
|
||||||
t = TiGetTypeExact(tp);
|
t = TiGetTypeExact(tp);
|
||||||
if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
||||||
{
|
{
|
||||||
PUSHTILE(tp, tilePlaneNum);
|
PUSHTILELEFT(tp, tilePlaneNum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Left */
|
/* Left */
|
||||||
leftside:
|
leftside:
|
||||||
if (IsSplit(tile) && SplitSide(tile)) goto bottomside;
|
if (IsSplit(tile) && (dinfo & TT_SIDE)) goto bottomside;
|
||||||
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
|
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
|
||||||
{
|
{
|
||||||
if (IsSplit(tp))
|
if (IsSplit(tp))
|
||||||
{
|
{
|
||||||
t = SplitRightType(tp);
|
t = SplitRightType(tp);
|
||||||
// if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
if (ExtGetRegion(tp, (TileType)TT_SIDE) == CD2PTR(extNbrUn)
|
||||||
if (TiGetClientPTR(tp) != arg->fra_region && TTMaskHasType(mask, t))
|
&& TTMaskHasType(mask, t))
|
||||||
{
|
{
|
||||||
PUSHTILERIGHT(tp, tilePlaneNum);
|
PUSHTILERIGHT(tp, tilePlaneNum);
|
||||||
}
|
}
|
||||||
|
|
@ -167,22 +171,22 @@ leftside:
|
||||||
t = TiGetTypeExact(tp);
|
t = TiGetTypeExact(tp);
|
||||||
if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
||||||
{
|
{
|
||||||
PUSHTILE(tp, tilePlaneNum);
|
PUSHTILELEFT(tp, tilePlaneNum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bottom */
|
/* Bottom */
|
||||||
bottomside:
|
bottomside:
|
||||||
if (IsSplit(tile) && (!(SplitSide(tile) ^ SplitDirection(tile))))
|
if (IsSplit(tile) && (!(((dinfo & TT_SIDE) ? 1 : 0) ^ SplitDirection(tile))))
|
||||||
goto rightside;
|
goto rightside;
|
||||||
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
|
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
|
||||||
{
|
{
|
||||||
if (IsSplit(tp))
|
if (IsSplit(tp))
|
||||||
{
|
{
|
||||||
t = SplitTopType(tp);
|
t = SplitTopType(tp);
|
||||||
// if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
tpdinfo = SplitDirection(tp) ? (TileType)TT_SIDE : (TileType)0;
|
||||||
if (TiGetClientPTR(tp) != arg->fra_region && TTMaskHasType(mask, t))
|
if (ExtGetRegion(tp, tpdinfo) == CD2PTR(extNbrUn) && TTMaskHasType(mask, t))
|
||||||
{
|
{
|
||||||
PUSHTILETOP(tp, tilePlaneNum);
|
PUSHTILETOP(tp, tilePlaneNum);
|
||||||
}
|
}
|
||||||
|
|
@ -192,21 +196,21 @@ bottomside:
|
||||||
t = TiGetTypeExact(tp);
|
t = TiGetTypeExact(tp);
|
||||||
if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
||||||
{
|
{
|
||||||
PUSHTILE(tp, tilePlaneNum);
|
PUSHTILELEFT(tp, tilePlaneNum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Right */
|
/* Right */
|
||||||
rightside:
|
rightside:
|
||||||
if (IsSplit(tile) && !SplitSide(tile)) goto donesides;
|
if (IsSplit(tile) && !(dinfo & TT_SIDE)) goto donesides;
|
||||||
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp))
|
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp))
|
||||||
{
|
{
|
||||||
if (IsSplit(tp))
|
if (IsSplit(tp))
|
||||||
{
|
{
|
||||||
t = SplitLeftType(tp);
|
t = SplitLeftType(tp);
|
||||||
// if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
if (ExtGetRegion(tp, (TileType)0) == CD2PTR(extNbrUn)
|
||||||
if (TiGetClientPTR(tp) != arg->fra_region && TTMaskHasType(mask, t))
|
&& TTMaskHasType(mask, t))
|
||||||
{
|
{
|
||||||
PUSHTILELEFT(tp, tilePlaneNum);
|
PUSHTILELEFT(tp, tilePlaneNum);
|
||||||
}
|
}
|
||||||
|
|
@ -216,7 +220,7 @@ rightside:
|
||||||
t = TiGetTypeExact(tp);
|
t = TiGetTypeExact(tp);
|
||||||
if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
||||||
{
|
{
|
||||||
PUSHTILE(tp, tilePlaneNum);
|
PUSHTILELEFT(tp, tilePlaneNum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -224,9 +228,14 @@ rightside:
|
||||||
donesides:
|
donesides:
|
||||||
/* Apply the client's filter procedure if one exists */
|
/* Apply the client's filter procedure if one exists */
|
||||||
if (arg->fra_each)
|
if (arg->fra_each)
|
||||||
if ((*arg->fra_each)(tile, tilePlaneNum, arg))
|
if ((*arg->fra_each)(tile, dinfo, tilePlaneNum, arg))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
/* Use tilePlaneNum value -1 to force ExtFindNeighbors to stay
|
||||||
|
* on a single plane.
|
||||||
|
*/
|
||||||
|
if (tilePlaneNum < 0) continue;
|
||||||
|
|
||||||
/* If this is a contact, visit all the other planes */
|
/* If this is a contact, visit all the other planes */
|
||||||
if (DBIsContact(type))
|
if (DBIsContact(type))
|
||||||
{
|
{
|
||||||
|
|
@ -235,6 +244,7 @@ donesides:
|
||||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||||
if (PlaneMaskHasPlane(pMask, pNum))
|
if (PlaneMaskHasPlane(pMask, pNum))
|
||||||
{
|
{
|
||||||
|
ExtRegion *tpreg;
|
||||||
Plane *plane = arg->fra_def->cd_planes[pNum];
|
Plane *plane = arg->fra_def->cd_planes[pNum];
|
||||||
|
|
||||||
/* Find the point on the new plane */
|
/* Find the point on the new plane */
|
||||||
|
|
@ -242,14 +252,14 @@ donesides:
|
||||||
GOTOPOINT(tp, &tile->ti_ll);
|
GOTOPOINT(tp, &tile->ti_ll);
|
||||||
PlaneSetHint(plane, tp);
|
PlaneSetHint(plane, tp);
|
||||||
|
|
||||||
/* If not yet visited, process tp */
|
|
||||||
if (TiGetClient(tp) != extNbrUn) continue;
|
|
||||||
|
|
||||||
/* tp and tile should have the same geometry for a contact */
|
/* tp and tile should have the same geometry for a contact */
|
||||||
if (IsSplit(tile) && IsSplit(tp))
|
if (IsSplit(tile) && IsSplit(tp))
|
||||||
{
|
{
|
||||||
if (SplitSide(tile))
|
if (dinfo & TT_SIDE)
|
||||||
{
|
{
|
||||||
|
/* Only process tp if not yet visited */
|
||||||
|
tpreg = ExtGetRegion(tp, (TileType)TT_SIDE);
|
||||||
|
if (tpreg != CD2PTR(extNbrUn)) continue;
|
||||||
t = SplitRightType(tp);
|
t = SplitRightType(tp);
|
||||||
if (TTMaskHasType(mask, t))
|
if (TTMaskHasType(mask, t))
|
||||||
{
|
{
|
||||||
|
|
@ -258,6 +268,9 @@ donesides:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* Only process tp if not yet visited */
|
||||||
|
tpreg = ExtGetRegion(tp, (TileType)0);
|
||||||
|
if (tpreg != CD2PTR(extNbrUn)) continue;
|
||||||
t = SplitLeftType(tp);
|
t = SplitLeftType(tp);
|
||||||
if (TTMaskHasType(mask, t))
|
if (TTMaskHasType(mask, t))
|
||||||
{
|
{
|
||||||
|
|
@ -266,24 +279,37 @@ donesides:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (IsSplit(tp))
|
else if (IsSplit(tp))
|
||||||
|
{
|
||||||
|
/* Only process tp if not yet visited */
|
||||||
|
tpreg = ExtGetRegion(tp, (TileType)TT_SIDE);
|
||||||
|
if (tpreg == CD2PTR(extNbrUn))
|
||||||
{
|
{
|
||||||
t = SplitRightType(tp);
|
t = SplitRightType(tp);
|
||||||
if (TTMaskHasType(mask, t))
|
if (TTMaskHasType(mask, t))
|
||||||
{
|
{
|
||||||
PUSHTILERIGHT(tp, pNum);
|
PUSHTILERIGHT(tp, pNum);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
/* Try both sides */
|
||||||
|
tpreg = ExtGetRegion(tp, (TileType)0);
|
||||||
|
if (tpreg == CD2PTR(extNbrUn))
|
||||||
|
{
|
||||||
t = SplitLeftType(tp);
|
t = SplitLeftType(tp);
|
||||||
if (TTMaskHasType(mask, t))
|
if (TTMaskHasType(mask, t))
|
||||||
{
|
{
|
||||||
PUSHTILELEFT(tp, pNum);
|
PUSHTILELEFT(tp, pNum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* Only process tp if not yet visited */
|
||||||
|
tpreg = ExtGetRegion(tp, (TileType)0);
|
||||||
|
if (tpreg != CD2PTR(extNbrUn)) continue;
|
||||||
t = TiGetTypeExact(tp);
|
t = TiGetTypeExact(tp);
|
||||||
if (TTMaskHasType(mask, t))
|
if (TTMaskHasType(mask, t))
|
||||||
{
|
{
|
||||||
PUSHTILE(tp, pNum);
|
PUSHTILELEFT(tp, pNum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -300,27 +326,28 @@ donesides:
|
||||||
*/
|
*/
|
||||||
if ((pMask = DBAllConnPlanes[type]))
|
if ((pMask = DBAllConnPlanes[type]))
|
||||||
{
|
{
|
||||||
|
pla.uninit = extNbrUn;
|
||||||
TITORECT(tile, &pla.area);
|
TITORECT(tile, &pla.area);
|
||||||
GEO_EXPAND(&pla.area, 1, &biggerArea);
|
GEO_EXPAND(&pla.area, 1, &biggerArea);
|
||||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||||
if ((pNum != tilePlaneNum) && PlaneMaskHasPlane(pMask, pNum))
|
if ((pNum != tilePlaneNum) && PlaneMaskHasPlane(pMask, pNum))
|
||||||
{
|
{
|
||||||
pla.plane = pNum;
|
pla.plane = pNum;
|
||||||
(void) DBSrPaintArea((Tile *) NULL,
|
(void) DBSrPaintNMArea((Tile *) NULL,
|
||||||
arg->fra_def->cd_planes[pNum], &biggerArea,
|
arg->fra_def->cd_planes[pNum],
|
||||||
|
TiGetTypeExact(tile) | dinfo, &biggerArea,
|
||||||
mask, extNbrPushFunc, (ClientData) &pla);
|
mask, extNbrPushFunc, (ClientData) &pla);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tilesfound;
|
return tilesfound;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
/* Flush the stack */
|
/* Flush the stack */
|
||||||
while (!StackEmpty(extNodeStack))
|
while (!StackEmpty(extNodeStack))
|
||||||
{
|
{
|
||||||
POPTILE(tile, tilePlaneNum);
|
POPTILE(tile, dinfo, tilePlaneNum);
|
||||||
TiSetClientPTR(tile, arg->fra_region);
|
ExtSetRegion(tile, dinfo, arg->fra_region);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -335,9 +362,9 @@ fail:
|
||||||
* with tileArea, and it hasn't already been visited, push it on the stack
|
* with tileArea, and it hasn't already been visited, push it on the stack
|
||||||
* extNodeStack.
|
* extNodeStack.
|
||||||
*
|
*
|
||||||
* Uses the global parameter extNbrUn to determine whether or not a tile
|
* Uses the value pla->uninit to determine whether or not a tile has been
|
||||||
* has been visited; if the tile's client field is equal to extNbrUn, then
|
* visited; if the tile's client field is equal to pla->uninit, then this
|
||||||
* this is the first time the tile has been seen.
|
* is the first time the tile has been seen.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* Always returns 0.
|
* Always returns 0.
|
||||||
|
|
@ -349,8 +376,9 @@ fail:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extNbrPushFunc(tile, pla)
|
extNbrPushFunc(tile, dinfo, pla)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
PlaneAndArea *pla;
|
PlaneAndArea *pla;
|
||||||
{
|
{
|
||||||
Rect *tileArea;
|
Rect *tileArea;
|
||||||
|
|
@ -359,7 +387,7 @@ extNbrPushFunc(tile, pla)
|
||||||
tileArea = &pla->area;
|
tileArea = &pla->area;
|
||||||
|
|
||||||
/* Ignore tile if it's already been visited */
|
/* Ignore tile if it's already been visited */
|
||||||
if (TiGetClient(tile) != extNbrUn)
|
if (ExtGetRegion(tile, dinfo) != CD2PTR(pla->uninit))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Only consider tile if it overlaps tileArea or shares part of a side */
|
/* Only consider tile if it overlaps tileArea or shares part of a side */
|
||||||
|
|
@ -372,7 +400,232 @@ extNbrPushFunc(tile, pla)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Push tile on the stack and mark as being visited */
|
/* Push tile on the stack and mark as being visited */
|
||||||
PUSHTILE(tile, pla->plane);
|
PUSHTILE(tile, dinfo, pla->plane);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* extEnumTerminal ---
|
||||||
|
*
|
||||||
|
* Search out an area belonging to a device terminal starting with a given
|
||||||
|
* tile, and running a callback function for each tile found. Note that
|
||||||
|
* this routine is called from inside extEnumTilePerim and so is already
|
||||||
|
* inside an extFindNeighbors() search function. The function must be
|
||||||
|
* careful not to modify regions, as the outer search function depends on
|
||||||
|
* them. Because a device terminal should be a compact area, it is okay
|
||||||
|
* to create a linked list of tiles and use the linked list to reset the
|
||||||
|
* regions at the end, rather than depending on the state of any tile's
|
||||||
|
* ClientData record.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Whatever the callback function does. Specifically, changing tile
|
||||||
|
* ClientData records is *not* supposed to be a side effect of this
|
||||||
|
* function, and all ClientData modifications must be put back exactly
|
||||||
|
* as they were found.
|
||||||
|
*
|
||||||
|
* NOTE: This routine should be called only once for each device terminal.
|
||||||
|
* Once the terminal area and perimeter have been measured, it will not be
|
||||||
|
* called again.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
extEnumTerminal(Tile *tile, /* Starting tile for search */
|
||||||
|
TileType dinfo, /* Split tile information */
|
||||||
|
TileTypeBitMask *connect, /* Pointer to connection table */
|
||||||
|
void (*func)(), /* Callback function */
|
||||||
|
ClientData clientData) /* Client data for callback function */
|
||||||
|
{
|
||||||
|
ExtRegion *termreg;
|
||||||
|
TileAndDinfo *pendlist = NULL, *resetlist = NULL;
|
||||||
|
TileAndDinfo *curtad;
|
||||||
|
const TileTypeBitMask *connectMask;
|
||||||
|
Tile *tp, *t2;
|
||||||
|
TileType tpdi, t2di;
|
||||||
|
TileType loctype, checktype;
|
||||||
|
Rect tileArea;
|
||||||
|
|
||||||
|
/* The region attached to the first terminal tile will be the
|
||||||
|
* "uninitialized" value to check.
|
||||||
|
*/
|
||||||
|
|
||||||
|
termreg = ExtGetRegion(tile, dinfo);
|
||||||
|
/* Set the ClientData to VISITPENDING */
|
||||||
|
ExtSetRegion(tile, dinfo, (ExtRegion *)VISITPENDING);
|
||||||
|
|
||||||
|
/* Start the linked list with this file */
|
||||||
|
curtad = (TileAndDinfo *)mallocMagic(sizeof(TileAndDinfo));
|
||||||
|
curtad->tad_tile = tile;
|
||||||
|
curtad->tad_dinfo = dinfo;
|
||||||
|
curtad->tad_next = NULL;
|
||||||
|
pendlist = curtad;
|
||||||
|
|
||||||
|
/* Yet another boundary search routine. Just done with a linked list
|
||||||
|
* and not a stack because it's expected to search only a handful of
|
||||||
|
* tiles.
|
||||||
|
*/
|
||||||
|
|
||||||
|
while (pendlist != NULL)
|
||||||
|
{
|
||||||
|
tp = pendlist->tad_tile;
|
||||||
|
tpdi = pendlist->tad_dinfo;
|
||||||
|
|
||||||
|
TiToRect(tp, &tileArea);
|
||||||
|
|
||||||
|
/* Call the client function. The function has no return value. */
|
||||||
|
(*func)(tp, tpdi, clientData);
|
||||||
|
|
||||||
|
/* Move this tile entry to reset list */
|
||||||
|
curtad = pendlist;
|
||||||
|
pendlist = pendlist->tad_next;
|
||||||
|
curtad->tad_next = resetlist;
|
||||||
|
resetlist = curtad;
|
||||||
|
|
||||||
|
/* Search all sides of the tile for other tiles having the same
|
||||||
|
* terminal node (same region in the ClientData record),
|
||||||
|
* and add them to the linked list. This code is largely copied
|
||||||
|
* from dbSrConnectFunc(). Note that the connect table is used
|
||||||
|
* because the device's gate node may have the same region but
|
||||||
|
* is not part of the terminal.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (IsSplit(tp))
|
||||||
|
{
|
||||||
|
if (tpdi & TT_SIDE)
|
||||||
|
loctype = SplitRightType(tp);
|
||||||
|
else
|
||||||
|
loctype = SplitLeftType(tp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
loctype = TiGetTypeExact(tp);
|
||||||
|
connectMask = &connect[loctype];
|
||||||
|
|
||||||
|
/* Left side */
|
||||||
|
if (IsSplit(tp) && (tpdi & TT_SIDE)) goto termbottom;
|
||||||
|
|
||||||
|
for (t2 = BL(tp); BOTTOM(t2) < tileArea.r_ytop; t2 = RT(t2))
|
||||||
|
{
|
||||||
|
if (IsSplit(t2))
|
||||||
|
checktype = SplitRightType(t2);
|
||||||
|
else
|
||||||
|
checktype = TiGetTypeExact(t2);
|
||||||
|
if (TTMaskHasType(connectMask, checktype))
|
||||||
|
{
|
||||||
|
t2di = (TileType)TT_SIDE;
|
||||||
|
/* Tile must belong to the terminal node and not been visited */
|
||||||
|
if (ExtGetRegion(t2, t2di) != termreg) continue;
|
||||||
|
/* Add t2 to the linked list */
|
||||||
|
curtad = (TileAndDinfo *)mallocMagic(sizeof(TileAndDinfo));
|
||||||
|
curtad->tad_tile = t2;
|
||||||
|
curtad->tad_dinfo = t2di;
|
||||||
|
curtad->tad_next = pendlist;
|
||||||
|
pendlist = curtad;
|
||||||
|
/* Set the ClientData to VISITPENDING */
|
||||||
|
ExtSetRegion(t2, t2di, (ExtRegion *)VISITPENDING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bottom side */
|
||||||
|
termbottom:
|
||||||
|
if (IsSplit(tp) && ((!((tpdi & TT_SIDE) ? 1 : 0)) ^ SplitDirection(tp)))
|
||||||
|
goto termright;
|
||||||
|
|
||||||
|
for (t2 = LB(tp); LEFT(t2) < tileArea.r_xtop; t2 = TR(t2))
|
||||||
|
{
|
||||||
|
if (IsSplit(t2))
|
||||||
|
checktype = SplitTopType(t2);
|
||||||
|
else
|
||||||
|
checktype = TiGetTypeExact(t2);
|
||||||
|
if (TTMaskHasType(connectMask, checktype))
|
||||||
|
{
|
||||||
|
t2di = SplitDirection(t2) ? (TileType)TT_SIDE : (TileType)0;
|
||||||
|
/* Tile must belong to the terminal node and not been visited */
|
||||||
|
if (ExtGetRegion(t2, t2di) != termreg) continue;
|
||||||
|
/* Add t2 to the linked list */
|
||||||
|
curtad = (TileAndDinfo *)mallocMagic(sizeof(TileAndDinfo));
|
||||||
|
curtad->tad_tile = t2;
|
||||||
|
curtad->tad_dinfo = t2di;
|
||||||
|
curtad->tad_next = pendlist;
|
||||||
|
pendlist = curtad;
|
||||||
|
/* Set the ClientData to VISITPENDING */
|
||||||
|
ExtSetRegion(t2, t2di, (ExtRegion *)VISITPENDING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Right side: */
|
||||||
|
termright:
|
||||||
|
if (IsSplit(tp) && !(tpdi & TT_SIDE)) goto termtop;
|
||||||
|
|
||||||
|
for (t2 = TR(tp); TOP(t2) > tileArea.r_ybot; t2 = LB(t2))
|
||||||
|
{
|
||||||
|
if (IsSplit(t2))
|
||||||
|
checktype = SplitLeftType(t2);
|
||||||
|
else
|
||||||
|
checktype = TiGetTypeExact(t2);
|
||||||
|
if (TTMaskHasType(connectMask, checktype))
|
||||||
|
{
|
||||||
|
t2di = (TileType)0;
|
||||||
|
/* Tile must belong to the terminal node and not been visited */
|
||||||
|
if (ExtGetRegion(t2, t2di) != termreg) continue;
|
||||||
|
/* Add t2 to the linked list */
|
||||||
|
curtad = (TileAndDinfo *)mallocMagic(sizeof(TileAndDinfo));
|
||||||
|
curtad->tad_tile = t2;
|
||||||
|
curtad->tad_dinfo = t2di;
|
||||||
|
curtad->tad_next = pendlist;
|
||||||
|
pendlist = curtad;
|
||||||
|
/* Set the ClientData to VISITPENDING */
|
||||||
|
ExtSetRegion(t2, t2di, (ExtRegion *)VISITPENDING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Top side */
|
||||||
|
termtop:
|
||||||
|
if (IsSplit(tp) && (((tpdi & TT_SIDE) ? 1 : 0) ^ SplitDirection(tp)))
|
||||||
|
goto termdone;
|
||||||
|
|
||||||
|
for (t2 = RT(tp); RIGHT(t2) > tileArea.r_xbot; t2 = BL(t2))
|
||||||
|
{
|
||||||
|
if (IsSplit(t2))
|
||||||
|
checktype = SplitBottomType(t2);
|
||||||
|
else
|
||||||
|
checktype = TiGetTypeExact(t2);
|
||||||
|
if (TTMaskHasType(connectMask, checktype))
|
||||||
|
{
|
||||||
|
t2di = SplitDirection(t2) ? (TileType)0 : (TileType)TT_SIDE;
|
||||||
|
/* Tile must belong to the terminal node and not been visited */
|
||||||
|
if (ExtGetRegion(t2, t2di) != termreg) continue;
|
||||||
|
/* Add t2 to the linked list */
|
||||||
|
curtad = (TileAndDinfo *)mallocMagic(sizeof(TileAndDinfo));
|
||||||
|
curtad->tad_tile = t2;
|
||||||
|
curtad->tad_dinfo = t2di;
|
||||||
|
curtad->tad_next = pendlist;
|
||||||
|
pendlist = curtad;
|
||||||
|
/* Set the ClientData to VISITPENDING */
|
||||||
|
ExtSetRegion(t2, t2di, (ExtRegion *)VISITPENDING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
termdone:
|
||||||
|
/* (continue) */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up---Put the ClientData entries in the tiles back to
|
||||||
|
* term reg and free up the linked list memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
while (resetlist != NULL)
|
||||||
|
{
|
||||||
|
curtad = resetlist->tad_next;
|
||||||
|
ExtSetRegion(resetlist->tad_tile, resetlist->tad_dinfo, termreg);
|
||||||
|
freeMagic(resetlist);
|
||||||
|
resetlist = curtad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "extract/extract.h"
|
#include "extract/extract.h"
|
||||||
#include "extract/extractInt.h"
|
#include "extract/extractInt.h"
|
||||||
|
|
||||||
#define POINTEQUAL(p, q) ((p)->p_x == (q)->p_x && (p)->p_y == (q)->p_y)
|
#define POINTEQUAL(p, q) (((p)->p_x == (q)->p_x) && ((p)->p_y == (q)->p_y))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
|
|
@ -57,7 +57,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
* {
|
* {
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* The value returned by this function is ignored.
|
* The value returned by the callback function is ignored.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* Returns the total length of the portion of the perimeter of
|
* Returns the total length of the portion of the perimeter of
|
||||||
|
|
@ -68,10 +68,10 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
* to each qualifying segment of the boundary.
|
* to each qualifying segment of the boundary.
|
||||||
*
|
*
|
||||||
* Note:
|
* Note:
|
||||||
* The width/length calculation method is manhattan-only. So this
|
* The width/length calculation method is manhattan-only, and will
|
||||||
* routine is pseudo-manhattan. It computes the true non-manhattan
|
* likely need correcting. This routine computes the true perimeter
|
||||||
* perimeter, but calls the function on the perimeter tiles as if
|
* length and calls the callback function on the perimeter tiles of
|
||||||
* the whole tile is the transistor type.
|
* the correct tile type.
|
||||||
*
|
*
|
||||||
* Non-interruptible.
|
* Non-interruptible.
|
||||||
*
|
*
|
||||||
|
|
@ -81,28 +81,34 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
int
|
int
|
||||||
extEnumTilePerim(
|
extEnumTilePerim(
|
||||||
Tile *tpIn,
|
Tile *tpIn,
|
||||||
|
TileType dinfo,
|
||||||
const TileTypeBitMask *maskp,
|
const TileTypeBitMask *maskp,
|
||||||
int pNum, /* Plane of perimeter */
|
int pNum, /* Plane of perimeter */
|
||||||
int (*func)(),
|
int (*func)(),
|
||||||
ClientData cdata)
|
ClientData cdata)
|
||||||
{
|
{
|
||||||
TileTypeBitMask mask = *maskp; /* TTMaskCopy(&mask, maskp) */
|
TileTypeBitMask mask = *maskp;
|
||||||
TileType origType;
|
|
||||||
Tile *tpOut;
|
Tile *tpOut;
|
||||||
int perimCorrect;
|
int perimCorrect;
|
||||||
Boundary b;
|
Boundary b;
|
||||||
unsigned char sides = 0;
|
unsigned char sides = 0; /* Sides to be ignored */
|
||||||
|
|
||||||
b.b_inside = tpIn;
|
b.b_inside = tpIn;
|
||||||
b.b_plane = pNum;
|
b.b_plane = pNum;
|
||||||
perimCorrect = 0;
|
perimCorrect = 0;
|
||||||
|
|
||||||
/* Diagonal */
|
|
||||||
if (IsSplit(tpIn))
|
if (IsSplit(tpIn))
|
||||||
{
|
{
|
||||||
TileType otype = (SplitSide(tpIn)) ? SplitLeftType(tpIn): SplitRightType(tpIn);
|
/* Handle a diagonal boundary across a split tile.
|
||||||
TileType itype = (SplitSide(tpIn)) ? SplitRightType(tpIn): SplitLeftType(tpIn);
|
* "dinfo" determines which side of the split tile is considered "inside" the
|
||||||
origType = TiGetTypeExact(tpIn);
|
* boundary and which is "outside". Invoke the callback function for the
|
||||||
|
* diagonal, then determine which two sides don't need to be searched and
|
||||||
|
* set the corresponding boundary direction bit in "sides".
|
||||||
|
*/
|
||||||
|
|
||||||
|
TileType otype = (dinfo & TT_SIDE) ? SplitLeftType(tpIn): SplitRightType(tpIn);
|
||||||
|
TileType itype = (dinfo & TT_SIDE) ? SplitRightType(tpIn): SplitLeftType(tpIn);
|
||||||
|
|
||||||
if (TTMaskHasType(&mask, otype))
|
if (TTMaskHasType(&mask, otype))
|
||||||
{
|
{
|
||||||
int width = RIGHT(tpIn) - LEFT(tpIn);
|
int width = RIGHT(tpIn) - LEFT(tpIn);
|
||||||
|
|
@ -110,14 +116,40 @@ extEnumTilePerim(
|
||||||
perimCorrect = width * width + height * height;
|
perimCorrect = width * width + height * height;
|
||||||
perimCorrect = (int)sqrt((double)perimCorrect);
|
perimCorrect = (int)sqrt((double)perimCorrect);
|
||||||
}
|
}
|
||||||
sides = (SplitSide(tpIn)) ? BD_LEFT : BD_RIGHT;
|
|
||||||
sides |= (SplitSide(tpIn) == SplitDirection(tpIn)) ? BD_BOTTOM : BD_TOP;
|
/* Invoke the callback function on diagonal boundaries */
|
||||||
TiSetBody(tpIn, itype);
|
|
||||||
|
b.b_outside = tpIn; /* Same tile on both sides of the boundary */
|
||||||
|
TiToRect(tpIn, &b.b_segment);
|
||||||
|
|
||||||
|
if (SplitDirection(tpIn))
|
||||||
|
{
|
||||||
|
if (dinfo & TT_SIDE)
|
||||||
|
b.b_direction = BD_NE;
|
||||||
|
else
|
||||||
|
b.b_direction = BD_SW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (dinfo & TT_SIDE)
|
||||||
|
b.b_direction = BD_SE;
|
||||||
|
else
|
||||||
|
b.b_direction = BD_NW;
|
||||||
|
}
|
||||||
|
if (func) (*func)(&b, cdata);
|
||||||
|
|
||||||
|
/* Flag which two sides of the tile don't need searching */
|
||||||
|
|
||||||
|
sides = (dinfo & TT_SIDE) ? BD_LEFT : BD_RIGHT;
|
||||||
|
sides |= (((dinfo & TT_SIDE) ? 1 : 0) == SplitDirection(tpIn)) ?
|
||||||
|
BD_BOTTOM : BD_TOP;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sides = 0;
|
sides = 0;
|
||||||
|
|
||||||
/* Top */
|
/* Top */
|
||||||
|
if (!(sides & BD_TOP))
|
||||||
|
{
|
||||||
b.b_segment.r_ybot = b.b_segment.r_ytop = TOP(tpIn);
|
b.b_segment.r_ybot = b.b_segment.r_ytop = TOP(tpIn);
|
||||||
b.b_direction = BD_TOP;
|
b.b_direction = BD_TOP;
|
||||||
for (tpOut = RT(tpIn); RIGHT(tpOut) > LEFT(tpIn); tpOut = BL(tpOut))
|
for (tpOut = RT(tpIn); RIGHT(tpOut) > LEFT(tpIn); tpOut = BL(tpOut))
|
||||||
|
|
@ -127,12 +159,14 @@ extEnumTilePerim(
|
||||||
b.b_segment.r_xbot = MAX(LEFT(tpIn), LEFT(tpOut));
|
b.b_segment.r_xbot = MAX(LEFT(tpIn), LEFT(tpOut));
|
||||||
b.b_segment.r_xtop = MIN(RIGHT(tpIn), RIGHT(tpOut));
|
b.b_segment.r_xtop = MIN(RIGHT(tpIn), RIGHT(tpOut));
|
||||||
b.b_outside = tpOut;
|
b.b_outside = tpOut;
|
||||||
if (sides & BD_TOP) perimCorrect -= BoundaryLength(&b);
|
|
||||||
if (func) (*func)(&b, cdata);
|
if (func) (*func)(&b, cdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Bottom */
|
/* Bottom */
|
||||||
|
if (!(sides & BD_BOTTOM))
|
||||||
|
{
|
||||||
b.b_segment.r_ybot = b.b_segment.r_ytop = BOTTOM(tpIn);
|
b.b_segment.r_ybot = b.b_segment.r_ytop = BOTTOM(tpIn);
|
||||||
b.b_direction = BD_BOTTOM;
|
b.b_direction = BD_BOTTOM;
|
||||||
for (tpOut = LB(tpIn); LEFT(tpOut) < RIGHT(tpIn); tpOut = TR(tpOut))
|
for (tpOut = LB(tpIn); LEFT(tpOut) < RIGHT(tpIn); tpOut = TR(tpOut))
|
||||||
|
|
@ -142,12 +176,14 @@ extEnumTilePerim(
|
||||||
b.b_segment.r_xbot = MAX(LEFT(tpIn), LEFT(tpOut));
|
b.b_segment.r_xbot = MAX(LEFT(tpIn), LEFT(tpOut));
|
||||||
b.b_segment.r_xtop = MIN(RIGHT(tpIn), RIGHT(tpOut));
|
b.b_segment.r_xtop = MIN(RIGHT(tpIn), RIGHT(tpOut));
|
||||||
b.b_outside = tpOut;
|
b.b_outside = tpOut;
|
||||||
if (sides & BD_BOTTOM) perimCorrect -= BoundaryLength(&b);
|
|
||||||
if (func) (*func)(&b, cdata);
|
if (func) (*func)(&b, cdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Left */
|
/* Left */
|
||||||
|
if (!(sides & BD_LEFT))
|
||||||
|
{
|
||||||
b.b_segment.r_xbot = b.b_segment.r_xtop = LEFT(tpIn);
|
b.b_segment.r_xbot = b.b_segment.r_xtop = LEFT(tpIn);
|
||||||
b.b_direction = BD_LEFT;
|
b.b_direction = BD_LEFT;
|
||||||
for (tpOut = BL(tpIn); BOTTOM(tpOut) < TOP(tpIn); tpOut = RT(tpOut))
|
for (tpOut = BL(tpIn); BOTTOM(tpOut) < TOP(tpIn); tpOut = RT(tpOut))
|
||||||
|
|
@ -157,12 +193,14 @@ extEnumTilePerim(
|
||||||
b.b_segment.r_ybot = MAX(BOTTOM(tpIn), BOTTOM(tpOut));
|
b.b_segment.r_ybot = MAX(BOTTOM(tpIn), BOTTOM(tpOut));
|
||||||
b.b_segment.r_ytop = MIN(TOP(tpIn), TOP(tpOut));
|
b.b_segment.r_ytop = MIN(TOP(tpIn), TOP(tpOut));
|
||||||
b.b_outside = tpOut;
|
b.b_outside = tpOut;
|
||||||
if (sides & BD_LEFT) perimCorrect -= BoundaryLength(&b);
|
|
||||||
if (func) (*func)(&b, cdata);
|
if (func) (*func)(&b, cdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Right */
|
/* Right */
|
||||||
|
if (!(sides & BD_RIGHT))
|
||||||
|
{
|
||||||
b.b_segment.r_xbot = b.b_segment.r_xtop = RIGHT(tpIn);
|
b.b_segment.r_xbot = b.b_segment.r_xtop = RIGHT(tpIn);
|
||||||
b.b_direction = BD_RIGHT;
|
b.b_direction = BD_RIGHT;
|
||||||
for (tpOut = TR(tpIn); TOP(tpOut) > BOTTOM(tpIn); tpOut = LB(tpOut))
|
for (tpOut = TR(tpIn); TOP(tpOut) > BOTTOM(tpIn); tpOut = LB(tpOut))
|
||||||
|
|
@ -172,13 +210,10 @@ extEnumTilePerim(
|
||||||
b.b_segment.r_ybot = MAX(BOTTOM(tpIn), BOTTOM(tpOut));
|
b.b_segment.r_ybot = MAX(BOTTOM(tpIn), BOTTOM(tpOut));
|
||||||
b.b_segment.r_ytop = MIN(TOP(tpIn), TOP(tpOut));
|
b.b_segment.r_ytop = MIN(TOP(tpIn), TOP(tpOut));
|
||||||
b.b_outside = tpOut;
|
b.b_outside = tpOut;
|
||||||
if (sides & BD_RIGHT) perimCorrect -= BoundaryLength(&b);
|
|
||||||
if (func) (*func)(&b, cdata);
|
if (func) (*func)(&b, cdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (sides != 0)
|
|
||||||
TiSetBody(tpIn, origType);
|
|
||||||
|
|
||||||
return (perimCorrect);
|
return (perimCorrect);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,58 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "extract/extractInt.h"
|
#include "extract/extractInt.h"
|
||||||
#include "utils/signals.h"
|
#include "utils/signals.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* ExtGetRegion ---
|
||||||
|
*
|
||||||
|
* Get the region from the ClientData of a tile. Normally this is just the
|
||||||
|
* ClientData record recast as an ExtRegion pointer. However, if the tile
|
||||||
|
* is split and neither tile side is TT_SPACE, then the Tile will be given
|
||||||
|
* an ExtSplitRegion structure, and the returned region depends on the side
|
||||||
|
* specified by "dinfo" (bit TT_SIDE).
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* Returns the tile's client data record cast to a region pointer.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* This routine was previously implemented as an in-line definition
|
||||||
|
* "extGetRegion(Tile *tp)".
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
ExtRegion *
|
||||||
|
ExtGetRegion(Tile *tp, /* Tile to get region record from */
|
||||||
|
TileType dinfo) /* Split tile information, if relevant */
|
||||||
|
{
|
||||||
|
ExtSplitRegion *esr;
|
||||||
|
|
||||||
|
if (IsSplit(tp))
|
||||||
|
{
|
||||||
|
if ((TiGetLeftType(tp) == TT_SPACE) || (TiGetRightType(tp) == TT_SPACE))
|
||||||
|
return (ExtRegion *)tp->ti_client;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
esr = (ExtSplitRegion *)tp->ti_client;
|
||||||
|
|
||||||
|
/* If this tile has not been handled and no ExtSplitRegion has
|
||||||
|
* been created, then ti_client should be either CLIENTDEFAULT
|
||||||
|
* or VISITPENDING. It should not have any other values.
|
||||||
|
*/
|
||||||
|
if ((ClientData)esr == CLIENTDEFAULT)
|
||||||
|
return CD2PTR(CLIENTDEFAULT);
|
||||||
|
else if ((ClientData)esr == VISITPENDING)
|
||||||
|
return CD2PTR(VISITPENDING);
|
||||||
|
return (dinfo & TT_SIDE) ? esr->reg_right : esr->reg_left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return (ExtRegion *)tp->ti_client;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -53,6 +105,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
* ExtRegion *
|
* ExtRegion *
|
||||||
* (*first)(tile, arg)
|
* (*first)(tile, arg)
|
||||||
* Tile *tile; /# Tile is on plane arg->fra_pNum #/
|
* Tile *tile; /# Tile is on plane arg->fra_pNum #/
|
||||||
|
* TileType dinfo; /# Split tile information #/
|
||||||
* FindRegion *arg;
|
* FindRegion *arg;
|
||||||
* {
|
* {
|
||||||
* }
|
* }
|
||||||
|
|
@ -62,6 +115,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
*
|
*
|
||||||
* (*each)(tile, planeNum, arg)
|
* (*each)(tile, planeNum, arg)
|
||||||
* Tile *tile;
|
* Tile *tile;
|
||||||
|
* TileType dinfo; /# Split tile information #/
|
||||||
* int planeNum; /# May be different than arg->fra_pNum #/
|
* int planeNum; /# May be different than arg->fra_pNum #/
|
||||||
* FindRegion *arg;
|
* FindRegion *arg;
|
||||||
* {
|
* {
|
||||||
|
|
@ -85,7 +139,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ExtRegion *
|
ExtRegion *
|
||||||
ExtFindRegions(def, area, mask, connectsTo, uninit, first, each)
|
ExtFindRegions(def, area, mask, connectsTo, first, each)
|
||||||
CellDef *def; /* Cell definition being searched */
|
CellDef *def; /* Cell definition being searched */
|
||||||
Rect *area; /* Area to search initially for tiles */
|
Rect *area; /* Area to search initially for tiles */
|
||||||
TileTypeBitMask *mask; /* In the initial area search, only visit
|
TileTypeBitMask *mask; /* In the initial area search, only visit
|
||||||
|
|
@ -101,9 +155,6 @@ ExtFindRegions(def, area, mask, connectsTo, uninit, first, each)
|
||||||
* so this is the same as:
|
* so this is the same as:
|
||||||
* TTMaskHasType(&connectsTo[t2], t1)
|
* TTMaskHasType(&connectsTo[t2], t1)
|
||||||
*/
|
*/
|
||||||
ClientData uninit; /* Contents of a ti_client field indicating
|
|
||||||
* that the tile has not yet been visited.
|
|
||||||
*/
|
|
||||||
ExtRegion * (*first)(); /* Applied to first tile in region */
|
ExtRegion * (*first)(); /* Applied to first tile in region */
|
||||||
int (*each)(); /* Applied to each tile in region */
|
int (*each)(); /* Applied to each tile in region */
|
||||||
{
|
{
|
||||||
|
|
@ -113,7 +164,7 @@ ExtFindRegions(def, area, mask, connectsTo, uninit, first, each)
|
||||||
ASSERT(first != NULL, "ExtFindRegions");
|
ASSERT(first != NULL, "ExtFindRegions");
|
||||||
arg.fra_connectsTo = connectsTo;
|
arg.fra_connectsTo = connectsTo;
|
||||||
arg.fra_def = def;
|
arg.fra_def = def;
|
||||||
arg.fra_uninit = uninit;
|
arg.fra_uninit = CLIENTDEFAULT;
|
||||||
arg.fra_first = first;
|
arg.fra_first = first;
|
||||||
arg.fra_each = each;
|
arg.fra_each = each;
|
||||||
arg.fra_region = (ExtRegion *) NULL;
|
arg.fra_region = (ExtRegion *) NULL;
|
||||||
|
|
@ -124,7 +175,7 @@ ExtFindRegions(def, area, mask, connectsTo, uninit, first, each)
|
||||||
SigDisableInterrupts();
|
SigDisableInterrupts();
|
||||||
for (arg.fra_pNum=PL_TECHDEPBASE; arg.fra_pNum<DBNumPlanes; arg.fra_pNum++)
|
for (arg.fra_pNum=PL_TECHDEPBASE; arg.fra_pNum<DBNumPlanes; arg.fra_pNum++)
|
||||||
(void) DBSrPaintClient((Tile *) NULL, def->cd_planes[arg.fra_pNum],
|
(void) DBSrPaintClient((Tile *) NULL, def->cd_planes[arg.fra_pNum],
|
||||||
area, mask, uninit, extRegionAreaFunc, (ClientData) &arg);
|
area, mask, CLIENTDEFAULT, extRegionAreaFunc, (ClientData) &arg);
|
||||||
SigEnableInterrupts();
|
SigEnableInterrupts();
|
||||||
|
|
||||||
return (arg.fra_region);
|
return (arg.fra_region);
|
||||||
|
|
@ -155,19 +206,20 @@ ExtFindRegions(def, area, mask, connectsTo, uninit, first, each)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extRegionAreaFunc(tile, arg)
|
extRegionAreaFunc(tile, dinfo, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
FindRegion *arg;
|
FindRegion *arg;
|
||||||
{
|
{
|
||||||
/* Allocate a new region */
|
/* Allocate a new region */
|
||||||
if (arg->fra_first)
|
if (arg->fra_first)
|
||||||
(void) (*arg->fra_first)(tile, arg);
|
(void) (*arg->fra_first)(tile, dinfo, arg);
|
||||||
|
|
||||||
if (DebugIsSet(extDebugID, extDebAreaEnum))
|
if (DebugIsSet(extDebugID, extDebAreaEnum))
|
||||||
extShowTile(tile, "area enum", 0);
|
extShowTile(tile, "area enum", 0);
|
||||||
|
|
||||||
/* Recursively visit all tiles surrounding this one that we connect to */
|
/* Recursively visit all tiles surrounding this one that we connect to */
|
||||||
(void) ExtFindNeighbors(tile, arg->fra_pNum, arg);
|
(void) ExtFindNeighbors(tile, dinfo, arg->fra_pNum, arg);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,7 +232,7 @@ extRegionAreaFunc(tile, arg)
|
||||||
* Given a CellDef whose tiles have been set to point to LabRegions
|
* Given a CellDef whose tiles have been set to point to LabRegions
|
||||||
* by ExtFindRegions, walk down the label list and assign labels
|
* by ExtFindRegions, walk down the label list and assign labels
|
||||||
* to regions. If the tile over which a label lies is still uninitialized
|
* to regions. If the tile over which a label lies is still uninitialized
|
||||||
* ie, points to extUnInit, we skip the label.
|
* ie, points to CLIENTDEFAULT, we skip the label.
|
||||||
*
|
*
|
||||||
* A label is attached to the LabRegion for a tile if the label's
|
* A label is attached to the LabRegion for a tile if the label's
|
||||||
* type and the tile's type are connected according to the table
|
* type and the tile's type are connected according to the table
|
||||||
|
|
@ -245,10 +297,10 @@ ExtLabelRegions(def, connTo, nodeList, clipArea)
|
||||||
GOTOPOINT(tp, &p);
|
GOTOPOINT(tp, &p);
|
||||||
PlaneSetHint(def->cd_planes[pNum], tp);
|
PlaneSetHint(def->cd_planes[pNum], tp);
|
||||||
if (extConnectsTo(TiGetType(tp), lab->lab_type, connTo)
|
if (extConnectsTo(TiGetType(tp), lab->lab_type, connTo)
|
||||||
&& extHasRegion(tp, extUnInit))
|
&& extHasRegion(tp, CLIENTDEFAULT))
|
||||||
{
|
{
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
reg = (LabRegion *) extGetRegion(tp);
|
reg = (LabRegion *) ExtGetRegion(tp, (TileType)0);
|
||||||
ll = (LabelList *) mallocMagic((unsigned) (sizeof (LabelList)));
|
ll = (LabelList *) mallocMagic((unsigned) (sizeof (LabelList)));
|
||||||
ll->ll_label = lab;
|
ll->ll_label = lab;
|
||||||
if (lab->lab_flags & PORT_DIR_MASK)
|
if (lab->lab_flags & PORT_DIR_MASK)
|
||||||
|
|
@ -412,7 +464,7 @@ ExtLabelOneRegion(def, connTo, reg)
|
||||||
GOTOPOINT(tp, &p);
|
GOTOPOINT(tp, &p);
|
||||||
PlaneSetHint(def->cd_planes[pNum], tp);
|
PlaneSetHint(def->cd_planes[pNum], tp);
|
||||||
if (extConnectsTo(TiGetType(tp), lab->lab_type, connTo)
|
if (extConnectsTo(TiGetType(tp), lab->lab_type, connTo)
|
||||||
&& (NodeRegion *) extGetRegion(tp) == reg)
|
&& (NodeRegion *) ExtGetRegion(tp, (TileType)0) == reg)
|
||||||
{
|
{
|
||||||
ll = (LabelList *) mallocMagic((unsigned) (sizeof (LabelList)));
|
ll = (LabelList *) mallocMagic((unsigned) (sizeof (LabelList)));
|
||||||
ll->ll_label = lab;
|
ll->ll_label = lab;
|
||||||
|
|
@ -444,7 +496,6 @@ ExtLabelOneRegion(def, connTo, reg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -475,7 +526,7 @@ ExtResetTiles(def, resetTo)
|
||||||
int pNum;
|
int pNum;
|
||||||
|
|
||||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||||
DBResetTilePlane(def->cd_planes[pNum], resetTo);
|
DBResetTilePlaneSpecial(def->cd_planes[pNum], resetTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,7 @@ extSubtree(parentUse, reg, f)
|
||||||
ha.ha_parentUse = parentUse;
|
ha.ha_parentUse = parentUse;
|
||||||
ha.ha_parentReg = reg;
|
ha.ha_parentReg = reg;
|
||||||
ha.ha_nodename = extSubtreeTileToNode;
|
ha.ha_nodename = extSubtreeTileToNode;
|
||||||
|
ha.ha_interArea = GeoNullRect;
|
||||||
ha.ha_cumFlat.et_use = extYuseCum;
|
ha.ha_cumFlat.et_use = extYuseCum;
|
||||||
HashInit(&ha.ha_connHash, 32, 0);
|
HashInit(&ha.ha_connHash, 32, 0);
|
||||||
|
|
||||||
|
|
@ -250,6 +251,17 @@ extSubtree(parentUse, reg, f)
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
/* If result == FALSE then ha.ha_interArea is invalid. */
|
/* If result == FALSE then ha.ha_interArea is invalid. */
|
||||||
ha.ha_interArea = rlab;
|
ha.ha_interArea = rlab;
|
||||||
|
/* Ensure that the interaction area is not zero */
|
||||||
|
if (ha.ha_interArea.r_xtop - ha.ha_interArea.r_xbot == 0)
|
||||||
|
{
|
||||||
|
ha.ha_interArea.r_xtop++;
|
||||||
|
ha.ha_interArea.r_xbot--;
|
||||||
|
}
|
||||||
|
if (ha.ha_interArea.r_ytop - ha.ha_interArea.r_ybot == 0)
|
||||||
|
{
|
||||||
|
ha.ha_interArea.r_ytop++;
|
||||||
|
ha.ha_interArea.r_ybot--;
|
||||||
|
}
|
||||||
result = 1;
|
result = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -345,8 +357,9 @@ done:
|
||||||
|
|
||||||
#ifdef exactinteractions
|
#ifdef exactinteractions
|
||||||
int
|
int
|
||||||
extSubtreeCopyPlane(tile, plane)
|
extSubtreeCopyPlane(tile, dinfo, plane)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
Plane *plane;
|
Plane *plane;
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
@ -358,8 +371,9 @@ extSubtreeCopyPlane(tile, plane)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
extSubtreeShrinkPlane(tile, plane)
|
extSubtreeShrinkPlane(tile, dinfo, plane)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
Plane *plane;
|
Plane *plane;
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
@ -374,8 +388,9 @@ extSubtreeShrinkPlane(tile, plane)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
extSubtreeInterFunc(tile, ha)
|
extSubtreeInterFunc(tile, dinfo, ha)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
HierExtractArg *ha;
|
HierExtractArg *ha;
|
||||||
{
|
{
|
||||||
TITORECT(tile, &ha->ha_interArea);
|
TITORECT(tile, &ha->ha_interArea);
|
||||||
|
|
@ -684,18 +699,22 @@ extSubtreeOutputCoupling(ha)
|
||||||
HashStartSearch(&hs);
|
HashStartSearch(&hs);
|
||||||
while ((he = HashNext(&ha->ha_cumFlat.et_coupleHash, &hs)))
|
while ((he = HashNext(&ha->ha_cumFlat.et_coupleHash, &hs)))
|
||||||
{
|
{
|
||||||
|
TileType dinfo;
|
||||||
|
|
||||||
cap = extGetCapValue(he) / ExtCurStyle->exts_capScale;
|
cap = extGetCapValue(he) / ExtCurStyle->exts_capScale;
|
||||||
if (cap == 0)
|
if (cap == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ck = (CoupleKey *) he->h_key.h_words;
|
ck = (CoupleKey *) he->h_key.h_words;
|
||||||
|
|
||||||
tp = extNodeToTile(ck->ck_1, &ha->ha_cumFlat);
|
tp = extNodeToTile(ck->ck_1, &ha->ha_cumFlat, &dinfo);
|
||||||
name = extSubtreeTileToNode(tp, ck->ck_1->nreg_pnum, &ha->ha_cumFlat, ha, TRUE);
|
name = extSubtreeTileToNode(tp, dinfo, ck->ck_1->nreg_pnum,
|
||||||
|
&ha->ha_cumFlat, ha, TRUE);
|
||||||
fprintf(ha->ha_outf, "cap \"%s\" ", name);
|
fprintf(ha->ha_outf, "cap \"%s\" ", name);
|
||||||
|
|
||||||
tp = extNodeToTile(ck->ck_2, &ha->ha_cumFlat);
|
tp = extNodeToTile(ck->ck_2, &ha->ha_cumFlat, &dinfo);
|
||||||
name = extSubtreeTileToNode(tp, ck->ck_2->nreg_pnum, &ha->ha_cumFlat, ha, TRUE);
|
name = extSubtreeTileToNode(tp, dinfo, ck->ck_2->nreg_pnum,
|
||||||
|
&ha->ha_cumFlat, ha, TRUE);
|
||||||
fprintf(ha->ha_outf, "\"%s\" %lg\n", name, cap);
|
fprintf(ha->ha_outf, "\"%s\" %lg\n", name, cap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -713,8 +732,9 @@ extSubtreeOutputCoupling(ha)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extFoundProc(tile, clientData)
|
extFoundProc(tile, dinfo, clientData)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
ClientData clientData;
|
ClientData clientData;
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -770,6 +790,7 @@ extSubtreeFunc(scx, ha)
|
||||||
*/
|
*/
|
||||||
ha->ha_subArea = use->cu_bbox;
|
ha->ha_subArea = use->cu_bbox;
|
||||||
GEOCLIP(&ha->ha_subArea, &ha->ha_interArea);
|
GEOCLIP(&ha->ha_subArea, &ha->ha_interArea);
|
||||||
|
|
||||||
hy.hy_area = &ha->ha_subArea;
|
hy.hy_area = &ha->ha_subArea;
|
||||||
hy.hy_target = oneFlat->et_use;
|
hy.hy_target = oneFlat->et_use;
|
||||||
hy.hy_prefix = TRUE;
|
hy.hy_prefix = TRUE;
|
||||||
|
|
@ -882,7 +903,7 @@ extSubtreeFunc(scx, ha)
|
||||||
(NodeRegion *) ExtFindRegions(cumUse->cu_def, &TiPlaneRect,
|
(NodeRegion *) ExtFindRegions(cumUse->cu_def, &TiPlaneRect,
|
||||||
&ExtCurStyle->exts_activeTypes,
|
&ExtCurStyle->exts_activeTypes,
|
||||||
ExtCurStyle->exts_nodeConn,
|
ExtCurStyle->exts_nodeConn,
|
||||||
extUnInit, extHierLabFirst, (int (*)()) NULL);
|
extHierLabFirst, (int (*)()) NULL);
|
||||||
ExtLabelRegions(cumUse->cu_def, ExtCurStyle->exts_nodeConn,
|
ExtLabelRegions(cumUse->cu_def, ExtCurStyle->exts_nodeConn,
|
||||||
&(ha->ha_cumFlat.et_nodes), &TiPlaneRect);
|
&(ha->ha_cumFlat.et_nodes), &TiPlaneRect);
|
||||||
}
|
}
|
||||||
|
|
@ -919,7 +940,7 @@ extSubtreeFunc(scx, ha)
|
||||||
/* Free the cumulative node list we extracted above */
|
/* Free the cumulative node list we extracted above */
|
||||||
if (ha->ha_cumFlat.et_nodes)
|
if (ha->ha_cumFlat.et_nodes)
|
||||||
{
|
{
|
||||||
ExtResetTiles(cumUse->cu_def, extUnInit);
|
ExtResetTiles(cumUse->cu_def, CLIENTDEFAULT);
|
||||||
ExtFreeLabRegions((LabRegion *) ha->ha_cumFlat.et_nodes);
|
ExtFreeLabRegions((LabRegion *) ha->ha_cumFlat.et_nodes);
|
||||||
ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL;
|
ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -1040,8 +1061,9 @@ extSubstrateFunc(scx, ha)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
extSubtreeTileToNode(tp, pNum, et, ha, doHard)
|
extSubtreeTileToNode(tp, dinfo, pNum, et, ha, doHard)
|
||||||
Tile *tp; /* Tile whose node name is to be found */
|
Tile *tp; /* Tile whose node name is to be found */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
int pNum; /* Plane of the tile */
|
int pNum; /* Plane of the tile */
|
||||||
ExtTree *et; /* Yank buffer to search */
|
ExtTree *et; /* Yank buffer to search */
|
||||||
HierExtractArg *ha; /* Extraction context */
|
HierExtractArg *ha; /* Extraction context */
|
||||||
|
|
@ -1061,9 +1083,9 @@ extSubtreeTileToNode(tp, pNum, et, ha, doHard)
|
||||||
TileType ttype;
|
TileType ttype;
|
||||||
|
|
||||||
/* If there is a label list, use it */
|
/* If there is a label list, use it */
|
||||||
if (extHasRegion(tp, extUnInit))
|
if (extHasRegion(tp, CLIENTDEFAULT))
|
||||||
{
|
{
|
||||||
reg = (LabRegion *) extGetRegion(tp);
|
reg = (LabRegion *) ExtGetRegion(tp, dinfo);
|
||||||
if (reg->lreg_labels)
|
if (reg->lreg_labels)
|
||||||
return (extNodeName(reg));
|
return (extNodeName(reg));
|
||||||
}
|
}
|
||||||
|
|
@ -1080,12 +1102,7 @@ extSubtreeTileToNode(tp, pNum, et, ha, doHard)
|
||||||
* can cause problems.
|
* can cause problems.
|
||||||
*/
|
*/
|
||||||
if (IsSplit(tp))
|
if (IsSplit(tp))
|
||||||
{
|
ttype = (dinfo & TT_SIDE) ? SplitRightType(tp) : SplitLeftType(tp);
|
||||||
if (SplitSide(tp))
|
|
||||||
ttype = SplitRightType(tp);
|
|
||||||
else
|
|
||||||
ttype = SplitLeftType(tp);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
ttype = TiGetTypeExact(tp);
|
ttype = TiGetTypeExact(tp);
|
||||||
|
|
||||||
|
|
@ -1095,7 +1112,7 @@ extSubtreeTileToNode(tp, pNum, et, ha, doHard)
|
||||||
{
|
{
|
||||||
if (DBSrPaintNMArea((Tile *) NULL,
|
if (DBSrPaintNMArea((Tile *) NULL,
|
||||||
et->et_lookNames->cd_planes[pNum],
|
et->et_lookNames->cd_planes[pNum],
|
||||||
TiGetTypeExact(tp), &r, &DBAllButSpaceBits,
|
TiGetTypeExact(tp) | dinfo, &r, &DBAllButSpaceBits,
|
||||||
extConnFindFunc, (ClientData) ®))
|
extConnFindFunc, (ClientData) ®))
|
||||||
{
|
{
|
||||||
if (SigInterruptPending)
|
if (SigInterruptPending)
|
||||||
|
|
@ -1119,8 +1136,8 @@ extSubtreeTileToNode(tp, pNum, et, ha, doHard)
|
||||||
|
|
||||||
/* We have to do it the hard way */
|
/* We have to do it the hard way */
|
||||||
if (!doHard) return ((char *) NULL);
|
if (!doHard) return ((char *) NULL);
|
||||||
if (extHasRegion(tp, extUnInit)
|
if (extHasRegion(tp, CLIENTDEFAULT)
|
||||||
&& (reg = extSubtreeHardNode(tp, pNum, et, ha)))
|
&& (reg = extSubtreeHardNode(tp, dinfo, pNum, et, ha)))
|
||||||
{
|
{
|
||||||
if (ExtDoWarn & EXTWARN_LABELS)
|
if (ExtDoWarn & EXTWARN_LABELS)
|
||||||
{
|
{
|
||||||
|
|
@ -1154,13 +1171,14 @@ extSubtreeTileToNode(tp, pNum, et, ha, doHard)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extConnFindFunc(tp, preg)
|
extConnFindFunc(tp, dinfo, preg)
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
|
TileType dinfo; // Unused, but needs to be handled
|
||||||
LabRegion **preg;
|
LabRegion **preg;
|
||||||
{
|
{
|
||||||
if (extHasRegion(tp, extUnInit))
|
if (extHasRegion(tp, CLIENTDEFAULT))
|
||||||
{
|
{
|
||||||
*preg = (LabRegion *) extGetRegion(tp);
|
*preg = (LabRegion *)ExtGetRegion(tp, dinfo);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1198,13 +1216,14 @@ extConnFindFunc(tp, preg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
LabRegion *
|
LabRegion *
|
||||||
extSubtreeHardNode(tp, pNum, et, ha)
|
extSubtreeHardNode(tp, dinfo, pNum, et, ha)
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
|
TileType dinfo;
|
||||||
int pNum;
|
int pNum;
|
||||||
ExtTree *et;
|
ExtTree *et;
|
||||||
HierExtractArg *ha;
|
HierExtractArg *ha;
|
||||||
{
|
{
|
||||||
LabRegion *lreg = (LabRegion *) extGetRegion(tp);
|
LabRegion *lreg = (LabRegion *) ExtGetRegion(tp, dinfo);
|
||||||
CellDef *def = et->et_use->cu_def;
|
CellDef *def = et->et_use->cu_def;
|
||||||
TileType ttype;
|
TileType ttype;
|
||||||
char labelBuf[4096];
|
char labelBuf[4096];
|
||||||
|
|
@ -1215,7 +1234,7 @@ extSubtreeHardNode(tp, pNum, et, ha)
|
||||||
|
|
||||||
if (IsSplit(tp))
|
if (IsSplit(tp))
|
||||||
{
|
{
|
||||||
if (SplitSide(tp))
|
if (dinfo & TT_SIDE)
|
||||||
ttype = SplitRightType(tp);
|
ttype = SplitRightType(tp);
|
||||||
else
|
else
|
||||||
ttype = SplitLeftType(tp);
|
ttype = SplitLeftType(tp);
|
||||||
|
|
|
||||||
|
|
@ -1368,7 +1368,7 @@ ExtTechSimplePerimCap(argc, argv)
|
||||||
|
|
||||||
if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder)
|
if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder)
|
||||||
{
|
{
|
||||||
TechError("Cannot parse area cap line without plane ordering!\n");
|
TechError("Cannot parse perimeter cap line without plane ordering!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1376,9 +1376,14 @@ ExtTechSimplePerimCap(argc, argv)
|
||||||
TTMaskSetMask(allExtractTypes, &types);
|
TTMaskSetMask(allExtractTypes, &types);
|
||||||
plane1 = DBTechNoisyNamePlane(argv[2]);
|
plane1 = DBTechNoisyNamePlane(argv[2]);
|
||||||
|
|
||||||
TTMaskCom2(¬types, &types);
|
/* As part of the "simple perimeter" simplifications, "nottypes" can
|
||||||
|
* only be space. This prevents perimeter edges from being seen
|
||||||
|
* between, e.g., poly and transistor gates, or metal and metal
|
||||||
|
* resistors.
|
||||||
|
*/
|
||||||
|
TTMaskSetOnlyType(¬types, TT_SPACE);
|
||||||
|
|
||||||
TTMaskAndMask(&types, &DBPlaneTypes[plane1]);
|
TTMaskAndMask(&types, &DBPlaneTypes[plane1]);
|
||||||
TTMaskAndMask(¬types, &DBPlaneTypes[plane1]);
|
|
||||||
|
|
||||||
capVal = aToCap(argv[argc - 1]);
|
capVal = aToCap(argv[argc - 1]);
|
||||||
|
|
||||||
|
|
@ -1632,7 +1637,7 @@ ExtTechSimpleOverlapCap(argv)
|
||||||
|
|
||||||
if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder)
|
if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder)
|
||||||
{
|
{
|
||||||
TechError("Cannot parse area cap line without plane ordering!\n");
|
TechError("Cannot parse overlap cap line without plane ordering!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1732,7 +1737,7 @@ ExtTechSimpleSideOverlapCap(argv)
|
||||||
|
|
||||||
if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder)
|
if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder)
|
||||||
{
|
{
|
||||||
TechError("Cannot parse area cap line without plane ordering!\n");
|
TechError("Cannot parse side overlap cap line without plane ordering!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1740,9 +1745,14 @@ ExtTechSimpleSideOverlapCap(argv)
|
||||||
TTMaskSetMask(allExtractTypes, &types);
|
TTMaskSetMask(allExtractTypes, &types);
|
||||||
plane1 = DBTechNoisyNamePlane(argv[2]);
|
plane1 = DBTechNoisyNamePlane(argv[2]);
|
||||||
|
|
||||||
TTMaskCom2(¬types, &types);
|
/* As part of the "simple sideoverlap" simplifications, "nottypes"
|
||||||
|
* can only be space. This prevents perimeter edges from being
|
||||||
|
* seen between, e.g., poly and transistor gates, or metal and
|
||||||
|
* metal resistors.
|
||||||
|
*/
|
||||||
|
TTMaskSetOnlyType(¬types, TT_SPACE);
|
||||||
|
|
||||||
TTMaskAndMask(&types, &DBPlaneTypes[plane1]);
|
TTMaskAndMask(&types, &DBPlaneTypes[plane1]);
|
||||||
TTMaskAndMask(¬types, &DBPlaneTypes[plane1]);
|
|
||||||
|
|
||||||
DBTechNoisyNameMask(argv[3], &ov);
|
DBTechNoisyNameMask(argv[3], &ov);
|
||||||
TTMaskSetMask(allExtractTypes, &ov);
|
TTMaskSetMask(allExtractTypes, &ov);
|
||||||
|
|
@ -2747,24 +2757,34 @@ ExtTechLine(sectionName, argc, argv)
|
||||||
DBTechNoisyNameMask(argv[4], &termtypes[0]); /* bottom */
|
DBTechNoisyNameMask(argv[4], &termtypes[0]); /* bottom */
|
||||||
TTMaskSetMask(allExtractTypes, &termtypes[0]);
|
TTMaskSetMask(allExtractTypes, &termtypes[0]);
|
||||||
termtypes[1] = DBZeroTypeBits;
|
termtypes[1] = DBZeroTypeBits;
|
||||||
|
|
||||||
if (argc > 5)
|
|
||||||
gccap = aToCap(argv[argc - 1]); /* area cap */
|
|
||||||
if ((argc > 6) && StrIsNumeric(argv[argc - 2]))
|
|
||||||
{
|
|
||||||
gscap = aToCap(argv[argc - 2]); /* perimeter cap */
|
|
||||||
argc--;
|
|
||||||
}
|
|
||||||
nterm = 1;
|
nterm = 1;
|
||||||
|
|
||||||
if ((argc > 6) && strcmp(argv[5], "None"))
|
/* If argv[argc - 1] is a numerical value, then it is
|
||||||
|
* an area cap value and may be followed by another
|
||||||
|
* numerical value, the perimeter cap.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((argc > 5) && StrIsNumeric(argv[argc - 1]))
|
||||||
{
|
{
|
||||||
DBTechNoisyNameMask(argv[5], &subsTypes); /* substrate */
|
gccap = aToCap(argv[argc - 1]); /* area cap */
|
||||||
|
argc--;
|
||||||
|
|
||||||
|
if ((argc > 5) && StrIsNumeric(argv[argc - 1]))
|
||||||
|
{
|
||||||
|
gscap = aToCap(argv[argc - 1]); /* perimeter cap */
|
||||||
|
argc--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((argc > 5) && strcmp(argv[5], "None"))
|
||||||
|
{
|
||||||
|
/* substrate */
|
||||||
|
DBTechNoisyNameMask(argv[5], &subsTypes);
|
||||||
TTMaskSetMask(allExtractTypes, &subsTypes);
|
TTMaskSetMask(allExtractTypes, &subsTypes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
subsTypes = DBZeroTypeBits;
|
subsTypes = DBZeroTypeBits;
|
||||||
if (argc > 7) subsName = argv[6];
|
if (argc > 6) subsName = argv[6];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEV_SUBCKT:
|
case DEV_SUBCKT:
|
||||||
|
|
@ -3350,6 +3370,21 @@ ExtTechLine(sectionName, argc, argv)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
char *decimal;
|
||||||
|
|
||||||
|
if ((decimal = strchr(argv[2], '.')) != NULL)
|
||||||
|
{
|
||||||
|
*decimal = '\0';
|
||||||
|
if (StrIsInt(argv[2]))
|
||||||
|
{
|
||||||
|
resVal = aToRes(argv[2]);
|
||||||
|
if (strcmp(decimal + 1, "0"))
|
||||||
|
TxError("Resist argument truncated to integer value.\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
TxError("Unparseable resist argument \"%s\"\n", argv[2]);
|
||||||
|
}
|
||||||
|
else
|
||||||
TxError("Resist argument must be integer or \"None\".\n");
|
TxError("Resist argument must be integer or \"None\".\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -316,8 +316,10 @@ ExtractTest(w, cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
extShowInter(tile)
|
extShowInter(tile, dinfo, clientdata)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
|
ClientData clientdata; /* (unused) */
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -358,8 +358,8 @@ extTimesCellFunc(cs)
|
||||||
/* Count the number of transistors */
|
/* Count the number of transistors */
|
||||||
transList = (TransRegion *) ExtFindRegions(def, &TiPlaneRect,
|
transList = (TransRegion *) ExtFindRegions(def, &TiPlaneRect,
|
||||||
&ExtCurStyle->exts_deviceMask, ExtCurStyle->exts_deviceConn,
|
&ExtCurStyle->exts_deviceMask, ExtCurStyle->exts_deviceConn,
|
||||||
extUnInit, extTransFirst, extTransEach);
|
extTransFirst, extTransEach);
|
||||||
ExtResetTiles(def, extUnInit);
|
ExtResetTiles(def, CLIENTDEFAULT);
|
||||||
for (tl = transList; tl; tl = tl->treg_next)
|
for (tl = transList; tl; tl = tl->treg_next)
|
||||||
cs->cs_fets++;
|
cs->cs_fets++;
|
||||||
ExtFreeLabRegions((LabRegion *) transList);
|
ExtFreeLabRegions((LabRegion *) transList);
|
||||||
|
|
@ -396,8 +396,9 @@ extTimesCellFunc(cs)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
extCountTiles(tile, cs)
|
extCountTiles(tile, dinfo, cs)
|
||||||
Tile *tile; /* UNUSED */
|
Tile *tile; /* (unused) */
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
struct cellStats *cs;
|
struct cellStats *cs;
|
||||||
{
|
{
|
||||||
cs->cs_rects++;
|
cs->cs_rects++;
|
||||||
|
|
@ -843,7 +844,7 @@ extPaintOnly(def)
|
||||||
|
|
||||||
reg = extBasic(def, extDevNull);
|
reg = extBasic(def, extDevNull);
|
||||||
if (reg) ExtFreeLabRegions((LabRegion *) reg);
|
if (reg) ExtFreeLabRegions((LabRegion *) reg);
|
||||||
ExtResetTiles(def, extUnInit);
|
ExtResetTiles(def, CLIENTDEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1115,8 +1116,9 @@ extInterAreaFunc(use, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
extInterCountFunc(tile, pArea)
|
extInterCountFunc(tile, dinfo, pArea)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
int *pArea;
|
int *pArea;
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,11 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
* names that don't end in '!'.
|
* names that don't end in '!'.
|
||||||
* If option is EXT_UNIQ_NOPORTS, then generate unique names as for
|
* If option is EXT_UNIQ_NOPORTS, then generate unique names as for
|
||||||
* option 0 only if the label is not a port.
|
* option 0 only if the label is not a port.
|
||||||
|
* If option is EXT_UNIQ_TEMP, then generate unique names as for
|
||||||
|
* EXT_UNIQ_ALL, but also set the LABEL_UNIQUE flag for the
|
||||||
|
* label. This way, the unique label form can be used by the
|
||||||
|
* extraction code but labels (and port indexes) can be reverted
|
||||||
|
* afterward, and no permanent change is made to the circuit.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* Returns the number of warnings generated.
|
* Returns the number of warnings generated.
|
||||||
|
|
@ -109,7 +114,7 @@ extUniqueCell(def, option)
|
||||||
lregList = (LabRegion *) ExtFindRegions(def, &TiPlaneRect,
|
lregList = (LabRegion *) ExtFindRegions(def, &TiPlaneRect,
|
||||||
&ExtCurStyle->exts_activeTypes,
|
&ExtCurStyle->exts_activeTypes,
|
||||||
ExtCurStyle->exts_nodeConn,
|
ExtCurStyle->exts_nodeConn,
|
||||||
extUnInit, extHierLabFirst, (int (*)()) NULL);
|
extHierLabFirst, (int (*)()) NULL);
|
||||||
|
|
||||||
/* Assign the labels to their associated regions */
|
/* Assign the labels to their associated regions */
|
||||||
ExtLabelRegions(def, ExtCurStyle->exts_nodeConn, &lregList, &TiPlaneRect);
|
ExtLabelRegions(def, ExtCurStyle->exts_nodeConn, &lregList, &TiPlaneRect);
|
||||||
|
|
@ -187,7 +192,7 @@ extUniqueCell(def, option)
|
||||||
HashKill(&labelHash);
|
HashKill(&labelHash);
|
||||||
ExtFreeLabRegions((LabRegion *) lregList);
|
ExtFreeLabRegions((LabRegion *) lregList);
|
||||||
if (nodeList) freeMagic(nodeList);
|
if (nodeList) freeMagic(nodeList);
|
||||||
ExtResetTiles(def, extUnInit);
|
ExtResetTiles(def, CLIENTDEFAULT);
|
||||||
if (nwarn)
|
if (nwarn)
|
||||||
TxError("%s: %d warnings\n", def->cd_name, nwarn);
|
TxError("%s: %d warnings\n", def->cd_name, nwarn);
|
||||||
return (nwarn);
|
return (nwarn);
|
||||||
|
|
@ -219,7 +224,7 @@ extMakeUnique(def, ll, lreg, lregList, labelHash, option)
|
||||||
* changes a label to make it unique.
|
* changes a label to make it unique.
|
||||||
*/
|
*/
|
||||||
text = ll->ll_label->lab_text;
|
text = ll->ll_label->lab_text;
|
||||||
if (option == EXT_UNIQ_ALL)
|
if (option == EXT_UNIQ_ALL || option == EXT_UNIQ_TEMP)
|
||||||
goto makeUnique;
|
goto makeUnique;
|
||||||
else if ((option == EXT_UNIQ_NOPORTS || option == EXT_UNIQ_NOTOPPORTS)
|
else if ((option == EXT_UNIQ_NOPORTS || option == EXT_UNIQ_NOTOPPORTS)
|
||||||
&& !(ll->ll_label->lab_flags & PORT_DIR_MASK))
|
&& !(ll->ll_label->lab_flags & PORT_DIR_MASK))
|
||||||
|
|
@ -320,8 +325,11 @@ makeUnique:
|
||||||
lab = ll2->ll_label;
|
lab = ll2->ll_label;
|
||||||
saveLab = *lab;
|
saveLab = *lab;
|
||||||
|
|
||||||
|
/* Flag this label as having been modified */
|
||||||
|
if (option == EXT_UNIQ_TEMP) flags |= LABEL_UNIQUE;
|
||||||
|
|
||||||
DBRemoveLabel(def, lab);
|
DBRemoveLabel(def, lab);
|
||||||
(void) DBPutFontLabel(def, &saveLab.lab_rect,
|
DBPutFontLabel(def, &saveLab.lab_rect,
|
||||||
saveLab.lab_font, saveLab.lab_size, saveLab.lab_rotate,
|
saveLab.lab_font, saveLab.lab_size, saveLab.lab_rotate,
|
||||||
&saveLab.lab_offset, saveLab.lab_just, name2,
|
&saveLab.lab_offset, saveLab.lab_just, name2,
|
||||||
saveLab.lab_type, flags, (unsigned int)portno);
|
saveLab.lab_type, flags, (unsigned int)portno);
|
||||||
|
|
@ -334,3 +342,64 @@ makeUnique:
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* extRevertUniqueCell --
|
||||||
|
*
|
||||||
|
* For the cell 'def', look for labels marked with LABEL_UNIQUE and
|
||||||
|
* remove the unique suffix. If the label is a port, then revert
|
||||||
|
* the port index back to the original port number.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* Changes the label records in the cell def.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
ExtRevertUniqueCell(CellDef *def)
|
||||||
|
{
|
||||||
|
Label *lab, *tlab;
|
||||||
|
char *uptr;
|
||||||
|
|
||||||
|
for (lab = def->cd_labels; lab; lab = lab->lab_next)
|
||||||
|
{
|
||||||
|
if (lab->lab_flags & LABEL_UNIQUE)
|
||||||
|
{
|
||||||
|
/* There is no need to regenerate the label. We are
|
||||||
|
* only reducing the string length, so just drop a null
|
||||||
|
* at the last underscore and leave it at that.
|
||||||
|
*/
|
||||||
|
|
||||||
|
lab->lab_flags &= ~LABEL_UNIQUE; /* Clear the flag */
|
||||||
|
|
||||||
|
/* Place a null at the last underscore */
|
||||||
|
uptr = strrchr(lab->lab_text, '_');
|
||||||
|
if (uptr != NULL) /* should always be true */
|
||||||
|
*uptr = '\0';
|
||||||
|
|
||||||
|
/* If the label is a port, then find the first unmodified
|
||||||
|
* version of the label and change the port back to its
|
||||||
|
* port number
|
||||||
|
*/
|
||||||
|
if (lab->lab_flags & PORT_DIR_MASK)
|
||||||
|
{
|
||||||
|
for (tlab = def->cd_labels; tlab; tlab = tlab->lab_next)
|
||||||
|
{
|
||||||
|
if (tlab == lab) continue;
|
||||||
|
else if (!strcmp(tlab->lab_text, lab->lab_text))
|
||||||
|
{
|
||||||
|
lab->lab_port = tlab->lab_port;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,12 +68,14 @@ extern const char * const extDevTable[];
|
||||||
#define EXT_DOADJUST 0x001 /* Extract hierarchical adjustments */
|
#define EXT_DOADJUST 0x001 /* Extract hierarchical adjustments */
|
||||||
#define EXT_DOCAPACITANCE 0x002 /* Extract capacitance */
|
#define EXT_DOCAPACITANCE 0x002 /* Extract capacitance */
|
||||||
#define EXT_DOCOUPLING 0x004 /* Extract coupling capacitance */
|
#define EXT_DOCOUPLING 0x004 /* Extract coupling capacitance */
|
||||||
#define EXT_DORESISTANCE 0x008 /* Extract resistance */
|
#define EXT_DORESISTANCE 0x008 /* Extract lumped resistance */
|
||||||
#define EXT_DOLENGTH 0x010 /* Extract pathlengths */
|
#define EXT_DOLENGTH 0x010 /* Extract pathlengths */
|
||||||
#define EXT_DOFRINGEHALO 0x020 /* Distributed fringe capacitance */
|
#define EXT_DOFRINGEHALO 0x020 /* Distributed fringe capacitance */
|
||||||
#define EXT_DOALL 0x03f /* ALL OF THE ABOVE */
|
#define EXT_DOALL 0x03f /* ALL OF THE ABOVE */
|
||||||
#define EXT_DOLABELCHECK 0x040 /* Check for connections by label */
|
#define EXT_DOLABELCHECK 0x040 /* Check for connections by label */
|
||||||
#define EXT_DOALIASES 0x080 /* Output all node aliases */
|
#define EXT_DOALIASES 0x080 /* Output all node aliases */
|
||||||
|
#define EXT_DOUNIQUE 0x100 /* Force unique nodes during extraction */
|
||||||
|
#define EXT_DOEXTRESIST 0x200 /* Do full R-C extraction */
|
||||||
|
|
||||||
extern int ExtOptions; /* Bitmask of above */
|
extern int ExtOptions; /* Bitmask of above */
|
||||||
extern char *ExtLocalPath; /* If non-NULL, location to write .ext files */
|
extern char *ExtLocalPath; /* If non-NULL, location to write .ext files */
|
||||||
|
|
@ -83,6 +85,7 @@ extern char *ExtLocalPath; /* If non-NULL, location to write .ext files */
|
||||||
#define EXT_UNIQ_TAGGED 1
|
#define EXT_UNIQ_TAGGED 1
|
||||||
#define EXT_UNIQ_NOPORTS 2
|
#define EXT_UNIQ_NOPORTS 2
|
||||||
#define EXT_UNIQ_NOTOPPORTS 3
|
#define EXT_UNIQ_NOTOPPORTS 3
|
||||||
|
#define EXT_UNIQ_TEMP 4 /* Used only with "EXT_DOUNIQUE" */
|
||||||
|
|
||||||
extern bool ExtTechLine();
|
extern bool ExtTechLine();
|
||||||
extern void ExtTechInit();
|
extern void ExtTechInit();
|
||||||
|
|
@ -108,8 +111,10 @@ extern void ExtGetZAxis();
|
||||||
|
|
||||||
extern void ExtDumpCaps();
|
extern void ExtDumpCaps();
|
||||||
|
|
||||||
extern int extEnumTilePerim(Tile *tpIn, const TileTypeBitMask *maskp, int pNum, int (*func)(), ClientData cdata);
|
extern int extEnumTilePerim(Tile *tpIn, TileType dinfo, const TileTypeBitMask *maskp, int pNum, int (*func)(), ClientData cdata);
|
||||||
extern Plane *extPrepSubstrate();
|
extern Plane *extPrepSubstrate();
|
||||||
|
extern FILE *ExtFileOpen(CellDef *def, char *file, char *mode, char **prealfile);
|
||||||
|
|
||||||
|
|
||||||
/* C99 compat */
|
/* C99 compat */
|
||||||
extern void ExtAll();
|
extern void ExtAll();
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,19 @@ typedef struct reg
|
||||||
struct reg *reg_next; /* Next region in list */
|
struct reg *reg_next; /* Next region in list */
|
||||||
} ExtRegion;
|
} ExtRegion;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Special structure for split tiles which have something other than
|
||||||
|
* TT_SPACE on both sides and require two regions to represent both
|
||||||
|
* nets connected to the tile.
|
||||||
|
*/
|
||||||
|
typedef struct split_reg
|
||||||
|
{
|
||||||
|
ExtRegion *reg_guard; // Use this to guard against failure to
|
||||||
|
// identify a split region (temporary).
|
||||||
|
ExtRegion *reg_left; // Region belonging to tile left side
|
||||||
|
ExtRegion *reg_right; // Region belonging to tile right side
|
||||||
|
} ExtSplitRegion;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GENERIC region with labels.
|
* GENERIC region with labels.
|
||||||
* Any other structure that wants to reference node names
|
* Any other structure that wants to reference node names
|
||||||
|
|
@ -196,6 +209,7 @@ typedef struct nreg
|
||||||
* in X, then in Y.
|
* in X, then in Y.
|
||||||
*/
|
*/
|
||||||
LabelList *nreg_labels; /* See LabRegion for description */
|
LabelList *nreg_labels; /* See LabRegion for description */
|
||||||
|
ClientData nreg_subnet; /* Subnet record generated by extresist */
|
||||||
CapValue nreg_cap; /* Capacitance to ground */
|
CapValue nreg_cap; /* Capacitance to ground */
|
||||||
ResValue nreg_resist; /* Resistance estimate */
|
ResValue nreg_resist; /* Resistance estimate */
|
||||||
PerimArea nreg_pa[1]; /* Dummy; each node actually has
|
PerimArea nreg_pa[1]; /* Dummy; each node actually has
|
||||||
|
|
@ -212,16 +226,18 @@ typedef struct treg
|
||||||
{
|
{
|
||||||
struct treg *treg_next; /* Next region in list */
|
struct treg *treg_next; /* Next region in list */
|
||||||
int treg_pnum; /* UNUSED */
|
int treg_pnum; /* UNUSED */
|
||||||
int treg_type; /* Type of tile that contains treg_ll */
|
int treg_type; /* UNUSED */
|
||||||
Point treg_ll; /* UNUSED */
|
Point treg_ll; /* UNUSED */
|
||||||
LabelList *treg_labels; /* Attribute list */
|
LabelList *treg_labels; /* Attribute list */
|
||||||
Tile *treg_tile; /* Some tile in the channel */
|
Tile *treg_tile; /* Some tile in the channel */
|
||||||
|
TileType treg_dinfo; /* Diagonal information for treg_tile* */
|
||||||
int treg_area; /* Area of channel */
|
int treg_area; /* Area of channel */
|
||||||
} TransRegion;
|
} TransRegion;
|
||||||
|
|
||||||
typedef struct { /* Maintain plane information when pushing */
|
typedef struct { /* Maintain plane information when pushing */
|
||||||
Rect area; /* tiles on the node stack. For use with */
|
Rect area; /* tiles on the node stack. For use with */
|
||||||
int plane; /* function extNbrPushFunc(). */
|
int plane; /* function extNbrPushFunc(). */
|
||||||
|
ClientData uninit; /* Value of an unvisited region */
|
||||||
} PlaneAndArea;
|
} PlaneAndArea;
|
||||||
|
|
||||||
/* Structure to be kept in a hash table of node regions for the current */
|
/* Structure to be kept in a hash table of node regions for the current */
|
||||||
|
|
@ -253,7 +269,7 @@ typedef struct
|
||||||
CellDef *fra_def; /* Def being searched */
|
CellDef *fra_def; /* Def being searched */
|
||||||
int fra_pNum; /* Plane currently searching */
|
int fra_pNum; /* Plane currently searching */
|
||||||
ClientData fra_uninit; /* This value appears in the ti_client
|
ClientData fra_uninit; /* This value appears in the ti_client
|
||||||
* field of a tile if it's not yet
|
* field of a tile if it has not yet
|
||||||
* been visited.
|
* been visited.
|
||||||
*/
|
*/
|
||||||
ExtRegion *(*fra_first)(); /* Function to init new region */
|
ExtRegion *(*fra_first)(); /* Function to init new region */
|
||||||
|
|
@ -281,16 +297,27 @@ typedef struct
|
||||||
int b_plane; /* extract argument for extSideOverlap */
|
int b_plane; /* extract argument for extSideOverlap */
|
||||||
} Boundary;
|
} Boundary;
|
||||||
|
|
||||||
|
/* Define Manhattan boundary length */
|
||||||
|
|
||||||
#define BoundaryLength(bp) \
|
#define BoundaryLength(bp) \
|
||||||
((bp)->b_segment.r_xtop - (bp)->b_segment.r_xbot \
|
((bp)->b_segment.r_xtop - (bp)->b_segment.r_xbot \
|
||||||
+ (bp)->b_segment.r_ytop - (bp)->b_segment.r_ybot)
|
+ (bp)->b_segment.r_ytop - (bp)->b_segment.r_ybot)
|
||||||
|
|
||||||
/* Directions in which we can be following the boundary of a perimeter */
|
/* Directions in which we can be following the boundary of a perimeter */
|
||||||
|
|
||||||
#define BD_LEFT 1 /* Inside is to right */
|
#define BD_LEFT 0x01 /* Inside is to right */
|
||||||
#define BD_TOP 2 /* Inside is below */
|
#define BD_TOP 0x02 /* Inside is below */
|
||||||
#define BD_RIGHT 4 /* Inside is to left */
|
#define BD_RIGHT 0x04 /* Inside is to left */
|
||||||
#define BD_BOTTOM 8 /* Inside is above */
|
#define BD_BOTTOM 0x08 /* Inside is above */
|
||||||
|
|
||||||
|
/* Non-manhattan boundary directions. Inside is in the
|
||||||
|
* direction indicated (e.g., BD_NW, inside is top left)
|
||||||
|
*/
|
||||||
|
#define BD_NW 0x10 /* TT_SIDE = 0 TT_DIR = 0 */
|
||||||
|
#define BD_SW 0x20 /* TT_SIDE = 0 TT_DIR = 1 */
|
||||||
|
#define BD_SE 0x40 /* TT_SIDE = 1 TT_DIR = 0 */
|
||||||
|
#define BD_NE 0x80 /* TT_SIDE = 1 TT_DIR = 1 */
|
||||||
|
|
||||||
|
|
||||||
/* -------- Yank buffers for hierarchical and array extraction -------- */
|
/* -------- Yank buffers for hierarchical and array extraction -------- */
|
||||||
|
|
||||||
|
|
@ -342,6 +369,7 @@ typedef struct extTree
|
||||||
* char *
|
* char *
|
||||||
* proc(tp, et, ha)
|
* proc(tp, et, ha)
|
||||||
* Tile *tp;
|
* Tile *tp;
|
||||||
|
* TileType dinfo;
|
||||||
* ExtTree *et;
|
* ExtTree *et;
|
||||||
* HierExtractArg *ha;
|
* HierExtractArg *ha;
|
||||||
* {
|
* {
|
||||||
|
|
@ -372,7 +400,7 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
Tile *hierOneTile; /* Used in ExtHier.c, tile from extHierOneFlat */
|
Tile *hierOneTile; /* Used in ExtHier.c, tile from extHierOneFlat */
|
||||||
int hierPNum; /* Used in ExtHier.c, plane of tile above */
|
int hierPNum; /* Used in ExtHier.c, plane of tile above */
|
||||||
TileType hierType; /* Used in ExtHier.c, type of tile above */
|
TileType hierType; /* Used in ExtHier.c, type of tile above, incl. TT_SIDE */
|
||||||
int hierPNumBelow; /* Used in ExtHier.c, plane of tile below */
|
int hierPNumBelow; /* Used in ExtHier.c, plane of tile below */
|
||||||
} HierExtractArg;
|
} HierExtractArg;
|
||||||
|
|
||||||
|
|
@ -934,12 +962,6 @@ extern ExtStyle *ExtCurStyle;
|
||||||
|
|
||||||
/* ------------------- Hierarchical node merging ---------------------- */
|
/* ------------------- Hierarchical node merging ---------------------- */
|
||||||
|
|
||||||
/*
|
|
||||||
* Table used to hold all merged nodes during hierarchical extraction.
|
|
||||||
* Used for duplicate suppression.
|
|
||||||
*/
|
|
||||||
extern HashTable extHierMergeTable;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Each hash entry in the above table points to a NodeName struct.
|
* Each hash entry in the above table points to a NodeName struct.
|
||||||
* Each NodeName points to the Node corresponding to that name.
|
* Each NodeName points to the Node corresponding to that name.
|
||||||
|
|
@ -968,17 +990,10 @@ typedef struct node
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
|
|
||||||
/*
|
extern ExtRegion *ExtGetRegion(Tile *tile, TileType dinfo);
|
||||||
* Value normally resident in the ti_client field of a tile,
|
|
||||||
* indicating that the tile has not yet been visited in a
|
|
||||||
* region search.
|
|
||||||
*/
|
|
||||||
extern ClientData extUnInit;
|
|
||||||
|
|
||||||
#define extGetRegion(tp) ( (tp)->ti_client )
|
|
||||||
#define extHasRegion(tp,und) ( (tp)->ti_client != (und) )
|
#define extHasRegion(tp,und) ( (tp)->ti_client != (und) )
|
||||||
|
|
||||||
|
|
||||||
/* For non-recursive flooding algorithm */
|
/* For non-recursive flooding algorithm */
|
||||||
#define VISITPENDING ((ClientData) NULL) /* Marks tiles on stack */
|
#define VISITPENDING ((ClientData) NULL) /* Marks tiles on stack */
|
||||||
|
|
||||||
|
|
@ -989,44 +1004,47 @@ extern ClientData extUnInit;
|
||||||
/* because the search algorithm can overwrite it between the */
|
/* because the search algorithm can overwrite it between the */
|
||||||
/* time the tile is pushed and the time that it is popped. */
|
/* time the tile is pushed and the time that it is popped. */
|
||||||
|
|
||||||
#define PUSHTILE(tp, pl) \
|
#define PUSHTILE(tp, di, pl) \
|
||||||
(tp)->ti_client = VISITPENDING; \
|
ExtSetRegion(tp, di, (ExtRegion *)VISITPENDING); \
|
||||||
STACKPUSH((ClientData)(pointertype)(pl | \
|
STACKPUSH((ClientData)(pointertype)pl, extNodeStack); \
|
||||||
((TileType)(spointertype)(tp)->ti_body & TT_SIDE)), extNodeStack); \
|
STACKPUSH((ClientData)(pointertype)di, extNodeStack); \
|
||||||
STACKPUSH((ClientData)(pointertype)tp, extNodeStack)
|
STACKPUSH((ClientData)(pointertype)tp, extNodeStack)
|
||||||
|
|
||||||
#define POPTILE(tp, pl) \
|
#define POPTILE(tp, di, pl) \
|
||||||
tp = (Tile *) STACKPOP(extNodeStack); \
|
tp = (Tile *) STACKPOP(extNodeStack); \
|
||||||
pl = (spointertype) STACKPOP(extNodeStack); \
|
di = (spointertype) STACKPOP(extNodeStack); \
|
||||||
if (pl & TT_SIDE) { \
|
pl = (spointertype) STACKPOP(extNodeStack)
|
||||||
TiSetBody((tp), TiGetTypeExact(tp) | TT_SIDE); \
|
|
||||||
pl &= (~TT_SIDE); \
|
|
||||||
} \
|
|
||||||
else \
|
|
||||||
TiSetBody((tp), TiGetTypeExact(tp) & (~TT_SIDE))
|
|
||||||
|
|
||||||
/* Variations of "pushtile" to force a specific value on TT_SIDE */
|
/* Variations of "pushtile" to force a specific value on TT_SIDE */
|
||||||
|
|
||||||
#define PUSHTILEBOTTOM(tp, pl) \
|
#define PUSHTILEBOTTOM(tp, pl) \
|
||||||
(tp)->ti_client = VISITPENDING; \
|
{ \
|
||||||
STACKPUSH((ClientData)(pointertype)(pl | \
|
TileType di = (SplitDirection(tp)) ? 0 : TT_SIDE; \
|
||||||
((SplitDirection(tp)) ? 0 : TT_SIDE)), extNodeStack) ;\
|
ExtSetRegion(tp, di, (ExtRegion *)VISITPENDING); \
|
||||||
STACKPUSH((ClientData)(pointertype)tp, extNodeStack)
|
STACKPUSH((ClientData)(pointertype)pl, extNodeStack); \
|
||||||
|
STACKPUSH((ClientData)(pointertype)di, extNodeStack); \
|
||||||
|
STACKPUSH((ClientData)(pointertype)tp, extNodeStack); \
|
||||||
|
}
|
||||||
|
|
||||||
#define PUSHTILETOP(tp, pl) \
|
#define PUSHTILETOP(tp, pl) \
|
||||||
(tp)->ti_client = VISITPENDING; \
|
{ \
|
||||||
STACKPUSH((ClientData)(pointertype)(pl | \
|
TileType di = (SplitDirection(tp)) ? TT_SIDE : 0; \
|
||||||
((SplitDirection(tp)) ? TT_SIDE : 0)), extNodeStack) ;\
|
ExtSetRegion(tp, di, (ExtRegion *)VISITPENDING); \
|
||||||
STACKPUSH((ClientData)(pointertype)tp, extNodeStack)
|
STACKPUSH((ClientData)(pointertype)pl, extNodeStack); \
|
||||||
|
STACKPUSH((ClientData)(pointertype)di, extNodeStack); \
|
||||||
|
STACKPUSH((ClientData)(pointertype)tp, extNodeStack); \
|
||||||
|
}
|
||||||
|
|
||||||
#define PUSHTILELEFT(tp, pl) \
|
#define PUSHTILELEFT(tp, pl) \
|
||||||
(tp)->ti_client = VISITPENDING; \
|
ExtSetRegion(tp, (TileType)0, (ExtRegion *)VISITPENDING); \
|
||||||
STACKPUSH((ClientData)(pointertype)(pl), extNodeStack); \
|
STACKPUSH((ClientData)(pointertype)(pl), extNodeStack); \
|
||||||
|
STACKPUSH((ClientData)(pointertype)0, extNodeStack); \
|
||||||
STACKPUSH((ClientData)(pointertype)tp, extNodeStack)
|
STACKPUSH((ClientData)(pointertype)tp, extNodeStack)
|
||||||
|
|
||||||
#define PUSHTILERIGHT(tp, pl) \
|
#define PUSHTILERIGHT(tp, pl) \
|
||||||
(tp)->ti_client = VISITPENDING; \
|
ExtSetRegion(tp, (TileType)TT_SIDE, (ExtRegion *)VISITPENDING); \
|
||||||
STACKPUSH((ClientData)(pointertype)(pl | TT_SIDE), extNodeStack); \
|
STACKPUSH((ClientData)(pointertype)pl, extNodeStack); \
|
||||||
|
STACKPUSH((ClientData)(pointertype)TT_SIDE, extNodeStack); \
|
||||||
STACKPUSH((ClientData)(pointertype)tp, extNodeStack)
|
STACKPUSH((ClientData)(pointertype)tp, extNodeStack)
|
||||||
|
|
||||||
/* ------------------------- Region finding --------------------------- */
|
/* ------------------------- Region finding --------------------------- */
|
||||||
|
|
@ -1056,11 +1074,12 @@ extern Tile *extNodeToTile();
|
||||||
#define NODETONODE(nold, et, nnew) \
|
#define NODETONODE(nold, et, nnew) \
|
||||||
if (1) { \
|
if (1) { \
|
||||||
Tile *tp; \
|
Tile *tp; \
|
||||||
|
TileType di; \
|
||||||
\
|
\
|
||||||
(nnew) = (NodeRegion *) NULL; \
|
(nnew) = (NodeRegion *) NULL; \
|
||||||
tp = extNodeToTile((nold), (et)); \
|
tp = extNodeToTile((nold), (et), (TileType *)&di); \
|
||||||
if (tp && extHasRegion(tp, extUnInit)) \
|
if (tp && extHasRegion(tp, CLIENTDEFAULT)) \
|
||||||
(nnew) = (NodeRegion *) extGetRegion(tp); \
|
(nnew) = (NodeRegion *) ExtGetRegion(tp, di); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------- Miscellaneous procedures ---------------------- */
|
/* -------------------- Miscellaneous procedures ---------------------- */
|
||||||
|
|
@ -1072,6 +1091,7 @@ extern ExtTree *extHierNewOne();
|
||||||
extern int extNbrPushFunc();
|
extern int extNbrPushFunc();
|
||||||
extern TileType extGetDevType();
|
extern TileType extGetDevType();
|
||||||
extern void extMakeNodeNumPrint();
|
extern void extMakeNodeNumPrint();
|
||||||
|
extern void ExtSetRegion();
|
||||||
|
|
||||||
/* --------------------- Miscellaneous globals ------------------------ */
|
/* --------------------- Miscellaneous globals ------------------------ */
|
||||||
|
|
||||||
|
|
@ -1104,6 +1124,11 @@ extern Plane *extCellFile();
|
||||||
extern int extInterAreaFunc();
|
extern int extInterAreaFunc();
|
||||||
extern int extTreeSrPaintArea();
|
extern int extTreeSrPaintArea();
|
||||||
extern int extMakeUnique();
|
extern int extMakeUnique();
|
||||||
|
extern void extEnumTerminal();
|
||||||
|
extern void extEnumTerminal(Tile *tile, TileType dinfo,
|
||||||
|
TileTypeBitMask *connect, void (*func)(), ClientData clientData);
|
||||||
|
extern void ExtRevertUniqueCell(CellDef *def);
|
||||||
|
|
||||||
|
|
||||||
/* ------------------ Connectivity table management ------------------- */
|
/* ------------------ Connectivity table management ------------------- */
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -482,8 +482,9 @@ gaPropagateBlockages(list)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
gaSetClient(tile, cdata)
|
gaSetClient(tile, dinfo, cdata)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
ClientData cdata;
|
ClientData cdata;
|
||||||
{
|
{
|
||||||
tile->ti_client = (ClientData) cdata;
|
tile->ti_client = (ClientData) cdata;
|
||||||
|
|
@ -511,8 +512,9 @@ gaSetClient(tile, cdata)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
gaSplitTile(tile, r)
|
gaSplitTile(tile, dinfo, r)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
Rect *r;
|
Rect *r;
|
||||||
{
|
{
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
|
|
@ -632,7 +634,7 @@ gaInitRiverBlockages(routeUse, ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
gaAlwaysOne()
|
gaAlwaysOne(Tile *tile, TileType dinfo, ClientData clientdata)
|
||||||
{
|
{
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -572,8 +572,9 @@ gaIsClear(use, r, mask)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
gaIsClearFunc(tile, cxp)
|
gaIsClearFunc(tile, dinfo, cxp)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
TreeContext *cxp;
|
TreeContext *cxp;
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
||||||
|
|
@ -322,6 +322,7 @@ overlap:
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
* gaStemContainingChannelFunc --
|
* gaStemContainingChannelFunc --
|
||||||
*
|
*
|
||||||
* Called via DBSrPaintArea on behalf of gaStemContainingChannel above
|
* Called via DBSrPaintArea on behalf of gaStemContainingChannel above
|
||||||
|
|
@ -341,8 +342,9 @@ overlap:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
gaStemContainingChannelFunc(tile, pCh)
|
gaStemContainingChannelFunc(tile, dinfo, pCh)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
GCRChannel **pCh;
|
GCRChannel **pCh;
|
||||||
{
|
{
|
||||||
GCRChannel *ch;
|
GCRChannel *ch;
|
||||||
|
|
|
||||||
|
|
@ -254,8 +254,9 @@ GAGenChans(chanType, area, f)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
gaSplitOut(tile, f)
|
gaSplitOut(tile, dinfo, f)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
FILE *f;
|
FILE *f;
|
||||||
{
|
{
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
|
||||||
|
|
@ -231,9 +231,10 @@ w3dFillDiagonal(x1, y1, x2, y2, ztop, zbot)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
w3dFillOps(trans, tile, cliprect, ztop, zbot)
|
w3dFillOps(trans, tile, dinfo, cliprect, ztop, zbot)
|
||||||
Transform *trans;
|
Transform *trans;
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
Rect *cliprect;
|
Rect *cliprect;
|
||||||
float ztop;
|
float ztop;
|
||||||
float zbot;
|
float zbot;
|
||||||
|
|
@ -254,15 +255,15 @@ w3dFillOps(trans, tile, cliprect, ztop, zbot)
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
Rect fullr;
|
Rect fullr;
|
||||||
TileType dinfo;
|
TileType newdinfo;
|
||||||
|
|
||||||
dinfo = DBTransformDiagonal(TiGetTypeExact(tile), trans);
|
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, trans);
|
||||||
|
|
||||||
fullr = r;
|
fullr = r;
|
||||||
if (cliprect != NULL)
|
if (cliprect != NULL)
|
||||||
GeoClip(&r, cliprect);
|
GeoClip(&r, cliprect);
|
||||||
|
|
||||||
GrClipTriangle(&fullr, &r, cliprect != NULL, dinfo, p, &np);
|
GrClipTriangle(&fullr, &r, cliprect != NULL, newdinfo, p, &np);
|
||||||
|
|
||||||
if (np > 0)
|
if (np > 0)
|
||||||
{
|
{
|
||||||
|
|
@ -289,7 +290,7 @@ w3dFillOps(trans, tile, cliprect, ztop, zbot)
|
||||||
|
|
||||||
/* Find tile outline and render sides */
|
/* Find tile outline and render sides */
|
||||||
|
|
||||||
if (GrBoxOutline(tile, &tilesegs))
|
if (GrBoxOutline(tile, dinfo, &tilesegs))
|
||||||
{
|
{
|
||||||
xbot = (float)r.r_xbot;
|
xbot = (float)r.r_xbot;
|
||||||
ybot = (float)r.r_ybot;
|
ybot = (float)r.r_ybot;
|
||||||
|
|
@ -380,8 +381,9 @@ w3dFillOps(trans, tile, cliprect, ztop, zbot)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
w3dRenderVolume(tile, trans, cliprect)
|
w3dRenderVolume(tile, dinfo, trans, cliprect)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
Transform *trans;
|
Transform *trans;
|
||||||
Rect *cliprect;
|
Rect *cliprect;
|
||||||
{
|
{
|
||||||
|
|
@ -403,7 +405,7 @@ w3dRenderVolume(tile, trans, cliprect)
|
||||||
|
|
||||||
if ((grCurFill == GR_STSOLID) || (grCurFill == GR_STSTIPPLE))
|
if ((grCurFill == GR_STSOLID) || (grCurFill == GR_STSTIPPLE))
|
||||||
{
|
{
|
||||||
w3dFillOps(trans, tile, cliprect, ztop, zbot);
|
w3dFillOps(trans, tile, dinfo, cliprect, ztop, zbot);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* To do: Outlines and contact crosses */
|
/* To do: Outlines and contact crosses */
|
||||||
|
|
@ -411,8 +413,9 @@ w3dRenderVolume(tile, trans, cliprect)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
w3dRenderCIF(tile, layer, trans)
|
w3dRenderCIF(tile, dinfo, layer, trans)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
CIFLayer *layer;
|
CIFLayer *layer;
|
||||||
Transform *trans;
|
Transform *trans;
|
||||||
{
|
{
|
||||||
|
|
@ -435,7 +438,7 @@ w3dRenderCIF(tile, layer, trans)
|
||||||
|
|
||||||
if ((grCurFill == GR_STSOLID) || (grCurFill == GR_STSTIPPLE))
|
if ((grCurFill == GR_STSOLID) || (grCurFill == GR_STSTIPPLE))
|
||||||
{
|
{
|
||||||
w3dFillOps(trans, tile, NULL, ztop, zbot);
|
w3dFillOps(trans, tile, dinfo, NULL, ztop, zbot);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* To do: Outlines */
|
/* To do: Outlines */
|
||||||
|
|
@ -543,8 +546,9 @@ w3dSetProjection(w)
|
||||||
/* Magic layer tile painting function */
|
/* Magic layer tile painting function */
|
||||||
|
|
||||||
int
|
int
|
||||||
w3dPaintFunc(tile, cxp)
|
w3dPaintFunc(tile, dinfo, cxp)
|
||||||
Tile *tile; /* Tile to be displayed */
|
Tile *tile; /* Tile to be displayed */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
TreeContext *cxp; /* From DBTreeSrTiles */
|
TreeContext *cxp; /* From DBTreeSrTiles */
|
||||||
{
|
{
|
||||||
SearchContext *scx = cxp->tc_scx;
|
SearchContext *scx = cxp->tc_scx;
|
||||||
|
|
@ -582,15 +586,16 @@ w3dPaintFunc(tile, cxp)
|
||||||
w3dNeedStyle = FALSE;
|
w3dNeedStyle = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
w3dRenderVolume(tile, &scx->scx_trans, &scx->scx_area);
|
w3dRenderVolume(tile, dinfo, &scx->scx_trans, &scx->scx_area);
|
||||||
return 0; /* keep the search going! */
|
return 0; /* keep the search going! */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CIF layer tile painting function */
|
/* CIF layer tile painting function */
|
||||||
|
|
||||||
int
|
int
|
||||||
w3dCIFPaintFunc(tile, arg)
|
w3dCIFPaintFunc(tile, dinfo, arg)
|
||||||
Tile *tile; /* Tile to be displayed */
|
Tile *tile; /* Tile to be displayed */
|
||||||
|
TileType dinfo; /* Split tile information */
|
||||||
ClientData *arg; /* is NULL */
|
ClientData *arg; /* is NULL */
|
||||||
{
|
{
|
||||||
CIFLayer *layer = (CIFLayer *)arg;
|
CIFLayer *layer = (CIFLayer *)arg;
|
||||||
|
|
@ -626,7 +631,7 @@ w3dCIFPaintFunc(tile, arg)
|
||||||
w3dNeedStyle = FALSE;
|
w3dNeedStyle = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
w3dRenderCIF(tile, layer, &GeoIdentityTransform);
|
w3dRenderCIF(tile, dinfo, layer, &GeoIdentityTransform);
|
||||||
return 0; /* keep the search going! */
|
return 0; /* keep the search going! */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -689,15 +694,22 @@ w3dCutBox(w, cmd)
|
||||||
{
|
{
|
||||||
if (crec->clipped)
|
if (crec->clipped)
|
||||||
{
|
{
|
||||||
|
char *cllx, *clly, *curx, *cury;
|
||||||
|
|
||||||
|
cllx = DBWPrintValue(crec->cutbox.r_xbot, w, TRUE);
|
||||||
|
clly = DBWPrintValue(crec->cutbox.r_ybot, w, TRUE);
|
||||||
|
curx = DBWPrintValue(crec->cutbox.r_xtop, w, TRUE);
|
||||||
|
cury = DBWPrintValue(crec->cutbox.r_ytop, w, TRUE);
|
||||||
|
|
||||||
Tcl_Obj *rlist = Tcl_NewListObj(0, NULL);
|
Tcl_Obj *rlist = Tcl_NewListObj(0, NULL);
|
||||||
Tcl_ListObjAppendElement(magicinterp, rlist,
|
Tcl_ListObjAppendElement(magicinterp, rlist,
|
||||||
Tcl_NewIntObj((int)(crec->cutbox.r_xbot)));
|
Tcl_NewStringObj(cllx, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, rlist,
|
Tcl_ListObjAppendElement(magicinterp, rlist,
|
||||||
Tcl_NewIntObj((int)(crec->cutbox.r_ybot)));
|
Tcl_NewStringObj(clly, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, rlist,
|
Tcl_ListObjAppendElement(magicinterp, rlist,
|
||||||
Tcl_NewIntObj((int)(crec->cutbox.r_xtop)));
|
Tcl_NewStringObj(curx, -1));
|
||||||
Tcl_ListObjAppendElement(magicinterp, rlist,
|
Tcl_ListObjAppendElement(magicinterp, rlist,
|
||||||
Tcl_NewIntObj((int)(crec->cutbox.r_ytop)));
|
Tcl_NewStringObj(cury, -1));
|
||||||
|
|
||||||
Tcl_SetObjResult(magicinterp, rlist);
|
Tcl_SetObjResult(magicinterp, rlist);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -571,8 +571,9 @@ grAddSegment(llx, lly, urx, ury, segments)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GrBoxOutline(tile, tilesegs)
|
GrBoxOutline(tile, dinfo, tilesegs)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo;
|
||||||
LinkedRect **tilesegs;
|
LinkedRect **tilesegs;
|
||||||
{
|
{
|
||||||
Rect rect;
|
Rect rect;
|
||||||
|
|
@ -586,7 +587,7 @@ GrBoxOutline(tile, tilesegs)
|
||||||
*tilesegs = NULL;
|
*tilesegs = NULL;
|
||||||
TiToRect(tile, &rect);
|
TiToRect(tile, &rect);
|
||||||
|
|
||||||
if (IsSplit(tile) && SplitSide(tile))
|
if (IsSplit(tile) && (dinfo & TT_SIDE))
|
||||||
isolate |= 0x1;
|
isolate |= 0x1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -620,7 +621,7 @@ GrBoxOutline(tile, tilesegs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (IsSplit(tile) && !SplitSide(tile))
|
if (IsSplit(tile) && !(dinfo & TT_SIDE))
|
||||||
isolate |= 0x2;
|
isolate |= 0x2;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -656,7 +657,7 @@ GrBoxOutline(tile, tilesegs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsSplit(tile) &&
|
if (IsSplit(tile) &&
|
||||||
(SplitSide(tile) == SplitDirection(tile)))
|
(((dinfo & TT_SIDE) ? 1 : 0) == SplitDirection(tile)))
|
||||||
isolate |= 0x4;
|
isolate |= 0x4;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -692,7 +693,7 @@ GrBoxOutline(tile, tilesegs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsSplit(tile) &&
|
if (IsSplit(tile) &&
|
||||||
(SplitSide(tile) != SplitDirection(tile)))
|
(((dinfo & TT_SIDE) ? 1 : 0) != SplitDirection(tile)))
|
||||||
isolate |= 0x8;
|
isolate |= 0x8;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -773,7 +774,7 @@ GrBoxOutline(tile, tilesegs)
|
||||||
*---------------------------------------------------------
|
*---------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
GrBox(MagWindow *mw, Transform *trans, Tile *tile)
|
GrBox(MagWindow *mw, Transform *trans, Tile *tile, TileType dinfo)
|
||||||
{
|
{
|
||||||
Rect r, r2, clipr;
|
Rect r, r2, clipr;
|
||||||
bool needClip, needObscure, simpleBox;
|
bool needClip, needObscure, simpleBox;
|
||||||
|
|
@ -813,16 +814,16 @@ GrBox(MagWindow *mw, Transform *trans, Tile *tile)
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
{
|
{
|
||||||
/* Perform matrix transformations on split tiles */
|
/* Perform matrix transformations on split tiles */
|
||||||
TileType dinfo;
|
TileType newdinfo;
|
||||||
Rect fullr;
|
Rect fullr;
|
||||||
|
|
||||||
dinfo = DBTransformDiagonal(TiGetTypeExact(tile), trans);
|
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, trans);
|
||||||
clipr = fullr = r;
|
clipr = fullr = r;
|
||||||
|
|
||||||
if (needClip)
|
if (needClip)
|
||||||
GeoClip(&clipr, &grCurClip);
|
GeoClip(&clipr, &grCurClip);
|
||||||
|
|
||||||
GrClipTriangle(&fullr, &clipr, needClip, dinfo, polyp, &np);
|
GrClipTriangle(&fullr, &clipr, needClip, newdinfo, polyp, &np);
|
||||||
|
|
||||||
if ((grCurFill == GR_STSOLID) ||
|
if ((grCurFill == GR_STSOLID) ||
|
||||||
(grCurFill == GR_STSTIPPLE) || (grCurFill == GR_STGRID) )
|
(grCurFill == GR_STSTIPPLE) || (grCurFill == GR_STGRID) )
|
||||||
|
|
@ -891,7 +892,7 @@ GrBox(MagWindow *mw, Transform *trans, Tile *tile)
|
||||||
|
|
||||||
if (grCurOutline != 0)
|
if (grCurOutline != 0)
|
||||||
{
|
{
|
||||||
if (GrBoxOutline(tile, &tilesegs))
|
if (GrBoxOutline(tile, dinfo, &tilesegs))
|
||||||
{
|
{
|
||||||
/* simple box (from GrFastBox)*/
|
/* simple box (from GrFastBox)*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -235,8 +235,10 @@ glChanBuildMap(chanList)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
glChanFeedFunc(tile)
|
glChanFeedFunc(tile, dinfo, clientdata)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
|
ClientData clientdata; /* (unused) */
|
||||||
{
|
{
|
||||||
char *mesg;
|
char *mesg;
|
||||||
Rect r;
|
Rect r;
|
||||||
|
|
@ -342,8 +344,9 @@ glChanCheckCover(chanList, mask)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
glChanCheckFunc(tile, ch)
|
glChanCheckFunc(tile, dinfo, ch)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
GCRChannel *ch;
|
GCRChannel *ch;
|
||||||
{
|
{
|
||||||
char mesg[1024];
|
char mesg[1024];
|
||||||
|
|
@ -454,8 +457,10 @@ glChanShowTiles(mesg)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
glChanShowFunc(tile)
|
glChanShowFunc(tile, dinfo, clientdata)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
|
ClientData clientdata; /* (unused) */
|
||||||
{
|
{
|
||||||
GCRChannel *ch;
|
GCRChannel *ch;
|
||||||
char mesg[1024];
|
char mesg[1024];
|
||||||
|
|
@ -498,8 +503,9 @@ glChanShowFunc(tile)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
glChanClipFunc(tile, area)
|
glChanClipFunc(tile, dinfo, area)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
Rect *area;
|
Rect *area;
|
||||||
{
|
{
|
||||||
ClientData tileClient = tile->ti_client;
|
ClientData tileClient = tile->ti_client;
|
||||||
|
|
@ -567,8 +573,10 @@ glChanClipFunc(tile, area)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
glChanMergeFunc(tile)
|
glChanMergeFunc(tile, dinfo, clientdata)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
|
ClientData clientdata; /* (unused) */
|
||||||
{
|
{
|
||||||
GCRChannel *ch = (GCRChannel *) tile->ti_client;
|
GCRChannel *ch = (GCRChannel *) tile->ti_client;
|
||||||
Tile *delayed = NULL; /* delayed free to extend lifetime */
|
Tile *delayed = NULL; /* delayed free to extend lifetime */
|
||||||
|
|
@ -774,8 +782,9 @@ glChanBlockDens(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
glChanPaintFunc(tile, type)
|
glChanPaintFunc(tile, dinfo, type)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
TileType type;
|
TileType type;
|
||||||
{
|
{
|
||||||
static TileType changeTable[4][4] = {
|
static TileType changeTable[4][4] = {
|
||||||
|
|
@ -869,8 +878,9 @@ glChanFlood(area, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
glChanFloodVFunc(tile, area)
|
glChanFloodVFunc(tile, dinfo, area)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
Rect *area;
|
Rect *area;
|
||||||
{
|
{
|
||||||
PaintArea *pa;
|
PaintArea *pa;
|
||||||
|
|
@ -888,8 +898,9 @@ glChanFloodVFunc(tile, area)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
glChanFloodHFunc(tile, area)
|
glChanFloodHFunc(tile, dinfo, area)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
Rect *area;
|
Rect *area;
|
||||||
{
|
{
|
||||||
PaintArea *pa;
|
PaintArea *pa;
|
||||||
|
|
@ -928,8 +939,10 @@ glChanFloodHFunc(tile, area)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
glChanSplitRiver(tile)
|
glChanSplitRiver(tile, dinfo, clientdata)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
|
ClientData clientdata; /* (unused) */
|
||||||
{
|
{
|
||||||
ClientData tileClient = tile->ti_client;
|
ClientData tileClient = tile->ti_client;
|
||||||
Tile *tp, *newTile;
|
Tile *tp, *newTile;
|
||||||
|
|
@ -1009,8 +1022,10 @@ glChanSplitRiver(tile)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
glChanRiverBlock(tile)
|
glChanRiverBlock(tile, dinfo, clientdata)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
TileType dinfo; /* (unused) */
|
||||||
|
ClientData clientdata; /* (unused) */
|
||||||
{
|
{
|
||||||
GCRPin *pin, *pinLast;
|
GCRPin *pin, *pinLast;
|
||||||
GCRChannel *ch;
|
GCRChannel *ch;
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue