Compare commits
No commits in common. "master" and "8.3.587" have entirely different histories.
|
|
@ -138,8 +138,6 @@ jobs:
|
|||
echo "BUILD_GCC_VERSION=$BUILD_GCC_VERSION" >> $GITHUB_ENV
|
||||
echo "BUILD_CLANG_VERSION=$BUILD_CLANG_VERSION" >> $GITHUB_ENV
|
||||
|
||||
sudo apt-get update
|
||||
|
||||
if [ -n "$BUILD_GCC_VERSION" ]
|
||||
then
|
||||
GCCV=$BUILD_GCC_VERSION
|
||||
|
|
|
|||
|
|
@ -33,22 +33,10 @@ jobs:
|
|||
cd emsdk
|
||||
./emsdk install latest
|
||||
./emsdk activate latest
|
||||
- name: Emscripten Diagnostic
|
||||
run: |
|
||||
source ./emsdk/emsdk_env.sh
|
||||
echo "===== gcc -dM -E - ====="
|
||||
echo | gcc -dM -E - | sort
|
||||
echo "===== g++ -dM -E - ====="
|
||||
echo | g++ -dM -E - | sort
|
||||
echo "===== emcc -dM -E - ====="
|
||||
echo | emcc -dM -E - | sort
|
||||
echo "===== em++ -dM -E - ====="
|
||||
echo | em++ -dM -E - | sort
|
||||
- name: Build
|
||||
run: |
|
||||
source ./emsdk/emsdk_env.sh
|
||||
# The --without and --disable in these build options is due to no WASM library being available for that feature
|
||||
CFLAGS="--std=c17 -D_DEFAULT_SOURCE=1 -DEMSCRIPTEN=1 -g" emconfigure ./configure --without-cairo --without-opengl --without-x --without-tk --without-tcl --disable-readline --disable-compression --target=asmjs-unknown-emscripten
|
||||
emconfigure ./configure --without-cairo --without-opengl --without-x --disable-readline --disable-compression --target=asmjs-unknown-emscripten
|
||||
echo "===== defs.mak ====="
|
||||
cat defs.mak
|
||||
echo "===== defs.mak ====="
|
||||
|
|
|
|||
|
|
@ -10,6 +10,19 @@ on:
|
|||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
vezzal:
|
||||
# The type of runner that the job will run on
|
||||
runs-on: ubuntu-latest
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
- name: Pulling the docker image
|
||||
run: docker pull vezzal/vezzal:v1
|
||||
|
||||
- name: Start the container with the docker image
|
||||
run: docker run -id --name test_magic vezzal/vezzal:v1 bash | exit
|
||||
|
||||
- name: Run the testing on the container and send the mail
|
||||
run: docker exec test_magic /vezzal/test_magic.sh "lankasaicharan123@gmail.com,tim@opencircuitdesign.com" ${{secrets.MAILING_KEY}}
|
||||
simple_build_linux:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
|
|
@ -32,22 +45,10 @@ jobs:
|
|||
cd emsdk
|
||||
./emsdk install latest
|
||||
./emsdk activate latest
|
||||
- name: Emscripten Diagnostic
|
||||
run: |
|
||||
source ./emsdk/emsdk_env.sh
|
||||
echo "===== gcc -dM -E - ====="
|
||||
echo | gcc -dM -E - | sort
|
||||
echo "===== g++ -dM -E - ====="
|
||||
echo | g++ -dM -E - | sort
|
||||
echo "===== emcc -dM -E - ====="
|
||||
echo | emcc -dM -E - | sort
|
||||
echo "===== em++ -dM -E - ====="
|
||||
echo | em++ -dM -E - | sort
|
||||
- name: Build
|
||||
run: |
|
||||
source ./emsdk/emsdk_env.sh
|
||||
# The --without and --disable in these build options is due to no WASM library being available for that feature
|
||||
CFLAGS="--std=c17 -D_DEFAULT_SOURCE=1 -DEMSCRIPTEN=1 -g" emconfigure ./configure --without-cairo --without-opengl --without-x --without-tk --without-tcl --disable-readline --disable-compression --target=asmjs-unknown-emscripten
|
||||
emconfigure ./configure --without-cairo --without-opengl --without-x --disable-readline --disable-compression --target=asmjs-unknown-emscripten
|
||||
echo "===== defs.mak ====="
|
||||
cat defs.mak
|
||||
echo "===== defs.mak ====="
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ int calmaNonManhattan;
|
|||
int CalmaFlattenLimit = 10;
|
||||
int NameConvertErrors = 0;
|
||||
bool CalmaRewound = FALSE;
|
||||
bool CalmaRecordPaths = FALSE;
|
||||
TileTypeBitMask *CalmaMaskHints = NULL;
|
||||
|
||||
extern HashTable calmaDefInitHash;
|
||||
|
|
@ -246,9 +245,7 @@ calmaExact(void)
|
|||
int pNum;
|
||||
Plane *newplane;
|
||||
Plane **parray;
|
||||
|
||||
/* Forward reference */
|
||||
int gdsCopyPaintFunc(Tile *tile, TileType dinfo, GDSCopyRec *gdsCopyRec);
|
||||
int gdsCopyPaintFunc(Tile *tile, GDSCopyRec *gdsCopyRec); /* Forward reference */
|
||||
|
||||
parray = (Plane **)mallocMagic(MAXCIFRLAYERS * sizeof(Plane *));
|
||||
|
||||
|
|
@ -506,33 +503,28 @@ calmaParseStructure(
|
|||
|
||||
if (CalmaReadOnly || predefined)
|
||||
{
|
||||
PropertyRecord *proprec;
|
||||
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 */
|
||||
/* the same way that cell references are handled in .mag files. */
|
||||
DBPathSubstitute(filename, cstring, cifReadCellDef);
|
||||
fncopy = StrDup(NULL, cstring);
|
||||
sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos);
|
||||
DBPropPut(cifReadCellDef, "GDS_START", (ClientData)fpcopy);
|
||||
|
||||
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);
|
||||
|
||||
fpcopy = (char *)mallocMagic(20);
|
||||
filepos = FTELL(calmaInputFile);
|
||||
sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos);
|
||||
DBPropPut(cifReadCellDef, "GDS_END", (ClientData)fpcopy);
|
||||
|
||||
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);
|
||||
DBPropPut(cifReadCellDef, "GDS_FILE", (ClientData)fncopy);
|
||||
|
||||
if (predefined)
|
||||
{
|
||||
|
|
@ -759,7 +751,6 @@ calmaParseElement(
|
|||
int
|
||||
calmaEnumFunc(
|
||||
Tile *tile,
|
||||
TileType dinfo,
|
||||
int *plane)
|
||||
{
|
||||
return 1;
|
||||
|
|
@ -789,8 +780,8 @@ calmaElementSref(
|
|||
char *filename)
|
||||
{
|
||||
int nbytes, rtype, cols, rows, nref, n, i, savescale;
|
||||
int xlo, ylo, xhi, yhi, xsep, ysep, angle;
|
||||
bool madeinst = FALSE, rotated = FALSE;
|
||||
int xlo, ylo, xhi, yhi, xsep, ysep;
|
||||
bool madeinst = FALSE;
|
||||
char *sname = NULL;
|
||||
bool isArray = FALSE;
|
||||
bool dolookahead = FALSE;
|
||||
|
|
@ -798,13 +789,12 @@ calmaElementSref(
|
|||
Point refarray[3], refunscaled[3], p;
|
||||
CellUse *use;
|
||||
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;
|
||||
int propAttrType;
|
||||
|
||||
/* Forward reference */
|
||||
int gdsCopyPaintFunc(Tile *tile, TileType dinfo, GDSCopyRec *gdsCopyRec);
|
||||
int gdsHasUses(CellUse *use, ClientData clientdata);
|
||||
|
||||
/* Skip CALMA_ELFLAGS, CALMA_PLEX */
|
||||
calmaSkipSet(calmaElementIgnore);
|
||||
|
||||
|
|
@ -990,73 +980,17 @@ calmaElementSref(
|
|||
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
|
||||
* 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
|
||||
* 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++)
|
||||
{
|
||||
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);
|
||||
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
||||
{
|
||||
|
|
@ -1077,6 +1011,9 @@ calmaElementSref(
|
|||
}
|
||||
refarray[n].p_x *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
||||
}
|
||||
|
||||
if (FEOF(calmaInputFile))
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Skip remainder */
|
||||
|
|
@ -1352,28 +1289,27 @@ gdsHasUses(
|
|||
int
|
||||
gdsCopyPaintFunc(
|
||||
Tile *tile,
|
||||
TileType dinfo,
|
||||
GDSCopyRec *gdsCopyRec)
|
||||
{
|
||||
int pNum;
|
||||
TileType newdinfo;
|
||||
TileType dinfo;
|
||||
Rect sourceRect, targetRect;
|
||||
Transform *trans = gdsCopyRec->trans;
|
||||
Plane *plane = gdsCopyRec->plane;
|
||||
|
||||
newdinfo = TiGetTypeExact(tile) | dinfo;
|
||||
dinfo = TiGetTypeExact(tile);
|
||||
|
||||
if (trans)
|
||||
{
|
||||
TiToRect(tile, &sourceRect);
|
||||
GeoTransRect(trans, &sourceRect, &targetRect);
|
||||
if (IsSplit(tile))
|
||||
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, trans);
|
||||
dinfo = DBTransformDiagonal(TiGetTypeExact(tile), trans);
|
||||
}
|
||||
else
|
||||
TiToRect(tile, &targetRect);
|
||||
|
||||
DBNMPaintPlane(plane, newdinfo, &targetRect, CIFPaintTable,
|
||||
DBNMPaintPlane(plane, dinfo, &targetRect, CIFPaintTable,
|
||||
(PaintUndoInfo *)NULL);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -114,8 +114,6 @@ calmaInputRescale(
|
|||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* calmaReadX ---
|
||||
* calmaReadY ---
|
||||
* calmaReadPoint ---
|
||||
*
|
||||
* Read a point from the input.
|
||||
|
|
@ -134,17 +132,11 @@ calmaInputRescale(
|
|||
* encountered, then everything in the GDS planes is rescaled
|
||||
* 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
|
||||
calmaReadX(
|
||||
calmaReadPoint(
|
||||
Point *p,
|
||||
int iscale)
|
||||
{
|
||||
|
|
@ -171,15 +163,6 @@ calmaReadX(
|
|||
}
|
||||
}
|
||||
p->p_x /= calmaReadScale2;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
calmaReadY(
|
||||
Point *p,
|
||||
int iscale)
|
||||
{
|
||||
int rescale;
|
||||
|
||||
READI4((p)->p_y);
|
||||
p->p_y *= (calmaReadScale1 * iscale);
|
||||
|
|
@ -205,15 +188,6 @@ calmaReadY(
|
|||
p->p_y /= calmaReadScale2;
|
||||
}
|
||||
|
||||
void
|
||||
calmaReadPoint(
|
||||
Point *p,
|
||||
int iscale)
|
||||
{
|
||||
calmaReadX(p, iscale);
|
||||
calmaReadY(p, iscale);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
|
|
@ -718,12 +692,7 @@ 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,
|
||||
(pathtype == CALMAPATH_SQUAREFLUSH || pathtype == CALMAPATH_CUSTOM) ?
|
||||
FALSE : TRUE, plane, CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||
|
|
|
|||
|
|
@ -97,10 +97,10 @@ typedef struct {
|
|||
|
||||
/* Forward declarations */
|
||||
extern int calmaWriteInitFunc(CellDef *def);
|
||||
extern int calmaWritePaintFunc(Tile *tile, TileType dinfo, calmaOutputStruct *cos);
|
||||
extern int calmaMergePaintFunc(Tile *tile, TileType dinfo, calmaOutputStruct *cos);
|
||||
extern int calmaWritePaintFunc(Tile *tile, calmaOutputStruct *cos);
|
||||
extern int calmaMergePaintFunc(Tile *tile, calmaOutputStruct *cos);
|
||||
extern int calmaWriteUseFunc(CellUse *use, FILE *f);
|
||||
extern int calmaPaintLabelFunc(Tile *tile, TileType dinfo, calmaOutputStruct *cos);
|
||||
extern int calmaPaintLabelFunc(Tile *tile, calmaOutputStruct *cos);
|
||||
extern void calmaWriteContacts(FILE *f);
|
||||
extern void calmaDelContacts(void);
|
||||
extern void calmaOutFunc(CellDef *def, FILE *f, const Rect *cliprect);
|
||||
|
|
@ -528,7 +528,7 @@ calmaDumpStructure(
|
|||
|
||||
/* Is view abstract? */
|
||||
DBPropGet(edef, "LEFview", &isAbstract);
|
||||
chklibname = DBPropGetString(edef, "GDS_FILE", &isReadOnly);
|
||||
chklibname = (char *)DBPropGet(edef, "GDS_FILE", &isReadOnly);
|
||||
|
||||
if (isAbstract && isReadOnly)
|
||||
{
|
||||
|
|
@ -738,7 +738,7 @@ calmaFullDump(
|
|||
* names in the GDS file do not shadow any names in the database.
|
||||
*/
|
||||
|
||||
viewopts = DBPropGetString(def, "LEFview", &isAbstract);
|
||||
viewopts = (char *)DBPropGet(def, "LEFview", &isAbstract);
|
||||
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
||||
{
|
||||
/* 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, "CIFhier", &needHier);
|
||||
|
||||
filename = DBPropGetString(def, "GDS_FILE", &isReadOnly);
|
||||
filename = (char *)DBPropGet(def, "GDS_FILE", &isReadOnly);
|
||||
|
||||
/* When used with "calma addendum true", don't output the read-only */
|
||||
/* cells. This makes the library incomplete and dependent on the */
|
||||
|
|
@ -1033,12 +1033,13 @@ calmaProcessDef(
|
|||
}
|
||||
else
|
||||
{
|
||||
cval = DBPropGetDouble(def, "GDS_END", NULL);
|
||||
offptr = (char *)DBPropGet(def, "GDS_END", NULL);
|
||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
||||
cellend = (off_t)cval;
|
||||
cval = DBPropGetDouble(def, "GDS_BEGIN", &oldStyle);
|
||||
offptr = (char *)DBPropGet(def, "GDS_BEGIN", &oldStyle);
|
||||
if (!oldStyle)
|
||||
{
|
||||
cval = DBPropGetDouble(def, "GDS_START", NULL);
|
||||
offptr = (char *)DBPropGet(def, "GDS_START", NULL);
|
||||
|
||||
/* Write our own header and string name, to ensure */
|
||||
/* that the magic cell name and GDS name match. */
|
||||
|
|
@ -1055,6 +1056,7 @@ calmaProcessDef(
|
|||
calmaOutStructName(CALMA_STRNAME, def, outf);
|
||||
}
|
||||
|
||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
||||
cellstart = (off_t)cval;
|
||||
|
||||
/* GDS_START has been defined as the start of data after the cell */
|
||||
|
|
@ -1261,7 +1263,7 @@ calmaOutFunc(
|
|||
int dbunits;
|
||||
calmaOutputStruct cos;
|
||||
bool propfound;
|
||||
PropertyRecord *proprec;
|
||||
char *propvalue;
|
||||
|
||||
cos.f = f;
|
||||
cos.area = (cliprect == &TiPlaneRect) ? NULL : cliprect;
|
||||
|
|
@ -1321,20 +1323,14 @@ calmaOutFunc(
|
|||
|
||||
/* Include any fixed bounding box as part of the area to process, */
|
||||
/* in case the fixed bounding box is larger than the geometry. */
|
||||
proprec = DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
Rect bbox;
|
||||
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(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 (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
||||
GeoInclude(&bbox, &bigArea);
|
||||
}
|
||||
}
|
||||
|
||||
CIFErrorDef = def;
|
||||
|
|
@ -2468,7 +2464,6 @@ calmaProcessBoundary(
|
|||
int
|
||||
calmaMergePaintFunc(
|
||||
Tile *tile, /* Tile to be written out. */
|
||||
TileType dinfo, /* Split tile information (unused) */
|
||||
calmaOutputStruct *cos) /* Information needed by algorithm */
|
||||
{
|
||||
FILE *f = cos->f;
|
||||
|
|
@ -2499,10 +2494,11 @@ calmaMergePaintFunc(
|
|||
split_type = -1;
|
||||
if (IsSplit(t))
|
||||
{
|
||||
/* If we use TT_SIDE, then we need to set it when the */
|
||||
/* If we use SplitSide, then we need to set it when the */
|
||||
/* tile is pushed. Since these are one-or-zero mask layers */
|
||||
/* I assume it is okay to just check which side is TT_SPACE */
|
||||
|
||||
/* split_type = (SplitSide(t) << 1) | SplitDirection(t); */
|
||||
split_type = SplitDirection(t);
|
||||
if (TiGetLeftType(t) == TT_SPACE) split_type |= 2;
|
||||
num_points = 2;
|
||||
|
|
@ -2725,9 +2721,7 @@ right_search:
|
|||
done_searches:
|
||||
if (intedges == 0)
|
||||
{
|
||||
calmaWritePaintFunc(t,
|
||||
(split_type & 2) ? (TileType)TT_SIDE : (TileType)0,
|
||||
cos);
|
||||
calmaWritePaintFunc(t, cos);
|
||||
|
||||
/* Although calmaWritePaintFunc is called only on isolated */
|
||||
/* tiles, we may have expanded it. This could use a LOT of */
|
||||
|
|
@ -2797,7 +2791,6 @@ done_searches:
|
|||
int
|
||||
calmaWritePaintFunc(
|
||||
Tile *tile, /* Tile to be written out. */
|
||||
TileType dinfo, /* Split tile information */
|
||||
calmaOutputStruct *cos) /* File for output and clipping area */
|
||||
{
|
||||
FILE *f = cos->f;
|
||||
|
|
@ -2833,7 +2826,7 @@ calmaWritePaintFunc(
|
|||
/* Coordinates */
|
||||
calmaOutRH(36, CALMA_XY, CALMA_I4, f);
|
||||
|
||||
switch (((dinfo & TT_SIDE) ? 2 : 0) | SplitDirection(tile))
|
||||
switch ((SplitSide(tile) << 1) | SplitDirection(tile))
|
||||
{
|
||||
case 0x0:
|
||||
calmaOutI4(r.r_xbot, f); calmaOutI4(r.r_ybot, f);
|
||||
|
|
@ -3074,7 +3067,6 @@ calmaWriteLabelFunc(
|
|||
int
|
||||
calmaPaintLabelFunc(
|
||||
Tile *tile, /* Tile contains area for label. */
|
||||
TileType dinfo, /* Split tile information (unused) */
|
||||
calmaOutputStruct *cos) /* File for output and clipping area */
|
||||
{
|
||||
FILE *f = cos->f;
|
||||
|
|
|
|||
|
|
@ -107,10 +107,10 @@ typedef struct {
|
|||
} calmaOutputStructZ;
|
||||
|
||||
/* Forward declarations */
|
||||
extern int calmaWritePaintFuncZ(Tile *tile, TileType dinfo, calmaOutputStructZ *cos);
|
||||
extern int calmaMergePaintFuncZ(Tile *tile, TileType dinfo, calmaOutputStructZ *cos);
|
||||
extern int calmaWritePaintFuncZ(Tile *tile, calmaOutputStructZ *cos);
|
||||
extern int calmaMergePaintFuncZ(Tile *tile, calmaOutputStructZ *cos);
|
||||
extern int calmaWriteUseFuncZ(CellUse *use, gzFile f);
|
||||
extern int calmaPaintLabelFuncZ(Tile *tile, TileType dinfo, calmaOutputStructZ *cos);
|
||||
extern int calmaPaintLabelFuncZ(Tile *tile, calmaOutputStructZ *cos);
|
||||
extern void calmaWriteContactsZ(gzFile f);
|
||||
extern void calmaOutFuncZ(CellDef *def, gzFile f, const Rect *cliprect);
|
||||
extern void calmaOutStructNameZ(int type, CellDef *def, gzFile f);
|
||||
|
|
@ -508,7 +508,7 @@ calmaDumpStructureZ(
|
|||
|
||||
/* Is view abstract? */
|
||||
DBPropGet(edef, "LEFview", &isAbstract);
|
||||
chklibname = DBPropGetString(edef, "GDS_FILE", &isReadOnly);
|
||||
chklibname = (char *)DBPropGet(edef, "GDS_FILE", &isReadOnly);
|
||||
|
||||
if (isAbstract && isReadOnly)
|
||||
{
|
||||
|
|
@ -716,7 +716,7 @@ calmaFullDumpZ(
|
|||
* names in the GDS file do not shadow any names in the database.
|
||||
*/
|
||||
|
||||
viewopts = DBPropGetString(def, "LEFview", &isAbstract);
|
||||
viewopts = (char *)DBPropGet(def, "LEFview", &isAbstract);
|
||||
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
||||
{
|
||||
/* 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_END", &hasGDSEnd);
|
||||
DBPropGet(def, "CIFhier", &needHier);
|
||||
filename = DBPropGetString(def, "GDS_FILE", &isReadOnly);
|
||||
filename = (char *)DBPropGet(def, "GDS_FILE", &isReadOnly);
|
||||
|
||||
/* When used with "calma addendum true", don't output the read-only */
|
||||
/* cells. This makes the library incomplete and dependent on the */
|
||||
|
|
@ -985,12 +985,13 @@ calmaProcessDefZ(
|
|||
}
|
||||
else
|
||||
{
|
||||
cval = DBPropGetDouble(def, "GDS_END", NULL);
|
||||
offptr = (char *)DBPropGet(def, "GDS_END", NULL);
|
||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
||||
cellend = (z_off_t)cval;
|
||||
cval = DBPropGetDouble(def, "GDS_BEGIN", &oldStyle);
|
||||
offptr = (char *)DBPropGet(def, "GDS_BEGIN", &oldStyle);
|
||||
if (!oldStyle)
|
||||
{
|
||||
cval = DBPropGetDouble(def, "GDS_START", NULL);
|
||||
offptr = (char *)DBPropGet(def, "GDS_START", NULL);
|
||||
|
||||
/* Write our own header and string name, to ensure */
|
||||
/* that the magic cell name and GDS name match. */
|
||||
|
|
@ -1007,6 +1008,7 @@ calmaProcessDefZ(
|
|||
calmaOutStructNameZ(CALMA_STRNAME, def, outf);
|
||||
}
|
||||
|
||||
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
||||
cellstart = (z_off_t)cval;
|
||||
|
||||
/* GDS_START has been defined as the start of data after the cell */
|
||||
|
|
@ -1184,7 +1186,6 @@ calmaOutFuncZ(
|
|||
int dbunits;
|
||||
calmaOutputStructZ cos;
|
||||
bool propfound;
|
||||
PropertyRecord *proprec;
|
||||
char *propvalue;
|
||||
extern int compport(const void *one, const void *two); /* Forward declaration */
|
||||
|
||||
|
|
@ -1246,20 +1247,14 @@ calmaOutFuncZ(
|
|||
|
||||
/* Include any fixed bounding box as part of the area to process, */
|
||||
/* in case the fixed bounding box is larger than the geometry. */
|
||||
proprec = DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
Rect bbox;
|
||||
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(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 (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop) == 4)
|
||||
GeoInclude(&bbox, &bigArea);
|
||||
}
|
||||
}
|
||||
|
||||
CIFErrorDef = def;
|
||||
|
|
@ -1904,7 +1899,6 @@ calmaProcessBoundaryZ(
|
|||
int
|
||||
calmaMergePaintFuncZ(
|
||||
Tile *tile, /* Tile to be written out. */
|
||||
TileType dinfo, /* Split tile information (unused) */
|
||||
calmaOutputStructZ *cos) /* Information needed by algorithm */
|
||||
{
|
||||
gzFile f = cos->f;
|
||||
|
|
@ -1935,10 +1929,11 @@ calmaMergePaintFuncZ(
|
|||
split_type = -1;
|
||||
if (IsSplit(t))
|
||||
{
|
||||
/* If we use TT_SIDE, then we need to set it when the */
|
||||
/* If we use SplitSide, then we need to set it when the */
|
||||
/* tile is pushed. Since these are one-or-zero mask layers */
|
||||
/* I assume it is okay to just check which side is TT_SPACE */
|
||||
|
||||
/* split_type = (SplitSide(t) << 1) | SplitDirection(t); */
|
||||
split_type = SplitDirection(t);
|
||||
if (TiGetLeftType(t) == TT_SPACE) split_type |= 2;
|
||||
num_points = 2;
|
||||
|
|
@ -2161,9 +2156,7 @@ right_search:
|
|||
done_searches:
|
||||
if (intedges == 0)
|
||||
{
|
||||
calmaWritePaintFuncZ(t,
|
||||
(split_type & 2) ? (TileType)TT_SIDE : (TileType)0,
|
||||
cos);
|
||||
calmaWritePaintFuncZ(t, cos);
|
||||
|
||||
/* Although calmaWritePaintFunc is called only on isolated */
|
||||
/* tiles, we may have expanded it. This could use a LOT of */
|
||||
|
|
@ -2233,7 +2226,6 @@ done_searches:
|
|||
int
|
||||
calmaWritePaintFuncZ(
|
||||
Tile *tile, /* Tile to be written out. */
|
||||
TileType dinfo, /* Split tile information */
|
||||
calmaOutputStructZ *cos) /* File for output and clipping area */
|
||||
{
|
||||
gzFile f = cos->f;
|
||||
|
|
@ -2269,7 +2261,7 @@ calmaWritePaintFuncZ(
|
|||
/* Coordinates */
|
||||
calmaOutRHZ(36, CALMA_XY, CALMA_I4, f);
|
||||
|
||||
switch (((dinfo & TT_SIDE) ? 2 : 0) | SplitDirection(tile))
|
||||
switch ((SplitSide(tile) << 1) | SplitDirection(tile))
|
||||
{
|
||||
case 0x0:
|
||||
calmaOutI4Z(r.r_xbot, f); calmaOutI4Z(r.r_ybot, f);
|
||||
|
|
@ -2510,7 +2502,6 @@ calmaWriteLabelFuncZ(
|
|||
int
|
||||
calmaPaintLabelFuncZ(
|
||||
Tile *tile, /* Tile contains area for label. */
|
||||
TileType dinfo, /* Split tile information (unused) */
|
||||
calmaOutputStructZ *cos) /* File for output and clipping area */
|
||||
{
|
||||
gzFile f = cos->f;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ extern TileTypeBitMask *CalmaMaskHints;
|
|||
extern bool CalmaMergeTiles;
|
||||
extern bool CalmaFlattenArrays;
|
||||
extern bool CalmaNoDRCCheck;
|
||||
extern bool CalmaRecordPaths;
|
||||
extern bool CalmaFlattenUses;
|
||||
extern int CalmaFlattenLimit;
|
||||
extern float CalmaMagScale;
|
||||
|
|
@ -82,8 +81,6 @@ extern int calmaProcessDefZ(CellDef *def, gzFile outf, bool do_library);
|
|||
#endif
|
||||
extern bool calmaReadI2Record(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 bool calmaReadR8(double *pd);
|
||||
extern bool calmaReadStampRecord(int type, int *stampptr);
|
||||
|
|
|
|||
620
cif/CIFgen.c
620
cif/CIFgen.c
File diff suppressed because it is too large
Load Diff
213
cif/CIFhier.c
213
cif/CIFhier.c
|
|
@ -209,41 +209,52 @@ typedef struct _maskHintsData
|
|||
{
|
||||
Transform *mh_trans;
|
||||
CellDef *mh_def;
|
||||
Plane *mh_plane;
|
||||
} MaskHintsData;
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* cifCopyMaskHintFunc --
|
||||
* cifMaskHints --
|
||||
*
|
||||
* Callback function used by cifFlatMaskHints. Transforms a tile
|
||||
* from the original plane and paints it into the target plane,
|
||||
* both of which are properties.
|
||||
* Copy a mask hint into a target cell by adding it to the
|
||||
* property list of the target cell. If the target cell already
|
||||
* has the same mask hint key, then the mask hint value is
|
||||
* appended to the property in the target cell def.
|
||||
*
|
||||
* Results:
|
||||
* Zero to keep the search going.
|
||||
* Returns:
|
||||
* 0 to keep the search going.
|
||||
*
|
||||
* Side effects:
|
||||
* Paints geometry into the target plane.
|
||||
* Modifies properties of the target cell def.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* DEPRECATED */
|
||||
int
|
||||
cifCopyMaskHintFunc(Tile *tile,
|
||||
TileType dinfo,
|
||||
ClientData cdata)
|
||||
cifMaskHints(
|
||||
char *name,
|
||||
char *value,
|
||||
CellDef *targetDef)
|
||||
{
|
||||
MaskHintsData *mhd = (MaskHintsData *)cdata;
|
||||
Rect r, newr;
|
||||
char *propvalue, *newval;
|
||||
bool propfound;
|
||||
|
||||
TiToRect(tile, &r);
|
||||
|
||||
/* Transform tile area to coordinates of mhd->mh_plane and paint */
|
||||
GeoTransRect(mhd->mh_trans, &r, &newr);
|
||||
DBPaintPlane(mhd->mh_plane, &newr, CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||
if (!strncmp(name, "MASKHINTS_", 10))
|
||||
{
|
||||
/* Check if name exists already in the flattened cell */
|
||||
propvalue = (char *)DBPropGet(targetDef, name, &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
|
@ -253,8 +264,8 @@ cifCopyMaskHintFunc(Tile *tile,
|
|||
* cifFlatMaskHints --
|
||||
*
|
||||
* Copy a mask hint into a flattened cell by transforming it into the
|
||||
* coordinate system of the flattened cell, and painting it into the
|
||||
* property plane of the flattened cell.
|
||||
* coordinate system of the flattened cell, and adding it to the
|
||||
* property list of the flattened cell.
|
||||
*
|
||||
* Returns:
|
||||
* 0 to keep the search going.
|
||||
|
|
@ -268,40 +279,67 @@ cifCopyMaskHintFunc(Tile *tile,
|
|||
int
|
||||
cifFlatMaskHints(
|
||||
char *name,
|
||||
PropertyRecord *proprec,
|
||||
char *value,
|
||||
MaskHintsData *mhd)
|
||||
{
|
||||
Rect r, newr;
|
||||
char *vptr, *newval, *lastval, *propvalue;
|
||||
bool propfound;
|
||||
int i, lastlen, numvals;
|
||||
PropertyRecord *newproprec, *oldproprec;
|
||||
Plane *plane;
|
||||
int lastlen, numvals;
|
||||
|
||||
if (!strncmp(name, "MASKHINTS_", 10))
|
||||
{
|
||||
/* Check if name exists already in the flattened cell */
|
||||
oldproprec = (PropertyRecord *)DBPropGet(mhd->mh_def, name, &propfound);
|
||||
if (propfound)
|
||||
newval = (char *)NULL;
|
||||
vptr = value;
|
||||
while (*vptr != '\0')
|
||||
{
|
||||
ASSERT(oldproprec->prop_value.prop_type == PROPERTY_TYPE_PLANE,
|
||||
"cifFlatMaskHints");
|
||||
plane = oldproprec->prop_value.prop_plane;
|
||||
}
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
mhd->mh_plane = plane;
|
||||
DBSrPaintArea((Tile *)NULL, proprec->prop_value.prop_plane,
|
||||
&TiPlaneRect, &CIFSolidBits,
|
||||
cifCopyMaskHintFunc, (ClientData)mhd);
|
||||
/* Check if name exists already in the flattened cell */
|
||||
propvalue = (char *)DBPropGet(mhd->mh_def, name, &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
/* Append newval to the property */
|
||||
lastval = newval;
|
||||
newval = mallocMagic(strlen(lastval) + strlen(propvalue) + 2);
|
||||
sprintf(newval, "%s %s", propvalue, lastval);
|
||||
freeMagic(lastval);
|
||||
}
|
||||
DBPropPut(mhd->mh_def, name, newval);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -312,10 +350,9 @@ cifFlatMaskHints(
|
|||
* CIFCopyMaskHints --
|
||||
*
|
||||
* Callback function to copy mask hints from one cell into another.
|
||||
* (Occasionally called as a standalone function, not as a callback.)
|
||||
*
|
||||
* Results:
|
||||
* Return 0 to keep the search going.
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* May modify properties in the target cell.
|
||||
|
|
@ -323,7 +360,7 @@ cifFlatMaskHints(
|
|||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
void
|
||||
CIFCopyMaskHints(
|
||||
SearchContext *scx,
|
||||
CellDef *targetDef)
|
||||
|
|
@ -333,9 +370,38 @@ CIFCopyMaskHints(
|
|||
CellDef *sourceDef = scx->scx_use->cu_def;
|
||||
mhd.mh_trans = &scx->scx_trans;
|
||||
mhd.mh_def = targetDef;
|
||||
mhd.mh_plane = (Plane *)NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -367,16 +433,15 @@ CIFCopyMaskHints(
|
|||
int
|
||||
cifHierCopyFunc(
|
||||
Tile *tile, /* Pointer to tile to copy. */
|
||||
TileType dinfo, /* Split tile information */
|
||||
TreeContext *cxp) /* Describes context of search, including
|
||||
* transform and client data.
|
||||
*/
|
||||
{
|
||||
TileType type = TiGetTypeExact(tile) | dinfo;
|
||||
TileType type = TiGetTypeExact(tile);
|
||||
Rect sourceRect, targetRect;
|
||||
int pNum;
|
||||
CellDef *def = (CellDef *) cxp->tc_filter->tf_arg;
|
||||
TileType newdinfo = 0;
|
||||
int dinfo = 0;
|
||||
|
||||
/* Ignore tiles in vendor GDS, unless this is specifically */
|
||||
/* overridden by the "see-vendor" option. */
|
||||
|
|
@ -392,8 +457,8 @@ cifHierCopyFunc(
|
|||
|
||||
if (IsSplit(tile))
|
||||
{
|
||||
newdinfo = DBTransformDiagonal(type, &cxp->tc_scx->scx_trans);
|
||||
type = (dinfo & TT_SIDE) ? SplitRightType(tile) :
|
||||
dinfo = DBTransformDiagonal(type, &cxp->tc_scx->scx_trans);
|
||||
type = (SplitSide(tile)) ? SplitRightType(tile) :
|
||||
SplitLeftType(tile);
|
||||
}
|
||||
|
||||
|
|
@ -408,7 +473,7 @@ cifHierCopyFunc(
|
|||
{
|
||||
if (DBPaintOnPlane(type, pNum))
|
||||
{
|
||||
DBNMPaintPlane(def->cd_planes[pNum], newdinfo, &targetRect,
|
||||
DBNMPaintPlane(def->cd_planes[pNum], dinfo, &targetRect,
|
||||
DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL);
|
||||
}
|
||||
}
|
||||
|
|
@ -460,7 +525,7 @@ cifHierCellFunc(
|
|||
|
||||
/* Flatten mask hints in the area of interest */
|
||||
CIFCopyMaskHints(scx, CIFComponentDef);
|
||||
DBTreeSrCells(&newscx, 0, CIFCopyMaskHints,
|
||||
DBTreeSrCells(&newscx, 0, cifHierCopyMaskHints,
|
||||
(ClientData)CIFComponentDef);
|
||||
|
||||
/* Set CIFErrorDef to NULL to ignore errors here... these will
|
||||
|
|
@ -497,11 +562,9 @@ cifHierCellFunc(
|
|||
int
|
||||
cifHierErrorFunc(
|
||||
Tile *tile, /* Tile that covers area it shouldn't. */
|
||||
TileType dinfo, /* Split tile information */
|
||||
Rect *checkArea) /* Intersection of this and tile is error. */
|
||||
{
|
||||
Rect area;
|
||||
bool side = (dinfo & TT_SIDE) ? TRUE : FALSE;
|
||||
|
||||
TiToRect(tile, &area);
|
||||
|
||||
|
|
@ -509,8 +572,8 @@ cifHierErrorFunc(
|
|||
* space bounds the checkArea.
|
||||
*/
|
||||
if (IsSplit(tile))
|
||||
if (((area.r_xbot == checkArea->r_xbot) && !side) ||
|
||||
((area.r_xtop == checkArea->r_xtop) && side))
|
||||
if (((area.r_xbot == checkArea->r_xbot) && !SplitSide(tile)) ||
|
||||
((area.r_xtop == checkArea->r_xtop) && SplitSide(tile)))
|
||||
return 0;
|
||||
|
||||
GeoClip(&area, checkArea);
|
||||
|
|
@ -541,7 +604,6 @@ cifHierErrorFunc(
|
|||
int
|
||||
cifHierCheckFunc(
|
||||
Tile *tile, /* Tile containing CIF. */
|
||||
TileType dinfo, /* Split tile information */
|
||||
Plane *plane) /* Plane to check against and modify. */
|
||||
{
|
||||
Rect area;
|
||||
|
|
@ -550,10 +612,10 @@ cifHierCheckFunc(
|
|||
|
||||
if (IsSplit(tile))
|
||||
{
|
||||
DBSrPaintNMArea((Tile *)NULL, plane, TiGetTypeExact(tile) | dinfo,
|
||||
DBSrPaintNMArea((Tile *)NULL, plane, TiGetTypeExact(tile),
|
||||
&area, &DBSpaceBits, cifHierErrorFunc, (ClientData) &area);
|
||||
|
||||
DBNMPaintPlane(plane, TiGetTypeExact(tile) | dinfo, &area, CIFEraseTable,
|
||||
DBNMPaintPlane(plane, TiGetTypeExact(tile), &area, CIFEraseTable,
|
||||
(PaintUndoInfo *) NULL);
|
||||
}
|
||||
else
|
||||
|
|
@ -589,7 +651,6 @@ cifHierCheckFunc(
|
|||
int
|
||||
cifHierTempCheckFunc(
|
||||
Tile *tile, /* Tile containing CIF. */
|
||||
TileType dinfo, /* Information about split tiles */
|
||||
Plane *plane) /* Plane to check against and modify. */
|
||||
{
|
||||
Rect area;
|
||||
|
|
@ -597,7 +658,7 @@ cifHierTempCheckFunc(
|
|||
TiToRect(tile, &area);
|
||||
|
||||
if (IsSplit(tile))
|
||||
DBNMPaintPlane(plane, TiGetTypeExact(tile) | dinfo, &area, CIFEraseTable,
|
||||
DBNMPaintPlane(plane, TiGetTypeExact(tile), &area, CIFEraseTable,
|
||||
(PaintUndoInfo *) NULL);
|
||||
else
|
||||
DBPaintPlane(plane, &area, CIFEraseTable, (PaintUndoInfo *) NULL);
|
||||
|
|
@ -625,7 +686,6 @@ cifHierTempCheckFunc(
|
|||
int
|
||||
cifHierPaintFunc(
|
||||
Tile *tile,
|
||||
TileType dinfo, /* Information about split tiles */
|
||||
Plane *plane) /* Plane in which to paint CIF over tile's
|
||||
* area.
|
||||
*/
|
||||
|
|
@ -633,9 +693,9 @@ cifHierPaintFunc(
|
|||
Rect area;
|
||||
|
||||
TiToRect(tile, &area);
|
||||
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, dinfo, &area);
|
||||
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, &area);
|
||||
if (IsSplit(tile))
|
||||
DBNMPaintPlane(plane, TiGetTypeExact(tile) | dinfo, &area, CIFPaintTable,
|
||||
DBNMPaintPlane(plane, TiGetTypeExact(tile), &area, CIFPaintTable,
|
||||
(PaintUndoInfo *) NULL);
|
||||
else
|
||||
DBPaintPlane(plane, &area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||
|
|
@ -788,7 +848,7 @@ CIFGenSubcells(
|
|||
cifHierCopyFunc, (ClientData) CIFTotalDef);
|
||||
/* Flatten mask hints in the area of interest */
|
||||
CIFCopyMaskHints(&scx, CIFTotalDef);
|
||||
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
||||
(ClientData)CIFTotalDef);
|
||||
|
||||
CIFErrorDef = def;
|
||||
|
|
@ -966,14 +1026,14 @@ cifHierElementFunc(
|
|||
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
|
||||
cifHierCopyFunc, (ClientData) CIFTotalDef);
|
||||
CIFCopyMaskHints(&scx, CIFTotalDef);
|
||||
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
||||
(ClientData)CIFTotalDef);
|
||||
|
||||
DBCellClearDef(CIFComponentDef);
|
||||
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
|
||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
||||
(ClientData)CIFComponentDef);
|
||||
|
||||
CIFErrorDef = (CellDef *) NULL;
|
||||
|
|
@ -1007,7 +1067,6 @@ cifHierElementFunc(
|
|||
int
|
||||
cifGrowSliver(
|
||||
Tile *tile,
|
||||
TileType dinfo, /* Split tile information, needs to be handled */
|
||||
Rect *area)
|
||||
{
|
||||
int height, width, expand_up, expand_side;
|
||||
|
|
@ -1068,24 +1127,22 @@ cifGrowSliver(
|
|||
|
||||
int
|
||||
cifHierPaintArrayFunc(
|
||||
Tile *tile,
|
||||
TileType dinfo,
|
||||
ClientData clientdata) /* (unused) */
|
||||
Tile *tile)
|
||||
{
|
||||
Rect area;
|
||||
int i, j, xbot, xtop;
|
||||
|
||||
TiToRect(tile, &area);
|
||||
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, dinfo, &area);
|
||||
if (CIFCurStyle->cs_flags & CWF_GROW_SLIVERS) cifGrowSliver(tile, &area);
|
||||
xbot = area.r_xbot;
|
||||
xtop = area.r_xtop;
|
||||
for (i=0; i<cifHierYCount; i++)
|
||||
{
|
||||
for (j = 0; j < cifHierXCount; j++)
|
||||
for (j=0; j<cifHierXCount; j++)
|
||||
{
|
||||
DBNMPaintPlane(cifHierCurPlane, TiGetTypeExact(tile) | dinfo,
|
||||
&area, CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||
CIFTileOps++;
|
||||
DBPaintPlane(cifHierCurPlane, &area, CIFPaintTable,
|
||||
(PaintUndoInfo *) NULL);
|
||||
CIFTileOps += 1;
|
||||
area.r_xbot += cifHierXSpacing;
|
||||
area.r_xtop += cifHierXSpacing;
|
||||
}
|
||||
|
|
|
|||
11
cif/CIFint.h
11
cif/CIFint.h
|
|
@ -145,8 +145,6 @@ typedef struct cifop
|
|||
* CIFOP_BRIDGE - Added 6/11/20---Bridge across catecorner gaps
|
||||
* CIFOP_BRIDGELIM - Added 27/07/20---Bridge across catecorner gaps, but with limiting layers
|
||||
* CIFOP_MASKHINTS - Added 12/14/20---Add geometry from cell properties, if any.
|
||||
* CIFOP_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
|
||||
|
|
@ -174,8 +172,6 @@ typedef struct cifop
|
|||
#define CIFOP_BRIDGE 23
|
||||
#define CIFOP_BRIDGELIM 24
|
||||
#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 */
|
||||
#define CIFOP_INT_NOT 0x1 /* Inverted sense (not interacting) */
|
||||
|
|
@ -339,9 +335,10 @@ extern void CIFClearPlanes(Plane **planes);
|
|||
extern Plane *CIFGenLayer(CIFOp *op, const Rect *area, CellDef *cellDef, CellDef *origDef, Plane *temps[],
|
||||
bool hier, ClientData clientdata);
|
||||
extern void CIFInitCells(void);
|
||||
extern int cifHierCopyFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
|
||||
extern int cifHierCopyFunc(Tile *tile, TreeContext *cxp);
|
||||
extern int cifHierCopyMaskHints(SearchContext *scx, ClientData clientData);
|
||||
extern void CIFLoadStyle(char *stylename);
|
||||
extern int CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef);
|
||||
extern void CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef);
|
||||
|
||||
/* C99 compat */
|
||||
extern void CIFCoverageLayer(CellDef *rootDef, Rect *area, char *layer, bool dolist);
|
||||
|
|
@ -349,7 +346,7 @@ extern bool CIFWriteFlat(CellDef *rootDef, FILE *f);
|
|||
extern void CIFScalePlanes(int scalen, int scaled, Plane **planearray);
|
||||
extern void CIFInputRescale(int n, int d);
|
||||
extern int CIFScaleCoord(int cifCoord, int snap_type);
|
||||
extern int cifGrowSliver(Tile *tile, TileType dinfo, Rect *area);
|
||||
extern int cifGrowSliver(Tile *tile, Rect *area);
|
||||
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 cifSquareGridFunc(Rect *area, CIFOp *op, int *rows, int *columns, Rect *cut);
|
||||
|
|
|
|||
211
cif/CIFrdcl.c
211
cif/CIFrdcl.c
|
|
@ -505,7 +505,6 @@ CIFParseStart(void)
|
|||
|
||||
int cifCheckPaintFunc(
|
||||
Tile *tile,
|
||||
TileType dinfo,
|
||||
ClientData clientData)
|
||||
{
|
||||
return 1;
|
||||
|
|
@ -516,28 +515,27 @@ int cifCheckPaintFunc(
|
|||
int
|
||||
cifCopyPaintFunc(
|
||||
Tile *tile,
|
||||
TileType dinfo,
|
||||
CIFCopyRec *cifCopyRec)
|
||||
{
|
||||
int pNum;
|
||||
TileType newdinfo;
|
||||
TileType dinfo;
|
||||
Rect sourceRect, targetRect;
|
||||
Transform *trans = cifCopyRec->trans;
|
||||
Plane *plane = cifCopyRec->plane;
|
||||
|
||||
newdinfo = TiGetTypeExact(tile) | dinfo;
|
||||
dinfo = TiGetTypeExact(tile);
|
||||
|
||||
if (trans)
|
||||
{
|
||||
TiToRect(tile, &sourceRect);
|
||||
GeoTransRect(trans, &sourceRect, &targetRect);
|
||||
if (IsSplit(tile))
|
||||
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, trans);
|
||||
dinfo = DBTransformDiagonal(TiGetTypeExact(tile), trans);
|
||||
}
|
||||
else
|
||||
TiToRect(tile, &targetRect);
|
||||
|
||||
DBNMPaintPlane(plane, newdinfo, &targetRect, CIFPaintTable,
|
||||
DBNMPaintPlane(plane, dinfo, &targetRect, CIFPaintTable,
|
||||
(PaintUndoInfo *)NULL);
|
||||
|
||||
return 0;
|
||||
|
|
@ -563,7 +561,6 @@ cifCopyPaintFunc(
|
|||
int
|
||||
cifMaskHintFunc(
|
||||
Tile *tile,
|
||||
TileType dinfo, /* Unused, do not support non-manhattan hints */
|
||||
LinkedRect **lrecp)
|
||||
{
|
||||
Rect r;
|
||||
|
|
@ -600,9 +597,8 @@ int
|
|||
CIFPaintCurrent(
|
||||
int filetype)
|
||||
{
|
||||
/* Forward declarations. */
|
||||
extern int cifMakeBoundaryFunc(Tile *tile, TileType dinfo, ClientData clientdata);
|
||||
extern int cifPaintCurrentFunc(Tile *tile, TileType dinfo, TileType type);
|
||||
extern int cifMakeBoundaryFunc(Tile *tile, ClientData clientdata); /* Forward declaration. */
|
||||
extern int cifPaintCurrentFunc(Tile *tile, TileType type); /* Forward declaration. */
|
||||
|
||||
Plane *plane, *swapplane;
|
||||
int i;
|
||||
|
|
@ -613,7 +609,7 @@ CIFPaintCurrent(
|
|||
CIFOp *op;
|
||||
|
||||
plane = CIFGenLayer(cifCurReadStyle->crs_layers[i]->crl_ops,
|
||||
&TiPlaneRect, cifReadCellDef, cifReadCellDef,
|
||||
&TiPlaneRect, (CellDef *)NULL, (CellDef *)NULL,
|
||||
cifCurReadPlanes, FALSE, (ClientData)NULL);
|
||||
|
||||
/* Generate a paint/erase table, then paint from the CIF
|
||||
|
|
@ -688,8 +684,6 @@ CIFPaintCurrent(
|
|||
}
|
||||
else if (op == NULL)
|
||||
{
|
||||
LinkedRect *lrec = NULL, *lsrch;
|
||||
|
||||
/* Handle boundary layer */
|
||||
|
||||
op = cifCurReadStyle->crs_layers[i]->crl_ops;
|
||||
|
|
@ -704,102 +698,6 @@ CIFPaintCurrent(
|
|||
(ClientData)NULL) == 1))
|
||||
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
|
||||
&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 */
|
||||
|
|
@ -888,7 +786,9 @@ CIFPaintCurrent(
|
|||
|
||||
for (i = 0; i < cifNReadLayers; i++)
|
||||
{
|
||||
LinkedRect *lrec = NULL, *lsrch;
|
||||
LinkedRect *lrec = NULL;
|
||||
char *propstr = NULL;
|
||||
char locstr[512];
|
||||
Plane *tempp;
|
||||
|
||||
if (!TTMaskHasType(CalmaMaskHints, i)) continue;
|
||||
|
|
@ -913,55 +813,53 @@ CIFPaintCurrent(
|
|||
(CellDef *)NULL, CIFPlanes, FALSE, (ClientData)NULL);
|
||||
|
||||
/* Scan the resulting plane and generate linked Rect structures for
|
||||
* 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.)
|
||||
* each shape found.
|
||||
*/
|
||||
DBSrPaintArea((Tile *)NULL, presult, &TiPlaneRect, &CIFSolidBits,
|
||||
cifMaskHintFunc, (ClientData)&lrec);
|
||||
|
||||
if (lrec != NULL)
|
||||
{
|
||||
PropertyRecord *proprec;
|
||||
bool propfound;
|
||||
char *propname;
|
||||
Plane *plane;
|
||||
|
||||
propname = (char *)mallocMagic(11 + strlen(cifReadLayers[i]));
|
||||
sprintf(propname, "MASKHINTS_%s", cifReadLayers[i]);
|
||||
|
||||
/* Paint all linked Rects into a mask-hints property plane
|
||||
* in the target cell.
|
||||
propstr = (char *)NULL;
|
||||
|
||||
/* Turn all linked Rects into a mask-hints property in the
|
||||
* target cell.
|
||||
*/
|
||||
|
||||
proprec = DBPropGet(cifReadCellDef, propname, &propfound);
|
||||
if (!propfound)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
plane = proprec->prop_value.prop_plane;
|
||||
|
||||
while (lrec != NULL)
|
||||
{
|
||||
lrec->r_r.r_xbot /= CIFCurStyle->cs_scaleFactor;
|
||||
lrec->r_r.r_ybot /= CIFCurStyle->cs_scaleFactor;
|
||||
lrec->r_r.r_xtop /= CIFCurStyle->cs_scaleFactor;
|
||||
lrec->r_r.r_ytop /= CIFCurStyle->cs_scaleFactor;
|
||||
|
||||
DBPaintPlane(plane, &lrec->r_r, CIFPaintTable,
|
||||
(PaintUndoInfo *)NULL);
|
||||
|
||||
char *newstr;
|
||||
sprintf(locstr, "%d %d %d %d",
|
||||
lrec->r_r.r_xbot / CIFCurStyle->cs_scaleFactor,
|
||||
lrec->r_r.r_ybot / CIFCurStyle->cs_scaleFactor,
|
||||
lrec->r_r.r_xtop / CIFCurStyle->cs_scaleFactor,
|
||||
lrec->r_r.r_ytop / CIFCurStyle->cs_scaleFactor);
|
||||
if (propstr == NULL)
|
||||
{
|
||||
newstr = (char *)mallocMagic(strlen(locstr) + 1);
|
||||
sprintf(newstr, "%s", locstr);
|
||||
}
|
||||
else
|
||||
{
|
||||
newstr = (char *)mallocMagic(strlen(locstr)
|
||||
+ strlen(propstr) + 2);
|
||||
sprintf(newstr, "%s %s", propstr, locstr);
|
||||
freeMagic(propstr);
|
||||
}
|
||||
propstr = newstr;
|
||||
free_magic1_t mm1 = freeMagic1_init();
|
||||
freeMagic1(&mm1, lrec);
|
||||
lrec = lrec->r_next;
|
||||
freeMagic1_end(&mm1);
|
||||
}
|
||||
/* NOTE: propstr is transferred to the CellDef and should
|
||||
* not be free'd here.
|
||||
*/
|
||||
DBPropPut(cifReadCellDef, propname, propstr);
|
||||
freeMagic(propname);
|
||||
}
|
||||
|
||||
|
|
@ -993,14 +891,12 @@ CIFPaintCurrent(
|
|||
int
|
||||
cifMakeBoundaryFunc(
|
||||
Tile *tile, /* Tile of CIF information. */
|
||||
TileType dinfo, /* Split tile information (unused) */
|
||||
ClientData clientdata) /* Pass the file type (CIF or CALMA) */
|
||||
{
|
||||
/* It is assumed that there is one rectangle for the boundary. */
|
||||
/* If there are multiple rectangles defined with the boundary */
|
||||
/* layer, then the last one defines the FIXED_BBOX property. */
|
||||
|
||||
PropertyRecord *proprec;
|
||||
Rect area;
|
||||
char propertyvalue[128], *storedvalue;
|
||||
int savescale;
|
||||
|
|
@ -1032,24 +928,19 @@ cifMakeBoundaryFunc(
|
|||
|
||||
if (cifReadCellDef->cd_flags & CDFIXEDBBOX)
|
||||
{
|
||||
PropertyRecord *proprec;
|
||||
char *propvalue;
|
||||
bool found;
|
||||
|
||||
/* Only flag a warning if the redefined boundary was */
|
||||
/* different from the original. */
|
||||
|
||||
proprec = DBPropGet(cifReadCellDef, "FIXED_BBOX", &found);
|
||||
propvalue = (char *)DBPropGet(cifReadCellDef, "FIXED_BBOX", &found);
|
||||
if (found)
|
||||
{
|
||||
Rect bbox;
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(proprec->prop_len == 4))
|
||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop) == 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) ||
|
||||
(bbox.r_ybot != area.r_ybot) ||
|
||||
(bbox.r_xtop != area.r_xtop) ||
|
||||
|
|
@ -1066,15 +957,10 @@ cifMakeBoundaryFunc(
|
|||
}
|
||||
}
|
||||
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + 2 * sizeof(int));
|
||||
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||
proprec->prop_len = 4;
|
||||
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);
|
||||
sprintf(propertyvalue, "%d %d %d %d",
|
||||
area.r_xbot, area.r_ybot, area.r_xtop, area.r_ytop);
|
||||
storedvalue = StrDup((char **)NULL, propertyvalue);
|
||||
DBPropPut(cifReadCellDef, "FIXED_BBOX", storedvalue);
|
||||
cifReadCellDef->cd_flags |= CDFIXEDBBOX;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1084,7 +970,6 @@ cifMakeBoundaryFunc(
|
|||
int
|
||||
cifPaintCurrentFunc(
|
||||
Tile *tile, /* Tile of CIF information. */
|
||||
TileType dinfo, /* Split tile information */
|
||||
TileType type) /* Magic type to be painted. */
|
||||
{
|
||||
Rect area;
|
||||
|
|
@ -1134,7 +1019,7 @@ cifPaintCurrentFunc(
|
|||
for (pNum = PL_PAINTBASE; pNum < DBNumPlanes; pNum++)
|
||||
if (DBPaintOnPlane(type, pNum))
|
||||
{
|
||||
DBNMPaintPlane(cifReadCellDef->cd_planes[pNum], TiGetTypeExact(tile) | dinfo,
|
||||
DBNMPaintPlane(cifReadCellDef->cd_planes[pNum], TiGetTypeExact(tile),
|
||||
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) NULL);
|
||||
}
|
||||
|
||||
|
|
@ -1786,8 +1671,8 @@ CIFReadCellCleanup(
|
|||
}
|
||||
|
||||
/* Do geometrical processing on the top-level cell. */
|
||||
if (filetype == FILE_CIF) CIFPaintCurrent(filetype);
|
||||
|
||||
CIFPaintCurrent(FILE_CIF);
|
||||
DBAdjustLabels(EditCellUse->cu_def, &TiPlaneRect);
|
||||
DBReComputeBbox(EditCellUse->cu_def);
|
||||
DBWAreaChanged(EditCellUse->cu_def, &EditCellUse->cu_def->cd_bbox,
|
||||
|
|
|
|||
|
|
@ -244,61 +244,40 @@ CIFPropRecordPath(
|
|||
{
|
||||
extern float CIFGetOutputScale(int convert);
|
||||
CIFPath *pathp;
|
||||
char *namestr = NULL;
|
||||
int components, i, x, y, mult, pathnum;
|
||||
PropertyRecord *proprec;
|
||||
bool propfound;
|
||||
char *pathstr, *sptr;
|
||||
int components;
|
||||
float x, y, oscale, mult;
|
||||
|
||||
/* If "name" is a property, then append a suffix to it to ensure uniqueness */
|
||||
DBPropGet(def, propname, &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
pathnum = 0;
|
||||
namestr = mallocMagic(strlen(propname) + 10);
|
||||
while (propfound)
|
||||
{
|
||||
sprintf(namestr, "%s_%d", propname, pathnum);
|
||||
DBPropGet(def, namestr, &propfound);
|
||||
pathnum++;
|
||||
}
|
||||
}
|
||||
oscale = CIFGetOutputScale(1000); /* 1000 for conversion to um */
|
||||
if (oscale == 0.0) oscale = 1.0;
|
||||
mult = (iswire == TRUE) ? 0.5 : 1.0;
|
||||
|
||||
mult = (iswire == TRUE) ? 1 : 0;
|
||||
|
||||
/* Count the number of components in the path */
|
||||
pathp = pathheadp;
|
||||
components = 0;
|
||||
|
||||
/* Count the number of components in the path */
|
||||
while (pathp != NULL)
|
||||
{
|
||||
components++;
|
||||
pathp = pathp->cifp_next;
|
||||
components++;
|
||||
}
|
||||
/* Allocate enough space to hold 2 * N points. */
|
||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
||||
((components - 1) * 2) * sizeof(int));
|
||||
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
||||
proprec->prop_len = components * 2;
|
||||
/* Allocate enough space to hold 2 * N points at "infinity" */
|
||||
pathstr = (char *)mallocMagic(components * 40);
|
||||
|
||||
pathp = pathheadp;
|
||||
i = 0;
|
||||
sptr = pathstr;
|
||||
while (pathp != NULL)
|
||||
{
|
||||
x = pathp->cifp_x >> mult;
|
||||
y = pathp->cifp_y >> mult;
|
||||
|
||||
proprec->prop_value.prop_integer[i] = x;
|
||||
proprec->prop_value.prop_integer[i + 1] = y;
|
||||
|
||||
i += 2;
|
||||
x = (float)pathp->cifp_x * oscale * mult;
|
||||
y = (float)pathp->cifp_y * oscale * mult;
|
||||
sprintf(sptr, "%.3f %.3f ", x, y);
|
||||
sptr = sptr + strlen(sptr);
|
||||
pathp = pathp->cifp_next;
|
||||
}
|
||||
if (namestr)
|
||||
{
|
||||
DBPropPut(def, namestr, proprec);
|
||||
freeMagic(namestr);
|
||||
}
|
||||
else
|
||||
DBPropPut(def, propname, proprec);
|
||||
|
||||
/* Reallocate pathstr to be no larger than needed to hold the path contents */
|
||||
StrDup(&pathstr, pathstr);
|
||||
DBPropPut(def, propname, (ClientData)pathstr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -324,19 +324,14 @@ cifNewReadStyle(void)
|
|||
{
|
||||
/* Destroy old style and free all memory allocated to it */
|
||||
|
||||
for (i = 0; i < MAXCIFRLAYERS; i++)
|
||||
for (i=0; i<MAXCIFRLAYERS; i+=1)
|
||||
{
|
||||
layer = cifCurReadStyle->crs_layers[i];
|
||||
if (layer != NULL)
|
||||
{
|
||||
free_magic1_t mm1 = freeMagic1_init();
|
||||
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_end(&mm1);
|
||||
freeMagic((char *)layer);
|
||||
}
|
||||
|
|
@ -995,12 +990,6 @@ CIFReadTechLine(
|
|||
newOp->co_opcode = CIFOP_COPYUP;
|
||||
else if (strcmp(argv[0], "boundary") == 0)
|
||||
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
|
||||
{
|
||||
TechError("Unknown statement \"%s\".\n", argv[0]);
|
||||
|
|
@ -1027,15 +1016,6 @@ CIFReadTechLine(
|
|||
goto errorReturn;
|
||||
}
|
||||
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. */
|
||||
|
|
@ -1119,7 +1099,6 @@ CIFReadTechFinal(void)
|
|||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
CIFReadLoadStyle(
|
||||
char *stylename)
|
||||
|
|
|
|||
33
cif/CIFsee.c
33
cif/CIFsee.c
|
|
@ -78,7 +78,6 @@ typedef struct {
|
|||
int
|
||||
cifPaintDBFunc(
|
||||
Tile *tile, /* Tile of CIF information. */
|
||||
TileType dinfo,
|
||||
PaintLayerData *pld)
|
||||
{
|
||||
Rect area;
|
||||
|
|
@ -107,7 +106,7 @@ cifPaintDBFunc(
|
|||
if (DBPaintOnPlane(type, pNum))
|
||||
{
|
||||
ui.pu_pNum = pNum;
|
||||
DBNMPaintPlane(paintDef->cd_planes[pNum], TiGetTypeExact(tile) | dinfo,
|
||||
DBNMPaintPlane(paintDef->cd_planes[pNum], TiGetTypeExact(tile),
|
||||
&area, DBStdPaintTbl(type, pNum), (PaintUndoInfo *) &ui);
|
||||
}
|
||||
|
||||
|
|
@ -166,9 +165,9 @@ CIFPaintLayer(
|
|||
scx.scx_use = CIFDummyUse;
|
||||
scx.scx_trans = GeoIdentityTransform;
|
||||
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
||||
(ClientData)CIFComponentDef);
|
||||
|
||||
oldCount = DBWFeedbackCount;
|
||||
|
|
@ -220,7 +219,6 @@ CIFPaintLayer(
|
|||
int
|
||||
cifSeeFunc(
|
||||
Tile *tile, /* Tile to be entered as feedback. */
|
||||
TileType dinfo, /* Split tile information */
|
||||
SeeLayerData *sld) /* Layer and explanation for the feedback. */
|
||||
{
|
||||
Rect area;
|
||||
|
|
@ -235,10 +233,10 @@ cifSeeFunc(
|
|||
(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,
|
||||
sld->style | ((TiGetTypeExact(tile) | dinfo) &
|
||||
(TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
|
||||
sld->style |
|
||||
(TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
|
||||
/* (preserve information about the geometry of a diagonal tile) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -287,9 +285,9 @@ CIFSeeLayer(
|
|||
scx.scx_use = CIFDummyUse;
|
||||
scx.scx_trans = GeoIdentityTransform;
|
||||
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
||||
(ClientData)CIFComponentDef);
|
||||
|
||||
oldCount = DBWFeedbackCount;
|
||||
|
|
@ -440,11 +438,9 @@ CIFCoverageLayer(
|
|||
SearchContext scx;
|
||||
TileTypeBitMask mask, depend;
|
||||
float fcover;
|
||||
int cifCoverageFunc(Tile *tile, ClientData *arg);
|
||||
bool doBox = (area != &rootDef->cd_bbox) ? TRUE : FALSE;
|
||||
|
||||
/* Forward declaration */
|
||||
int cifCoverageFunc(Tile *tile, TileType dinfo, ClientData *arg);
|
||||
|
||||
/* Check out the CIF layer name. */
|
||||
|
||||
if (!CIFNameToMask(layer, &mask, &depend)) return;
|
||||
|
|
@ -459,9 +455,9 @@ CIFCoverageLayer(
|
|||
scx.scx_use = CIFDummyUse;
|
||||
scx.scx_trans = GeoIdentityTransform;
|
||||
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
||||
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
||||
(ClientData)CIFComponentDef);
|
||||
|
||||
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,
|
||||
|
|
@ -504,10 +500,10 @@ CIFCoverageLayer(
|
|||
}
|
||||
else
|
||||
{
|
||||
TxPrintf("%s Area = %"DLONG_PREFIX"d CIF units^2\n", doBox ? "Cursor Box" :
|
||||
TxPrintf("%s Area = %lld CIF units^2\n", doBox ? "Cursor Box" :
|
||||
"Cell", btotal);
|
||||
TxPrintf("Layer Bounding Area = %"DLONG_PREFIX"d CIF units^2\n", atotal);
|
||||
TxPrintf("Layer Total Area = %"DLONG_PREFIX"d CIF units^2\n", cstats.coverage);
|
||||
TxPrintf("Layer Bounding Area = %lld CIF units^2\n", atotal);
|
||||
TxPrintf("Layer Total Area = %lld CIF units^2\n", cstats.coverage);
|
||||
TxPrintf("Coverage in %s = %1.1f%%\n", doBox ? "box" :
|
||||
"cell", 100.0 * fcover);
|
||||
}
|
||||
|
|
@ -516,7 +512,6 @@ CIFCoverageLayer(
|
|||
int
|
||||
cifCoverageFunc(
|
||||
Tile *tile,
|
||||
TileType dinfo, /* (unused) */
|
||||
ClientData *arg)
|
||||
{
|
||||
coverstats *cstats = (coverstats *)arg;
|
||||
|
|
|
|||
|
|
@ -817,7 +817,7 @@ CIFTechLine(
|
|||
else
|
||||
{
|
||||
l = strlen(CIFCurStyle->cs_name) - strlen(tptr);
|
||||
if ((l > 0) && !strcmp(tptr, CIFCurStyle->cs_name + l))
|
||||
if (!strcmp(tptr, CIFCurStyle->cs_name + l))
|
||||
{
|
||||
CIFCurStyle->cs_status = TECH_PENDING;
|
||||
return TRUE;
|
||||
|
|
@ -1107,8 +1107,6 @@ CIFTechLine(
|
|||
newOp->co_opcode = CIFOP_BBOX;
|
||||
else if (strcmp(argv[0], "net") == 0)
|
||||
newOp->co_opcode = CIFOP_NET;
|
||||
else if (strcmp(argv[0], "tagged") == 0)
|
||||
newOp->co_opcode = CIFOP_TAGGED;
|
||||
else if (strcmp(argv[0], "maxrect") == 0)
|
||||
newOp->co_opcode = CIFOP_MAXRECT;
|
||||
else if (strcmp(argv[0], "boundary") == 0)
|
||||
|
|
@ -1119,8 +1117,6 @@ CIFTechLine(
|
|||
newOp->co_opcode = CIFOP_CLOSE;
|
||||
else if (strcmp(argv[0], "orthogonal") == 0)
|
||||
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)
|
||||
newOp->co_opcode = CIFOP_BRIDGE;
|
||||
else if (strcmp(argv[0], "bridge-lim") == 0)
|
||||
|
|
@ -1359,7 +1355,6 @@ bloatCheck:
|
|||
bloatDone: break;
|
||||
|
||||
case CIFOP_NET:
|
||||
case CIFOP_TAGGED:
|
||||
if (argc != 3) goto wrongNumArgs;
|
||||
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
|
||||
cifParseLayers(argv[2], CIFCurStyle, &newOp->co_paintMask,
|
||||
|
|
@ -1674,12 +1669,12 @@ cifComputeRadii(
|
|||
|
||||
for (op = layer->cl_ops; op != NULL; op = op->co_next)
|
||||
{
|
||||
/* BBOX, NET, TAGGED, and MASKHINTS operators should never be */
|
||||
/* used hierarchically so ignore any grow/shrink operators that */
|
||||
/* BBOX, NET, and MASKHINTS operators should never be used */
|
||||
/* hierarchically so ignore any grow/shrink operators that */
|
||||
/* come after them. */
|
||||
|
||||
if (op->co_opcode == CIFOP_BBOX || op->co_opcode == CIFOP_NET ||
|
||||
op->co_opcode == CIFOP_TAGGED || op->co_opcode == CIFOP_MASKHINTS)
|
||||
op->co_opcode == CIFOP_MASKHINTS)
|
||||
break;
|
||||
|
||||
/* If CIF layers are used, switch to the max of current
|
||||
|
|
@ -1991,8 +1986,8 @@ CIFTechFinal(void)
|
|||
/* Presence of op->co_opcode in CIFOP_OR indicates a copy */
|
||||
/* of the SquaresData pointer from a following operator. */
|
||||
/* CIFOP_BBOX and CIFOP_MAXRECT uses the co_client field */
|
||||
/* as a flag field, while CIFOP_NET, CIFOP_MASKHINTS, and */
|
||||
/* CIFOP_TAGGED use it for a string. */
|
||||
/* as a flag field, while CIFOP_NET and CIFOP_MASKHINTS */
|
||||
/* uses it for a string. */
|
||||
else
|
||||
{
|
||||
switch (op->co_opcode)
|
||||
|
|
@ -2004,7 +1999,6 @@ CIFTechFinal(void)
|
|||
case CIFOP_MAXRECT:
|
||||
case CIFOP_MANHATTAN:
|
||||
case CIFOP_NET:
|
||||
case CIFOP_TAGGED:
|
||||
break;
|
||||
case CIFOP_BRIDGELIM:
|
||||
case CIFOP_BRIDGE:
|
||||
|
|
@ -2540,7 +2534,6 @@ CIFTechOutputScale(
|
|||
case CIFOP_MAXRECT:
|
||||
case CIFOP_MANHATTAN:
|
||||
case CIFOP_NET:
|
||||
case CIFOP_TAGGED:
|
||||
case CIFOP_INTERACT:
|
||||
break;
|
||||
case CIFOP_BRIDGELIM:
|
||||
|
|
@ -2656,8 +2649,8 @@ CIFTechOutputScale(
|
|||
default:
|
||||
/* op->co_opcode in CIFOP_OR is a pointer copy, */
|
||||
/* in CIFOP_BBOX and CIFOP_MAXRECT is a flag, */
|
||||
/* and in CIFOP_NET, CIFOP_MASKHINTS, and */
|
||||
/* CIFOP_TAGGED is a string. */
|
||||
/* and in CIFOP_NET and CIFOP_MASKHINTS is a */
|
||||
/* string. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
|||
/* Forward declarations */
|
||||
extern int cifWriteInitFunc(CellDef *def);
|
||||
extern int cifWriteMarkFunc(CellUse *use);
|
||||
extern int cifWritePaintFunc(Tile *tile, TileType dinfo, FILE *f);
|
||||
extern int cifWriteLabelFunc(Tile *tile, TileType dinfo, FILE *f);
|
||||
extern int cifWritePaintFunc(Tile *tile, FILE *f);
|
||||
extern int cifWriteLabelFunc(Tile *tile, FILE *f);
|
||||
extern int cifWriteUseFunc(CellUse *use, FILE *f);
|
||||
extern void cifOutPreamble(FILE *outf, CellDef *cell);
|
||||
extern void cifOut(FILE *outf);
|
||||
|
|
@ -584,7 +584,6 @@ cifWriteUseFunc(
|
|||
int
|
||||
cifWriteLabelFunc(
|
||||
Tile *tile, /* Tile to be written out. */
|
||||
TileType dinfo, /* Split tile information (unused) */
|
||||
FILE *f) /* File in which to write. */
|
||||
{
|
||||
Rect r;
|
||||
|
|
@ -644,8 +643,7 @@ cifWriteLabelFunc(
|
|||
int
|
||||
cifWritePaintFunc(
|
||||
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;
|
||||
|
||||
|
|
@ -664,7 +662,7 @@ cifWritePaintFunc(
|
|||
Point points[5];
|
||||
int i, np;
|
||||
|
||||
GrClipTriangle(&r, NULL, FALSE, TiGetTypeExact(tile) | dinfo, points, &np);
|
||||
GrClipTriangle(&r, NULL, FALSE, TiGetTypeExact(tile), points, &np);
|
||||
|
||||
/* Write triangle as a CIF polygon */
|
||||
|
||||
|
|
|
|||
150
commands/CmdAB.c
150
commands/CmdAB.c
|
|
@ -338,17 +338,14 @@ CmdArray(
|
|||
case ARRAY_WIDTH:
|
||||
if (locargc == 2)
|
||||
{
|
||||
char *xsepvalue;
|
||||
for (la = lahead; la != NULL; la = la->ar_next)
|
||||
{
|
||||
xsepvalue = DBWPrintValue(la->arrayInfo.ar_xsep,
|
||||
w, TRUE);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
if (doList)
|
||||
{
|
||||
tobj = Tcl_NewListObj(0, NULL);
|
||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||
Tcl_NewStringObj(xsepvalue, -1));
|
||||
Tcl_NewIntObj(la->arrayInfo.ar_xsep));
|
||||
Tcl_SetObjResult(magicinterp, tobj);
|
||||
}
|
||||
else
|
||||
|
|
@ -358,7 +355,7 @@ CmdArray(
|
|||
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
||||
else
|
||||
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
||||
TxPrintf("x separation %s\n", xsepvalue);
|
||||
TxPrintf("x separation %d\n", la->arrayInfo.ar_xsep);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
}
|
||||
#endif
|
||||
|
|
@ -377,17 +374,14 @@ CmdArray(
|
|||
case ARRAY_HEIGHT:
|
||||
if (locargc == 2)
|
||||
{
|
||||
char *ysepvalue;
|
||||
for (la = lahead; la != NULL; la = la->ar_next)
|
||||
{
|
||||
ysepvalue = DBWPrintValue(la->arrayInfo.ar_ysep,
|
||||
w, FALSE);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
if (doList)
|
||||
{
|
||||
tobj = Tcl_NewListObj(0, NULL);
|
||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||
Tcl_NewStringObj(ysepvalue, -1));
|
||||
Tcl_NewIntObj(la->arrayInfo.ar_ysep));
|
||||
Tcl_SetObjResult(magicinterp, tobj);
|
||||
}
|
||||
else
|
||||
|
|
@ -397,7 +391,7 @@ CmdArray(
|
|||
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
||||
else
|
||||
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
||||
TxPrintf("y separation %s\n", ysepvalue);
|
||||
TxPrintf("y separation %d\n", la->arrayInfo.ar_ysep);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
}
|
||||
#endif
|
||||
|
|
@ -416,21 +410,16 @@ CmdArray(
|
|||
case ARRAY_PITCH:
|
||||
if (locargc == 2)
|
||||
{
|
||||
char *xpitch, *ypitch;
|
||||
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
|
||||
if (doList)
|
||||
{
|
||||
tobj = Tcl_NewListObj(0, NULL);
|
||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||
Tcl_NewStringObj(xpitch, -1));
|
||||
Tcl_NewIntObj(la->arrayInfo.ar_xsep));
|
||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||
Tcl_NewStringObj(ypitch, -1));
|
||||
Tcl_NewIntObj(la->arrayInfo.ar_ysep));
|
||||
Tcl_SetObjResult(magicinterp, tobj);
|
||||
}
|
||||
else
|
||||
|
|
@ -440,8 +429,8 @@ CmdArray(
|
|||
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
||||
else
|
||||
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
||||
TxPrintf("x separation %s ", xpitch);
|
||||
TxPrintf("y separation %s\n", ypitch);
|
||||
TxPrintf("x separation %d ", la->arrayInfo.ar_xsep);
|
||||
TxPrintf("y separation %d\n", la->arrayInfo.ar_ysep);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
}
|
||||
#endif
|
||||
|
|
@ -461,21 +450,16 @@ CmdArray(
|
|||
case ARRAY_POSITION:
|
||||
if (locargc == 2)
|
||||
{
|
||||
char *xpos, *ypos;
|
||||
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
|
||||
if (doList)
|
||||
{
|
||||
tobj = Tcl_NewListObj(0, NULL);
|
||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||
Tcl_NewStringObj(xpos, -1));
|
||||
Tcl_NewIntObj(la->cellUse->cu_bbox.r_xbot));
|
||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
||||
Tcl_NewStringObj(ypos, -1));
|
||||
Tcl_NewIntObj(la->cellUse->cu_bbox.r_ybot));
|
||||
Tcl_SetObjResult(magicinterp, tobj);
|
||||
}
|
||||
else
|
||||
|
|
@ -485,8 +469,8 @@ CmdArray(
|
|||
TxPrintf("Cell use \"%s\":", la->cellUse->cu_id);
|
||||
else
|
||||
TxPrintf("Cell \"%s\":", la->cellUse->cu_def->cd_name);
|
||||
TxPrintf("x=%s ", xpos);
|
||||
TxPrintf("y=%s\n", ypos);
|
||||
TxPrintf("x=%d ", la->cellUse->cu_bbox.r_xbot);
|
||||
TxPrintf("y=%d\n", la->cellUse->cu_bbox.r_ybot);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
}
|
||||
#endif
|
||||
|
|
@ -779,8 +763,8 @@ CmdBox(
|
|||
break;
|
||||
case BOX_EXISTS:
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetObjResult(magicinterp,
|
||||
Tcl_NewBooleanObj(ToolGetBox(NULL, NULL) ? TRUE : FALSE));
|
||||
Tcl_SetResult(magicinterp, ToolGetBox(NULL, NULL) ? "1" : "0",
|
||||
NULL);
|
||||
#else
|
||||
TxPrintf("%s\n", ToolGetBox(NULL, NULL) ? "True" : "False");
|
||||
#endif
|
||||
|
|
@ -890,16 +874,13 @@ CmdBox(
|
|||
TxRebuildCommand(cmd);
|
||||
return;
|
||||
}
|
||||
else if (DBWUnits != DBW_UNITS_USER)
|
||||
else if (DBWSnapToGrid != DBW_SNAP_USER)
|
||||
{
|
||||
distancex = cmdParseCoord(w, cmd->tx_argv[3], TRUE, FALSE);
|
||||
distancey = distancex;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For user units, the distance may be different in the X and Y
|
||||
* directions for a given value.
|
||||
*/
|
||||
switch (direction)
|
||||
{
|
||||
case GEO_EAST: case GEO_WEST:
|
||||
|
|
@ -927,14 +908,15 @@ CmdBox(
|
|||
case BOX_WIDTH:
|
||||
if (argc == 2)
|
||||
{
|
||||
char *boxvalues;
|
||||
boxvalues = DBWPrintValue(boxptr->r_xtop - boxptr->r_xbot,
|
||||
w, TRUE);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(boxvalues, -1));
|
||||
char *boxvalues = (char *)Tcl_Alloc(50);
|
||||
sprintf(boxvalues, "%d",
|
||||
boxptr->r_xtop - boxptr->r_xbot);
|
||||
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
||||
#else
|
||||
TxPrintf("%s box width is %s\n", (refEdit) ? "Edit" : "Root",
|
||||
boxvalues);
|
||||
TxPrintf("%s box width is %d\n",
|
||||
(refEdit) ? "Edit" : "Root",
|
||||
boxptr->r_xtop - boxptr->r_xbot);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
|
@ -946,14 +928,15 @@ CmdBox(
|
|||
case BOX_HEIGHT:
|
||||
if (argc == 2)
|
||||
{
|
||||
char *boxvalues;
|
||||
boxvalues = DBWPrintValue(boxptr->r_ytop - boxptr->r_ybot,
|
||||
w, FALSE);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(boxvalues, -1));
|
||||
char *boxvalues = (char *)Tcl_Alloc(50);
|
||||
sprintf(boxvalues, "%d",
|
||||
boxptr->r_ytop - boxptr->r_ybot);
|
||||
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
||||
#else
|
||||
TxPrintf("%s box height is %s\n", (refEdit) ? "Edit" : "Root",
|
||||
boxvalues);
|
||||
TxPrintf("%s box height is %d\n",
|
||||
(refEdit) ? "Edit" : "Root",
|
||||
boxptr->r_ytop - boxptr->r_ybot);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
|
@ -966,24 +949,16 @@ CmdBox(
|
|||
if (argc == 2)
|
||||
{
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_Obj *tobj;
|
||||
#endif
|
||||
char *boxvaluex, *boxvaluey;
|
||||
boxvaluex = DBWPrintValue(boxptr->r_xtop - boxptr->r_xbot,
|
||||
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);
|
||||
char *boxvalues = (char *)Tcl_Alloc(50);
|
||||
sprintf(boxvalues, "%d %d",
|
||||
boxptr->r_xtop - boxptr->r_xbot,
|
||||
boxptr->r_ytop - boxptr->r_ybot);
|
||||
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
||||
#else
|
||||
TxPrintf("%s box size is %s x %s\n",
|
||||
TxPrintf("%s box size is %d x %d\n",
|
||||
(refEdit) ? "Edit" : "Root",
|
||||
boxvaluex, boxvaluey);
|
||||
boxptr->r_xtop - boxptr->r_xbot,
|
||||
boxptr->r_ytop - boxptr->r_ybot);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
|
@ -998,22 +973,14 @@ CmdBox(
|
|||
if (argc == 2)
|
||||
{
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_Obj *tobj;
|
||||
#endif
|
||||
char *boxvaluex, *boxvaluey;
|
||||
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);
|
||||
char *boxvalues = (char *)Tcl_Alloc(50);
|
||||
sprintf(boxvalues, "%d %d",
|
||||
boxptr->r_xbot, boxptr->r_ybot);
|
||||
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
||||
#else
|
||||
TxPrintf("%s box lower-left corner at (%s, %s)\n",
|
||||
TxPrintf("%s box lower-left corner at (%d, %d)\n",
|
||||
(refEdit) ? "Edit" : "Root",
|
||||
boxvaluex, boxvaluey);
|
||||
boxptr->r_xbot, boxptr->r_ybot);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
|
@ -1045,31 +1012,16 @@ CmdBox(
|
|||
if (argc == 2)
|
||||
{
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_Obj *tobj;
|
||||
#endif
|
||||
char *boxvaluellx, *boxvaluelly;
|
||||
char *boxvalueurx, *boxvalueury;
|
||||
|
||||
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);
|
||||
char *boxvalues = (char *)Tcl_Alloc(50);
|
||||
sprintf(boxvalues, "%d %d %d %d",
|
||||
boxptr->r_xbot, boxptr->r_ybot,
|
||||
boxptr->r_xtop, boxptr->r_ytop);
|
||||
Tcl_SetResult(magicinterp, boxvalues, TCL_DYNAMIC);
|
||||
#else
|
||||
TxPrintf("%s box coordinates (%s, %s) to (%s, %s)\n",
|
||||
TxPrintf("%s box coordinates (%d, %d) to (%d, %d)\n",
|
||||
(refEdit) ? "Edit" : "Root",
|
||||
boxvaluellx, boxvaluelly, boxvalueurx, boxvalueury);
|
||||
boxptr->r_xbot, boxptr->r_ybot,
|
||||
boxptr->r_xtop, boxptr->r_ytop);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,13 +117,12 @@ bool cmdDumpParseArgs(char *cmdName, MagWindow *w, TxCommand *cmd, CellUse *dumm
|
|||
#define CALMA_READ 19
|
||||
#define CALMA_READONLY 20
|
||||
#define CALMA_RESCALE 21
|
||||
#define CALMA_SAVEPATHS 22
|
||||
#define CALMA_WARNING 23
|
||||
#define CALMA_WRITE 24
|
||||
#define CALMA_POLYS 25
|
||||
#define CALMA_PATHS 26
|
||||
#define CALMA_UNDEFINED 27
|
||||
#define CALMA_UNIQUE 28
|
||||
#define CALMA_WARNING 22
|
||||
#define CALMA_WRITE 23
|
||||
#define CALMA_POLYS 24
|
||||
#define CALMA_PATHS 25
|
||||
#define CALMA_UNDEFINED 26
|
||||
#define CALMA_UNIQUE 27
|
||||
|
||||
#define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */
|
||||
|
||||
|
|
@ -176,7 +175,6 @@ CmdCalma(
|
|||
" into edit cell",
|
||||
"readonly [yes|no] set cell as read-only and generate output from GDS file",
|
||||
"rescale [yes|no] allow or disallow internal grid subdivision",
|
||||
"savepaths [yes|no] save path centerlines as cell properties",
|
||||
"warning [option] set warning information level",
|
||||
"write file output Calma GDS-II format to \"file\"\n"
|
||||
" for the window's root cell",
|
||||
|
|
@ -740,27 +738,6 @@ CmdCalma(
|
|||
CalmaSubcellPolygons = (unsigned char)option;
|
||||
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:
|
||||
if (cmd->tx_argc == 2)
|
||||
{
|
||||
|
|
@ -1323,7 +1300,7 @@ CmdCellname(
|
|||
if (cellDef == (CellDef *) NULL)
|
||||
TxError("Unknown cell %s\n", cellname);
|
||||
else
|
||||
CmdDoProperty(cellDef, w, cmd, 3 + ((dolist) ? 1 : 0));
|
||||
CmdDoProperty(cellDef, cmd, 3 + ((dolist) ? 1 : 0));
|
||||
break;
|
||||
|
||||
case IDX_DELETE:
|
||||
|
|
@ -2419,10 +2396,8 @@ CmdContact(
|
|||
CCStruct ccs;
|
||||
Rect area;
|
||||
LinkedRect *lr = NULL;
|
||||
|
||||
/* Forward declarations */
|
||||
int cmdContactFunc(Tile *tile, TileType dinfo, CCStruct *ccs);
|
||||
int cmdContactEraseFunc(Tile *tile, TileType dinfo, LinkedRect **lr);
|
||||
int cmdContactFunc(Tile *tile, CCStruct *ccs); /* Forward declaration */
|
||||
int cmdContactEraseFunc(Tile *tile, LinkedRect **lr); /* Forward declaration */
|
||||
|
||||
windCheckOnlyWindow(&w, DBWclientID);
|
||||
if ((w == (MagWindow *) NULL) || (w->w_client != DBWclientID))
|
||||
|
|
@ -2556,14 +2531,11 @@ CmdContact(
|
|||
int
|
||||
cmdContactFunc(
|
||||
Tile *tile,
|
||||
TileType dinfo,
|
||||
CCStruct *ccs)
|
||||
{
|
||||
TileType stype;
|
||||
TileTypeBitMask smask;
|
||||
|
||||
/* Forward declaration */
|
||||
int cmdContactFunc2(Tile *tile, TileType dinfo, CCStruct *ccs);
|
||||
int cmdContactFunc2(Tile *tile, CCStruct *ccs); /* Forward declaration */
|
||||
|
||||
TiToRect(tile, &ccs->area);
|
||||
GeoClip(&ccs->area, &ccs->clip);
|
||||
|
|
@ -2573,16 +2545,14 @@ cmdContactFunc(
|
|||
break;
|
||||
|
||||
TTMaskSetOnlyType(&smask, stype);
|
||||
DBSrPaintNMArea((Tile *)NULL, ccs->rootDef->cd_planes[DBPlane(stype)],
|
||||
TiGetTypeExact(tile) | dinfo, &ccs->area, &smask,
|
||||
cmdContactFunc2, (ClientData)ccs);
|
||||
DBSrPaintArea((Tile *) NULL, ccs->rootDef->cd_planes[DBPlane(stype)],
|
||||
&ccs->area, &smask, cmdContactFunc2, (ClientData)ccs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cmdContactFunc2(
|
||||
Tile *tile,
|
||||
TileType dinfo, /* (unused) */
|
||||
CCStruct *ccs)
|
||||
{
|
||||
LinkedRect *newlr;
|
||||
|
|
@ -2605,7 +2575,6 @@ cmdContactFunc2(
|
|||
int
|
||||
cmdContactEraseFunc(
|
||||
Tile *tile,
|
||||
TileType dinfo, /* (unused) */
|
||||
LinkedRect **lr)
|
||||
{
|
||||
LinkedRect *newlr;
|
||||
|
|
@ -2859,15 +2828,14 @@ CmdCorner(
|
|||
TileTypeBitMask maskBits;
|
||||
Rect editBox;
|
||||
SearchContext scx;
|
||||
extern int cmdCornerFunc(Tile *tile, TreeContext *cxp);
|
||||
bool hasErr = FALSE;
|
||||
int locargc = cmd->tx_argc;
|
||||
|
||||
extern int cmdBevelFunc(Tile *tile, TreeContext *cxp);
|
||||
bool dobevel = FALSE;
|
||||
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)
|
||||
{
|
||||
TxError("Usage: %s direction1 direction2 [layers]\n",
|
||||
|
|
@ -3062,7 +3030,6 @@ CmdCorner(
|
|||
int
|
||||
cmdCornerFunc(
|
||||
Tile *tile, /* Tile to fill with. */
|
||||
TileType dinfo, /* Split tile information (unused) */
|
||||
TreeContext *cxp) /* Describes state of search. */
|
||||
{
|
||||
Rect r1, r2, r3;
|
||||
|
|
@ -3229,7 +3196,6 @@ AddNewPoint(
|
|||
int
|
||||
cmdBevelFunc(
|
||||
Tile *tile, /* Tile to fill with. */
|
||||
TileType dinfo, /* Split tile information (unused) */
|
||||
TreeContext *cxp) /* Describes state of search. */
|
||||
{
|
||||
Rect r1, r2, r3;
|
||||
|
|
@ -4619,7 +4585,6 @@ CmdDrc(
|
|||
int
|
||||
cmdDropPaintCell(
|
||||
Tile *tile,
|
||||
TileType dinfo,
|
||||
TreeContext *cxp)
|
||||
{
|
||||
CellDef *cellDef = cxp->tc_scx->scx_use->cu_def;
|
||||
|
|
@ -4628,7 +4593,7 @@ cmdDropPaintCell(
|
|||
TileType type;
|
||||
Rect area;
|
||||
|
||||
if (dinfo & TT_SIDE)
|
||||
if (SplitSide(tile))
|
||||
type = SplitRightType(tile);
|
||||
else
|
||||
type = SplitLeftType(tile);
|
||||
|
|
@ -4661,7 +4626,6 @@ cmdDropPaintCell(
|
|||
int
|
||||
cmdDropFunc(
|
||||
Tile *tile,
|
||||
TileType dinfo,
|
||||
ClientData clientData)
|
||||
{
|
||||
TileTypeBitMask tMask, *lMask = (TileTypeBitMask *)clientData;
|
||||
|
|
@ -4672,7 +4636,7 @@ cmdDropFunc(
|
|||
scx.scx_use = EditCellUse;
|
||||
scx.scx_trans = GeoIdentityTransform;
|
||||
|
||||
if (dinfo & TT_SIDE)
|
||||
if (SplitSide(tile))
|
||||
type = SplitRightType(tile);
|
||||
else
|
||||
type = SplitLeftType(tile);
|
||||
|
|
@ -5014,20 +4978,15 @@ cmdDumpParseArgs(
|
|||
bbox = def->cd_bbox;
|
||||
if (def->cd_flags & CDFIXEDBBOX)
|
||||
{
|
||||
PropertyRecord *proprec;
|
||||
char *propvalue;
|
||||
bool found;
|
||||
|
||||
proprec = DBPropGet(def, "FIXED_BBOX", &found);
|
||||
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &found);
|
||||
if (found)
|
||||
{
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(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 (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop) != 4)
|
||||
bbox = def->cd_bbox;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
191
commands/CmdE.c
191
commands/CmdE.c
|
|
@ -781,82 +781,39 @@ cmdEraseCellsFunc(
|
|||
* Implement the "expand" command.
|
||||
*
|
||||
* Usage:
|
||||
* expand [selection|surround|overlap|all] [toggle]
|
||||
*
|
||||
* "selection" expands cells in the selection. All other options
|
||||
* expand cells in the layout. "all" expands all cells in the
|
||||
* layout. "surround" expands cells which the cursor box
|
||||
* surrounds completely, and "overlap" expands cells which the
|
||||
* cursor box overlaps.
|
||||
*
|
||||
* If "toggle" is specified, flips the expanded/unexpanded status.
|
||||
* Cells which were expanded are unexpanded, and cells which were
|
||||
* unexpanded are expanded.
|
||||
*
|
||||
* For backwards compatibility:
|
||||
* "expand" alone implements "expand overlap".
|
||||
* "expand toggle" implements "expand selection toggle".
|
||||
*
|
||||
* Also see: CmdUnexpand
|
||||
* expand
|
||||
* expand toggle
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Expansion state of cells is changed. May read cells in from
|
||||
* disk, and update bounding boxes that have changed.
|
||||
* If "toggle" is specified, flips the expanded/unexpanded status
|
||||
* of all selected cells. Otherwise, aren't any unexpanded cells
|
||||
* left under the box. May read cells in from disk, and updates
|
||||
* bounding boxes that have changed.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define EXPAND_SELECTION 0
|
||||
#define EXPAND_SURROUND 1
|
||||
#define EXPAND_OVERLAP 2
|
||||
#define EXPAND_ALL 3
|
||||
#define EXPAND_HELP 4
|
||||
|
||||
void
|
||||
CmdExpand(
|
||||
MagWindow *w,
|
||||
TxCommand *cmd)
|
||||
{
|
||||
int windowMask, boxMask, d, option;
|
||||
bool doToggle = FALSE;
|
||||
const char * const *msg;
|
||||
int windowMask, boxMask, d;
|
||||
Rect rootRect;
|
||||
CellUse *rootBoxUse;
|
||||
CellDef *rootBoxDef;
|
||||
|
||||
int cmdExpandFunc(CellUse *use, int windowMask); /* Forward reference. */
|
||||
|
||||
static const char * const cmdExpandOption[] = {
|
||||
"selection expand cell instances in the selection",
|
||||
"surround expand cell instances which the cursor box surrounds",
|
||||
"overlap expand cell instances which the cursor box overlaps",
|
||||
"all expand all cell instances",
|
||||
NULL
|
||||
};
|
||||
|
||||
if (cmd->tx_argc > 1)
|
||||
if (cmd->tx_argc > 2 || (cmd->tx_argc == 2
|
||||
&& (strncmp(cmd->tx_argv[1], "toggle", strlen(cmd->tx_argv[1])) != 0)))
|
||||
{
|
||||
if (!strncmp(cmd->tx_argv[cmd->tx_argc - 1], "toggle",
|
||||
strlen(cmd->tx_argv[cmd->tx_argc - 1])))
|
||||
{
|
||||
doToggle = TRUE;
|
||||
cmd->tx_argc--;
|
||||
}
|
||||
TxError("Usage: %s or %s toggle\n", cmd->tx_argv[0], cmd->tx_argv[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmd->tx_argc > 1)
|
||||
{
|
||||
option = Lookup(cmd->tx_argv[1], cmdExpandOption);
|
||||
if (option < 0) option = EXPAND_HELP;
|
||||
}
|
||||
else
|
||||
option = EXPAND_OVERLAP;
|
||||
|
||||
if (option == EXPAND_HELP) goto badusage;
|
||||
|
||||
windCheckOnlyWindow(&w, DBWclientID);
|
||||
if (w == (MagWindow *) NULL)
|
||||
{
|
||||
|
|
@ -887,95 +844,23 @@ CmdExpand(
|
|||
WindScale(d, 1);
|
||||
TxPrintf("expand: rescaled by %d\n", d);
|
||||
d = DBLambda[1];
|
||||
if (doToggle) break; /* Don't toggle twice */
|
||||
if (cmd->tx_argc == 2) break; /* Don't toggle twice */
|
||||
}
|
||||
(void) ToolGetBoxWindow(&rootRect, &boxMask);
|
||||
|
||||
if (option != EXPAND_SELECTION)
|
||||
if (cmd->tx_argc == 2)
|
||||
SelectExpand(windowMask);
|
||||
else
|
||||
{
|
||||
if ((boxMask & windowMask) != windowMask)
|
||||
{
|
||||
TxError("The box isn't in the same window as the cursor.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case EXPAND_SELECTION:
|
||||
SelectExpand(windowMask,
|
||||
(doToggle) ? DB_EXPAND_TOGGLE : DB_EXPAND,
|
||||
(Rect *)NULL, FALSE);
|
||||
break;
|
||||
case EXPAND_OVERLAP:
|
||||
if (doToggle)
|
||||
{
|
||||
DBExpandAll(rootBoxUse, &rootRect, windowMask,
|
||||
DB_EXPAND_TOGGLE | DB_EXPAND_OVERLAP,
|
||||
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||
SelectExpand(windowMask,
|
||||
DB_EXPAND_TOGGLE | DB_EXPAND_OVERLAP,
|
||||
&rootRect, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBExpandAll(rootBoxUse, &rootRect, windowMask,
|
||||
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||
SelectExpand(windowMask,
|
||||
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||
&rootRect, FALSE);
|
||||
}
|
||||
break;
|
||||
case EXPAND_SURROUND:
|
||||
if (doToggle)
|
||||
{
|
||||
DBExpandAll(rootBoxUse, &rootRect, windowMask,
|
||||
DB_EXPAND_TOGGLE | DB_EXPAND_SURROUND,
|
||||
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||
SelectExpand(windowMask,
|
||||
DB_EXPAND_TOGGLE | DB_EXPAND_SURROUND,
|
||||
&rootRect, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBExpandAll(rootBoxUse, &rootRect, windowMask,
|
||||
DB_EXPAND | DB_EXPAND_SURROUND,
|
||||
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||
SelectExpand(windowMask,
|
||||
DB_EXPAND | DB_EXPAND_SURROUND,
|
||||
&rootRect, TRUE);
|
||||
}
|
||||
break;
|
||||
case EXPAND_ALL:
|
||||
if (doToggle)
|
||||
{
|
||||
DBExpandAll(rootBoxUse, &TiPlaneRect, windowMask,
|
||||
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||
SelectExpand(windowMask,
|
||||
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||
(Rect *)NULL, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBExpandAll(rootBoxUse, &TiPlaneRect, windowMask,
|
||||
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||
cmdExpandFunc, (ClientData)(pointertype)windowMask);
|
||||
SelectExpand(windowMask,
|
||||
DB_EXPAND | DB_EXPAND_OVERLAP,
|
||||
(Rect *)NULL, FALSE);
|
||||
}
|
||||
break;
|
||||
DBExpandAll(rootBoxUse, &rootRect, windowMask,
|
||||
TRUE, cmdExpandFunc, (ClientData)(pointertype) windowMask);
|
||||
}
|
||||
} while (d != DBLambda[1]);
|
||||
|
||||
return;
|
||||
|
||||
badusage:
|
||||
for (msg = &(cmdExpandOption[0]); *msg != NULL; msg++)
|
||||
TxPrintf(" %s\n", *msg);
|
||||
TxPrintf(" toggle Toggle the visibility of cell instances.\n");
|
||||
}
|
||||
|
||||
/* This function is called for each cell whose expansion status changed.
|
||||
|
|
@ -1040,14 +925,11 @@ cmdExpandFunc(
|
|||
#define DOALL 1
|
||||
#define DOCAPACITANCE 2
|
||||
#define DOCOUPLING 3
|
||||
#define DOEXTRESIST 4
|
||||
#define DOLENGTH 5
|
||||
#define DOLOCAL 6
|
||||
#define DORESISTANCE 7
|
||||
#define DOLABELCHECK 8
|
||||
#define DOALIASES 9
|
||||
#define DOUNIQUE 10
|
||||
#define DOEXTRESIST2 11
|
||||
#define DOLENGTH 4
|
||||
#define DOLOCAL 5
|
||||
#define DORESISTANCE 6
|
||||
#define DOLABELCHECK 7
|
||||
#define DOALIASES 8
|
||||
|
||||
#define LENCLEAR 0
|
||||
#define LENDRIVER 1
|
||||
|
|
@ -1090,14 +972,11 @@ CmdExtract(
|
|||
"all all options",
|
||||
"capacitance extract substrate capacitance",
|
||||
"coupling extract coupling capacitance",
|
||||
"extresist extract resistance",
|
||||
"length compute driver-receiver pathlengths",
|
||||
"local put all generated files in the current directory",
|
||||
"lumped estimate lumped resistance",
|
||||
"resistance estimate resistance",
|
||||
"labelcheck check for connections through sticky labels",
|
||||
"aliases output all net name aliases",
|
||||
"unique ensure unique node names during extraction",
|
||||
"resistance extract resistance (same as \"do extresist\")",
|
||||
NULL
|
||||
};
|
||||
static const char * const cmdExtLength[] =
|
||||
|
|
@ -1241,13 +1120,12 @@ CmdExtract(
|
|||
}
|
||||
else if (argc == 2)
|
||||
{
|
||||
char *halodisp;
|
||||
halodisp = DBWPrintValue(ExtCurStyle->exts_sideCoupleHalo,
|
||||
w, TRUE);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(halodisp, -1));
|
||||
Tcl_Obj *tobj;
|
||||
tobj = Tcl_NewIntObj(ExtCurStyle->exts_sideCoupleHalo);
|
||||
Tcl_SetObjResult(magicinterp, tobj);
|
||||
#else
|
||||
TxPrintf("Side overlap halo is %s\n", halodisp);
|
||||
TxPrintf("Side overlap halo is %d\n", ExtCurStyle->exts_sideCoupleHalo);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
|
@ -1272,12 +1150,12 @@ CmdExtract(
|
|||
}
|
||||
else if (argc == 2)
|
||||
{
|
||||
char *stepdisp;
|
||||
stepdisp = DBWPrintValue(ExtCurStyle->exts_stepSize, w, TRUE);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(stepdisp, -1));
|
||||
Tcl_Obj *tobj;
|
||||
tobj = Tcl_NewIntObj(ExtCurStyle->exts_stepSize);
|
||||
Tcl_SetObjResult(magicinterp, tobj);
|
||||
#else
|
||||
TxPrintf("Extraction step size is %s\n", stepdisp);
|
||||
TxPrintf("Extraction step size is %d\n", ExtCurStyle->exts_stepSize);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
|
@ -1399,11 +1277,9 @@ CmdExtract(
|
|||
TxPrintf("%s capacitance\n", OPTSET(EXT_DOCAPACITANCE));
|
||||
TxPrintf("%s coupling\n", OPTSET(EXT_DOCOUPLING));
|
||||
TxPrintf("%s length\n", OPTSET(EXT_DOLENGTH));
|
||||
TxPrintf("%s lumped R\n", OPTSET(EXT_DORESISTANCE));
|
||||
TxPrintf("%s resistance\n", OPTSET(EXT_DORESISTANCE));
|
||||
TxPrintf("%s label check\n", OPTSET(EXT_DOLABELCHECK));
|
||||
TxPrintf("%s aliases\n", OPTSET(EXT_DOALIASES));
|
||||
TxPrintf("%s unique\n", OPTSET(EXT_DOUNIQUE));
|
||||
TxPrintf("%s resistance (extresist)\n", OPTSET(EXT_DOEXTRESIST));
|
||||
return;
|
||||
#undef OPTSET
|
||||
}
|
||||
|
|
@ -1433,9 +1309,6 @@ CmdExtract(
|
|||
case DORESISTANCE: option = EXT_DORESISTANCE; break;
|
||||
case DOLABELCHECK: option = EXT_DOLABELCHECK; break;
|
||||
case DOALIASES: option = EXT_DOALIASES; break;
|
||||
case DOUNIQUE: option = EXT_DOUNIQUE; break;
|
||||
case DOEXTRESIST:
|
||||
case DOEXTRESIST2: option = EXT_DOEXTRESIST; break;
|
||||
case DOLOCAL:
|
||||
/* "extract do local" and "extract no local" are kept for
|
||||
* backwards compatibility, but now effectively implement
|
||||
|
|
|
|||
|
|
@ -102,17 +102,15 @@ struct cmdFPArg
|
|||
int
|
||||
feedPolyFunc(
|
||||
Tile *tile,
|
||||
TileType dinfo,
|
||||
struct cmdFPArg *arg)
|
||||
{
|
||||
Rect area;
|
||||
TiToRect(tile, &area);
|
||||
|
||||
/* (NOTE: Preserve information about the geometry of a diagonal tile) */
|
||||
DBWFeedbackAdd(&area, arg->text, arg->def, FEEDMAGNIFY,
|
||||
arg->style |
|
||||
((TiGetTypeExact(tile) | dinfo) &
|
||||
(TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
|
||||
(TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE)));
|
||||
/* (preserve information about the geometry of a diagonal tile) */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -509,15 +507,13 @@ struct cmdFillArea *cmdFillList; /* List of areas to fill. */
|
|||
|
||||
void
|
||||
CmdFill(
|
||||
MagWindow *w, /* Window in which command was invoked. */
|
||||
MagWindow *w, /* Window in which command was invoked. */
|
||||
TxCommand *cmd) /* Describes the command that was invoked. */
|
||||
{
|
||||
TileTypeBitMask maskBits;
|
||||
Rect editBox;
|
||||
SearchContext scx;
|
||||
|
||||
/* Forward declaration */
|
||||
extern int cmdFillFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
|
||||
extern int cmdFillFunc(Tile *tile, TreeContext *cxp);
|
||||
|
||||
if (cmd->tx_argc < 2 || cmd->tx_argc > 3)
|
||||
{
|
||||
|
|
@ -607,16 +603,11 @@ CmdFill(
|
|||
* paint here it may mess up the search. Instead, the procedures
|
||||
* save areas on a list. The list is post-processed to paint the
|
||||
* 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
|
||||
cmdFillFunc(
|
||||
Tile *tile, /* Tile to fill with. */
|
||||
TileType dinfo, /* Split tile information (unused) */
|
||||
TreeContext *cxp) /* Describes state of search. */
|
||||
{
|
||||
Rect r1, r2;
|
||||
|
|
@ -1219,7 +1210,7 @@ CmdGetnode(
|
|||
TxError("Put the cursor in a layout window\n");
|
||||
return;
|
||||
}
|
||||
if (is_fast == TRUE)
|
||||
if( is_fast == TRUE )
|
||||
{
|
||||
SimRecomputeSel = TRUE;
|
||||
SimGetsnode();
|
||||
|
|
@ -1227,8 +1218,7 @@ CmdGetnode(
|
|||
else
|
||||
SimGetnode();
|
||||
|
||||
if (SimGetnodeAlias) /* "erase" the hash table */
|
||||
{
|
||||
if (SimGetnodeAlias) { /* "erase" the hash table */
|
||||
HashKill(&SimGNAliasTbl);
|
||||
HashInit(&SimGNAliasTbl, 120, STRINGS);
|
||||
}
|
||||
|
|
@ -1614,7 +1604,7 @@ CmdFindNetProc(
|
|||
int pnum, xpos, ypos;
|
||||
char *xstr, *ystr;
|
||||
bool locvalid = FALSE, usefound = TRUE;
|
||||
TileType ttype, dinfo = (TileType)0;
|
||||
TileType ttype;
|
||||
|
||||
scx.scx_use = use;
|
||||
scx.scx_trans = GeoIdentityTransform;
|
||||
|
|
@ -1652,7 +1642,6 @@ CmdFindNetProc(
|
|||
|
||||
if ((xstr = strchr(s, '_')) != NULL)
|
||||
{
|
||||
char *hashpos;
|
||||
bool isNeg = FALSE;
|
||||
|
||||
/* The characters up to the leading '_' should match one of the */
|
||||
|
|
@ -1696,17 +1685,6 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1729,23 +1707,17 @@ checklocal:
|
|||
|
||||
if (locvalid == TRUE)
|
||||
{
|
||||
int findTile(Tile *tile, TileType dinfo, TileAndDinfo *tad);
|
||||
int findTile(Tile *tile, TileType *rtype);
|
||||
CellDef *targetdef = use->cu_def;
|
||||
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 */
|
||||
/* 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. */
|
||||
/* exists on the plane pnum. */
|
||||
|
||||
tad.tad_tile = (Tile *)NULL;
|
||||
tad.tad_dinfo = dinfo;
|
||||
DBSrPaintArea(NULL, plane, &localrect, &DBAllTypeBits, findTile,
|
||||
(ClientData) &tad);
|
||||
ttype = tad.tad_dinfo & TT_LEFTMASK;
|
||||
(ClientData) &ttype);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1869,31 +1841,20 @@ CmdGoto(
|
|||
int
|
||||
findTile(
|
||||
Tile *tile,
|
||||
TileType dinfo, /* (unused) */
|
||||
TileAndDinfo *tad)
|
||||
TileType *rtype)
|
||||
{
|
||||
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 (tad->tad_dinfo & TT_SIDE)
|
||||
if (SplitSide(tile))
|
||||
ttype = SplitRightType(tile);
|
||||
else
|
||||
ttype = SplitLeftType(tile);
|
||||
}
|
||||
else
|
||||
ttype = TiGetTypeExact(tile);
|
||||
|
||||
/* Leave the tile type in tad_dinfo before returning */
|
||||
tad->tad_dinfo = ttype;
|
||||
|
||||
*rtype = ttype;
|
||||
return 1; /* stop search */
|
||||
}
|
||||
|
||||
|
|
|
|||
588
commands/CmdLQ.c
588
commands/CmdLQ.c
|
|
@ -45,8 +45,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
|||
#include "utils/undo.h"
|
||||
#include "select/select.h"
|
||||
#include "netmenu/netmenu.h"
|
||||
|
||||
/* C99 compat */
|
||||
#include "cif/cif.h"
|
||||
#include "cif/CIFint.h"
|
||||
|
||||
/* Forward declarations */
|
||||
|
||||
|
|
@ -517,14 +518,14 @@ CmdLoad(
|
|||
|
||||
DBExpandAll(topuse, &(topuse->cu_bbox),
|
||||
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
|
||||
DB_EXPAND, keepGoing, NULL);
|
||||
TRUE, keepGoing, NULL);
|
||||
|
||||
DBExpandAll(topuse, &(topuse->cu_bbox),
|
||||
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
|
||||
DB_UNEXPAND, keepGoing, NULL);
|
||||
FALSE, keepGoing, NULL);
|
||||
DBExpand(topuse,
|
||||
((DBWclientRec *)w->w_clientData)->dbw_bitmask,
|
||||
DB_EXPAND);
|
||||
TRUE);
|
||||
|
||||
/* We don't want to save and restore DBLambda, because */
|
||||
/* loading the file may change their values. Instead, we */
|
||||
|
|
@ -2295,8 +2296,6 @@ parsepositions:
|
|||
editDef->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
|
||||
}
|
||||
|
||||
#define PROPERTY_TYPE_COMPAT 4 /* Last entry in cmdPropertyType */
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -2320,448 +2319,47 @@ parsepositions:
|
|||
void
|
||||
CmdDoProperty(
|
||||
CellDef *def,
|
||||
MagWindow *w,
|
||||
TxCommand *cmd,
|
||||
int argstart)
|
||||
{
|
||||
PropertyRecord *proprec;
|
||||
char *value;
|
||||
bool propfound, dolist;
|
||||
int proptype, proplen, propvalue, i;
|
||||
dlong dvalue;
|
||||
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 */
|
||||
char *value;
|
||||
bool propfound;
|
||||
int locargc = cmd->tx_argc - argstart + 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 */
|
||||
DBPropEnum(def, printPropertiesFunc, (ClientData)w);
|
||||
DBPropEnum(def, printPropertiesFunc, NULL);
|
||||
}
|
||||
|
||||
else if (locargc == 2)
|
||||
{
|
||||
/* If the property type was "compat", then give the state of the
|
||||
* compatibility flag and return.
|
||||
*/
|
||||
if (proptype == PROPERTY_TYPE_COMPAT)
|
||||
{
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(DBPropCompat));
|
||||
#else
|
||||
TxPrintf("%s\n", (DBPropCompat == TRUE) ? "True" : "False");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print the value of the indicated property */
|
||||
proprec = (PropertyRecord *)DBPropGet(def, cmd->tx_argv[argstart], &propfound);
|
||||
/* print the value of the indicated property */
|
||||
value = (char *)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;
|
||||
}
|
||||
Tcl_SetResult(magicinterp, value, NULL);
|
||||
#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;
|
||||
}
|
||||
TxPrintf("%s", value);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
#ifdef MAGIC_WRAPPER
|
||||
/* If the command was "cellname list property ...", then */
|
||||
/* just return NULL if the property was not found. */
|
||||
if (!dolist)
|
||||
if (strcmp(cmd->tx_argv[1], "list"))
|
||||
#endif
|
||||
TxError("Property name \"%s\" is not defined\n", cmd->tx_argv[argstart]);
|
||||
TxError("Property name \"%s\" is not defined\n", cmd->tx_argv[1]);
|
||||
}
|
||||
}
|
||||
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)
|
||||
DBPropPut(def, cmd->tx_argv[argstart], NULL);
|
||||
else
|
||||
{
|
||||
if (proptype == PROPERTY_TYPE_STRING)
|
||||
{
|
||||
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);
|
||||
value = StrDup((char **)NULL, cmd->tx_argv[argstart + 1]);
|
||||
DBPropPut(def, cmd->tx_argv[argstart], value);
|
||||
}
|
||||
def->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
|
||||
}
|
||||
|
|
@ -2782,14 +2380,10 @@ CmdDoProperty(
|
|||
* defined in database/DBprop.c.
|
||||
*
|
||||
* Usage:
|
||||
* property [string|integer|dimension] [name] [value]
|
||||
* property [name] [value]
|
||||
*
|
||||
* If the first argument is present, it must be one of the known
|
||||
* 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.
|
||||
* "name" is a unique string tag for the property, and "value" is its
|
||||
* string value.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
|
|
@ -2816,62 +2410,9 @@ CmdProperty(
|
|||
else
|
||||
def = ((CellUse *) w->w_surfaceID)->cu_def;
|
||||
|
||||
CmdDoProperty(def, w, cmd, 1);
|
||||
CmdDoProperty(def, 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
|
||||
|
|
@ -2881,84 +2422,27 @@ printPlanePropFunc(
|
|||
int
|
||||
printPropertiesFunc(
|
||||
const char *name,
|
||||
PropertyRecord *proprec,
|
||||
MagWindow *w)
|
||||
ClientData value,
|
||||
ClientData cdata) /* not used */
|
||||
{
|
||||
int i;
|
||||
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_Obj *tobj, *lobj;
|
||||
char *keyvalue;
|
||||
|
||||
tobj = Tcl_GetObjResult(magicinterp);
|
||||
lobj = Tcl_NewListObj(0, NULL);
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewStringObj(name, -1));
|
||||
|
||||
switch (proprec->prop_type)
|
||||
if (value == NULL)
|
||||
{
|
||||
case PROPERTY_TYPE_STRING:
|
||||
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;
|
||||
keyvalue = (char *)mallocMagic(strlen(name) + 4);
|
||||
sprintf(keyvalue, "%s {}", name);
|
||||
}
|
||||
Tcl_ListObjAppendElement(magicinterp, tobj, lobj);
|
||||
Tcl_SetObjResult(magicinterp, tobj);
|
||||
else
|
||||
{
|
||||
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
|
||||
switch (proprec->prop_type)
|
||||
{
|
||||
case PROPERTY_TYPE_STRING:
|
||||
TxPrintf("%s = %s\n", name, (const char *)proprec->prop_value.prop_string);
|
||||
break;
|
||||
case PROPERTY_TYPE_INTEGER:
|
||||
TxPrintf("%s = ", name);
|
||||
for (i = 0; i < proprec->prop_len; i++)
|
||||
TxPrintf("%d ", proprec->prop_value.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_value.prop_double[i]);
|
||||
TxPrintf("\n");
|
||||
break;
|
||||
}
|
||||
TxPrintf("%s = %s\n", name, (const char *)value);
|
||||
#endif
|
||||
|
||||
return 0; /* keep the search alive */
|
||||
|
|
|
|||
219
commands/CmdRS.c
219
commands/CmdRS.c
|
|
@ -1084,33 +1084,25 @@ CmdSelect(
|
|||
*/
|
||||
|
||||
case SEL_BBOX:
|
||||
{
|
||||
char *selllx, *sellly, *selurx, *selury;
|
||||
|
||||
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
|
||||
lobj = Tcl_NewListObj(0, NULL);
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewStringObj(selllx, -1));
|
||||
Tcl_NewIntObj(selarea.r_xbot));
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewStringObj(sellly, -1));
|
||||
Tcl_NewIntObj(selarea.r_ybot));
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewStringObj(selurx, -1));
|
||||
Tcl_NewIntObj(selarea.r_xtop));
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewStringObj(selury, -1));
|
||||
Tcl_NewIntObj(selarea.r_ytop));
|
||||
Tcl_SetObjResult(magicinterp, lobj);
|
||||
#else
|
||||
TxPrintf("Select bounding box: %s %s %s %s\n",
|
||||
selllx, sellly, selurx, selury);
|
||||
TxPrintf("Select bounding box: %d %d %d %d\n",
|
||||
selarea.r_xbot, selarea.r_ybot,
|
||||
selarea.r_xtop, selarea.r_ytop);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
* Make a copy of the selection at its present loction but do not
|
||||
|
|
@ -1801,18 +1793,13 @@ cmdLabelSizeFunc(
|
|||
|
||||
if (value == NULL)
|
||||
{
|
||||
char *labsize;
|
||||
MagWindow *w;
|
||||
|
||||
windCheckOnlyWindow(&w, DBWclientID);
|
||||
labsize = DBWPrintValue(label->lab_size / 8, w, FALSE);
|
||||
|
||||
#ifdef MAGIC_WRAPPER
|
||||
lobj = Tcl_GetObjResult(magicinterp);
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewStringObj(labsize, -1));
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewDoubleObj((double)label->lab_size / 8.0));
|
||||
Tcl_SetObjResult(magicinterp, lobj);
|
||||
#else
|
||||
TxPrintf("%s\n", labsize);
|
||||
TxPrintf("%g\n", (double)label->lab_size / 8.0);
|
||||
#endif
|
||||
}
|
||||
else if (label->lab_size != *value)
|
||||
|
|
@ -1957,22 +1944,18 @@ cmdLabelOffsetFunc(
|
|||
|
||||
if (point == NULL)
|
||||
{
|
||||
char *laboffx, *laboffy;
|
||||
MagWindow *w;
|
||||
|
||||
windCheckOnlyWindow(&w, DBWclientID);
|
||||
laboffx = DBWPrintValue(label->lab_offset.p_x / 8, w, TRUE);
|
||||
laboffy = DBWPrintValue(label->lab_offset.p_x / 8, w, FALSE);
|
||||
|
||||
#ifdef MAGIC_WRAPPER
|
||||
lobj = Tcl_GetObjResult(magicinterp);
|
||||
pobj = Tcl_NewListObj(0, NULL);
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(laboffx, -1));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(laboffy, -1));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
||||
Tcl_NewDoubleObj((double)label->lab_offset.p_x / 8.0));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
||||
Tcl_NewDoubleObj((double)label->lab_offset.p_y / 8.0));
|
||||
Tcl_SetObjResult(magicinterp, lobj);
|
||||
#else
|
||||
TxPrintf("%s %s\n", laboffx, laboffy);
|
||||
TxPrintf("%g %g\n", (double)(label->lab_offset.p_x) / 8.0,
|
||||
(double)(label->lab_offset.p_y) / 8.0);
|
||||
#endif
|
||||
}
|
||||
else if (!GEO_SAMEPOINT(label->lab_offset, *point))
|
||||
|
|
@ -2002,25 +1985,23 @@ cmdLabelRectFunc(
|
|||
|
||||
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
|
||||
lobj = Tcl_GetObjResult(magicinterp);
|
||||
pobj = Tcl_NewListObj(0, NULL);
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(labllx, -1));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(lablly, -1));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(laburx, -1));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(labury, -1));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
||||
Tcl_NewIntObj((double)label->lab_rect.r_xbot));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj,
|
||||
Tcl_NewIntObj((double)label->lab_rect.r_ybot));
|
||||
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);
|
||||
#else
|
||||
TxPrintf("%s %s %s %s\n", labllx, lablly, laburx,labury);
|
||||
TxPrintf("%d %d %d %d\n",
|
||||
label->lab_rect.r_xbot, label->lab_rect.r_ybot,
|
||||
label->lab_rect.r_xtop, label->lab_rect.r_ytop);
|
||||
#endif
|
||||
}
|
||||
else if (!GEO_SAMERECT(label->lab_rect, *rect))
|
||||
|
|
@ -2221,13 +2202,9 @@ CmdSetLabel(
|
|||
}
|
||||
else if (EditCellUse)
|
||||
{
|
||||
if (locargc == 2)
|
||||
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelTextFunc, (ClientData)NULL);
|
||||
else
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelTextFunc,
|
||||
(ClientData)cmd->tx_argv[argstart + 1]);
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelTextFunc, (locargc == 3) ?
|
||||
(ClientData)cmd->tx_argv[argstart + 1] : (ClientData)NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -2293,12 +2270,9 @@ CmdSetLabel(
|
|||
}
|
||||
else if (EditCellUse)
|
||||
{
|
||||
if (locargc == 2)
|
||||
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelFontFunc, (ClientData)NULL);
|
||||
else
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelFontFunc, (ClientData)&font);
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelFontFunc, (locargc == 3) ?
|
||||
(ClientData)&font : (ClientData)NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -2326,12 +2300,9 @@ CmdSetLabel(
|
|||
}
|
||||
else if (EditCellUse)
|
||||
{
|
||||
if (locargc == 2)
|
||||
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelJustFunc, (ClientData)NULL);
|
||||
else
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelJustFunc, (ClientData)&pos);
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelJustFunc, (locargc == 3) ?
|
||||
(ClientData)&pos : (ClientData)NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -2346,13 +2317,11 @@ CmdSetLabel(
|
|||
{
|
||||
if (locargc == 2)
|
||||
{
|
||||
char *labsize;
|
||||
|
||||
labsize = DBWPrintValue(DefaultLabel->lab_size, w, FALSE);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(labsize, -1));
|
||||
Tcl_SetObjResult(magicinterp,
|
||||
Tcl_NewIntObj(DefaultLabel->lab_size));
|
||||
#else
|
||||
TxPrintf("%s\n", labsize);
|
||||
TxPrintf("%d\n", DefaultLabel->lab_size);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
|
@ -2360,12 +2329,9 @@ CmdSetLabel(
|
|||
}
|
||||
else if (EditCellUse)
|
||||
{
|
||||
if (locargc == 2)
|
||||
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelSizeFunc, (ClientData)NULL);
|
||||
else
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelSizeFunc, (ClientData)&size);
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelSizeFunc, (locargc == 3) ?
|
||||
(ClientData)&size : (ClientData)NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -2394,20 +2360,16 @@ CmdSetLabel(
|
|||
{
|
||||
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
|
||||
lobj = Tcl_NewListObj(0, NULL);
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewStringObj(laboffx, -1));
|
||||
Tcl_NewIntObj(DefaultLabel->lab_offset.p_x));
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewStringObj(laboffy, -1));
|
||||
Tcl_NewIntObj(DefaultLabel->lab_offset.p_y));
|
||||
Tcl_SetObjResult(magicinterp, lobj);
|
||||
#else
|
||||
TxPrintf("%s %s\n", laboffx, laboffy);
|
||||
TxPrintf("%d %d\n", DefaultLabel->lab_offset.p_x,
|
||||
DefaultLabel->lab_offset.p_y);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
|
@ -2415,12 +2377,9 @@ CmdSetLabel(
|
|||
}
|
||||
else if (EditCellUse)
|
||||
{
|
||||
if (locargc == 2)
|
||||
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelOffsetFunc, (ClientData)NULL);
|
||||
else
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelOffsetFunc, (ClientData)&offset);
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelOffsetFunc, (locargc != 2) ?
|
||||
(ClientData)&offset : (ClientData)NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -2484,12 +2443,10 @@ CmdSetLabel(
|
|||
rect.r_ytop = cmdScaleCoord(w, cmd->tx_argv[argstart + 4],
|
||||
TRUE, FALSE, 1);
|
||||
}
|
||||
if ((locargc == 3) || (locargc == 6))
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelRectFunc, (ClientData)&rect);
|
||||
else
|
||||
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelRectFunc, (ClientData)NULL);
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelRectFunc,
|
||||
((locargc == 6) || (locargc == 3)) ?
|
||||
(ClientData)&rect : (ClientData)NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -2515,12 +2472,9 @@ CmdSetLabel(
|
|||
}
|
||||
else if (EditCellUse)
|
||||
{
|
||||
if (locargc == 2)
|
||||
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelRotateFunc, (ClientData)NULL);
|
||||
else
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelRotateFunc, (ClientData)&rotate);
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelRotateFunc, (locargc == 3) ?
|
||||
(ClientData)&rotate : (ClientData)NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -2552,12 +2506,9 @@ CmdSetLabel(
|
|||
}
|
||||
else if (EditCellUse)
|
||||
{
|
||||
if (locargc == 2)
|
||||
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelStickyFunc, (ClientData)NULL);
|
||||
else
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelStickyFunc, (ClientData)&flags);
|
||||
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelStickyFunc, (locargc == 3) ?
|
||||
(ClientData)&flags : (ClientData)NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -2596,12 +2547,9 @@ CmdSetLabel(
|
|||
}
|
||||
else if (EditCellUse)
|
||||
{
|
||||
if (locargc == 2)
|
||||
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelLayerFunc, (ClientData)NULL);
|
||||
else
|
||||
SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelLayerFunc, (ClientData)&ttype);
|
||||
SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL,
|
||||
cmdLabelLayerFunc, (locargc == 3) ?
|
||||
(ClientData)&ttype : (ClientData)NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -2936,39 +2884,16 @@ CmdSnap(
|
|||
TxPrintf("Usage: snap [internal | lambda | user]\n");
|
||||
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)
|
||||
{
|
||||
case SNAP_OFF: case SNAP_INTERNAL:
|
||||
DBWSnapToGrid = DBW_UNITS_INTERNAL;
|
||||
DBWSnapToGrid = DBW_SNAP_INTERNAL;
|
||||
return;
|
||||
case SNAP_LAMBDA:
|
||||
DBWSnapToGrid = DBW_UNITS_LAMBDA;
|
||||
DBWSnapToGrid = DBW_SNAP_LAMBDA;
|
||||
return;
|
||||
case SNAP_GRID: case SNAP_USER: case SNAP_ON:
|
||||
DBWSnapToGrid = DBW_UNITS_USER;
|
||||
DBWSnapToGrid = DBW_SNAP_USER;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2976,19 +2901,21 @@ printit:
|
|||
if (n == SNAP_LIST) /* list */
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetResult(magicinterp,
|
||||
(DBWSnapToGrid == DBW_UNITS_INTERNAL) ? "internal" :
|
||||
((DBWSnapToGrid == DBW_UNITS_LAMBDA) ? "lambda" : "user"),
|
||||
(DBWSnapToGrid == DBW_SNAP_INTERNAL) ? "internal" :
|
||||
((DBWSnapToGrid == DBW_SNAP_LAMBDA) ? "lambda" : "user"),
|
||||
TCL_VOLATILE);
|
||||
#else
|
||||
TxPrintf("%s\n", (DBWSnapToGrid == DBW_UNITS_INTERNAL) ? "internal" :
|
||||
((DBWSnapToGrid == DBW_UNITS_LAMBDA) ? "lambda" : "user"));
|
||||
TxPrintf("%s\n", (DBWSnapToGrid == DBW_SNAP_INTERNAL) ? "internal" :
|
||||
((DBWSnapToGrid == DBW_SNAP_LAMBDA) ? "lambda" : "user"));
|
||||
#endif
|
||||
else
|
||||
TxPrintf("Box is aligned to %s grid\n",
|
||||
(DBWSnapToGrid == DBW_UNITS_INTERNAL) ? "internal" :
|
||||
((DBWSnapToGrid == DBW_UNITS_LAMBDA) ? "lambda" : "user"));
|
||||
(DBWSnapToGrid == DBW_SNAP_INTERNAL) ? "internal" :
|
||||
((DBWSnapToGrid == DBW_SNAP_LAMBDA) ? "lambda" : "user"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
|
|||
|
|
@ -73,22 +73,9 @@ TileTypeBitMask CmdYMAllButSpace;
|
|||
* lambda, a suffix of "g" indicates the user grid, and a suffix in metric
|
||||
* notation ("nm", "um", "mm", "cm") indicates natural units. Other valid
|
||||
* units are "cu" or "centimicrons" for centimicrons, or "microns" for um.
|
||||
* Traditional (backwards-compatible) behavior: Units without any suffix
|
||||
* are assumed to be in lambda if "snap" (DBWSnapToGrid) is set to lambda,
|
||||
* 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).
|
||||
* Units without any suffix are assumed to be in lambda if "snap"
|
||||
* (DBWSnapToGrid) is set to lambda, grid units if "snap" is set to the
|
||||
* user grid, and internal units otherwise.
|
||||
*
|
||||
* 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
|
||||
|
|
@ -112,13 +99,6 @@ 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
|
||||
cmdScaleCoord(
|
||||
MagWindow *w,
|
||||
|
|
@ -129,195 +109,107 @@ cmdScaleCoord(
|
|||
{
|
||||
char *endptr;
|
||||
double dval = 0;
|
||||
int mscale = 1, curunits;
|
||||
int retval, curval, parseop;
|
||||
int mscale = 1;
|
||||
DBWclientRec *crec;
|
||||
|
||||
if (*arg == '{' || *arg == '"') arg++;
|
||||
while (isspace(*arg) && (*arg != '\0')) arg++;
|
||||
if (*arg == '{') arg++;
|
||||
while (isspace(*arg)) arg++;
|
||||
|
||||
parseop = PARSEOP_NONE;
|
||||
retval = 0;
|
||||
while (*arg != '\0')
|
||||
dval = strtod(arg, &endptr);
|
||||
dval *= (double)scale;
|
||||
|
||||
if (endptr == arg)
|
||||
{
|
||||
dval = strtod(arg, &endptr);
|
||||
dval *= (double)scale;
|
||||
mscale = -1;
|
||||
/* strtod() error condition */
|
||||
TxError("Coordinate value cannot be parsed: assuming 0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (endptr == arg)
|
||||
else if ((*endptr == 'l')
|
||||
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_LAMBDA)))
|
||||
{
|
||||
/* lambda or default units */
|
||||
dval *= (double)DBLambda[1];
|
||||
dval /= (double)DBLambda[0];
|
||||
return round(dval);
|
||||
}
|
||||
else if ((*endptr == 'i')
|
||||
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_INTERNAL)))
|
||||
{
|
||||
/* internal units */
|
||||
return round(dval);
|
||||
}
|
||||
else if ((*endptr == 'g')
|
||||
|| ((*endptr == '\0') && (DBWSnapToGrid == DBW_SNAP_USER)))
|
||||
{
|
||||
/* grid units */
|
||||
if (w == (MagWindow *)NULL)
|
||||
{
|
||||
/* strtod() error condition */
|
||||
TxError("Coordinate value cannot be parsed: assuming 0\n");
|
||||
curval = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Original behavior was to accept un-suffixed values according to the
|
||||
* "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 */
|
||||
dval *= (double)DBLambda[1];
|
||||
dval /= (double)DBLambda[0];
|
||||
}
|
||||
else if ((*endptr == 'i')
|
||||
|| (((*endptr == '\0') || isspace(*endptr))
|
||||
&& (curunits == DBW_UNITS_INTERNAL)))
|
||||
{
|
||||
/* internal units */
|
||||
}
|
||||
else if ((*endptr == 'g')
|
||||
|| (((*endptr == '\0') || isspace(*endptr))
|
||||
&& (curunits == DBW_UNITS_USER)))
|
||||
{
|
||||
/* grid units */
|
||||
windCheckOnlyWindow(&w, DBWclientID);
|
||||
if (w == (MagWindow *)NULL)
|
||||
{
|
||||
windCheckOnlyWindow(&w, DBWclientID);
|
||||
if (w == (MagWindow *)NULL)
|
||||
{
|
||||
curval = round(dval); /* Default, if window is unknown */
|
||||
break;
|
||||
}
|
||||
}
|
||||
crec = (DBWclientRec *) w->w_clientData;
|
||||
if (is_x)
|
||||
{
|
||||
dval *= (double)(crec->dbw_gridRect.r_xtop
|
||||
return round(dval); /* Default, if window is unknown */
|
||||
}
|
||||
crec = (DBWclientRec *) w->w_clientData;
|
||||
if (is_x)
|
||||
{
|
||||
dval *= (double)(crec->dbw_gridRect.r_xtop
|
||||
- crec->dbw_gridRect.r_xbot);
|
||||
if (!is_relative)
|
||||
dval += (double)crec->dbw_gridRect.r_xbot;
|
||||
}
|
||||
else
|
||||
{
|
||||
dval *= (double)(crec->dbw_gridRect.r_ytop
|
||||
if (!is_relative)
|
||||
dval += (double)crec->dbw_gridRect.r_xbot;
|
||||
}
|
||||
else
|
||||
{
|
||||
dval *= (double)(crec->dbw_gridRect.r_ytop
|
||||
- crec->dbw_gridRect.r_ybot);
|
||||
if (!is_relative)
|
||||
dval += (double)crec->dbw_gridRect.r_ybot;
|
||||
}
|
||||
if (!is_relative)
|
||||
dval += (double)crec->dbw_gridRect.r_ybot;
|
||||
}
|
||||
else if (((*endptr == '\0') || isspace(*endptr))
|
||||
&& (curunits == DBW_UNITS_MICRONS))
|
||||
{
|
||||
mscale = 1000;
|
||||
}
|
||||
else if (*endptr != '\0')
|
||||
{
|
||||
/* natural units referred to the current cifoutput style */
|
||||
if (*(endptr + 1) == 'm')
|
||||
{
|
||||
switch (*endptr)
|
||||
{
|
||||
case 'n':
|
||||
mscale = 1;
|
||||
break;
|
||||
case 'u':
|
||||
mscale = 1000;
|
||||
break;
|
||||
case 'm':
|
||||
mscale = 1000000;
|
||||
break;
|
||||
case 'c':
|
||||
mscale = 10000000;
|
||||
break;
|
||||
default:
|
||||
TxError("Unknown metric prefix \"%cm\"; assuming "
|
||||
"internal units\n", *endptr);
|
||||
mscale = -1;
|
||||
}
|
||||
}
|
||||
else if ((*endptr == 'u') && !isalnum(*(endptr + 1)))
|
||||
/* Maybe "u" is too ambiguous but it is very commonly used as
|
||||
* an abbreviation for "micron".
|
||||
*/
|
||||
mscale = 1000;
|
||||
else if (!strncmp(endptr, "micron", 6))
|
||||
mscale = 1000;
|
||||
else if (!strncmp(endptr, "centimicron", 11) || !strcmp(endptr, "cu"))
|
||||
mscale = 10;
|
||||
else if (!isspace(*endptr) && (*endptr != '+') && (*endptr != '-') &&
|
||||
(*endptr != '*') && (*endptr != '/'))
|
||||
{
|
||||
TxError("Unknown coordinate type at \"%s\"; assuming internal units\n",
|
||||
endptr);
|
||||
mscale = -1;
|
||||
}
|
||||
}
|
||||
if (mscale != -1)
|
||||
dval /= CIFGetOutputScale(mscale);
|
||||
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')
|
||||
return round(dval);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* natural units referred to the current cifoutput style */
|
||||
if (*(endptr + 1) == 'm')
|
||||
{
|
||||
switch (*endptr)
|
||||
{
|
||||
case '}':
|
||||
case '"':
|
||||
parseop = PARSEOP_END;
|
||||
case 'n':
|
||||
mscale = 1;
|
||||
break;
|
||||
case '+':
|
||||
parseop = PARSEOP_ADD;
|
||||
endptr++;
|
||||
case 'u':
|
||||
mscale = 1000;
|
||||
break;
|
||||
case '-':
|
||||
parseop = PARSEOP_SUB;
|
||||
endptr++;
|
||||
case 'm':
|
||||
mscale = 1000000;
|
||||
break;
|
||||
case '*':
|
||||
parseop = PARSEOP_MUL;
|
||||
endptr++;
|
||||
break;
|
||||
case '/':
|
||||
parseop = PARSEOP_DIV;
|
||||
endptr++;
|
||||
break;
|
||||
case ' ':
|
||||
case '\t':
|
||||
endptr++;
|
||||
case 'c':
|
||||
mscale = 10000000;
|
||||
break;
|
||||
default:
|
||||
/* Should this flag an error? */
|
||||
return retval;
|
||||
TxError("Unknown metric prefix \"%cm\"; assuming internal units\n",
|
||||
*endptr);
|
||||
return round(dval);
|
||||
}
|
||||
if (parseop != PARSEOP_NONE) break;
|
||||
}
|
||||
arg = endptr;
|
||||
while (isspace(*arg) && (*arg != '\0')) arg++;
|
||||
else if (!strcmp(endptr, "u"))
|
||||
/* Maybe "u" is too ambiguous but it is very commonly used as
|
||||
* an abbreviation for "micron".
|
||||
*/
|
||||
mscale = 1000;
|
||||
else if (!strncmp(endptr, "micron", 6))
|
||||
mscale = 1000;
|
||||
else if (!strncmp(endptr, "centimicron", 11) || !strcmp(endptr, "cu"))
|
||||
mscale = 10;
|
||||
else if (!isspace(*endptr))
|
||||
{
|
||||
TxError("Unknown coordinate type \"%s\"; assuming internal units\n",
|
||||
endptr);
|
||||
return round(dval);
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
if (!isspace(*endptr))
|
||||
dval /= CIFGetOutputScale(mscale);
|
||||
return round(dval);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -761,16 +653,13 @@ cmdSaveCell(
|
|||
if (!tryRename || (fileName == NULL) || (strcmp(cellDef->cd_name, fileName) == 0))
|
||||
goto cleanup;
|
||||
|
||||
/* Rename the cell, unless fileName is a .tcl file (scripted output) */
|
||||
if ((strlen(fileName) <= 4) || strcmp(fileName + strlen(fileName) - 4, ".tcl"))
|
||||
/* Rename the cell */
|
||||
if (!DBCellRenameDef(cellDef, fileName))
|
||||
{
|
||||
if (!DBCellRenameDef(cellDef, fileName))
|
||||
{
|
||||
/* This should never happen */
|
||||
TxError("Magic error: there is already a cell named \"%s\"\n",
|
||||
/* This should never happen */
|
||||
TxError("Magic error: there is already a cell named \"%s\"\n",
|
||||
fileName);
|
||||
goto cleanup;
|
||||
}
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (EditCellUse && (cellDef == EditCellUse->cu_def))
|
||||
|
|
@ -1239,7 +1128,7 @@ cmdExpandOneLevel(
|
|||
extern int cmdExpand1func(CellUse *cu, ClientData bitmask);
|
||||
|
||||
/* first, expand this cell use */
|
||||
DBExpand(cu, bitmask, expand ? DB_EXPAND : DB_UNEXPAND);
|
||||
DBExpand(cu, bitmask, expand);
|
||||
|
||||
/* now, unexpand its direct children (ONE LEVEL ONLY) */
|
||||
if (expand)
|
||||
|
|
@ -1251,7 +1140,7 @@ cmdExpand1func(
|
|||
CellUse *cu,
|
||||
ClientData bitmask)
|
||||
{
|
||||
DBExpand(cu, (int)CD2INT(bitmask), DB_UNEXPAND);
|
||||
DBExpand(cu, (int)CD2INT(bitmask), FALSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
309
commands/CmdTZ.c
309
commands/CmdTZ.c
|
|
@ -61,9 +61,7 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
|||
|
||||
int
|
||||
existFunc(
|
||||
Tile *tile, /* (unused) */
|
||||
TileType dinfo, /* (unused) */
|
||||
ClientData clientdata) /* (unused) */
|
||||
Tile *tile)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -455,18 +453,15 @@ CmdTech(
|
|||
}
|
||||
if (!strncmp(cmd->tx_argv[2], "width", 5))
|
||||
{
|
||||
char *techwidth;
|
||||
tresult = DRCGetDefaultLayerWidth(t1);
|
||||
techwidth = DBWPrintValue(tresult, w, TRUE);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techwidth, -1));
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
|
||||
#else
|
||||
TxPrintf("Minimum width is %s\n", techwidth);
|
||||
TxPrintf("Minimum width is %d\n", tresult);
|
||||
#endif
|
||||
}
|
||||
else if (!strncmp(cmd->tx_argv[2], "spac", 4))
|
||||
{
|
||||
char *techspace;
|
||||
if (cmd->tx_argc >= 5)
|
||||
{
|
||||
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
|
||||
|
|
@ -478,16 +473,14 @@ CmdTech(
|
|||
else
|
||||
t2 = t1;
|
||||
tresult = DRCGetDefaultLayerSpacing(t1, t2);
|
||||
techspace = DBWPrintValue(tresult, w, TRUE);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techspace, -1));
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
|
||||
#else
|
||||
TxPrintf("Minimum spacing is %s\n", techspace);
|
||||
TxPrintf("Minimum spacing is %d\n", tresult);
|
||||
#endif
|
||||
}
|
||||
else if (!strncmp(cmd->tx_argv[2], "surr", 4))
|
||||
{
|
||||
char *techsurround;
|
||||
if (cmd->tx_argc >= 5)
|
||||
{
|
||||
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
|
||||
|
|
@ -503,17 +496,14 @@ CmdTech(
|
|||
}
|
||||
|
||||
tresult = DRCGetDefaultLayerSurround(t1, t2);
|
||||
techsurround = DBWPrintValue(tresult, w, TRUE);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techsurround, -1));
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
|
||||
#else
|
||||
TxPrintf("Minimum surround is %s\n", techsurround);
|
||||
TxPrintf("Minimum surround is %d\n", tresult);
|
||||
#endif
|
||||
}
|
||||
else if (!strncmp(cmd->tx_argv[2], "direc", 5))
|
||||
{
|
||||
char *techdirec;
|
||||
|
||||
if (cmd->tx_argc >= 5)
|
||||
{
|
||||
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
|
||||
|
|
@ -529,11 +519,10 @@ CmdTech(
|
|||
}
|
||||
|
||||
tresult = DRCGetDirectionalLayerSurround(t1, t2);
|
||||
techdirec = DBWPrintValue(tresult, w, TRUE);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewStringObj(techdirec, -1));
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
|
||||
#else
|
||||
TxPrintf("Minimum surround (in one orientation) is %s\n", techdirec);
|
||||
TxPrintf("Minimum surround (in one orientation) is %d\n", tresult);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -702,62 +691,32 @@ CmdTool(
|
|||
* Implement the "unexpand" command.
|
||||
*
|
||||
* Usage:
|
||||
* unexpand [selection|surround|overlap|all]
|
||||
*
|
||||
* "selection" unexpands (hides) cells in the selection. All
|
||||
* other options unexpand cells in the layout. "all" unexpands
|
||||
* all cells in the layout. "surround" unexpannds cells which
|
||||
* the cursor box surrounds completely, and "overlap" unexpands
|
||||
* cells which the cursor box overlaps.
|
||||
*
|
||||
* For backwards compatibility:
|
||||
* "unexpand" alone implements "unexpand surround".
|
||||
*
|
||||
* Also see: CmdExpand
|
||||
* unexpand
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Changes the expansion state of cells.
|
||||
* Unexpands all cells under the box that don't completely
|
||||
* contain the box.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define UNEXPAND_SELECTION 0
|
||||
#define UNEXPAND_SURROUND 1
|
||||
#define UNEXPAND_OVERLAP 2
|
||||
#define UNEXPAND_ALL 3
|
||||
#define UNEXPAND_HELP 4
|
||||
|
||||
void
|
||||
CmdUnexpand(
|
||||
MagWindow *w,
|
||||
TxCommand *cmd)
|
||||
{
|
||||
int windowMask, boxMask, option;
|
||||
const char * const *msg;
|
||||
int windowMask, boxMask;
|
||||
Rect rootRect;
|
||||
|
||||
int cmdUnexpandFunc(CellUse *use, int windowMask); /* Forward reference. */
|
||||
|
||||
static const char * const cmdUnexpandOption[] = {
|
||||
"selection expand cell instances in the selection",
|
||||
"surround expand cell instances which the cursor box surrounds",
|
||||
"overlap expand cell instances which the cursor box overlaps",
|
||||
"all expand all cell instances",
|
||||
NULL
|
||||
};
|
||||
|
||||
if (cmd->tx_argc > 1)
|
||||
if (cmd->tx_argc != 1)
|
||||
{
|
||||
option = Lookup(cmd->tx_argv[1], cmdUnexpandOption);
|
||||
if (option < 0) option = UNEXPAND_HELP;
|
||||
TxError("Usage: %s\n", cmd->tx_argv[0]);
|
||||
return;
|
||||
}
|
||||
else
|
||||
option = UNEXPAND_SURROUND;
|
||||
|
||||
if (option == UNEXPAND_HELP) goto badusage;
|
||||
|
||||
windCheckOnlyWindow(&w, DBWclientID);
|
||||
if (w == (MagWindow *) NULL)
|
||||
|
|
@ -773,42 +732,8 @@ CmdUnexpand(
|
|||
TxError("The box isn't in the same window as the cursor.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case UNEXPAND_SELECTION:
|
||||
SelectExpand(windowMask, DB_UNEXPAND, (Rect *)NULL, FALSE);
|
||||
break;
|
||||
case UNEXPAND_OVERLAP:
|
||||
DBExpandAll(((CellUse *)w->w_surfaceID), &rootRect, windowMask,
|
||||
DB_UNEXPAND | DB_EXPAND_OVERLAP,
|
||||
cmdUnexpandFunc, (ClientData)(pointertype)windowMask);
|
||||
SelectExpand(windowMask,
|
||||
DB_UNEXPAND | DB_EXPAND_OVERLAP,
|
||||
&rootRect, FALSE);
|
||||
break;
|
||||
case UNEXPAND_SURROUND:
|
||||
DBExpandAll(((CellUse *)w->w_surfaceID), &rootRect, windowMask,
|
||||
DB_UNEXPAND | DB_EXPAND_SURROUND,
|
||||
cmdUnexpandFunc, (ClientData)(pointertype)windowMask);
|
||||
SelectExpand(windowMask,
|
||||
DB_UNEXPAND | DB_EXPAND_SURROUND,
|
||||
&rootRect, TRUE);
|
||||
break;
|
||||
case UNEXPAND_ALL:
|
||||
DBExpandAll(((CellUse *)w->w_surfaceID), &TiPlaneRect, windowMask,
|
||||
DB_UNEXPAND | DB_EXPAND_OVERLAP,
|
||||
cmdUnexpandFunc, (ClientData)(pointertype)windowMask);
|
||||
SelectExpand(windowMask,
|
||||
DB_UNEXPAND | DB_EXPAND_OVERLAP,
|
||||
(Rect *)NULL);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
|
||||
badusage:
|
||||
for (msg = &(cmdUnexpandOption[0]); *msg != NULL; msg++)
|
||||
TxPrintf(" %s\n", *msg);
|
||||
DBExpandAll(((CellUse *) w->w_surfaceID), &rootRect, windowMask,
|
||||
FALSE, cmdUnexpandFunc, (ClientData)(pointertype) windowMask);
|
||||
}
|
||||
|
||||
/* This function is called for each cell whose expansion status changed.
|
||||
|
|
@ -827,182 +752,6 @@ cmdUnexpandFunc(
|
|||
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]);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -1090,8 +839,7 @@ struct linked_id {
|
|||
|
||||
int
|
||||
cmdWhatPrintCell(
|
||||
Tile *tile, /* (unused) */
|
||||
TileType dinfo, /* (unused) */
|
||||
Tile *tile,
|
||||
TreeContext *cxp)
|
||||
{
|
||||
struct linked_id **lid = (struct linked_id **)cxp->tc_filter->tf_arg;
|
||||
|
|
@ -1146,7 +894,6 @@ static LabelStore *labelBlockTop, *labelEntry;
|
|||
int
|
||||
cmdFindWhatTileFunc(
|
||||
Tile *tile,
|
||||
TileType dinfo,
|
||||
ClientData clientData)
|
||||
{
|
||||
struct linked_id **lid = (struct linked_id **)clientData;
|
||||
|
|
@ -1158,7 +905,7 @@ cmdFindWhatTileFunc(
|
|||
scx.scx_use = EditCellUse;
|
||||
scx.scx_trans = GeoIdentityTransform;
|
||||
|
||||
if (dinfo & TT_SIDE)
|
||||
if (SplitSide(tile))
|
||||
type = SplitRightType(tile);
|
||||
else
|
||||
type = SplitLeftType(tile);
|
||||
|
|
@ -1945,20 +1692,18 @@ CmdWire(
|
|||
case VALUES:
|
||||
if (locargc == 2)
|
||||
{
|
||||
char *wdisp;
|
||||
width = WireGetWidth();
|
||||
type = WireGetType();
|
||||
wdisp = DBWPrintValue(width, w, TRUE);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
lobj = Tcl_NewListObj(0, NULL);
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewStringObj(DBTypeLongNameTbl[type], -1));
|
||||
Tcl_NewIntObj(width));
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
||||
Tcl_NewStringObj(wdisp, -1));
|
||||
Tcl_NewStringObj(DBTypeLongNameTbl[type], -1));
|
||||
Tcl_SetObjResult(magicinterp, lobj);
|
||||
#else
|
||||
TxPrintf("Wire layer %s, width %s\n",
|
||||
DBTypeLongNameTbl[type], wdisp);
|
||||
TxPrintf("Wire layer %s, width %d\n",
|
||||
DBTypeLongNameTbl[type], width);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
|
@ -1983,14 +1728,12 @@ CmdWire(
|
|||
case WIDTH:
|
||||
if (locargc == 2)
|
||||
{
|
||||
char *wdisp;
|
||||
width = WireGetWidth();
|
||||
wdisp = DBWPrintValue(width, w, TRUE);
|
||||
#ifdef MAGIC_WRAPPER
|
||||
lobj = Tcl_NewStringObj(wdisp, -1);
|
||||
lobj = Tcl_NewIntObj(width);
|
||||
Tcl_SetObjResult(magicinterp, lobj);
|
||||
#else
|
||||
TxPrintf("Wire width is %s\n", wdisp);
|
||||
TxPrintf("Wire width is %d\n", width);
|
||||
#endif
|
||||
}
|
||||
else if (locargc != 3)
|
||||
|
|
|
|||
|
|
@ -211,8 +211,7 @@ CmdExtractTest(
|
|||
|
||||
int
|
||||
tileCountProc(
|
||||
Tile *tile, /* (unused) */
|
||||
TileType dinfo, /* (unused) */
|
||||
Tile *tile,
|
||||
int *tcount)
|
||||
{
|
||||
(*tcount)++;
|
||||
|
|
@ -801,13 +800,11 @@ cmdStatsCount(
|
|||
CellDef *def,
|
||||
struct countClient *cc)
|
||||
{
|
||||
int cmdStatsCountTile(Tile *tile, struct cellInfo *ci);
|
||||
int pNum;
|
||||
struct cellInfo *ci;
|
||||
TileType t;
|
||||
|
||||
/* Forward declaration */
|
||||
int cmdStatsCountTile(Tile *tile, TileType dinfo, struct cellInfo *ci);
|
||||
|
||||
if (def->cd_client)
|
||||
return (1);
|
||||
|
||||
|
|
@ -832,7 +829,6 @@ cmdStatsCount(
|
|||
int
|
||||
cmdStatsCountTile(
|
||||
Tile *tile,
|
||||
TileType dinfo, /* (unused) */
|
||||
struct cellInfo *ci)
|
||||
{
|
||||
TileType type = TiGetType(tile);
|
||||
|
|
@ -1103,18 +1099,17 @@ CmdTsearch(
|
|||
MagWindow *w,
|
||||
TxCommand *cmd)
|
||||
{
|
||||
int cmdTsrFunc(Tile *tp);
|
||||
char *RunStats(int flags, struct tms *lastt, struct tms *deltat);
|
||||
char *rstatp;
|
||||
static TileTypeBitMask mask;
|
||||
static struct tms tlast, tdelta;
|
||||
Rect rtool, rsearch;
|
||||
/**** Rect *ebox; ****/
|
||||
Plane *plane;
|
||||
int i, pNum, count;
|
||||
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)
|
||||
{
|
||||
TxError("Usage: tsearch plane count [mask [new|mayo]]\n");
|
||||
|
|
@ -1214,9 +1209,7 @@ CmdTsearch(
|
|||
|
||||
int
|
||||
cmdTsrFunc(
|
||||
Tile *tp,
|
||||
TileType dinfo, /* (unused) */
|
||||
ClientData clientdata) /* (unused) */
|
||||
Tile *tp)
|
||||
{
|
||||
if (cmdTsearchDebug)
|
||||
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 CmdInit(void);
|
||||
|
||||
extern void CmdDoProperty(CellDef *def, MagWindow *w, TxCommand *cmd, int argstart);
|
||||
extern void CmdDoProperty(CellDef *def, TxCommand *cmd, int argstart);
|
||||
extern void CmdPaintEraseButton(MagWindow *w, Point *refPoint, bool isPaint, bool isScreen);
|
||||
|
||||
#endif /* _MAGIC__COMMANDS__COMMANDS_H */
|
||||
|
|
|
|||
|
|
@ -37,8 +37,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "windows/windows.h"
|
||||
#include "dbwind/dbwind.h"
|
||||
#include "commands/commands.h"
|
||||
|
||||
/* C99 compat */
|
||||
#include "graphics/graphics.h"
|
||||
#include "cif/CIFint.h"
|
||||
|
||||
/*
|
||||
* The following variable points to the tables currently used for
|
||||
|
|
@ -356,43 +357,9 @@ DBCellCheckCopyAllPaint(scx, mask, xMask, targetUse, func)
|
|||
struct propUseDefStruct {
|
||||
CellDef *puds_source;
|
||||
CellDef *puds_dest;
|
||||
Plane *puds_plane; /* Mask hint plane in 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;
|
||||
}
|
||||
|
||||
/*
|
||||
*-----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -413,52 +380,63 @@ dbCopyMaskHintPlaneFunc(Tile *tile,
|
|||
*/
|
||||
|
||||
int
|
||||
dbCopyMaskHintsFunc(key, proprec, puds)
|
||||
dbCopyMaskHintsFunc(key, value, puds)
|
||||
char *key;
|
||||
PropertyRecord *proprec;
|
||||
ClientData value;
|
||||
struct propUseDefStruct *puds;
|
||||
{
|
||||
CellDef *dest = puds->puds_dest;
|
||||
Transform *trans = puds->puds_trans;
|
||||
Rect *clip = puds->puds_area;
|
||||
PropertyRecord *parentproprec, *newproprec;
|
||||
char *propstr = (char *)value;
|
||||
char *parentprop, *newvalue, *vptr;
|
||||
Rect r, rnew;
|
||||
bool propfound;
|
||||
int i, j;
|
||||
|
||||
if (!strncmp(key, "MASKHINTS_", 10))
|
||||
{
|
||||
char *vptr, *lastval;
|
||||
int lastlen;
|
||||
Plane *plane;
|
||||
|
||||
ASSERT(proprec->prop_type == PROPERTY_TYPE_PLANE, "dbCopyMaskHintsFunc");
|
||||
/* Append to existing mask hint (if any) */
|
||||
parentprop = (char *)DBPropGet(dest, key, &propfound);
|
||||
newvalue = (propfound) ? StrDup((char **)NULL, parentprop) : (char *)NULL;
|
||||
|
||||
/* Get the existing mask hint plane in the parent cell, and
|
||||
* create it if it does not already exist.
|
||||
*/
|
||||
parentproprec = (PropertyRecord *)DBPropGet(dest, key, &propfound);
|
||||
|
||||
if (propfound)
|
||||
plane = parentproprec->prop_value.prop_plane;
|
||||
else
|
||||
vptr = propstr;
|
||||
while (*vptr != '\0')
|
||||
{
|
||||
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
||||
newproprec->prop_type = PROPERTY_TYPE_PLANE;
|
||||
newproprec->prop_len = 0;
|
||||
plane = DBNewPlane((ClientData)TT_SPACE);
|
||||
newproprec->prop_value.prop_plane = plane;
|
||||
DBPropPut(dest, key, newproprec);
|
||||
}
|
||||
puds->puds_plane = plane;
|
||||
if (sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||
&r.r_xtop, &r.r_ytop) == 4)
|
||||
{
|
||||
GeoTransRect(trans, &r, &rnew);
|
||||
|
||||
/* Copy the properties from child to parent */
|
||||
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
||||
proprec->prop_value.prop_plane,
|
||||
clip, &CIFSolidBits, dbCopyMaskHintPlaneFunc,
|
||||
(ClientData)puds);
|
||||
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) ? " " : "",
|
||||
rnew.r_xbot, rnew.r_ybot, rnew.r_xtop, rnew.r_ytop);
|
||||
if (lastval) freeMagic(lastval);
|
||||
|
||||
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(dest, key, newvalue);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -490,7 +468,6 @@ DBCellCopyMaskHints(child, parent, transform)
|
|||
puds.puds_source = child->cu_def;
|
||||
puds.puds_dest = parent;
|
||||
puds.puds_trans = transform;
|
||||
puds.puds_area = (Rect *)&TiPlaneRect;
|
||||
DBPropEnum(child->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
|
||||
}
|
||||
|
||||
|
|
@ -524,7 +501,6 @@ dbFlatCopyMaskHintsFunc(scx, def)
|
|||
puds.puds_source = scx->scx_use->cu_def;
|
||||
puds.puds_dest = def;
|
||||
puds.puds_trans = &scx->scx_trans;
|
||||
puds.puds_area = &scx->scx_area;
|
||||
|
||||
DBPropEnum(use->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
|
||||
|
||||
|
|
@ -991,15 +967,14 @@ DBCellGenerateSimpleSubstrate(scx, subType, notSubMask, targetDef)
|
|||
*/
|
||||
|
||||
int
|
||||
dbEraseSubFunc(tile, dinfo, cxp)
|
||||
dbEraseSubFunc(tile, cxp)
|
||||
Tile *tile; /* Pointer to source tile with shield type */
|
||||
TileType dinfo; /* Split tile information */
|
||||
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
||||
{
|
||||
SearchContext *scx;
|
||||
Rect sourceRect, targetRect;
|
||||
int pNum;
|
||||
TileType newdinfo, loctype, subType;
|
||||
TileType dinfo, loctype, subType;
|
||||
Plane *plane;
|
||||
struct dbCopySubData *csd; /* Client data */
|
||||
|
||||
|
|
@ -1008,14 +983,13 @@ dbEraseSubFunc(tile, dinfo, cxp)
|
|||
plane = csd->csd_plane;
|
||||
pNum = csd->csd_pNum;
|
||||
subType = csd->csd_subtype;
|
||||
dinfo = TiGetTypeExact(tile);
|
||||
if (IsSplit(tile))
|
||||
{
|
||||
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
if (loctype == TT_SPACE) return 0;
|
||||
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, &scx->scx_trans);
|
||||
dinfo = DBTransformDiagonal(dinfo, &scx->scx_trans);
|
||||
}
|
||||
else
|
||||
newdinfo = (TileType)0;
|
||||
|
||||
/* Construct the rect for the tile */
|
||||
TITORECT(tile, &sourceRect);
|
||||
|
|
@ -1025,7 +999,7 @@ dbEraseSubFunc(tile, dinfo, cxp)
|
|||
|
||||
csd->csd_modified = TRUE;
|
||||
|
||||
return DBNMPaintPlane(plane, newdinfo, &targetRect, DBStdEraseTbl(subType, pNum),
|
||||
return DBNMPaintPlane(plane, dinfo, &targetRect, DBStdEraseTbl(subType, pNum),
|
||||
(PaintUndoInfo *)NULL);
|
||||
}
|
||||
|
||||
|
|
@ -1037,15 +1011,14 @@ dbEraseSubFunc(tile, dinfo, cxp)
|
|||
*/
|
||||
|
||||
int
|
||||
dbPaintSubFunc(tile, dinfo, cxp)
|
||||
dbPaintSubFunc(tile, cxp)
|
||||
Tile *tile; /* Pointer to source tile with shield type */
|
||||
TileType dinfo; /* Split tile information */
|
||||
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
||||
{
|
||||
SearchContext *scx;
|
||||
Rect sourceRect, targetRect;
|
||||
int pNum;
|
||||
TileType newdinfo, loctype, subType;
|
||||
TileType dinfo, loctype, subType;
|
||||
Plane *plane;
|
||||
struct dbCopySubData *csd; /* Client data */
|
||||
|
||||
|
|
@ -1054,14 +1027,13 @@ dbPaintSubFunc(tile, dinfo, cxp)
|
|||
plane = csd->csd_plane;
|
||||
pNum = csd->csd_pNum;
|
||||
subType = csd->csd_subtype;
|
||||
dinfo = TiGetTypeExact(tile);
|
||||
if (IsSplit(tile))
|
||||
{
|
||||
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
if (loctype == TT_SPACE) return 0;
|
||||
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, &scx->scx_trans);
|
||||
dinfo = DBTransformDiagonal(dinfo, &scx->scx_trans);
|
||||
}
|
||||
else
|
||||
newdinfo = (TileType)0;
|
||||
|
||||
/* Construct the rect for the tile */
|
||||
TITORECT(tile, &sourceRect);
|
||||
|
|
@ -1071,7 +1043,7 @@ dbPaintSubFunc(tile, dinfo, cxp)
|
|||
|
||||
csd->csd_modified = TRUE;
|
||||
|
||||
return DBNMPaintPlane(plane, newdinfo, &targetRect, DBStdPaintTbl(subType, pNum),
|
||||
return DBNMPaintPlane(plane, dinfo, &targetRect, DBStdPaintTbl(subType, pNum),
|
||||
(PaintUndoInfo *)NULL);
|
||||
}
|
||||
|
||||
|
|
@ -1084,15 +1056,14 @@ dbPaintSubFunc(tile, dinfo, cxp)
|
|||
*/
|
||||
|
||||
int
|
||||
dbEraseNonSub(tile, dinfo, cxp)
|
||||
dbEraseNonSub(tile, cxp)
|
||||
Tile *tile; /* Pointer to tile to erase from target */
|
||||
TileType dinfo; /* Split tile information */
|
||||
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
||||
{
|
||||
SearchContext *scx;
|
||||
Rect sourceRect, targetRect;
|
||||
Plane *plane; /* Plane of target data */
|
||||
TileType newdinfo, loctype, subType;
|
||||
TileType dinfo, loctype, subType;
|
||||
struct dbCopySubData *csd;
|
||||
int pNum;
|
||||
|
||||
|
|
@ -1103,14 +1074,13 @@ dbEraseNonSub(tile, dinfo, cxp)
|
|||
|
||||
scx = cxp->tc_scx;
|
||||
|
||||
dinfo = TiGetTypeExact(tile);
|
||||
if (IsSplit(tile))
|
||||
{
|
||||
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
if (loctype == TT_SPACE) return 0;
|
||||
newdinfo = DBTransformDiagonal(TiGetTypeExact(tile) | dinfo, &scx->scx_trans);
|
||||
dinfo = DBTransformDiagonal(dinfo, &scx->scx_trans);
|
||||
}
|
||||
else
|
||||
newdinfo = (TileType)0;
|
||||
|
||||
/* Construct the rect for the tile */
|
||||
TITORECT(tile, &sourceRect);
|
||||
|
|
@ -1119,7 +1089,7 @@ dbEraseNonSub(tile, dinfo, cxp)
|
|||
GEOTRANSRECT(&scx->scx_trans, &sourceRect, &targetRect);
|
||||
|
||||
/* Erase the substrate type from the area of this tile in the target plane. */
|
||||
return DBNMPaintPlane(plane, newdinfo, &targetRect, DBStdEraseTbl(subType, pNum),
|
||||
return DBNMPaintPlane(plane, dinfo, &targetRect, DBStdEraseTbl(subType, pNum),
|
||||
(PaintUndoInfo *)NULL);
|
||||
}
|
||||
|
||||
|
|
@ -1131,9 +1101,8 @@ dbEraseNonSub(tile, dinfo, cxp)
|
|||
*/
|
||||
|
||||
int
|
||||
dbCopySubFunc(tile, dinfo, csd)
|
||||
dbCopySubFunc(tile, csd)
|
||||
Tile *tile; /* Pointer to tile to erase from target */
|
||||
TileType dinfo; /* Split tile information */
|
||||
struct dbCopySubData *csd; /* Client data */
|
||||
{
|
||||
Rect rect;
|
||||
|
|
@ -1143,10 +1112,10 @@ dbCopySubFunc(tile, dinfo, csd)
|
|||
|
||||
plane = csd->csd_plane;
|
||||
pNum = csd->csd_pNum;
|
||||
type = TiGetTypeExact(tile) | dinfo;
|
||||
type = TiGetTypeExact(tile);
|
||||
if (IsSplit(tile))
|
||||
{
|
||||
loctype = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
if (loctype == TT_SPACE) return 0;
|
||||
}
|
||||
else
|
||||
|
|
@ -1467,9 +1436,8 @@ DBCellCopyLabels(scx, mask, xMask, targetUse, pArea)
|
|||
***/
|
||||
|
||||
int
|
||||
dbCopyManhattanPaint(tile, dinfo, cxp)
|
||||
Tile *tile; /* Pointer to tile to copy */
|
||||
TileType dinfo; /* Split tile information */
|
||||
dbCopyManhattanPaint(tile, cxp)
|
||||
Tile *tile; /* Pointer to tile to copy */
|
||||
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
||||
{
|
||||
SearchContext *scx = cxp->tc_scx;
|
||||
|
|
@ -1515,9 +1483,8 @@ dbCopyManhattanPaint(tile, dinfo, cxp)
|
|||
***/
|
||||
|
||||
int
|
||||
dbCopyAllPaint(tile, dinfo, cxp)
|
||||
Tile *tile; /* Pointer to tile to copy */
|
||||
TileType dinfo; /* Split tile information */
|
||||
dbCopyAllPaint(tile, cxp)
|
||||
Tile *tile; /* Pointer to tile to copy */
|
||||
TreeContext *cxp; /* Context from DBTreeSrTiles */
|
||||
{
|
||||
SearchContext *scx = cxp->tc_scx;
|
||||
|
|
@ -1525,7 +1492,7 @@ dbCopyAllPaint(tile, dinfo, cxp)
|
|||
Rect sourceRect, targetRect;
|
||||
PaintUndoInfo ui;
|
||||
CellDef *def;
|
||||
TileType type = TiGetTypeExact(tile) | dinfo;
|
||||
TileType type = TiGetTypeExact(tile);
|
||||
int pNum = cxp->tc_plane;
|
||||
int result;
|
||||
TileTypeBitMask *typeMask;
|
||||
|
|
@ -1538,13 +1505,13 @@ dbCopyAllPaint(tile, dinfo, cxp)
|
|||
*/
|
||||
|
||||
bool splittile = FALSE;
|
||||
TileType newdinfo = 0;
|
||||
TileType dinfo = 0;
|
||||
|
||||
if (IsSplit(tile))
|
||||
{
|
||||
splittile = TRUE;
|
||||
newdinfo = DBTransformDiagonal(type, &scx->scx_trans);
|
||||
type = (dinfo & TT_SIDE) ? SplitRightType(tile) :
|
||||
dinfo = DBTransformDiagonal(type, &scx->scx_trans);
|
||||
type = (SplitSide(tile)) ? SplitRightType(tile) :
|
||||
SplitLeftType(tile);
|
||||
}
|
||||
|
||||
|
|
@ -1604,7 +1571,7 @@ dbCopyAllPaint(tile, dinfo, cxp)
|
|||
Rect rrect, orect;
|
||||
int np, i, j;
|
||||
|
||||
GrClipTriangle(&targetRect, &arg->caa_rect, TRUE, newdinfo, points, &np);
|
||||
GrClipTriangle(&targetRect, &arg->caa_rect, TRUE, dinfo, points, &np);
|
||||
|
||||
if (np == 0)
|
||||
return(0);
|
||||
|
|
@ -1633,7 +1600,7 @@ dbCopyAllPaint(tile, dinfo, cxp)
|
|||
rrect.r_ybot = points[0].p_y;
|
||||
rrect.r_ytop = points[2].p_y;
|
||||
GeoCanonicalRect(&rrect, &targetRect);
|
||||
newdinfo = 0;
|
||||
dinfo = 0;
|
||||
}
|
||||
else if (np >= 4) /* Process extra rectangles in the area */
|
||||
{
|
||||
|
|
@ -1690,7 +1657,7 @@ topbottom:
|
|||
|
||||
splitdone:
|
||||
|
||||
result = (*dbCurPaintPlane)(def, pNum, newdinfo | type, &targetRect, &ui);
|
||||
result = (*dbCurPaintPlane)(def, pNum, dinfo | type, &targetRect, &ui);
|
||||
if ((result != 0) && (arg->caa_func != NULL))
|
||||
{
|
||||
/* result == 1 used exclusively for DRC off-grid error flagging */
|
||||
|
|
|
|||
|
|
@ -152,9 +152,10 @@ DBCellRename(cellname, newname, doforce)
|
|||
|
||||
if (doforce && ((celldef->cd_flags & CDVENDORGDS) == CDVENDORGDS))
|
||||
{
|
||||
char *chkgdsfile;
|
||||
bool isReadOnly;
|
||||
|
||||
DBPropGet(celldef, "GDS_FILE", &isReadOnly);
|
||||
chkgdsfile = (char *)DBPropGet(celldef, "GDS_FILE", &isReadOnly);
|
||||
/* Note that clearing GDS_FILE will also clear CDVENDORGDS flag */
|
||||
if (isReadOnly) DBPropPut(celldef, "GDS_FILE", NULL);
|
||||
|
||||
|
|
@ -1619,9 +1620,7 @@ dbAbutmentUseFunc(selUse, use, transform, data)
|
|||
{
|
||||
Rect bbox, refbox;
|
||||
Transform *trans;
|
||||
PropertyRecord *proprec;
|
||||
char *propvalue;
|
||||
char *refllx, *reflly, *refurx, *refury;
|
||||
bool found;
|
||||
bool *dolist = (bool *)data;
|
||||
|
||||
|
|
@ -1643,47 +1642,32 @@ dbAbutmentUseFunc(selUse, use, transform, data)
|
|||
}
|
||||
|
||||
trans = &use->cu_transform;
|
||||
proprec = DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
||||
propvalue = (char *)DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
||||
if (!found)
|
||||
bbox = use->cu_def->cd_bbox;
|
||||
else
|
||||
{
|
||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
||||
(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");
|
||||
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||
&bbox.r_xtop, &bbox.r_ytop) != 4)
|
||||
bbox = use->cu_def->cd_bbox;
|
||||
}
|
||||
}
|
||||
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
|
||||
if (*dolist)
|
||||
{
|
||||
pobj = Tcl_NewListObj(0, NULL);
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(refllx, -1));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(reflly, -1));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(refurx, -1));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewStringObj(refury, -1));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_xbot));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_ybot));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_xtop));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(refbox.r_ytop));
|
||||
Tcl_SetObjResult(magicinterp, pobj);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
TxPrintf("Abutment box: %s %s %s %s\n", refllx, reflly, refurx, refury);
|
||||
TxPrintf("Abutment box: %d %d %d %d\n", refbox.r_xbot, refbox.r_ybot,
|
||||
refbox.r_xtop, refbox.r_ytop);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -120,7 +120,6 @@ DBSrCellPlaneArea(BPlane *plane, const Rect *rect, int (*func)(), ClientData arg
|
|||
* int
|
||||
* func(tile, cxp)
|
||||
* Tile *tile;
|
||||
* TileType dinfo;
|
||||
* TreeContext *cxp;
|
||||
* {
|
||||
* }
|
||||
|
|
@ -417,7 +416,6 @@ dbCellUniqueTileSrFunc(scx, fp)
|
|||
* int
|
||||
* func(tile, cxp)
|
||||
* Tile *tile;
|
||||
* TileType dinfo;
|
||||
* TreeContext *cxp;
|
||||
* {
|
||||
* }
|
||||
|
|
@ -588,25 +586,6 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
|
|||
if (!DBCellRead(def, TRUE, TRUE, NULL))
|
||||
return 0;
|
||||
|
||||
if (flags & TF_LABEL_REVERSE_SEARCH)
|
||||
{
|
||||
/* Search children first */
|
||||
filter.tf_func = func;
|
||||
filter.tf_arg = cdarg;
|
||||
filter.tf_mask = mask;
|
||||
filter.tf_xmask = xMask;
|
||||
filter.tf_tpath = tpath;
|
||||
filter.tf_flags = flags;
|
||||
|
||||
scx2 = *scx;
|
||||
if (scx2.scx_area.r_xbot > TiPlaneRect.r_xbot) scx2.scx_area.r_xbot -= 1;
|
||||
if (scx2.scx_area.r_ybot > TiPlaneRect.r_ybot) scx2.scx_area.r_ybot -= 1;
|
||||
if (scx2.scx_area.r_xtop < TiPlaneRect.r_xtop) scx2.scx_area.r_xtop += 1;
|
||||
if (scx2.scx_area.r_ytop < TiPlaneRect.r_ytop) scx2.scx_area.r_ytop += 1;
|
||||
if (DBCellSrArea(&scx2, dbCellLabelSrFunc, (ClientData) &filter))
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (lab = def->cd_labels; lab; lab = lab->lab_next)
|
||||
{
|
||||
if (SigInterruptPending) break;
|
||||
|
|
@ -659,8 +638,6 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
|
|||
return (1);
|
||||
}
|
||||
|
||||
if (flags & TF_LABEL_REVERSE_SEARCH) return 0; /* children already searched */
|
||||
|
||||
filter.tf_func = func;
|
||||
filter.tf_arg = cdarg;
|
||||
filter.tf_mask = mask;
|
||||
|
|
@ -732,16 +709,6 @@ dbCellLabelSrFunc(scx, fp)
|
|||
}
|
||||
}
|
||||
|
||||
/* If fp->tf_flags has TF_LABEL_REVERSE_SEARCH, then search child
|
||||
* uses first, then the parent. This is for display, so that if
|
||||
* a child cell and parent cell have overlapping labels, the parent
|
||||
* label is the one on top.
|
||||
*/
|
||||
|
||||
if (fp->tf_flags & TF_LABEL_REVERSE_SEARCH)
|
||||
if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp))
|
||||
result = 1;
|
||||
|
||||
/* Apply the function first to any of the labels in this def. */
|
||||
|
||||
result = 0;
|
||||
|
|
@ -763,11 +730,9 @@ dbCellLabelSrFunc(scx, fp)
|
|||
}
|
||||
}
|
||||
|
||||
/* Now visit each child use recursively, if not doing a reverse search */
|
||||
|
||||
if (!(fp->tf_flags & TF_LABEL_REVERSE_SEARCH))
|
||||
if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp))
|
||||
result = 1;
|
||||
/* Now visit each child use recursively */
|
||||
if (DBCellSrArea(scx, dbCellLabelSrFunc, (ClientData) fp))
|
||||
result = 1;
|
||||
|
||||
cleanup:
|
||||
/* Remove the trailing pathname component from the TerminalPath */
|
||||
|
|
@ -949,9 +914,8 @@ DBSeeTypesAll(rootUse, rootRect, xMask, mask)
|
|||
*/
|
||||
|
||||
int
|
||||
dbSeeTypesAllSrFunc(tile, dinfo, cxp)
|
||||
dbSeeTypesAllSrFunc(tile, cxp)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
TreeContext *cxp;
|
||||
{
|
||||
Rect tileRect;
|
||||
|
|
@ -962,7 +926,7 @@ dbSeeTypesAllSrFunc(tile, dinfo, cxp)
|
|||
if (GEO_OVERLAP((&tileRect), area))
|
||||
{
|
||||
if (IsSplit(tile))
|
||||
TTMaskSetType(mask, (dinfo & TT_SIDE) ?
|
||||
TTMaskSetType(mask, SplitSide(tile) ?
|
||||
SplitRightType(tile) : SplitLeftType(tile));
|
||||
else
|
||||
TTMaskSetType(mask, TiGetType(tile));
|
||||
|
|
@ -1643,9 +1607,8 @@ dbScalePlane(oldplane, newplane, pnum, scalen, scaled, doCIF)
|
|||
*/
|
||||
|
||||
int
|
||||
dbTileScaleFunc(tile, dinfo, scvals)
|
||||
dbTileScaleFunc(tile, scvals)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
struct scaleArg *scvals;
|
||||
{
|
||||
TileType type;
|
||||
|
|
@ -1668,10 +1631,10 @@ dbTileScaleFunc(tile, dinfo, scvals)
|
|||
return 0;
|
||||
}
|
||||
|
||||
type = TiGetTypeExact(tile) | dinfo;
|
||||
type = TiGetTypeExact(tile);
|
||||
exact = type;
|
||||
if (IsSplit(tile))
|
||||
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
DBNMPaintPlane(scvals->ptarget, exact, &targetRect,
|
||||
(
|
||||
#ifdef CIF_MODULE
|
||||
|
|
@ -1726,9 +1689,8 @@ dbMovePlane(oldplane, newplane, pnum, origx, origy)
|
|||
*/
|
||||
|
||||
int
|
||||
dbTileMoveFunc(tile, dinfo, mvvals)
|
||||
dbTileMoveFunc(tile, mvvals)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
struct moveArg *mvvals;
|
||||
{
|
||||
TileType type;
|
||||
|
|
@ -1741,12 +1703,12 @@ dbTileMoveFunc(tile, dinfo, mvvals)
|
|||
DBMovePoint(&targetRect.r_ll, mvvals->origx, mvvals->origy);
|
||||
DBMovePoint(&targetRect.r_ur, mvvals->origx, mvvals->origy);
|
||||
|
||||
type = TiGetTypeExact(tile) | dinfo;
|
||||
type = TiGetTypeExact(tile);
|
||||
exact = type;
|
||||
if (IsSplit(tile))
|
||||
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
DBNMPaintPlane(mvvals->ptarget, exact, &targetRect,
|
||||
(mvvals->pnum < 0) ? CIFPaintTable : DBStdPaintTbl(type, mvvals->pnum),
|
||||
DBStdPaintTbl(type, mvvals->pnum),
|
||||
(PaintUndoInfo *)NULL);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1839,48 +1801,84 @@ typedef struct _cellpropstruct {
|
|||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int dbScaleProp(name, proprec, cps)
|
||||
int dbScaleProp(name, value, cps)
|
||||
char *name;
|
||||
PropertyRecord *proprec;
|
||||
char *value;
|
||||
CellPropStruct *cps;
|
||||
{
|
||||
int i, scalen, scaled;
|
||||
Point p;
|
||||
int scalen, scaled;
|
||||
char *newvalue, *vptr;
|
||||
Rect r;
|
||||
|
||||
/* Only "dimension" and "plane" type properties get scaled */
|
||||
|
||||
if (proprec->prop_type == PROPERTY_TYPE_PLANE)
|
||||
if ((strlen(name) > 5) && !strncmp(name + strlen(name) - 5, "_BBOX", 5))
|
||||
{
|
||||
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 (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||
&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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
|
||||
|
||||
/* 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;
|
||||
|
||||
for (i = 0; i < proprec->prop_len; i += 2)
|
||||
else if (!strncmp(name, "MASKHINTS_", 10))
|
||||
{
|
||||
if ((i + 1) >= proprec->prop_len) break;
|
||||
char *vptr, *lastval;
|
||||
int lastlen;
|
||||
|
||||
p.p_x = proprec->prop_value.prop_integer[i];
|
||||
p.p_y = proprec->prop_value.prop_integer[i + 1];
|
||||
DBScalePoint(&p, scalen, scaled);
|
||||
proprec->prop_value.prop_integer[i] = p.p_x;
|
||||
proprec->prop_value.prop_integer[i + 1] = p.p_y;
|
||||
newvalue = (char *)NULL;
|
||||
vptr = value;
|
||||
while (*vptr != '\0')
|
||||
{
|
||||
if (sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||
&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 */
|
||||
}
|
||||
|
||||
|
|
@ -1896,47 +1894,33 @@ int dbScaleProp(name, proprec, cps)
|
|||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int dbMoveProp(name, proprec, cps)
|
||||
int dbMoveProp(name, value, cps)
|
||||
char *name;
|
||||
PropertyRecord *proprec;
|
||||
char *value;
|
||||
CellPropStruct *cps;
|
||||
{
|
||||
int i, origx, origy;
|
||||
int origx, origy;
|
||||
char *newvalue;
|
||||
Point p;
|
||||
Rect r;
|
||||
|
||||
/* Only "dimension" and "plane" type properties get scaled */
|
||||
|
||||
if (proprec->prop_type == PROPERTY_TYPE_PLANE)
|
||||
if (((strlen(name) > 5) && !strncmp(name + strlen(name) - 5, "_BBOX", 5))
|
||||
|| !strncmp(name, "MASKHINTS_", 10))
|
||||
{
|
||||
Plane *newplane;
|
||||
if (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||
&r.r_xtop, &r.r_ytop) == 4)
|
||||
{
|
||||
origx = cps->cps_point.p_x;
|
||||
origy = cps->cps_point.p_y;
|
||||
|
||||
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;
|
||||
DBMovePoint(&r.r_ll, origx, origy);
|
||||
DBMovePoint(&r.r_ur, origx, origy);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
|
||||
|
||||
origx = cps->cps_point.p_x;
|
||||
origy = cps->cps_point.p_y;
|
||||
|
||||
for (i = 0; i < proprec->prop_len; i += 2)
|
||||
{
|
||||
if ((i + 1) >= proprec->prop_len) break;
|
||||
|
||||
p.p_x = proprec->prop_value.prop_integer[i];
|
||||
p.p_y = proprec->prop_value.prop_integer[i + 1];
|
||||
DBMovePoint(&p, origx, origy);
|
||||
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 */
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -128,6 +128,85 @@ DBInvTransformDiagonal(oldtype, trans)
|
|||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -197,7 +276,7 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
|
|||
{
|
||||
struct conSrArg csa;
|
||||
int startPlane, result;
|
||||
TileAndDinfo start_tad; /* Starting tile and split information */
|
||||
Tile *startTile; /* Starting tile for search. */
|
||||
|
||||
result = 0;
|
||||
csa.csa_def = def;
|
||||
|
|
@ -208,18 +287,17 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
|
|||
* the tile address and returns.
|
||||
*/
|
||||
|
||||
start_tad.tad_tile = NULL;
|
||||
start_tad.tad_next = NULL; /* unused */
|
||||
startTile = NULL;
|
||||
for (startPlane = PL_TECHDEPBASE; startPlane < DBNumPlanes; startPlane++)
|
||||
{
|
||||
csa.csa_pNum = startPlane;
|
||||
if (DBSrPaintArea((Tile *) NULL,
|
||||
def->cd_planes[startPlane], startArea, mask,
|
||||
dbSrConnectStartFunc, PTR2CD(&start_tad)) != 0) break;
|
||||
dbSrConnectStartFunc, PTR2CD(&startTile)) != 0) break;
|
||||
}
|
||||
if (start_tad.tad_tile == NULL) return 0;
|
||||
if (startTile == NULL) return 0;
|
||||
/* The following lets us call DBSrConnect recursively */
|
||||
else if (start_tad.tad_tile->ti_client == (ClientData)1) return 0;
|
||||
else if (startTile->ti_client == (ClientData)1) return 0;
|
||||
|
||||
/* Pass 1. During this pass the client function gets called. */
|
||||
|
||||
|
|
@ -228,8 +306,7 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
|
|||
csa.csa_clientDefault = CLIENTDEFAULT;
|
||||
csa.csa_clear = FALSE;
|
||||
csa.csa_connect = connect;
|
||||
if (dbSrConnectFunc(start_tad.tad_tile, start_tad.tad_dinfo,
|
||||
PTR2CD(&csa)) != 0) result = 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.
|
||||
|
|
@ -238,7 +315,7 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
|
|||
SigDisableInterrupts();
|
||||
csa.csa_clientFunc = NULL;
|
||||
csa.csa_clear = TRUE;
|
||||
(void) dbSrConnectFunc(start_tad.tad_tile, start_tad.tad_dinfo, PTR2CD(&csa));
|
||||
(void) dbSrConnectFunc(startTile, PTR2CD(&csa));
|
||||
SigEnableInterrupts();
|
||||
|
||||
return result;
|
||||
|
|
@ -248,12 +325,11 @@ DBSrConnect(def, startArea, mask, connect, bounds, func, clientData)
|
|||
int
|
||||
dbSrConnectStartFunc(
|
||||
Tile *tile, /* This will be the starting tile. */
|
||||
TileType dinfo, /* (unused) */
|
||||
ClientData cdata) /* We store tile and split info here. */
|
||||
ClientData cdata) /* We store tile's address here. */
|
||||
/* (Tile **pTile) */
|
||||
{
|
||||
TileAndDinfo *tad = (TileAndDinfo *)CD2PTR(cdata);
|
||||
tad->tad_tile = tile;
|
||||
tad->tad_dinfo = dinfo;
|
||||
Tile **pTile = (Tile **)CD2PTR(cdata);
|
||||
*pTile = tile;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -291,7 +367,7 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
|
|||
{
|
||||
struct conSrArg csa;
|
||||
int startPlane, result;
|
||||
TileAndDinfo tad;
|
||||
Tile *startTile; /* Starting tile for search. */
|
||||
|
||||
result = 0;
|
||||
csa.csa_def = def;
|
||||
|
|
@ -302,18 +378,17 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
|
|||
* the tile address and returns.
|
||||
*/
|
||||
|
||||
tad.tad_tile = NULL;
|
||||
tad.tad_next = NULL; /* unused */
|
||||
startTile = NULL;
|
||||
for (startPlane = PL_TECHDEPBASE; startPlane < DBNumPlanes; startPlane++)
|
||||
{
|
||||
csa.csa_pNum = startPlane;
|
||||
if (DBSrPaintArea((Tile *) NULL,
|
||||
def->cd_planes[startPlane], startArea, mask,
|
||||
dbSrConnectStartFunc, PTR2CD(&tad)) != 0) break;
|
||||
dbSrConnectStartFunc, PTR2CD(&startTile)) != 0) break;
|
||||
}
|
||||
if (tad.tad_tile == NULL) return 0;
|
||||
if (startTile == NULL) return 0;
|
||||
/* The following lets us call DBSrConnect recursively */
|
||||
else if (tad.tad_tile->ti_client == (ClientData)1) return 0;
|
||||
else if (startTile->ti_client == (ClientData)1) return 0;
|
||||
|
||||
/* Pass 1. During this pass the client function gets called. */
|
||||
|
||||
|
|
@ -322,7 +397,7 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
|
|||
csa.csa_clientDefault = CLIENTDEFAULT;
|
||||
csa.csa_clear = FALSE;
|
||||
csa.csa_connect = connect;
|
||||
if (dbSrConnectFunc(tad.tad_tile, tad.tad_dinfo, PTR2CD(&csa)) != 0) result = 1;
|
||||
if (dbSrConnectFunc(startTile, PTR2CD(&csa)) != 0) result = 1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -345,15 +420,12 @@ DBSrConnectOnePass(def, startArea, mask, connect, bounds, func, clientData)
|
|||
*/
|
||||
|
||||
int
|
||||
dbcFindTileFunc(tile, dinfo, arg)
|
||||
dbcFindTileFunc(tile, arg)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
ClientData arg;
|
||||
{
|
||||
TileAndDinfo *tad = (TileAndDinfo *)arg;
|
||||
|
||||
tad->tad_tile = tile;
|
||||
tad->tad_dinfo = dinfo;
|
||||
Tile **tptr = (Tile **)arg;
|
||||
*tptr = tile;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -393,7 +465,6 @@ dbcFindTileFunc(tile, dinfo, arg)
|
|||
int
|
||||
dbSrConnectFunc(
|
||||
Tile *tile, /* Tile that is connected. */
|
||||
TileType dinfo, /* Split tile information */
|
||||
ClientData cdata) /* Contains information about the search. */
|
||||
/* (struct conSrArg *csa) */
|
||||
{
|
||||
|
|
@ -413,13 +484,11 @@ dbSrConnectFunc(
|
|||
/* Drop the first entry on the stack */
|
||||
pNum = csa->csa_pNum;
|
||||
STACKPUSH(INT2CD(tile), dbConnectStack);
|
||||
STACKPUSH(INT2CD(dinfo), dbConnectStack);
|
||||
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
||||
|
||||
while (!StackEmpty(dbConnectStack))
|
||||
{
|
||||
pNum = (int)CD2INT(STACKPOP(dbConnectStack));
|
||||
dinfo = (int)CD2INT(STACKPOP(dbConnectStack));
|
||||
tile = (Tile *)CD2INT(STACKPOP(dbConnectStack));
|
||||
if (result == 1) continue;
|
||||
|
||||
|
|
@ -453,7 +522,7 @@ dbSrConnectFunc(
|
|||
|
||||
if (callClient && (csa->csa_clientFunc != NULL))
|
||||
{
|
||||
if ((*csa->csa_clientFunc)(tile, dinfo, pNum, csa->csa_clientData) != 0)
|
||||
if ((*csa->csa_clientFunc)(tile, pNum, csa->csa_clientData) != 0)
|
||||
{
|
||||
result = 1;
|
||||
continue;
|
||||
|
|
@ -467,7 +536,7 @@ dbSrConnectFunc(
|
|||
|
||||
if (IsSplit(tile))
|
||||
{
|
||||
if (dinfo & TT_SIDE)
|
||||
if (SplitSide(tile))
|
||||
loctype = SplitRightType(tile);
|
||||
else
|
||||
loctype = SplitLeftType(tile);
|
||||
|
|
@ -478,7 +547,7 @@ dbSrConnectFunc(
|
|||
|
||||
/* Left side: */
|
||||
|
||||
if (IsSplit(tile) && (dinfo & TT_SIDE)) goto bottomside;
|
||||
if (IsSplit(tile) && SplitSide(tile)) goto bottomside;
|
||||
|
||||
for (t2 = BL(tile); BOTTOM(t2) < tileArea.r_ytop; t2 = RT(t2))
|
||||
{
|
||||
|
|
@ -495,11 +564,9 @@ dbSrConnectFunc(
|
|||
if (t2->ti_client == csa->csa_clientDefault) continue;
|
||||
}
|
||||
else if (t2->ti_client == (ClientData) 1) continue;
|
||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||
if (IsSplit(t2))
|
||||
STACKPUSH(INT2CD((TileType)TT_SIDE), dbConnectStack);
|
||||
else
|
||||
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) | TT_SIDE)); /* bit set */
|
||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
||||
}
|
||||
}
|
||||
|
|
@ -507,7 +574,7 @@ dbSrConnectFunc(
|
|||
/* Bottom side: */
|
||||
|
||||
bottomside:
|
||||
if (IsSplit(tile) && ((!((dinfo & TT_SIDE) ? 1 : 0)) ^ SplitDirection(tile)))
|
||||
if (IsSplit(tile) && (!(SplitSide(tile) ^ SplitDirection(tile))))
|
||||
goto rightside;
|
||||
|
||||
for (t2 = LB(tile); LEFT(t2) < tileArea.r_xtop; t2 = TR(t2))
|
||||
|
|
@ -525,17 +592,16 @@ bottomside:
|
|||
if (t2->ti_client == csa->csa_clientDefault) continue;
|
||||
}
|
||||
else if (t2->ti_client == (ClientData) 1) continue;
|
||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||
if (IsSplit(t2))
|
||||
{
|
||||
if (SplitDirection(t2))
|
||||
STACKPUSH(INT2CD((TileType)TT_SIDE), dbConnectStack);
|
||||
/* bit set */
|
||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) | TT_SIDE));
|
||||
else
|
||||
/* bit clear */
|
||||
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) & ~TT_SIDE));
|
||||
}
|
||||
else
|
||||
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
||||
}
|
||||
}
|
||||
|
|
@ -543,7 +609,7 @@ bottomside:
|
|||
/* Right side: */
|
||||
|
||||
rightside:
|
||||
if (IsSplit(tile) && !(dinfo & TT_SIDE)) goto topside;
|
||||
if (IsSplit(tile) && !SplitSide(tile)) goto topside;
|
||||
|
||||
for (t2 = TR(tile); ; t2 = LB(t2))
|
||||
{
|
||||
|
|
@ -560,8 +626,9 @@ rightside:
|
|||
if (t2->ti_client == csa->csa_clientDefault) 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(0), dbConnectStack);
|
||||
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
||||
}
|
||||
nextRight: if (BOTTOM(t2) <= tileArea.r_ybot) break;
|
||||
|
|
@ -570,8 +637,7 @@ rightside:
|
|||
/* Top side: */
|
||||
topside:
|
||||
|
||||
if (IsSplit(tile) && (((dinfo & TT_SIDE) ? 1 : 0) ^ SplitDirection(tile)))
|
||||
goto donesides;
|
||||
if (IsSplit(tile) && (SplitSide(tile) ^ SplitDirection(tile))) goto donesides;
|
||||
|
||||
for (t2 = RT(tile); ; t2 = BL(t2))
|
||||
{
|
||||
|
|
@ -588,18 +654,16 @@ topside:
|
|||
if (t2->ti_client == csa->csa_clientDefault) goto nextTop;
|
||||
}
|
||||
else if (t2->ti_client == (ClientData) 1) goto nextTop;
|
||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||
if (IsSplit(t2))
|
||||
{
|
||||
if (SplitDirection(t2))
|
||||
/* bit clear */
|
||||
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) & ~TT_SIDE));
|
||||
else
|
||||
/* bit set */
|
||||
STACKPUSH(INT2CD((TileType)TT_SIDE), dbConnectStack);
|
||||
TiSetBody(t2, INT2CD(CD2INT(t2->ti_body) | TT_SIDE));
|
||||
}
|
||||
else
|
||||
STACKPUSH(INT2CD(0), dbConnectStack);
|
||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||
STACKPUSH(INT2CD(pNum), dbConnectStack);
|
||||
}
|
||||
nextTop: if (LEFT(t2) <= tileArea.r_xbot) break;
|
||||
|
|
@ -618,7 +682,6 @@ donesides:
|
|||
{
|
||||
Rect newArea;
|
||||
GEO_EXPAND(&tileArea, 1, &newArea);
|
||||
TileAndDinfo tad;
|
||||
|
||||
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
|
||||
{
|
||||
|
|
@ -626,20 +689,18 @@ donesides:
|
|||
if (IsSplit(tile))
|
||||
{
|
||||
if (DBSrPaintNMArea((Tile *) NULL, csa->csa_def->cd_planes[i],
|
||||
TiGetTypeExact(tile) | dinfo, &newArea, connectMask,
|
||||
dbcFindTileFunc, (ClientData)&tad) != 0)
|
||||
TiGetTypeExact(tile), &newArea, connectMask,
|
||||
dbcFindTileFunc, (ClientData)&t2) != 0)
|
||||
{
|
||||
STACKPUSH(PTR2CD(tad.tad_tile), dbConnectStack);
|
||||
STACKPUSH(INT2CD(tad.tad_dinfo), dbConnectStack);
|
||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||
STACKPUSH(INT2CD(i), dbConnectStack);
|
||||
}
|
||||
}
|
||||
else if (DBSrPaintArea((Tile *) NULL, csa->csa_def->cd_planes[i],
|
||||
&newArea, connectMask, dbcFindTileFunc,
|
||||
(ClientData)&tad) != 0)
|
||||
(ClientData)&t2) != 0)
|
||||
{
|
||||
STACKPUSH(PTR2CD(tad.tad_tile), dbConnectStack);
|
||||
STACKPUSH(INT2CD(tad.tad_dinfo), dbConnectStack);
|
||||
STACKPUSH(INT2CD(t2), dbConnectStack);
|
||||
STACKPUSH(INT2CD(i), dbConnectStack);
|
||||
}
|
||||
}
|
||||
|
|
@ -673,10 +734,9 @@ donesides:
|
|||
/** @typedef cb_database_srpaintnmarea_t */
|
||||
/** @typedef cb_database_srpaintarea_t */
|
||||
int
|
||||
dbcUnconnectFunc(tile, dinfo, clientData)
|
||||
dbcUnconnectFunc(tile, clientData)
|
||||
Tile *tile; /* Current tile */
|
||||
TileType dinfo; /* Split tile information, unused */
|
||||
ClientData clientData; /* Unused. */
|
||||
ClientData clientData; /* Unused. */
|
||||
|
||||
{
|
||||
return 1;
|
||||
|
|
@ -889,9 +949,8 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
|
|||
*/
|
||||
|
||||
int
|
||||
dbcConnectFunc(tile, dinfo, cx)
|
||||
dbcConnectFunc(tile, cx)
|
||||
Tile *tile; /* Tile found. */
|
||||
TileType dinfo; /* Split tile information */
|
||||
TreeContext *cx; /* Describes context of search. The client
|
||||
* data is a pointer to a conSrArg2 record
|
||||
* containing various required information.
|
||||
|
|
@ -904,8 +963,8 @@ dbcConnectFunc(tile, dinfo, cx)
|
|||
Rect *srArea;
|
||||
SearchContext *scx = cx->tc_scx;
|
||||
SearchContext scx2;
|
||||
TileType loctype = TiGetTypeExact(tile) | dinfo;
|
||||
TileType newdinfo = 0;
|
||||
TileType loctype = TiGetTypeExact(tile);
|
||||
TileType dinfo = 0;
|
||||
int retval, i, pNum = cx->tc_plane;
|
||||
CellDef *def;
|
||||
|
||||
|
|
@ -937,8 +996,8 @@ dbcConnectFunc(tile, dinfo, cx)
|
|||
|
||||
if (IsSplit(tile))
|
||||
{
|
||||
newdinfo = DBTransformDiagonal(loctype, &scx->scx_trans);
|
||||
loctype = ((dinfo & TT_SIDE)) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
dinfo = DBTransformDiagonal(loctype, &scx->scx_trans);
|
||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
}
|
||||
|
||||
/* See if the destination cell contains stuff over the whole
|
||||
|
|
@ -976,7 +1035,7 @@ dbcConnectFunc(tile, dinfo, cx)
|
|||
def = csa2->csa2_use->cu_def;
|
||||
retval = 1;
|
||||
if (DBSrPaintNMArea((Tile *) NULL, def->cd_planes[pNum],
|
||||
newdinfo, &newarea, ¬ConnectMask, dbcUnconnectFunc,
|
||||
dinfo, &newarea, ¬ConnectMask, dbcUnconnectFunc,
|
||||
(ClientData) NULL) == 0)
|
||||
retval = 0;
|
||||
|
||||
|
|
@ -985,7 +1044,7 @@ dbcConnectFunc(tile, dinfo, cx)
|
|||
* the storage for the current list element.
|
||||
*/
|
||||
|
||||
DBNMPaintPlane(def->cd_planes[pNum], newdinfo,
|
||||
DBNMPaintPlane(def->cd_planes[pNum], dinfo,
|
||||
&newarea, DBStdPaintTbl(loctype, pNum),
|
||||
(PaintUndoInfo *) NULL);
|
||||
|
||||
|
|
@ -1002,14 +1061,14 @@ dbcConnectFunc(tile, dinfo, cx)
|
|||
|
||||
/* Only extend those sides bordering the diagonal tile */
|
||||
|
||||
if (newdinfo & TT_DIAGONAL)
|
||||
if (dinfo & TT_DIAGONAL)
|
||||
{
|
||||
if (newdinfo & TT_SIDE) /* right */
|
||||
if (dinfo & TT_SIDE) /* right */
|
||||
newarea.r_xtop += 1;
|
||||
else /* left */
|
||||
newarea.r_xbot -= 1;
|
||||
if (((newdinfo & TT_SIDE) >> 1)
|
||||
== (newdinfo & TT_DIRECTION)) /* top */
|
||||
if (((dinfo & TT_SIDE) >> 1)
|
||||
== (dinfo & TT_DIRECTION)) /* top */
|
||||
newarea.r_ytop += 1;
|
||||
else /* bottom */
|
||||
newarea.r_ybot -= 1;
|
||||
|
|
@ -1049,7 +1108,7 @@ dbcConnectFunc(tile, dinfo, cx)
|
|||
|
||||
csa2->csa2_list[csa2->csa2_top].area = newarea;
|
||||
csa2->csa2_list[csa2->csa2_top].connectMask = connectMask;
|
||||
csa2->csa2_list[csa2->csa2_top].dinfo = newdinfo;
|
||||
csa2->csa2_list[csa2->csa2_top].dinfo = dinfo;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ struct expandArg
|
|||
{
|
||||
bool ea_deref; /* TRUE if root def dereference flag is set */
|
||||
int ea_xmask; /* Expand mask. */
|
||||
int ea_type; /* Expand, unexpand, or toggle */
|
||||
int (*ea_func)(); /* Function to call for each cell whose
|
||||
* status is changed.
|
||||
*/
|
||||
|
|
@ -68,22 +67,15 @@ struct expandArg
|
|||
*/
|
||||
|
||||
void
|
||||
DBExpand(cellUse, expandMask, expandType)
|
||||
DBExpand(cellUse, expandMask, expandFlag)
|
||||
CellUse *cellUse;
|
||||
int expandMask;
|
||||
int expandType;
|
||||
bool expandFlag;
|
||||
{
|
||||
CellDef *def;
|
||||
bool expandFlag, expandTest;
|
||||
|
||||
expandTest = DBDescendSubcell(cellUse, expandMask);
|
||||
if ((expandType & DB_EXPAND_MASK) == DB_EXPAND_TOGGLE)
|
||||
expandFlag = expandTest;
|
||||
else
|
||||
{
|
||||
expandFlag = ((expandType & DB_EXPAND_MASK) == DB_EXPAND) ? TRUE : FALSE;
|
||||
if (expandFlag == expandTest) return;
|
||||
}
|
||||
|
||||
if (DBDescendSubcell(cellUse, expandMask) == expandFlag)
|
||||
return;
|
||||
|
||||
if (expandFlag)
|
||||
{
|
||||
|
|
@ -138,17 +130,17 @@ DBExpand(cellUse, expandMask, expandType)
|
|||
*/
|
||||
|
||||
void
|
||||
DBExpandAll(rootUse, rootRect, expandMask, expandType, func, cdarg)
|
||||
DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg)
|
||||
CellUse *rootUse; /* Root cell use from which search begins */
|
||||
Rect *rootRect; /* Area to be expanded, in root coordinates */
|
||||
int expandMask; /* Window mask in which cell is to be expanded */
|
||||
int expandType; /* DB_EXPAND, DB_UNEXPAND, DB_EXPAND_TOGGLE */
|
||||
bool expandFlag; /* TRUE => expand, FALSE => unexpand */
|
||||
int (*func)(); /* Function to call for each cell whose expansion
|
||||
* status is modified. NULL means don't call anyone.
|
||||
*/
|
||||
ClientData cdarg; /* Argument to pass to func. */
|
||||
{
|
||||
int dbExpandFunc();
|
||||
int dbExpandFunc(), dbUnexpandFunc();
|
||||
SearchContext scontext;
|
||||
struct expandArg arg;
|
||||
|
||||
|
|
@ -156,26 +148,29 @@ DBExpandAll(rootUse, rootRect, expandMask, expandType, func, cdarg)
|
|||
(void) DBCellRead(rootUse->cu_def, TRUE, TRUE, NULL);
|
||||
|
||||
/*
|
||||
* Walk through the area and set the expansion state appropriately.
|
||||
* Walk through the area and set the expansion state
|
||||
* appropriately.
|
||||
*/
|
||||
|
||||
arg.ea_xmask = expandMask;
|
||||
arg.ea_func = func;
|
||||
arg.ea_arg = cdarg;
|
||||
arg.ea_type = expandType;
|
||||
arg.ea_deref = (rootUse->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
|
||||
|
||||
scontext.scx_use = rootUse;
|
||||
scontext.scx_trans = GeoIdentityTransform;
|
||||
scontext.scx_area = *rootRect;
|
||||
DBCellSrArea(&scontext, dbExpandFunc, (ClientData) &arg);
|
||||
if (expandFlag)
|
||||
DBCellSrArea(&scontext, dbExpandFunc, (ClientData) &arg);
|
||||
else
|
||||
DBCellSrArea(&scontext, dbUnexpandFunc, (ClientData) &arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* dbExpandFunc --
|
||||
*
|
||||
* Filter function called by DBCellSrArea on behalf of DBExpandAll above
|
||||
* when cells are being expanded, unexpanded, or toggled.
|
||||
* when cells are being expanded.
|
||||
*/
|
||||
|
||||
int
|
||||
|
|
@ -189,55 +184,68 @@ dbExpandFunc(scx, arg)
|
|||
{
|
||||
CellUse *childUse = scx->scx_use;
|
||||
int n = DBLambda[1];
|
||||
int expandTest;
|
||||
int expandType = (arg->ea_type & DB_EXPAND_MASK);
|
||||
int expandSurround = (arg->ea_type & DB_EXPAND_SURROUND_MASK);
|
||||
bool surround;
|
||||
|
||||
expandTest = DBDescendSubcell(childUse, arg->ea_xmask);
|
||||
|
||||
/*
|
||||
* Change the expansion status of this cell if necessary. Call the
|
||||
* client's function if the expansion status has changed.
|
||||
*/
|
||||
|
||||
if (!expandTest && ((expandType == DB_EXPAND) || (expandType == DB_EXPAND_TOGGLE)))
|
||||
if (!DBDescendSubcell(childUse, arg->ea_xmask))
|
||||
{
|
||||
surround = (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area)
|
||||
|| GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox));
|
||||
if (surround || (expandSurround == DB_EXPAND_OVERLAP))
|
||||
/* If the cell is unavailable, then don't expand it.
|
||||
*/
|
||||
if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0)
|
||||
{
|
||||
/* If the cell is unavailable, then don't expand it.
|
||||
*/
|
||||
if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0)
|
||||
/* If the parent is dereferenced, then the child should be, too */
|
||||
if (arg->ea_deref) childUse->cu_def->cd_flags |= CDDEREFERENCE;
|
||||
if(!DBCellRead(childUse->cu_def, TRUE, TRUE, NULL))
|
||||
{
|
||||
/* If the parent is dereferenced, then the child should be, too */
|
||||
if (arg->ea_deref) childUse->cu_def->cd_flags |= CDDEREFERENCE;
|
||||
if (!DBCellRead(childUse->cu_def, TRUE, TRUE, NULL))
|
||||
{
|
||||
TxError("Cell %s is unavailable. It could not be expanded.\n",
|
||||
childUse->cu_def->cd_name);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
childUse->cu_expandMask |= arg->ea_xmask;
|
||||
expandTest = TRUE;
|
||||
if (arg->ea_func != NULL)
|
||||
{
|
||||
if ((*arg->ea_func)(childUse, arg->ea_arg) != 0) return 1;
|
||||
TxError("Cell %s is unavailable. It could not be expanded.\n",
|
||||
childUse->cu_def->cd_name);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
childUse->cu_expandMask |= arg->ea_xmask;
|
||||
if (arg->ea_func != NULL)
|
||||
{
|
||||
if ((*arg->ea_func)(childUse, arg->ea_arg) != 0) return 1;
|
||||
}
|
||||
}
|
||||
else if (expandTest && ((expandType == DB_UNEXPAND) ||
|
||||
(expandType == DB_EXPAND_TOGGLE)))
|
||||
|
||||
if (DBCellSrArea(scx, dbExpandFunc, (ClientData) arg))
|
||||
return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* dbUnexpandFunc --
|
||||
*
|
||||
* Filter function called by DBCellSrArea on behalf of DBExpandAll above
|
||||
* when cells are being unexpanded.
|
||||
*/
|
||||
|
||||
int
|
||||
dbUnexpandFunc(scx, arg)
|
||||
SearchContext *scx; /* Pointer to search context containing
|
||||
* child use, search area in coor-
|
||||
* dinates of the child use, and
|
||||
* transform back to "root".
|
||||
*/
|
||||
struct expandArg *arg; /* Client data from caller */
|
||||
{
|
||||
CellUse *childUse = scx->scx_use;
|
||||
|
||||
/*
|
||||
* Change the expansion status of this cell if necessary.
|
||||
*/
|
||||
|
||||
if (DBDescendSubcell(childUse, arg->ea_xmask))
|
||||
{
|
||||
surround = (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area)
|
||||
|| GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox));
|
||||
if (surround || (expandSurround == DB_EXPAND_OVERLAP))
|
||||
if (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area)
|
||||
|| GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox))
|
||||
{
|
||||
childUse->cu_expandMask &= ~arg->ea_xmask;
|
||||
expandTest = FALSE;
|
||||
|
||||
/* Call the client's function, if there is one. */
|
||||
|
||||
|
|
@ -248,7 +256,11 @@ dbExpandFunc(scx, arg)
|
|||
}
|
||||
}
|
||||
|
||||
if (DBCellSrArea(scx, dbExpandFunc, (ClientData) arg))
|
||||
/* Don't recursively search things that aren't already expanded. */
|
||||
|
||||
else return 2;
|
||||
|
||||
if (DBCellSrArea(scx, dbUnexpandFunc, (ClientData) arg))
|
||||
return 1;
|
||||
return 2;
|
||||
}
|
||||
|
|
|
|||
1082
database/DBio.c
1082
database/DBio.c
File diff suppressed because it is too large
Load Diff
|
|
@ -583,9 +583,8 @@ DBReOrientLabel(cellDef, area, newPos)
|
|||
*/
|
||||
|
||||
int
|
||||
dbGetLabelArea(tile, dinfo, area)
|
||||
dbGetLabelArea(tile, area)
|
||||
Tile *tile; /* Tile found. */
|
||||
TileType dinfo; /* Split tile information (unused) */
|
||||
Rect *area; /* Area to be modified. */
|
||||
{
|
||||
Rect r;
|
||||
|
|
@ -1086,15 +1085,14 @@ DBPickLabelLayer(def, lab, doCalma)
|
|||
*/
|
||||
|
||||
int
|
||||
dbPickFunc1(tile, dinfo, mask)
|
||||
dbPickFunc1(tile, mask)
|
||||
Tile *tile; /* Tile found. */
|
||||
TileType dinfo; /* Split tile information */
|
||||
TileTypeBitMask *mask; /* Mask to be modified. */
|
||||
{
|
||||
TileType type;
|
||||
|
||||
if (IsSplit(tile))
|
||||
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
else
|
||||
type = TiGetType(tile);
|
||||
|
||||
|
|
@ -1113,16 +1111,15 @@ dbPickFunc1(tile, dinfo, mask)
|
|||
*/
|
||||
|
||||
int
|
||||
dbPickFunc2(tile, dinfo, mask)
|
||||
dbPickFunc2(tile, mask)
|
||||
Tile *tile; /* Tile found. */
|
||||
TileType dinfo; /* Split tile information */
|
||||
TileTypeBitMask *mask; /* Mask to be modified. */
|
||||
{
|
||||
TileType type;
|
||||
TileTypeBitMask tmp, *rMask;
|
||||
|
||||
if (IsSplit(tile))
|
||||
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
type = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
else
|
||||
type = TiGetType(tile);
|
||||
|
||||
|
|
|
|||
|
|
@ -487,6 +487,8 @@ enumerate:
|
|||
newType = (method == (unsigned char)PAINT_XOR) ?
|
||||
*resultTbl : resultTbl[oldType];
|
||||
|
||||
if (mergeFlags & MRG_RIGHT)
|
||||
tile = TiNMMergeRight(tile, plane); // was commented out?
|
||||
if (mergeFlags & MRG_LEFT)
|
||||
TiNMMergeLeft(LB(newtile), plane);
|
||||
}
|
||||
|
|
@ -494,6 +496,8 @@ enumerate:
|
|||
{
|
||||
if (mergeFlags & MRG_LEFT)
|
||||
TiNMMergeLeft(newtile, plane);
|
||||
if (mergeFlags & MRG_RIGHT)
|
||||
TiNMMergeRight(LB(tile), plane); // was commented out?
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1435,6 +1439,10 @@ DBDiagonalProc(oldtype, dinfo)
|
|||
else
|
||||
return -1;
|
||||
|
||||
/* For purposes of "undo" recording, record which side we just painted */
|
||||
if (dinfo->side)
|
||||
newtype |= TT_SIDE;
|
||||
|
||||
return newtype;
|
||||
}
|
||||
|
||||
|
|
@ -1816,15 +1824,14 @@ nextrect:
|
|||
*/
|
||||
|
||||
int
|
||||
dbNMEnumFunc(tile, dinfo, arg)
|
||||
dbNMEnumFunc(tile, arg)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
LinkedRect **arg;
|
||||
{
|
||||
LinkedRect *lr;
|
||||
|
||||
/* Ignore the second call to any diagonal---only count once! */
|
||||
if (IsSplit(tile) && (dinfo & TT_SIDE)) return 0;
|
||||
if (IsSplit(tile) && SplitSide(tile)) return 0;
|
||||
|
||||
lr = (LinkedRect *) mallocMagic(sizeof(LinkedRect));
|
||||
TiToRect(tile, &lr->r_r);
|
||||
|
|
|
|||
|
|
@ -119,9 +119,8 @@ DBPaint (cellDef, rect, type)
|
|||
*/
|
||||
|
||||
int
|
||||
dbResolveImages(tile, dinfo, cellDef)
|
||||
dbResolveImages(tile, cellDef)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
CellDef *cellDef;
|
||||
{
|
||||
Rect rect;
|
||||
|
|
@ -131,7 +130,7 @@ dbResolveImages(tile, dinfo, cellDef)
|
|||
/* Recursive call back to DBPaint---this will ensure that */
|
||||
/* all of the planes of the image type are painted. */
|
||||
|
||||
DBPaint(cellDef, &rect, TiGetTypeExact(tile) | dinfo);
|
||||
DBPaint(cellDef, &rect, TiGetTypeExact(tile));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,16 +32,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "database/database.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.
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -57,16 +47,16 @@ bool DBPropCompat = TRUE; /* If TRUE, then always save properties to
|
|||
|
||||
void
|
||||
DBPropPut(cellDef, name, value)
|
||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||
char *name; /* The name of the property desired. */
|
||||
PropertyRecord *value; /* MUST point to a malloc'ed structure, or NULL.
|
||||
* This will be freed when the CellDef is freed.
|
||||
*/
|
||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||
char *name; /* The name of the property desired. */
|
||||
ClientData value; /* MUST point to a malloc'ed structure, or NULL.
|
||||
* This will be freed when the CellDef is freed.
|
||||
*/
|
||||
|
||||
{
|
||||
HashTable *htab;
|
||||
HashEntry *entry;
|
||||
PropertyRecord *oldvalue;
|
||||
char *oldvalue;
|
||||
|
||||
/* 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 */
|
||||
|
|
@ -105,23 +95,12 @@ DBPropPut(cellDef, name, value)
|
|||
}
|
||||
|
||||
entry = HashFind(htab, name);
|
||||
oldvalue = (PropertyRecord *)HashGetValue(entry);
|
||||
/* All properties are allocated as a single block and can just be freed,
|
||||
* 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)
|
||||
oldvalue = (char *)HashGetValue(entry);
|
||||
if (oldvalue != NULL) freeMagic(oldvalue);
|
||||
if (value == (ClientData)NULL)
|
||||
HashRemove(htab, name);
|
||||
else
|
||||
HashSetValue(entry, PTR2CD(value));
|
||||
HashSetValue(entry, value);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
|
|
@ -131,13 +110,13 @@ DBPropPut(cellDef, name, value)
|
|||
* Get a 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 record.
|
||||
* NULL if the property didn't exist, or if the property value was NULL.
|
||||
* Otherwise, ClientData that represents the property.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
PropertyRecord *
|
||||
ClientData
|
||||
DBPropGet(cellDef, name, found)
|
||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||
char *name; /* The name of the property desired. */
|
||||
|
|
@ -145,12 +124,12 @@ DBPropGet(cellDef, name, found)
|
|||
* exists.
|
||||
*/
|
||||
{
|
||||
PropertyRecord *result;
|
||||
ClientData result;
|
||||
bool haveit;
|
||||
HashTable *htab;
|
||||
HashEntry *entry;
|
||||
|
||||
result = (PropertyRecord *)NULL;
|
||||
result = (ClientData) NULL;
|
||||
haveit = FALSE;
|
||||
htab = (HashTable *) cellDef->cd_props;
|
||||
if (htab == (HashTable *) NULL) goto done;
|
||||
|
|
@ -159,7 +138,7 @@ DBPropGet(cellDef, name, found)
|
|||
if (entry != NULL)
|
||||
{
|
||||
haveit = TRUE;
|
||||
result = (PropertyRecord *)HashGetValue(entry);
|
||||
result = (ClientData) HashGetValue(entry);
|
||||
}
|
||||
|
||||
done:
|
||||
|
|
@ -167,109 +146,6 @@ done:
|
|||
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 --
|
||||
|
|
@ -292,7 +168,7 @@ DBPropEnum(cellDef, func, cdata)
|
|||
*
|
||||
* int foo(name, value, cdata)
|
||||
* char *name;
|
||||
* PropertyRecord *value;
|
||||
* ClientData value;
|
||||
* ClientData cdata;
|
||||
* {
|
||||
* -- return 0 to continue,
|
||||
|
|
@ -313,7 +189,7 @@ DBPropEnum(cellDef, func, cdata)
|
|||
HashStartSearch(&hs);
|
||||
while ((entry = HashNext(htab, &hs)) != NULL)
|
||||
{
|
||||
res = (*func)(entry->h_key.h_name, (PropertyRecord *)entry->h_pointer, cdata);
|
||||
res = (*func)(entry->h_key.h_name, (ClientData) entry->h_pointer, cdata);
|
||||
if (res != 0) return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,296 +44,6 @@ struct dbCheck
|
|||
|
||||
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 */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -346,7 +56,6 @@ DBTestNMInteract(Rect *rect1,
|
|||
* int
|
||||
* func(tile, cdata)
|
||||
* Tile *tile;
|
||||
* TileType dinfo;
|
||||
* ClientData cdata;
|
||||
* {
|
||||
* }
|
||||
|
|
@ -428,27 +137,148 @@ nm_enum:
|
|||
/* the tile enumeration if it is not. */
|
||||
/* Watch for calculations involving (M)INFINITY in tile (tp)! */
|
||||
|
||||
if (IsSplit(tp))
|
||||
{
|
||||
TileType tpdi = TiGetTypeExact(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 (TTMaskHasType(mask, SplitLeftType(tp)))
|
||||
if (DBTestNMInteract(rect, ttype, tp, tpdi, TRUE))
|
||||
if ((*func)(tp, (TileType)TT_DIAGONAL, arg))
|
||||
return 1;
|
||||
if (TTMaskHasType(mask, SplitRightType(tp)))
|
||||
if (DBTestNMInteract(rect, ttype, tp, tpdi | TT_SIDE, TRUE))
|
||||
if ((*func)(tp, (TileType)TT_DIAGONAL | TT_SIDE, arg))
|
||||
return 1;
|
||||
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
|
||||
{
|
||||
if (TTMaskHasType(mask, TiGetType(tp)))
|
||||
if (DBTestNMInteract(rect, ttype, tp, (TileType)0, TRUE))
|
||||
if ((*func)(tp, (TileType)0, arg))
|
||||
return 1;
|
||||
/* 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 (!TTMaskHasType(mask, SplitLeftType(tp)))
|
||||
ignore_sides |= IGNORE_LEFT;
|
||||
if (!TTMaskHasType(mask, SplitRightType(tp)))
|
||||
ignore_sides |= IGNORE_RIGHT;
|
||||
|
||||
tpt = TiGetTypeExact(tp);
|
||||
if ((tpt & TT_DIRECTION) == (ttype & TT_DIRECTION))
|
||||
{
|
||||
f3 = (LEFT(tp) > MINFINITY + 2) ?
|
||||
((dlong)(rect->r_xtop - LEFT(tp)) * rheight) : DLONG_MAX;
|
||||
f4 = (RIGHT(tp) < INFINITY - 2) ?
|
||||
((dlong)(RIGHT(tp) - rect->r_xbot) * rheight) : DLONG_MAX;
|
||||
|
||||
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
|
||||
{
|
||||
if ((f1 < f3) && (f2 > f4))
|
||||
/* Tile top left is outside search area */
|
||||
ignore_sides |= IGNORE_LEFT;
|
||||
}
|
||||
}
|
||||
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:
|
||||
tpnew = TR(tp);
|
||||
if (LEFT(tpnew) < rect->r_xtop)
|
||||
|
|
@ -495,7 +325,6 @@ enum_next:
|
|||
* int
|
||||
* func(tile, cdata)
|
||||
* Tile *tile;
|
||||
* TileType dinfo;
|
||||
* ClientData cdata;
|
||||
* {
|
||||
* }
|
||||
|
|
@ -587,7 +416,9 @@ enumerate:
|
|||
(dlong)(rect->r_xbot - LEFT(tp)) * theight : DLONG_MIN;
|
||||
if (SplitDirection(tp) ? (f1 > f4) : (f2 > f4))
|
||||
{
|
||||
if ((*func)(tp, (TileType)TT_DIAGONAL, arg)) return (1);
|
||||
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
|
||||
& ~TT_SIDE)); /* bit clear */
|
||||
if ((*func)(tp, arg)) return (1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -598,12 +429,14 @@ enumerate:
|
|||
(dlong)(RIGHT(tp) - rect->r_xtop) * theight : DLONG_MIN;
|
||||
if (SplitDirection(tp) ? (f2 > f3) : (f1 > f3))
|
||||
{
|
||||
if ((*func)(tp, (TileType)TT_DIAGONAL | TT_SIDE, arg)) return (1);
|
||||
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
|
||||
| TT_SIDE)); /* bit set */
|
||||
if ((*func)(tp, arg)) return (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (TTMaskHasType(mask, TiGetType(tp)) && (*func)(tp, (TileType)0, arg))
|
||||
if (TTMaskHasType(mask, TiGetType(tp)) && (*func)(tp, arg))
|
||||
return (1);
|
||||
|
||||
tpnew = TR(tp);
|
||||
|
|
@ -652,7 +485,6 @@ enumerate:
|
|||
* int
|
||||
* func(tile, cdata)
|
||||
* Tile *tile;
|
||||
* TileType dinfo;
|
||||
* ClientData cdata;
|
||||
* {
|
||||
* }
|
||||
|
|
@ -744,7 +576,9 @@ enumerate:
|
|||
(dlong)(rect->r_xbot - LEFT(tp)) * (dlong)theight : DLONG_MIN;
|
||||
if (SplitDirection(tp) ? (f1 > f4) : (f2 > f4))
|
||||
{
|
||||
if ((tp->ti_client == client) && (*func)(tp, (TileType)TT_DIAGONAL, arg))
|
||||
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
|
||||
& ~TT_SIDE)); /* bit clear */
|
||||
if ((tp->ti_client == client) && (*func)(tp, arg))
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
|
@ -756,15 +590,16 @@ enumerate:
|
|||
(dlong)(RIGHT(tp) - rect->r_xtop) * (dlong)theight : DLONG_MIN;
|
||||
if (SplitDirection(tp) ? (f2 > f3) : (f1 > f3))
|
||||
{
|
||||
if ((tp->ti_client == client) && (*func)(tp, (TileType)TT_DIAGONAL
|
||||
| TT_SIDE, arg))
|
||||
TiSetBody(tp, INT2CD((TileType)CD2INT(TiGetBody(tp))
|
||||
| TT_SIDE)); /* bit set */
|
||||
if ((tp->ti_client == client) && (*func)(tp, arg))
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (TTMaskHasType(mask, TiGetType(tp)) && tp->ti_client == client
|
||||
&& (*func)(tp, (TileType)0, arg))
|
||||
&& (*func)(tp, arg))
|
||||
return (1);
|
||||
|
||||
tpnew = TR(tp);
|
||||
|
|
@ -830,7 +665,7 @@ DBResetTilePlane(plane, cdata)
|
|||
/* Each iteration visits another tile on the LHS of the search area */
|
||||
while (TOP(tp) > rect->r_ybot)
|
||||
{
|
||||
/* Each iteration resets another tile */
|
||||
/* Each iteration frees another tile */
|
||||
enumerate:
|
||||
tp->ti_client = cdata;
|
||||
|
||||
|
|
@ -866,88 +701,6 @@ 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 */;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -1165,9 +918,8 @@ DBCheckMaxHStrips(plane, area, proc, cdata)
|
|||
*/
|
||||
|
||||
int
|
||||
dbCheckMaxHFunc(tile, dinfo, dbc)
|
||||
dbCheckMaxHFunc(tile, dbc)
|
||||
Tile *tile;
|
||||
TileType dinfo; /* (unused) */
|
||||
struct dbCheck *dbc;
|
||||
{
|
||||
Tile *tp;
|
||||
|
|
@ -1258,9 +1010,8 @@ DBCheckMaxVStrips(plane, area, proc, cdata)
|
|||
*/
|
||||
|
||||
int
|
||||
dbCheckMaxVFunc(tile, dinfo, dbc)
|
||||
dbCheckMaxVFunc(tile, dbc)
|
||||
Tile *tile;
|
||||
TileType dinfo; /* (unused) */
|
||||
struct dbCheck *dbc;
|
||||
{
|
||||
Tile *tp;
|
||||
|
|
|
|||
|
|
@ -303,14 +303,9 @@ typedef struct label
|
|||
#define PORT_SHAPE_RING 0x1000 /* Port is a ring shape */
|
||||
#define PORT_SHAPE_THRU 0x1800 /* Port is a feedthrough shape */
|
||||
|
||||
#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 */
|
||||
#define PORT_VISITED 0x2000 /* Bit for checking if a port */
|
||||
/* has been previously visited. */
|
||||
#define LABEL_STICKY 0x4000 /* Label does not change layers */
|
||||
#define LABEL_GENERATE 0x8000 /* Auto-generated label */
|
||||
|
||||
/*
|
||||
|
|
@ -556,18 +551,6 @@ typedef struct diag_info
|
|||
bool side;
|
||||
} 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. */
|
||||
/* Used in selOps.c but also passed back to CmdRS.c for select command. */
|
||||
|
||||
|
|
@ -651,7 +634,6 @@ typedef struct treeFilter
|
|||
#define TF_LABEL_ATTACH_NOT_SE 0x10 /* Same as above, ignore tile SE corner */
|
||||
#define TF_LABEL_ATTACH_NOT_SW 0x20 /* Same as above, ignore tile SW corner */
|
||||
#define TF_LABEL_ATTACH_CORNER 0x3C /* Mask of the four types above */
|
||||
#define TF_LABEL_REVERSE_SEARCH 0x40 /* Search children before parent */
|
||||
|
||||
/* To do: Make the tpath entries dynamically allocated */
|
||||
#define FLATTERMSIZE 4096 /* Used for generating flattened labels */
|
||||
|
|
@ -705,25 +687,6 @@ struct conSrArg2
|
|||
|
||||
#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 ------------- */
|
||||
|
||||
typedef struct
|
||||
|
|
@ -756,14 +719,6 @@ typedef struct
|
|||
#define PAINT_MARK 1 /* Mark tiles that are painted */
|
||||
#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 -------------------- */
|
||||
|
||||
/* Painting/erasing */
|
||||
|
|
@ -949,9 +904,7 @@ extern void DBFreePaintPlane();
|
|||
|
||||
/* Cell properties */
|
||||
extern void DBPropPut();
|
||||
extern PropertyRecord *DBPropGet();
|
||||
extern char *DBPropGetString();
|
||||
extern dlong DBPropGetDouble();
|
||||
extern ClientData DBPropGet();
|
||||
extern int DBPropEnum();
|
||||
extern void DBPropClearAll();
|
||||
|
||||
|
|
@ -967,10 +920,9 @@ extern int DBArraySr();
|
|||
extern bool DBNearestLabel();
|
||||
extern int DBSrLabelLoc();
|
||||
extern TileType DBTransformDiagonal();
|
||||
extern bool DBTestNMInteract(Rect *rect1, TileType tt1, Tile *t2, TileType di2, bool overlap_only);
|
||||
extern int dbcUnconnectFunc(Tile *tile, TileType dinfo, ClientData clientData); /* (notused) */
|
||||
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) */
|
||||
extern int dbcUnconnectFunc(Tile *tile, ClientData clientData); /* (notused) */
|
||||
extern int dbSrConnectFunc(Tile *tile, ClientData clientData); /* (struct conSrArg *csa) */
|
||||
extern int dbSrConnectStartFunc(Tile *tile, ClientData clientData); /* cb_database_srpaintarea_t (Tile **pTile) */
|
||||
|
||||
/* C99 compat */
|
||||
extern void DBEraseValid();
|
||||
|
|
@ -1017,10 +969,10 @@ extern int dbIsPrimary();
|
|||
extern void dbTechMatchResidues();
|
||||
extern void DBUndoInit();
|
||||
extern void DBResetTilePlane();
|
||||
extern void DBResetTilePlaneSpecial();
|
||||
extern void DBNewYank();
|
||||
extern int DBSrPaintClient();
|
||||
extern int DBSrConnect();
|
||||
extern int DBSrConnectOnePlane();
|
||||
extern char *dbFgets();
|
||||
extern void DBAdjustLabelsNew();
|
||||
extern bool DBScaleValue();
|
||||
|
|
@ -1049,7 +1001,6 @@ extern int DBLambda[2];
|
|||
/* -------------------- Exported magic file suffix -------------------- */
|
||||
|
||||
extern char *DBSuffix; /* Suffix appended to all Magic cell names */
|
||||
extern bool DBPropCompat; /* Backwards-compatible properties */
|
||||
|
||||
/* -------------------- User Interface Stuff -------------------------- */
|
||||
|
||||
|
|
@ -1062,19 +1013,6 @@ extern unsigned char DBVerbose; /* If 0, don't print any messages */
|
|||
#define DB_VERBOSE_WARN 2
|
||||
#define DB_VERBOSE_ALL 3
|
||||
|
||||
/* ---------- Definitions for expanding/unexpanding cells --------------*/
|
||||
|
||||
/* Selection expansion flags */
|
||||
#define DB_EXPAND_MASK 3 /* 1 = expand, 0 = unexpand, 2 = toggle */
|
||||
#define DB_EXPAND_SURROUND_MASK 4 /* 1 = surround, 0 = touch */
|
||||
|
||||
/* Selection expansion values */
|
||||
#define DB_EXPAND 0
|
||||
#define DB_UNEXPAND 1
|
||||
#define DB_EXPAND_TOGGLE 2
|
||||
#define DB_EXPAND_SURROUND 4
|
||||
#define DB_EXPAND_OVERLAP 0
|
||||
|
||||
/* ------------------ Exported technology variables ------------------- */
|
||||
|
||||
/***
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ extern void CmdRandom(), CmdSave(), CmdScaleGrid(), CmdSee();
|
|||
extern void CmdSelect(), CmdSetLabel(), CmdSideways();
|
||||
extern void CmdShell(), CmdSnap();
|
||||
extern void CmdStretch(), CmdStraighten();
|
||||
extern void CmdTech(), CmdTool(), CmdUnexpand(), CmdUnits();
|
||||
extern void CmdTech(), CmdTool(), CmdUnexpand();
|
||||
extern void CmdUpsidedown(), CmdWhat(), CmdWire(), CmdWriteall();
|
||||
extern void CmdGoto(), CmdFlatten(), CmdXload(), CmdXor();
|
||||
|
||||
|
|
@ -474,9 +474,6 @@ DBWInitCommands()
|
|||
WindAddCommand(DBWclientID,
|
||||
"unexpand unexpand subcells under box",
|
||||
CmdUnexpand, FALSE);
|
||||
WindAddCommand(DBWclientID,
|
||||
"units [type] set type of units parsed and displayed",
|
||||
CmdUnits, FALSE);
|
||||
WindAddCommand(DBWclientID,
|
||||
"upsidedown flip selection and box upside down",
|
||||
CmdUpsidedown, FALSE);
|
||||
|
|
|
|||
|
|
@ -421,8 +421,7 @@ DBWredisplay(w, rootArea, clipArea)
|
|||
/* Set style information beforehand */
|
||||
GrSetStuff(STYLE_LABEL);
|
||||
(void) DBTreeSrLabels(&scontext, &DBAllTypeBits, bitMask,
|
||||
(TerminalPath *) NULL,
|
||||
TF_LABEL_DISPLAY | TF_LABEL_ATTACH | TF_LABEL_REVERSE_SEARCH,
|
||||
(TerminalPath *) NULL, TF_LABEL_DISPLAY | TF_LABEL_ATTACH,
|
||||
dbwLabelFunc, (ClientData)(&crec->dbw_visibleLayers));
|
||||
GrClipTo(&rootClip);
|
||||
}
|
||||
|
|
@ -572,9 +571,8 @@ DBWredisplay(w, rootArea, clipArea)
|
|||
*/
|
||||
|
||||
int
|
||||
dbwPaintFunc(tile, dinfo, cxp)
|
||||
Tile *tile; /* Tile to be redisplayed. */
|
||||
TileType dinfo; /* Split tile information */
|
||||
dbwPaintFunc(tile, cxp)
|
||||
Tile *tile; /* Tile to be redisplayed. */
|
||||
TreeContext *cxp; /* From DBTreeSrTiles */
|
||||
{
|
||||
SearchContext *scx = cxp->tc_scx;
|
||||
|
|
@ -654,7 +652,7 @@ dbwPaintFunc(tile, dinfo, cxp)
|
|||
/* whether to render the outline with a fast rectangle- */
|
||||
/* drawing routine or to render it segment by segment. */
|
||||
|
||||
GrBox(dbwWindow, &scx->scx_trans, tile, dinfo);
|
||||
GrBox(dbwWindow, &scx->scx_trans, tile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1077,10 +1075,8 @@ dbwBBoxFunc(scx)
|
|||
*/
|
||||
|
||||
int
|
||||
dbwTileFunc(tile, dinfo, clientdata)
|
||||
dbwTileFunc(tile)
|
||||
Tile *tile; /* A tile to be redisplayed. */
|
||||
TileType dinfo; /* Split tile information (unused) */
|
||||
ClientData clientdata; /* (unused) */
|
||||
{
|
||||
Rect r, r2;
|
||||
int xoffset, yoffset;
|
||||
|
|
@ -1117,7 +1113,7 @@ dbwTileFunc(tile, dinfo, clientdata)
|
|||
|
||||
if (dbwSeeTypes)
|
||||
{
|
||||
(void) sprintf(string, "%s", DBTypeShortName(TiGetType(tile)));
|
||||
(void) sprintf(string, "%s",DBTypeShortName(TiGetType(tile)));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1133,7 +1129,7 @@ dbwTileFunc(tile, dinfo, clientdata)
|
|||
|
||||
#define XYOFFSET 12
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (i=0; i<4; i++)
|
||||
{
|
||||
xoffset = 0;
|
||||
yoffset = 0;
|
||||
|
|
@ -1176,13 +1172,13 @@ dbwTileFunc(tile, dinfo, clientdata)
|
|||
yoffset = temp;
|
||||
}
|
||||
|
||||
if ((dbwWatchTrans.t_a < 0) || (dbwWatchTrans.t_b < 0))
|
||||
if ( (dbwWatchTrans.t_a < 0) || (dbwWatchTrans.t_b < 0) )
|
||||
{
|
||||
/* mirror in x */
|
||||
xoffset = -xoffset;
|
||||
}
|
||||
|
||||
if ((dbwWatchTrans.t_d < 0) || (dbwWatchTrans.t_e < 0))
|
||||
if ( (dbwWatchTrans.t_d < 0) || (dbwWatchTrans.t_e < 0) )
|
||||
{
|
||||
/* mirror in y */
|
||||
yoffset = -yoffset;
|
||||
|
|
|
|||
|
|
@ -249,10 +249,7 @@ DBWFeedbackRedraw(window, plane)
|
|||
}
|
||||
|
||||
int
|
||||
dbwFeedbackAlways1(
|
||||
Tile *tile, /* (unused) */
|
||||
TileType dinfo, /* (unused) */
|
||||
ClientData clientdata) /* (unused) */
|
||||
dbwFeedbackAlways1()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -392,9 +392,8 @@ DBWHLRedrawWind(window)
|
|||
*/
|
||||
|
||||
int
|
||||
dbwhlEraseFunc(tile, dinfo, window)
|
||||
dbwhlEraseFunc(tile, window)
|
||||
Tile *tile; /* Tile describing area to be erased. */
|
||||
TileType dinfo; /* Split tile information (unused) */
|
||||
MagWindow *window; /* Window that is being altered. */
|
||||
{
|
||||
Rect area;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "tcltk/tclmagic.h"
|
||||
#include "utils/main.h"
|
||||
#include "utils/magic.h"
|
||||
#include "utils/geometry.h"
|
||||
|
|
@ -34,7 +33,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "utils/hash.h"
|
||||
#include "database/database.h"
|
||||
#include "utils/main.h"
|
||||
#include "cif/cif.h"
|
||||
#include "commands/commands.h"
|
||||
#include "dbwind/dbwind.h"
|
||||
#include "graphics/graphics.h"
|
||||
|
|
@ -546,12 +544,12 @@ DBWloadWindow(window, name, flags)
|
|||
newEditUse = DBCellNewUse(newEditDef, (char *) NULL);
|
||||
(void) StrDup(&(newEditUse->cu_id), "Topmost cell in the window");
|
||||
DBExpand(newEditUse,
|
||||
((DBWclientRec *)window->w_clientData)->dbw_bitmask, DB_EXPAND);
|
||||
((DBWclientRec *)window->w_clientData)->dbw_bitmask, TRUE);
|
||||
|
||||
if (expand)
|
||||
DBExpandAll(newEditUse, &(newEditUse->cu_bbox),
|
||||
((DBWclientRec *)window->w_clientData)->dbw_bitmask,
|
||||
DB_UNEXPAND, UnexpandFunc,
|
||||
FALSE, UnexpandFunc,
|
||||
INT2CD(((DBWclientRec *)window->w_clientData)->dbw_bitmask));
|
||||
|
||||
if (newEdit)
|
||||
|
|
@ -655,311 +653,6 @@ DBWexit()
|
|||
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,21 +65,11 @@ typedef struct _crosshairRec {
|
|||
static CrosshairRec curCrosshair; /* Crosshair position */
|
||||
|
||||
/*
|
||||
* If the following is DBW_UNITS_USER, the box gets snapped to the user's
|
||||
* If the following is DBW_SNAP_USER, the box gets snapped to the user's
|
||||
* grid always, instead of snapping to the usual 1x1 grid. If the value
|
||||
* is DBW_UNITS_INTERNAL, the box gets snapped to the internal grid.
|
||||
* is DBW_SNAP_INTERNAL, the box gets snapped to the internal grid.
|
||||
*/
|
||||
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;
|
||||
int DBWSnapToGrid = DBW_SNAP_LAMBDA;
|
||||
|
||||
/* Forward reference: */
|
||||
|
||||
|
|
@ -92,8 +82,8 @@ extern int DBWToolDraw();
|
|||
* toolFindPoint --
|
||||
*
|
||||
* Returns the point in root coordinates.
|
||||
* If DBWSnapToGrid is DBW_UNITS_USER, pick the nearest point that is
|
||||
* aligned with the window's grid. If DBWSnapToGrid is DBW_UNITS_LAMBDA,
|
||||
* If DBWSnapToGrid is DBW_SNAP_USER, pick the nearest point that is
|
||||
* aligned with the window's grid. If DBWSnapToGrid is DBW_SNAP_LAMBDA,
|
||||
* pick the nearest point that is an integer lambda value.
|
||||
*
|
||||
* Results:
|
||||
|
|
@ -130,7 +120,7 @@ toolFindPoint(p, rootPoint, rootArea)
|
|||
if (!GEO_ENCLOSE(p, &WindCurrentWindow->w_screenArea)) return NULL;
|
||||
|
||||
WindPointToSurface(WindCurrentWindow, p, rootPoint, rootArea);
|
||||
if (DBWSnapToGrid != DBW_UNITS_INTERNAL)
|
||||
if (DBWSnapToGrid != DBW_SNAP_INTERNAL)
|
||||
ToolSnapToGrid(WindCurrentWindow, rootPoint, rootArea);
|
||||
return WindCurrentWindow;
|
||||
|
||||
|
|
@ -774,10 +764,7 @@ DBWDrawBox(window, plane)
|
|||
}
|
||||
|
||||
int
|
||||
dbwBoxAlways1(
|
||||
Tile *tile, /* (unused) */
|
||||
TileType dinfo, /* (unused) */
|
||||
ClientData clientdata) /* (unused) */
|
||||
dbwBoxAlways1()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -854,8 +841,8 @@ DBWResetBox(CellDef *def)
|
|||
* Repositions the box by one of its corners.
|
||||
* 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
|
||||
* command) if DBWSnapToGrid is DBW_UNITS_USER. If DBWSnapToGrid is
|
||||
* DBW_UNITS_LAMBDA, the box corner is snapped to the nearest integer
|
||||
* command) if DBWSnapToGrid is DBW_SNAP_USER. If DBWSnapToGrid is
|
||||
* DBW_SNAP_LAMBDA, the box corner is snapped to the nearest integer
|
||||
* lambda value.
|
||||
*
|
||||
* Results:
|
||||
|
|
@ -958,8 +945,8 @@ ToolMoveBox(corner, point, screenCoords, rootDef)
|
|||
*
|
||||
* 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
|
||||
* command) if DBWSnapToGrid is DBW_UNITS_USER. If DBWSnapToGrid is
|
||||
* DBW_UNITS_LAMBDA, the box corner is snapped to the nearest integer
|
||||
* command) if DBWSnapToGrid is DBW_SNAP_USER. If DBWSnapToGrid is
|
||||
* DBW_SNAP_LAMBDA, the box corner is snapped to the nearest integer
|
||||
* lambda value.
|
||||
*
|
||||
* Results:
|
||||
|
|
@ -1102,7 +1089,7 @@ ToolSnapToGrid(w, p, rEnclose)
|
|||
if (crec == NULL || p == NULL)
|
||||
return;
|
||||
|
||||
if (DBWSnapToGrid == DBW_UNITS_LAMBDA)
|
||||
if (DBWSnapToGrid == DBW_SNAP_LAMBDA)
|
||||
{
|
||||
lr.r_xbot = lr.r_ybot = 0;
|
||||
lr.r_xtop = DBLambda[1] / DBLambda[0];
|
||||
|
|
|
|||
|
|
@ -113,7 +113,6 @@ typedef struct DBW1 {
|
|||
|
||||
extern WindClient DBWclientID;
|
||||
extern int DBWSnapToGrid;
|
||||
extern int DBWUnits;
|
||||
|
||||
extern int DBWMaxTechStyles;
|
||||
extern int DBWMaxTileStyles;
|
||||
|
|
@ -122,17 +121,13 @@ extern int DBWNumStyles;
|
|||
extern int RtrPolyWidth, RtrMetalWidth, RtrContactWidth;
|
||||
|
||||
/*
|
||||
* Exported procedure headers for redisplay and output
|
||||
* Exported procedure headers for redisplay
|
||||
*/
|
||||
|
||||
extern int DBWWatchTiles();
|
||||
extern void DBWAreaChanged();
|
||||
extern void DBWLabelChanged();
|
||||
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
|
||||
|
|
@ -174,36 +169,14 @@ extern void DBWBoxHandler();
|
|||
#define TOOL_ILG -1
|
||||
|
||||
/* The following defines are used to indicate which coordinate system
|
||||
* is used when displaying or returning values. By default this is
|
||||
* 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.
|
||||
* the cursor box snaps to when moved with mouse clicks (values for
|
||||
* DBWSnapToGrid).
|
||||
*/
|
||||
|
||||
#define DBW_UNITS_DEFAULT -1 /* backwards-compatible behavior */
|
||||
#define DBW_UNITS_INTERNAL 0 /* internal units */
|
||||
#define DBW_UNITS_LAMBDA 1 /* lambda 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".
|
||||
*/
|
||||
#define DBW_SNAP_INTERNAL 0 /* internal units (fine grid) */
|
||||
#define DBW_SNAP_LAMBDA 1 /* lambda units (coarse grid) */
|
||||
#define DBW_SNAP_USER 2 /* user grid units (user grid) */
|
||||
#define DBW_SNAP_MICRONS 3 /* micron units */
|
||||
|
||||
/* The following window mask can be used to select all database windows
|
||||
* for things like the mask parameter to DBWAreaChanged.
|
||||
|
|
|
|||
|
|
@ -71,15 +71,12 @@ Operations on cell definitions.
|
|||
<DT> <B>rename</B> <I>name newname</I>
|
||||
<DD> Change the name of the cell definition <I>name</I> to
|
||||
<I>newname</I>.
|
||||
<DT> <B>delete</B> <I>name</I> [<B>-noprompt</B>]
|
||||
<DT> <B>delete</B> <I>name</I>
|
||||
<DD> Delete the cell definition with name <I>name</I>. If cell
|
||||
<I>name</I> is a descendent of another cell, the command
|
||||
will be prohibited. If the cell <I>name</I> is currently
|
||||
the topmost cell in the window, the window will be loaded
|
||||
with default cell "(UNNAMED)". If option <B>-noprompt</B>
|
||||
is specified, then the actions specified above happen
|
||||
immediately. Otherwise, a dialog box will be raised
|
||||
asking for confirmation to delete the cell.
|
||||
with default cell "(UNNAMED)".
|
||||
<DT> <B>dereference</B> <I>name</I>
|
||||
<DD> Perform a flush of the cell (per the "<B>flush</B>" command),
|
||||
first removing any file path associated with the cell, so
|
||||
|
|
|
|||
|
|
@ -334,23 +334,23 @@
|
|||
</TR>
|
||||
<TR>
|
||||
<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=version.html> <B>version</B></A> </TD>
|
||||
</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=windowborder.html> <B>windowborder</B></A> </TD>
|
||||
<TD> <A HREF=windowcaption.html> <B>windowcaption</B></A> </TD>
|
||||
</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=windowscrollbars.html> <B>windowscrollbars</B></A> </TD>
|
||||
<TD> <A HREF=xview.html> <B>xview</B></A> </TD>
|
||||
</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=tk_path_name.html> <I>tk_path_name</I></A> </TD>
|
||||
<TD> </TD>
|
||||
</TR>
|
||||
</TBODY>
|
||||
</TABLE>
|
||||
|
|
|
|||
|
|
@ -117,7 +117,6 @@ techmanager
|
|||
tool
|
||||
undo
|
||||
unexpand
|
||||
units
|
||||
updatedisplay
|
||||
upsidedown
|
||||
version
|
||||
|
|
|
|||
|
|
@ -26,8 +26,7 @@ expanded/unexpanded cells in the current selection.
|
|||
|
||||
<H3>Usage:</H3>
|
||||
<BLOCKQUOTE>
|
||||
<B>expand</B> [<B>selection</B>|<B>surround</B>|<B>overlap</B>|<B>all</B>]
|
||||
[<B>toggle</B>] <BR><BR>
|
||||
<B>expand</B> [<B>toggle</B>] <BR><BR>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3>Shortcuts:</H3>
|
||||
|
|
@ -39,32 +38,14 @@ expanded/unexpanded cells in the current selection.
|
|||
<H3>Summary:</H3>
|
||||
<BLOCKQUOTE>
|
||||
The <B>expand</B> command expands the view of subcells to
|
||||
display the contents of the subcells.
|
||||
|
||||
Option <B>overlap</B> expands all unexpanded subcells that
|
||||
overlap with the cursor box in the layout window. <P>
|
||||
|
||||
Option <B>surround</B> expands all unexpanded subcells that
|
||||
are completely surrounded by the cursor box in the layout window. <P>
|
||||
|
||||
Option <B>all</B> expands all subcells in the layout window. <P>
|
||||
|
||||
Option <B>selection</B> operates on the current selection, not
|
||||
relative to the cursor box, expanding all selected cells. <P>
|
||||
|
||||
Option <B>toggle</B> will expand a selected cell that is
|
||||
unexpanded, or unexpand a cell that is already expanded.
|
||||
<B>toggle</B> may be given as an additional option to any
|
||||
of the other options above; however, the <B>toggle</B> option
|
||||
must be the last option given to the command.<P>
|
||||
|
||||
With no arguments, the <B>expand</B> command behaves like
|
||||
<B>expand overlap</B>, and the <B>expand toggle</B> command
|
||||
with no additonal arguments behaves like
|
||||
<B>expand selection toggle</B>, for backwards-compatible
|
||||
behavior with earlier versions of magic which offered only
|
||||
the <B>toggle</B> option.
|
||||
display the contents of the subcells. Without arguments,
|
||||
the <B>expand</B> command expands all unexpanded subcells that
|
||||
touch or intersect the cursor box in the layout window. <P>
|
||||
|
||||
Option <B>expand toggle</B> operates on the current selection,
|
||||
not relative to the cursor box, and will expand a selected
|
||||
cell that is unexpanded, or unexpand a cell that is already
|
||||
expanded.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3>Implementation Notes:</H3>
|
||||
|
|
|
|||
|
|
@ -42,11 +42,9 @@ Circuit netlist extractor
|
|||
<DL>
|
||||
<DT> <B>capacitance</B>
|
||||
<DD> Extract local parasitic capacitance values to substrate
|
||||
<DT> <B>coupling</B>
|
||||
<DD> Extract the parasitic coupling capacitance between
|
||||
nodes.
|
||||
<DT> <B>lumped</B>
|
||||
<DD> Extract lumped resistance values.
|
||||
<DT> <B>resistance</B>
|
||||
<DD> Extract lumped resistance values. Note that this
|
||||
is <I>not</I> the same as full parasitic resistance.
|
||||
The values extracted are "lumped" resistance and
|
||||
indicate the value for which the delay through the
|
||||
net can be computed with R times C, where R is the
|
||||
|
|
@ -57,10 +55,9 @@ Circuit netlist extractor
|
|||
command. Lumped resistances have no meaning in
|
||||
SPICE netlists and will only be used when running
|
||||
<B>ext2sim</B> to generate a .sim netlist.
|
||||
Prior to magic version 8.3.597, this option was
|
||||
<B>resistance</B>, but as that was often confused
|
||||
with full parasitic resistance extraction, it has
|
||||
been changed.
|
||||
<DT> <B>coupling</B>
|
||||
<DD> Extract the parasitic coupling capacitance between
|
||||
nodes.
|
||||
<DT> <B>length</B>
|
||||
<DD> Extract the length of the shortest path from a driver
|
||||
to a receiver, for computing more accurate parasitic
|
||||
|
|
@ -76,7 +73,7 @@ Circuit netlist extractor
|
|||
array instances, is guaranteed to be strictly positive.
|
||||
<DT> <B>all</B>
|
||||
<DD> Apply all standard options (does not include options
|
||||
"local", "labelcheck", "aliases", or "resistance").
|
||||
"local", "labelcheck", or "aliases").
|
||||
<DT> <B>local</B>
|
||||
<DD> Write all .ext files to the current working directory.
|
||||
If not specified, each .ext file will be placed in the
|
||||
|
|
@ -102,28 +99,6 @@ Circuit netlist extractor
|
|||
but will usually just slow down processing by commands
|
||||
like "ext2spice" that use the .ext file contents, so it
|
||||
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>
|
||||
</BLOCKQUOTE>
|
||||
These options (except for "local") determine how much
|
||||
|
|
@ -238,9 +213,7 @@ Circuit netlist extractor
|
|||
<I>Warning:</I> This operation immediately modifies the
|
||||
existing layout in preparation for extraction. Label
|
||||
modifications are permanent, and cannot be undone. All
|
||||
cells in the hierarchy may potentially be modified. To avoid
|
||||
this issue, use the "extract do unique" option instead (see
|
||||
above). <BR>
|
||||
cells in the hierarchy may potentially be modified. <BR>
|
||||
<DT> <B>warn</B> [[<B>no</B>] <I>option</I>]
|
||||
<DD> Enable/disable reporting of non-fatal errors, where <I>option</I>
|
||||
may be one of the following:
|
||||
|
|
|
|||
|
|
@ -92,25 +92,17 @@ information.
|
|||
The <B>extresist</B> command provides a method for generating
|
||||
a more detailed model of resistance, in which long network
|
||||
routes and branching routes are replaced with resistor devices
|
||||
and device networks. This is known as "full R-C extraction". <P>
|
||||
and device networks. <P>
|
||||
|
||||
Using <B>extresist</B> as a standalone command is a multi-step
|
||||
process. It is first necessary to run <B>extract</B> to get
|
||||
the initial netlist.
|
||||
After a <TT>.ext</TT> file has been generated, the
|
||||
<B>extresist</B> command may be run. The output is
|
||||
Using <B>extresist</B> is a multi-step process. It is first
|
||||
necessary to run both <B>extract</B> and <B>ext2sim</B> to get
|
||||
the initial netlist (with lumped, not detailed, resistances).
|
||||
After a <TT>.sim</TT> file has been generated, the
|
||||
<B>extresist all</B> command may be run. The output is
|
||||
a file <TT>.res.ext</TT> for each cell in the hierarchy.
|
||||
Finally, with the option <B>extresist on</B> set, <B>ext2spice</B>
|
||||
will generate the final, 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.
|
||||
Finally, with the option <B>extresist on</B> set,
|
||||
<B>ext2sim</B> or <B>ext2spice</B> will generate the final,
|
||||
detailed simulation file. <P>
|
||||
|
||||
More details on using <B>extresist</B> can be found in
|
||||
<B>magic</B> Tutorial number 8.
|
||||
|
|
@ -125,7 +117,6 @@ information.
|
|||
<BLOCKQUOTE>
|
||||
<A HREF=extract.html><B>extract</B></A> <BR>
|
||||
<A HREF=ext2sim.html><B>ext2sim</B></A> <BR>
|
||||
<A HREF=ext2spice.html><B>ext2spice</B></A> <BR>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P><IMG SRC=graphics/line1.gif><P>
|
||||
|
|
|
|||
|
|
@ -182,13 +182,6 @@ Read GDSII input or generate GDSII output.
|
|||
than to subsplit the internal grid to such a fine value.
|
||||
The "<B>cif limit</B>" function may also be used to limit
|
||||
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>]
|
||||
<DD> When reading a GDS file, this option forces magic to rename
|
||||
cell definitions in the database when a cell of the same name
|
||||
|
|
|
|||
|
|
@ -87,50 +87,6 @@ Place a label in the layout
|
|||
to another layer. <P>
|
||||
</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>
|
||||
<BLOCKQUOTE>
|
||||
<B>label</B> is implemented as a built-in command in <B>magic</B>.
|
||||
|
|
|
|||
|
|
@ -25,13 +25,9 @@ Attach a "property" (string key and value pair) to the edit cell
|
|||
|
||||
<H3>Usage:</H3>
|
||||
<BLOCKQUOTE>
|
||||
<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>
|
||||
<B>property</B> [<I>key</I> [<I>value</I>]] <BR><BR>
|
||||
<BLOCKQUOTE>
|
||||
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>.
|
||||
where <I>key</I> and <I>value</I> are any text strings.
|
||||
</BLOCKQUOTE>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
|
@ -49,64 +45,11 @@ Attach a "property" (string key and value pair) to the edit cell
|
|||
with the key is returned. With both arguments, the string
|
||||
<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
|
||||
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.
|
||||
its original value will be overwritten.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
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):
|
||||
Property names reserved by and used by magic:
|
||||
<DL>
|
||||
<DT> <B>GDS_FILE</B>
|
||||
<DD> The value is the name of a GDS file which contains the mask
|
||||
|
|
@ -117,14 +60,12 @@ 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
|
||||
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
|
||||
searched for the data bounds. This property is always of type
|
||||
<B>double</B>.
|
||||
searched for the data bounds.
|
||||
<DT> <B>GDS_END</B>
|
||||
<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
|
||||
in the file. If <B>GDS_START</B> is set to <B>0</B>, then this
|
||||
property may be omitted. This property is always of type
|
||||
<B>double</B>.
|
||||
property may be omitted.
|
||||
<DT> <B>LEFview</B>
|
||||
<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
|
||||
|
|
@ -156,8 +97,6 @@ Attach a "property" (string key and value pair) to the edit cell
|
|||
corresponding to the abutment box of the cell, in magic's internal
|
||||
units. The abutment box is automatically read from LEF files, but
|
||||
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>
|
||||
<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
|
||||
|
|
@ -165,8 +104,7 @@ Attach a "property" (string key and value pair) to the edit cell
|
|||
will be entirely covered in obstruction layers (unless cut-outs
|
||||
are required to accommodate pins). Any set-back applied by the
|
||||
"lef write -hide <value>" option will be applied to this obstruction
|
||||
box. This property is always of type <B>dimension</B> and must
|
||||
contain exactly four values.
|
||||
box.
|
||||
<DT> <B>flatten</B>
|
||||
<DD> This property is used in conjunction with the "flatten -doproperty"
|
||||
command option and marks the cell for flattening. Cells without
|
||||
|
|
@ -208,8 +146,7 @@ Attach a "property" (string key and value pair) to the edit cell
|
|||
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,
|
||||
such that <I>type</I> could be defined as the absence of a mask layer,
|
||||
for example. This property is always of type <B>dimension</B> and
|
||||
must have a multiple of four values.
|
||||
for example.
|
||||
</DL>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
|
@ -220,11 +157,6 @@ Attach a "property" (string key and value pair) to the edit cell
|
|||
the cell definition structure.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3>See Also:</H3>
|
||||
<BLOCKQUOTE>
|
||||
<A HREF=units.html><B>units</B></A> <BR>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P><IMG SRC=graphics/line1.gif><P>
|
||||
<TABLE BORDER=0>
|
||||
<TR>
|
||||
|
|
|
|||
|
|
@ -39,15 +39,21 @@ in the selected grid.
|
|||
feature size, and <B>user</B>, based on the value given by the
|
||||
user to the <B>grid</B> command. <P>
|
||||
|
||||
Historically, in addition to changing the behavior of the box
|
||||
to mouse button events, the <B>snap</B> command also changed
|
||||
the way that <A HREF=distance.html>distance measurements</A>
|
||||
are interpreted in commands that take distance arguments.
|
||||
This behavior remains the default for backwards compatibility.
|
||||
The <B>units</B> command overrides this behavior and allows
|
||||
<B>snap</B> to control only the box positioning behavior,
|
||||
independently of how unsuffixed values are parsed by the
|
||||
interpreter. <P>
|
||||
In addition to changing the behavior of the box to mouse
|
||||
button events, the <B>snap</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 snap grid. 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). 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
|
||||
type. <P>
|
||||
|
|
@ -74,7 +80,6 @@ in the selected grid.
|
|||
|
||||
<H3>See Also:</H3>
|
||||
<BLOCKQUOTE>
|
||||
<A HREF=units.html><B>units</B></A> <BR>
|
||||
<A HREF=grid.html><B>grid</B></A> <BR>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,7 @@ Unexpand everything inside or touching the cursor box.
|
|||
|
||||
<H3>Usage:</H3>
|
||||
<BLOCKQUOTE>
|
||||
<B>unexpand</B> [<B>selection</B>|<B>surround</B>|<B>overlap</B>|<B>all</B>]
|
||||
<BR><BR>
|
||||
<B>unexpand</B> <BR><BR>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3>Shortcuts:</H3>
|
||||
|
|
@ -38,23 +37,8 @@ Unexpand everything inside or touching the cursor box.
|
|||
<BLOCKQUOTE>
|
||||
The <B>unexpand</B> command unexpands the view of subcells to
|
||||
hide the contents of the subcells and show the bounding box
|
||||
outline only.
|
||||
|
||||
Option <B>overlap</B> unexpands all expanded subcells that
|
||||
overlap with the cursor box in the layout window. <P>
|
||||
|
||||
Option <B>surround</B> unexpands all expanded subcells that
|
||||
are completely surrounded by the cursor box in the layout window. <P>
|
||||
|
||||
Option <B>all</B> unexpands all subcells in the layout window. <P>
|
||||
|
||||
Option <B>selection</B> operates on the current selection, not
|
||||
relative to the cursor box, unexpanding all selected cells. <P>
|
||||
|
||||
With no arguments, the <B>unexpand</B> command behaves like
|
||||
<B>unexpand surround</B>, for backwards-compatible behavior with
|
||||
earlier versions of magic which did not offer the options.
|
||||
|
||||
outline only. The <B>unexpand</B> command unexpands all subcells
|
||||
that touch or intersect the cursor box in the layout window. <P>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H3>Implementation Notes:</H3>
|
||||
|
|
|
|||
|
|
@ -1,102 +0,0 @@
|
|||
<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,12 +45,10 @@ view [get|bbox|llx lly urx ury]
|
|||
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,
|
||||
in the coordinate system of the layout (according to the units
|
||||
set by the "units" command). <P>
|
||||
in the coordinate system of the layout. <P>
|
||||
|
||||
<B>view get</B> returns the coordinates of the screen limits in
|
||||
the coordinate system of the layout (according to the units set
|
||||
by the "units" command). <P>
|
||||
the coordinate system of the layout (internal database units). <P>
|
||||
|
||||
<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
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ extern int drcArrayYankFunc(), drcArrayOverlapFunc();
|
|||
static DRCCookie drcArrayCookie = {
|
||||
0, 0, 0, 0,
|
||||
{ {0} }, { {0} },
|
||||
0, DRC_EXCEPTION_NONE, 0, 0,
|
||||
0, 0, 0,
|
||||
DRC_ARRAY_OVERLAP_TAG,
|
||||
(DRCCookie *) NULL
|
||||
};
|
||||
|
|
|
|||
171
drc/DRCbasic.c
171
drc/DRCbasic.c
|
|
@ -27,8 +27,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include <stdio.h>
|
||||
#include <string.h> // for memcpy()
|
||||
#include <math.h> // for sqrt() for diagonal check
|
||||
|
||||
#include "tcltk/tclmagic.h"
|
||||
#include "utils/magic.h"
|
||||
#include "utils/geometry.h"
|
||||
#include "tiles/tile.h"
|
||||
|
|
@ -38,9 +36,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "utils/signals.h"
|
||||
#include "utils/maxrect.h"
|
||||
#include "utils/malloc.h"
|
||||
#include "utils/undo.h"
|
||||
#include "textio/textio.h"
|
||||
#include "cif/CIFint.h"
|
||||
|
||||
int dbDRCDebug = 0;
|
||||
|
||||
|
|
@ -52,7 +48,7 @@ int dbDRCDebug = 0;
|
|||
static DRCCookie drcOverlapCookie = {
|
||||
0, 0, 0, 0,
|
||||
{ {0} }, { {0} },
|
||||
0, DRC_EXCEPTION_NONE, 0, 0,
|
||||
0, 0, 0,
|
||||
DRC_OVERLAP_TAG,
|
||||
(DRCCookie *) NULL
|
||||
};
|
||||
|
|
@ -66,33 +62,7 @@ extern MaxRectsData *drcCanonicalMaxwidth();
|
|||
/*
|
||||
*-----------------------------------------------------------------------
|
||||
*
|
||||
* 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 --
|
||||
* drcCifPointToSegment
|
||||
*
|
||||
* Euclidean-distance point-to-segment distance (squared)
|
||||
* calculation (borrowed from XCircuit)
|
||||
|
|
@ -170,9 +140,8 @@ drcCifPointToSegment(px, py, s1x, s1y, s2x, s2y)
|
|||
*/
|
||||
|
||||
int
|
||||
areaCheck(tile, dinfo, arg)
|
||||
areaCheck(tile, arg)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
struct drcClientData *arg;
|
||||
{
|
||||
Rect rect; /* Area where error is to be recorded. */
|
||||
|
|
@ -226,7 +195,7 @@ areaCheck(tile, dinfo, arg)
|
|||
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||
return 0;
|
||||
else if (IsSplit(tile) && !SplitDirection(tile) && !(dinfo & TT_SIDE))
|
||||
else if (IsSplit(tile) && !SplitDirection(tile) && !SplitSide(tile))
|
||||
{
|
||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
||||
arg->dCD_constraint->r_ytop - sdist,
|
||||
|
|
@ -241,7 +210,7 @@ areaCheck(tile, dinfo, arg)
|
|||
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||
return 0;
|
||||
else if (IsSplit(tile) && SplitDirection(tile) && (dinfo & TT_SIDE))
|
||||
else if (IsSplit(tile) && SplitDirection(tile) && SplitSide(tile))
|
||||
{
|
||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
||||
arg->dCD_constraint->r_ytop - sdist,
|
||||
|
|
@ -257,7 +226,7 @@ areaCheck(tile, dinfo, arg)
|
|||
+ sdist - rect.r_ytop) >= 0)
|
||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||
return 0;
|
||||
else if (IsSplit(tile) && SplitDirection(tile) && !(dinfo & TT_SIDE))
|
||||
else if (IsSplit(tile) && SplitDirection(tile) && !SplitSide(tile))
|
||||
{
|
||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
||||
arg->dCD_constraint->r_ybot + sdist,
|
||||
|
|
@ -273,7 +242,7 @@ areaCheck(tile, dinfo, arg)
|
|||
+ sdist - rect.r_ytop) >= 0)
|
||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||
return 0;
|
||||
else if (IsSplit(tile) && !SplitDirection(tile) && (dinfo & TT_SIDE))
|
||||
else if (IsSplit(tile) && !SplitDirection(tile) && SplitSide(tile))
|
||||
{
|
||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
||||
arg->dCD_constraint->r_ybot + sdist,
|
||||
|
|
@ -337,9 +306,8 @@ areaCheck(tile, dinfo, arg)
|
|||
*/
|
||||
|
||||
int
|
||||
areaNMReject(tile, dinfo, arg)
|
||||
areaNMReject(tile, arg)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
ClientData *arg;
|
||||
{
|
||||
Tile *checktile = (Tile *)arg;
|
||||
|
|
@ -369,9 +337,8 @@ areaNMReject(tile, dinfo, arg)
|
|||
*/
|
||||
|
||||
int
|
||||
areaNMCheck(tile, dinfo, arg)
|
||||
areaNMCheck(tile, arg)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
struct drcClientData *arg;
|
||||
{
|
||||
Rect rect; /* Area where error is to be recorded. */
|
||||
|
|
@ -408,8 +375,7 @@ areaNMCheck(tile, dinfo, arg)
|
|||
|
||||
TTMaskSetOnlyType(&mask, TiGetLeftType(tile));
|
||||
TTMaskSetType(&mask, TiGetRightType(tile));
|
||||
if (DBSrPaintNMArea((Tile *)tile, (Plane *)NULL,
|
||||
TiGetTypeExact(tile) | dinfo, arg->dCD_rlist,
|
||||
if (DBSrPaintNMArea((Tile *)tile, (Plane *)NULL, dinfo, arg->dCD_rlist,
|
||||
&mask, areaNMReject, (ClientData)tile) == 0)
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -498,26 +464,6 @@ DRCBasicCheck (celldef, checkRect, clipRect, function, cdata)
|
|||
DBResetTilePlane(celldef->cd_planes[planeNum], DRC_UNPROCESSED);
|
||||
(void) DBSrPaintArea ((Tile *) NULL, celldef->cd_planes[planeNum],
|
||||
checkRect, &DBAllTypeBits, drcTile, (ClientData) &arg);
|
||||
|
||||
#ifdef MAGIC_WRAPPER
|
||||
/* Execute pending Tcl events, so the DRC process doesn't block. */
|
||||
|
||||
/* WARNING: This code cannot be enabled until some method is
|
||||
* worked out to determine if any event resulted in a change
|
||||
* to the DRC check plane which would invalidate the current
|
||||
* search. If so, the search must end immediately and the
|
||||
* area being checked must be reinstated. The code was added
|
||||
* to see how it speeds up the response time of magic when
|
||||
* some of the DRC rules are compute-intensive. It speeds up
|
||||
* performance enough that it is worthwhile to implement the
|
||||
* method just mentioned.
|
||||
*/
|
||||
#if 0
|
||||
UndoEnable();
|
||||
while (Tcl_DoOneEvent(TCL_DONT_WAIT));
|
||||
UndoDisable();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
drcCifCheck(&arg);
|
||||
if (arg.dCD_rlist != NULL) freeMagic(arg.dCD_rlist);
|
||||
|
|
@ -546,9 +492,8 @@ DRCBasicCheck (celldef, checkRect, clipRect, function, cdata)
|
|||
*/
|
||||
|
||||
int
|
||||
drcTile (tile, dinfo, arg)
|
||||
Tile *tile; /* Tile being examined */
|
||||
TileType dinfo; /* Split tile information */
|
||||
drcTile (tile, arg)
|
||||
Tile *tile; /* Tile being examined */
|
||||
struct drcClientData *arg;
|
||||
{
|
||||
DRCCookie *cptr; /* Current design rule on list */
|
||||
|
|
@ -588,7 +533,7 @@ drcTile (tile, dinfo, arg)
|
|||
/* DRC searches only one direction on regular tiles, the split */
|
||||
/* tiles are only processed for one of the two cases. */
|
||||
|
||||
if (IsSplit(tile) && !(dinfo & TT_SIDE))
|
||||
if (IsSplit(tile) && !SplitSide(tile))
|
||||
{
|
||||
int deltax, deltay;
|
||||
TileType tt, to;
|
||||
|
|
@ -610,7 +555,7 @@ drcTile (tile, dinfo, arg)
|
|||
{
|
||||
int deltax, deltay, w, h;
|
||||
double r;
|
||||
TileType newdinfo, dsplit;
|
||||
TileType dinfo, dsplit;
|
||||
|
||||
/* Work to be done: Handle triggering rules for non-Manhattan */
|
||||
/* edges; especially important for the wide-spacing rule. */
|
||||
|
|
@ -660,7 +605,7 @@ drcTile (tile, dinfo, arg)
|
|||
|
||||
if (SplitDirection(tile) == 0) deltay = -deltay;
|
||||
|
||||
newdinfo = TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION);
|
||||
dinfo = TiGetTypeExact(tile) & (TT_DIAGONAL | TT_DIRECTION);
|
||||
if (!(cptr->drcc_flags & DRC_REVERSE))
|
||||
{
|
||||
/* Forward case is behind the triangle */
|
||||
|
|
@ -668,19 +613,19 @@ drcTile (tile, dinfo, arg)
|
|||
deltay = -deltay;
|
||||
|
||||
/* Split side changes in the reverse case */
|
||||
newdinfo |= TT_SIDE;
|
||||
dinfo |= TT_SIDE;
|
||||
}
|
||||
|
||||
/* The area to check is bounded between the diagonals of
|
||||
* tile and errRect (which is the tile area, offset).
|
||||
* Pass errRect and newdinfo to areaNMCheck using the
|
||||
* Pass errRect and dinfo to areaNMCheck using the
|
||||
* ClientData structure arg->dCD_rlist and arg->dCD_entries,
|
||||
* which are not used by areaNMCheck.
|
||||
*/
|
||||
arg->dCD_rlist = (Rect *)mallocMagic(sizeof(Rect));
|
||||
*(arg->dCD_rlist) = errRect;
|
||||
arg->dCD_entries = newdinfo;
|
||||
if (newdinfo & TT_SIDE)
|
||||
arg->dCD_entries = dinfo;
|
||||
if (dinfo & TT_SIDE)
|
||||
arg->dCD_entries &= ~TT_SIDE;
|
||||
else
|
||||
arg->dCD_entries |= TT_SIDE;
|
||||
|
|
@ -692,7 +637,7 @@ drcTile (tile, dinfo, arg)
|
|||
errRect.r_ytop += deltay;
|
||||
|
||||
DBSrPaintNMArea((Tile *) NULL,
|
||||
arg->dCD_celldef->cd_planes[cptr->drcc_plane], newdinfo,
|
||||
arg->dCD_celldef->cd_planes[cptr->drcc_plane], dinfo,
|
||||
&errRect, &tmpMask, areaNMCheck, (ClientData) arg);
|
||||
|
||||
arg->dCD_entries = 0;
|
||||
|
|
@ -777,44 +722,6 @@ drcTile (tile, dinfo, arg)
|
|||
for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL;
|
||||
cptr = cptr->drcc_next)
|
||||
{
|
||||
/* Handle rule exceptions and exemptions */
|
||||
if (cptr->drcc_exception != DRC_EXCEPTION_NONE)
|
||||
{
|
||||
PropertyRecord *proprec;
|
||||
bool propfound, isinside = FALSE;
|
||||
char *name;
|
||||
int idx = cptr->drcc_exception & ~DRC_EXCEPTION_MASK;
|
||||
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 & DRC_EXCEPTION_MASK) == 0))
|
||||
continue;
|
||||
if (isinside && ((cptr->drcc_exception & DRC_EXCEPTION_MASK) != 0))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */
|
||||
/* the code above for non-Manhattan shapes and do not */
|
||||
/* need to be processed again. */
|
||||
|
|
@ -1224,44 +1131,6 @@ drcTile (tile, dinfo, arg)
|
|||
for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL;
|
||||
cptr = cptr->drcc_next)
|
||||
{
|
||||
/* Handle rule exceptions and exemptions */
|
||||
if (cptr->drcc_exception != DRC_EXCEPTION_NONE)
|
||||
{
|
||||
PropertyRecord *proprec;
|
||||
bool propfound, isinside = FALSE;
|
||||
char *name;
|
||||
int idx = cptr->drcc_exception & ~DRC_EXCEPTION_MASK;
|
||||
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_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 & DRC_EXCEPTION_MASK) == 0))
|
||||
continue;
|
||||
if (isinside && ((cptr->drcc_exception & DRC_EXCEPTION_MASK) != 0))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */
|
||||
/* the code above for non-Manhattan shapes and do not */
|
||||
/* need to be processed again. */
|
||||
|
|
|
|||
20
drc/DRCcif.c
20
drc/DRCcif.c
|
|
@ -603,9 +603,8 @@ drcCifCheck(arg)
|
|||
*/
|
||||
|
||||
int
|
||||
drcCifTile (tile, dinfo, arg)
|
||||
Tile *tile; /* Tile being examined */
|
||||
TileType dinfo; /* Split tile information */
|
||||
drcCifTile (tile, arg)
|
||||
Tile *tile; /* Tile being examined */
|
||||
struct drcClientData *arg;
|
||||
{
|
||||
DRCCookie *cptr; /* Current design rule on list */
|
||||
|
|
@ -629,7 +628,7 @@ drcCifTile (tile, dinfo, arg)
|
|||
/* check. */
|
||||
|
||||
if (IsSplit(tile))
|
||||
if (dinfo & TT_SIDE)
|
||||
if (SplitSide(tile))
|
||||
goto tbcheck;
|
||||
|
||||
/*
|
||||
|
|
@ -827,7 +826,7 @@ tbcheck:
|
|||
/* bottom check. */
|
||||
|
||||
if (IsSplit(tile))
|
||||
if (((dinfo & TT_SIDE) ? 1 : 0) == SplitDirection(tile))
|
||||
if (SplitSide(tile) == SplitDirection(tile))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
|
@ -1032,9 +1031,8 @@ tbcheck:
|
|||
*/
|
||||
|
||||
int
|
||||
areaCifCheck(tile, dinfo, arg)
|
||||
areaCifCheck(tile, arg)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
struct drcClientData *arg;
|
||||
{
|
||||
Rect rect; /* Area where error is to be recorded. */
|
||||
|
|
@ -1087,7 +1085,7 @@ areaCifCheck(tile, dinfo, arg)
|
|||
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||
return 0;
|
||||
else if (IsSplit(tile) && !SplitDirection(tile) && !(dinfo & TT_SIDE))
|
||||
else if (IsSplit(tile) && !SplitDirection(tile) && !SplitSide(tile))
|
||||
{
|
||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
||||
arg->dCD_constraint->r_ytop - sdist,
|
||||
|
|
@ -1102,7 +1100,7 @@ areaCifCheck(tile, dinfo, arg)
|
|||
- arg->dCD_constraint->r_ytop + sdist) >= 0)
|
||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||
return 0;
|
||||
else if (IsSplit(tile) && SplitDirection(tile) && (dinfo & TT_SIDE))
|
||||
else if (IsSplit(tile) && SplitDirection(tile) && SplitSide(tile))
|
||||
{
|
||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
||||
arg->dCD_constraint->r_ytop - sdist,
|
||||
|
|
@ -1118,7 +1116,7 @@ areaCifCheck(tile, dinfo, arg)
|
|||
+ sdist - cifrect.r_ytop) >= 0)
|
||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||
return 0;
|
||||
else if (IsSplit(tile) && SplitDirection(tile) && !(dinfo & TT_SIDE))
|
||||
else if (IsSplit(tile) && SplitDirection(tile) && !SplitSide(tile))
|
||||
{
|
||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xbot + sdist,
|
||||
arg->dCD_constraint->r_ybot + sdist,
|
||||
|
|
@ -1134,7 +1132,7 @@ areaCifCheck(tile, dinfo, arg)
|
|||
+ sdist - cifrect.r_ytop) >= 0)
|
||||
&& ((sqx * sqx + sqy * sqy) >= ssdist))
|
||||
return 0;
|
||||
else if (IsSplit(tile) && !SplitDirection(tile) && (dinfo & TT_SIDE))
|
||||
else if (IsSplit(tile) && !SplitDirection(tile) && SplitSide(tile))
|
||||
{
|
||||
sstest = drcCifPointToSegment(arg->dCD_constraint->r_xtop - sdist,
|
||||
arg->dCD_constraint->r_ybot + sdist,
|
||||
|
|
|
|||
|
|
@ -639,10 +639,9 @@ checkDone:
|
|||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
drcCheckTile(tile, dinfo, arg)
|
||||
Tile *tile; /* Tile in DRC_CHECK plane */
|
||||
TileType dinfo; /* Split tile information (unused) */
|
||||
ClientData arg; /* Not used. */
|
||||
drcCheckTile(tile, arg)
|
||||
Tile * tile; /* tile in DRC_CHECK plane */
|
||||
ClientData arg; /* Not used. */
|
||||
{
|
||||
Rect square; /* Square area of the checkerboard
|
||||
* being processed right now.
|
||||
|
|
@ -768,15 +767,13 @@ drcCheckTile(tile, dinfo, arg)
|
|||
*/
|
||||
|
||||
int
|
||||
drcXorFunc(tile, dinfo, clientdata)
|
||||
drcXorFunc(tile)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
ClientData clientdata;
|
||||
{
|
||||
Rect area;
|
||||
|
||||
TiToRect(tile, &area);
|
||||
DBNMPaintPlane(drcDisplayPlane, dinfo, &area, drcXorTable, (PaintUndoInfo *) NULL);
|
||||
DBPaintPlane(drcDisplayPlane, &area, drcXorTable, (PaintUndoInfo *) NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -785,15 +782,14 @@ drcXorFunc(tile, dinfo, clientdata)
|
|||
*/
|
||||
|
||||
int
|
||||
drcPutBackFunc(tile, dinfo, cellDef)
|
||||
drcPutBackFunc(tile, cellDef)
|
||||
Tile *tile; /* Error tile, from drcTempPlane. */
|
||||
TileType dinfo; /* Split tile information */
|
||||
CellDef *cellDef; /* Celldef in which to paint error. */
|
||||
{
|
||||
Rect area;
|
||||
|
||||
TiToRect(tile, &area);
|
||||
DBNMPaintPlane(cellDef->cd_planes[PL_DRC_ERROR], dinfo, &area,
|
||||
DBPaintPlane(cellDef->cd_planes[PL_DRC_ERROR], &area,
|
||||
DBStdPaintTbl(TiGetType(tile), PL_DRC_ERROR),
|
||||
(PaintUndoInfo *) NULL);
|
||||
return 0;
|
||||
|
|
@ -820,9 +816,8 @@ drcPutBackFunc(tile, dinfo, cellDef)
|
|||
*/
|
||||
|
||||
int
|
||||
drcIncludeArea(tile, dinfo, rect)
|
||||
drcIncludeArea(tile, rect)
|
||||
Tile *tile;
|
||||
TileType dinfo; /* (unused) */
|
||||
Rect *rect; /* Rectangle in which to record total area. */
|
||||
{
|
||||
Rect dum;
|
||||
|
|
|
|||
|
|
@ -468,9 +468,8 @@ drcCheckRectSize(starttile, arg, cptr)
|
|||
|
||||
int
|
||||
MaxRectsExclude(
|
||||
Tile *tile, /* (unused) */
|
||||
TileType dinfo, /* (unused) */
|
||||
ClientData clientdata) /* (unused) */
|
||||
Tile *tile,
|
||||
ClientData clientdata)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,9 +184,9 @@ drcSubstitute (cptr)
|
|||
DRCCookie * cptr; /* Design rule violated */
|
||||
{
|
||||
static char *why_out = NULL;
|
||||
char *whyptr, *sptr, *wptr, *vptr;
|
||||
int subscnt = 0, whylen, saveunits;
|
||||
float value;
|
||||
char *whyptr, *sptr, *wptr;
|
||||
int subscnt = 0, whylen;
|
||||
float oscale, value;
|
||||
extern float CIFGetOutputScale();
|
||||
|
||||
whyptr = DRCCurStyle->DRCWhyList[cptr->drcc_tag];
|
||||
|
|
@ -203,14 +203,10 @@ drcSubstitute (cptr)
|
|||
why_out = (char *)mallocMagic(whylen * sizeof(char));
|
||||
strcpy(why_out, whyptr);
|
||||
|
||||
/* For backwards compatibility: If the units are set to "default",
|
||||
* then print the DRC value in microns, with units, which is how
|
||||
* the output was previously presented.
|
||||
*/
|
||||
saveunits = DBWUnits;
|
||||
if (saveunits == DBW_UNITS_DEFAULT)
|
||||
DBWUnits = DBW_UNITS_MICRONS | DBW_UNITS_PRINT_FLAG;
|
||||
|
||||
if (cptr->drcc_flags & DRC_CIFRULE)
|
||||
oscale = CIFGetScale(100); /* 100 = microns to centimicrons */
|
||||
else
|
||||
oscale = CIFGetOutputScale(1000); /* 1000 for conversion to um */
|
||||
wptr = why_out;
|
||||
|
||||
while ((sptr = strchr(whyptr, '%')) != NULL)
|
||||
|
|
@ -222,29 +218,21 @@ drcSubstitute (cptr)
|
|||
switch (*(sptr + 1))
|
||||
{
|
||||
case 'd':
|
||||
if (cptr->drcc_flags & DRC_CIFRULE)
|
||||
vptr = DBWPrintCIFValue(cptr->drcc_dist, (MagWindow *)NULL, TRUE);
|
||||
else
|
||||
vptr = DBWPrintValue(cptr->drcc_dist, (MagWindow *)NULL, TRUE);
|
||||
snprintf(wptr, 20, "%s", vptr);
|
||||
/* Replace with "dist" value in microns */
|
||||
value = (float)cptr->drcc_dist * oscale;
|
||||
snprintf(wptr, 20, "%01.3gum", value);
|
||||
wptr += strlen(wptr);
|
||||
break;
|
||||
case 'c':
|
||||
/* Replace with "cdist" value in microns */
|
||||
if (cptr->drcc_flags & DRC_CIFRULE)
|
||||
vptr = DBWPrintCIFValue(cptr->drcc_cdist, (MagWindow *)NULL, TRUE);
|
||||
else
|
||||
vptr = DBWPrintValue(cptr->drcc_cdist, (MagWindow *)NULL, TRUE);
|
||||
snprintf(wptr, 20, "%s", vptr);
|
||||
value = (float)cptr->drcc_cdist * oscale;
|
||||
snprintf(wptr, 20, "%01.3gum", value);
|
||||
wptr += strlen(wptr);
|
||||
break;
|
||||
case 'a':
|
||||
/* Replace with "cdist" value in microns squared */
|
||||
if (cptr->drcc_flags & DRC_CIFRULE)
|
||||
vptr = DBWPrintCIFSqValue(cptr->drcc_cdist, (MagWindow *)NULL);
|
||||
else
|
||||
vptr = DBWPrintSqValue(cptr->drcc_cdist, (MagWindow *)NULL);
|
||||
snprintf(wptr, 20, "%s", vptr);
|
||||
value = (float)cptr->drcc_cdist * oscale * oscale;
|
||||
snprintf(wptr, 20, "%01.4gum^2", value);
|
||||
wptr += strlen(wptr);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -257,7 +245,6 @@ drcSubstitute (cptr)
|
|||
/* copy remainder of string (including trailing null) */
|
||||
strncpy(wptr, whyptr, strlen(whyptr) + 1);
|
||||
|
||||
DBWUnits = saveunits;
|
||||
return why_out;
|
||||
}
|
||||
|
||||
|
|
@ -438,8 +425,6 @@ drcListallError (celldef, rect, cptr, scx)
|
|||
}
|
||||
if (drcsave == DRCErrorCount)
|
||||
{
|
||||
char *rllx, *rlly, *rurx, *rury;
|
||||
|
||||
DRCErrorCount += 1;
|
||||
h = HashFind(&DRCErrorTable, drcSubstitute(cptr));
|
||||
lobj = (Tcl_Obj *) HashGetValue(h);
|
||||
|
|
@ -448,15 +433,10 @@ drcListallError (celldef, rect, cptr, scx)
|
|||
|
||||
pobj = Tcl_NewListObj(0, NULL);
|
||||
|
||||
rllx = DBWPrintValue(r.r_xbot, (MagWindow *)NULL, TRUE);
|
||||
rlly = DBWPrintValue(r.r_ybot, (MagWindow *)NULL, FALSE);
|
||||
rurx = DBWPrintValue(r.r_xtop, (MagWindow *)NULL, TRUE);
|
||||
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, pobj, Tcl_NewIntObj(r.r_xbot));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_ybot));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_xtop));
|
||||
Tcl_ListObjAppendElement(magicinterp, pobj, Tcl_NewIntObj(r.r_ytop));
|
||||
Tcl_ListObjAppendElement(magicinterp, lobj, pobj);
|
||||
|
||||
HashSetValue(h, lobj);
|
||||
|
|
@ -977,10 +957,9 @@ drcCountFunc(scx, dupTable)
|
|||
}
|
||||
|
||||
int
|
||||
drcCountFunc2(tile, dinfo, countptr)
|
||||
Tile *tile; /* Tile found in error plane. */
|
||||
TileType dinfo; /* Split tile information (unused) */
|
||||
int *countptr; /* Address of count word. */
|
||||
drcCountFunc2(tile, countptr)
|
||||
Tile *tile; /* Tile found in error plane. */
|
||||
int *countptr; /* Address of count word. */
|
||||
{
|
||||
if (TiGetType(tile) != (TileType) TT_SPACE) (*countptr)++;
|
||||
return 0;
|
||||
|
|
@ -1127,9 +1106,8 @@ drcFindFunc(scx, finddata)
|
|||
}
|
||||
|
||||
int
|
||||
drcFindFunc2(tile, dinfo, finddata)
|
||||
drcFindFunc2(tile, finddata)
|
||||
Tile *tile; /* Tile in error plane. */
|
||||
TileType dinfo; /* Split tile information (unused) */
|
||||
Sindx *finddata; /* Information about error to find */
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ static ClientData drcSubClientData; /* To be passed to error function. */
|
|||
static DRCCookie drcSubcellCookie = {
|
||||
0, 0, 0, 0,
|
||||
{ {0} }, { {0} },
|
||||
0, DRC_EXCEPTION_NONE, 0, 0,
|
||||
0, 0, 0,
|
||||
DRC_SUBCELL_OVERLAP_TAG,
|
||||
(DRCCookie *) NULL
|
||||
};
|
||||
|
|
@ -65,7 +65,7 @@ static DRCCookie drcSubcellCookie = {
|
|||
static DRCCookie drcInSubCookie = {
|
||||
0, 0, 0, 0,
|
||||
{ {0} }, { {0} },
|
||||
0, DRC_EXCEPTION_NONE, 0, 0,
|
||||
0, 0, 0,
|
||||
DRC_IN_SUBCELL_TAG,
|
||||
(DRCCookie *) NULL
|
||||
};
|
||||
|
|
@ -79,7 +79,7 @@ static DRCCookie drcInSubCookie = {
|
|||
static DRCCookie drcOffGridCookie = {
|
||||
0, 0, 0, 0,
|
||||
{ {0} }, { {0} },
|
||||
0, DRC_EXCEPTION_NONE, 0, 0,
|
||||
0, 0, 0,
|
||||
DRC_OFFGRID_TAG,
|
||||
(DRCCookie *) NULL
|
||||
};
|
||||
|
|
@ -158,9 +158,8 @@ drcFindOtherCells(use, dlu)
|
|||
*/
|
||||
|
||||
int
|
||||
drcSubCopyErrors(tile, dinfo, cxp)
|
||||
drcSubCopyErrors(tile, cxp)
|
||||
Tile *tile;
|
||||
TileType dinfo; /* (unused) */
|
||||
TreeContext *cxp;
|
||||
{
|
||||
Rect area;
|
||||
|
|
@ -318,9 +317,7 @@ drcSubcellFunc(subUse, dsa)
|
|||
*/
|
||||
|
||||
int
|
||||
drcAlwaysOne(Tile *tile,
|
||||
TileType dinfo,
|
||||
ClientData clientdata)
|
||||
drcAlwaysOne()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -422,6 +419,7 @@ DRCFindInteractions(def, area, radius, interaction)
|
|||
CellUse *use;
|
||||
SearchContext scx;
|
||||
Rect searchArea, intArea;
|
||||
int flags;
|
||||
struct drcSubcellArg dsa;
|
||||
struct drcLinkedUse *curDLU;
|
||||
|
||||
|
|
@ -494,21 +492,24 @@ DRCFindInteractions(def, area, radius, interaction)
|
|||
/* If errors are being propagated up from child to parent, */
|
||||
/* then the interaction area is always valid. */
|
||||
|
||||
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
|
||||
if (!(flags & PROPAGATE_FLAG))
|
||||
{
|
||||
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[i],
|
||||
&intArea, &DBAllButSpaceBits, drcAlwaysOne,
|
||||
(ClientData) NULL) != 0)
|
||||
for (i = PL_TECHDEPBASE; i < DBNumPlanes; i++)
|
||||
{
|
||||
use = (CellUse *) -1;
|
||||
break;
|
||||
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[i],
|
||||
&intArea, &DBAllButSpaceBits, drcAlwaysOne,
|
||||
(ClientData) NULL) != 0)
|
||||
{
|
||||
use = (CellUse *) -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
scx.scx_use = DRCDummyUse;
|
||||
scx.scx_trans = GeoIdentityTransform;
|
||||
scx.scx_area = intArea;
|
||||
if (DBTreeSrCells(&scx, 0, drcSubCheckPaint, (ClientData) &use) == 0)
|
||||
return 0;
|
||||
}
|
||||
scx.scx_use = DRCDummyUse;
|
||||
scx.scx_trans = GeoIdentityTransform;
|
||||
scx.scx_area = intArea;
|
||||
if (DBTreeSrCells(&scx, 0, drcSubCheckPaint, (ClientData) &use) == 0)
|
||||
return 0;
|
||||
|
||||
/* OK, no more excuses, there's really an interaction area here. */
|
||||
|
||||
|
|
@ -539,9 +540,8 @@ DRCFindInteractions(def, area, radius, interaction)
|
|||
*/
|
||||
|
||||
int
|
||||
drcExactOverlapCheck(tile, dinfo, arg)
|
||||
drcExactOverlapCheck(tile, arg)
|
||||
Tile *tile; /* Tile to check. */
|
||||
TileType dinfo; /* Split tile information (unused) */
|
||||
struct drcClientData *arg; /* How to detect and process errors. */
|
||||
{
|
||||
Rect rect;
|
||||
|
|
@ -579,9 +579,8 @@ drcExactOverlapCheck(tile, dinfo, arg)
|
|||
*/
|
||||
|
||||
int
|
||||
drcExactOverlapTile(tile, dinfo, cxp)
|
||||
drcExactOverlapTile(tile, cxp)
|
||||
Tile *tile; /* Tile that must overlap exactly. */
|
||||
TileType dinfo; /* Split tile information (unused) */
|
||||
TreeContext *cxp; /* Tells how to translate out of subcell.
|
||||
* The client data must be a drcClientData
|
||||
* record, and the caller must have filled
|
||||
|
|
@ -826,7 +825,6 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
|
|||
*/
|
||||
subArea = *erasebox;
|
||||
GeoClip(&subArea, &cliparea);
|
||||
if (GEO_RECTNULL(&subArea)) continue;
|
||||
GEO_EXPAND(&subArea, DRCTechHalo, &intArea);
|
||||
|
||||
errorSaveType = DRCErrorType;
|
||||
|
|
|
|||
202
drc/DRCtech.c
202
drc/DRCtech.c
|
|
@ -72,12 +72,6 @@ static int drcRulesOptimized = 0;
|
|||
|
||||
static int DRCtag = 0;
|
||||
|
||||
/* Keep track of what rule exemption or exception is in effect
|
||||
* while reading the DRC tech file section.
|
||||
*/
|
||||
|
||||
static unsigned char drcCurException = DRC_EXCEPTION_NONE;
|
||||
|
||||
/*
|
||||
* Forward declarations.
|
||||
*/
|
||||
|
|
@ -85,7 +79,6 @@ int drcWidth(), drcSpacing(), drcEdge(), drcNoOverlap();
|
|||
int drcExactOverlap(), drcExtend();
|
||||
int drcSurround(), drcRectOnly(), drcOverhang();
|
||||
int drcStepSize(), drcOption(), drcOffGrid();
|
||||
int drcException(), drcExemption();
|
||||
int drcMaxwidth(), drcArea(), drcRectangle(), drcAngles();
|
||||
int drcCifSetStyle(), drcCifWidth(), drcCifSpacing();
|
||||
int drcCifMaxwidth(), drcCifArea();
|
||||
|
|
@ -308,12 +301,6 @@ drcTechFreeStyle()
|
|||
/* Clear the Why string list */
|
||||
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);
|
||||
DRCCurStyle = NULL;
|
||||
}
|
||||
|
|
@ -397,63 +384,6 @@ drcWhyCreate(whystring)
|
|||
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 an unsigned character containing
|
||||
* the index in the lower 7 bits and a high bit indicating if the rule
|
||||
* is an exception (0) or an exemption (1)).
|
||||
*
|
||||
* Side effects:
|
||||
* Adds to the DRCExceptionList if "name" has not been used before.
|
||||
* Calls StrDup() and increments DRCExceptionSize.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
unsigned 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 (unsigned char)i;
|
||||
|
||||
/* Note that i cannot be 127 as this is reserved for DRC_EXCEPTION_NONE */
|
||||
if (i > 126)
|
||||
{
|
||||
/* I would be shocked if this code ever got executed. */
|
||||
TxError("Error: Too many rule exceptions! Limit is 126.\n");
|
||||
return 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 (unsigned char)i;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -641,8 +571,6 @@ DRCTechStyleInit()
|
|||
DRCCurStyle->DRCStepSize = 0;
|
||||
DRCCurStyle->DRCFlags = (char)0;
|
||||
DRCCurStyle->DRCWhySize = 0;
|
||||
DRCCurStyle->DRCExceptionList = (char **)NULL;
|
||||
DRCCurStyle->DRCExceptionSize = 0;
|
||||
|
||||
HashInit(&DRCWhyErrorTable, 16, HT_STRINGKEYS);
|
||||
|
||||
|
|
@ -735,7 +663,6 @@ DRCTechStyleInit()
|
|||
}
|
||||
|
||||
drcCifInit();
|
||||
drcCurException = DRC_EXCEPTION_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1028,7 +955,6 @@ drcCifAssign(cookie, dist, next, mask, corner, tag, cdist, flags, planeto, plane
|
|||
(cookie)->drcc_plane = planeto;
|
||||
(cookie)->drcc_mod = 0;
|
||||
(cookie)->drcc_cmod = 0;
|
||||
(cookie)->drcc_exception = drcCurException;
|
||||
}
|
||||
|
||||
// This is like drcCifAssign, but checks for bad plane numbers in planeto and
|
||||
|
|
@ -1105,37 +1031,50 @@ DRCTechAddRule(sectionName, argc, argv)
|
|||
int (*rk_proc)(); /* Procedure implementing this keyword */
|
||||
const char *rk_err; /* Error message */
|
||||
} ruleKeys[] = {
|
||||
{"angles", 4, 4, drcAngles, "layers 45|90 why"},
|
||||
{"angles", 4, 4, drcAngles,
|
||||
"layers 45|90 why"},
|
||||
{"edge", 8, 10, drcEdge,
|
||||
"layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"},
|
||||
{"edge4way", 8, 10, drcEdge,
|
||||
"layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"},
|
||||
{"exact_overlap", 2, 2, drcExactOverlap, "layers"},
|
||||
{"exception", 2, 2, drcException, "name"},
|
||||
{"exemption", 2, 2, drcExemption, "name"},
|
||||
{"exact_overlap", 2, 2, drcExactOverlap,
|
||||
"layers"},
|
||||
{"extend", 5, 6, drcExtend,
|
||||
"layers1 layers2 distance [option] why"},
|
||||
{"no_overlap", 3, 3, drcNoOverlap, "layers1 layers2"},
|
||||
{"option", 2, 2, drcOption, "option_name option_value"},
|
||||
{"overhang", 5, 5, drcOverhang, "layers1 layers2 distance why"},
|
||||
{"rect_only", 3, 3, drcRectOnly, "layers why"},
|
||||
{"no_overlap", 3, 3, drcNoOverlap,
|
||||
"layers1 layers2"},
|
||||
{"option", 2, 2, drcOption,
|
||||
"option_name option_value"},
|
||||
{"overhang", 5, 5, drcOverhang,
|
||||
"layers1 layers2 distance why"},
|
||||
{"rect_only", 3, 3, drcRectOnly,
|
||||
"layers why"},
|
||||
{"spacing", 6, 7, drcSpacing,
|
||||
"layers1 layers2 separation [layers3] adjacency why"},
|
||||
{"stepsize", 2, 2, drcStepSize, "step_size"},
|
||||
{"stepsize", 2, 2, drcStepSize,
|
||||
"step_size"},
|
||||
{"surround", 6, 7, drcSurround,
|
||||
"layers1 layers2 distance presence why"},
|
||||
{"width", 4, 5, drcWidth, "layers width why"},
|
||||
{"width", 4, 5, drcWidth,
|
||||
"layers width why"},
|
||||
{"widespacing", 7, 8, drcSpacing,
|
||||
"layers1 width layers2 separation adjacency why"},
|
||||
{"area", 5, 5, drcArea, "layers area horizon why"},
|
||||
{"off_grid", 4, 4, drcOffGrid, "layers pitch why"},
|
||||
{"maxwidth", 4, 6, drcMaxwidth, "layers maxwidth bends why"},
|
||||
{"cifstyle", 2, 2, drcCifSetStyle, "cif_style"},
|
||||
{"cifwidth", 4, 4, drcCifWidth, "layers width why"},
|
||||
{"area", 5, 5, drcArea,
|
||||
"layers area horizon why"},
|
||||
{"off_grid", 4, 4, drcOffGrid,
|
||||
"layers pitch why"},
|
||||
{"maxwidth", 4, 6, drcMaxwidth,
|
||||
"layers maxwidth bends why"},
|
||||
{"cifstyle", 2, 2, drcCifSetStyle,
|
||||
"cif_style"},
|
||||
{"cifwidth", 4, 4, drcCifWidth,
|
||||
"layers width why"},
|
||||
{"cifspacing", 6, 6, drcCifSpacing,
|
||||
"layers1 layers2 separation adjacency why"},
|
||||
{"cifarea", 5, 5, drcCifArea, "layers area horizon why"},
|
||||
{"cifmaxwidth", 5, 5, drcCifMaxwidth, "layers maxwidth bends why"},
|
||||
{"cifarea", 5, 5, drcCifArea,
|
||||
"layers area horizon why"},
|
||||
{"cifmaxwidth", 5, 5, drcCifMaxwidth,
|
||||
"layers maxwidth bends why"},
|
||||
{"rectangle", 5, 5, drcRectangle,
|
||||
"layers maxwidth [even|odd|any] why"},
|
||||
{0}
|
||||
|
|
@ -1756,7 +1695,7 @@ drcMaxwidth(argc, argv)
|
|||
if (PlaneMaskHasPlane(pmask2, plane2))
|
||||
break;
|
||||
|
||||
if (PlaneMaskHasPlane(pmask, plane2))
|
||||
if (plane2 == plane)
|
||||
TechError("Warning: Exclude types for \"maxwidth\" are on the "
|
||||
"same plane and so cannot be checked.\n");
|
||||
}
|
||||
|
|
@ -3695,84 +3634,6 @@ drcRectangle(argc, argv)
|
|||
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 contains the index in
|
||||
* the lower 7 bits, and a flag in the upper bit (0 = exception rule,
|
||||
* 1 = exemption rule). The index can be recovered by masking off
|
||||
* the upper bit.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
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 = 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 = DRC_EXCEPTION_NONE;
|
||||
else
|
||||
drcCurException = drcExceptionCreate(argv[1]) | DRC_EXCEPTION_MASK;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -4258,7 +4119,6 @@ drcTechFinalStyle(style)
|
|||
if (dp->drcc_dist > next->drcc_dist) continue;
|
||||
if (dp->drcc_cdist > next->drcc_cdist) continue;
|
||||
if (dp->drcc_plane != next->drcc_plane) continue;
|
||||
if (dp->drcc_exception != next->drcc_exception) continue;
|
||||
if (dp->drcc_flags & DRC_REVERSE)
|
||||
{
|
||||
if (!(next->drcc_flags & DRC_REVERSE)) continue;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ typedef struct drccookie
|
|||
TileTypeBitMask drcc_mask; /* Legal types on RHS */
|
||||
TileTypeBitMask drcc_corner; /* Types that trigger corner check */
|
||||
unsigned short drcc_flags; /* Miscellaneous flags, see below. */
|
||||
unsigned char drcc_exception; /* Index to list of exceptions */
|
||||
int drcc_edgeplane; /* Plane of edge */
|
||||
int drcc_plane; /* Index of plane on which to check
|
||||
* legal types. */
|
||||
|
|
@ -92,11 +91,6 @@ typedef struct drccookie
|
|||
#define DRC_UNPROCESSED CLIENTDEFAULT
|
||||
#define DRC_PROCESSED 1
|
||||
|
||||
/* drcc_exception defaults to 255 meaning no exceptions/exemptions */
|
||||
#define DRC_EXCEPTION_NONE ((unsigned char)0xff)
|
||||
/* The high bit of the value determines if this is an exception or an exemption. */
|
||||
#define DRC_EXCEPTION_MASK ((unsigned char)0x80)
|
||||
|
||||
/*
|
||||
* Background DRC (DRC Idle proc) for Tcl-based Magic
|
||||
*/
|
||||
|
|
@ -183,8 +177,6 @@ typedef struct drcstyle
|
|||
unsigned short DRCFlags; /* Option flags */
|
||||
char **DRCWhyList; /* Indexed list of "why" text strings */
|
||||
int DRCWhySize; /* Length of DRCWhyList */
|
||||
char **DRCExceptionList; /* Indexed list of DRC exceptions */
|
||||
int DRCExceptionSize; /* Length of DRCExceptionList */
|
||||
PaintResultType DRCPaintTable[NP][NT][NT];
|
||||
} DRCStyle;
|
||||
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
|||
#include "dbwind/dbwind.h" /* for DBWclientID */
|
||||
#include "commands/commands.h" /* for module auto-load */
|
||||
#include "textio/txcommands.h"
|
||||
#include "extract/extract.h" /* for extDevTable */
|
||||
#include "extflat/extflat.h"
|
||||
#include "extflat/EFint.h"
|
||||
#include "extract/extract.h" /* for extDevTable */
|
||||
#include "utils/runstats.h"
|
||||
#include "utils/malloc.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -41,11 +41,14 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
|||
#include "commands/commands.h" /* for module auto-load */
|
||||
#include "textio/txcommands.h"
|
||||
#include "extflat/extflat.h"
|
||||
#include "extract/extract.h" /* for extDevTable */
|
||||
#include "extflat/EFint.h"
|
||||
#include "extract/extract.h" /* for extDevTable */
|
||||
#include "utils/runstats.h"
|
||||
#include "ext2spice/ext2spice.h"
|
||||
|
||||
/* C99 compat */
|
||||
#include "extflat/extflat.h"
|
||||
|
||||
/* These global values are defined in ext2spice.c */
|
||||
extern HashTable subcktNameTable;
|
||||
extern DQueue subcktNameQueue;
|
||||
|
|
@ -239,9 +242,20 @@ spcHierWriteParams(
|
|||
|
||||
/* 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]);
|
||||
while (plist != NULL)
|
||||
{
|
||||
if (checkme) TxPrintf("Plist entry %s %s\n", plist->parm_name, plist->parm_type);
|
||||
|
||||
switch (plist->parm_type[0])
|
||||
{
|
||||
case 'a':
|
||||
|
|
@ -342,6 +356,7 @@ spcHierWriteParams(
|
|||
// Check for device length vs. terminal length
|
||||
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);
|
||||
if (esScale < 0)
|
||||
fprintf(esSpiceF, "%g", l * scale);
|
||||
|
|
@ -356,8 +371,10 @@ spcHierWriteParams(
|
|||
{
|
||||
/* l1, l2, etc. used to indicate the length of the terminal */
|
||||
/* Find value in dev_params */
|
||||
if (checkme) TxPrintf("Handling entry l1 or l2\n");
|
||||
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) &&
|
||||
(dparam->parm_name[0] == 'l') &&
|
||||
(dparam->parm_name[1] == plist->parm_type[1]) &&
|
||||
|
|
@ -366,6 +383,8 @@ spcHierWriteParams(
|
|||
int dval;
|
||||
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);
|
||||
if (esScale < 0)
|
||||
fprintf(esSpiceF, "%g", dval * scale);
|
||||
|
|
@ -634,7 +653,7 @@ subcktHierVisit(
|
|||
|
||||
if (hasports || is_top)
|
||||
return subcktVisit(use, hierName, is_top);
|
||||
else if ((def->def_flags & DEF_NODEVICES) && (!isStub))
|
||||
else if (def->def_flags & DEF_NODEVICES)
|
||||
return 0;
|
||||
else
|
||||
return subcktVisit(use, hierName, is_top);
|
||||
|
|
@ -1088,7 +1107,6 @@ spcdevHierVisit(
|
|||
|
||||
if (!has_model)
|
||||
{
|
||||
fprintf(esSpiceF, " ");
|
||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
|
||||
}
|
||||
|
|
@ -1139,7 +1157,6 @@ spcdevHierVisit(
|
|||
|
||||
if (!has_model)
|
||||
{
|
||||
fprintf(esSpiceF, " ");
|
||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||
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 "commands/commands.h" /* for module auto-load */
|
||||
#include "textio/txcommands.h"
|
||||
#include "extract/extract.h" /* for extDevTable */
|
||||
#include "extflat/extflat.h"
|
||||
#include "extflat/EFint.h"
|
||||
#include "extract/extract.h" /* for extDevTable */
|
||||
#include "utils/runstats.h"
|
||||
|
||||
#include "ext2spice/ext2spice.h"
|
||||
|
|
@ -1689,43 +1689,23 @@ subcktVisit(
|
|||
HashStartSearch(&hs);
|
||||
while ((he = HashNext(&def->def_nodes, &hs)))
|
||||
{
|
||||
bool found = FALSE;
|
||||
|
||||
sname = (EFNodeName *) HashGetValue(he);
|
||||
if (sname == NULL) continue;
|
||||
snode = sname->efnn_node;
|
||||
|
||||
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)
|
||||
{
|
||||
if (found == TRUE) break;
|
||||
|
||||
portidx = nodeName->efnn_port;
|
||||
if (portidx < 0) continue;
|
||||
if (nodeList[portidx] == NULL)
|
||||
{
|
||||
nodeList[portidx] = nodeName;
|
||||
found = TRUE;
|
||||
}
|
||||
else if (EFHNBest(nodeName->efnn_hier, nodeList[portidx]->efnn_hier))
|
||||
{
|
||||
nodeList[portidx] = nodeName;
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1952,7 +1932,6 @@ topVisit(
|
|||
{
|
||||
char stmp[MAX_STR_SIZE];
|
||||
int portidx;
|
||||
bool found = FALSE;
|
||||
|
||||
sname = (EFNodeName *) HashGetValue(he);
|
||||
if (sname == NULL) continue; /* Should not happen */
|
||||
|
|
@ -1960,68 +1939,33 @@ topVisit(
|
|||
snode = sname->efnn_node;
|
||||
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)
|
||||
{
|
||||
if (found == TRUE) break;
|
||||
portidx = nodeName->efnn_port;
|
||||
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)
|
||||
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
|
||||
* the node. Otherwise, artifacts of the abstract view
|
||||
* may cause nodes to be merged and the names lost.
|
||||
*/
|
||||
|
||||
if (def->def_flags & DEF_ABSTRACT)
|
||||
{
|
||||
heh = HashLookOnly(&efNodeHashTable, (char *)nodeName->efnn_hier);
|
||||
|
||||
/* If view is abstract, rely on the given port name, not
|
||||
* the node. Otherwise, artifacts of the abstract view
|
||||
* may cause nodes to be merged and the names lost.
|
||||
*/
|
||||
EFHNSprintf(stmp, nodeName->efnn_hier);
|
||||
pname = stmp;
|
||||
}
|
||||
else
|
||||
// pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL);
|
||||
pname = nodeSpiceName(nodeName->efnn_hier, NULL);
|
||||
|
||||
if (heh == (HashEntry *)NULL) /* pname now resolved for log output */
|
||||
|
|
@ -2039,10 +1983,7 @@ topVisit(
|
|||
hep = HashFind(&portNameTable, pname);
|
||||
HashSetValue(hep, (ClientData)(pointertype)nodeName->efnn_port);
|
||||
if (sorted_ports[portidx] == NULL)
|
||||
{
|
||||
sorted_ports[portidx] = StrDup((char **)NULL, pname);
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -3140,7 +3081,6 @@ spcdevVisit(
|
|||
|
||||
if (!has_model)
|
||||
{
|
||||
fprintf(esSpiceF, " ");
|
||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
|
||||
}
|
||||
|
|
@ -3187,7 +3127,6 @@ spcdevVisit(
|
|||
|
||||
if (!has_model)
|
||||
{
|
||||
fprintf(esSpiceF, " ");
|
||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
|
||||
}
|
||||
|
|
@ -3375,15 +3314,12 @@ spcdevSubstrate(
|
|||
/* Canonical name */
|
||||
nn = (EFNodeName *) HashGetValue(he);
|
||||
if (outf)
|
||||
{
|
||||
const char *spicename;
|
||||
spicename = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier, NULL);
|
||||
fprintf(outf, "%s", spicename);
|
||||
}
|
||||
fprintf(outf, "%s", nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier,
|
||||
NULL));
|
||||
|
||||
/* Create node client if it doesn't exist */
|
||||
if ((nodeClient *)nn->efnn_node->efnode_client == (nodeClient *)NULL)
|
||||
initNodeClient(nn->efnn_node);
|
||||
initNodeClientHier(nn->efnn_node);
|
||||
|
||||
/* Mark node as visited (set bit one higher than number of resist classes) */
|
||||
if (esDistrJunct)
|
||||
|
|
|
|||
|
|
@ -754,9 +754,8 @@ antennacheckVisit(
|
|||
*/
|
||||
|
||||
int
|
||||
areaMarkFunc(tile, dinfo, ams)
|
||||
areaMarkFunc(tile, ams)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
AntennaMarkStruct *ams;
|
||||
{
|
||||
Rect rect;
|
||||
|
|
@ -779,9 +778,8 @@ areaMarkFunc(tile, dinfo, ams)
|
|||
*/
|
||||
|
||||
int
|
||||
areaAccumFunc(tile, dinfo, gdas)
|
||||
areaAccumFunc(tile, gdas)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
GateDiffAccumStruct *gdas;
|
||||
{
|
||||
Rect *rect = &(gdas->r);
|
||||
|
|
@ -790,7 +788,7 @@ areaAccumFunc(tile, dinfo, gdas)
|
|||
|
||||
/* Avoid double-counting the area of contacts */
|
||||
if (IsSplit(tile))
|
||||
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
type = SplitSide(tile) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
else
|
||||
type = TiGetType(tile);
|
||||
|
||||
|
|
@ -800,7 +798,6 @@ areaAccumFunc(tile, dinfo, gdas)
|
|||
|
||||
TiToRect(tile, rect);
|
||||
area = (dlong)(rect->r_xtop - rect->r_xbot) * (dlong)(rect->r_ytop - rect->r_ybot);
|
||||
if (IsSplit(tile)) area /= 2;
|
||||
gdas->accum += area;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -819,9 +816,8 @@ areaAccumFunc(tile, dinfo, gdas)
|
|||
*/
|
||||
|
||||
int
|
||||
antennaAccumFunc(tile, dinfo, aaptr)
|
||||
antennaAccumFunc(tile, aaptr)
|
||||
Tile *tile;
|
||||
TileType dinfo; /* Not used, but should be handled */
|
||||
AntennaAccumStruct *aaptr;
|
||||
{
|
||||
Rect *rect = &(aaptr->r);
|
||||
|
|
@ -1007,7 +1003,6 @@ antennaAccumFunc(tile, dinfo, aaptr)
|
|||
TiToRect(tile, rect);
|
||||
area = (dlong)(rect->r_xtop - rect->r_xbot)
|
||||
* (dlong)(rect->r_ytop - rect->r_ybot);
|
||||
if (IsSplit(tile)) area /= 2;
|
||||
|
||||
typeareas[type] += area;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,9 +34,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header$";
|
|||
#include "tiles/tile.h"
|
||||
#include "database/database.h" /* for TileType definition */
|
||||
#include "extflat/extflat.h"
|
||||
#include "extflat/extparse.h"
|
||||
#include "extflat/EFint.h"
|
||||
#include "extract/extract.h"
|
||||
#include "extract/extract.h" /* for device class list */
|
||||
#include "extract/extractInt.h" /* for extGetDevType() */
|
||||
|
||||
/* C99 compat */
|
||||
|
|
@ -648,21 +647,8 @@ efBuildEquiv(def, nodeName1, nodeName2, resist, isspice)
|
|||
return;
|
||||
}
|
||||
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);
|
||||
if (uptr1) *uptr1 = '_';
|
||||
if (uptr2) *uptr2 = '_';
|
||||
}
|
||||
else
|
||||
/* Do not merge the nodes when folding in extresist parasitics */
|
||||
return;
|
||||
|
|
@ -874,13 +860,13 @@ efBuildDevice(
|
|||
const Rect *r, /* Coordinates of 1x1 rectangle entirely inside device */
|
||||
int argc, /* Size of argv */
|
||||
char *argv[]) /* Tokens for the rest of the dev line.
|
||||
* Starts after the four device coordinate arguments.
|
||||
* The next arguments (0, 1, or 2) depend on the type of
|
||||
* device, followed by optional parameters. The rest are
|
||||
* taken in groups of 3, one for each terminal. Each
|
||||
* group of 3 consists of the node name to which the
|
||||
* terminal connects, the length of the terminal, and
|
||||
* an attribute list (or the token 0).
|
||||
* Starts with the last two position values, used to
|
||||
* hash the device record. The next arguments depend
|
||||
* on the type of device. The rest are taken in groups
|
||||
* of 3, one for each terminal. Each group of 3 consists
|
||||
* of the node name to which the terminal connects, the
|
||||
* length of the terminal, and an attribute list (or the
|
||||
* token 0).
|
||||
*/
|
||||
{
|
||||
int n, nterminals, pn;
|
||||
|
|
@ -892,7 +878,7 @@ efBuildDevice(
|
|||
int dev_type;
|
||||
char ptype, *pptr, **av;
|
||||
char devhash[64];
|
||||
int termstart;
|
||||
int argstart = 1; /* start of terminal list in argv[] */
|
||||
bool hasModel = strcmp(type, "None") ? TRUE : FALSE;
|
||||
|
||||
int area, perim; /* Total area, perimeter of primary type (i.e., channel) */
|
||||
|
|
@ -907,40 +893,24 @@ efBuildDevice(
|
|||
devtmp.dev_width = 0;
|
||||
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)
|
||||
{
|
||||
case DEV_FET:
|
||||
case DEV_MOSFET:
|
||||
case DEV_ASYMMETRIC:
|
||||
/* Terminals start after L and W values, substrate, and parameters */
|
||||
termstart = 3;
|
||||
break;
|
||||
case DEV_BJT:
|
||||
/* Terminals start after L and W values, plus parameters */
|
||||
termstart = 2;
|
||||
argstart = 3;
|
||||
break;
|
||||
case DEV_DIODE:
|
||||
case DEV_NDIODE:
|
||||
case DEV_PDIODE:
|
||||
/* Terminals start immediately after parameters */
|
||||
termstart = 0;
|
||||
argstart = 0;
|
||||
break;
|
||||
case DEV_RES:
|
||||
case DEV_CAP:
|
||||
case DEV_CAPREV:
|
||||
if (hasModel)
|
||||
/* Terminals start after L and W values, plus parameters */
|
||||
termstart = 2;
|
||||
/* Otherwise, terminals start after device value, plus parameters */
|
||||
argstart = 2;
|
||||
break;
|
||||
case DEV_SUBCKT:
|
||||
case DEV_VERILOGA:
|
||||
|
|
@ -948,14 +918,13 @@ efBuildDevice(
|
|||
case DEV_RSUBCKT:
|
||||
case DEV_CSUBCKT:
|
||||
case DEV_DSUBCKT:
|
||||
/* Terminals start immediately after parameters */
|
||||
termstart = 0;
|
||||
argstart = 0;
|
||||
}
|
||||
|
||||
devp = efGetDeviceParams(type);
|
||||
|
||||
/* Parse initial arguments for parameters */
|
||||
while ((pptr = strchr(argv[termstart], '=')) != NULL)
|
||||
while ((pptr = strchr(argv[argstart], '=')) != NULL)
|
||||
{
|
||||
/* If the parameter is in the parameter list "devp", then save
|
||||
* the value as appropriate. If not, then the entire phrase
|
||||
|
|
@ -967,7 +936,7 @@ efBuildDevice(
|
|||
|
||||
*pptr = '\0';
|
||||
for (sparm = devp; sparm; sparm = sparm->parm_next)
|
||||
if (!strncasecmp(sparm->parm_type, argv[termstart], 2))
|
||||
if (!strncasecmp(sparm->parm_type, argv[argstart], 2))
|
||||
break;
|
||||
*pptr = '=';
|
||||
if (sparm == NULL)
|
||||
|
|
@ -975,18 +944,18 @@ efBuildDevice(
|
|||
/* Copy the whole string into dev_params */
|
||||
/* (parm_type and parm_scale records are not used) */
|
||||
newparm = (DevParam *)mallocMagic(sizeof(DevParam));
|
||||
newparm->parm_name = StrDup((char **)NULL, argv[termstart]);
|
||||
newparm->parm_name = StrDup((char **)NULL, argv[argstart]);
|
||||
newparm->parm_next = devtmp.dev_params;
|
||||
devtmp.dev_params = newparm;
|
||||
termstart++;
|
||||
argstart++;
|
||||
continue;
|
||||
}
|
||||
|
||||
pptr++;
|
||||
switch(*argv[termstart])
|
||||
switch(*argv[argstart])
|
||||
{
|
||||
case 'a':
|
||||
if ((pptr - argv[termstart]) == 2)
|
||||
if ((pptr - argv[argstart]) == 2)
|
||||
devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
|
||||
* locScale * locScale);
|
||||
else
|
||||
|
|
@ -994,7 +963,7 @@ efBuildDevice(
|
|||
/* Check for a0, a1, a2, ... If a0, handle like "a".
|
||||
* Otherwise, don't handle it here.
|
||||
*/
|
||||
pn = *(argv[termstart] + 1) - '0';
|
||||
pn = *(argv[argstart] + 1) - '0';
|
||||
if (pn == 0)
|
||||
devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
|
||||
* locScale * locScale);
|
||||
|
|
@ -1002,21 +971,21 @@ efBuildDevice(
|
|||
break;
|
||||
|
||||
case 'p':
|
||||
if ((pptr - argv[termstart]) == 2)
|
||||
if ((pptr - argv[argstart]) == 2)
|
||||
devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale);
|
||||
else
|
||||
{
|
||||
/* Check for p0, p1, p2, ... If p0, handle like "p".
|
||||
* Otherwise, don't handle it here.
|
||||
*/
|
||||
pn = *(argv[termstart] + 1) - '0';
|
||||
pn = *(argv[argstart] + 1) - '0';
|
||||
if (pn == 0)
|
||||
devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
if ((pptr - argv[termstart]) == 2)
|
||||
if ((pptr - argv[argstart]) == 2)
|
||||
devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
|
||||
else
|
||||
{
|
||||
|
|
@ -1026,14 +995,14 @@ efBuildDevice(
|
|||
* values like "a1, a2, ..." or "p1, p2, ...".
|
||||
*/
|
||||
|
||||
pn = *(argv[termstart] + 1) - '0';
|
||||
pn = *(argv[argstart] + 1) - '0';
|
||||
if (pn == 0)
|
||||
devtmp.dev_length = (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_name = StrDup((char **)NULL, argv[argstart]);
|
||||
newparm->parm_next = devtmp.dev_params;
|
||||
devtmp.dev_params = newparm;
|
||||
}
|
||||
|
|
@ -1041,28 +1010,7 @@ efBuildDevice(
|
|||
break;
|
||||
|
||||
case 'w':
|
||||
if ((pptr - argv[termstart]) == 2)
|
||||
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;
|
||||
}
|
||||
}
|
||||
devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale);
|
||||
break;
|
||||
case 'c':
|
||||
devtmp.dev_cap = (float)atof(pptr);
|
||||
|
|
@ -1071,7 +1019,7 @@ efBuildDevice(
|
|||
devtmp.dev_res = (float)atof(pptr);
|
||||
break;
|
||||
}
|
||||
termstart++;
|
||||
argstart++;
|
||||
}
|
||||
|
||||
/* Check for optional substrate node */
|
||||
|
|
@ -1079,7 +1027,6 @@ efBuildDevice(
|
|||
{
|
||||
case DEV_RES:
|
||||
case DEV_CAP:
|
||||
case DEV_BJT:
|
||||
case DEV_CAPREV:
|
||||
case DEV_RSUBCKT:
|
||||
case DEV_CSUBCKT:
|
||||
|
|
@ -1090,22 +1037,22 @@ efBuildDevice(
|
|||
case DEV_DIODE:
|
||||
case DEV_NDIODE:
|
||||
case DEV_PDIODE:
|
||||
n = argc - termstart;
|
||||
n = argc - argstart;
|
||||
if ((n % 3) == 1)
|
||||
{
|
||||
if (strncmp(argv[termstart], "None", 4) != 0)
|
||||
devtmp.dev_subsnode = efBuildDevNode(def, argv[termstart], TRUE);
|
||||
if (strncmp(argv[argstart], "None", 4) != 0)
|
||||
devtmp.dev_subsnode = efBuildDevNode(def, argv[argstart], TRUE);
|
||||
|
||||
termstart++;
|
||||
argstart++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Between termstart and argc, we should only have terminal triples */
|
||||
if (((argc - termstart) % 3) != 0)
|
||||
/* Between argstart and argc, we should only have terminal triples */
|
||||
if (((argc - argstart) % 3) != 0)
|
||||
return 1;
|
||||
|
||||
nterminals = (argc - termstart) / 3;
|
||||
nterminals = (argc - argstart) / 3;
|
||||
|
||||
dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, type);
|
||||
|
||||
|
|
@ -1268,17 +1215,17 @@ efBuildDevice(
|
|||
case DEV_ASYMMETRIC:
|
||||
case DEV_BJT:
|
||||
/* "None" in the place of the substrate name means substrate is ignored */
|
||||
if ((termstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
||||
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
||||
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
||||
break;
|
||||
case DEV_RES:
|
||||
if ((termstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
||||
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
||||
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
||||
|
||||
break;
|
||||
case DEV_CAP:
|
||||
case DEV_CAPREV:
|
||||
if ((termstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
||||
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
||||
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
||||
|
||||
break;
|
||||
|
|
@ -1288,7 +1235,7 @@ efBuildDevice(
|
|||
#define TERM_PERIM 1
|
||||
#define TERM_ATTRS 2
|
||||
|
||||
for (av = &argv[termstart], n = 0; n < nterminals; n++, av += 3)
|
||||
for (av = &argv[argstart], n = 0; n < nterminals; n++, av += 3)
|
||||
{
|
||||
term = &newdev->dev_terms[n];
|
||||
term->dterm_node = efBuildDevNode(def, av[TERM_NAME], FALSE);
|
||||
|
|
@ -2116,7 +2063,7 @@ efNodeMerge(node1ptr, node2ptr)
|
|||
/* Make all EFNodeNames point to "keeping" */
|
||||
if (removing->efnode_name)
|
||||
{
|
||||
bool topportk, topportr, bestname, swapnames;
|
||||
bool topportk, topportr, bestname;
|
||||
|
||||
for (nn = removing->efnode_name; nn; nn = nn->efnn_next)
|
||||
{
|
||||
|
|
@ -2127,31 +2074,10 @@ efNodeMerge(node1ptr, node2ptr)
|
|||
topportk = (keeping->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
|
||||
topportr = (removing->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
|
||||
|
||||
/* The node "keeping" is being kept, but we need to decide which
|
||||
* node name of the two will be the node name of "keeping". If
|
||||
* "keeping" has the best node name, then we're good; otherwise,
|
||||
* 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)
|
||||
/* Concatenate list of EFNodeNames, taking into account precedence */
|
||||
if ((!keeping->efnode_name) || (!topportk && topportr)
|
||||
|| EFHNBest(removing->efnode_name->efnn_hier,
|
||||
keeping->efnode_name->efnn_hier))
|
||||
{
|
||||
/*
|
||||
* New official name is that of "removing".
|
||||
|
|
@ -2238,14 +2164,6 @@ efNodeMerge(node1ptr, node2ptr)
|
|||
if (removing->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
|
||||
* removing to keeping.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -36,7 +36,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "utils/magic.h"
|
||||
#include "utils/geometry.h"
|
||||
#include "textio/textio.h"
|
||||
#include "extflat/extparse.h"
|
||||
|
||||
extern char *efReadFileName;
|
||||
extern int efReadLineNum;
|
||||
|
||||
#ifdef MAGIC_WRAPPER
|
||||
extern int Tcl_printf();
|
||||
|
|
|
|||
|
|
@ -61,17 +61,15 @@ int efFlatGlobHash(HierName *);
|
|||
bool efFlatGlobCmp(HierName *, HierName *);
|
||||
char *efFlatGlobCopy(HierName *);
|
||||
void efFlatGlobError(EFNodeName *nameGlob, EFNodeName *nameFlat);
|
||||
int efAddNodes(HierContext *hc, int flags);
|
||||
int efAddConns(HierContext *hc, int flags);
|
||||
int efAddOneConn(HierContext *hc, char *name1, char *name2, Connection *conn, int flags);
|
||||
int efAddNodes(HierContext *hc, bool stdcell);
|
||||
int efAddConns(HierContext *hc, bool doWarn);
|
||||
int efAddOneConn(HierContext *hc, char *name1, char *name2, Connection *conn, bool doWarn);
|
||||
|
||||
/* Flags passed to efFlatNode() */
|
||||
|
||||
#define FLATNODE_STDCELL 0x01
|
||||
#define FLATNODE_DOWARN 0x02
|
||||
#define FLATNODE_NOABSTRACT 0x04
|
||||
#define FLATNODE_HIER 0x08
|
||||
#define FLATNODE_CHILD 0x10
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -218,7 +216,7 @@ EFFlatBuildOneLevel(def, flags)
|
|||
efFlatRootUse.use_def = efFlatRootDef;
|
||||
|
||||
/* Record all nodes down the hierarchy from here */
|
||||
flatnodeflags = FLATNODE_HIER; /* No FLATNODE_DOWARN */
|
||||
flatnodeflags = 0; /* No FLATNODE_DOWARN */
|
||||
efFlatNodes(&efFlatContext, INT2CD(flatnodeflags));
|
||||
|
||||
/* Expand all subcells that contain connectivity information but */
|
||||
|
|
@ -322,7 +320,9 @@ efFlatNodes(hc, clientData)
|
|||
ClientData 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)
|
||||
{
|
||||
|
|
@ -332,19 +332,13 @@ efFlatNodes(hc, clientData)
|
|||
def->def_name);
|
||||
}
|
||||
|
||||
/* 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));
|
||||
(void) efHierSrUses(hc, efFlatNodes, clientData);
|
||||
|
||||
/* Add all our own nodes to the table */
|
||||
efAddNodes(hc, flags);
|
||||
efAddNodes(hc, stdcell);
|
||||
|
||||
/* Process our own connections and adjustments */
|
||||
(void) efAddConns(hc, flags);
|
||||
(void) efAddConns(hc, doWarn);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
|
@ -392,11 +386,11 @@ efFlatNodesStdCell(hc)
|
|||
}
|
||||
|
||||
/* Add all our own nodes to the table */
|
||||
efAddNodes(hc, (int)FLATNODE_STDCELL);
|
||||
efAddNodes(hc, TRUE);
|
||||
|
||||
/* Process our own connections and adjustments */
|
||||
if (!(hc->hc_use->use_def->def_flags & DEF_SUBCIRCUIT))
|
||||
(void) efAddConns(hc, (int)FLATNODE_DOWARN);
|
||||
(void) efAddConns(hc, TRUE);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
|
@ -419,10 +413,10 @@ efFlatNodesDeviceless(hc, cdata)
|
|||
if ((HashGetNumEntries(&hc->hc_use->use_def->def_devs) == 0) && (newcount == 0))
|
||||
{
|
||||
/* Add all our own nodes to the table */
|
||||
efAddNodes(hc, (int)FLATNODE_STDCELL);
|
||||
efAddNodes(hc, TRUE);
|
||||
|
||||
/* Process our own connections and adjustments */
|
||||
efAddConns(hc, (int)FLATNODE_DOWARN);
|
||||
efAddConns(hc, TRUE);
|
||||
|
||||
/* Mark this definition as having no devices, so it will not be visited */
|
||||
hc->hc_use->use_def->def_flags |= DEF_NODEVICES;
|
||||
|
|
@ -461,7 +455,7 @@ efFlatNodesDeviceless(hc, cdata)
|
|||
int
|
||||
efAddNodes(
|
||||
HierContext *hc,
|
||||
int flags)
|
||||
bool stdcell)
|
||||
{
|
||||
Def *def = hc->hc_use->use_def;
|
||||
EFNodeName *nn, *newname, *oldname;
|
||||
|
|
@ -471,8 +465,6 @@ efAddNodes(
|
|||
HierName *hierName;
|
||||
int size, asize;
|
||||
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;
|
||||
|
||||
size = sizeof (EFNode) + (efNumResistClasses-1) * sizeof (EFPerimArea);
|
||||
|
|
@ -511,15 +503,12 @@ efAddNodes(
|
|||
// If called with "hierarchy on", all local node caps and adjustments
|
||||
// have been output and should be ignored.
|
||||
|
||||
if (!stdcell && !is_child)
|
||||
newnode->efnode_cap = node->efnode_cap;
|
||||
else
|
||||
newnode->efnode_cap = (EFCapValue)0.0;
|
||||
newnode->efnode_cap = (!stdcell) ? node->efnode_cap : (EFCapValue)0.0;
|
||||
newnode->efnode_client = (ClientData) NULL;
|
||||
newnode->efnode_flags = node->efnode_flags;
|
||||
newnode->efnode_type = node->efnode_type;
|
||||
newnode->efnode_num = 1;
|
||||
if (!stdcell && !is_child)
|
||||
if (!stdcell)
|
||||
bcopy((char *) node->efnode_pa, (char *) newnode->efnode_pa,
|
||||
efNumResistClasses * sizeof (EFPerimArea));
|
||||
else
|
||||
|
|
@ -612,7 +601,7 @@ efAddNodes(
|
|||
int
|
||||
efAddConns(
|
||||
HierContext *hc,
|
||||
int flags)
|
||||
bool doWarn)
|
||||
{
|
||||
Connection *conn;
|
||||
|
||||
|
|
@ -625,9 +614,9 @@ efAddConns(
|
|||
{
|
||||
/* Special case for speed when no array info is present */
|
||||
if (conn->conn_1.cn_nsubs == 0)
|
||||
efAddOneConn(hc, conn->conn_name1, conn->conn_name2, conn, flags);
|
||||
efAddOneConn(hc, conn->conn_name1, conn->conn_name2, conn, doWarn);
|
||||
else
|
||||
efHierSrArray(hc, conn, efAddOneConn, INT2CD(flags));
|
||||
efHierSrArray(hc, conn, efAddOneConn, INT2CD(doWarn));
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
|
@ -659,23 +648,18 @@ efAddOneConn(
|
|||
char *name1, /* These are strings, not HierNames */
|
||||
char *name2,
|
||||
Connection *conn,
|
||||
int flags)
|
||||
bool doWarn)
|
||||
{
|
||||
HashEntry *he1, *he2;
|
||||
EFNode *node, *newnode;
|
||||
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);
|
||||
if (he1 == NULL)
|
||||
return 0;
|
||||
|
||||
node = ((EFNodeName *) HashGetValue(he1))->efnn_node;
|
||||
|
||||
/* Adjust the resistance and capacitance of its corresponding node */
|
||||
|
||||
node = ((EFNodeName *) HashGetValue(he1))->efnn_node;
|
||||
node->efnode_cap += conn->conn_cap;
|
||||
for (n = 0; n < efNumResistClasses; n++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -82,12 +82,6 @@ extern void efHNRecord();
|
|||
* variables cause nets named VDD and GND to become globals, which was
|
||||
* 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:
|
||||
* TRUE if the name is a global.
|
||||
*
|
||||
|
|
@ -105,10 +99,12 @@ EFHNIsGlob(hierName)
|
|||
char *retstr;
|
||||
retstr = (char *)Tcl_GetVar2(magicinterp, "globals", hierName->hn_name,
|
||||
TCL_GLOBAL_ONLY);
|
||||
return (retstr != NULL) ? TRUE : FALSE;
|
||||
#else
|
||||
return hierName->hn_name[strlen(hierName->hn_name) - 1] == '!';
|
||||
if (retstr != NULL) return TRUE;
|
||||
|
||||
// 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] == '!';
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -524,22 +520,13 @@ EFHNBest(hierName1, hierName2)
|
|||
|
||||
last1 = hierName1->hn_name[strlen(hierName1->hn_name) - 1];
|
||||
last2 = hierName2->hn_name[strlen(hierName2->hn_name) - 1];
|
||||
|
||||
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 */
|
||||
if (last1 == '!') return TRUE;
|
||||
if (last2 == '!') return FALSE;
|
||||
#endif
|
||||
|
||||
/* Neither name is global, so choose label over generated name */
|
||||
/* Neither name is global, so chose label over generated name */
|
||||
if (last1 != '#' && last2 == '#') return TRUE;
|
||||
if (last1 == '#' && last2 != '#') return FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "commands/commands.h"
|
||||
#include "database/database.h"
|
||||
#include "extflat/extflat.h"
|
||||
#include "extflat/extparse.h"
|
||||
#include "extflat/EFint.h"
|
||||
#include "extract/extract.h"
|
||||
#include "extract/extractInt.h"
|
||||
|
|
@ -49,11 +48,58 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#ifndef MAGIC_WRAPPER
|
||||
/* This must match the definition for extDevTable in extract/ExtBasic.c */
|
||||
const char * const extDevTable[] = {"fet", "mosfet", "asymmetric", "bjt", "devres",
|
||||
"devcap", "devcaprev", "vsource", "diode", "pdiode",
|
||||
"ndiode", "subckt", "rsubckt", "msubckt", "csubckt",
|
||||
"dsubckt", "veriloga", NULL};
|
||||
"devcap", "devcaprev", "vsource", "diode", "pdiode",
|
||||
"ndiode", "subckt", "rsubckt", "msubckt", "csubckt",
|
||||
"dsubckt", "veriloga", NULL};
|
||||
#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 */
|
||||
char *efReadFileName; /* Name of file currently being read */
|
||||
int efReadLineNum; /* Current line number in above file */
|
||||
|
|
@ -63,6 +109,10 @@ bool EFSaveLocs; /* If TRUE, save location of merged top-level nodes */
|
|||
/* Data local to this file */
|
||||
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,6 +27,7 @@
|
|||
#include "extflat/EFtypes.h" /* EFCapValue, HierName, EFPerimArea, EFNode */
|
||||
#include "extflat/EFint.h" /* Def, HierContext, Connection, Distance, CallArg */
|
||||
|
||||
|
||||
extern float EFScale; /* Scale factor to multiply all coords by */
|
||||
extern char *EFTech; /* Technology of extracted circuit */
|
||||
extern char *EFStyle; /* Extraction style of extracted circuit */
|
||||
|
|
|
|||
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* 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,15 +713,14 @@ extArrayNodeName(np, ha, et1, et2)
|
|||
ExtTree *et1, *et2;
|
||||
{
|
||||
Tile *tp;
|
||||
TileType dinfo;
|
||||
|
||||
tp = extNodeToTile(np, et1, &dinfo);
|
||||
if (tp && TiGetType(tp) != TT_SPACE && extHasRegion(tp, CLIENTDEFAULT))
|
||||
return (extArrayTileToNode(tp, dinfo, np->nreg_pnum, et1, ha, TRUE));
|
||||
tp = extNodeToTile(np, et1);
|
||||
if (tp && TiGetType(tp) != TT_SPACE && extHasRegion(tp, extUnInit))
|
||||
return (extArrayTileToNode(tp, np->nreg_pnum, et1, ha, TRUE));
|
||||
|
||||
tp = extNodeToTile(np, et2, &dinfo);
|
||||
if (tp && TiGetType(tp) != TT_SPACE && extHasRegion(tp, CLIENTDEFAULT))
|
||||
return (extArrayTileToNode(tp, dinfo, np->nreg_pnum, et2, ha, TRUE));
|
||||
tp = extNodeToTile(np, et2);
|
||||
if (tp && TiGetType(tp) != TT_SPACE && extHasRegion(tp, extUnInit))
|
||||
return (extArrayTileToNode(tp, np->nreg_pnum, et2, ha, TRUE));
|
||||
|
||||
return ("(none)");
|
||||
}
|
||||
|
|
@ -769,9 +768,8 @@ extArrayNodeName(np, ha, et1, et2)
|
|||
*/
|
||||
|
||||
char *
|
||||
extArrayTileToNode(tp, dinfo, pNum, et, ha, doHard)
|
||||
extArrayTileToNode(tp, pNum, et, ha, doHard)
|
||||
Tile *tp;
|
||||
TileType dinfo;
|
||||
int pNum;
|
||||
ExtTree *et;
|
||||
HierExtractArg *ha;
|
||||
|
|
@ -793,15 +791,15 @@ extArrayTileToNode(tp, dinfo, pNum, et, ha, doHard)
|
|||
LabRegion *reg;
|
||||
Rect r;
|
||||
|
||||
if (extHasRegion(tp, CLIENTDEFAULT))
|
||||
if (extHasRegion(tp, extUnInit))
|
||||
{
|
||||
reg = (LabRegion *) ExtGetRegion(tp, dinfo);
|
||||
reg = (LabRegion *) extGetRegion(tp);
|
||||
if (reg->lreg_labels)
|
||||
goto found;
|
||||
}
|
||||
|
||||
if (!DebugIsSet(extDebugID, extDebNoHard))
|
||||
if ((reg = (LabRegion *) extArrayHardNode(tp, dinfo, pNum, def, ha)))
|
||||
if ((reg = (LabRegion *) extArrayHardNode(tp, pNum, def, ha)))
|
||||
goto found;
|
||||
|
||||
/* Blew it */
|
||||
|
|
@ -936,23 +934,17 @@ extArrayRange(dstp, lo, hi, prevRange, followRange)
|
|||
*/
|
||||
|
||||
LabRegion *
|
||||
extArrayHardNode(tp, dinfo, pNum, def, ha)
|
||||
extArrayHardNode(tp, pNum, def, ha)
|
||||
Tile *tp;
|
||||
TileType dinfo;
|
||||
int pNum;
|
||||
CellDef *def;
|
||||
HierExtractArg *ha;
|
||||
{
|
||||
TileType type;
|
||||
TileType type = TiGetType(tp);
|
||||
char labelBuf[4096];
|
||||
SearchContext scx;
|
||||
HardWay arg;
|
||||
|
||||
if (IsSplit(tp))
|
||||
type = (dinfo & TT_SIDE) ? TiGetRightType(tp) : TiGetLeftType(tp);
|
||||
else
|
||||
type = TiGetType(tp);
|
||||
|
||||
arg.hw_ha = ha;
|
||||
arg.hw_label = (Label *) NULL;
|
||||
arg.hw_mask = DBPlaneTypes[pNum];
|
||||
|
|
@ -979,7 +971,7 @@ extArrayHardNode(tp, dinfo, pNum, def, ha)
|
|||
LabRegion *lreg;
|
||||
LabelList *ll;
|
||||
|
||||
lreg = (LabRegion *) ExtGetRegion(tp, dinfo);
|
||||
lreg = (LabRegion *) extGetRegion(tp);
|
||||
ll = (LabelList *) mallocMagic((unsigned) (sizeof (LabelList)));
|
||||
lreg->lreg_labels = ll;
|
||||
ll->ll_next = (LabelList *) NULL;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -46,10 +46,20 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "utils/main.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 ------------------- */
|
||||
|
||||
/* Forward declarations */
|
||||
int extOutputUsesFunc();
|
||||
FILE *extFileOpen();
|
||||
|
||||
Plane* extCellFile();
|
||||
void extHeader();
|
||||
|
|
@ -95,7 +105,7 @@ ExtCell(def, outName, doLength)
|
|||
if (def->cd_flags & CDNOEXTRACT)
|
||||
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);
|
||||
|
||||
|
|
@ -131,7 +141,7 @@ ExtCell(def, outName, doLength)
|
|||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* ExtFileOpen --
|
||||
* extFileOpen --
|
||||
*
|
||||
* 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
|
||||
|
|
@ -149,7 +159,7 @@ ExtCell(def, outName, doLength)
|
|||
*/
|
||||
|
||||
FILE *
|
||||
ExtFileOpen(def, file, mode, prealfile)
|
||||
extFileOpen(def, file, mode, prealfile)
|
||||
CellDef *def; /* Cell whose .ext file is to be written */
|
||||
char *file; /* If non-NULL, open 'name'.ext; otherwise,
|
||||
* derive filename from 'def' as described
|
||||
|
|
@ -485,17 +495,8 @@ extCellFile(def, f, doLength)
|
|||
|
||||
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 */
|
||||
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 */
|
||||
for (lab = def->cd_labels; lab; lab = lab->lab_next)
|
||||
|
|
@ -516,7 +517,7 @@ extCellFile(def, f, doLength)
|
|||
|
||||
/* Clean up from basic extraction */
|
||||
if (reg) ExtFreeLabRegions((LabRegion *) reg);
|
||||
ExtResetTiles(def, CLIENTDEFAULT);
|
||||
ExtResetTiles(def, extUnInit);
|
||||
|
||||
/* Final pass: extract length information if desired */
|
||||
if (!SigInterruptPending && doLength && (ExtOptions & EXT_DOLENGTH))
|
||||
|
|
@ -594,7 +595,7 @@ extHeader(def, f)
|
|||
/* are to be passed to instances of the cell */
|
||||
/* (created by defining property "parameter") */
|
||||
|
||||
propvalue = DBPropGetString(def, "parameter", &propfound);
|
||||
propvalue = (char *)DBPropGet(def, "parameter", &propfound);
|
||||
if (propfound)
|
||||
{
|
||||
// Use device parameter table to store the cell def parameters,
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ typedef struct _ecs {
|
|||
|
||||
typedef struct _ecpls {
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
int plane_of_tile;
|
||||
int plane_checked;
|
||||
} extCoupleStruct;
|
||||
|
|
@ -312,9 +311,8 @@ extOutputCoupling(table, outFile)
|
|||
*/
|
||||
|
||||
int
|
||||
extBasicOverlap(tile, dinfo, ecs)
|
||||
extBasicOverlap(tile, ecs)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
extCapStruct *ecs;
|
||||
{
|
||||
int thisType;
|
||||
|
|
@ -327,7 +325,7 @@ extBasicOverlap(tile, dinfo, ecs)
|
|||
extCoupleStruct ecpls;
|
||||
|
||||
if (IsSplit(tile))
|
||||
thisType = ((dinfo & TT_SIDE)) ? SplitRightType(tile) :
|
||||
thisType = (SplitSide(tile)) ? SplitRightType(tile) :
|
||||
SplitLeftType(tile);
|
||||
else
|
||||
thisType = TiGetTypeExact(tile);
|
||||
|
|
@ -346,7 +344,6 @@ extBasicOverlap(tile, dinfo, ecs)
|
|||
}
|
||||
|
||||
ecpls.tile = tile;
|
||||
ecpls.dinfo = dinfo;
|
||||
ecpls.plane_of_tile = thisPlane;
|
||||
|
||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||
|
|
@ -413,9 +410,8 @@ struct sideoverlap
|
|||
};
|
||||
|
||||
int
|
||||
extAddOverlap(tbelow, dinfo, ecpls)
|
||||
extAddOverlap(tbelow, ecpls)
|
||||
Tile *tbelow;
|
||||
TileType dinfo; /* unused, but needs to be handled */
|
||||
extCoupleStruct *ecpls;
|
||||
{
|
||||
int extSubtractOverlap(), extSubtractOverlap2();
|
||||
|
|
@ -434,8 +430,8 @@ extAddOverlap(tbelow, dinfo, ecpls)
|
|||
/* subtract off any substrate (area) capacitance previously added */
|
||||
/* (Correction made 4/29/04 by Tim from a tip by Jeff Sondeen). */
|
||||
|
||||
rabove = (NodeRegion *) ExtGetRegion(tabove, ecpls->dinfo);
|
||||
rbelow = (NodeRegion *) ExtGetRegion(tbelow, dinfo);
|
||||
rabove = (NodeRegion *) extGetRegion(tabove);
|
||||
rbelow = (NodeRegion *) extGetRegion(tbelow);
|
||||
|
||||
/* Quick check on validity of tile's ti_client record */
|
||||
if (rbelow == (NodeRegion *)CLIENTDEFAULT) return 0;
|
||||
|
|
@ -452,16 +448,8 @@ extAddOverlap(tbelow, dinfo, ecpls)
|
|||
}
|
||||
ov.o_area = (ov.o_clip.r_ytop - ov.o_clip.r_ybot)
|
||||
* (ov.o_clip.r_xtop - ov.o_clip.r_xbot);
|
||||
|
||||
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);
|
||||
ta = TiGetType(tabove);
|
||||
tb = TiGetType(tbelow);
|
||||
|
||||
/* Revert any contacts to their residues */
|
||||
|
||||
|
|
@ -551,9 +539,8 @@ extAddOverlap(tbelow, dinfo, ecpls)
|
|||
/* Simple overlap. The area of overlap is subtracted from ov->o_area */
|
||||
|
||||
int
|
||||
extSubtractOverlap(tile, dinfo, ov)
|
||||
extSubtractOverlap(tile, ov)
|
||||
Tile *tile;
|
||||
TileType dinfo; /* (unused) */
|
||||
struct overlap *ov;
|
||||
{
|
||||
Rect r;
|
||||
|
|
@ -562,7 +549,6 @@ extSubtractOverlap(tile, dinfo, ov)
|
|||
TITORECT(tile, &r);
|
||||
GEOCLIP(&r, &ov->o_clip);
|
||||
area = (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot);
|
||||
if (IsSplit(tile)) area /= 2;
|
||||
if (area > 0)
|
||||
ov->o_area -= area;
|
||||
|
||||
|
|
@ -575,12 +561,10 @@ extSubtractOverlap(tile, dinfo, ov)
|
|||
/* shielding plane. */
|
||||
|
||||
int
|
||||
extSubtractOverlap2(tile, dinfo, ov)
|
||||
extSubtractOverlap2(tile, ov)
|
||||
Tile *tile;
|
||||
TileType dinfo; /* (unused) */
|
||||
struct overlap *ov;
|
||||
{
|
||||
TileType ttype;
|
||||
struct overlap ovnew;
|
||||
int area, pNum;
|
||||
Rect r;
|
||||
|
|
@ -590,16 +574,9 @@ extSubtractOverlap2(tile, dinfo, ov)
|
|||
area = (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot);
|
||||
if (area <= 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 */
|
||||
if (TTMaskHasType(&ov->o_tmask, ttype))
|
||||
if (TTMaskHasType(&ov->o_tmask, TiGetType(tile)))
|
||||
{
|
||||
ov->o_area -= area;
|
||||
return (0);
|
||||
|
|
@ -637,9 +614,8 @@ extSubtractOverlap2(tile, dinfo, ov)
|
|||
*/
|
||||
|
||||
int
|
||||
extSubtractSideOverlap(tile, dinfo, sov)
|
||||
extSubtractSideOverlap(tile, sov)
|
||||
Tile *tile;
|
||||
TileType dinfo; /* (unused) */
|
||||
struct sideoverlap *sov;
|
||||
{
|
||||
Rect r;
|
||||
|
|
@ -715,31 +691,24 @@ extSubtractSideOverlap(tile, dinfo, sov)
|
|||
/* shielding plane. */
|
||||
|
||||
int
|
||||
extSubtractSideOverlap2(tile, dinfo, sov)
|
||||
extSubtractSideOverlap2(tile, sov)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
struct sideoverlap *sov;
|
||||
{
|
||||
TileType ttype;
|
||||
struct sideoverlap sovnew;
|
||||
int area, pNum;
|
||||
Rect r;
|
||||
|
||||
if (IsSplit(tile))
|
||||
ttype = (dinfo & TT_SIDE) ? TiGetRightType(tile) : TiGetLeftType(tile);
|
||||
else
|
||||
ttype = TiGetTypeExact(tile);
|
||||
|
||||
TITORECT(tile, &r);
|
||||
GEOCLIP(&r, &sov->so_clip);
|
||||
area = (r.r_xtop - r.r_xbot) * (r.r_ytop - r.r_ybot);
|
||||
if (area <= 0) return (0);
|
||||
if (IsSplit(tile)) area /= 2;
|
||||
if (area <= 0)
|
||||
return (0);
|
||||
|
||||
/* This tile shields everything below */
|
||||
if (TTMaskHasType(&sov->so_tmask, ttype))
|
||||
if (TTMaskHasType(&sov->so_tmask, TiGetType(tile)))
|
||||
{
|
||||
extSubtractSideOverlap(tile, dinfo, sov);
|
||||
extSubtractSideOverlap(tile, sov);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
@ -795,250 +764,15 @@ extSubtractSideOverlap2(tile, dinfo, sov)
|
|||
*/
|
||||
|
||||
int
|
||||
extBasicCouple(tile, dinfo, ecs)
|
||||
extBasicCouple(tile, ecs)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
extCapStruct *ecs;
|
||||
{
|
||||
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],
|
||||
(void) extEnumTilePerim(tile, &ExtCurStyle->exts_sideEdges[TiGetType(tile)],
|
||||
ecs->plane, extAddCouple, (ClientData) ecs);
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -1074,7 +808,7 @@ extAddCouple(bp, ecs)
|
|||
Boundary *bp; /* Boundary being considered */
|
||||
extCapStruct *ecs;
|
||||
{
|
||||
TileType tin, tout;
|
||||
TileType tin = TiGetType(bp->b_inside), tout = TiGetType(bp->b_outside);
|
||||
int pNum;
|
||||
PlaneMask pMask;
|
||||
Boundary bpCopy;
|
||||
|
|
@ -1082,21 +816,6 @@ extAddCouple(bp, ecs)
|
|||
extSidewallStruct esws;
|
||||
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.
|
||||
* that handles cases such as FET types not being declared in
|
||||
* defaultperimeter, as the edge between poly and FET will be
|
||||
|
|
@ -1186,7 +905,7 @@ extAddCouple(bp, ecs)
|
|||
extSideBottom, bp, &esws);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1217,10 +936,9 @@ extRemoveSubcap(bp, clip, esws)
|
|||
|
||||
if (!esws->fringe_halo) return;
|
||||
|
||||
/* Get the types on the inside and outside of the boundary */
|
||||
extGetBoundaryTypes(bp, &ta, &tb);
|
||||
|
||||
rbp = (NodeRegion *)ExtGetRegion(bp->b_inside, (TileType)0);
|
||||
ta = TiGetType(bp->b_inside);
|
||||
tb = TiGetType(bp->b_outside);
|
||||
rbp = (NodeRegion *)extGetRegion(bp->b_inside);
|
||||
|
||||
if (bp->b_segment.r_xtop == bp->b_segment.r_xbot)
|
||||
length = bp->b_segment.r_ytop - bp->b_segment.r_ybot;
|
||||
|
|
@ -1289,14 +1007,6 @@ extFindOverlap(tp, area, esws)
|
|||
TileType tin = TiGetType(bp->b_inside);
|
||||
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];
|
||||
extOverlapDef = esws->def;
|
||||
|
||||
|
|
@ -1345,14 +1055,13 @@ extFindOverlap(tp, area, esws)
|
|||
*/
|
||||
|
||||
int
|
||||
extSideOverlapHalo(tp, dinfo, esws)
|
||||
extSideOverlapHalo(tp, esws)
|
||||
Tile *tp; /* Overlapped tile */
|
||||
TileType dinfo; /* Split tile information */
|
||||
extSidewallStruct *esws; /* Overlapping edge and plane information */
|
||||
{
|
||||
Boundary *bp = esws->bp; /* Overlapping edge */
|
||||
NodeRegion *rtp = (NodeRegion *) ExtGetRegion(tp, dinfo);
|
||||
NodeRegion *rbp = (NodeRegion *) ExtGetRegion(bp->b_inside, (TileType)0);
|
||||
NodeRegion *rtp = (NodeRegion *) extGetRegion(tp);
|
||||
NodeRegion *rbp = (NodeRegion *) extGetRegion(bp->b_inside);
|
||||
TileType ta, tb;
|
||||
Rect tpr;
|
||||
struct sideoverlap sov;
|
||||
|
|
@ -1367,10 +1076,7 @@ extSideOverlapHalo(tp, dinfo, esws)
|
|||
|
||||
/* Nothing to do for space tiles, so just return. */
|
||||
/* (TO DO: Make sure TT_SPACE is removed from all exts_sideOverlapOtherTypes */
|
||||
if (IsSplit(tp))
|
||||
tb = (dinfo & TT_SIDE) ? TiGetRightType(tp) : TiGetLeftType(tp);
|
||||
else
|
||||
tb = TiGetTypeExact(tp);
|
||||
tb = TiGetType(tp);
|
||||
if (tb == TT_SPACE) return (0);
|
||||
|
||||
/* Get the area of the coupling tile, and clip to the fringe area */
|
||||
|
|
@ -1446,7 +1152,7 @@ extSideOverlapHalo(tp, dinfo, esws)
|
|||
if (!PlaneMaskHasPlane(e->ec_pmask, esws->plane_checked)) continue;
|
||||
|
||||
/* Does this rule "e" include the tile we found? */
|
||||
if (TTMaskHasType(&e->ec_near, tb))
|
||||
if (TTMaskHasType(&e->ec_near, TiGetType(tp)))
|
||||
{
|
||||
/* We have a possible capacitor, but are the tiles shielded from
|
||||
* each other part of the way?
|
||||
|
|
@ -1576,14 +1282,13 @@ extSideOverlapHalo(tp, dinfo, esws)
|
|||
*/
|
||||
|
||||
int
|
||||
extSideOverlap(tp, dinfo, esws)
|
||||
extSideOverlap(tp, esws)
|
||||
Tile *tp; /* Overlapped tile */
|
||||
TileType dinfo; /* Split tile information */
|
||||
extSidewallStruct *esws; /* Overlapping edge and plane information */
|
||||
{
|
||||
Boundary *bp = esws->bp; /* Overlapping edge */
|
||||
NodeRegion *rtp = (NodeRegion *) ExtGetRegion(tp, dinfo);
|
||||
NodeRegion *rbp = (NodeRegion *) ExtGetRegion(bp->b_inside, (TileType)0);
|
||||
NodeRegion *rtp = (NodeRegion *) extGetRegion(tp);
|
||||
NodeRegion *rbp = (NodeRegion *) extGetRegion(bp->b_inside);
|
||||
TileType ta, tb;
|
||||
Rect tpr;
|
||||
struct overlap ov;
|
||||
|
|
@ -1596,10 +1301,7 @@ extSideOverlap(tp, dinfo, esws)
|
|||
|
||||
/* Nothing to do for space tiles, so just return. */
|
||||
/* (TO DO: Make sure TT_SPACE is removed from all exts_sideOverlapOtherTypes */
|
||||
if (IsSplit(tp))
|
||||
tb = (dinfo & TT_SIDE) ? TiGetRightType(tp) : TiGetLeftType(tp);
|
||||
else
|
||||
tb = TiGetTypeExact(tp);
|
||||
tb = TiGetType(tp);
|
||||
if (tb == TT_SPACE) return (0);
|
||||
|
||||
if (bp->b_segment.r_xtop == bp->b_segment.r_xbot)
|
||||
|
|
@ -1634,7 +1336,7 @@ extSideOverlap(tp, dinfo, esws)
|
|||
if (!PlaneMaskHasPlane(e->ec_pmask, esws->plane_checked)) continue;
|
||||
|
||||
/* Does this rule "e" include the tile we found? */
|
||||
if (TTMaskHasType(&e->ec_near, tb))
|
||||
if (TTMaskHasType(&e->ec_near, TiGetType(tp)))
|
||||
{
|
||||
/* We have a possible capacitor, but are the tiles shielded from
|
||||
* each other part of the way?
|
||||
|
|
@ -1776,7 +1478,11 @@ extWalkTop(area, mask, func, bp, esws)
|
|||
tp = tile;
|
||||
while (RIGHT(tp) > area->r_xbot)
|
||||
{
|
||||
ttype = TiGetBottomType(tp);
|
||||
if (IsSplit(tp))
|
||||
ttype = (SplitSide(tp)) ? SplitRightType(tp) : SplitLeftType(tp);
|
||||
else
|
||||
ttype = TiGetTypeExact(tp);
|
||||
|
||||
if (TTMaskHasType(mask, ttype))
|
||||
{
|
||||
bool lookLeft, lookRight;
|
||||
|
|
@ -1884,7 +1590,11 @@ extWalkBottom(area, mask, func, bp, esws)
|
|||
tp = tile;
|
||||
while (LEFT(tp) < area->r_xtop)
|
||||
{
|
||||
ttype = TiGetTopType(tp);
|
||||
if (IsSplit(tp))
|
||||
ttype = (SplitSide(tp)) ? SplitRightType(tp) : SplitLeftType(tp);
|
||||
else
|
||||
ttype = TiGetTypeExact(tp);
|
||||
|
||||
if (TTMaskHasType(mask, ttype))
|
||||
{
|
||||
bool lookLeft, lookRight;
|
||||
|
|
@ -1992,7 +1702,11 @@ extWalkRight(area, mask, func, bp, esws)
|
|||
tp = tile;
|
||||
while (TOP(tp) > area->r_ybot)
|
||||
{
|
||||
ttype = TiGetLeftType(tp);
|
||||
if (IsSplit(tp))
|
||||
ttype = (SplitSide(tp)) ? SplitRightType(tp) : SplitLeftType(tp);
|
||||
else
|
||||
ttype = TiGetTypeExact(tp);
|
||||
|
||||
if (TTMaskHasType(mask, ttype))
|
||||
{
|
||||
bool lookDown, lookUp;
|
||||
|
|
@ -2100,7 +1814,11 @@ extWalkLeft(area, mask, func, bp, esws)
|
|||
tp = tile;
|
||||
while (BOTTOM(tp) < area->r_ytop)
|
||||
{
|
||||
ttype = TiGetRightType(tp);
|
||||
if (IsSplit(tp))
|
||||
ttype = (SplitSide(tp)) ? SplitRightType(tp) : SplitLeftType(tp);
|
||||
else
|
||||
ttype = TiGetTypeExact(tp);
|
||||
|
||||
if (TTMaskHasType(mask, ttype))
|
||||
{
|
||||
bool lookDown, lookUp;
|
||||
|
|
@ -2199,13 +1917,11 @@ extSideLeft(tpfar, bp, esws)
|
|||
Boundary *bp;
|
||||
extSidewallStruct *esws;
|
||||
{
|
||||
NodeRegion *rinside, *rfar;
|
||||
NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside);
|
||||
NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar);
|
||||
Tile *tpnear;
|
||||
|
||||
/* 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)
|
||||
if (rfar != (NodeRegion *) extUnInit && rfar != rinside)
|
||||
{
|
||||
int sep = bp->b_segment.r_xbot - RIGHT(tpfar);
|
||||
int limit = MAX(bp->b_segment.r_ybot, BOTTOM(tpfar));
|
||||
|
|
@ -2215,8 +1931,8 @@ extSideLeft(tpfar, bp, esws)
|
|||
{
|
||||
int overlap = MIN(TOP(tpnear), start) - MAX(BOTTOM(tpnear), limit);
|
||||
if (overlap > 0)
|
||||
extSideCommon(rinside, rfar, tpnear, tpfar, bp->b_direction,
|
||||
overlap, sep, esws->extCoupleList);
|
||||
extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep,
|
||||
esws->extCoupleList);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2251,13 +1967,11 @@ extSideRight(tpfar, bp, esws)
|
|||
Boundary *bp;
|
||||
extSidewallStruct *esws;
|
||||
{
|
||||
NodeRegion *rinside, *rfar;
|
||||
NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside);
|
||||
NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar);
|
||||
Tile *tpnear;
|
||||
|
||||
/* 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)
|
||||
if (rfar != (NodeRegion *) extUnInit && rfar != rinside)
|
||||
{
|
||||
int sep = LEFT(tpfar) - bp->b_segment.r_xtop;
|
||||
int limit = MIN(bp->b_segment.r_ytop, TOP(tpfar));
|
||||
|
|
@ -2267,8 +1981,8 @@ extSideRight(tpfar, bp, esws)
|
|||
{
|
||||
int overlap = MIN(TOP(tpnear), limit) - MAX(BOTTOM(tpnear), start);
|
||||
if (overlap > 0)
|
||||
extSideCommon(rinside, rfar, tpnear, tpfar, bp->b_direction,
|
||||
overlap, sep, esws->extCoupleList);
|
||||
extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep,
|
||||
esws->extCoupleList);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2303,13 +2017,11 @@ extSideTop(tpfar, bp, esws)
|
|||
Boundary *bp;
|
||||
extSidewallStruct *esws;
|
||||
{
|
||||
NodeRegion *rinside, *rfar;
|
||||
NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside);
|
||||
NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar);
|
||||
Tile *tpnear;
|
||||
|
||||
/* 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)
|
||||
if (rfar != (NodeRegion *) extUnInit && rfar != rinside)
|
||||
{
|
||||
int sep = BOTTOM(tpfar) - bp->b_segment.r_ytop;
|
||||
int limit = MIN(bp->b_segment.r_xtop, RIGHT(tpfar));
|
||||
|
|
@ -2319,8 +2031,8 @@ extSideTop(tpfar, bp, esws)
|
|||
{
|
||||
int overlap = MIN(RIGHT(tpnear), limit) - MAX(LEFT(tpnear), start);
|
||||
if (overlap > 0)
|
||||
extSideCommon(rinside, rfar, tpnear, tpfar, bp->b_direction,
|
||||
overlap, sep, esws->extCoupleList);
|
||||
extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep,
|
||||
esws->extCoupleList);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2355,13 +2067,11 @@ extSideBottom(tpfar, bp, esws)
|
|||
Boundary *bp;
|
||||
extSidewallStruct *esws;
|
||||
{
|
||||
NodeRegion *rinside, *rfar;
|
||||
NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside);
|
||||
NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar);
|
||||
Tile *tpnear;
|
||||
|
||||
/* 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)
|
||||
if (rfar != (NodeRegion *) extUnInit && rfar != rinside)
|
||||
{
|
||||
int sep = bp->b_segment.r_ybot - TOP(tpfar);
|
||||
int limit = MAX(bp->b_segment.r_xbot, LEFT(tpfar));
|
||||
|
|
@ -2371,8 +2081,8 @@ extSideBottom(tpfar, bp, esws)
|
|||
{
|
||||
int overlap = MIN(RIGHT(tpnear), start) - MAX(LEFT(tpnear), limit);
|
||||
if (overlap > 0)
|
||||
extSideCommon(rinside, rfar, tpnear, tpfar, bp->b_direction,
|
||||
overlap, sep, esws->extCoupleList);
|
||||
extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep,
|
||||
esws->extCoupleList);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2386,7 +2096,7 @@ extSideBottom(tpfar, bp, esws)
|
|||
*
|
||||
* Perform the actual update to the hash table entry for
|
||||
* the regions 'rinside' and 'rfar'. We assume that neither
|
||||
* 'rinside' nor 'rfar' are CLIENTDEFAULT, and further that they
|
||||
* 'rinside' nor 'rfar' are extUnInit, and further that they
|
||||
* are not equal.
|
||||
*
|
||||
* Walk along the rules in extCoupleList, applying the appropriate
|
||||
|
|
@ -2403,24 +2113,20 @@ extSideBottom(tpfar, bp, esws)
|
|||
*/
|
||||
|
||||
void
|
||||
extSideCommon(rinside, rfar, tpnear, tpfar, bdir, overlap, sep, extCoupleList)
|
||||
extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep, extCoupleList)
|
||||
NodeRegion *rinside, *rfar; /* Both must be valid */
|
||||
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,
|
||||
* and distance between the two.
|
||||
*/
|
||||
EdgeCap *extCoupleList; /* List of sidewall capacitance rules */
|
||||
{
|
||||
TileType near, far;
|
||||
TileType near = TiGetType(tpnear), far = TiGetType(tpfar);
|
||||
HashEntry *he;
|
||||
EdgeCap *e;
|
||||
CoupleKey ck;
|
||||
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;
|
||||
else ck.ck_1 = rfar, ck.ck_2 = rinside;
|
||||
he = HashFind(extCoupleHashPtr, (char *) &ck);
|
||||
|
|
|
|||
|
|
@ -71,9 +71,8 @@ bool extHardSetLabel();
|
|||
*/
|
||||
|
||||
ExtRegion *
|
||||
extLabFirst(tile, dinfo, arg)
|
||||
extLabFirst(tile, arg)
|
||||
Tile *tile;
|
||||
TileType dinfo; /* (unused) */
|
||||
FindRegion *arg;
|
||||
{
|
||||
TransRegion *reg;
|
||||
|
|
@ -83,11 +82,6 @@ extLabFirst(tile, dinfo, arg)
|
|||
reg->treg_pnum = DBNumPlanes;
|
||||
reg->treg_area = DBNumPlanes;
|
||||
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 */
|
||||
reg->treg_next = (TransRegion *) arg->fra_region;
|
||||
|
|
@ -97,16 +91,25 @@ extLabFirst(tile, dinfo, arg)
|
|||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
extLabEach(tile, dinfo, pNum, arg)
|
||||
extLabEach(tile, pNum, arg)
|
||||
Tile *tile;
|
||||
TileType dinfo; /* (unused) */
|
||||
int pNum;
|
||||
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;
|
||||
|
||||
if (reg->treg_area == DBNumPlanes) reg->treg_area = pNum;
|
||||
extSetNodeNum((LabRegion *)reg, pNum, tile, dinfo);
|
||||
extSetNodeNum((LabRegion *)reg, pNum, tile);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +172,7 @@ extHardProc(scx, arg)
|
|||
CellDef *def = scx->scx_use->cu_def;
|
||||
TransRegion *reg;
|
||||
TransRegion *labRegList;
|
||||
LabelList *subList = NULL;
|
||||
LabelList *subList;
|
||||
char *savenext;
|
||||
int ret = 0;
|
||||
|
||||
|
|
@ -200,7 +203,7 @@ extHardProc(scx, arg)
|
|||
* single child.
|
||||
*/
|
||||
labRegList = (TransRegion *) ExtFindRegions(def, &scx->scx_area,
|
||||
&arg->hw_mask, ExtCurStyle->exts_nodeConn,
|
||||
&arg->hw_mask, ExtCurStyle->exts_nodeConn, extUnInit,
|
||||
extLabFirst, extLabEach);
|
||||
if (labRegList)
|
||||
{
|
||||
|
|
@ -237,8 +240,7 @@ extHardProc(scx, arg)
|
|||
*/
|
||||
if (ExtCurStyle->exts_globSubstrateDefaultType != -1)
|
||||
for (reg = labRegList; reg; reg = reg->treg_next)
|
||||
if (TTMaskHasType(&ExtCurStyle->exts_globSubstrateTypes,
|
||||
reg->treg_type & TT_LEFTMASK))
|
||||
if (TTMaskHasType(&ExtCurStyle->exts_globSubstrateTypes, reg->treg_type))
|
||||
if (reg->treg_pnum != ExtCurStyle->exts_globSubstratePlane)
|
||||
{
|
||||
reg->treg_labels = subList;
|
||||
|
|
@ -259,7 +261,6 @@ extHardProc(scx, arg)
|
|||
goto done;
|
||||
|
||||
success:
|
||||
if (subList != NULL) freeMagic(subList);
|
||||
extHardFreeAll(def, labRegList);
|
||||
ret = 1;
|
||||
|
||||
|
|
@ -337,7 +338,7 @@ extHardSetLabel(scx, reg, arg)
|
|||
tp = PlaneGetHint(scx->scx_use->cu_def->cd_planes[pNum]);
|
||||
GOTOPOINT(tp, &r.r_ll);
|
||||
PlaneSetHint(scx->scx_use->cu_def->cd_planes[pNum], tp);
|
||||
if ((TransRegion *)ExtGetRegion(tp, (TileType)0) == reg)
|
||||
if ((TransRegion *)extGetRegion(tp) == reg)
|
||||
{
|
||||
/* found an OK point */
|
||||
r.r_ur.p_x =r.r_ll.p_x+1;
|
||||
|
|
@ -346,7 +347,7 @@ extHardSetLabel(scx, reg, arg)
|
|||
else
|
||||
{
|
||||
GOTOPOINT(tp, &r.r_ur);
|
||||
if ((TransRegion *)ExtGetRegion(tp, (TileType)0) == reg)
|
||||
if ((TransRegion *)extGetRegion(tp) == reg)
|
||||
{
|
||||
r.r_ll = r.r_ur;
|
||||
}
|
||||
|
|
@ -492,17 +493,17 @@ extHardFreeAll(def, tReg)
|
|||
arg.fra_connectsTo = ExtCurStyle->exts_nodeConn;
|
||||
arg.fra_def = def;
|
||||
arg.fra_each = (int (*)()) NULL;
|
||||
arg.fra_region = (ExtRegion *) CLIENTDEFAULT;
|
||||
arg.fra_region = (ExtRegion *) extUnInit;
|
||||
|
||||
free_magic1_t mm1 = freeMagic1_init();
|
||||
for (reg = tReg; reg; reg = reg->treg_next)
|
||||
{
|
||||
/* Reset all ti_client fields to CLIENTDEFAULT */
|
||||
/* Reset all ti_client fields to extUnInit */
|
||||
arg.fra_uninit = (ClientData) reg;
|
||||
if (reg->treg_tile)
|
||||
{
|
||||
arg.fra_pNum = reg->treg_area;
|
||||
ExtFindNeighbors(reg->treg_tile, reg->treg_dinfo, arg.fra_pNum, &arg);
|
||||
ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg);
|
||||
}
|
||||
|
||||
/* Free all LabelLists and then the region */
|
||||
|
|
|
|||
|
|
@ -60,93 +60,34 @@ int extHierConnectFunc2();
|
|||
int extHierConnectFunc3();
|
||||
Node *extHierNewNode();
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* extTestNMInteract --
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* extHierSubShieldFunc -- */
|
||||
/* */
|
||||
/* Simple callback function for extHierSubstrate() that halts the */
|
||||
/* search if any substrate shield type is found in the search area */
|
||||
/* */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
int
|
||||
extHierSubShieldFunc(tile, dinfo, clientdata)
|
||||
Tile *tile; /* (unused) */
|
||||
TileType dinfo; /* (unused) */
|
||||
ClientData clientdata; /* (unused) */
|
||||
extHierSubShieldFunc(tile)
|
||||
Tile *tile;
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
* extHierSubstrate --
|
||||
*
|
||||
* Find the substrate node of a child cell and make a connection
|
||||
* between parent and child substrates. If either of the
|
||||
* 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
|
||||
* done.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
/*----------------------------------------------------------------------*/
|
||||
/* extHierSubstrate -- */
|
||||
/* */
|
||||
/* Find the substrate node of a child cell and make a connection */
|
||||
/* between parent and child substrates. If either of the */
|
||||
/* 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 */
|
||||
/* done. */
|
||||
/* */
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
void
|
||||
extHierSubstrate(ha, use, x, y)
|
||||
|
|
@ -183,7 +124,6 @@ extHierSubstrate(ha, use, x, y)
|
|||
/* The parent def's substrate node is in glob_subsnode */
|
||||
|
||||
name1 = extNodeName(glob_subsnode);
|
||||
if (*name1 == '(' && !strcmp(name1, "(none)")) return; /* Don't process "(none)" nodes! */
|
||||
he = HashFind(table, name1);
|
||||
nn = (NodeName *) HashGetValue(he);
|
||||
node1 = nn ? nn->nn_node : extHierNewNode(he);
|
||||
|
|
@ -192,7 +132,7 @@ extHierSubstrate(ha, use, x, y)
|
|||
nodeList = extFindNodes(use->cu_def, (Rect *) NULL, TRUE);
|
||||
if (nodeList == NULL)
|
||||
{
|
||||
ExtResetTiles(use->cu_def, CLIENTDEFAULT);
|
||||
ExtResetTiles(use->cu_def, extUnInit);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -232,7 +172,7 @@ extHierSubstrate(ha, use, x, y)
|
|||
extHierSubShieldFunc, (ClientData)NULL) != 0)
|
||||
{
|
||||
freeMagic(nodeList);
|
||||
ExtResetTiles(use->cu_def, CLIENTDEFAULT);
|
||||
ExtResetTiles(use->cu_def, extUnInit);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -241,7 +181,7 @@ extHierSubstrate(ha, use, x, y)
|
|||
/* Make sure substrate labels are represented */
|
||||
ExtLabelRegions(use->cu_def, ExtCurStyle->exts_nodeConn, &nodeList,
|
||||
&TiPlaneRect);
|
||||
ExtResetTiles(use->cu_def, CLIENTDEFAULT);
|
||||
ExtResetTiles(use->cu_def, extUnInit);
|
||||
|
||||
name2 = extNodeName(temp_subsnode);
|
||||
|
||||
|
|
@ -354,8 +294,8 @@ extHierConnections(ha, cumFlat, oneFlat)
|
|||
if (!(lab->lab_flags & LABEL_STICKY)) continue;
|
||||
|
||||
r = lab->lab_rect;
|
||||
if (!GEO_TOUCH(&r, &ha->ha_subArea)) continue;
|
||||
GEOCLIP(&r, &ha->ha_subArea);
|
||||
if (GEO_RECTNULL(&r)) continue;
|
||||
|
||||
cumDef = cumFlat->et_use->cu_def;
|
||||
connected = &DBConnectTbl[lab->lab_type];
|
||||
|
|
@ -385,9 +325,8 @@ extHierConnections(ha, cumFlat, oneFlat)
|
|||
*/
|
||||
|
||||
int
|
||||
extHierConnectFunc1(oneTile, dinfo, ha)
|
||||
extHierConnectFunc1(oneTile, ha)
|
||||
Tile *oneTile; /* Comes from 'oneFlat' in extHierConnections */
|
||||
TileType dinfo; /* Split tile information (unused) */
|
||||
HierExtractArg *ha; /* Extraction context */
|
||||
{
|
||||
CellDef *cumDef = extHierCumFlat->et_use->cu_def;
|
||||
|
|
@ -408,16 +347,12 @@ extHierConnectFunc1(oneTile, dinfo, ha)
|
|||
|
||||
if (IsSplit(oneTile))
|
||||
{
|
||||
/* For split tiles, move the tile type to lower (right side) field
|
||||
* but retain the TT_SIDE bit, to indicate which side of hierOneTile
|
||||
* is the connected side.
|
||||
*/
|
||||
ha->hierType = (dinfo & TT_SIDE) ? SplitRightType(oneTile) :
|
||||
rtype = ha->hierType;
|
||||
ha->hierType = (rtype & TT_SIDE) ? SplitRightType(oneTile) :
|
||||
SplitLeftType(oneTile);
|
||||
ha->hierType |= (dinfo & (TT_DIAGONAL | TT_DIRECTION | TT_SIDE));
|
||||
}
|
||||
|
||||
connected = &(ExtCurStyle->exts_nodeConn[ha->hierType & TT_LEFTMASK]);
|
||||
connected = &(ExtCurStyle->exts_nodeConn[ha->hierType]);
|
||||
TITORECT(oneTile, &r);
|
||||
GEOCLIP(&r, &ha->ha_subArea);
|
||||
r.r_xbot--, r.r_ybot--, r.r_xtop++, r.r_ytop++;
|
||||
|
|
@ -429,7 +364,7 @@ extHierConnectFunc1(oneTile, dinfo, ha)
|
|||
{
|
||||
if (IsSplit(oneTile))
|
||||
DBSrPaintNMArea((Tile *) NULL, cumDef->cd_planes[i],
|
||||
ha->hierType, &r,
|
||||
rtype, &r,
|
||||
((i == ha->hierPNum) ? &ExtCurStyle->exts_activeTypes
|
||||
: connected), extHierConnectFunc2, (ClientData) ha);
|
||||
else
|
||||
|
|
@ -477,9 +412,8 @@ extHierConnectFunc1(oneTile, dinfo, ha)
|
|||
nn = (NodeName *) HashGetValue(he);
|
||||
node1 = nn ? nn->nn_node : extHierNewNode(he);
|
||||
|
||||
name = (*ha->ha_nodename)(ha->hierOneTile, ha->hierType, ha->hierPNum,
|
||||
name = (*ha->ha_nodename)(ha->hierOneTile, ha->hierPNum,
|
||||
extHierOneFlat, ha, TRUE);
|
||||
if (*name == '(' && !strcmp(name, "(none)")) return 0; /* Don't process "(none)" nodes! */
|
||||
he = HashFind(table, name);
|
||||
nn = (NodeName *) HashGetValue(he);
|
||||
node2 = nn ? nn->nn_node : extHierNewNode(he);
|
||||
|
|
@ -541,9 +475,8 @@ extHierConnectFunc1(oneTile, dinfo, ha)
|
|||
*/
|
||||
|
||||
int
|
||||
extHierConnectFunc2(cum, dinfo, ha)
|
||||
extHierConnectFunc2(cum, ha)
|
||||
Tile *cum; /* Comes from extHierCumFlat->et_use->cu_def */
|
||||
TileType dinfo; /* Split tile information */
|
||||
HierExtractArg *ha; /* Extraction context */
|
||||
{
|
||||
HashTable *table = &ha->ha_connHash;
|
||||
|
|
@ -563,22 +496,7 @@ extHierConnectFunc2(cum, dinfo, ha)
|
|||
/* If the tiles don't even touch, they don't connect */
|
||||
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))
|
||||
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;
|
||||
}
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Only make a connection if the types of 'ha->hierOneTile' and 'cum'
|
||||
|
|
@ -589,19 +507,17 @@ extHierConnectFunc2(cum, dinfo, ha)
|
|||
ttype = TiGetTypeExact(cum);
|
||||
|
||||
if (IsSplit(cum))
|
||||
ttype = (dinfo & TT_SIDE) ? SplitRightType(cum) : SplitLeftType(cum);
|
||||
ttype = (ttype & TT_SIDE) ? SplitRightType(cum) : SplitLeftType(cum);
|
||||
|
||||
if (extConnectsTo(ha->hierType & TT_LEFTMASK, ttype, ExtCurStyle->exts_nodeConn))
|
||||
if (extConnectsTo(ha->hierType, ttype, ExtCurStyle->exts_nodeConn))
|
||||
{
|
||||
name1 = (*ha->ha_nodename)(cum, dinfo, ha->hierPNumBelow, extHierCumFlat, ha, TRUE);
|
||||
if (*name1 == '(' && !strcmp(name1, "(none)")) return 0; /* Don't process "(none)" nodes! */
|
||||
name1 = (*ha->ha_nodename)(cum, ha->hierPNumBelow, extHierCumFlat, ha, TRUE);
|
||||
he = HashFind(table, name1);
|
||||
nn = (NodeName *) HashGetValue(he);
|
||||
node1 = nn ? nn->nn_node : extHierNewNode(he);
|
||||
|
||||
name2 = (*ha->ha_nodename)(ha->hierOneTile, ha->hierType, ha->hierPNum,
|
||||
extHierOneFlat, ha, TRUE);
|
||||
if (*name2 == '(' && !strcmp(name2, "(none)")) return 0; /* Don't process "(none)" nodes! */
|
||||
name2 = (*ha->ha_nodename)(ha->hierOneTile, ha->hierPNum, extHierOneFlat,
|
||||
ha, TRUE);
|
||||
he = HashFind(table, name2);
|
||||
nn = (NodeName *) HashGetValue(he);
|
||||
node2 = nn ? nn->nn_node : extHierNewNode(he);
|
||||
|
|
@ -646,7 +562,7 @@ extHierConnectFunc2(cum, dinfo, ha)
|
|||
|
||||
snprintf(message, sizeof(message),
|
||||
"Illegal overlap between %s and %s (types do not connect)",
|
||||
DBTypeLongNameTbl[ha->hierType & TT_LEFTMASK], DBTypeLongNameTbl[ttype]);
|
||||
DBTypeLongNameTbl[ha->hierType], DBTypeLongNameTbl[ttype]);
|
||||
|
||||
extNumErrors++;
|
||||
if (!DebugIsSet(extDebugID, extDebNoFeedback))
|
||||
|
|
@ -668,9 +584,8 @@ extHierConnectFunc2(cum, dinfo, ha)
|
|||
*/
|
||||
|
||||
int
|
||||
extHierConnectFunc3(cum, dinfo, ha)
|
||||
extHierConnectFunc3(cum, ha)
|
||||
Tile *cum; /* Comes from extHierCumFlat->et_use->cu_def */
|
||||
TileType dinfo; /* Split tile information */
|
||||
HierExtractArg *ha; /* Extraction context */
|
||||
{
|
||||
HashTable *table = &ha->ha_connHash;
|
||||
|
|
@ -701,19 +616,16 @@ extHierConnectFunc3(cum, dinfo, ha)
|
|||
ttype = TiGetTypeExact(cum);
|
||||
|
||||
if (IsSplit(cum))
|
||||
ttype = (dinfo & TT_SIDE) ? SplitRightType(cum) : SplitLeftType(cum);
|
||||
ttype = (ttype & TT_SIDE) ? SplitRightType(cum) : SplitLeftType(cum);
|
||||
|
||||
if (extConnectsTo(ha->hierType & TT_LEFTMASK, ttype, ExtCurStyle->exts_nodeConn))
|
||||
if (extConnectsTo(ha->hierType, ttype, ExtCurStyle->exts_nodeConn))
|
||||
{
|
||||
name1 = (*ha->ha_nodename)(cum, ha->hierType, ha->hierPNumBelow,
|
||||
extHierCumFlat, ha, TRUE);
|
||||
if (*name1 == '(' && !strcmp(name1, "(none)")) return 0; /* Don't process "(none)" nodes! */
|
||||
name1 = (*ha->ha_nodename)(cum, ha->hierPNumBelow, extHierCumFlat, ha, TRUE);
|
||||
he = HashFind(table, name1);
|
||||
nn = (NodeName *) HashGetValue(he);
|
||||
node1 = nn ? nn->nn_node : extHierNewNode(he);
|
||||
|
||||
name2 = lab->lab_text;
|
||||
if (*name2 == '(' && !strcmp(name2, "(none)")) return 0; /* Don't process "(none)" nodes! */
|
||||
he = HashFind(table, name2);
|
||||
nn = (NodeName *) HashGetValue(he);
|
||||
node2 = nn ? nn->nn_node : extHierNewNode(he);
|
||||
|
|
@ -758,7 +670,7 @@ extHierConnectFunc3(cum, dinfo, ha)
|
|||
|
||||
snprintf(message, sizeof(message),
|
||||
"Illegal overlap between %s and %s (types do not connect)",
|
||||
DBTypeLongNameTbl[ha->hierType & TT_LEFTMASK], DBTypeLongNameTbl[ttype]);
|
||||
DBTypeLongNameTbl[ha->hierType], DBTypeLongNameTbl[ttype]);
|
||||
|
||||
extNumErrors++;
|
||||
if (!DebugIsSet(extDebugID, extDebNoFeedback))
|
||||
|
|
@ -859,20 +771,18 @@ extHierAdjustments(ha, cumFlat, oneFlat, lookFlat)
|
|||
*/
|
||||
for (np = oneFlat->et_nodes; np; np = np->nreg_next)
|
||||
{
|
||||
TileType dinfo;
|
||||
|
||||
/* Ignore orphaned nodes (non-Manhattan shards outside the clip box) */
|
||||
if (np->nreg_pnum == DBNumPlanes) continue;
|
||||
|
||||
tp = extNodeToTile(np, lookFlat, &dinfo);
|
||||
tp = extNodeToTile(np, lookFlat);
|
||||
|
||||
/* Ignore regions that do not participate in extraction */
|
||||
if (!extHasRegion(tp, CLIENTDEFAULT)) continue;
|
||||
if (!extHasRegion(tp, extUnInit)) continue;
|
||||
|
||||
/* Ignore substrate nodes (failsafe: should not happen) */
|
||||
if (TiGetTypeExact(tp) == TT_SPACE) continue;
|
||||
|
||||
if (tp && (name = (*ha->ha_nodename)(tp, dinfo, np->nreg_pnum, lookFlat, ha, FALSE))
|
||||
if (tp && (name = (*ha->ha_nodename)(tp, np->nreg_pnum, lookFlat, ha, FALSE))
|
||||
&& (he = HashLookOnly(&ha->ha_connHash, name))
|
||||
&& (nn = (NodeName *) HashGetValue(he)))
|
||||
{
|
||||
|
|
@ -1036,9 +946,8 @@ extHierNewNode(he)
|
|||
|
||||
/*ARGSUSED*/
|
||||
ExtRegion *
|
||||
extHierLabFirst(tile, dinfo, arg)
|
||||
extHierLabFirst(tile, arg)
|
||||
Tile *tile;
|
||||
TileType dinfo; /* (unused) */
|
||||
FindRegion *arg;
|
||||
{
|
||||
LabRegion *new;
|
||||
|
|
@ -1057,16 +966,15 @@ extHierLabFirst(tile, dinfo, arg)
|
|||
|
||||
/*ARGSUSED*/
|
||||
int
|
||||
extHierLabEach(tile, dinfo, pNum, arg)
|
||||
extHierLabEach(tile, pNum, arg)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
int pNum;
|
||||
FindRegion *arg;
|
||||
{
|
||||
LabRegion *reg;
|
||||
|
||||
reg = (LabRegion *) arg->fra_region;
|
||||
extSetNodeNum(reg, pNum, tile, dinfo);
|
||||
extSetNodeNum(reg, pNum, tile);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -270,9 +270,8 @@ extInterSubtreeElement(use, trans, x, y, r)
|
|||
*/
|
||||
|
||||
int
|
||||
extInterSubtreeTile(tile, dinfo, cxp)
|
||||
extInterSubtreeTile(tile, cxp)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
TreeContext *cxp;
|
||||
{
|
||||
SearchContext newscx;
|
||||
|
|
|
|||
|
|
@ -434,9 +434,8 @@ extLengthYank(use, labList)
|
|||
*/
|
||||
|
||||
int
|
||||
extLengthLabels(tile, dinfo, rootUse)
|
||||
Tile *tile; /* Some tile in extPathDef */
|
||||
TileType dinfo; /* Split tile information (unused) */
|
||||
extLengthLabels(tile, rootUse)
|
||||
Tile *tile; /* Some tile in extPathDef */
|
||||
CellUse *rootUse; /* The original root cell */
|
||||
{
|
||||
char name[MAXNAMESIZE];
|
||||
|
|
@ -728,9 +727,8 @@ extPathResetClient(tile)
|
|||
*/
|
||||
|
||||
int
|
||||
extPathPairFunc(tile, dinfo, epa)
|
||||
extPathPairFunc(tile, epa)
|
||||
Tile *tile;
|
||||
TileType dinfo; // Unused
|
||||
struct extPathArg *epa;
|
||||
{
|
||||
Point startPoint;
|
||||
|
|
@ -911,9 +909,8 @@ extPathFlood(tile, p, distance, epa)
|
|||
}
|
||||
|
||||
int
|
||||
extPathFloodFunc(dstTile, dinfo, epfa)
|
||||
extPathFloodFunc(dstTile, epfa)
|
||||
Tile *dstTile;
|
||||
TileType dinfo; // Unused
|
||||
struct extPathFloodArg *epfa;
|
||||
{
|
||||
Rect srcRect, dstRect;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "debug/debug.h"
|
||||
#include "extract/extract.h"
|
||||
#include "extract/extractInt.h"
|
||||
#include "resis/resis.h"
|
||||
#include "utils/signals.h"
|
||||
#include "utils/stack.h"
|
||||
#include "utils/utils.h"
|
||||
|
|
@ -44,6 +43,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "utils/main.h"
|
||||
#include "utils/undo.h"
|
||||
|
||||
/* Imports from elsewhere in this module */
|
||||
extern FILE *extFileOpen();
|
||||
|
||||
/* ------------------------ Exported variables ------------------------ */
|
||||
|
||||
/*
|
||||
|
|
@ -81,6 +83,16 @@ typedef struct _linkedDef {
|
|||
struct _linkedDef *ld_next;
|
||||
} 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 *extDefStack;
|
||||
|
||||
|
|
@ -197,10 +209,9 @@ extIsUsedFunc(use, clientData)
|
|||
*/
|
||||
|
||||
int
|
||||
extEnumFunc(tile, dinfo, clientdata)
|
||||
Tile *tile; /* (unused) */
|
||||
TileType dinfo; /* (unused) */
|
||||
ClientData clientdata; /* (unused) */
|
||||
extEnumFunc(tile, plane)
|
||||
Tile *tile;
|
||||
int *plane;
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -594,7 +605,7 @@ extParents(use, doExtract)
|
|||
extDefParentFunc(use->cu_def);
|
||||
|
||||
/* Now extract all the cells we just found */
|
||||
extExtractStack(extDefStack, doExtract, (CellDef *)NULL);
|
||||
extExtractStack(extDefStack, doExtract, (CellDef *) NULL);
|
||||
StackFree(extDefStack);
|
||||
|
||||
/* Replace any modified substrate planes in use->cu_def's children */
|
||||
|
|
@ -676,7 +687,7 @@ ExtParentArea(use, changedArea, doExtract)
|
|||
extDefParentAreaFunc(use->cu_def, use->cu_def, (CellUse *) NULL, &area);
|
||||
|
||||
/* Now extract all the cells we just found */
|
||||
extExtractStack(extDefStack, doExtract, (CellDef *)NULL);
|
||||
extExtractStack(extDefStack, doExtract, (CellDef *) NULL);
|
||||
StackFree(extDefStack);
|
||||
}
|
||||
|
||||
|
|
@ -794,30 +805,12 @@ ExtractOneCell(def, outName, doLength)
|
|||
|
||||
savePlane = ExtCell(def, outName, doLength);
|
||||
|
||||
/* 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 */
|
||||
/* Restore all modified substrate planes */
|
||||
|
||||
if (savePlane != NULL) ExtRevertSubstrate(def, savePlane);
|
||||
free_magic1_t mm1 = freeMagic1_init();
|
||||
for (; sl; sl = sl->sl_next)
|
||||
{
|
||||
if (EXT_DOUNIQUE) ExtRevertUniqueCell(sl->sl_def);
|
||||
ExtRevertSubstrate(sl->sl_def, sl->sl_plane);
|
||||
freeMagic1(&mm1, sl);
|
||||
}
|
||||
|
|
@ -861,10 +854,7 @@ extContainsCellFunc(
|
|||
}
|
||||
|
||||
int
|
||||
extContainsPaintFunc(
|
||||
Tile *tile, /* (unused) */
|
||||
TileType dinfo, /* (unused) */
|
||||
ClientData clientdata) /* (unused) */
|
||||
extContainsPaintFunc()
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
|
@ -950,7 +940,7 @@ extTimestampMisMatch(def)
|
|||
|
||||
doLocal = (ExtLocalPath == NULL) ? FALSE : TRUE;
|
||||
|
||||
extFile = ExtFileOpen(def, (char *) NULL, "r", (char **) NULL);
|
||||
extFile = extFileOpen(def, (char *) NULL, "r", (char **) NULL);
|
||||
if (extFile == NULL)
|
||||
return (TRUE);
|
||||
|
||||
|
|
@ -996,18 +986,10 @@ extExtractStack(stack, doExtract, rootDef)
|
|||
bool first = TRUE;
|
||||
Plane *savePlane;
|
||||
CellDef *def;
|
||||
LinkedDef *savelist = NULL, *revlist = NULL, *newld;
|
||||
struct saveList *newsl, *sl = (struct saveList *)NULL;
|
||||
|
||||
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;
|
||||
if (!SigInterruptPending)
|
||||
{
|
||||
|
|
@ -1022,8 +1004,6 @@ extExtractStack(stack, doExtract, rootDef)
|
|||
newsl->sl_next = sl;
|
||||
sl = newsl;
|
||||
}
|
||||
else
|
||||
def->cd_flags &= ~CDNOEXTRACT;
|
||||
|
||||
errorcnt += extNumErrors;
|
||||
warnings += extNumWarnings;
|
||||
|
|
@ -1035,55 +1015,13 @@ extExtractStack(stack, doExtract, rootDef)
|
|||
TxFlush();
|
||||
first = FALSE;
|
||||
}
|
||||
else
|
||||
def->cd_flags &= ~CDNOEXTRACT;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
/* Replace any modified substrate planes */
|
||||
free_magic1_t mm1 = freeMagic1_init();
|
||||
for (; sl; sl = sl->sl_next)
|
||||
{
|
||||
if (EXT_DOUNIQUE) ExtRevertUniqueCell(sl->sl_def);
|
||||
|
||||
ExtRevertSubstrate(sl->sl_def, sl->sl_plane);
|
||||
sl->sl_def->cd_flags &= ~CDNOEXTRACT;
|
||||
freeMagic1(&mm1, sl);
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
* the value VISITPENDING in its ti_client field.
|
||||
*/
|
||||
|
||||
/* Used for communicating with extNbrPushFunc */
|
||||
ClientData extNbrUn;
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -71,44 +74,41 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
*/
|
||||
|
||||
int
|
||||
ExtFindNeighbors(tile, dinfo, tilePlaneNum, arg)
|
||||
ExtFindNeighbors(tile, tilePlaneNum, arg)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
int tilePlaneNum;
|
||||
FindRegion *arg;
|
||||
{
|
||||
TileTypeBitMask *connTo = arg->fra_connectsTo;
|
||||
Tile *tp;
|
||||
TileType type, t, tpdinfo;
|
||||
TileType type, t;
|
||||
TileTypeBitMask *mask;
|
||||
Rect biggerArea;
|
||||
int pNum, tilesfound;
|
||||
PlaneMask pMask;
|
||||
PlaneAndArea pla;
|
||||
ClientData extNbrUn = arg->fra_uninit;
|
||||
|
||||
tilesfound = 0;
|
||||
|
||||
extNbrUn = arg->fra_uninit;
|
||||
if (extNodeStack == (Stack *) NULL)
|
||||
extNodeStack = StackNew(64);
|
||||
|
||||
/* Mark this tile as pending and push it */
|
||||
PUSHTILE(tile, dinfo, tilePlaneNum);
|
||||
PUSHTILE(tile, tilePlaneNum);
|
||||
|
||||
while (!StackEmpty(extNodeStack))
|
||||
{
|
||||
POPTILE(tile, dinfo, tilePlaneNum);
|
||||
POPTILE(tile, tilePlaneNum);
|
||||
|
||||
if (IsSplit(tile))
|
||||
{
|
||||
type = (dinfo & TT_SIDE) ? SplitRightType(tile):
|
||||
type = (SplitSide(tile)) ? SplitRightType(tile):
|
||||
SplitLeftType(tile);
|
||||
}
|
||||
else
|
||||
type = TiGetTypeExact(tile);
|
||||
|
||||
ASSERT(type != TT_SPACE, "ExtFindNeighbors");
|
||||
|
||||
mask = &connTo[type];
|
||||
|
||||
/*
|
||||
|
|
@ -117,27 +117,23 @@ ExtFindNeighbors(tile, dinfo, tilePlaneNum, arg)
|
|||
* been visited in the meantime. If it's still unvisited,
|
||||
* visit it and process its neighbors.
|
||||
*/
|
||||
|
||||
if (ExtGetRegion(tile, dinfo) == arg->fra_region)
|
||||
if (TiGetClientPTR(tile) == arg->fra_region)
|
||||
continue;
|
||||
|
||||
ExtSetRegion(tile, dinfo, arg->fra_region);
|
||||
|
||||
TiSetClientPTR(tile, arg->fra_region);
|
||||
tilesfound++;
|
||||
if (DebugIsSet(extDebugID, extDebNeighbor))
|
||||
extShowTile(tile, "neighbor", 1);
|
||||
|
||||
/* Top */
|
||||
topside:
|
||||
if (IsSplit(tile) && ((dinfo & TT_SIDE) ? 1 : 0) ^ SplitDirection(tile))
|
||||
goto leftside;
|
||||
if (IsSplit(tile) && (SplitSide(tile) ^ SplitDirection(tile))) goto leftside;
|
||||
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp))
|
||||
{
|
||||
if (IsSplit(tp))
|
||||
{
|
||||
t = SplitBottomType(tp);
|
||||
tpdinfo = SplitDirection(tp) ? (TileType)0 : (TileType)TT_SIDE;
|
||||
if (ExtGetRegion(tp, tpdinfo) == CD2PTR(extNbrUn) && TTMaskHasType(mask, t))
|
||||
// if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
||||
if (TiGetClientPTR(tp) != arg->fra_region && TTMaskHasType(mask, t))
|
||||
{
|
||||
PUSHTILEBOTTOM(tp, tilePlaneNum);
|
||||
}
|
||||
|
|
@ -147,21 +143,21 @@ topside:
|
|||
t = TiGetTypeExact(tp);
|
||||
if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
||||
{
|
||||
PUSHTILELEFT(tp, tilePlaneNum);
|
||||
PUSHTILE(tp, tilePlaneNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Left */
|
||||
leftside:
|
||||
if (IsSplit(tile) && (dinfo & TT_SIDE)) goto bottomside;
|
||||
if (IsSplit(tile) && SplitSide(tile)) goto bottomside;
|
||||
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
|
||||
{
|
||||
if (IsSplit(tp))
|
||||
{
|
||||
t = SplitRightType(tp);
|
||||
if (ExtGetRegion(tp, (TileType)TT_SIDE) == CD2PTR(extNbrUn)
|
||||
&& TTMaskHasType(mask, t))
|
||||
// if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
||||
if (TiGetClientPTR(tp) != arg->fra_region && TTMaskHasType(mask, t))
|
||||
{
|
||||
PUSHTILERIGHT(tp, tilePlaneNum);
|
||||
}
|
||||
|
|
@ -171,22 +167,22 @@ leftside:
|
|||
t = TiGetTypeExact(tp);
|
||||
if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
||||
{
|
||||
PUSHTILELEFT(tp, tilePlaneNum);
|
||||
PUSHTILE(tp, tilePlaneNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Bottom */
|
||||
bottomside:
|
||||
if (IsSplit(tile) && (!(((dinfo & TT_SIDE) ? 1 : 0) ^ SplitDirection(tile))))
|
||||
if (IsSplit(tile) && (!(SplitSide(tile) ^ SplitDirection(tile))))
|
||||
goto rightside;
|
||||
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
|
||||
{
|
||||
if (IsSplit(tp))
|
||||
{
|
||||
t = SplitTopType(tp);
|
||||
tpdinfo = SplitDirection(tp) ? (TileType)TT_SIDE : (TileType)0;
|
||||
if (ExtGetRegion(tp, tpdinfo) == CD2PTR(extNbrUn) && TTMaskHasType(mask, t))
|
||||
// if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
||||
if (TiGetClientPTR(tp) != arg->fra_region && TTMaskHasType(mask, t))
|
||||
{
|
||||
PUSHTILETOP(tp, tilePlaneNum);
|
||||
}
|
||||
|
|
@ -196,21 +192,21 @@ bottomside:
|
|||
t = TiGetTypeExact(tp);
|
||||
if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
||||
{
|
||||
PUSHTILELEFT(tp, tilePlaneNum);
|
||||
PUSHTILE(tp, tilePlaneNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Right */
|
||||
rightside:
|
||||
if (IsSplit(tile) && !(dinfo & TT_SIDE)) goto donesides;
|
||||
if (IsSplit(tile) && !SplitSide(tile)) goto donesides;
|
||||
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp))
|
||||
{
|
||||
if (IsSplit(tp))
|
||||
{
|
||||
t = SplitLeftType(tp);
|
||||
if (ExtGetRegion(tp, (TileType)0) == CD2PTR(extNbrUn)
|
||||
&& TTMaskHasType(mask, t))
|
||||
// if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
||||
if (TiGetClientPTR(tp) != arg->fra_region && TTMaskHasType(mask, t))
|
||||
{
|
||||
PUSHTILELEFT(tp, tilePlaneNum);
|
||||
}
|
||||
|
|
@ -220,7 +216,7 @@ rightside:
|
|||
t = TiGetTypeExact(tp);
|
||||
if (TiGetClient(tp) == extNbrUn && TTMaskHasType(mask, t))
|
||||
{
|
||||
PUSHTILELEFT(tp, tilePlaneNum);
|
||||
PUSHTILE(tp, tilePlaneNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -228,14 +224,9 @@ rightside:
|
|||
donesides:
|
||||
/* Apply the client's filter procedure if one exists */
|
||||
if (arg->fra_each)
|
||||
if ((*arg->fra_each)(tile, dinfo, tilePlaneNum, arg))
|
||||
if ((*arg->fra_each)(tile, tilePlaneNum, arg))
|
||||
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 (DBIsContact(type))
|
||||
{
|
||||
|
|
@ -244,7 +235,6 @@ donesides:
|
|||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||
if (PlaneMaskHasPlane(pMask, pNum))
|
||||
{
|
||||
ExtRegion *tpreg;
|
||||
Plane *plane = arg->fra_def->cd_planes[pNum];
|
||||
|
||||
/* Find the point on the new plane */
|
||||
|
|
@ -252,14 +242,14 @@ donesides:
|
|||
GOTOPOINT(tp, &tile->ti_ll);
|
||||
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 */
|
||||
if (IsSplit(tile) && IsSplit(tp))
|
||||
{
|
||||
if (dinfo & TT_SIDE)
|
||||
if (SplitSide(tile))
|
||||
{
|
||||
/* Only process tp if not yet visited */
|
||||
tpreg = ExtGetRegion(tp, (TileType)TT_SIDE);
|
||||
if (tpreg != CD2PTR(extNbrUn)) continue;
|
||||
t = SplitRightType(tp);
|
||||
if (TTMaskHasType(mask, t))
|
||||
{
|
||||
|
|
@ -268,9 +258,6 @@ donesides:
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Only process tp if not yet visited */
|
||||
tpreg = ExtGetRegion(tp, (TileType)0);
|
||||
if (tpreg != CD2PTR(extNbrUn)) continue;
|
||||
t = SplitLeftType(tp);
|
||||
if (TTMaskHasType(mask, t))
|
||||
{
|
||||
|
|
@ -280,36 +267,23 @@ donesides:
|
|||
}
|
||||
else if (IsSplit(tp))
|
||||
{
|
||||
/* Only process tp if not yet visited */
|
||||
tpreg = ExtGetRegion(tp, (TileType)TT_SIDE);
|
||||
if (tpreg == CD2PTR(extNbrUn))
|
||||
t = SplitRightType(tp);
|
||||
if (TTMaskHasType(mask, t))
|
||||
{
|
||||
t = SplitRightType(tp);
|
||||
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);
|
||||
if (TTMaskHasType(mask, t))
|
||||
{
|
||||
t = SplitLeftType(tp);
|
||||
if (TTMaskHasType(mask, t))
|
||||
{
|
||||
PUSHTILELEFT(tp, pNum);
|
||||
}
|
||||
PUSHTILELEFT(tp, pNum);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Only process tp if not yet visited */
|
||||
tpreg = ExtGetRegion(tp, (TileType)0);
|
||||
if (tpreg != CD2PTR(extNbrUn)) continue;
|
||||
t = TiGetTypeExact(tp);
|
||||
if (TTMaskHasType(mask, t))
|
||||
{
|
||||
PUSHTILELEFT(tp, pNum);
|
||||
PUSHTILE(tp, pNum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -326,28 +300,27 @@ donesides:
|
|||
*/
|
||||
if ((pMask = DBAllConnPlanes[type]))
|
||||
{
|
||||
pla.uninit = extNbrUn;
|
||||
TITORECT(tile, &pla.area);
|
||||
GEO_EXPAND(&pla.area, 1, &biggerArea);
|
||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||
if ((pNum != tilePlaneNum) && PlaneMaskHasPlane(pMask, pNum))
|
||||
{
|
||||
pla.plane = pNum;
|
||||
(void) DBSrPaintNMArea((Tile *) NULL,
|
||||
arg->fra_def->cd_planes[pNum],
|
||||
TiGetTypeExact(tile) | dinfo, &biggerArea,
|
||||
(void) DBSrPaintArea((Tile *) NULL,
|
||||
arg->fra_def->cd_planes[pNum], &biggerArea,
|
||||
mask, extNbrPushFunc, (ClientData) &pla);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tilesfound;
|
||||
|
||||
fail:
|
||||
/* Flush the stack */
|
||||
while (!StackEmpty(extNodeStack))
|
||||
{
|
||||
POPTILE(tile, dinfo, tilePlaneNum);
|
||||
ExtSetRegion(tile, dinfo, arg->fra_region);
|
||||
POPTILE(tile, tilePlaneNum);
|
||||
TiSetClientPTR(tile, arg->fra_region);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -362,9 +335,9 @@ fail:
|
|||
* with tileArea, and it hasn't already been visited, push it on the stack
|
||||
* extNodeStack.
|
||||
*
|
||||
* Uses the value pla->uninit to determine whether or not a tile has been
|
||||
* visited; if the tile's client field is equal to pla->uninit, then this
|
||||
* is the first time the tile has been seen.
|
||||
* Uses the global parameter extNbrUn to determine whether or not a tile
|
||||
* has been visited; if the tile's client field is equal to extNbrUn, then
|
||||
* this is the first time the tile has been seen.
|
||||
*
|
||||
* Results:
|
||||
* Always returns 0.
|
||||
|
|
@ -376,9 +349,8 @@ fail:
|
|||
*/
|
||||
|
||||
int
|
||||
extNbrPushFunc(tile, dinfo, pla)
|
||||
extNbrPushFunc(tile, pla)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
PlaneAndArea *pla;
|
||||
{
|
||||
Rect *tileArea;
|
||||
|
|
@ -387,7 +359,7 @@ extNbrPushFunc(tile, dinfo, pla)
|
|||
tileArea = &pla->area;
|
||||
|
||||
/* Ignore tile if it's already been visited */
|
||||
if (ExtGetRegion(tile, dinfo) != CD2PTR(pla->uninit))
|
||||
if (TiGetClient(tile) != extNbrUn)
|
||||
return 0;
|
||||
|
||||
/* Only consider tile if it overlaps tileArea or shares part of a side */
|
||||
|
|
@ -400,233 +372,7 @@ extNbrPushFunc(tile, dinfo, pla)
|
|||
}
|
||||
|
||||
/* Push tile on the stack and mark as being visited */
|
||||
PUSHTILE(tile, dinfo, pla->plane);
|
||||
PUSHTILE(tile, pla->plane);
|
||||
|
||||
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) */
|
||||
(void)0; /* older compilers need a statement after the label to prevent a compile error */
|
||||
}
|
||||
|
||||
/* 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/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 the callback function is ignored.
|
||||
* The value returned by this function is ignored.
|
||||
*
|
||||
* Results:
|
||||
* 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.
|
||||
*
|
||||
* Note:
|
||||
* The width/length calculation method is manhattan-only, and will
|
||||
* likely need correcting. This routine computes the true perimeter
|
||||
* length and calls the callback function on the perimeter tiles of
|
||||
* the correct tile type.
|
||||
* The width/length calculation method is manhattan-only. So this
|
||||
* routine is pseudo-manhattan. It computes the true non-manhattan
|
||||
* perimeter, but calls the function on the perimeter tiles as if
|
||||
* the whole tile is the transistor type.
|
||||
*
|
||||
* Non-interruptible.
|
||||
*
|
||||
|
|
@ -81,34 +81,28 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
int
|
||||
extEnumTilePerim(
|
||||
Tile *tpIn,
|
||||
TileType dinfo,
|
||||
const TileTypeBitMask *maskp,
|
||||
int pNum, /* Plane of perimeter */
|
||||
int (*func)(),
|
||||
ClientData cdata)
|
||||
{
|
||||
TileTypeBitMask mask = *maskp;
|
||||
TileTypeBitMask mask = *maskp; /* TTMaskCopy(&mask, maskp) */
|
||||
TileType origType;
|
||||
Tile *tpOut;
|
||||
int perimCorrect;
|
||||
Boundary b;
|
||||
unsigned char sides = 0; /* Sides to be ignored */
|
||||
unsigned char sides = 0;
|
||||
|
||||
b.b_inside = tpIn;
|
||||
b.b_plane = pNum;
|
||||
perimCorrect = 0;
|
||||
|
||||
/* Diagonal */
|
||||
if (IsSplit(tpIn))
|
||||
{
|
||||
/* Handle a diagonal boundary across a split tile.
|
||||
* "dinfo" determines which side of the split tile is considered "inside" the
|
||||
* 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);
|
||||
|
||||
TileType otype = (SplitSide(tpIn)) ? SplitLeftType(tpIn): SplitRightType(tpIn);
|
||||
TileType itype = (SplitSide(tpIn)) ? SplitRightType(tpIn): SplitLeftType(tpIn);
|
||||
origType = TiGetTypeExact(tpIn);
|
||||
if (TTMaskHasType(&mask, otype))
|
||||
{
|
||||
int width = RIGHT(tpIn) - LEFT(tpIn);
|
||||
|
|
@ -116,104 +110,75 @@ extEnumTilePerim(
|
|||
perimCorrect = width * width + height * height;
|
||||
perimCorrect = (int)sqrt((double)perimCorrect);
|
||||
}
|
||||
|
||||
/* Invoke the callback function on diagonal boundaries */
|
||||
|
||||
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;
|
||||
sides = (SplitSide(tpIn)) ? BD_LEFT : BD_RIGHT;
|
||||
sides |= (SplitSide(tpIn) == SplitDirection(tpIn)) ? BD_BOTTOM : BD_TOP;
|
||||
TiSetBody(tpIn, itype);
|
||||
}
|
||||
else
|
||||
sides = 0;
|
||||
|
||||
/* Top */
|
||||
if (!(sides & BD_TOP))
|
||||
b.b_segment.r_ybot = b.b_segment.r_ytop = TOP(tpIn);
|
||||
b.b_direction = BD_TOP;
|
||||
for (tpOut = RT(tpIn); RIGHT(tpOut) > LEFT(tpIn); tpOut = BL(tpOut))
|
||||
{
|
||||
b.b_segment.r_ybot = b.b_segment.r_ytop = TOP(tpIn);
|
||||
b.b_direction = BD_TOP;
|
||||
for (tpOut = RT(tpIn); RIGHT(tpOut) > LEFT(tpIn); tpOut = BL(tpOut))
|
||||
if (TTMaskHasType(&mask, TiGetBottomType(tpOut)))
|
||||
{
|
||||
if (TTMaskHasType(&mask, TiGetBottomType(tpOut)))
|
||||
{
|
||||
b.b_segment.r_xbot = MAX(LEFT(tpIn), LEFT(tpOut));
|
||||
b.b_segment.r_xtop = MIN(RIGHT(tpIn), RIGHT(tpOut));
|
||||
b.b_outside = tpOut;
|
||||
if (func) (*func)(&b, cdata);
|
||||
}
|
||||
b.b_segment.r_xbot = MAX(LEFT(tpIn), LEFT(tpOut));
|
||||
b.b_segment.r_xtop = MIN(RIGHT(tpIn), RIGHT(tpOut));
|
||||
b.b_outside = tpOut;
|
||||
if (sides & BD_TOP) perimCorrect -= BoundaryLength(&b);
|
||||
if (func) (*func)(&b, cdata);
|
||||
}
|
||||
}
|
||||
|
||||
/* Bottom */
|
||||
if (!(sides & BD_BOTTOM))
|
||||
b.b_segment.r_ybot = b.b_segment.r_ytop = BOTTOM(tpIn);
|
||||
b.b_direction = BD_BOTTOM;
|
||||
for (tpOut = LB(tpIn); LEFT(tpOut) < RIGHT(tpIn); tpOut = TR(tpOut))
|
||||
{
|
||||
b.b_segment.r_ybot = b.b_segment.r_ytop = BOTTOM(tpIn);
|
||||
b.b_direction = BD_BOTTOM;
|
||||
for (tpOut = LB(tpIn); LEFT(tpOut) < RIGHT(tpIn); tpOut = TR(tpOut))
|
||||
if (TTMaskHasType(&mask, TiGetTopType(tpOut)))
|
||||
{
|
||||
if (TTMaskHasType(&mask, TiGetTopType(tpOut)))
|
||||
{
|
||||
b.b_segment.r_xbot = MAX(LEFT(tpIn), LEFT(tpOut));
|
||||
b.b_segment.r_xtop = MIN(RIGHT(tpIn), RIGHT(tpOut));
|
||||
b.b_outside = tpOut;
|
||||
if (func) (*func)(&b, cdata);
|
||||
}
|
||||
b.b_segment.r_xbot = MAX(LEFT(tpIn), LEFT(tpOut));
|
||||
b.b_segment.r_xtop = MIN(RIGHT(tpIn), RIGHT(tpOut));
|
||||
b.b_outside = tpOut;
|
||||
if (sides & BD_BOTTOM) perimCorrect -= BoundaryLength(&b);
|
||||
if (func) (*func)(&b, cdata);
|
||||
}
|
||||
}
|
||||
|
||||
/* Left */
|
||||
if (!(sides & BD_LEFT))
|
||||
b.b_segment.r_xbot = b.b_segment.r_xtop = LEFT(tpIn);
|
||||
b.b_direction = BD_LEFT;
|
||||
for (tpOut = BL(tpIn); BOTTOM(tpOut) < TOP(tpIn); tpOut = RT(tpOut))
|
||||
{
|
||||
b.b_segment.r_xbot = b.b_segment.r_xtop = LEFT(tpIn);
|
||||
b.b_direction = BD_LEFT;
|
||||
for (tpOut = BL(tpIn); BOTTOM(tpOut) < TOP(tpIn); tpOut = RT(tpOut))
|
||||
if (TTMaskHasType(&mask, TiGetRightType(tpOut)))
|
||||
{
|
||||
if (TTMaskHasType(&mask, TiGetRightType(tpOut)))
|
||||
{
|
||||
b.b_segment.r_ybot = MAX(BOTTOM(tpIn), BOTTOM(tpOut));
|
||||
b.b_segment.r_ytop = MIN(TOP(tpIn), TOP(tpOut));
|
||||
b.b_outside = tpOut;
|
||||
if (func) (*func)(&b, cdata);
|
||||
}
|
||||
b.b_segment.r_ybot = MAX(BOTTOM(tpIn), BOTTOM(tpOut));
|
||||
b.b_segment.r_ytop = MIN(TOP(tpIn), TOP(tpOut));
|
||||
b.b_outside = tpOut;
|
||||
if (sides & BD_LEFT) perimCorrect -= BoundaryLength(&b);
|
||||
if (func) (*func)(&b, cdata);
|
||||
}
|
||||
}
|
||||
|
||||
/* Right */
|
||||
if (!(sides & BD_RIGHT))
|
||||
b.b_segment.r_xbot = b.b_segment.r_xtop = RIGHT(tpIn);
|
||||
b.b_direction = BD_RIGHT;
|
||||
for (tpOut = TR(tpIn); TOP(tpOut) > BOTTOM(tpIn); tpOut = LB(tpOut))
|
||||
{
|
||||
b.b_segment.r_xbot = b.b_segment.r_xtop = RIGHT(tpIn);
|
||||
b.b_direction = BD_RIGHT;
|
||||
for (tpOut = TR(tpIn); TOP(tpOut) > BOTTOM(tpIn); tpOut = LB(tpOut))
|
||||
if (TTMaskHasType(&mask, TiGetLeftType(tpOut)))
|
||||
{
|
||||
if (TTMaskHasType(&mask, TiGetLeftType(tpOut)))
|
||||
{
|
||||
b.b_segment.r_ybot = MAX(BOTTOM(tpIn), BOTTOM(tpOut));
|
||||
b.b_segment.r_ytop = MIN(TOP(tpIn), TOP(tpOut));
|
||||
b.b_outside = tpOut;
|
||||
if (func) (*func)(&b, cdata);
|
||||
}
|
||||
b.b_segment.r_ybot = MAX(BOTTOM(tpIn), BOTTOM(tpOut));
|
||||
b.b_segment.r_ytop = MIN(TOP(tpIn), TOP(tpOut));
|
||||
b.b_outside = tpOut;
|
||||
if (sides & BD_RIGHT) perimCorrect -= BoundaryLength(&b);
|
||||
if (func) (*func)(&b, cdata);
|
||||
}
|
||||
}
|
||||
|
||||
if (sides != 0)
|
||||
TiSetBody(tpIn, origType);
|
||||
|
||||
return (perimCorrect);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,58 +36,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "extract/extractInt.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;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -105,7 +53,6 @@ ExtGetRegion(Tile *tp, /* Tile to get region record from */
|
|||
* ExtRegion *
|
||||
* (*first)(tile, arg)
|
||||
* Tile *tile; /# Tile is on plane arg->fra_pNum #/
|
||||
* TileType dinfo; /# Split tile information #/
|
||||
* FindRegion *arg;
|
||||
* {
|
||||
* }
|
||||
|
|
@ -115,7 +62,6 @@ ExtGetRegion(Tile *tp, /* Tile to get region record from */
|
|||
*
|
||||
* (*each)(tile, planeNum, arg)
|
||||
* Tile *tile;
|
||||
* TileType dinfo; /# Split tile information #/
|
||||
* int planeNum; /# May be different than arg->fra_pNum #/
|
||||
* FindRegion *arg;
|
||||
* {
|
||||
|
|
@ -139,7 +85,7 @@ ExtGetRegion(Tile *tp, /* Tile to get region record from */
|
|||
*/
|
||||
|
||||
ExtRegion *
|
||||
ExtFindRegions(def, area, mask, connectsTo, first, each)
|
||||
ExtFindRegions(def, area, mask, connectsTo, uninit, first, each)
|
||||
CellDef *def; /* Cell definition being searched */
|
||||
Rect *area; /* Area to search initially for tiles */
|
||||
TileTypeBitMask *mask; /* In the initial area search, only visit
|
||||
|
|
@ -155,6 +101,9 @@ ExtFindRegions(def, area, mask, connectsTo, first, each)
|
|||
* so this is the same as:
|
||||
* 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 */
|
||||
int (*each)(); /* Applied to each tile in region */
|
||||
{
|
||||
|
|
@ -164,7 +113,7 @@ ExtFindRegions(def, area, mask, connectsTo, first, each)
|
|||
ASSERT(first != NULL, "ExtFindRegions");
|
||||
arg.fra_connectsTo = connectsTo;
|
||||
arg.fra_def = def;
|
||||
arg.fra_uninit = CLIENTDEFAULT;
|
||||
arg.fra_uninit = uninit;
|
||||
arg.fra_first = first;
|
||||
arg.fra_each = each;
|
||||
arg.fra_region = (ExtRegion *) NULL;
|
||||
|
|
@ -175,7 +124,7 @@ ExtFindRegions(def, area, mask, connectsTo, first, each)
|
|||
SigDisableInterrupts();
|
||||
for (arg.fra_pNum=PL_TECHDEPBASE; arg.fra_pNum<DBNumPlanes; arg.fra_pNum++)
|
||||
(void) DBSrPaintClient((Tile *) NULL, def->cd_planes[arg.fra_pNum],
|
||||
area, mask, CLIENTDEFAULT, extRegionAreaFunc, (ClientData) &arg);
|
||||
area, mask, uninit, extRegionAreaFunc, (ClientData) &arg);
|
||||
SigEnableInterrupts();
|
||||
|
||||
return (arg.fra_region);
|
||||
|
|
@ -206,20 +155,19 @@ ExtFindRegions(def, area, mask, connectsTo, first, each)
|
|||
*/
|
||||
|
||||
int
|
||||
extRegionAreaFunc(tile, dinfo, arg)
|
||||
extRegionAreaFunc(tile, arg)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
FindRegion *arg;
|
||||
{
|
||||
/* Allocate a new region */
|
||||
if (arg->fra_first)
|
||||
(void) (*arg->fra_first)(tile, dinfo, arg);
|
||||
(void) (*arg->fra_first)(tile, arg);
|
||||
|
||||
if (DebugIsSet(extDebugID, extDebAreaEnum))
|
||||
extShowTile(tile, "area enum", 0);
|
||||
|
||||
/* Recursively visit all tiles surrounding this one that we connect to */
|
||||
(void) ExtFindNeighbors(tile, dinfo, arg->fra_pNum, arg);
|
||||
(void) ExtFindNeighbors(tile, arg->fra_pNum, arg);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
@ -232,7 +180,7 @@ extRegionAreaFunc(tile, dinfo, arg)
|
|||
* Given a CellDef whose tiles have been set to point to LabRegions
|
||||
* by ExtFindRegions, walk down the label list and assign labels
|
||||
* to regions. If the tile over which a label lies is still uninitialized
|
||||
* ie, points to CLIENTDEFAULT, we skip the label.
|
||||
* ie, points to extUnInit, we skip the label.
|
||||
*
|
||||
* 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
|
||||
|
|
@ -297,10 +245,10 @@ ExtLabelRegions(def, connTo, nodeList, clipArea)
|
|||
GOTOPOINT(tp, &p);
|
||||
PlaneSetHint(def->cd_planes[pNum], tp);
|
||||
if (extConnectsTo(TiGetType(tp), lab->lab_type, connTo)
|
||||
&& extHasRegion(tp, CLIENTDEFAULT))
|
||||
&& extHasRegion(tp, extUnInit))
|
||||
{
|
||||
found = TRUE;
|
||||
reg = (LabRegion *) ExtGetRegion(tp, (TileType)0);
|
||||
reg = (LabRegion *) extGetRegion(tp);
|
||||
ll = (LabelList *) mallocMagic((unsigned) (sizeof (LabelList)));
|
||||
ll->ll_label = lab;
|
||||
if (lab->lab_flags & PORT_DIR_MASK)
|
||||
|
|
@ -464,7 +412,7 @@ ExtLabelOneRegion(def, connTo, reg)
|
|||
GOTOPOINT(tp, &p);
|
||||
PlaneSetHint(def->cd_planes[pNum], tp);
|
||||
if (extConnectsTo(TiGetType(tp), lab->lab_type, connTo)
|
||||
&& (NodeRegion *) ExtGetRegion(tp, (TileType)0) == reg)
|
||||
&& (NodeRegion *) extGetRegion(tp) == reg)
|
||||
{
|
||||
ll = (LabelList *) mallocMagic((unsigned) (sizeof (LabelList)));
|
||||
ll->ll_label = lab;
|
||||
|
|
@ -496,6 +444,7 @@ ExtLabelOneRegion(def, connTo, reg)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -526,7 +475,7 @@ ExtResetTiles(def, resetTo)
|
|||
int pNum;
|
||||
|
||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||
DBResetTilePlaneSpecial(def->cd_planes[pNum], resetTo);
|
||||
DBResetTilePlane(def->cd_planes[pNum], resetTo);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -197,7 +197,6 @@ extSubtree(parentUse, reg, f)
|
|||
ha.ha_parentUse = parentUse;
|
||||
ha.ha_parentReg = reg;
|
||||
ha.ha_nodename = extSubtreeTileToNode;
|
||||
ha.ha_interArea = GeoNullRect;
|
||||
ha.ha_cumFlat.et_use = extYuseCum;
|
||||
HashInit(&ha.ha_connHash, 32, 0);
|
||||
|
||||
|
|
@ -251,17 +250,6 @@ extSubtree(parentUse, reg, f)
|
|||
if (result == 0) {
|
||||
/* If result == FALSE then ha.ha_interArea is invalid. */
|
||||
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;
|
||||
}
|
||||
else
|
||||
|
|
@ -357,9 +345,8 @@ done:
|
|||
|
||||
#ifdef exactinteractions
|
||||
int
|
||||
extSubtreeCopyPlane(tile, dinfo, plane)
|
||||
extSubtreeCopyPlane(tile, plane)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
Plane *plane;
|
||||
{
|
||||
Rect r;
|
||||
|
|
@ -371,9 +358,8 @@ extSubtreeCopyPlane(tile, dinfo, plane)
|
|||
}
|
||||
|
||||
int
|
||||
extSubtreeShrinkPlane(tile, dinfo, plane)
|
||||
extSubtreeShrinkPlane(tile, plane)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
Plane *plane;
|
||||
{
|
||||
Rect r;
|
||||
|
|
@ -388,9 +374,8 @@ extSubtreeShrinkPlane(tile, dinfo, plane)
|
|||
}
|
||||
|
||||
int
|
||||
extSubtreeInterFunc(tile, dinfo, ha)
|
||||
extSubtreeInterFunc(tile, ha)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
HierExtractArg *ha;
|
||||
{
|
||||
TITORECT(tile, &ha->ha_interArea);
|
||||
|
|
@ -699,22 +684,18 @@ extSubtreeOutputCoupling(ha)
|
|||
HashStartSearch(&hs);
|
||||
while ((he = HashNext(&ha->ha_cumFlat.et_coupleHash, &hs)))
|
||||
{
|
||||
TileType dinfo;
|
||||
|
||||
cap = extGetCapValue(he) / ExtCurStyle->exts_capScale;
|
||||
if (cap == 0)
|
||||
continue;
|
||||
|
||||
ck = (CoupleKey *) he->h_key.h_words;
|
||||
|
||||
tp = extNodeToTile(ck->ck_1, &ha->ha_cumFlat, &dinfo);
|
||||
name = extSubtreeTileToNode(tp, dinfo, ck->ck_1->nreg_pnum,
|
||||
&ha->ha_cumFlat, ha, TRUE);
|
||||
tp = extNodeToTile(ck->ck_1, &ha->ha_cumFlat);
|
||||
name = extSubtreeTileToNode(tp, ck->ck_1->nreg_pnum, &ha->ha_cumFlat, ha, TRUE);
|
||||
fprintf(ha->ha_outf, "cap \"%s\" ", name);
|
||||
|
||||
tp = extNodeToTile(ck->ck_2, &ha->ha_cumFlat, &dinfo);
|
||||
name = extSubtreeTileToNode(tp, dinfo, ck->ck_2->nreg_pnum,
|
||||
&ha->ha_cumFlat, ha, TRUE);
|
||||
tp = extNodeToTile(ck->ck_2, &ha->ha_cumFlat);
|
||||
name = extSubtreeTileToNode(tp, ck->ck_2->nreg_pnum, &ha->ha_cumFlat, ha, TRUE);
|
||||
fprintf(ha->ha_outf, "\"%s\" %lg\n", name, cap);
|
||||
}
|
||||
}
|
||||
|
|
@ -732,9 +713,8 @@ extSubtreeOutputCoupling(ha)
|
|||
*/
|
||||
|
||||
int
|
||||
extFoundProc(tile, dinfo, clientData)
|
||||
extFoundProc(tile, clientData)
|
||||
Tile *tile;
|
||||
TileType dinfo;
|
||||
ClientData clientData;
|
||||
{
|
||||
return 1;
|
||||
|
|
@ -790,7 +770,6 @@ extSubtreeFunc(scx, ha)
|
|||
*/
|
||||
ha->ha_subArea = use->cu_bbox;
|
||||
GEOCLIP(&ha->ha_subArea, &ha->ha_interArea);
|
||||
|
||||
hy.hy_area = &ha->ha_subArea;
|
||||
hy.hy_target = oneFlat->et_use;
|
||||
hy.hy_prefix = TRUE;
|
||||
|
|
@ -903,7 +882,7 @@ extSubtreeFunc(scx, ha)
|
|||
(NodeRegion *) ExtFindRegions(cumUse->cu_def, &TiPlaneRect,
|
||||
&ExtCurStyle->exts_activeTypes,
|
||||
ExtCurStyle->exts_nodeConn,
|
||||
extHierLabFirst, (int (*)()) NULL);
|
||||
extUnInit, extHierLabFirst, (int (*)()) NULL);
|
||||
ExtLabelRegions(cumUse->cu_def, ExtCurStyle->exts_nodeConn,
|
||||
&(ha->ha_cumFlat.et_nodes), &TiPlaneRect);
|
||||
}
|
||||
|
|
@ -940,7 +919,7 @@ extSubtreeFunc(scx, ha)
|
|||
/* Free the cumulative node list we extracted above */
|
||||
if (ha->ha_cumFlat.et_nodes)
|
||||
{
|
||||
ExtResetTiles(cumUse->cu_def, CLIENTDEFAULT);
|
||||
ExtResetTiles(cumUse->cu_def, extUnInit);
|
||||
ExtFreeLabRegions((LabRegion *) ha->ha_cumFlat.et_nodes);
|
||||
ha->ha_cumFlat.et_nodes = (NodeRegion *) NULL;
|
||||
}
|
||||
|
|
@ -1061,10 +1040,9 @@ extSubstrateFunc(scx, ha)
|
|||
*/
|
||||
|
||||
char *
|
||||
extSubtreeTileToNode(tp, dinfo, pNum, et, ha, doHard)
|
||||
Tile *tp; /* Tile whose node name is to be found */
|
||||
TileType dinfo; /* Split tile information */
|
||||
int pNum; /* Plane of the tile */
|
||||
extSubtreeTileToNode(tp, pNum, et, ha, doHard)
|
||||
Tile *tp; /* Tile whose node name is to be found */
|
||||
int pNum; /* Plane of the tile */
|
||||
ExtTree *et; /* Yank buffer to search */
|
||||
HierExtractArg *ha; /* Extraction context */
|
||||
bool doHard; /* If TRUE, we look up this node's name the hard way
|
||||
|
|
@ -1083,9 +1061,9 @@ extSubtreeTileToNode(tp, dinfo, pNum, et, ha, doHard)
|
|||
TileType ttype;
|
||||
|
||||
/* If there is a label list, use it */
|
||||
if (extHasRegion(tp, CLIENTDEFAULT))
|
||||
if (extHasRegion(tp, extUnInit))
|
||||
{
|
||||
reg = (LabRegion *) ExtGetRegion(tp, dinfo);
|
||||
reg = (LabRegion *) extGetRegion(tp);
|
||||
if (reg->lreg_labels)
|
||||
return (extNodeName(reg));
|
||||
}
|
||||
|
|
@ -1102,7 +1080,12 @@ extSubtreeTileToNode(tp, dinfo, pNum, et, ha, doHard)
|
|||
* can cause problems.
|
||||
*/
|
||||
if (IsSplit(tp))
|
||||
ttype = (dinfo & TT_SIDE) ? SplitRightType(tp) : SplitLeftType(tp);
|
||||
{
|
||||
if (SplitSide(tp))
|
||||
ttype = SplitRightType(tp);
|
||||
else
|
||||
ttype = SplitLeftType(tp);
|
||||
}
|
||||
else
|
||||
ttype = TiGetTypeExact(tp);
|
||||
|
||||
|
|
@ -1112,7 +1095,7 @@ extSubtreeTileToNode(tp, dinfo, pNum, et, ha, doHard)
|
|||
{
|
||||
if (DBSrPaintNMArea((Tile *) NULL,
|
||||
et->et_lookNames->cd_planes[pNum],
|
||||
TiGetTypeExact(tp) | dinfo, &r, &DBAllButSpaceBits,
|
||||
TiGetTypeExact(tp), &r, &DBAllButSpaceBits,
|
||||
extConnFindFunc, (ClientData) ®))
|
||||
{
|
||||
if (SigInterruptPending)
|
||||
|
|
@ -1136,8 +1119,8 @@ extSubtreeTileToNode(tp, dinfo, pNum, et, ha, doHard)
|
|||
|
||||
/* We have to do it the hard way */
|
||||
if (!doHard) return ((char *) NULL);
|
||||
if (extHasRegion(tp, CLIENTDEFAULT)
|
||||
&& (reg = extSubtreeHardNode(tp, dinfo, pNum, et, ha)))
|
||||
if (extHasRegion(tp, extUnInit)
|
||||
&& (reg = extSubtreeHardNode(tp, pNum, et, ha)))
|
||||
{
|
||||
if (ExtDoWarn & EXTWARN_LABELS)
|
||||
{
|
||||
|
|
@ -1171,14 +1154,13 @@ extSubtreeTileToNode(tp, dinfo, pNum, et, ha, doHard)
|
|||
*/
|
||||
|
||||
int
|
||||
extConnFindFunc(tp, dinfo, preg)
|
||||
extConnFindFunc(tp, preg)
|
||||
Tile *tp;
|
||||
TileType dinfo; // Unused, but needs to be handled
|
||||
LabRegion **preg;
|
||||
{
|
||||
if (extHasRegion(tp, CLIENTDEFAULT))
|
||||
if (extHasRegion(tp, extUnInit))
|
||||
{
|
||||
*preg = (LabRegion *)ExtGetRegion(tp, dinfo);
|
||||
*preg = (LabRegion *) extGetRegion(tp);
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
|
@ -1216,14 +1198,13 @@ extConnFindFunc(tp, dinfo, preg)
|
|||
*/
|
||||
|
||||
LabRegion *
|
||||
extSubtreeHardNode(tp, dinfo, pNum, et, ha)
|
||||
extSubtreeHardNode(tp, pNum, et, ha)
|
||||
Tile *tp;
|
||||
TileType dinfo;
|
||||
int pNum;
|
||||
ExtTree *et;
|
||||
HierExtractArg *ha;
|
||||
{
|
||||
LabRegion *lreg = (LabRegion *) ExtGetRegion(tp, dinfo);
|
||||
LabRegion *lreg = (LabRegion *) extGetRegion(tp);
|
||||
CellDef *def = et->et_use->cu_def;
|
||||
TileType ttype;
|
||||
char labelBuf[4096];
|
||||
|
|
@ -1234,7 +1215,7 @@ extSubtreeHardNode(tp, dinfo, pNum, et, ha)
|
|||
|
||||
if (IsSplit(tp))
|
||||
{
|
||||
if (dinfo & TT_SIDE)
|
||||
if (SplitSide(tp))
|
||||
ttype = SplitRightType(tp);
|
||||
else
|
||||
ttype = SplitLeftType(tp);
|
||||
|
|
|
|||
|
|
@ -1368,7 +1368,7 @@ ExtTechSimplePerimCap(argc, argv)
|
|||
|
||||
if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder)
|
||||
{
|
||||
TechError("Cannot parse perimeter cap line without plane ordering!\n");
|
||||
TechError("Cannot parse area cap line without plane ordering!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1376,14 +1376,9 @@ ExtTechSimplePerimCap(argc, argv)
|
|||
TTMaskSetMask(allExtractTypes, &types);
|
||||
plane1 = DBTechNoisyNamePlane(argv[2]);
|
||||
|
||||
/* 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);
|
||||
|
||||
TTMaskCom2(¬types, &types);
|
||||
TTMaskAndMask(&types, &DBPlaneTypes[plane1]);
|
||||
TTMaskAndMask(¬types, &DBPlaneTypes[plane1]);
|
||||
|
||||
capVal = aToCap(argv[argc - 1]);
|
||||
|
||||
|
|
@ -1637,7 +1632,7 @@ ExtTechSimpleOverlapCap(argv)
|
|||
|
||||
if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder)
|
||||
{
|
||||
TechError("Cannot parse overlap cap line without plane ordering!\n");
|
||||
TechError("Cannot parse area cap line without plane ordering!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1737,7 +1732,7 @@ ExtTechSimpleSideOverlapCap(argv)
|
|||
|
||||
if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder)
|
||||
{
|
||||
TechError("Cannot parse side overlap cap line without plane ordering!\n");
|
||||
TechError("Cannot parse area cap line without plane ordering!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1745,14 +1740,9 @@ ExtTechSimpleSideOverlapCap(argv)
|
|||
TTMaskSetMask(allExtractTypes, &types);
|
||||
plane1 = DBTechNoisyNamePlane(argv[2]);
|
||||
|
||||
/* 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);
|
||||
|
||||
TTMaskCom2(¬types, &types);
|
||||
TTMaskAndMask(&types, &DBPlaneTypes[plane1]);
|
||||
TTMaskAndMask(¬types, &DBPlaneTypes[plane1]);
|
||||
|
||||
DBTechNoisyNameMask(argv[3], &ov);
|
||||
TTMaskSetMask(allExtractTypes, &ov);
|
||||
|
|
@ -2757,34 +2747,24 @@ ExtTechLine(sectionName, argc, argv)
|
|||
DBTechNoisyNameMask(argv[4], &termtypes[0]); /* bottom */
|
||||
TTMaskSetMask(allExtractTypes, &termtypes[0]);
|
||||
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;
|
||||
|
||||
/* 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]))
|
||||
if ((argc > 6) && strcmp(argv[5], "None"))
|
||||
{
|
||||
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);
|
||||
DBTechNoisyNameMask(argv[5], &subsTypes); /* substrate */
|
||||
TTMaskSetMask(allExtractTypes, &subsTypes);
|
||||
}
|
||||
else
|
||||
subsTypes = DBZeroTypeBits;
|
||||
if (argc > 6) subsName = argv[6];
|
||||
if (argc > 7) subsName = argv[6];
|
||||
break;
|
||||
|
||||
case DEV_SUBCKT:
|
||||
|
|
@ -3370,22 +3350,7 @@ ExtTechLine(sectionName, argc, argv)
|
|||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -316,10 +316,8 @@ ExtractTest(w, cmd)
|
|||
}
|
||||
|
||||
int
|
||||
extShowInter(tile, dinfo, clientdata)
|
||||
extShowInter(tile)
|
||||
Tile *tile;
|
||||
TileType dinfo; /* (unused) */
|
||||
ClientData clientdata; /* (unused) */
|
||||
{
|
||||
Rect r;
|
||||
|
||||
|
|
|
|||
|
|
@ -358,8 +358,8 @@ extTimesCellFunc(cs)
|
|||
/* Count the number of transistors */
|
||||
transList = (TransRegion *) ExtFindRegions(def, &TiPlaneRect,
|
||||
&ExtCurStyle->exts_deviceMask, ExtCurStyle->exts_deviceConn,
|
||||
extTransFirst, extTransEach);
|
||||
ExtResetTiles(def, CLIENTDEFAULT);
|
||||
extUnInit, extTransFirst, extTransEach);
|
||||
ExtResetTiles(def, extUnInit);
|
||||
for (tl = transList; tl; tl = tl->treg_next)
|
||||
cs->cs_fets++;
|
||||
ExtFreeLabRegions((LabRegion *) transList);
|
||||
|
|
@ -396,9 +396,8 @@ extTimesCellFunc(cs)
|
|||
*/
|
||||
|
||||
int
|
||||
extCountTiles(tile, dinfo, cs)
|
||||
Tile *tile; /* (unused) */
|
||||
TileType dinfo; /* (unused) */
|
||||
extCountTiles(tile, cs)
|
||||
Tile *tile; /* UNUSED */
|
||||
struct cellStats *cs;
|
||||
{
|
||||
cs->cs_rects++;
|
||||
|
|
@ -844,7 +843,7 @@ extPaintOnly(def)
|
|||
|
||||
reg = extBasic(def, extDevNull);
|
||||
if (reg) ExtFreeLabRegions((LabRegion *) reg);
|
||||
ExtResetTiles(def, CLIENTDEFAULT);
|
||||
ExtResetTiles(def, extUnInit);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1116,9 +1115,8 @@ extInterAreaFunc(use, f)
|
|||
}
|
||||
|
||||
int
|
||||
extInterCountFunc(tile, dinfo, pArea)
|
||||
extInterCountFunc(tile, pArea)
|
||||
Tile *tile;
|
||||
TileType dinfo; /* (unused) */
|
||||
int *pArea;
|
||||
{
|
||||
Rect r;
|
||||
|
|
|
|||
|
|
@ -61,11 +61,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
* names that don't end in '!'.
|
||||
* If option is EXT_UNIQ_NOPORTS, then generate unique names as for
|
||||
* 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:
|
||||
* Returns the number of warnings generated.
|
||||
|
|
@ -114,7 +109,7 @@ extUniqueCell(def, option)
|
|||
lregList = (LabRegion *) ExtFindRegions(def, &TiPlaneRect,
|
||||
&ExtCurStyle->exts_activeTypes,
|
||||
ExtCurStyle->exts_nodeConn,
|
||||
extHierLabFirst, (int (*)()) NULL);
|
||||
extUnInit, extHierLabFirst, (int (*)()) NULL);
|
||||
|
||||
/* Assign the labels to their associated regions */
|
||||
ExtLabelRegions(def, ExtCurStyle->exts_nodeConn, &lregList, &TiPlaneRect);
|
||||
|
|
@ -192,7 +187,7 @@ extUniqueCell(def, option)
|
|||
HashKill(&labelHash);
|
||||
ExtFreeLabRegions((LabRegion *) lregList);
|
||||
if (nodeList) freeMagic(nodeList);
|
||||
ExtResetTiles(def, CLIENTDEFAULT);
|
||||
ExtResetTiles(def, extUnInit);
|
||||
if (nwarn)
|
||||
TxError("%s: %d warnings\n", def->cd_name, nwarn);
|
||||
return (nwarn);
|
||||
|
|
@ -224,7 +219,7 @@ extMakeUnique(def, ll, lreg, lregList, labelHash, option)
|
|||
* changes a label to make it unique.
|
||||
*/
|
||||
text = ll->ll_label->lab_text;
|
||||
if (option == EXT_UNIQ_ALL || option == EXT_UNIQ_TEMP)
|
||||
if (option == EXT_UNIQ_ALL)
|
||||
goto makeUnique;
|
||||
else if ((option == EXT_UNIQ_NOPORTS || option == EXT_UNIQ_NOTOPPORTS)
|
||||
&& !(ll->ll_label->lab_flags & PORT_DIR_MASK))
|
||||
|
|
@ -325,11 +320,8 @@ makeUnique:
|
|||
lab = ll2->ll_label;
|
||||
saveLab = *lab;
|
||||
|
||||
/* Flag this label as having been modified */
|
||||
if (option == EXT_UNIQ_TEMP) flags |= LABEL_UNIQUE;
|
||||
|
||||
DBRemoveLabel(def, lab);
|
||||
DBPutFontLabel(def, &saveLab.lab_rect,
|
||||
(void) DBPutFontLabel(def, &saveLab.lab_rect,
|
||||
saveLab.lab_font, saveLab.lab_size, saveLab.lab_rotate,
|
||||
&saveLab.lab_offset, saveLab.lab_just, name2,
|
||||
saveLab.lab_type, flags, (unsigned int)portno);
|
||||
|
|
@ -342,64 +334,3 @@ makeUnique:
|
|||
|
||||
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,14 +68,12 @@ extern const char * const extDevTable[];
|
|||
#define EXT_DOADJUST 0x001 /* Extract hierarchical adjustments */
|
||||
#define EXT_DOCAPACITANCE 0x002 /* Extract capacitance */
|
||||
#define EXT_DOCOUPLING 0x004 /* Extract coupling capacitance */
|
||||
#define EXT_DORESISTANCE 0x008 /* Extract lumped resistance */
|
||||
#define EXT_DORESISTANCE 0x008 /* Extract resistance */
|
||||
#define EXT_DOLENGTH 0x010 /* Extract pathlengths */
|
||||
#define EXT_DOFRINGEHALO 0x020 /* Distributed fringe capacitance */
|
||||
#define EXT_DOALL 0x03f /* ALL OF THE ABOVE */
|
||||
#define EXT_DOLABELCHECK 0x040 /* Check for connections by label */
|
||||
#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 char *ExtLocalPath; /* If non-NULL, location to write .ext files */
|
||||
|
|
@ -85,7 +83,6 @@ extern char *ExtLocalPath; /* If non-NULL, location to write .ext files */
|
|||
#define EXT_UNIQ_TAGGED 1
|
||||
#define EXT_UNIQ_NOPORTS 2
|
||||
#define EXT_UNIQ_NOTOPPORTS 3
|
||||
#define EXT_UNIQ_TEMP 4 /* Used only with "EXT_DOUNIQUE" */
|
||||
|
||||
extern bool ExtTechLine();
|
||||
extern void ExtTechInit();
|
||||
|
|
@ -111,10 +108,8 @@ extern void ExtGetZAxis();
|
|||
|
||||
extern void ExtDumpCaps();
|
||||
|
||||
extern int extEnumTilePerim(Tile *tpIn, TileType dinfo, const TileTypeBitMask *maskp, int pNum, int (*func)(), ClientData cdata);
|
||||
extern int extEnumTilePerim(Tile *tpIn, const TileTypeBitMask *maskp, int pNum, int (*func)(), ClientData cdata);
|
||||
extern Plane *extPrepSubstrate();
|
||||
extern FILE *ExtFileOpen(CellDef *def, char *file, char *mode, char **prealfile);
|
||||
|
||||
|
||||
/* C99 compat */
|
||||
extern void ExtAll();
|
||||
|
|
|
|||
|
|
@ -154,19 +154,6 @@ typedef struct reg
|
|||
struct reg *reg_next; /* Next region in list */
|
||||
} 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.
|
||||
* Any other structure that wants to reference node names
|
||||
|
|
@ -209,7 +196,6 @@ typedef struct nreg
|
|||
* in X, then in Y.
|
||||
*/
|
||||
LabelList *nreg_labels; /* See LabRegion for description */
|
||||
ClientData nreg_subnet; /* Subnet record generated by extresist */
|
||||
CapValue nreg_cap; /* Capacitance to ground */
|
||||
ResValue nreg_resist; /* Resistance estimate */
|
||||
PerimArea nreg_pa[1]; /* Dummy; each node actually has
|
||||
|
|
@ -226,18 +212,16 @@ typedef struct treg
|
|||
{
|
||||
struct treg *treg_next; /* Next region in list */
|
||||
int treg_pnum; /* UNUSED */
|
||||
int treg_type; /* UNUSED */
|
||||
int treg_type; /* Type of tile that contains treg_ll */
|
||||
Point treg_ll; /* UNUSED */
|
||||
LabelList *treg_labels; /* Attribute list */
|
||||
Tile *treg_tile; /* Some tile in the channel */
|
||||
TileType treg_dinfo; /* Diagonal information for treg_tile* */
|
||||
int treg_area; /* Area of channel */
|
||||
} TransRegion;
|
||||
|
||||
typedef struct { /* Maintain plane information when pushing */
|
||||
Rect area; /* tiles on the node stack. For use with */
|
||||
int plane; /* function extNbrPushFunc(). */
|
||||
ClientData uninit; /* Value of an unvisited region */
|
||||
} PlaneAndArea;
|
||||
|
||||
/* Structure to be kept in a hash table of node regions for the current */
|
||||
|
|
@ -269,7 +253,7 @@ typedef struct
|
|||
CellDef *fra_def; /* Def being searched */
|
||||
int fra_pNum; /* Plane currently searching */
|
||||
ClientData fra_uninit; /* This value appears in the ti_client
|
||||
* field of a tile if it has not yet
|
||||
* field of a tile if it's not yet
|
||||
* been visited.
|
||||
*/
|
||||
ExtRegion *(*fra_first)(); /* Function to init new region */
|
||||
|
|
@ -297,27 +281,16 @@ typedef struct
|
|||
int b_plane; /* extract argument for extSideOverlap */
|
||||
} Boundary;
|
||||
|
||||
/* Define Manhattan boundary length */
|
||||
|
||||
#define BoundaryLength(bp) \
|
||||
((bp)->b_segment.r_xtop - (bp)->b_segment.r_xbot \
|
||||
+ (bp)->b_segment.r_ytop - (bp)->b_segment.r_ybot)
|
||||
|
||||
/* Directions in which we can be following the boundary of a perimeter */
|
||||
|
||||
#define BD_LEFT 0x01 /* Inside is to right */
|
||||
#define BD_TOP 0x02 /* Inside is below */
|
||||
#define BD_RIGHT 0x04 /* Inside is to left */
|
||||
#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 */
|
||||
|
||||
#define BD_LEFT 1 /* Inside is to right */
|
||||
#define BD_TOP 2 /* Inside is below */
|
||||
#define BD_RIGHT 4 /* Inside is to left */
|
||||
#define BD_BOTTOM 8 /* Inside is above */
|
||||
|
||||
/* -------- Yank buffers for hierarchical and array extraction -------- */
|
||||
|
||||
|
|
@ -369,7 +342,6 @@ typedef struct extTree
|
|||
* char *
|
||||
* proc(tp, et, ha)
|
||||
* Tile *tp;
|
||||
* TileType dinfo;
|
||||
* ExtTree *et;
|
||||
* HierExtractArg *ha;
|
||||
* {
|
||||
|
|
@ -400,7 +372,7 @@ typedef struct
|
|||
*/
|
||||
Tile *hierOneTile; /* Used in ExtHier.c, tile from extHierOneFlat */
|
||||
int hierPNum; /* Used in ExtHier.c, plane of tile above */
|
||||
TileType hierType; /* Used in ExtHier.c, type of tile above, incl. TT_SIDE */
|
||||
TileType hierType; /* Used in ExtHier.c, type of tile above */
|
||||
int hierPNumBelow; /* Used in ExtHier.c, plane of tile below */
|
||||
} HierExtractArg;
|
||||
|
||||
|
|
@ -962,6 +934,12 @@ extern ExtStyle *ExtCurStyle;
|
|||
|
||||
/* ------------------- 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 NodeName points to the Node corresponding to that name.
|
||||
|
|
@ -990,10 +968,17 @@ 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) )
|
||||
|
||||
|
||||
/* For non-recursive flooding algorithm */
|
||||
#define VISITPENDING ((ClientData) NULL) /* Marks tiles on stack */
|
||||
|
||||
|
|
@ -1004,47 +989,44 @@ extern ExtRegion *ExtGetRegion(Tile *tile, TileType dinfo);
|
|||
/* because the search algorithm can overwrite it between the */
|
||||
/* time the tile is pushed and the time that it is popped. */
|
||||
|
||||
#define PUSHTILE(tp, di, pl) \
|
||||
ExtSetRegion(tp, di, (ExtRegion *)VISITPENDING); \
|
||||
STACKPUSH((ClientData)(pointertype)pl, extNodeStack); \
|
||||
STACKPUSH((ClientData)(pointertype)di, extNodeStack); \
|
||||
#define PUSHTILE(tp, pl) \
|
||||
(tp)->ti_client = VISITPENDING; \
|
||||
STACKPUSH((ClientData)(pointertype)(pl | \
|
||||
((TileType)(spointertype)(tp)->ti_body & TT_SIDE)), extNodeStack); \
|
||||
STACKPUSH((ClientData)(pointertype)tp, extNodeStack)
|
||||
|
||||
#define POPTILE(tp, di, pl) \
|
||||
#define POPTILE(tp, pl) \
|
||||
tp = (Tile *) STACKPOP(extNodeStack); \
|
||||
di = (spointertype) STACKPOP(extNodeStack); \
|
||||
pl = (spointertype) STACKPOP(extNodeStack)
|
||||
pl = (spointertype) STACKPOP(extNodeStack); \
|
||||
if (pl & TT_SIDE) { \
|
||||
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 */
|
||||
|
||||
#define PUSHTILEBOTTOM(tp, pl) \
|
||||
{ \
|
||||
TileType di = (SplitDirection(tp)) ? 0 : TT_SIDE; \
|
||||
ExtSetRegion(tp, di, (ExtRegion *)VISITPENDING); \
|
||||
STACKPUSH((ClientData)(pointertype)pl, extNodeStack); \
|
||||
STACKPUSH((ClientData)(pointertype)di, extNodeStack); \
|
||||
STACKPUSH((ClientData)(pointertype)tp, extNodeStack); \
|
||||
}
|
||||
(tp)->ti_client = VISITPENDING; \
|
||||
STACKPUSH((ClientData)(pointertype)(pl | \
|
||||
((SplitDirection(tp)) ? 0 : TT_SIDE)), extNodeStack) ;\
|
||||
STACKPUSH((ClientData)(pointertype)tp, extNodeStack)
|
||||
|
||||
#define PUSHTILETOP(tp, pl) \
|
||||
{ \
|
||||
TileType di = (SplitDirection(tp)) ? TT_SIDE : 0; \
|
||||
ExtSetRegion(tp, di, (ExtRegion *)VISITPENDING); \
|
||||
STACKPUSH((ClientData)(pointertype)pl, extNodeStack); \
|
||||
STACKPUSH((ClientData)(pointertype)di, extNodeStack); \
|
||||
STACKPUSH((ClientData)(pointertype)tp, extNodeStack); \
|
||||
}
|
||||
(tp)->ti_client = VISITPENDING; \
|
||||
STACKPUSH((ClientData)(pointertype)(pl | \
|
||||
((SplitDirection(tp)) ? TT_SIDE : 0)), extNodeStack) ;\
|
||||
STACKPUSH((ClientData)(pointertype)tp, extNodeStack)
|
||||
|
||||
#define PUSHTILELEFT(tp, pl) \
|
||||
ExtSetRegion(tp, (TileType)0, (ExtRegion *)VISITPENDING); \
|
||||
(tp)->ti_client = VISITPENDING; \
|
||||
STACKPUSH((ClientData)(pointertype)(pl), extNodeStack); \
|
||||
STACKPUSH((ClientData)(pointertype)0, extNodeStack); \
|
||||
STACKPUSH((ClientData)(pointertype)tp, extNodeStack)
|
||||
|
||||
#define PUSHTILERIGHT(tp, pl) \
|
||||
ExtSetRegion(tp, (TileType)TT_SIDE, (ExtRegion *)VISITPENDING); \
|
||||
STACKPUSH((ClientData)(pointertype)pl, extNodeStack); \
|
||||
STACKPUSH((ClientData)(pointertype)TT_SIDE, extNodeStack); \
|
||||
(tp)->ti_client = VISITPENDING; \
|
||||
STACKPUSH((ClientData)(pointertype)(pl | TT_SIDE), extNodeStack); \
|
||||
STACKPUSH((ClientData)(pointertype)tp, extNodeStack)
|
||||
|
||||
/* ------------------------- Region finding --------------------------- */
|
||||
|
|
@ -1074,12 +1056,11 @@ extern Tile *extNodeToTile();
|
|||
#define NODETONODE(nold, et, nnew) \
|
||||
if (1) { \
|
||||
Tile *tp; \
|
||||
TileType di; \
|
||||
\
|
||||
(nnew) = (NodeRegion *) NULL; \
|
||||
tp = extNodeToTile((nold), (et), (TileType *)&di); \
|
||||
if (tp && extHasRegion(tp, CLIENTDEFAULT)) \
|
||||
(nnew) = (NodeRegion *) ExtGetRegion(tp, di); \
|
||||
tp = extNodeToTile((nold), (et)); \
|
||||
if (tp && extHasRegion(tp, extUnInit)) \
|
||||
(nnew) = (NodeRegion *) extGetRegion(tp); \
|
||||
}
|
||||
|
||||
/* -------------------- Miscellaneous procedures ---------------------- */
|
||||
|
|
@ -1091,7 +1072,6 @@ extern ExtTree *extHierNewOne();
|
|||
extern int extNbrPushFunc();
|
||||
extern TileType extGetDevType();
|
||||
extern void extMakeNodeNumPrint();
|
||||
extern void ExtSetRegion();
|
||||
|
||||
/* --------------------- Miscellaneous globals ------------------------ */
|
||||
|
||||
|
|
@ -1124,11 +1104,6 @@ extern Plane *extCellFile();
|
|||
extern int extInterAreaFunc();
|
||||
extern int extTreeSrPaintArea();
|
||||
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 ------------------- */
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue