Compare commits
No commits in common. "master" and "8.3.597" have entirely different histories.
|
|
@ -138,8 +138,6 @@ jobs:
|
||||||
echo "BUILD_GCC_VERSION=$BUILD_GCC_VERSION" >> $GITHUB_ENV
|
echo "BUILD_GCC_VERSION=$BUILD_GCC_VERSION" >> $GITHUB_ENV
|
||||||
echo "BUILD_CLANG_VERSION=$BUILD_CLANG_VERSION" >> $GITHUB_ENV
|
echo "BUILD_CLANG_VERSION=$BUILD_CLANG_VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
sudo apt-get update
|
|
||||||
|
|
||||||
if [ -n "$BUILD_GCC_VERSION" ]
|
if [ -n "$BUILD_GCC_VERSION" ]
|
||||||
then
|
then
|
||||||
GCCV=$BUILD_GCC_VERSION
|
GCCV=$BUILD_GCC_VERSION
|
||||||
|
|
|
||||||
|
|
@ -33,22 +33,10 @@ jobs:
|
||||||
cd emsdk
|
cd emsdk
|
||||||
./emsdk install latest
|
./emsdk install latest
|
||||||
./emsdk activate 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
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
source ./emsdk/emsdk_env.sh
|
source ./emsdk/emsdk_env.sh
|
||||||
# The --without and --disable in these build options is due to no WASM library being available for that feature
|
emconfigure ./configure --without-cairo --without-opengl --without-x --disable-readline --disable-compression --target=asmjs-unknown-emscripten
|
||||||
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
|
|
||||||
echo "===== defs.mak ====="
|
echo "===== defs.mak ====="
|
||||||
cat defs.mak
|
cat defs.mak
|
||||||
echo "===== 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
|
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||||
jobs:
|
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:
|
simple_build_linux:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
|
|
@ -32,22 +45,10 @@ jobs:
|
||||||
cd emsdk
|
cd emsdk
|
||||||
./emsdk install latest
|
./emsdk install latest
|
||||||
./emsdk activate 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
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
source ./emsdk/emsdk_env.sh
|
source ./emsdk/emsdk_env.sh
|
||||||
# The --without and --disable in these build options is due to no WASM library being available for that feature
|
emconfigure ./configure --without-cairo --without-opengl --without-x --disable-readline --disable-compression --target=asmjs-unknown-emscripten
|
||||||
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
|
|
||||||
echo "===== defs.mak ====="
|
echo "===== defs.mak ====="
|
||||||
cat defs.mak
|
cat defs.mak
|
||||||
echo "===== defs.mak ====="
|
echo "===== defs.mak ====="
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,6 @@ int calmaNonManhattan;
|
||||||
int CalmaFlattenLimit = 10;
|
int CalmaFlattenLimit = 10;
|
||||||
int NameConvertErrors = 0;
|
int NameConvertErrors = 0;
|
||||||
bool CalmaRewound = FALSE;
|
bool CalmaRewound = FALSE;
|
||||||
bool CalmaRecordPaths = FALSE;
|
|
||||||
TileTypeBitMask *CalmaMaskHints = NULL;
|
TileTypeBitMask *CalmaMaskHints = NULL;
|
||||||
|
|
||||||
extern HashTable calmaDefInitHash;
|
extern HashTable calmaDefInitHash;
|
||||||
|
|
@ -506,33 +505,28 @@ calmaParseStructure(
|
||||||
|
|
||||||
if (CalmaReadOnly || predefined)
|
if (CalmaReadOnly || predefined)
|
||||||
{
|
{
|
||||||
PropertyRecord *proprec;
|
|
||||||
char cstring[1024];
|
char cstring[1024];
|
||||||
|
|
||||||
|
/* Writing the file position into a string is slow, but */
|
||||||
|
/* it prevents requiring special handling when printing */
|
||||||
|
/* out the properties. */
|
||||||
|
|
||||||
|
char *fpcopy = (char *)mallocMagic(20);
|
||||||
|
char *fncopy;
|
||||||
|
|
||||||
/* Substitute variable for PDK path or ~ for home directory */
|
/* Substitute variable for PDK path or ~ for home directory */
|
||||||
/* the same way that cell references are handled in .mag files. */
|
/* the same way that cell references are handled in .mag files. */
|
||||||
DBPathSubstitute(filename, cstring, cifReadCellDef);
|
DBPathSubstitute(filename, cstring, cifReadCellDef);
|
||||||
|
fncopy = StrDup(NULL, cstring);
|
||||||
|
sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos);
|
||||||
|
DBPropPut(cifReadCellDef, "GDS_START", (ClientData)fpcopy);
|
||||||
|
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
fpcopy = (char *)mallocMagic(20);
|
||||||
proprec->prop_type = PROPERTY_TYPE_DOUBLE;
|
|
||||||
proprec->prop_len = 1;
|
|
||||||
proprec->prop_value.prop_double[0] = filepos;
|
|
||||||
DBPropPut(cifReadCellDef, "GDS_START", (ClientData)proprec);
|
|
||||||
|
|
||||||
filepos = FTELL(calmaInputFile);
|
filepos = FTELL(calmaInputFile);
|
||||||
|
sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos);
|
||||||
|
DBPropPut(cifReadCellDef, "GDS_END", (ClientData)fpcopy);
|
||||||
|
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
DBPropPut(cifReadCellDef, "GDS_FILE", (ClientData)fncopy);
|
||||||
proprec->prop_type = PROPERTY_TYPE_DOUBLE;
|
|
||||||
proprec->prop_len = 1;
|
|
||||||
proprec->prop_value.prop_double[0] = filepos;
|
|
||||||
DBPropPut(cifReadCellDef, "GDS_END", (ClientData)proprec);
|
|
||||||
|
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) - 7 +
|
|
||||||
strlen(cstring));
|
|
||||||
proprec->prop_type = PROPERTY_TYPE_STRING;
|
|
||||||
proprec->prop_len = 1;
|
|
||||||
strcpy(proprec->prop_value.prop_string, cstring);
|
|
||||||
DBPropPut(cifReadCellDef, "GDS_FILE", (ClientData)proprec);
|
|
||||||
|
|
||||||
if (predefined)
|
if (predefined)
|
||||||
{
|
{
|
||||||
|
|
@ -789,8 +783,8 @@ calmaElementSref(
|
||||||
char *filename)
|
char *filename)
|
||||||
{
|
{
|
||||||
int nbytes, rtype, cols, rows, nref, n, i, savescale;
|
int nbytes, rtype, cols, rows, nref, n, i, savescale;
|
||||||
int xlo, ylo, xhi, yhi, xsep, ysep, angle;
|
int xlo, ylo, xhi, yhi, xsep, ysep;
|
||||||
bool madeinst = FALSE, rotated = FALSE;
|
bool madeinst = FALSE;
|
||||||
char *sname = NULL;
|
char *sname = NULL;
|
||||||
bool isArray = FALSE;
|
bool isArray = FALSE;
|
||||||
bool dolookahead = FALSE;
|
bool dolookahead = FALSE;
|
||||||
|
|
@ -990,73 +984,17 @@ calmaElementSref(
|
||||||
refarray[2].p_x = refarray[2].p_y = 0;
|
refarray[2].p_x = refarray[2].p_y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the array is given an angle, then the meaning of rows and
|
|
||||||
* columns needs to be swapped for the purpose of ignoring
|
|
||||||
* X or Y values in the case of a 1-row or 1-column entry.
|
|
||||||
*/
|
|
||||||
angle = GeoTransAngle(&trans, 0);
|
|
||||||
if ((angle == 90) || (angle == 270) || (angle == -90) || (angle == -270))
|
|
||||||
rotated = TRUE;
|
|
||||||
|
|
||||||
/* If this is a cell reference, then we scale to magic coordinates
|
/* If this is a cell reference, then we scale to magic coordinates
|
||||||
* and place the cell in the magic database. However, if this is
|
* and place the cell in the magic database. However, if this is
|
||||||
* a cell to be flattened a la "gds flatten", then we keep the GDS
|
* a cell to be flattened a la "gds flatten", then we keep the GDS
|
||||||
* coordinates, and don't scale to the magic database.
|
* coordinates, and don't scale to the magic database.
|
||||||
*
|
|
||||||
* NOTE: Scaling everything in the middle or reading array data
|
|
||||||
* and then retroactively adjusting the array data read earlier
|
|
||||||
* is problematic, and probably incorrect.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
for (n = 0; n < nref; n++)
|
|
||||||
{
|
|
||||||
savescale = calmaReadScale1;
|
|
||||||
|
|
||||||
/* If there is only one column, then X data in the 2nd or 3rd
|
|
||||||
* entry is irrelevant. If there is only one row, then Y data
|
|
||||||
* in the 2nd or 3rd entry is irrelevant. Prevent issues caused
|
|
||||||
* by incorrect/uninitialized data in these positions by ignoring
|
|
||||||
* them as needed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((n > 0) && ((!rotated && (rows == 1)) || (rotated && (cols == 1))))
|
|
||||||
{
|
|
||||||
calmaReadX(&refarray[n], 1);
|
|
||||||
calmaSkipBytes(4);
|
|
||||||
refarray[n].p_y = refarray[0].p_y;
|
|
||||||
}
|
|
||||||
else if ((n > 0) && ((!rotated && (cols == 1)) || (rotated && (rows == 1))))
|
|
||||||
{
|
|
||||||
calmaSkipBytes(4);
|
|
||||||
calmaReadY(&refarray[n], 1);
|
|
||||||
refarray[n].p_x = refarray[0].p_x;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
calmaReadPoint(&refarray[n], 1);
|
|
||||||
|
|
||||||
if (savescale != calmaReadScale1)
|
|
||||||
{
|
|
||||||
/* Scale changed, so update previous points read */
|
|
||||||
int newscale = calmaReadScale1 / savescale;
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
{
|
|
||||||
refarray[i].p_x *= newscale;
|
|
||||||
refarray[i].p_y *= newscale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FEOF(calmaInputFile))
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (n = 0; n < nref; n++)
|
|
||||||
refunscaled[n] = refarray[n]; // Save for CDFLATGDS cells
|
|
||||||
|
|
||||||
for (n = 0; n < nref; n++)
|
for (n = 0; n < nref; n++)
|
||||||
{
|
{
|
||||||
savescale = cifCurReadStyle->crs_scaleFactor;
|
savescale = cifCurReadStyle->crs_scaleFactor;
|
||||||
|
calmaReadPoint(&refarray[n], 1);
|
||||||
|
refunscaled[n] = refarray[n]; // Save for CDFLATGDS cells
|
||||||
refarray[n].p_x = CIFScaleCoord(refarray[n].p_x, COORD_EXACT);
|
refarray[n].p_x = CIFScaleCoord(refarray[n].p_x, COORD_EXACT);
|
||||||
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
||||||
{
|
{
|
||||||
|
|
@ -1077,6 +1015,9 @@ calmaElementSref(
|
||||||
}
|
}
|
||||||
refarray[n].p_x *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
refarray[n].p_x *= (savescale / cifCurReadStyle->crs_scaleFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FEOF(calmaInputFile))
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip remainder */
|
/* Skip remainder */
|
||||||
|
|
|
||||||
|
|
@ -114,8 +114,6 @@ calmaInputRescale(
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* calmaReadX ---
|
|
||||||
* calmaReadY ---
|
|
||||||
* calmaReadPoint ---
|
* calmaReadPoint ---
|
||||||
*
|
*
|
||||||
* Read a point from the input.
|
* Read a point from the input.
|
||||||
|
|
@ -134,17 +132,11 @@ calmaInputRescale(
|
||||||
* encountered, then everything in the GDS planes is rescaled
|
* encountered, then everything in the GDS planes is rescaled
|
||||||
* to match.
|
* to match.
|
||||||
*
|
*
|
||||||
* Notes:
|
|
||||||
* This routine has been split into individual X and Y reads so that
|
|
||||||
* array data can be read while ignoring offset information when there
|
|
||||||
* is only one row or column; otherwise, bad or uninitialized data
|
|
||||||
* in the record can cause unnecessary and incorrect scaling.
|
|
||||||
*
|
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
calmaReadX(
|
calmaReadPoint(
|
||||||
Point *p,
|
Point *p,
|
||||||
int iscale)
|
int iscale)
|
||||||
{
|
{
|
||||||
|
|
@ -171,15 +163,6 @@ calmaReadX(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p->p_x /= calmaReadScale2;
|
p->p_x /= calmaReadScale2;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
calmaReadY(
|
|
||||||
Point *p,
|
|
||||||
int iscale)
|
|
||||||
{
|
|
||||||
int rescale;
|
|
||||||
|
|
||||||
READI4((p)->p_y);
|
READI4((p)->p_y);
|
||||||
p->p_y *= (calmaReadScale1 * iscale);
|
p->p_y *= (calmaReadScale1 * iscale);
|
||||||
|
|
@ -205,15 +188,6 @@ calmaReadY(
|
||||||
p->p_y /= calmaReadScale2;
|
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,
|
CIFPaintWirePath(pathheadp, width,
|
||||||
(pathtype == CALMAPATH_SQUAREFLUSH || pathtype == CALMAPATH_CUSTOM) ?
|
(pathtype == CALMAPATH_SQUAREFLUSH || pathtype == CALMAPATH_CUSTOM) ?
|
||||||
FALSE : TRUE, plane, CIFPaintTable, (PaintUndoInfo *)NULL);
|
FALSE : TRUE, plane, CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||||
|
|
|
||||||
|
|
@ -528,7 +528,7 @@ calmaDumpStructure(
|
||||||
|
|
||||||
/* Is view abstract? */
|
/* Is view abstract? */
|
||||||
DBPropGet(edef, "LEFview", &isAbstract);
|
DBPropGet(edef, "LEFview", &isAbstract);
|
||||||
chklibname = DBPropGetString(edef, "GDS_FILE", &isReadOnly);
|
chklibname = (char *)DBPropGet(edef, "GDS_FILE", &isReadOnly);
|
||||||
|
|
||||||
if (isAbstract && isReadOnly)
|
if (isAbstract && isReadOnly)
|
||||||
{
|
{
|
||||||
|
|
@ -738,7 +738,7 @@ calmaFullDump(
|
||||||
* names in the GDS file do not shadow any names in the database.
|
* names in the GDS file do not shadow any names in the database.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
viewopts = DBPropGetString(def, "LEFview", &isAbstract);
|
viewopts = (char *)DBPropGet(def, "LEFview", &isAbstract);
|
||||||
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
||||||
{
|
{
|
||||||
/* Generate a SHORT name for this cell (else it is easy to run into the
|
/* Generate a SHORT name for this cell (else it is easy to run into the
|
||||||
|
|
@ -918,7 +918,7 @@ calmaProcessDef(
|
||||||
DBPropGet(def, "GDS_END", &hasGDSEnd);
|
DBPropGet(def, "GDS_END", &hasGDSEnd);
|
||||||
DBPropGet(def, "CIFhier", &needHier);
|
DBPropGet(def, "CIFhier", &needHier);
|
||||||
|
|
||||||
filename = DBPropGetString(def, "GDS_FILE", &isReadOnly);
|
filename = (char *)DBPropGet(def, "GDS_FILE", &isReadOnly);
|
||||||
|
|
||||||
/* When used with "calma addendum true", don't output the read-only */
|
/* When used with "calma addendum true", don't output the read-only */
|
||||||
/* cells. This makes the library incomplete and dependent on the */
|
/* cells. This makes the library incomplete and dependent on the */
|
||||||
|
|
@ -1033,12 +1033,13 @@ calmaProcessDef(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cval = DBPropGetDouble(def, "GDS_END", NULL);
|
offptr = (char *)DBPropGet(def, "GDS_END", NULL);
|
||||||
|
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
||||||
cellend = (off_t)cval;
|
cellend = (off_t)cval;
|
||||||
cval = DBPropGetDouble(def, "GDS_BEGIN", &oldStyle);
|
offptr = (char *)DBPropGet(def, "GDS_BEGIN", &oldStyle);
|
||||||
if (!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 */
|
/* Write our own header and string name, to ensure */
|
||||||
/* that the magic cell name and GDS name match. */
|
/* that the magic cell name and GDS name match. */
|
||||||
|
|
@ -1055,6 +1056,7 @@ calmaProcessDef(
|
||||||
calmaOutStructName(CALMA_STRNAME, def, outf);
|
calmaOutStructName(CALMA_STRNAME, def, outf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
||||||
cellstart = (off_t)cval;
|
cellstart = (off_t)cval;
|
||||||
|
|
||||||
/* GDS_START has been defined as the start of data after the cell */
|
/* GDS_START has been defined as the start of data after the cell */
|
||||||
|
|
@ -1261,7 +1263,7 @@ calmaOutFunc(
|
||||||
int dbunits;
|
int dbunits;
|
||||||
calmaOutputStruct cos;
|
calmaOutputStruct cos;
|
||||||
bool propfound;
|
bool propfound;
|
||||||
PropertyRecord *proprec;
|
char *propvalue;
|
||||||
|
|
||||||
cos.f = f;
|
cos.f = f;
|
||||||
cos.area = (cliprect == &TiPlaneRect) ? NULL : cliprect;
|
cos.area = (cliprect == &TiPlaneRect) ? NULL : cliprect;
|
||||||
|
|
@ -1321,21 +1323,15 @@ calmaOutFunc(
|
||||||
|
|
||||||
/* Include any fixed bounding box as part of the area to process, */
|
/* Include any fixed bounding box as part of the area to process, */
|
||||||
/* in case the fixed bounding box is larger than the geometry. */
|
/* in case the fixed bounding box is larger than the geometry. */
|
||||||
proprec = DBPropGet(def, "FIXED_BBOX", &propfound);
|
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
Rect bbox;
|
Rect bbox;
|
||||||
|
|
||||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||||
(proprec->prop_len == 4))
|
&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];
|
|
||||||
GeoInclude(&bbox, &bigArea);
|
GeoInclude(&bbox, &bigArea);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
CIFErrorDef = def;
|
CIFErrorDef = def;
|
||||||
CIFGen(def, def, &bigArea, CIFPlanes, &DBAllTypeBits, TRUE, TRUE, FALSE,
|
CIFGen(def, def, &bigArea, CIFPlanes, &DBAllTypeBits, TRUE, TRUE, FALSE,
|
||||||
|
|
|
||||||
|
|
@ -508,7 +508,7 @@ calmaDumpStructureZ(
|
||||||
|
|
||||||
/* Is view abstract? */
|
/* Is view abstract? */
|
||||||
DBPropGet(edef, "LEFview", &isAbstract);
|
DBPropGet(edef, "LEFview", &isAbstract);
|
||||||
chklibname = DBPropGetString(edef, "GDS_FILE", &isReadOnly);
|
chklibname = (char *)DBPropGet(edef, "GDS_FILE", &isReadOnly);
|
||||||
|
|
||||||
if (isAbstract && isReadOnly)
|
if (isAbstract && isReadOnly)
|
||||||
{
|
{
|
||||||
|
|
@ -716,7 +716,7 @@ calmaFullDumpZ(
|
||||||
* names in the GDS file do not shadow any names in the database.
|
* names in the GDS file do not shadow any names in the database.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
viewopts = DBPropGetString(def, "LEFview", &isAbstract);
|
viewopts = (char *)DBPropGet(def, "LEFview", &isAbstract);
|
||||||
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
if ((!isAbstract) || (strcasecmp(viewopts, "no_prefix")))
|
||||||
{
|
{
|
||||||
/* Generate a SHORT name for this cell (else it is easy to run into the
|
/* Generate a SHORT name for this cell (else it is easy to run into the
|
||||||
|
|
@ -870,7 +870,7 @@ calmaProcessDefZ(
|
||||||
DBPropGet(def, "GDS_START", &hasContent);
|
DBPropGet(def, "GDS_START", &hasContent);
|
||||||
DBPropGet(def, "GDS_END", &hasGDSEnd);
|
DBPropGet(def, "GDS_END", &hasGDSEnd);
|
||||||
DBPropGet(def, "CIFhier", &needHier);
|
DBPropGet(def, "CIFhier", &needHier);
|
||||||
filename = DBPropGetString(def, "GDS_FILE", &isReadOnly);
|
filename = (char *)DBPropGet(def, "GDS_FILE", &isReadOnly);
|
||||||
|
|
||||||
/* When used with "calma addendum true", don't output the read-only */
|
/* When used with "calma addendum true", don't output the read-only */
|
||||||
/* cells. This makes the library incomplete and dependent on the */
|
/* cells. This makes the library incomplete and dependent on the */
|
||||||
|
|
@ -985,12 +985,13 @@ calmaProcessDefZ(
|
||||||
}
|
}
|
||||||
else
|
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;
|
cellend = (z_off_t)cval;
|
||||||
cval = DBPropGetDouble(def, "GDS_BEGIN", &oldStyle);
|
offptr = (char *)DBPropGet(def, "GDS_BEGIN", &oldStyle);
|
||||||
if (!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 */
|
/* Write our own header and string name, to ensure */
|
||||||
/* that the magic cell name and GDS name match. */
|
/* that the magic cell name and GDS name match. */
|
||||||
|
|
@ -1007,6 +1008,7 @@ calmaProcessDefZ(
|
||||||
calmaOutStructNameZ(CALMA_STRNAME, def, outf);
|
calmaOutStructNameZ(CALMA_STRNAME, def, outf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sscanf(offptr, "%"DLONG_PREFIX"d", &cval);
|
||||||
cellstart = (z_off_t)cval;
|
cellstart = (z_off_t)cval;
|
||||||
|
|
||||||
/* GDS_START has been defined as the start of data after the cell */
|
/* GDS_START has been defined as the start of data after the cell */
|
||||||
|
|
@ -1184,7 +1186,6 @@ calmaOutFuncZ(
|
||||||
int dbunits;
|
int dbunits;
|
||||||
calmaOutputStructZ cos;
|
calmaOutputStructZ cos;
|
||||||
bool propfound;
|
bool propfound;
|
||||||
PropertyRecord *proprec;
|
|
||||||
char *propvalue;
|
char *propvalue;
|
||||||
extern int compport(const void *one, const void *two); /* Forward declaration */
|
extern int compport(const void *one, const void *two); /* Forward declaration */
|
||||||
|
|
||||||
|
|
@ -1246,21 +1247,15 @@ calmaOutFuncZ(
|
||||||
|
|
||||||
/* Include any fixed bounding box as part of the area to process, */
|
/* Include any fixed bounding box as part of the area to process, */
|
||||||
/* in case the fixed bounding box is larger than the geometry. */
|
/* in case the fixed bounding box is larger than the geometry. */
|
||||||
proprec = DBPropGet(def, "FIXED_BBOX", &propfound);
|
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
Rect bbox;
|
Rect bbox;
|
||||||
|
|
||||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||||
(proprec->prop_len == 4))
|
&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];
|
|
||||||
GeoInclude(&bbox, &bigArea);
|
GeoInclude(&bbox, &bigArea);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
CIFErrorDef = def;
|
CIFErrorDef = def;
|
||||||
CIFGen(def, def, &bigArea, CIFPlanes, &DBAllTypeBits, TRUE, TRUE, FALSE,
|
CIFGen(def, def, &bigArea, CIFPlanes, &DBAllTypeBits, TRUE, TRUE, FALSE,
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,6 @@ extern TileTypeBitMask *CalmaMaskHints;
|
||||||
extern bool CalmaMergeTiles;
|
extern bool CalmaMergeTiles;
|
||||||
extern bool CalmaFlattenArrays;
|
extern bool CalmaFlattenArrays;
|
||||||
extern bool CalmaNoDRCCheck;
|
extern bool CalmaNoDRCCheck;
|
||||||
extern bool CalmaRecordPaths;
|
|
||||||
extern bool CalmaFlattenUses;
|
extern bool CalmaFlattenUses;
|
||||||
extern int CalmaFlattenLimit;
|
extern int CalmaFlattenLimit;
|
||||||
extern float CalmaMagScale;
|
extern float CalmaMagScale;
|
||||||
|
|
@ -82,8 +81,6 @@ extern int calmaProcessDefZ(CellDef *def, gzFile outf, bool do_library);
|
||||||
#endif
|
#endif
|
||||||
extern bool calmaReadI2Record(int type, int *pvalue);
|
extern bool calmaReadI2Record(int type, int *pvalue);
|
||||||
extern bool calmaReadI4Record(int type, int *pvalue);
|
extern bool calmaReadI4Record(int type, int *pvalue);
|
||||||
extern void calmaReadX(Point *p, int iscale);
|
|
||||||
extern void calmaReadY(Point *p, int iscale);
|
|
||||||
extern void calmaReadPoint(Point *p, int iscale);
|
extern void calmaReadPoint(Point *p, int iscale);
|
||||||
extern bool calmaReadR8(double *pd);
|
extern bool calmaReadR8(double *pd);
|
||||||
extern bool calmaReadStampRecord(int type, int *stampptr);
|
extern bool calmaReadStampRecord(int type, int *stampptr);
|
||||||
|
|
|
||||||
350
cif/CIFgen.c
350
cif/CIFgen.c
|
|
@ -25,7 +25,6 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
||||||
#include <stdlib.h> /* for abs() */
|
#include <stdlib.h> /* for abs() */
|
||||||
#include <math.h> /* for ceil() and sqrt() */
|
#include <math.h> /* for ceil() and sqrt() */
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h> /* for strcmp() */
|
|
||||||
|
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
|
|
@ -1501,7 +1500,6 @@ cifBloatAllFunc(
|
||||||
|
|
||||||
while (!StackEmpty(BloatStack))
|
while (!StackEmpty(BloatStack))
|
||||||
{
|
{
|
||||||
Rect cifarea;
|
|
||||||
TileType tt;
|
TileType tt;
|
||||||
|
|
||||||
POPTILE(t, dinfo, BloatStack);
|
POPTILE(t, dinfo, BloatStack);
|
||||||
|
|
@ -1518,6 +1516,8 @@ cifBloatAllFunc(
|
||||||
|
|
||||||
if (op->co_distance > 0)
|
if (op->co_distance > 0)
|
||||||
{
|
{
|
||||||
|
Rect cifarea;
|
||||||
|
|
||||||
cifarea.r_xbot = area.r_xbot;
|
cifarea.r_xbot = area.r_xbot;
|
||||||
cifarea.r_ybot = area.r_ybot;
|
cifarea.r_ybot = area.r_ybot;
|
||||||
cifarea.r_xtop = area.r_xtop;
|
cifarea.r_xtop = area.r_xtop;
|
||||||
|
|
@ -1555,42 +1555,40 @@ cifBloatAllFunc(
|
||||||
{
|
{
|
||||||
tt = TiGetTypeExact(t);
|
tt = TiGetTypeExact(t);
|
||||||
if (op->co_distance > 0)
|
if (op->co_distance > 0)
|
||||||
DBNMPaintPlane(cifPlane, TiGetTypeExact(t), &cifarea,
|
GeoClip(&area, &clipArea);
|
||||||
CIFPaintTable, (PaintUndoInfo *) NULL);
|
|
||||||
else
|
|
||||||
DBNMPaintPlane(cifPlane, TiGetTypeExact(t), &area,
|
DBNMPaintPlane(cifPlane, TiGetTypeExact(t), &area,
|
||||||
CIFPaintTable, (PaintUndoInfo *) NULL);
|
CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Top */
|
/* Top */
|
||||||
if ((op->co_distance == 0) || (area.r_ytop < clipArea.r_ytop))
|
|
||||||
for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp))
|
for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp))
|
||||||
if (TTMaskHasType(connect, TiGetBottomType(tp)))
|
if (TTMaskHasType(connect, TiGetBottomType(tp)))
|
||||||
PUSHTILE(tp, (SplitDirection(tp) == ((tt & TT_DIRECTION) ? 1 : 0)) ?
|
PUSHTILE(tp,
|
||||||
(TileType)0 : (TileType)TT_SIDE, BloatStack);
|
(SplitDirection(tp) == ((tt & TT_DIRECTION) ? 1 : 0)) ?
|
||||||
|
(TileType)0 : (TileType)TT_SIDE,
|
||||||
|
BloatStack);
|
||||||
|
|
||||||
/* Left */
|
/* Left */
|
||||||
if ((op->co_distance == 0) || (area.r_xbot > clipArea.r_xbot))
|
|
||||||
for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp))
|
for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp))
|
||||||
if (TTMaskHasType(connect, TiGetRightType(tp)))
|
if (TTMaskHasType(connect, TiGetRightType(tp)))
|
||||||
PUSHTILE(tp, (TileType)TT_SIDE, BloatStack);
|
PUSHTILE(tp, (TileType)TT_SIDE, BloatStack);
|
||||||
|
|
||||||
/* Bottom */
|
/* Bottom */
|
||||||
if ((op->co_distance == 0) || (area.r_ybot > clipArea.r_ybot))
|
|
||||||
for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp))
|
for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp))
|
||||||
if (TTMaskHasType(connect, TiGetTopType(tp)))
|
if (TTMaskHasType(connect, TiGetTopType(tp)))
|
||||||
PUSHTILE(tp, (SplitDirection(tp) == ((tt & TT_DIRECTION) ? 1 : 0)) ?
|
PUSHTILE(tp,
|
||||||
(TileType)TT_SIDE : (TileType)0, BloatStack);
|
(SplitDirection(tp) == ((tt & TT_DIRECTION) ? 1 : 0)) ?
|
||||||
|
(TileType)TT_SIDE : (TileType)0,
|
||||||
|
BloatStack);
|
||||||
|
|
||||||
/* Right */
|
/* Right */
|
||||||
if ((op->co_distance == 0) || (area.r_xtop < clipArea.r_xtop))
|
|
||||||
for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp))
|
for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp))
|
||||||
if (TTMaskHasType(connect, TiGetLeftType(tp)))
|
if (TTMaskHasType(connect, TiGetLeftType(tp)))
|
||||||
PUSHTILE(tp, (TileType)0, BloatStack);
|
PUSHTILE(tp, (TileType)0, BloatStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear self */
|
/* Clear self */
|
||||||
// TiSetClient(tile, CIF_UNPROCESSED);
|
TiSetClient(tile, CIF_UNPROCESSED);
|
||||||
|
|
||||||
/* NOTE: Tiles must be cleared after the bloat-all function has
|
/* NOTE: Tiles must be cleared after the bloat-all function has
|
||||||
* completed. However, for bloat-all with a limiting distance,
|
* completed. However, for bloat-all with a limiting distance,
|
||||||
|
|
@ -4460,16 +4458,14 @@ bridgeErase(
|
||||||
maskBits = DBPlaneTypes[i];
|
maskBits = DBPlaneTypes[i];
|
||||||
TTMaskAndMask(&maskBits, &brlims->co_paintMask);
|
TTMaskAndMask(&maskBits, &brlims->co_paintMask);
|
||||||
if (!TTMaskEqual(&maskBits, &DBZeroTypeBits))
|
if (!TTMaskEqual(&maskBits, &DBZeroTypeBits))
|
||||||
if (DBSrPaintArea((Tile *) NULL, brlims->def->cd_planes[i],
|
if (DBSrPaintArea((Tile *) NULL, brlims->def->cd_planes[i], area, &brlims->co_paintMask, cifPaintFunc, CIFEraseTable))
|
||||||
area, &brlims->co_paintMask, cifPaintFunc, CIFEraseTable))
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (t = 0; t < TT_MAXTYPES; t++, temps++)
|
for (t = 0; t < TT_MAXTYPES; t++, temps++)
|
||||||
{
|
{
|
||||||
if (TTMaskHasType(&brlims->co_cifMask, t))
|
if (TTMaskHasType(&brlims->co_cifMask, t))
|
||||||
if (DBSrPaintArea((Tile *) NULL, *temps, area, &CIFSolidBits,
|
if (DBSrPaintArea((Tile *) NULL, *temps, area, &CIFSolidBits, cifPaintFunc, CIFEraseTable))
|
||||||
cifPaintFunc, CIFEraseTable))
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4770,106 +4766,6 @@ cifBridgeLimFunc2(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* cifNotSquareFunc --
|
|
||||||
*
|
|
||||||
* Process each tile and remove those which are square and not
|
|
||||||
* connected to any other tile of the same type. This operator aids
|
|
||||||
* in the detection of bar contacts to distinguish them from regular
|
|
||||||
* (square) contact cuts. Because of the special nature of the
|
|
||||||
* operator, only the negative-sense operator "not-square" is
|
|
||||||
* implemented, as the positive-sense operator is not especially
|
|
||||||
* useful (and can be implemented if needed with "not-square" and
|
|
||||||
* "and-not").
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* None.
|
|
||||||
*
|
|
||||||
* Side effects:
|
|
||||||
* Modifies the CIF planes.
|
|
||||||
*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
cifNotSquareFunc(
|
|
||||||
Tile *tile,
|
|
||||||
TileType dinfo,
|
|
||||||
ClientData clientData) /* (unused) */
|
|
||||||
{
|
|
||||||
Tile *tp;
|
|
||||||
TileType ttype;
|
|
||||||
Rect area;
|
|
||||||
int width, height;
|
|
||||||
bool isolated = TRUE;
|
|
||||||
|
|
||||||
if (IsSplit(tile)) return 0; /* Non-Manhattan tiles are never square */
|
|
||||||
ttype = TiGetType(tile);
|
|
||||||
if (ttype == TT_SPACE) return 0; /* Don't handle space tiles */
|
|
||||||
|
|
||||||
/* Search all four sides of the tile. Tiles are only considered square
|
|
||||||
* for the purposes of this operator if they are also unconnected to any
|
|
||||||
* other tile.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Top */
|
|
||||||
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp))
|
|
||||||
if (TiGetBottomType(tp) == ttype)
|
|
||||||
{
|
|
||||||
isolated = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Left */
|
|
||||||
if (isolated)
|
|
||||||
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
|
|
||||||
if (TiGetBottomType(tp) == ttype)
|
|
||||||
{
|
|
||||||
isolated = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bottom */
|
|
||||||
if (isolated)
|
|
||||||
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
|
|
||||||
if (TiGetBottomType(tp) == ttype)
|
|
||||||
{
|
|
||||||
isolated = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Right */
|
|
||||||
if (isolated)
|
|
||||||
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp))
|
|
||||||
if (TiGetBottomType(tp) == ttype)
|
|
||||||
{
|
|
||||||
isolated = FALSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
TiToRect(tile, &area);
|
|
||||||
|
|
||||||
if (isolated)
|
|
||||||
{
|
|
||||||
width = area.r_xtop - area.r_xbot;
|
|
||||||
height = area.r_ytop - area.r_ybot;
|
|
||||||
if (width == height) return 0; /* Square and isolated */
|
|
||||||
}
|
|
||||||
|
|
||||||
area.r_xbot *= cifScale;
|
|
||||||
area.r_ybot *= cifScale;
|
|
||||||
area.r_xtop *= cifScale;
|
|
||||||
area.r_ytop *= cifScale;
|
|
||||||
|
|
||||||
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *)NULL);
|
|
||||||
|
|
||||||
CIFTileOps += 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -4883,7 +4779,6 @@ cifNotSquareFunc(
|
||||||
* None.
|
* None.
|
||||||
*
|
*
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* Modifies the CIF planes.
|
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
@ -5045,47 +4940,6 @@ cifInteractingRegions(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* cifCopyPropPlaneFunc --
|
|
||||||
*
|
|
||||||
* Copy the contents of a plane saved as a plane-type property into the
|
|
||||||
* current CIF plane. The property plane is in magic internal
|
|
||||||
* coordinates, so each tile needs to be scaled and redrawn into the
|
|
||||||
* current CIF plane.
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* Zero to keep the search going
|
|
||||||
*
|
|
||||||
* Side effects:
|
|
||||||
* Copies translated geometry into the target plane.
|
|
||||||
*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
cifCopyPropPlaneFunc(Tile *tile,
|
|
||||||
TileType dinfo,
|
|
||||||
Plane *curPlane)
|
|
||||||
{
|
|
||||||
Rect bbox;
|
|
||||||
|
|
||||||
TiToRect(tile, &bbox);
|
|
||||||
|
|
||||||
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
|
|
||||||
|
|
||||||
bbox.r_xbot *= cifScale;
|
|
||||||
bbox.r_ybot *= cifScale;
|
|
||||||
bbox.r_xtop *= cifScale;
|
|
||||||
bbox.r_ytop *= cifScale;
|
|
||||||
|
|
||||||
cifScale = 1;
|
|
||||||
DBNMPaintPlane(curPlane, CIF_SOLIDTYPE, &bbox,
|
|
||||||
CIFPaintTable, (PaintUndoInfo *)NULL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -5137,15 +4991,13 @@ CIFGenLayer(
|
||||||
CIFSquaresInfo csi;
|
CIFSquaresInfo csi;
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
TileType ttype;
|
TileType ttype;
|
||||||
char *netname, *text;
|
char *netname;
|
||||||
Label *label;
|
|
||||||
BloatStruct bls;
|
BloatStruct bls;
|
||||||
BridgeStruct brs;
|
BridgeStruct brs;
|
||||||
BridgeLimStruct brlims;
|
BridgeLimStruct brlims;
|
||||||
BridgeData *bridge;
|
BridgeData *bridge;
|
||||||
BloatData *bloats, locbloat;
|
BloatData *bloats;
|
||||||
bool hstop = FALSE;
|
bool hstop = FALSE;
|
||||||
PropertyRecord *proprec;
|
|
||||||
char *propvalue;
|
char *propvalue;
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
|
|
@ -5543,6 +5395,7 @@ CIFGenLayer(
|
||||||
nextPlane = temp;
|
nextPlane = temp;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case CIFOP_MAXRECT:
|
case CIFOP_MAXRECT:
|
||||||
cifPlane = curPlane;
|
cifPlane = curPlane;
|
||||||
|
|
||||||
|
|
@ -5565,19 +5418,6 @@ CIFGenLayer(
|
||||||
nextPlane = temp;
|
nextPlane = temp;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CIFOP_NOTSQUARE:
|
|
||||||
DBClearPaintPlane(nextPlane);
|
|
||||||
cifPlane = nextPlane;
|
|
||||||
cifScale = 1;
|
|
||||||
DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect,
|
|
||||||
&CIFSolidBits, cifNotSquareFunc,
|
|
||||||
(ClientData)NULL);
|
|
||||||
|
|
||||||
temp = curPlane;
|
|
||||||
curPlane = nextPlane;
|
|
||||||
nextPlane = temp;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CIFOP_NET:
|
case CIFOP_NET:
|
||||||
if (hier)
|
if (hier)
|
||||||
{
|
{
|
||||||
|
|
@ -5603,105 +5443,6 @@ CIFGenLayer(
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CIFOP_TAGGED:
|
|
||||||
if (hier)
|
|
||||||
{
|
|
||||||
hstop = TRUE; /* Stop hierarchical processing */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find all relevant labels by text matching and then continue
|
|
||||||
* like CIFOP_BLOATALL. CIFOP_BLOATALL uses a BloatData record
|
|
||||||
* which is not part of CIFOP_TAGGED. Create a BloatData record
|
|
||||||
* on the fly for each tagged area based on type, and swap it for
|
|
||||||
* the text, so that cifBloatAllFunc believes this is actually a
|
|
||||||
* CIFOP_BLOATALL operation. Note that we don't actually care
|
|
||||||
* what layer the label is attached to (lab_type). We are looking
|
|
||||||
* for labels whose lab_rect values overlap the types that are given
|
|
||||||
* in the rule.
|
|
||||||
*/
|
|
||||||
|
|
||||||
cifPlane = curPlane;
|
|
||||||
bls.op = op;
|
|
||||||
bls.def = cellDef;
|
|
||||||
bls.temps = temps;
|
|
||||||
|
|
||||||
text = (char *)op->co_client;
|
|
||||||
|
|
||||||
bloats = &locbloat;
|
|
||||||
if (!TTMaskIsZero(&op->co_cifMask))
|
|
||||||
{
|
|
||||||
bloats->bl_plane = -1;
|
|
||||||
for (ttype = 0; ttype < TT_MAXTYPES; ttype++)
|
|
||||||
{
|
|
||||||
if (TTMaskHasType(&op->co_cifMask, ttype))
|
|
||||||
bloats->bl_distance[ttype] = 1;
|
|
||||||
else
|
|
||||||
bloats->bl_distance[ttype] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!TTMaskIsZero(&op->co_paintMask))
|
|
||||||
{
|
|
||||||
int plane, pmask;
|
|
||||||
pmask = DBTechTypesToPlanes(&op->co_paintMask);
|
|
||||||
for (plane = PL_TECHDEPBASE; plane < DBNumPlanes; plane++)
|
|
||||||
if (PlaneMaskHasPlane(pmask, plane))
|
|
||||||
break;
|
|
||||||
bloats->bl_plane = plane;
|
|
||||||
for (ttype = 0; ttype < TT_MAXTYPES; ttype++)
|
|
||||||
{
|
|
||||||
if (TTMaskHasType(&op->co_paintMask, ttype))
|
|
||||||
bloats->bl_distance[ttype] = 1;
|
|
||||||
else
|
|
||||||
bloats->bl_distance[ttype] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Replace the client data with the bloat record */
|
|
||||||
op->co_client = (ClientData)bloats;
|
|
||||||
|
|
||||||
if (bloats->bl_plane < 0)
|
|
||||||
{
|
|
||||||
/* bl_plane == -1 indicates bloating into a CIF templayer, */
|
|
||||||
/* so the only connecting type should be CIF_SOLIDTYPE. */
|
|
||||||
TTMaskSetOnlyType(&bls.connect, CIF_SOLIDTYPE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
TTMaskZero(&bls.connect);
|
|
||||||
for (i = 0; i < TT_MAXTYPES; i++)
|
|
||||||
if (bloats->bl_distance[i] != 0)
|
|
||||||
TTMaskSetType(&bls.connect, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (label = cellDef->cd_labels; label; label = label->lab_next)
|
|
||||||
if (!strcmp(label->lab_text, text))
|
|
||||||
cifSrTiles(op, &label->lab_rect, cellDef, temps,
|
|
||||||
cifBloatAllFunc, (ClientData)&bls);
|
|
||||||
|
|
||||||
/* Reset marked tiles */
|
|
||||||
|
|
||||||
if (bloats->bl_plane < 0) /* Bloat types are CIF types */
|
|
||||||
{
|
|
||||||
bls.temps = temps;
|
|
||||||
for (ttype = 0; ttype < TT_MAXTYPES; ttype++, bls.temps++)
|
|
||||||
if (bloats->bl_distance[ttype] > 0)
|
|
||||||
(void) DBSrPaintArea((Tile *)NULL, *bls.temps, &TiPlaneRect,
|
|
||||||
&CIFSolidBits, cifProcessResetFunc,
|
|
||||||
(ClientData)NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
DBSrPaintArea((Tile *)NULL, cellDef->cd_planes[bloats->bl_plane],
|
|
||||||
&TiPlaneRect, &bls.connect, cifProcessResetFunc,
|
|
||||||
(ClientData)NULL);
|
|
||||||
|
|
||||||
/* Replace the client data */
|
|
||||||
op->co_client = (ClientData)text;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CIFOP_BOUNDARY:
|
case CIFOP_BOUNDARY:
|
||||||
if (hier)
|
if (hier)
|
||||||
{
|
{
|
||||||
|
|
@ -5713,17 +5454,10 @@ CIFGenLayer(
|
||||||
|
|
||||||
if (origDef && (origDef->cd_flags & CDFIXEDBBOX))
|
if (origDef && (origDef->cd_flags & CDFIXEDBBOX))
|
||||||
{
|
{
|
||||||
proprec = DBPropGet(origDef, "FIXED_BBOX", &found);
|
propvalue = (char *)DBPropGet(origDef, "FIXED_BBOX", &found);
|
||||||
if (!found) break;
|
if (!found) break;
|
||||||
|
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
&bbox.r_xtop, &bbox.r_ytop) != 4) break;
|
||||||
(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];
|
|
||||||
}
|
|
||||||
|
|
||||||
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
|
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
|
||||||
bbox.r_xbot *= cifScale;
|
bbox.r_xbot *= cifScale;
|
||||||
|
|
@ -5785,22 +5519,46 @@ CIFGenLayer(
|
||||||
|
|
||||||
case CIFOP_MASKHINTS:
|
case CIFOP_MASKHINTS:
|
||||||
{
|
{
|
||||||
int n;
|
int j, numfound;
|
||||||
char propname[512];
|
char propname[512];
|
||||||
|
char *propptr;
|
||||||
char *layername = (char *)op->co_client;
|
char *layername = (char *)op->co_client;
|
||||||
Tile *t;
|
|
||||||
|
|
||||||
snprintf(propname, 512, "MASKHINTS_%s", layername);
|
sprintf(propname, "MASKHINTS_%s", layername);
|
||||||
|
|
||||||
if (cellDef == (CellDef *)NULL) break;
|
propvalue = (char *)DBPropGet(cellDef, propname, &found);
|
||||||
proprec = DBPropGet(cellDef, propname, &found);
|
|
||||||
if (!found) break; /* No mask hints available */
|
if (!found) break; /* No mask hints available */
|
||||||
|
propptr = propvalue;
|
||||||
|
while (*propptr)
|
||||||
|
{
|
||||||
|
numfound = sscanf(propptr, "%d %d %d %d",
|
||||||
|
&bbox.r_xbot, &bbox.r_ybot,
|
||||||
|
&bbox.r_xtop, &bbox.r_ytop);
|
||||||
|
|
||||||
ASSERT (proprec->prop_type == PROPERTY_TYPE_PLANE, "CIFGenLayer");
|
if (numfound != 4)
|
||||||
t = PlaneGetHint(proprec->prop_value.prop_plane);
|
{
|
||||||
DBSrPaintArea(t, proprec->prop_value.prop_plane,
|
/* To do: Allow keyword "rect", "tri", or "poly"
|
||||||
&TiPlaneRect, &CIFSolidBits,
|
* at the start of the list and parse accordingly.
|
||||||
cifCopyPropPlaneFunc, (ClientData)curPlane);
|
* For now, this only flags an error.
|
||||||
|
*/
|
||||||
|
TxError("%s: Cannot read rectangle values.\n", propname);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cifPlane = curPlane;
|
||||||
|
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
|
||||||
|
bbox.r_xbot *= cifScale;
|
||||||
|
bbox.r_xtop *= cifScale;
|
||||||
|
bbox.r_ybot *= cifScale;
|
||||||
|
bbox.r_ytop *= cifScale;
|
||||||
|
cifScale = 1;
|
||||||
|
DBNMPaintPlane(curPlane, CIF_SOLIDTYPE, &bbox,
|
||||||
|
CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||||
|
for (j = 0; j < 4; j++)
|
||||||
|
{
|
||||||
|
while (*propptr && isspace(*propptr)) propptr++;
|
||||||
|
while (*propptr && !isspace(*propptr)) propptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
||||||
162
cif/CIFhier.c
162
cif/CIFhier.c
|
|
@ -209,41 +209,52 @@ typedef struct _maskHintsData
|
||||||
{
|
{
|
||||||
Transform *mh_trans;
|
Transform *mh_trans;
|
||||||
CellDef *mh_def;
|
CellDef *mh_def;
|
||||||
Plane *mh_plane;
|
|
||||||
} MaskHintsData;
|
} MaskHintsData;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* cifCopyMaskHintFunc --
|
* cifMaskHints --
|
||||||
*
|
*
|
||||||
* Callback function used by cifFlatMaskHints. Transforms a tile
|
* Copy a mask hint into a target cell by adding it to the
|
||||||
* from the original plane and paints it into the target plane,
|
* property list of the target cell. If the target cell already
|
||||||
* both of which are properties.
|
* has the same mask hint key, then the mask hint value is
|
||||||
|
* appended to the property in the target cell def.
|
||||||
*
|
*
|
||||||
* Results:
|
* Returns:
|
||||||
* Zero to keep the search going.
|
* 0 to keep the search going.
|
||||||
*
|
*
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* Paints geometry into the target plane.
|
* Modifies properties of the target cell def.
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* DEPRECATED */
|
||||||
int
|
int
|
||||||
cifCopyMaskHintFunc(Tile *tile,
|
cifMaskHints(
|
||||||
TileType dinfo,
|
char *name,
|
||||||
ClientData cdata)
|
char *value,
|
||||||
|
CellDef *targetDef)
|
||||||
{
|
{
|
||||||
MaskHintsData *mhd = (MaskHintsData *)cdata;
|
char *propvalue, *newval;
|
||||||
Rect r, newr;
|
bool propfound;
|
||||||
|
|
||||||
TiToRect(tile, &r);
|
if (!strncmp(name, "MASKHINTS_", 10))
|
||||||
|
{
|
||||||
/* Transform tile area to coordinates of mhd->mh_plane and paint */
|
/* Check if name exists already in the flattened cell */
|
||||||
GeoTransRect(mhd->mh_trans, &r, &newr);
|
propvalue = (char *)DBPropGet(targetDef, name, &propfound);
|
||||||
DBPaintPlane(mhd->mh_plane, &newr, CIFPaintTable, (PaintUndoInfo *)NULL);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -253,8 +264,8 @@ cifCopyMaskHintFunc(Tile *tile,
|
||||||
* cifFlatMaskHints --
|
* cifFlatMaskHints --
|
||||||
*
|
*
|
||||||
* Copy a mask hint into a flattened cell by transforming it into the
|
* Copy a mask hint into a flattened cell by transforming it into the
|
||||||
* coordinate system of the flattened cell, and painting it into the
|
* coordinate system of the flattened cell, and adding it to the
|
||||||
* property plane of the flattened cell.
|
* property list of the flattened cell.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* 0 to keep the search going.
|
* 0 to keep the search going.
|
||||||
|
|
@ -268,40 +279,67 @@ cifCopyMaskHintFunc(Tile *tile,
|
||||||
int
|
int
|
||||||
cifFlatMaskHints(
|
cifFlatMaskHints(
|
||||||
char *name,
|
char *name,
|
||||||
PropertyRecord *proprec,
|
char *value,
|
||||||
MaskHintsData *mhd)
|
MaskHintsData *mhd)
|
||||||
{
|
{
|
||||||
Rect r, newr;
|
Rect r, newr;
|
||||||
char *vptr, *newval, *lastval, *propvalue;
|
char *vptr, *newval, *lastval, *propvalue;
|
||||||
bool propfound;
|
bool propfound;
|
||||||
int i, lastlen, numvals;
|
int lastlen, numvals;
|
||||||
PropertyRecord *newproprec, *oldproprec;
|
|
||||||
Plane *plane;
|
|
||||||
|
|
||||||
if (!strncmp(name, "MASKHINTS_", 10))
|
if (!strncmp(name, "MASKHINTS_", 10))
|
||||||
{
|
{
|
||||||
/* Check if name exists already in the flattened cell */
|
newval = (char *)NULL;
|
||||||
oldproprec = (PropertyRecord *)DBPropGet(mhd->mh_def, name, &propfound);
|
vptr = value;
|
||||||
if (propfound)
|
while (*vptr != '\0')
|
||||||
{
|
{
|
||||||
ASSERT(oldproprec->prop_value.prop_type == PROPERTY_TYPE_PLANE,
|
numvals = sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||||
"cifFlatMaskHints");
|
&r.r_xtop, &r.r_ytop);
|
||||||
plane = oldproprec->prop_value.prop_plane;
|
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
|
else
|
||||||
{
|
{
|
||||||
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
TxError("MASKHINTS_%s: Expected 4 values, found only %d\n",
|
||||||
newproprec->prop_len = 0; /* (unused) */
|
name + 10, numvals);
|
||||||
newproprec->prop_type = PROPERTY_TYPE_PLANE;
|
break;
|
||||||
plane = DBNewPlane((ClientData)TT_SPACE);
|
}
|
||||||
newproprec->prop_value.prop_plane = plane;
|
|
||||||
DBPropPut(mhd->mh_def, name, newproprec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mhd->mh_plane = plane;
|
/* Check if name exists already in the flattened cell */
|
||||||
DBSrPaintArea((Tile *)NULL, proprec->prop_value.prop_plane,
|
propvalue = (char *)DBPropGet(mhd->mh_def, name, &propfound);
|
||||||
&TiPlaneRect, &CIFSolidBits,
|
if (propfound)
|
||||||
cifCopyMaskHintFunc, (ClientData)mhd);
|
{
|
||||||
|
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -312,10 +350,9 @@ cifFlatMaskHints(
|
||||||
* CIFCopyMaskHints --
|
* CIFCopyMaskHints --
|
||||||
*
|
*
|
||||||
* Callback function to copy mask hints from one cell into another.
|
* Callback function to copy mask hints from one cell into another.
|
||||||
* (Occasionally called as a standalone function, not as a callback.)
|
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* Return 0 to keep the search going.
|
* None.
|
||||||
*
|
*
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* May modify properties in the target cell.
|
* May modify properties in the target cell.
|
||||||
|
|
@ -323,7 +360,7 @@ cifFlatMaskHints(
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
void
|
||||||
CIFCopyMaskHints(
|
CIFCopyMaskHints(
|
||||||
SearchContext *scx,
|
SearchContext *scx,
|
||||||
CellDef *targetDef)
|
CellDef *targetDef)
|
||||||
|
|
@ -333,9 +370,38 @@ CIFCopyMaskHints(
|
||||||
CellDef *sourceDef = scx->scx_use->cu_def;
|
CellDef *sourceDef = scx->scx_use->cu_def;
|
||||||
mhd.mh_trans = &scx->scx_trans;
|
mhd.mh_trans = &scx->scx_trans;
|
||||||
mhd.mh_def = targetDef;
|
mhd.mh_def = targetDef;
|
||||||
mhd.mh_plane = (Plane *)NULL;
|
|
||||||
|
|
||||||
DBPropEnum(sourceDef, cifFlatMaskHints, &mhd);
|
DBPropEnum(sourceDef, cifFlatMaskHints, &mhd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* cifHierCopyMaskHints --
|
||||||
|
*
|
||||||
|
* Callback function to copy mask hints from a subcell into a flattened
|
||||||
|
* cell, which is passed in the clientData record.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* Always returns 0 to keep the search alive.
|
||||||
|
*
|
||||||
|
* Side effects:
|
||||||
|
* May modify properties in the flattened cell.
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
cifHierCopyMaskHints(
|
||||||
|
SearchContext *scx,
|
||||||
|
ClientData clientData)
|
||||||
|
{
|
||||||
|
MaskHintsData mhd;
|
||||||
|
|
||||||
|
mhd.mh_trans = &scx->scx_trans;
|
||||||
|
mhd.mh_def = (CellDef *)clientData;
|
||||||
|
|
||||||
|
DBPropEnum(scx->scx_use->cu_def, cifFlatMaskHints, &mhd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -460,7 +526,7 @@ cifHierCellFunc(
|
||||||
|
|
||||||
/* Flatten mask hints in the area of interest */
|
/* Flatten mask hints in the area of interest */
|
||||||
CIFCopyMaskHints(scx, CIFComponentDef);
|
CIFCopyMaskHints(scx, CIFComponentDef);
|
||||||
DBTreeSrCells(&newscx, 0, CIFCopyMaskHints,
|
DBTreeSrCells(&newscx, 0, cifHierCopyMaskHints,
|
||||||
(ClientData)CIFComponentDef);
|
(ClientData)CIFComponentDef);
|
||||||
|
|
||||||
/* Set CIFErrorDef to NULL to ignore errors here... these will
|
/* Set CIFErrorDef to NULL to ignore errors here... these will
|
||||||
|
|
@ -788,7 +854,7 @@ CIFGenSubcells(
|
||||||
cifHierCopyFunc, (ClientData) CIFTotalDef);
|
cifHierCopyFunc, (ClientData) CIFTotalDef);
|
||||||
/* Flatten mask hints in the area of interest */
|
/* Flatten mask hints in the area of interest */
|
||||||
CIFCopyMaskHints(&scx, CIFTotalDef);
|
CIFCopyMaskHints(&scx, CIFTotalDef);
|
||||||
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
||||||
(ClientData)CIFTotalDef);
|
(ClientData)CIFTotalDef);
|
||||||
|
|
||||||
CIFErrorDef = def;
|
CIFErrorDef = def;
|
||||||
|
|
@ -966,14 +1032,14 @@ cifHierElementFunc(
|
||||||
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
|
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
|
||||||
cifHierCopyFunc, (ClientData) CIFTotalDef);
|
cifHierCopyFunc, (ClientData) CIFTotalDef);
|
||||||
CIFCopyMaskHints(&scx, CIFTotalDef);
|
CIFCopyMaskHints(&scx, CIFTotalDef);
|
||||||
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
||||||
(ClientData)CIFTotalDef);
|
(ClientData)CIFTotalDef);
|
||||||
|
|
||||||
DBCellClearDef(CIFComponentDef);
|
DBCellClearDef(CIFComponentDef);
|
||||||
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
|
(void) DBTreeSrTiles(&scx, &CIFCurStyle->cs_yankLayers, 0,
|
||||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||||
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
||||||
(ClientData)CIFComponentDef);
|
(ClientData)CIFComponentDef);
|
||||||
|
|
||||||
CIFErrorDef = (CellDef *) NULL;
|
CIFErrorDef = (CellDef *) NULL;
|
||||||
|
|
|
||||||
|
|
@ -145,8 +145,6 @@ typedef struct cifop
|
||||||
* CIFOP_BRIDGE - Added 6/11/20---Bridge across catecorner gaps
|
* CIFOP_BRIDGE - Added 6/11/20---Bridge across catecorner gaps
|
||||||
* CIFOP_BRIDGELIM - Added 27/07/20---Bridge across catecorner gaps, but with limiting layers
|
* CIFOP_BRIDGELIM - Added 27/07/20---Bridge across catecorner gaps, but with limiting layers
|
||||||
* CIFOP_MASKHINTS - Added 12/14/20---Add geometry from cell properties, if any.
|
* CIFOP_MASKHINTS - Added 12/14/20---Add geometry from cell properties, if any.
|
||||||
* CIFOP_NOTSQUARE - Added 2/26/26---Keep only geometry which is not square.
|
|
||||||
* CIFOP_TAGGED - Added 3/11/26---Find geometry attached to the given text label
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define CIFOP_AND 1
|
#define CIFOP_AND 1
|
||||||
|
|
@ -174,8 +172,6 @@ typedef struct cifop
|
||||||
#define CIFOP_BRIDGE 23
|
#define CIFOP_BRIDGE 23
|
||||||
#define CIFOP_BRIDGELIM 24
|
#define CIFOP_BRIDGELIM 24
|
||||||
#define CIFOP_MASKHINTS 25
|
#define CIFOP_MASKHINTS 25
|
||||||
#define CIFOP_NOTSQUARE 26
|
|
||||||
#define CIFOP_TAGGED 27
|
|
||||||
|
|
||||||
/* Definitions of bit fields used in the value of co_client for CIFOP_INTERACT */
|
/* Definitions of bit fields used in the value of co_client for CIFOP_INTERACT */
|
||||||
#define CIFOP_INT_NOT 0x1 /* Inverted sense (not interacting) */
|
#define CIFOP_INT_NOT 0x1 /* Inverted sense (not interacting) */
|
||||||
|
|
@ -340,8 +336,9 @@ extern Plane *CIFGenLayer(CIFOp *op, const Rect *area, CellDef *cellDef, CellDef
|
||||||
bool hier, ClientData clientdata);
|
bool hier, ClientData clientdata);
|
||||||
extern void CIFInitCells(void);
|
extern void CIFInitCells(void);
|
||||||
extern int cifHierCopyFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
|
extern int cifHierCopyFunc(Tile *tile, TileType dinfo, TreeContext *cxp);
|
||||||
|
extern int cifHierCopyMaskHints(SearchContext *scx, ClientData clientData);
|
||||||
extern void CIFLoadStyle(char *stylename);
|
extern void CIFLoadStyle(char *stylename);
|
||||||
extern int CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef);
|
extern void CIFCopyMaskHints(SearchContext *scx, CellDef *targetDef);
|
||||||
|
|
||||||
/* C99 compat */
|
/* C99 compat */
|
||||||
extern void CIFCoverageLayer(CellDef *rootDef, Rect *area, char *layer, bool dolist);
|
extern void CIFCoverageLayer(CellDef *rootDef, Rect *area, char *layer, bool dolist);
|
||||||
|
|
|
||||||
191
cif/CIFrdcl.c
191
cif/CIFrdcl.c
|
|
@ -613,7 +613,7 @@ CIFPaintCurrent(
|
||||||
CIFOp *op;
|
CIFOp *op;
|
||||||
|
|
||||||
plane = CIFGenLayer(cifCurReadStyle->crs_layers[i]->crl_ops,
|
plane = CIFGenLayer(cifCurReadStyle->crs_layers[i]->crl_ops,
|
||||||
&TiPlaneRect, cifReadCellDef, cifReadCellDef,
|
&TiPlaneRect, (CellDef *)NULL, (CellDef *)NULL,
|
||||||
cifCurReadPlanes, FALSE, (ClientData)NULL);
|
cifCurReadPlanes, FALSE, (ClientData)NULL);
|
||||||
|
|
||||||
/* Generate a paint/erase table, then paint from the CIF
|
/* Generate a paint/erase table, then paint from the CIF
|
||||||
|
|
@ -688,8 +688,6 @@ CIFPaintCurrent(
|
||||||
}
|
}
|
||||||
else if (op == NULL)
|
else if (op == NULL)
|
||||||
{
|
{
|
||||||
LinkedRect *lrec = NULL, *lsrch;
|
|
||||||
|
|
||||||
/* Handle boundary layer */
|
/* Handle boundary layer */
|
||||||
|
|
||||||
op = cifCurReadStyle->crs_layers[i]->crl_ops;
|
op = cifCurReadStyle->crs_layers[i]->crl_ops;
|
||||||
|
|
@ -704,102 +702,6 @@ CIFPaintCurrent(
|
||||||
(ClientData)NULL) == 1))
|
(ClientData)NULL) == 1))
|
||||||
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
|
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
|
||||||
&CIFSolidBits, cifMakeBoundaryFunc, INT2CD(filetype));
|
&CIFSolidBits, cifMakeBoundaryFunc, INT2CD(filetype));
|
||||||
|
|
||||||
/* Handle mask-hints input operator */
|
|
||||||
|
|
||||||
op = cifCurReadStyle->crs_layers[i]->crl_ops;
|
|
||||||
while (op)
|
|
||||||
{
|
|
||||||
if (op->co_opcode == CIFOP_MASKHINTS) break;
|
|
||||||
op = op->co_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (op && (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect,
|
|
||||||
&DBAllButSpaceBits, cifCheckPaintFunc,
|
|
||||||
(ClientData)NULL) == 1))
|
|
||||||
{
|
|
||||||
/* (To do: remove the linked Rects and paint directly
|
|
||||||
* into the plane in cifMaskHintFunc())
|
|
||||||
*/
|
|
||||||
DBSrPaintArea((Tile *) NULL, plane, &TiPlaneRect,
|
|
||||||
&CIFSolidBits, cifMaskHintFunc,
|
|
||||||
(ClientData)&lrec);
|
|
||||||
|
|
||||||
if (lrec != NULL)
|
|
||||||
{
|
|
||||||
PropertyRecord *proprec, *proporig;
|
|
||||||
char *propname, *layername;
|
|
||||||
int proplen, i, savescale;
|
|
||||||
bool origfound = FALSE;
|
|
||||||
Plane *plane;
|
|
||||||
|
|
||||||
layername = (char *)op->co_client;
|
|
||||||
propname = (char *)mallocMagic(11 + strlen(layername));
|
|
||||||
sprintf(propname, "MASKHINTS_%s", layername);
|
|
||||||
|
|
||||||
/* If there is already a mask hint plane for this layer,
|
|
||||||
* then add to it; otherwise, create a new plane.
|
|
||||||
*/
|
|
||||||
proprec = DBPropGet(cifReadCellDef, layername, &origfound);
|
|
||||||
if (origfound)
|
|
||||||
plane = proprec->prop_value.prop_plane;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
proprec = (PropertyRecord *)mallocMagic(
|
|
||||||
sizeof(PropertyRecord));
|
|
||||||
proprec->prop_type = PROPERTY_TYPE_PLANE;
|
|
||||||
proprec->prop_len = 0; /* (unused) */
|
|
||||||
plane = DBNewPlane((ClientData)TT_SPACE);
|
|
||||||
proprec->prop_value.prop_plane = plane;
|
|
||||||
DBPropPut(cifReadCellDef, propname, proprec);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (lrec != NULL)
|
|
||||||
{
|
|
||||||
lrec->r_r.r_xtop =
|
|
||||||
CIFScaleCoord(lrec->r_r.r_xtop, COORD_EXACT);
|
|
||||||
savescale = cifCurReadStyle->crs_scaleFactor;
|
|
||||||
lrec->r_r.r_ytop =
|
|
||||||
CIFScaleCoord(lrec->r_r.r_ytop, COORD_EXACT);
|
|
||||||
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
|
||||||
{
|
|
||||||
lrec->r_r.r_xtop *=
|
|
||||||
(savescale / cifCurReadStyle->crs_scaleFactor);
|
|
||||||
savescale = cifCurReadStyle->crs_scaleFactor;
|
|
||||||
}
|
|
||||||
lrec->r_r.r_xbot =
|
|
||||||
CIFScaleCoord(lrec->r_r.r_xbot, COORD_EXACT);
|
|
||||||
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
|
||||||
{
|
|
||||||
lrec->r_r.r_xtop *=
|
|
||||||
(savescale / cifCurReadStyle->crs_scaleFactor);
|
|
||||||
lrec->r_r.r_ytop *=
|
|
||||||
(savescale / cifCurReadStyle->crs_scaleFactor);
|
|
||||||
savescale = cifCurReadStyle->crs_scaleFactor;
|
|
||||||
}
|
|
||||||
lrec->r_r.r_ybot =
|
|
||||||
CIFScaleCoord(lrec->r_r.r_ybot, COORD_EXACT);
|
|
||||||
if (savescale != cifCurReadStyle->crs_scaleFactor)
|
|
||||||
{
|
|
||||||
lrec->r_r.r_xtop *=
|
|
||||||
(savescale / cifCurReadStyle->crs_scaleFactor);
|
|
||||||
lrec->r_r.r_ytop *=
|
|
||||||
(savescale / cifCurReadStyle->crs_scaleFactor);
|
|
||||||
lrec->r_r.r_xbot *=
|
|
||||||
(savescale / cifCurReadStyle->crs_scaleFactor);
|
|
||||||
}
|
|
||||||
|
|
||||||
DBPaintPlane(plane, &lrec->r_r, CIFPaintTable,
|
|
||||||
(PaintUndoInfo *)NULL);
|
|
||||||
|
|
||||||
free_magic1_t mm1 = freeMagic1_init();
|
|
||||||
freeMagic1(&mm1, lrec);
|
|
||||||
lrec = lrec->r_next;
|
|
||||||
freeMagic1_end(&mm1);
|
|
||||||
}
|
|
||||||
freeMagic(propname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Swap planes */
|
/* Swap planes */
|
||||||
|
|
@ -888,7 +790,9 @@ CIFPaintCurrent(
|
||||||
|
|
||||||
for (i = 0; i < cifNReadLayers; i++)
|
for (i = 0; i < cifNReadLayers; i++)
|
||||||
{
|
{
|
||||||
LinkedRect *lrec = NULL, *lsrch;
|
LinkedRect *lrec = NULL;
|
||||||
|
char *propstr = NULL;
|
||||||
|
char locstr[512];
|
||||||
Plane *tempp;
|
Plane *tempp;
|
||||||
|
|
||||||
if (!TTMaskHasType(CalmaMaskHints, i)) continue;
|
if (!TTMaskHasType(CalmaMaskHints, i)) continue;
|
||||||
|
|
@ -913,55 +817,53 @@ CIFPaintCurrent(
|
||||||
(CellDef *)NULL, CIFPlanes, FALSE, (ClientData)NULL);
|
(CellDef *)NULL, CIFPlanes, FALSE, (ClientData)NULL);
|
||||||
|
|
||||||
/* Scan the resulting plane and generate linked Rect structures for
|
/* Scan the resulting plane and generate linked Rect structures for
|
||||||
* each shape found. (To do: Remove the linked Rects and paint
|
* each shape found.
|
||||||
* directly into the plane in cifMaskHintFunc(), which is more
|
|
||||||
* efficient but not hugely so.)
|
|
||||||
*/
|
*/
|
||||||
DBSrPaintArea((Tile *)NULL, presult, &TiPlaneRect, &CIFSolidBits,
|
DBSrPaintArea((Tile *)NULL, presult, &TiPlaneRect, &CIFSolidBits,
|
||||||
cifMaskHintFunc, (ClientData)&lrec);
|
cifMaskHintFunc, (ClientData)&lrec);
|
||||||
|
|
||||||
if (lrec != NULL)
|
if (lrec != NULL)
|
||||||
{
|
{
|
||||||
PropertyRecord *proprec;
|
|
||||||
bool propfound;
|
|
||||||
char *propname;
|
char *propname;
|
||||||
Plane *plane;
|
|
||||||
|
|
||||||
propname = (char *)mallocMagic(11 + strlen(cifReadLayers[i]));
|
propname = (char *)mallocMagic(11 + strlen(cifReadLayers[i]));
|
||||||
sprintf(propname, "MASKHINTS_%s", cifReadLayers[i]);
|
sprintf(propname, "MASKHINTS_%s", cifReadLayers[i]);
|
||||||
|
|
||||||
/* Paint all linked Rects into a mask-hints property plane
|
propstr = (char *)NULL;
|
||||||
* in the target cell.
|
|
||||||
|
/* 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)
|
while (lrec != NULL)
|
||||||
{
|
{
|
||||||
lrec->r_r.r_xbot /= CIFCurStyle->cs_scaleFactor;
|
char *newstr;
|
||||||
lrec->r_r.r_ybot /= CIFCurStyle->cs_scaleFactor;
|
sprintf(locstr, "%d %d %d %d",
|
||||||
lrec->r_r.r_xtop /= CIFCurStyle->cs_scaleFactor;
|
lrec->r_r.r_xbot / CIFCurStyle->cs_scaleFactor,
|
||||||
lrec->r_r.r_ytop /= CIFCurStyle->cs_scaleFactor;
|
lrec->r_r.r_ybot / CIFCurStyle->cs_scaleFactor,
|
||||||
|
lrec->r_r.r_xtop / CIFCurStyle->cs_scaleFactor,
|
||||||
DBPaintPlane(plane, &lrec->r_r, CIFPaintTable,
|
lrec->r_r.r_ytop / CIFCurStyle->cs_scaleFactor);
|
||||||
(PaintUndoInfo *)NULL);
|
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();
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
freeMagic1(&mm1, lrec);
|
freeMagic1(&mm1, lrec);
|
||||||
lrec = lrec->r_next;
|
lrec = lrec->r_next;
|
||||||
freeMagic1_end(&mm1);
|
freeMagic1_end(&mm1);
|
||||||
}
|
}
|
||||||
|
/* NOTE: propstr is transferred to the CellDef and should
|
||||||
|
* not be free'd here.
|
||||||
|
*/
|
||||||
|
DBPropPut(cifReadCellDef, propname, propstr);
|
||||||
freeMagic(propname);
|
freeMagic(propname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1000,7 +902,6 @@ cifMakeBoundaryFunc(
|
||||||
/* If there are multiple rectangles defined with the boundary */
|
/* If there are multiple rectangles defined with the boundary */
|
||||||
/* layer, then the last one defines the FIXED_BBOX property. */
|
/* layer, then the last one defines the FIXED_BBOX property. */
|
||||||
|
|
||||||
PropertyRecord *proprec;
|
|
||||||
Rect area;
|
Rect area;
|
||||||
char propertyvalue[128], *storedvalue;
|
char propertyvalue[128], *storedvalue;
|
||||||
int savescale;
|
int savescale;
|
||||||
|
|
@ -1032,24 +933,19 @@ cifMakeBoundaryFunc(
|
||||||
|
|
||||||
if (cifReadCellDef->cd_flags & CDFIXEDBBOX)
|
if (cifReadCellDef->cd_flags & CDFIXEDBBOX)
|
||||||
{
|
{
|
||||||
PropertyRecord *proprec;
|
char *propvalue;
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
/* Only flag a warning if the redefined boundary was */
|
/* Only flag a warning if the redefined boundary was */
|
||||||
/* different from the original. */
|
/* different from the original. */
|
||||||
|
|
||||||
proprec = DBPropGet(cifReadCellDef, "FIXED_BBOX", &found);
|
propvalue = (char *)DBPropGet(cifReadCellDef, "FIXED_BBOX", &found);
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
Rect bbox;
|
Rect bbox;
|
||||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||||
(proprec->prop_len == 4))
|
&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) ||
|
if ((bbox.r_xbot != area.r_xbot) ||
|
||||||
(bbox.r_ybot != area.r_ybot) ||
|
(bbox.r_ybot != area.r_ybot) ||
|
||||||
(bbox.r_xtop != area.r_xtop) ||
|
(bbox.r_xtop != area.r_xtop) ||
|
||||||
|
|
@ -1066,15 +962,10 @@ cifMakeBoundaryFunc(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) + 2 * sizeof(int));
|
sprintf(propertyvalue, "%d %d %d %d",
|
||||||
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
area.r_xbot, area.r_ybot, area.r_xtop, area.r_ytop);
|
||||||
proprec->prop_len = 4;
|
storedvalue = StrDup((char **)NULL, propertyvalue);
|
||||||
proprec->prop_value.prop_integer[0] = area.r_xbot;
|
DBPropPut(cifReadCellDef, "FIXED_BBOX", storedvalue);
|
||||||
proprec->prop_value.prop_integer[1] = area.r_ybot;
|
|
||||||
proprec->prop_value.prop_integer[2] = area.r_xtop;
|
|
||||||
proprec->prop_value.prop_integer[3] = area.r_ytop;
|
|
||||||
|
|
||||||
DBPropPut(cifReadCellDef, "FIXED_BBOX", proprec);
|
|
||||||
cifReadCellDef->cd_flags |= CDFIXEDBBOX;
|
cifReadCellDef->cd_flags |= CDFIXEDBBOX;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1786,8 +1677,8 @@ CIFReadCellCleanup(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do geometrical processing on the top-level cell. */
|
/* Do geometrical processing on the top-level cell. */
|
||||||
if (filetype == FILE_CIF) CIFPaintCurrent(filetype);
|
|
||||||
|
|
||||||
|
CIFPaintCurrent(FILE_CIF);
|
||||||
DBAdjustLabels(EditCellUse->cu_def, &TiPlaneRect);
|
DBAdjustLabels(EditCellUse->cu_def, &TiPlaneRect);
|
||||||
DBReComputeBbox(EditCellUse->cu_def);
|
DBReComputeBbox(EditCellUse->cu_def);
|
||||||
DBWAreaChanged(EditCellUse->cu_def, &EditCellUse->cu_def->cd_bbox,
|
DBWAreaChanged(EditCellUse->cu_def, &EditCellUse->cu_def->cd_bbox,
|
||||||
|
|
|
||||||
|
|
@ -244,61 +244,40 @@ CIFPropRecordPath(
|
||||||
{
|
{
|
||||||
extern float CIFGetOutputScale(int convert);
|
extern float CIFGetOutputScale(int convert);
|
||||||
CIFPath *pathp;
|
CIFPath *pathp;
|
||||||
char *namestr = NULL;
|
char *pathstr, *sptr;
|
||||||
int components, i, x, y, mult, pathnum;
|
int components;
|
||||||
PropertyRecord *proprec;
|
float x, y, oscale, mult;
|
||||||
bool propfound;
|
|
||||||
|
|
||||||
/* If "name" is a property, then append a suffix to it to ensure uniqueness */
|
oscale = CIFGetOutputScale(1000); /* 1000 for conversion to um */
|
||||||
DBPropGet(def, propname, &propfound);
|
if (oscale == 0.0) oscale = 1.0;
|
||||||
if (propfound)
|
mult = (iswire == TRUE) ? 0.5 : 1.0;
|
||||||
{
|
|
||||||
pathnum = 0;
|
|
||||||
namestr = mallocMagic(strlen(propname) + 10);
|
|
||||||
while (propfound)
|
|
||||||
{
|
|
||||||
sprintf(namestr, "%s_%d", propname, pathnum);
|
|
||||||
DBPropGet(def, namestr, &propfound);
|
|
||||||
pathnum++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mult = (iswire == TRUE) ? 1 : 0;
|
|
||||||
|
|
||||||
/* Count the number of components in the path */
|
|
||||||
pathp = pathheadp;
|
pathp = pathheadp;
|
||||||
components = 0;
|
components = 0;
|
||||||
|
|
||||||
|
/* Count the number of components in the path */
|
||||||
while (pathp != NULL)
|
while (pathp != NULL)
|
||||||
{
|
{
|
||||||
components++;
|
|
||||||
pathp = pathp->cifp_next;
|
pathp = pathp->cifp_next;
|
||||||
|
components++;
|
||||||
}
|
}
|
||||||
/* Allocate enough space to hold 2 * N points. */
|
/* Allocate enough space to hold 2 * N points at "infinity" */
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
pathstr = (char *)mallocMagic(components * 40);
|
||||||
((components - 1) * 2) * sizeof(int));
|
|
||||||
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
|
||||||
proprec->prop_len = components * 2;
|
|
||||||
|
|
||||||
pathp = pathheadp;
|
pathp = pathheadp;
|
||||||
i = 0;
|
sptr = pathstr;
|
||||||
while (pathp != NULL)
|
while (pathp != NULL)
|
||||||
{
|
{
|
||||||
x = pathp->cifp_x >> mult;
|
x = (float)pathp->cifp_x * oscale * mult;
|
||||||
y = pathp->cifp_y >> mult;
|
y = (float)pathp->cifp_y * oscale * mult;
|
||||||
|
sprintf(sptr, "%.3f %.3f ", x, y);
|
||||||
proprec->prop_value.prop_integer[i] = x;
|
sptr = sptr + strlen(sptr);
|
||||||
proprec->prop_value.prop_integer[i + 1] = y;
|
|
||||||
|
|
||||||
i += 2;
|
|
||||||
pathp = pathp->cifp_next;
|
pathp = pathp->cifp_next;
|
||||||
}
|
}
|
||||||
if (namestr)
|
|
||||||
{
|
/* Reallocate pathstr to be no larger than needed to hold the path contents */
|
||||||
DBPropPut(def, namestr, proprec);
|
StrDup(&pathstr, pathstr);
|
||||||
freeMagic(namestr);
|
DBPropPut(def, propname, (ClientData)pathstr);
|
||||||
}
|
|
||||||
else
|
|
||||||
DBPropPut(def, propname, proprec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -324,19 +324,14 @@ cifNewReadStyle(void)
|
||||||
{
|
{
|
||||||
/* Destroy old style and free all memory allocated to it */
|
/* Destroy old style and free all memory allocated to it */
|
||||||
|
|
||||||
for (i = 0; i < MAXCIFRLAYERS; i++)
|
for (i=0; i<MAXCIFRLAYERS; i+=1)
|
||||||
{
|
{
|
||||||
layer = cifCurReadStyle->crs_layers[i];
|
layer = cifCurReadStyle->crs_layers[i];
|
||||||
if (layer != NULL)
|
if (layer != NULL)
|
||||||
{
|
{
|
||||||
free_magic1_t mm1 = freeMagic1_init();
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (op = layer->crl_ops; op != NULL; op = op->co_next)
|
for (op = layer->crl_ops; op != NULL; op = op->co_next)
|
||||||
{
|
|
||||||
if (op->co_opcode == CIFOP_MASKHINTS ||
|
|
||||||
op->co_opcode == CIFOP_TAGGED)
|
|
||||||
freeMagic((char *)op->co_client);
|
|
||||||
freeMagic1(&mm1, (char *)op);
|
freeMagic1(&mm1, (char *)op);
|
||||||
}
|
|
||||||
freeMagic1_end(&mm1);
|
freeMagic1_end(&mm1);
|
||||||
freeMagic((char *)layer);
|
freeMagic((char *)layer);
|
||||||
}
|
}
|
||||||
|
|
@ -995,12 +990,6 @@ CIFReadTechLine(
|
||||||
newOp->co_opcode = CIFOP_COPYUP;
|
newOp->co_opcode = CIFOP_COPYUP;
|
||||||
else if (strcmp(argv[0], "boundary") == 0)
|
else if (strcmp(argv[0], "boundary") == 0)
|
||||||
newOp->co_opcode = CIFOP_BOUNDARY;
|
newOp->co_opcode = CIFOP_BOUNDARY;
|
||||||
else if (strcmp(argv[0], "not-square") == 0)
|
|
||||||
newOp->co_opcode = CIFOP_NOTSQUARE;
|
|
||||||
else if (strcmp(argv[0], "mask-hints") == 0)
|
|
||||||
newOp->co_opcode = CIFOP_MASKHINTS;
|
|
||||||
else if (strcmp(argv[0], "tagged") == 0)
|
|
||||||
newOp->co_opcode = CIFOP_TAGGED;
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TechError("Unknown statement \"%s\".\n", argv[0]);
|
TechError("Unknown statement \"%s\".\n", argv[0]);
|
||||||
|
|
@ -1027,15 +1016,6 @@ CIFReadTechLine(
|
||||||
goto errorReturn;
|
goto errorReturn;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CIFOP_MASKHINTS:
|
|
||||||
if (argc != 2) goto wrongNumArgs;
|
|
||||||
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
|
|
||||||
break;
|
|
||||||
case CIFOP_TAGGED:
|
|
||||||
if (argc != 3) goto wrongNumArgs;
|
|
||||||
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
|
|
||||||
CIFParseReadLayers(argv[2], &newOp->co_cifMask, TRUE);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Link the new CIFOp onto the list. */
|
/* Link the new CIFOp onto the list. */
|
||||||
|
|
@ -1119,7 +1099,6 @@ CIFReadTechFinal(void)
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
CIFReadLoadStyle(
|
CIFReadLoadStyle(
|
||||||
char *stylename)
|
char *stylename)
|
||||||
|
|
|
||||||
12
cif/CIFsee.c
12
cif/CIFsee.c
|
|
@ -168,7 +168,7 @@ CIFPaintLayer(
|
||||||
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
||||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||||
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
||||||
(ClientData)CIFComponentDef);
|
(ClientData)CIFComponentDef);
|
||||||
|
|
||||||
oldCount = DBWFeedbackCount;
|
oldCount = DBWFeedbackCount;
|
||||||
|
|
@ -289,7 +289,7 @@ CIFSeeLayer(
|
||||||
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
||||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||||
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
||||||
(ClientData)CIFComponentDef);
|
(ClientData)CIFComponentDef);
|
||||||
|
|
||||||
oldCount = DBWFeedbackCount;
|
oldCount = DBWFeedbackCount;
|
||||||
|
|
@ -461,7 +461,7 @@ CIFCoverageLayer(
|
||||||
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
(void) DBTreeSrTiles(&scx, &DBAllButSpaceAndDRCBits, 0,
|
||||||
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
cifHierCopyFunc, (ClientData) CIFComponentDef);
|
||||||
CIFCopyMaskHints(&scx, CIFComponentDef);
|
CIFCopyMaskHints(&scx, CIFComponentDef);
|
||||||
DBTreeSrCells(&scx, 0, CIFCopyMaskHints,
|
DBTreeSrCells(&scx, 0, cifHierCopyMaskHints,
|
||||||
(ClientData)CIFComponentDef);
|
(ClientData)CIFComponentDef);
|
||||||
|
|
||||||
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,
|
CIFGen(CIFComponentDef, rootDef, area, CIFPlanes, &depend, TRUE, TRUE,
|
||||||
|
|
@ -504,10 +504,10 @@ CIFCoverageLayer(
|
||||||
}
|
}
|
||||||
else
|
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);
|
"Cell", btotal);
|
||||||
TxPrintf("Layer Bounding Area = %"DLONG_PREFIX"d CIF units^2\n", atotal);
|
TxPrintf("Layer Bounding Area = %lld CIF units^2\n", atotal);
|
||||||
TxPrintf("Layer Total Area = %"DLONG_PREFIX"d CIF units^2\n", cstats.coverage);
|
TxPrintf("Layer Total Area = %lld CIF units^2\n", cstats.coverage);
|
||||||
TxPrintf("Coverage in %s = %1.1f%%\n", doBox ? "box" :
|
TxPrintf("Coverage in %s = %1.1f%%\n", doBox ? "box" :
|
||||||
"cell", 100.0 * fcover);
|
"cell", 100.0 * fcover);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1107,8 +1107,6 @@ CIFTechLine(
|
||||||
newOp->co_opcode = CIFOP_BBOX;
|
newOp->co_opcode = CIFOP_BBOX;
|
||||||
else if (strcmp(argv[0], "net") == 0)
|
else if (strcmp(argv[0], "net") == 0)
|
||||||
newOp->co_opcode = CIFOP_NET;
|
newOp->co_opcode = CIFOP_NET;
|
||||||
else if (strcmp(argv[0], "tagged") == 0)
|
|
||||||
newOp->co_opcode = CIFOP_TAGGED;
|
|
||||||
else if (strcmp(argv[0], "maxrect") == 0)
|
else if (strcmp(argv[0], "maxrect") == 0)
|
||||||
newOp->co_opcode = CIFOP_MAXRECT;
|
newOp->co_opcode = CIFOP_MAXRECT;
|
||||||
else if (strcmp(argv[0], "boundary") == 0)
|
else if (strcmp(argv[0], "boundary") == 0)
|
||||||
|
|
@ -1119,8 +1117,6 @@ CIFTechLine(
|
||||||
newOp->co_opcode = CIFOP_CLOSE;
|
newOp->co_opcode = CIFOP_CLOSE;
|
||||||
else if (strcmp(argv[0], "orthogonal") == 0)
|
else if (strcmp(argv[0], "orthogonal") == 0)
|
||||||
newOp->co_opcode = CIFOP_MANHATTAN;
|
newOp->co_opcode = CIFOP_MANHATTAN;
|
||||||
else if (strcmp(argv[0], "not-square") == 0)
|
|
||||||
newOp->co_opcode = CIFOP_NOTSQUARE;
|
|
||||||
else if (strcmp(argv[0], "bridge") == 0)
|
else if (strcmp(argv[0], "bridge") == 0)
|
||||||
newOp->co_opcode = CIFOP_BRIDGE;
|
newOp->co_opcode = CIFOP_BRIDGE;
|
||||||
else if (strcmp(argv[0], "bridge-lim") == 0)
|
else if (strcmp(argv[0], "bridge-lim") == 0)
|
||||||
|
|
@ -1359,7 +1355,6 @@ bloatCheck:
|
||||||
bloatDone: break;
|
bloatDone: break;
|
||||||
|
|
||||||
case CIFOP_NET:
|
case CIFOP_NET:
|
||||||
case CIFOP_TAGGED:
|
|
||||||
if (argc != 3) goto wrongNumArgs;
|
if (argc != 3) goto wrongNumArgs;
|
||||||
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
|
newOp->co_client = (ClientData)StrDup((char **)NULL, argv[1]);
|
||||||
cifParseLayers(argv[2], CIFCurStyle, &newOp->co_paintMask,
|
cifParseLayers(argv[2], CIFCurStyle, &newOp->co_paintMask,
|
||||||
|
|
@ -1674,12 +1669,12 @@ cifComputeRadii(
|
||||||
|
|
||||||
for (op = layer->cl_ops; op != NULL; op = op->co_next)
|
for (op = layer->cl_ops; op != NULL; op = op->co_next)
|
||||||
{
|
{
|
||||||
/* BBOX, NET, TAGGED, and MASKHINTS operators should never be */
|
/* BBOX, NET, and MASKHINTS operators should never be used */
|
||||||
/* used hierarchically so ignore any grow/shrink operators that */
|
/* hierarchically so ignore any grow/shrink operators that */
|
||||||
/* come after them. */
|
/* come after them. */
|
||||||
|
|
||||||
if (op->co_opcode == CIFOP_BBOX || op->co_opcode == CIFOP_NET ||
|
if (op->co_opcode == CIFOP_BBOX || op->co_opcode == CIFOP_NET ||
|
||||||
op->co_opcode == CIFOP_TAGGED || op->co_opcode == CIFOP_MASKHINTS)
|
op->co_opcode == CIFOP_MASKHINTS)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* If CIF layers are used, switch to the max of current
|
/* If CIF layers are used, switch to the max of current
|
||||||
|
|
@ -1991,8 +1986,8 @@ CIFTechFinal(void)
|
||||||
/* Presence of op->co_opcode in CIFOP_OR indicates a copy */
|
/* Presence of op->co_opcode in CIFOP_OR indicates a copy */
|
||||||
/* of the SquaresData pointer from a following operator. */
|
/* of the SquaresData pointer from a following operator. */
|
||||||
/* CIFOP_BBOX and CIFOP_MAXRECT uses the co_client field */
|
/* CIFOP_BBOX and CIFOP_MAXRECT uses the co_client field */
|
||||||
/* as a flag field, while CIFOP_NET, CIFOP_MASKHINTS, and */
|
/* as a flag field, while CIFOP_NET and CIFOP_MASKHINTS */
|
||||||
/* CIFOP_TAGGED use it for a string. */
|
/* uses it for a string. */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (op->co_opcode)
|
switch (op->co_opcode)
|
||||||
|
|
@ -2004,7 +1999,6 @@ CIFTechFinal(void)
|
||||||
case CIFOP_MAXRECT:
|
case CIFOP_MAXRECT:
|
||||||
case CIFOP_MANHATTAN:
|
case CIFOP_MANHATTAN:
|
||||||
case CIFOP_NET:
|
case CIFOP_NET:
|
||||||
case CIFOP_TAGGED:
|
|
||||||
break;
|
break;
|
||||||
case CIFOP_BRIDGELIM:
|
case CIFOP_BRIDGELIM:
|
||||||
case CIFOP_BRIDGE:
|
case CIFOP_BRIDGE:
|
||||||
|
|
@ -2540,7 +2534,6 @@ CIFTechOutputScale(
|
||||||
case CIFOP_MAXRECT:
|
case CIFOP_MAXRECT:
|
||||||
case CIFOP_MANHATTAN:
|
case CIFOP_MANHATTAN:
|
||||||
case CIFOP_NET:
|
case CIFOP_NET:
|
||||||
case CIFOP_TAGGED:
|
|
||||||
case CIFOP_INTERACT:
|
case CIFOP_INTERACT:
|
||||||
break;
|
break;
|
||||||
case CIFOP_BRIDGELIM:
|
case CIFOP_BRIDGELIM:
|
||||||
|
|
@ -2656,8 +2649,8 @@ CIFTechOutputScale(
|
||||||
default:
|
default:
|
||||||
/* op->co_opcode in CIFOP_OR is a pointer copy, */
|
/* op->co_opcode in CIFOP_OR is a pointer copy, */
|
||||||
/* in CIFOP_BBOX and CIFOP_MAXRECT is a flag, */
|
/* in CIFOP_BBOX and CIFOP_MAXRECT is a flag, */
|
||||||
/* and in CIFOP_NET, CIFOP_MASKHINTS, and */
|
/* and in CIFOP_NET and CIFOP_MASKHINTS is a */
|
||||||
/* CIFOP_TAGGED is a string. */
|
/* string. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -779,8 +779,8 @@ CmdBox(
|
||||||
break;
|
break;
|
||||||
case BOX_EXISTS:
|
case BOX_EXISTS:
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_SetObjResult(magicinterp,
|
Tcl_SetResult(magicinterp, ToolGetBox(NULL, NULL) ? "1" : "0",
|
||||||
Tcl_NewBooleanObj(ToolGetBox(NULL, NULL) ? TRUE : FALSE));
|
NULL);
|
||||||
#else
|
#else
|
||||||
TxPrintf("%s\n", ToolGetBox(NULL, NULL) ? "True" : "False");
|
TxPrintf("%s\n", ToolGetBox(NULL, NULL) ? "True" : "False");
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -117,13 +117,12 @@ bool cmdDumpParseArgs(char *cmdName, MagWindow *w, TxCommand *cmd, CellUse *dumm
|
||||||
#define CALMA_READ 19
|
#define CALMA_READ 19
|
||||||
#define CALMA_READONLY 20
|
#define CALMA_READONLY 20
|
||||||
#define CALMA_RESCALE 21
|
#define CALMA_RESCALE 21
|
||||||
#define CALMA_SAVEPATHS 22
|
#define CALMA_WARNING 22
|
||||||
#define CALMA_WARNING 23
|
#define CALMA_WRITE 23
|
||||||
#define CALMA_WRITE 24
|
#define CALMA_POLYS 24
|
||||||
#define CALMA_POLYS 25
|
#define CALMA_PATHS 25
|
||||||
#define CALMA_PATHS 26
|
#define CALMA_UNDEFINED 26
|
||||||
#define CALMA_UNDEFINED 27
|
#define CALMA_UNIQUE 27
|
||||||
#define CALMA_UNIQUE 28
|
|
||||||
|
|
||||||
#define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */
|
#define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */
|
||||||
|
|
||||||
|
|
@ -176,7 +175,6 @@ CmdCalma(
|
||||||
" into edit cell",
|
" into edit cell",
|
||||||
"readonly [yes|no] set cell as read-only and generate output from GDS file",
|
"readonly [yes|no] set cell as read-only and generate output from GDS file",
|
||||||
"rescale [yes|no] allow or disallow internal grid subdivision",
|
"rescale [yes|no] allow or disallow internal grid subdivision",
|
||||||
"savepaths [yes|no] save path centerlines as cell properties",
|
|
||||||
"warning [option] set warning information level",
|
"warning [option] set warning information level",
|
||||||
"write file output Calma GDS-II format to \"file\"\n"
|
"write file output Calma GDS-II format to \"file\"\n"
|
||||||
" for the window's root cell",
|
" for the window's root cell",
|
||||||
|
|
@ -740,27 +738,6 @@ CmdCalma(
|
||||||
CalmaSubcellPolygons = (unsigned char)option;
|
CalmaSubcellPolygons = (unsigned char)option;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case CALMA_SAVEPATHS:
|
|
||||||
if (cmd->tx_argc == 2)
|
|
||||||
{
|
|
||||||
#ifdef MAGIC_WRAPPER
|
|
||||||
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaRecordPaths));
|
|
||||||
#else
|
|
||||||
TxPrintf("Paths in GDS cells read from input file are%s recorded"
|
|
||||||
" as cell properties.\n",
|
|
||||||
(CalmaRecordPaths) ? " " : " not");
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (cmd->tx_argc != 3)
|
|
||||||
goto wrongNumArgs;
|
|
||||||
|
|
||||||
option = Lookup(cmd->tx_argv[2], cmdCalmaYesNo);
|
|
||||||
if (option < 0)
|
|
||||||
goto wrongNumArgs;
|
|
||||||
CalmaRecordPaths = (option < 4) ? FALSE : TRUE;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case CALMA_NO_DUP:
|
case CALMA_NO_DUP:
|
||||||
if (cmd->tx_argc == 2)
|
if (cmd->tx_argc == 2)
|
||||||
{
|
{
|
||||||
|
|
@ -1323,7 +1300,7 @@ CmdCellname(
|
||||||
if (cellDef == (CellDef *) NULL)
|
if (cellDef == (CellDef *) NULL)
|
||||||
TxError("Unknown cell %s\n", cellname);
|
TxError("Unknown cell %s\n", cellname);
|
||||||
else
|
else
|
||||||
CmdDoProperty(cellDef, w, cmd, 3 + ((dolist) ? 1 : 0));
|
CmdDoProperty(cellDef, cmd, 3 + ((dolist) ? 1 : 0));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDX_DELETE:
|
case IDX_DELETE:
|
||||||
|
|
@ -5014,20 +4991,15 @@ cmdDumpParseArgs(
|
||||||
bbox = def->cd_bbox;
|
bbox = def->cd_bbox;
|
||||||
if (def->cd_flags & CDFIXEDBBOX)
|
if (def->cd_flags & CDFIXEDBBOX)
|
||||||
{
|
{
|
||||||
PropertyRecord *proprec;
|
char *propvalue;
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
proprec = DBPropGet(def, "FIXED_BBOX", &found);
|
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &found);
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||||
(proprec->prop_len == 4))
|
&bbox.r_xtop, &bbox.r_ytop) != 4)
|
||||||
{
|
bbox = def->cd_bbox;
|
||||||
bbox.r_xbot = proprec->prop_value.prop_integer[0];
|
|
||||||
bbox.r_ybot = proprec->prop_value.prop_integer[1];
|
|
||||||
bbox.r_xtop = proprec->prop_value.prop_integer[2];
|
|
||||||
bbox.r_ytop = proprec->prop_value.prop_integer[3];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -925,14 +925,13 @@ cmdExpandFunc(
|
||||||
#define DOALL 1
|
#define DOALL 1
|
||||||
#define DOCAPACITANCE 2
|
#define DOCAPACITANCE 2
|
||||||
#define DOCOUPLING 3
|
#define DOCOUPLING 3
|
||||||
#define DOEXTRESIST 4
|
#define DOLENGTH 4
|
||||||
#define DOLENGTH 5
|
#define DOLOCAL 5
|
||||||
#define DOLOCAL 6
|
#define DORESISTANCE 6
|
||||||
#define DORESISTANCE 7
|
#define DOLABELCHECK 7
|
||||||
#define DOLABELCHECK 8
|
#define DOALIASES 8
|
||||||
#define DOALIASES 9
|
#define DOUNIQUE 9
|
||||||
#define DOUNIQUE 10
|
#define DOEXTRESIST 10
|
||||||
#define DOEXTRESIST2 11
|
|
||||||
|
|
||||||
#define LENCLEAR 0
|
#define LENCLEAR 0
|
||||||
#define LENDRIVER 1
|
#define LENDRIVER 1
|
||||||
|
|
@ -975,14 +974,13 @@ CmdExtract(
|
||||||
"all all options",
|
"all all options",
|
||||||
"capacitance extract substrate capacitance",
|
"capacitance extract substrate capacitance",
|
||||||
"coupling extract coupling capacitance",
|
"coupling extract coupling capacitance",
|
||||||
"extresist extract resistance",
|
|
||||||
"length compute driver-receiver pathlengths",
|
"length compute driver-receiver pathlengths",
|
||||||
"local put all generated files in the current directory",
|
"local put all generated files in the current directory",
|
||||||
"lumped estimate lumped resistance",
|
"lumped estimate lumped resistance",
|
||||||
"labelcheck check for connections through sticky labels",
|
"labelcheck check for connections through sticky labels",
|
||||||
"aliases output all net name aliases",
|
"aliases output all net name aliases",
|
||||||
"unique ensure unique node names during extraction",
|
"unique ensure unique node names during extraction",
|
||||||
"resistance extract resistance (same as \"do extresist\")",
|
"resistance extract resistance",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
static const char * const cmdExtLength[] =
|
static const char * const cmdExtLength[] =
|
||||||
|
|
@ -1288,7 +1286,7 @@ CmdExtract(
|
||||||
TxPrintf("%s label check\n", OPTSET(EXT_DOLABELCHECK));
|
TxPrintf("%s label check\n", OPTSET(EXT_DOLABELCHECK));
|
||||||
TxPrintf("%s aliases\n", OPTSET(EXT_DOALIASES));
|
TxPrintf("%s aliases\n", OPTSET(EXT_DOALIASES));
|
||||||
TxPrintf("%s unique\n", OPTSET(EXT_DOUNIQUE));
|
TxPrintf("%s unique\n", OPTSET(EXT_DOUNIQUE));
|
||||||
TxPrintf("%s resistance (extresist)\n", OPTSET(EXT_DOEXTRESIST));
|
TxPrintf("%s resistance\n", OPTSET(EXT_DOEXTRESIST));
|
||||||
return;
|
return;
|
||||||
#undef OPTSET
|
#undef OPTSET
|
||||||
}
|
}
|
||||||
|
|
@ -1319,8 +1317,7 @@ CmdExtract(
|
||||||
case DOLABELCHECK: option = EXT_DOLABELCHECK; break;
|
case DOLABELCHECK: option = EXT_DOLABELCHECK; break;
|
||||||
case DOALIASES: option = EXT_DOALIASES; break;
|
case DOALIASES: option = EXT_DOALIASES; break;
|
||||||
case DOUNIQUE: option = EXT_DOUNIQUE; break;
|
case DOUNIQUE: option = EXT_DOUNIQUE; break;
|
||||||
case DOEXTRESIST:
|
case DOEXTRESIST: option = EXT_DOEXTRESIST; break;
|
||||||
case DOEXTRESIST2: option = EXT_DOEXTRESIST; break;
|
|
||||||
case DOLOCAL:
|
case DOLOCAL:
|
||||||
/* "extract do local" and "extract no local" are kept for
|
/* "extract do local" and "extract no local" are kept for
|
||||||
* backwards compatibility, but now effectively implement
|
* backwards compatibility, but now effectively implement
|
||||||
|
|
|
||||||
583
commands/CmdLQ.c
583
commands/CmdLQ.c
|
|
@ -45,8 +45,9 @@ static const char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magi
|
||||||
#include "utils/undo.h"
|
#include "utils/undo.h"
|
||||||
#include "select/select.h"
|
#include "select/select.h"
|
||||||
#include "netmenu/netmenu.h"
|
#include "netmenu/netmenu.h"
|
||||||
|
|
||||||
|
/* C99 compat */
|
||||||
#include "cif/cif.h"
|
#include "cif/cif.h"
|
||||||
#include "cif/CIFint.h"
|
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
|
|
||||||
|
|
@ -2295,8 +2296,6 @@ parsepositions:
|
||||||
editDef->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
|
editDef->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PROPERTY_TYPE_COMPAT 4 /* Last entry in cmdPropertyType */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -2320,449 +2319,47 @@ parsepositions:
|
||||||
void
|
void
|
||||||
CmdDoProperty(
|
CmdDoProperty(
|
||||||
CellDef *def,
|
CellDef *def,
|
||||||
MagWindow *w,
|
|
||||||
TxCommand *cmd,
|
TxCommand *cmd,
|
||||||
int argstart)
|
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 printPropertiesFunc();
|
||||||
int printPlanePropFunc();
|
char *value;
|
||||||
|
bool propfound;
|
||||||
/* These should match the property codes in database.h.in, except
|
int locargc = cmd->tx_argc - argstart + 1;
|
||||||
* for "compat" which must come at the end.
|
|
||||||
*/
|
|
||||||
static const char * const cmdPropertyType[] = {
|
|
||||||
"string", "integer", "dimension", "double", "plane", "compat", NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
/* If the first keyword is "list", then set dolist and increment
|
|
||||||
* the starting argument position.
|
|
||||||
*/
|
|
||||||
dolist = FALSE;
|
|
||||||
if (locargc > 1)
|
|
||||||
{
|
|
||||||
if (!strcmp(cmd->tx_argv[argstart], "list"))
|
|
||||||
{
|
|
||||||
dolist = TRUE;
|
|
||||||
locargc--;
|
|
||||||
argstart++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If a property type is given, parse it and then strip it from
|
|
||||||
* the arguments list.
|
|
||||||
*/
|
|
||||||
if (locargc > 1)
|
|
||||||
{
|
|
||||||
proptype = Lookup(cmd->tx_argv[argstart], cmdPropertyType);
|
|
||||||
if (proptype >= 0)
|
|
||||||
{
|
|
||||||
if (proptype != PROPERTY_TYPE_COMPAT)
|
|
||||||
{
|
|
||||||
locargc--;
|
|
||||||
argstart++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
proptype = PROPERTY_TYPE_STRING; /* default */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
proptype = PROPERTY_TYPE_STRING; /* default */
|
|
||||||
|
|
||||||
if (locargc == 1)
|
if (locargc == 1)
|
||||||
{
|
{
|
||||||
#ifdef MAGIC_WRAPPER
|
|
||||||
Tcl_Obj *tobj;
|
|
||||||
/* Create an empty list for the interpreter result; the
|
|
||||||
* printPropertiesFunc() function will append values to it.
|
|
||||||
*/
|
|
||||||
tobj = Tcl_NewListObj(0, NULL);
|
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
|
||||||
#endif
|
|
||||||
/* print all properties and their values */
|
/* print all properties and their values */
|
||||||
DBPropEnum(def, printPropertiesFunc, (ClientData)w);
|
DBPropEnum(def, printPropertiesFunc, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (locargc == 2)
|
else if (locargc == 2)
|
||||||
{
|
{
|
||||||
/* If the property type was "compat", then give the state of the
|
/* print the value of the indicated property */
|
||||||
* compatibility flag and return.
|
value = (char *)DBPropGet(def, cmd->tx_argv[argstart], &propfound);
|
||||||
*/
|
|
||||||
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);
|
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
|
||||||
proptype = proprec->prop_type;
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
switch (proptype)
|
Tcl_SetResult(magicinterp, value, NULL);
|
||||||
{
|
|
||||||
case PROPERTY_TYPE_STRING:
|
|
||||||
Tcl_SetResult(magicinterp, proprec->prop_value.prop_string, NULL);
|
|
||||||
break;
|
|
||||||
case PROPERTY_TYPE_INTEGER:
|
|
||||||
if (proprec->prop_len == 1)
|
|
||||||
Tcl_SetObjResult(magicinterp,
|
|
||||||
Tcl_NewIntObj(proprec->prop_value.prop_integer[0]));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tobj = Tcl_NewListObj(0, NULL);
|
|
||||||
for (i = 0; i < proprec->prop_len; i++)
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
|
||||||
Tcl_NewIntObj(
|
|
||||||
proprec->prop_value.prop_integer[i]));
|
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PROPERTY_TYPE_DIMENSION:
|
|
||||||
if (proprec->prop_len == 1)
|
|
||||||
Tcl_SetResult(magicinterp,
|
|
||||||
DBWPrintValue(proprec->prop_value.prop_integer[0],
|
|
||||||
w, TRUE), NULL);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tobj = Tcl_NewListObj(0, NULL);
|
|
||||||
for (i = 0; i < proprec->prop_len; i++)
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
|
||||||
Tcl_NewStringObj(DBWPrintValue(
|
|
||||||
proprec->prop_value.prop_integer[i], w,
|
|
||||||
((i % 2) == 0) ? TRUE : FALSE), -1));
|
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PROPERTY_TYPE_PLANE:
|
|
||||||
tobj = Tcl_NewListObj(0, NULL);
|
|
||||||
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
|
||||||
proprec->prop_value.prop_plane,
|
|
||||||
&TiPlaneRect, &CIFSolidBits, printPlanePropFunc,
|
|
||||||
(ClientData)tobj);
|
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
|
||||||
break;
|
|
||||||
case PROPERTY_TYPE_DOUBLE:
|
|
||||||
if (proprec->prop_len == 1)
|
|
||||||
Tcl_SetObjResult(magicinterp,
|
|
||||||
Tcl_NewWideIntObj((Tcl_WideInt)
|
|
||||||
proprec->prop_value.prop_double[0]));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tobj = Tcl_NewListObj(0, NULL);
|
|
||||||
for (i = 0; i < proprec->prop_len; i++)
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj,
|
|
||||||
Tcl_NewWideIntObj((Tcl_WideInt)
|
|
||||||
proprec->prop_value.prop_double[i]));
|
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
switch (proptype)
|
TxPrintf("%s", value);
|
||||||
{
|
|
||||||
case PROPERTY_TYPE_STRING:
|
|
||||||
TxPrintf("%s\n", proprec->prop_value.prop_string);
|
|
||||||
break;
|
|
||||||
case PROPERTY_TYPE_INTEGER:
|
|
||||||
for (i = 0; i < proprec->prop_len; i++)
|
|
||||||
TxPrintf("%d ", proprec->prop_value.prop_integer[i]);
|
|
||||||
TxPrintf("\n");
|
|
||||||
break;
|
|
||||||
case PROPERTY_TYPE_DIMENSION:
|
|
||||||
for (i = 0; i < proprec->prop_len; i++)
|
|
||||||
TxPrintf("%s ", DBWPrintValue(
|
|
||||||
proprec->prop_value.prop_integer[i], w,
|
|
||||||
((i % 2) == 0) ? TRUE : FALSE));
|
|
||||||
|
|
||||||
TxPrintf("\n");
|
|
||||||
break;
|
|
||||||
case PROPERTY_TYPE_PLANE:
|
|
||||||
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
|
||||||
proprec->prop_value.prop_plane,
|
|
||||||
&TiPlaneRect, &CIFSolidBits, printPlanePropFunc,
|
|
||||||
(ClientData)NULL);
|
|
||||||
TxPrintf("\n");
|
|
||||||
break;
|
|
||||||
case PROPERTY_TYPE_DOUBLE:
|
|
||||||
for (i = 0; i < proprec->prop_len; i++)
|
|
||||||
TxPrintf( "%"DLONG_PREFIX"d",
|
|
||||||
proprec->prop_value.prop_double[i]);
|
|
||||||
TxPrintf("\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
/* If the command was "cellname list property ...", then */
|
/* If the command was "cellname list property ...", then */
|
||||||
/* just return NULL if the property was not found. */
|
/* just return NULL if the property was not found. */
|
||||||
if (!dolist)
|
if (strcmp(cmd->tx_argv[1], "list"))
|
||||||
#endif
|
#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)
|
if (strlen(cmd->tx_argv[argstart + 1]) == 0)
|
||||||
DBPropPut(def, cmd->tx_argv[argstart], NULL);
|
DBPropPut(def, cmd->tx_argv[argstart], NULL);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (proptype == PROPERTY_TYPE_STRING)
|
value = StrDup((char **)NULL, cmd->tx_argv[argstart + 1]);
|
||||||
{
|
DBPropPut(def, cmd->tx_argv[argstart], value);
|
||||||
proplen = strlen(cmd->tx_argv[argstart + 1]);
|
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) -
|
|
||||||
7 + proplen);
|
|
||||||
proprec->prop_type = proptype;
|
|
||||||
proprec->prop_len = proplen;
|
|
||||||
strcpy(proprec->prop_value.prop_string, cmd->tx_argv[argstart + 1]);
|
|
||||||
}
|
|
||||||
else /* All non-string properties */
|
|
||||||
{
|
|
||||||
Plane *plane;
|
|
||||||
Rect r;
|
|
||||||
|
|
||||||
/* Two choices: If locargc == 3 then all values are in one
|
|
||||||
* argument. If locargc > 3, then parse each argument as a
|
|
||||||
* separate value.
|
|
||||||
*/
|
|
||||||
if (locargc > 3)
|
|
||||||
{
|
|
||||||
proplen = locargc - 2;
|
|
||||||
if (proptype == PROPERTY_TYPE_DOUBLE)
|
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
|
||||||
(proplen - 1)*sizeof(dlong));
|
|
||||||
else if (proptype == PROPERTY_TYPE_PLANE)
|
|
||||||
{
|
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
|
||||||
plane = DBNewPlane((ClientData)TT_SPACE);
|
|
||||||
proprec->prop_value.prop_plane = plane;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
|
||||||
(proplen - 2)*sizeof(int));
|
|
||||||
proprec->prop_type = proptype;
|
|
||||||
proprec->prop_len = proplen;
|
|
||||||
|
|
||||||
for (i = 1; i < locargc - 1; i++)
|
|
||||||
{
|
|
||||||
if (proptype == PROPERTY_TYPE_INTEGER)
|
|
||||||
{
|
|
||||||
if (sscanf(cmd->tx_argv[argstart + i], "%d",
|
|
||||||
&propvalue) == 1)
|
|
||||||
proprec->prop_value.prop_integer[i - 1] = propvalue;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TxError("Unable to parse value \"%s\" as an integer\n",
|
|
||||||
cmd->tx_argv[argstart + i]);
|
|
||||||
proprec->prop_value.prop_integer[i - 1] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (proptype == PROPERTY_TYPE_DOUBLE)
|
|
||||||
{
|
|
||||||
if (sscanf(cmd->tx_argv[argstart + i], "%"DLONG_PREFIX"d",
|
|
||||||
&dvalue) == 1)
|
|
||||||
proprec->prop_value.prop_double[i - 1] = dvalue;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TxError("Unable to parse value \"%s\" as an integer\n",
|
|
||||||
cmd->tx_argv[argstart + i]);
|
|
||||||
proprec->prop_value.prop_double[i - 1] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (proptype == PROPERTY_TYPE_PLANE)
|
|
||||||
{
|
|
||||||
propvalue = cmdParseCoord(w, cmd->tx_argv[argstart + i],
|
|
||||||
FALSE, ((i % 2) == 0) ? FALSE : TRUE);
|
|
||||||
switch ((i - 1) % 4)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
r.r_xbot = propvalue;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
r.r_ybot = propvalue;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
r.r_xtop = propvalue;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
r.r_ytop = propvalue;
|
|
||||||
DBPaintPlane(plane, &r, CIFPaintTable,
|
|
||||||
(PaintUndoInfo *)NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* PROPERTY_TYPE_DIMENSION */
|
|
||||||
{
|
|
||||||
propvalue = cmdParseCoord(w, cmd->tx_argv[argstart + i],
|
|
||||||
FALSE, ((i % 2) == 0) ? FALSE : TRUE);
|
|
||||||
proprec->prop_value.prop_integer[i - 1] = propvalue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Make two passes through the argument string, once to get
|
|
||||||
* the valid number of arguments, then again to parse the
|
|
||||||
* values, once the property record has been allocated
|
|
||||||
*/
|
|
||||||
if (proptype == PROPERTY_TYPE_PLANE)
|
|
||||||
{
|
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
|
||||||
plane = DBNewPlane((ClientData)TT_SPACE);
|
|
||||||
proprec->prop_value.prop_plane = plane;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value = cmd->tx_argv[argstart + 1];
|
|
||||||
for (proplen = 0; *value != '\0'; )
|
|
||||||
{
|
|
||||||
if (isspace(*value) && (*value != '\0')) value++;
|
|
||||||
if (!isspace(*value))
|
|
||||||
{
|
|
||||||
proplen++;
|
|
||||||
while (!isspace(*value) && (*value != '\0')) value++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (proplen > 0)
|
|
||||||
{
|
|
||||||
proprec = (PropertyRecord *)mallocMagic(
|
|
||||||
sizeof(PropertyRecord) +
|
|
||||||
(proplen - 2) * sizeof(int));
|
|
||||||
proprec->prop_type = proptype;
|
|
||||||
proprec->prop_len = proplen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Second pass */
|
|
||||||
value = cmd->tx_argv[argstart + 1];
|
|
||||||
for (proplen = 0; proplen < proprec->prop_len; proplen++)
|
|
||||||
{
|
|
||||||
if (isspace(*value) && (*value != '\0')) value++;
|
|
||||||
if (!isspace(*value))
|
|
||||||
{
|
|
||||||
char *spptr, spchar;
|
|
||||||
/* cmdParseCoord() can only handle one value at a
|
|
||||||
* time, so look ahead and null out the next space
|
|
||||||
* character if there is one.
|
|
||||||
*/
|
|
||||||
spptr = value + 1;
|
|
||||||
while (!isspace(*spptr) && (*spptr != '\0')) spptr++;
|
|
||||||
spchar = *spptr;
|
|
||||||
*spptr = '\0';
|
|
||||||
|
|
||||||
if (proptype == PROPERTY_TYPE_INTEGER)
|
|
||||||
{
|
|
||||||
if (sscanf(value, "%d", &propvalue) != 1)
|
|
||||||
{
|
|
||||||
TxError("Unable to parse integer "
|
|
||||||
"value from \"%s\"\n",
|
|
||||||
value);
|
|
||||||
propvalue = 0;
|
|
||||||
}
|
|
||||||
proprec->prop_value.prop_integer[proplen] = propvalue;
|
|
||||||
}
|
|
||||||
else if (proptype == PROPERTY_TYPE_DOUBLE)
|
|
||||||
{
|
|
||||||
if (sscanf(value, "%"DLONG_PREFIX"d", &dvalue) != 1)
|
|
||||||
{
|
|
||||||
TxError("Unable to parse integer "
|
|
||||||
"value from \"%s\"\n",
|
|
||||||
value);
|
|
||||||
propvalue = 0;
|
|
||||||
}
|
|
||||||
proprec->prop_value.prop_double[proplen] = dvalue;
|
|
||||||
}
|
|
||||||
else if (proptype == PROPERTY_TYPE_PLANE)
|
|
||||||
{
|
|
||||||
propvalue = cmdParseCoord(w, value, FALSE,
|
|
||||||
((proplen % 2) == 0) ? TRUE : FALSE);
|
|
||||||
switch (proplen % 4)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
r.r_xbot = propvalue;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
r.r_ybot = propvalue;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
r.r_xtop = propvalue;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
r.r_ytop = propvalue;
|
|
||||||
DBPaintPlane(plane, &r, CIFPaintTable,
|
|
||||||
(PaintUndoInfo *)NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* PROPERTY_TYPE_DIMENSION */
|
|
||||||
{
|
|
||||||
propvalue = cmdParseCoord(w, value, FALSE,
|
|
||||||
((proplen % 2) == 0) ? TRUE : FALSE);
|
|
||||||
proprec->prop_value.prop_integer[proplen] = propvalue;
|
|
||||||
}
|
|
||||||
*spptr = spchar;
|
|
||||||
while (!isspace(*value) && (*value != '\0')) value++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DBPropPut(def, cmd->tx_argv[argstart], proprec);
|
|
||||||
}
|
}
|
||||||
def->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
|
def->cd_flags |= (CDMODIFIED | CDGETNEWSTAMP);
|
||||||
}
|
}
|
||||||
|
|
@ -2783,14 +2380,10 @@ CmdDoProperty(
|
||||||
* defined in database/DBprop.c.
|
* defined in database/DBprop.c.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* property [string|integer|dimension] [name] [value]
|
* property [name] [value]
|
||||||
*
|
*
|
||||||
* If the first argument is present, it must be one of the known
|
* "name" is a unique string tag for the property, and "value" is its
|
||||||
* keywords, and determines the form in which "value" is interpreted and
|
* string value.
|
||||||
* stored. "name" is a unique string tag for the property. "value" is
|
|
||||||
* the value of the property, which is either a string, integer, or a
|
|
||||||
* list of integers. The difference between an "integer" and a "dimension"
|
|
||||||
* is that all values which are dimensions are scaled with internal units.
|
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* None.
|
* None.
|
||||||
|
|
@ -2817,62 +2410,9 @@ CmdProperty(
|
||||||
else
|
else
|
||||||
def = ((CellUse *) w->w_surfaceID)->cu_def;
|
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
|
* Callback function for printing a single property key:value pair
|
||||||
|
|
@ -2882,84 +2422,27 @@ printPlanePropFunc(
|
||||||
int
|
int
|
||||||
printPropertiesFunc(
|
printPropertiesFunc(
|
||||||
const char *name,
|
const char *name,
|
||||||
PropertyRecord *proprec,
|
ClientData value,
|
||||||
MagWindow *w)
|
ClientData cdata) /* not used */
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
Tcl_Obj *tobj, *lobj;
|
char *keyvalue;
|
||||||
|
|
||||||
tobj = Tcl_GetObjResult(magicinterp);
|
if (value == NULL)
|
||||||
lobj = Tcl_NewListObj(0, NULL);
|
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewStringObj(name, -1));
|
|
||||||
|
|
||||||
switch (proprec->prop_type)
|
|
||||||
{
|
{
|
||||||
case PROPERTY_TYPE_STRING:
|
keyvalue = (char *)mallocMagic(strlen(name) + 4);
|
||||||
Tcl_ListObjAppendElement(magicinterp, lobj,
|
sprintf(keyvalue, "%s {}", name);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
Tcl_ListObjAppendElement(magicinterp, tobj, lobj);
|
else
|
||||||
Tcl_SetObjResult(magicinterp, tobj);
|
{
|
||||||
|
keyvalue = (char *)mallocMagic(strlen(name) + strlen((const char *)value) + 2);
|
||||||
|
sprintf(keyvalue, "%s %s", name, (const char *)value);
|
||||||
|
}
|
||||||
|
Tcl_AppendElement(magicinterp, keyvalue);
|
||||||
|
freeMagic(keyvalue);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
switch (proprec->prop_type)
|
TxPrintf("%s = %s\n", name, (const char *)value);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0; /* keep the search alive */
|
return 0; /* keep the search alive */
|
||||||
|
|
|
||||||
|
|
@ -2900,29 +2900,6 @@ CmdSnap(
|
||||||
TxPrintf("Usage: snap [internal | lambda | user]\n");
|
TxPrintf("Usage: snap [internal | lambda | user]\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Backwards compatibility: Use of "snap" to set units display and
|
|
||||||
* parsing has been deprecated as of February 2026. However, as this
|
|
||||||
* is rather disruptive to existing scripts which use "snap" to change
|
|
||||||
* the parsing of units, then the following measure is being taken
|
|
||||||
* (for now, anyway): If DBWUnits is set to DBW_UNITS_DEFAULT, then
|
|
||||||
* "snap internal" will set DBWUnits as well as DBWSnapToGrid. If
|
|
||||||
* DBWUnits is changed first (e.g., "units internal"), then "snap" will
|
|
||||||
* affect only the snap grid. The older usage will be accompanied by a
|
|
||||||
* warning message. Note that backwards compatibility is being kept
|
|
||||||
* only in the case of "snap internal", which was commonly used in
|
|
||||||
* scripts to make sure that all units were interpreted as internal
|
|
||||||
* units.
|
|
||||||
*/
|
|
||||||
if ((DBWUnits == DBW_UNITS_DEFAULT) && (n == SNAP_INTERNAL))
|
|
||||||
{
|
|
||||||
DBWUnits = DBW_UNITS_INTERNAL;
|
|
||||||
TxError("Warning: snap setting is also changing units. This usage "
|
|
||||||
"is deprecated\nand may be removed in the future. Use "
|
|
||||||
"\"units\" to change units, and\nchange units before "
|
|
||||||
"setting snap to keep this message from appearing.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (n)
|
switch (n)
|
||||||
{
|
{
|
||||||
case SNAP_OFF: case SNAP_INTERNAL:
|
case SNAP_OFF: case SNAP_INTERNAL:
|
||||||
|
|
|
||||||
|
|
@ -156,9 +156,6 @@ cmdScaleCoord(
|
||||||
* "snap" setting. This behavior remains in effect until the "units"
|
* "snap" setting. This behavior remains in effect until the "units"
|
||||||
* command is used, in which case units follow the selected units
|
* command is used, in which case units follow the selected units
|
||||||
* value indepedendently of the snap setting.
|
* 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)
|
if (DBWUnits == DBW_UNITS_DEFAULT)
|
||||||
curunits = DBWSnapToGrid;
|
curunits = DBWSnapToGrid;
|
||||||
|
|
@ -166,22 +163,19 @@ cmdScaleCoord(
|
||||||
curunits = DBWUnits & DBW_UNITS_TYPE_MASK;
|
curunits = DBWUnits & DBW_UNITS_TYPE_MASK;
|
||||||
|
|
||||||
if ((*endptr == 'l')
|
if ((*endptr == 'l')
|
||||||
|| (((*endptr == '\0') || isspace(*endptr))
|
|| ((*endptr == '\0') && (curunits == DBW_UNITS_LAMBDA)))
|
||||||
&& (curunits == DBW_UNITS_LAMBDA)))
|
|
||||||
{
|
{
|
||||||
/* lambda or default units */
|
/* lambda or default units */
|
||||||
dval *= (double)DBLambda[1];
|
dval *= (double)DBLambda[1];
|
||||||
dval /= (double)DBLambda[0];
|
dval /= (double)DBLambda[0];
|
||||||
}
|
}
|
||||||
else if ((*endptr == 'i')
|
else if ((*endptr == 'i')
|
||||||
|| (((*endptr == '\0') || isspace(*endptr))
|
|| ((*endptr == '\0') && (curunits == DBW_UNITS_INTERNAL)))
|
||||||
&& (curunits == DBW_UNITS_INTERNAL)))
|
|
||||||
{
|
{
|
||||||
/* internal units */
|
/* internal units */
|
||||||
}
|
}
|
||||||
else if ((*endptr == 'g')
|
else if ((*endptr == 'g')
|
||||||
|| (((*endptr == '\0') || isspace(*endptr))
|
|| ((*endptr == '\0') && (curunits == DBW_UNITS_USER)))
|
||||||
&& (curunits == DBW_UNITS_USER)))
|
|
||||||
{
|
{
|
||||||
/* grid units */
|
/* grid units */
|
||||||
if (w == (MagWindow *)NULL)
|
if (w == (MagWindow *)NULL)
|
||||||
|
|
@ -209,12 +203,11 @@ cmdScaleCoord(
|
||||||
dval += (double)crec->dbw_gridRect.r_ybot;
|
dval += (double)crec->dbw_gridRect.r_ybot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (((*endptr == '\0') || isspace(*endptr))
|
else if (*endptr == '\0' && (curunits == DBW_UNITS_MICRONS))
|
||||||
&& (curunits == DBW_UNITS_MICRONS))
|
|
||||||
{
|
{
|
||||||
mscale = 1000;
|
mscale = 1000;
|
||||||
}
|
}
|
||||||
else if (*endptr != '\0')
|
else
|
||||||
{
|
{
|
||||||
/* natural units referred to the current cifoutput style */
|
/* natural units referred to the current cifoutput style */
|
||||||
if (*(endptr + 1) == 'm')
|
if (*(endptr + 1) == 'm')
|
||||||
|
|
@ -256,7 +249,7 @@ cmdScaleCoord(
|
||||||
mscale = -1;
|
mscale = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mscale != -1)
|
if ((mscale != -1) && !isspace(*endptr))
|
||||||
dval /= CIFGetOutputScale(mscale);
|
dval /= CIFGetOutputScale(mscale);
|
||||||
curval = round(dval);
|
curval = round(dval);
|
||||||
|
|
||||||
|
|
@ -304,13 +297,9 @@ cmdScaleCoord(
|
||||||
parseop = PARSEOP_DIV;
|
parseop = PARSEOP_DIV;
|
||||||
endptr++;
|
endptr++;
|
||||||
break;
|
break;
|
||||||
case ' ':
|
default:
|
||||||
case '\t':
|
|
||||||
endptr++;
|
endptr++;
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
/* Should this flag an error? */
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
if (parseop != PARSEOP_NONE) break;
|
if (parseop != PARSEOP_NONE) break;
|
||||||
}
|
}
|
||||||
|
|
@ -761,9 +750,7 @@ cmdSaveCell(
|
||||||
if (!tryRename || (fileName == NULL) || (strcmp(cellDef->cd_name, fileName) == 0))
|
if (!tryRename || (fileName == NULL) || (strcmp(cellDef->cd_name, fileName) == 0))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* Rename the cell, unless fileName is a .tcl file (scripted output) */
|
/* Rename the cell */
|
||||||
if ((strlen(fileName) <= 4) || strcmp(fileName + strlen(fileName) - 4, ".tcl"))
|
|
||||||
{
|
|
||||||
if (!DBCellRenameDef(cellDef, fileName))
|
if (!DBCellRenameDef(cellDef, fileName))
|
||||||
{
|
{
|
||||||
/* This should never happen */
|
/* This should never happen */
|
||||||
|
|
@ -771,7 +758,6 @@ cmdSaveCell(
|
||||||
fileName);
|
fileName);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (EditCellUse && (cellDef == EditCellUse->cu_def))
|
if (EditCellUse && (cellDef == EditCellUse->cu_def))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ extern int cmdParseCoord(MagWindow *w, char *arg, bool is_relative, bool is_x);
|
||||||
extern void cmdSaveCell(CellDef *cellDef, char *newName, bool noninteractive, bool tryRename);
|
extern void cmdSaveCell(CellDef *cellDef, char *newName, bool noninteractive, bool tryRename);
|
||||||
extern void CmdInit(void);
|
extern void CmdInit(void);
|
||||||
|
|
||||||
extern void CmdDoProperty(CellDef *def, 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);
|
extern void CmdPaintEraseButton(MagWindow *w, Point *refPoint, bool isPaint, bool isScreen);
|
||||||
|
|
||||||
#endif /* _MAGIC__COMMANDS__COMMANDS_H */
|
#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 "windows/windows.h"
|
||||||
#include "dbwind/dbwind.h"
|
#include "dbwind/dbwind.h"
|
||||||
#include "commands/commands.h"
|
#include "commands/commands.h"
|
||||||
|
|
||||||
|
/* C99 compat */
|
||||||
#include "graphics/graphics.h"
|
#include "graphics/graphics.h"
|
||||||
#include "cif/CIFint.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following variable points to the tables currently used for
|
* The following variable points to the tables currently used for
|
||||||
|
|
@ -356,43 +357,9 @@ DBCellCheckCopyAllPaint(scx, mask, xMask, targetUse, func)
|
||||||
struct propUseDefStruct {
|
struct propUseDefStruct {
|
||||||
CellDef *puds_source;
|
CellDef *puds_source;
|
||||||
CellDef *puds_dest;
|
CellDef *puds_dest;
|
||||||
Plane *puds_plane; /* Mask hint plane in dest */
|
|
||||||
Transform *puds_trans; /* Transform from source use to dest */
|
Transform *puds_trans; /* Transform from source use to dest */
|
||||||
Rect *puds_area; /* Clip area in source coordinates */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
*-----------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* dbCopyMaskHintPlaneFunc --
|
|
||||||
*
|
|
||||||
* Translate tiles from a child mask-hint property plane into the
|
|
||||||
* coordinate system of the parent, and paint the mask-hint area
|
|
||||||
* into the mask-hint property plane of the parent.
|
|
||||||
*
|
|
||||||
*-----------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
dbCopyMaskHintPlaneFunc(Tile *tile,
|
|
||||||
TileType dinfo,
|
|
||||||
struct propUseDefStruct *puds)
|
|
||||||
{
|
|
||||||
Transform *trans = puds->puds_trans;
|
|
||||||
Rect *clip = puds->puds_area;
|
|
||||||
Rect r, rnew;
|
|
||||||
Plane *plane = puds->puds_plane;
|
|
||||||
|
|
||||||
TiToRect(tile, &r);
|
|
||||||
GeoClip(&r, clip);
|
|
||||||
if (!GEO_RECTNULL(&r))
|
|
||||||
{
|
|
||||||
GeoTransRect(trans, &r, &rnew);
|
|
||||||
DBPaintPlane(plane, &rnew, CIFPaintTable, (PaintUndoInfo *)NULL);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-----------------------------------------------------------------------------
|
*-----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -413,52 +380,63 @@ dbCopyMaskHintPlaneFunc(Tile *tile,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
dbCopyMaskHintsFunc(key, proprec, puds)
|
dbCopyMaskHintsFunc(key, value, puds)
|
||||||
char *key;
|
char *key;
|
||||||
PropertyRecord *proprec;
|
ClientData value;
|
||||||
struct propUseDefStruct *puds;
|
struct propUseDefStruct *puds;
|
||||||
{
|
{
|
||||||
CellDef *dest = puds->puds_dest;
|
CellDef *dest = puds->puds_dest;
|
||||||
Transform *trans = puds->puds_trans;
|
Transform *trans = puds->puds_trans;
|
||||||
Rect *clip = puds->puds_area;
|
char *propstr = (char *)value;
|
||||||
PropertyRecord *parentproprec, *newproprec;
|
|
||||||
char *parentprop, *newvalue, *vptr;
|
char *parentprop, *newvalue, *vptr;
|
||||||
Rect r, rnew;
|
Rect r, rnew;
|
||||||
bool propfound;
|
bool propfound;
|
||||||
int i, j;
|
|
||||||
|
|
||||||
if (!strncmp(key, "MASKHINTS_", 10))
|
if (!strncmp(key, "MASKHINTS_", 10))
|
||||||
{
|
{
|
||||||
char *vptr, *lastval;
|
char *vptr, *lastval;
|
||||||
int lastlen;
|
int lastlen;
|
||||||
Plane *plane;
|
|
||||||
|
|
||||||
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
|
vptr = propstr;
|
||||||
* create it if it does not already exist.
|
while (*vptr != '\0')
|
||||||
*/
|
|
||||||
parentproprec = (PropertyRecord *)DBPropGet(dest, key, &propfound);
|
|
||||||
|
|
||||||
if (propfound)
|
|
||||||
plane = parentproprec->prop_value.prop_plane;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
newproprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
if (sscanf(vptr, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||||
newproprec->prop_type = PROPERTY_TYPE_PLANE;
|
&r.r_xtop, &r.r_ytop) == 4)
|
||||||
newproprec->prop_len = 0;
|
{
|
||||||
plane = DBNewPlane((ClientData)TT_SPACE);
|
GeoTransRect(trans, &r, &rnew);
|
||||||
newproprec->prop_value.prop_plane = plane;
|
|
||||||
DBPropPut(dest, key, newproprec);
|
|
||||||
}
|
|
||||||
puds->puds_plane = plane;
|
|
||||||
|
|
||||||
/* Copy the properties from child to parent */
|
lastval = newvalue;
|
||||||
DBSrPaintArea(PlaneGetHint(proprec->prop_value.prop_plane),
|
lastlen = (lastval) ? strlen(lastval) : 0;
|
||||||
proprec->prop_value.prop_plane,
|
newvalue = mallocMagic(40 + lastlen);
|
||||||
clip, &CIFSolidBits, dbCopyMaskHintPlaneFunc,
|
|
||||||
(ClientData)puds);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -490,7 +468,6 @@ DBCellCopyMaskHints(child, parent, transform)
|
||||||
puds.puds_source = child->cu_def;
|
puds.puds_source = child->cu_def;
|
||||||
puds.puds_dest = parent;
|
puds.puds_dest = parent;
|
||||||
puds.puds_trans = transform;
|
puds.puds_trans = transform;
|
||||||
puds.puds_area = (Rect *)&TiPlaneRect;
|
|
||||||
DBPropEnum(child->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
|
DBPropEnum(child->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -524,7 +501,6 @@ dbFlatCopyMaskHintsFunc(scx, def)
|
||||||
puds.puds_source = scx->scx_use->cu_def;
|
puds.puds_source = scx->scx_use->cu_def;
|
||||||
puds.puds_dest = def;
|
puds.puds_dest = def;
|
||||||
puds.puds_trans = &scx->scx_trans;
|
puds.puds_trans = &scx->scx_trans;
|
||||||
puds.puds_area = &scx->scx_area;
|
|
||||||
|
|
||||||
DBPropEnum(use->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
|
DBPropEnum(use->cu_def, dbCopyMaskHintsFunc, (ClientData)&puds);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -152,9 +152,10 @@ DBCellRename(cellname, newname, doforce)
|
||||||
|
|
||||||
if (doforce && ((celldef->cd_flags & CDVENDORGDS) == CDVENDORGDS))
|
if (doforce && ((celldef->cd_flags & CDVENDORGDS) == CDVENDORGDS))
|
||||||
{
|
{
|
||||||
|
char *chkgdsfile;
|
||||||
bool isReadOnly;
|
bool isReadOnly;
|
||||||
|
|
||||||
DBPropGet(celldef, "GDS_FILE", &isReadOnly);
|
chkgdsfile = (char *)DBPropGet(celldef, "GDS_FILE", &isReadOnly);
|
||||||
/* Note that clearing GDS_FILE will also clear CDVENDORGDS flag */
|
/* Note that clearing GDS_FILE will also clear CDVENDORGDS flag */
|
||||||
if (isReadOnly) DBPropPut(celldef, "GDS_FILE", NULL);
|
if (isReadOnly) DBPropPut(celldef, "GDS_FILE", NULL);
|
||||||
|
|
||||||
|
|
@ -1619,7 +1620,6 @@ dbAbutmentUseFunc(selUse, use, transform, data)
|
||||||
{
|
{
|
||||||
Rect bbox, refbox;
|
Rect bbox, refbox;
|
||||||
Transform *trans;
|
Transform *trans;
|
||||||
PropertyRecord *proprec;
|
|
||||||
char *propvalue;
|
char *propvalue;
|
||||||
char *refllx, *reflly, *refurx, *refury;
|
char *refllx, *reflly, *refurx, *refury;
|
||||||
bool found;
|
bool found;
|
||||||
|
|
@ -1643,26 +1643,15 @@ dbAbutmentUseFunc(selUse, use, transform, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
trans = &use->cu_transform;
|
trans = &use->cu_transform;
|
||||||
proprec = DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
propvalue = (char *)DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
||||||
if (!found)
|
if (!found)
|
||||||
bbox = use->cu_def->cd_bbox;
|
bbox = use->cu_def->cd_bbox;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||||
(proprec->prop_len == 4))
|
&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];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TxError("Unable to parse the cell's FIXED_BBOX property; using "
|
|
||||||
"the instance bounding box instead.\n");
|
|
||||||
bbox = use->cu_def->cd_bbox;
|
bbox = use->cu_def->cd_bbox;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
GeoTransRect(trans, &bbox, &refbox);
|
GeoTransRect(trans, &bbox, &refbox);
|
||||||
|
|
||||||
/* NOTE: Ideally, the MagWindow pointer should get passed to this routine */
|
/* NOTE: Ideally, the MagWindow pointer should get passed to this routine */
|
||||||
|
|
|
||||||
|
|
@ -1713,7 +1713,7 @@ dbTileMoveFunc(tile, dinfo, mvvals)
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
type = (dinfo & TT_SIDE) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||||
DBNMPaintPlane(mvvals->ptarget, exact, &targetRect,
|
DBNMPaintPlane(mvvals->ptarget, exact, &targetRect,
|
||||||
(mvvals->pnum < 0) ? CIFPaintTable : DBStdPaintTbl(type, mvvals->pnum),
|
DBStdPaintTbl(type, mvvals->pnum),
|
||||||
(PaintUndoInfo *)NULL);
|
(PaintUndoInfo *)NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1806,48 +1806,84 @@ typedef struct _cellpropstruct {
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int dbScaleProp(name, proprec, cps)
|
int dbScaleProp(name, value, cps)
|
||||||
char *name;
|
char *name;
|
||||||
PropertyRecord *proprec;
|
char *value;
|
||||||
CellPropStruct *cps;
|
CellPropStruct *cps;
|
||||||
{
|
{
|
||||||
int i, scalen, scaled;
|
int scalen, scaled;
|
||||||
Point p;
|
char *newvalue, *vptr;
|
||||||
|
Rect r;
|
||||||
|
|
||||||
/* Only "dimension" and "plane" type properties get scaled */
|
if ((strlen(name) > 5) && !strncmp(name + strlen(name) - 5, "_BBOX", 5))
|
||||||
|
{
|
||||||
if (proprec->prop_type == PROPERTY_TYPE_PLANE)
|
if (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||||
|
&r.r_xtop, &r.r_ytop) == 4)
|
||||||
{
|
{
|
||||||
Plane *newplane;
|
|
||||||
newplane = DBNewPlane((ClientData)TT_SPACE);
|
|
||||||
DBClearPaintPlane(newplane);
|
|
||||||
/* Plane index is unused; arbitrarily substitute -1 */
|
|
||||||
dbScalePlane(proprec->prop_value.prop_plane, newplane, -1,
|
|
||||||
scalen, scaled, TRUE);
|
|
||||||
DBFreePaintPlane(proprec->prop_value.prop_plane);
|
|
||||||
TiFreePlane(proprec->prop_value.prop_plane);
|
|
||||||
proprec->prop_value.prop_plane = newplane;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
|
|
||||||
|
|
||||||
/* Scale numerator held in point X value, */
|
/* Scale numerator held in point X value, */
|
||||||
/* scale denominator held in point Y value */
|
/* scale denominator held in point Y value */
|
||||||
|
|
||||||
scalen = cps->cps_point.p_x;
|
scalen = cps->cps_point.p_x;
|
||||||
scaled = cps->cps_point.p_y;
|
scaled = cps->cps_point.p_y;
|
||||||
|
|
||||||
for (i = 0; i < proprec->prop_len; i += 2)
|
DBScalePoint(&r.r_ll, scalen, scaled);
|
||||||
{
|
DBScalePoint(&r.r_ur, scalen, scaled);
|
||||||
if ((i + 1) >= proprec->prop_len) break;
|
|
||||||
|
|
||||||
p.p_x = proprec->prop_value.prop_integer[i];
|
newvalue = (char *)mallocMagic(40);
|
||||||
p.p_y = proprec->prop_value.prop_integer[i + 1];
|
sprintf(newvalue, "%d %d %d %d", r.r_xbot, r.r_ybot,
|
||||||
DBScalePoint(&p, scalen, scaled);
|
r.r_xtop, r.r_ytop);
|
||||||
proprec->prop_value.prop_integer[i] = p.p_x;
|
DBPropPut(cps->cps_def, name, newvalue);
|
||||||
proprec->prop_value.prop_integer[i + 1] = p.p_y;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (!strncmp(name, "MASKHINTS_", 10))
|
||||||
|
{
|
||||||
|
char *vptr, *lastval;
|
||||||
|
int lastlen;
|
||||||
|
|
||||||
|
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 */
|
return 0; /* Keep enumerating through properties */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1863,47 +1899,33 @@ int dbScaleProp(name, proprec, cps)
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int dbMoveProp(name, proprec, cps)
|
int dbMoveProp(name, value, cps)
|
||||||
char *name;
|
char *name;
|
||||||
PropertyRecord *proprec;
|
char *value;
|
||||||
CellPropStruct *cps;
|
CellPropStruct *cps;
|
||||||
{
|
{
|
||||||
int i, origx, origy;
|
int origx, origy;
|
||||||
char *newvalue;
|
char *newvalue;
|
||||||
Point p;
|
Rect r;
|
||||||
|
|
||||||
/* Only "dimension" and "plane" type properties get scaled */
|
if (((strlen(name) > 5) && !strncmp(name + strlen(name) - 5, "_BBOX", 5))
|
||||||
|
|| !strncmp(name, "MASKHINTS_", 10))
|
||||||
if (proprec->prop_type == PROPERTY_TYPE_PLANE)
|
{
|
||||||
|
if (sscanf(value, "%d %d %d %d", &r.r_xbot, &r.r_ybot,
|
||||||
|
&r.r_xtop, &r.r_ytop) == 4)
|
||||||
{
|
{
|
||||||
Plane *newplane;
|
|
||||||
|
|
||||||
newplane = DBNewPlane((ClientData) TT_SPACE);
|
|
||||||
DBClearPaintPlane(newplane);
|
|
||||||
/* Use plane index -1 to indicate use of CIFPaintTable */
|
|
||||||
dbMovePlane(proprec->prop_value.prop_plane, newplane, -1, origx, origy);
|
|
||||||
DBFreePaintPlane(proprec->prop_value.prop_plane);
|
|
||||||
TiFreePlane(proprec->prop_value.prop_plane);
|
|
||||||
proprec->prop_value.prop_plane = newplane;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proprec->prop_type != PROPERTY_TYPE_DIMENSION) return 0;
|
|
||||||
|
|
||||||
origx = cps->cps_point.p_x;
|
origx = cps->cps_point.p_x;
|
||||||
origy = cps->cps_point.p_y;
|
origy = cps->cps_point.p_y;
|
||||||
|
|
||||||
for (i = 0; i < proprec->prop_len; i += 2)
|
DBMovePoint(&r.r_ll, origx, origy);
|
||||||
{
|
DBMovePoint(&r.r_ur, origx, origy);
|
||||||
if ((i + 1) >= proprec->prop_len) break;
|
|
||||||
|
|
||||||
p.p_x = proprec->prop_value.prop_integer[i];
|
newvalue = (char *)mallocMagic(40);
|
||||||
p.p_y = proprec->prop_value.prop_integer[i + 1];
|
sprintf(newvalue, "%d %d %d %d", r.r_xbot, r.r_ybot,
|
||||||
DBMovePoint(&p, origx, origy);
|
r.r_xtop, r.r_ytop);
|
||||||
proprec->prop_value.prop_integer[i] = p.p_x;
|
DBPropPut(cps->cps_def, name, newvalue);
|
||||||
proprec->prop_value.prop_integer[i + 1] = p.p_y;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0; /* Keep enumerating through properties */
|
return 0; /* Keep enumerating through properties */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
933
database/DBio.c
933
database/DBio.c
File diff suppressed because it is too large
Load Diff
|
|
@ -32,16 +32,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "database/database.h"
|
#include "database/database.h"
|
||||||
#include "utils/malloc.h"
|
#include "utils/malloc.h"
|
||||||
|
|
||||||
/* Global variable */
|
|
||||||
|
|
||||||
bool DBPropCompat = TRUE; /* If TRUE, then always save properties to
|
|
||||||
* .mag files as type "string" for backwards
|
|
||||||
* compatibility. If FALSE, then properties
|
|
||||||
* are saved to the .mag file along with their
|
|
||||||
* type. Regardless of the setting, properties
|
|
||||||
* which are reserved keywords are converted
|
|
||||||
* to the best internal representation on input.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -59,14 +49,14 @@ void
|
||||||
DBPropPut(cellDef, name, value)
|
DBPropPut(cellDef, name, value)
|
||||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||||
char *name; /* The name of the property desired. */
|
char *name; /* The name of the property desired. */
|
||||||
PropertyRecord *value; /* MUST point to a malloc'ed structure, or NULL.
|
ClientData value; /* MUST point to a malloc'ed structure, or NULL.
|
||||||
* This will be freed when the CellDef is freed.
|
* This will be freed when the CellDef is freed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
{
|
{
|
||||||
HashTable *htab;
|
HashTable *htab;
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
PropertyRecord *oldvalue;
|
char *oldvalue;
|
||||||
|
|
||||||
/* Honor the NOEDIT flag. Note that the caller always assumes that */
|
/* Honor the NOEDIT flag. Note that the caller always assumes that */
|
||||||
/* the value would be saved in the hash table, so if it is not */
|
/* the value would be saved in the hash table, so if it is not */
|
||||||
|
|
@ -105,23 +95,12 @@ DBPropPut(cellDef, name, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
entry = HashFind(htab, name);
|
entry = HashFind(htab, name);
|
||||||
oldvalue = (PropertyRecord *)HashGetValue(entry);
|
oldvalue = (char *)HashGetValue(entry);
|
||||||
/* All properties are allocated as a single block and can just be freed,
|
if (oldvalue != NULL) freeMagic(oldvalue);
|
||||||
* except for plane properties, which require freeing the plane.
|
if (value == (ClientData)NULL)
|
||||||
*/
|
|
||||||
if (oldvalue != NULL)
|
|
||||||
{
|
|
||||||
if (oldvalue->prop_type == PROPERTY_TYPE_PLANE)
|
|
||||||
{
|
|
||||||
DBFreePaintPlane(oldvalue->prop_value.prop_plane);
|
|
||||||
TiFreePlane(oldvalue->prop_value.prop_plane);
|
|
||||||
}
|
|
||||||
freeMagic((char *)oldvalue);
|
|
||||||
}
|
|
||||||
if (value == (PropertyRecord *)NULL)
|
|
||||||
HashRemove(htab, name);
|
HashRemove(htab, name);
|
||||||
else
|
else
|
||||||
HashSetValue(entry, PTR2CD(value));
|
HashSetValue(entry, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
|
|
@ -131,13 +110,13 @@ DBPropPut(cellDef, name, value)
|
||||||
* Get a property from a celldef.
|
* Get a property from a celldef.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* NULL if the property didn't exist, or if the property record was NULL.
|
* NULL if the property didn't exist, or if the property value was NULL.
|
||||||
* Otherwise, returns a pointer to the property record.
|
* Otherwise, ClientData that represents the property.
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PropertyRecord *
|
ClientData
|
||||||
DBPropGet(cellDef, name, found)
|
DBPropGet(cellDef, name, found)
|
||||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
CellDef *cellDef; /* Pointer to definition of cell. */
|
||||||
char *name; /* The name of the property desired. */
|
char *name; /* The name of the property desired. */
|
||||||
|
|
@ -145,12 +124,12 @@ DBPropGet(cellDef, name, found)
|
||||||
* exists.
|
* exists.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
PropertyRecord *result;
|
ClientData result;
|
||||||
bool haveit;
|
bool haveit;
|
||||||
HashTable *htab;
|
HashTable *htab;
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
|
|
||||||
result = (PropertyRecord *)NULL;
|
result = (ClientData) NULL;
|
||||||
haveit = FALSE;
|
haveit = FALSE;
|
||||||
htab = (HashTable *) cellDef->cd_props;
|
htab = (HashTable *) cellDef->cd_props;
|
||||||
if (htab == (HashTable *) NULL) goto done;
|
if (htab == (HashTable *) NULL) goto done;
|
||||||
|
|
@ -159,7 +138,7 @@ DBPropGet(cellDef, name, found)
|
||||||
if (entry != NULL)
|
if (entry != NULL)
|
||||||
{
|
{
|
||||||
haveit = TRUE;
|
haveit = TRUE;
|
||||||
result = (PropertyRecord *)HashGetValue(entry);
|
result = (ClientData) HashGetValue(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
@ -167,109 +146,6 @@ done:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* DBPropGetString --
|
|
||||||
*
|
|
||||||
* Get a string property from a celldef.
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* NULL if the property didn't exist, or if the property record was NULL.
|
|
||||||
* Otherwise, returns a pointer to the property's string record.
|
|
||||||
*
|
|
||||||
* Notes:
|
|
||||||
* This is basically the original DBPropGet(), when properties were only
|
|
||||||
* allowed to be strings.
|
|
||||||
*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
char *
|
|
||||||
DBPropGetString(cellDef, name, found)
|
|
||||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
|
||||||
char *name; /* The name of the property desired. */
|
|
||||||
bool *found; /* If not NULL, filled in with TRUE iff the property
|
|
||||||
* exists.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
char *result = NULL;
|
|
||||||
PropertyRecord *proprec;
|
|
||||||
bool haveit;
|
|
||||||
HashTable *htab;
|
|
||||||
HashEntry *entry;
|
|
||||||
|
|
||||||
haveit = FALSE;
|
|
||||||
htab = (HashTable *) cellDef->cd_props;
|
|
||||||
if (htab == (HashTable *) NULL) goto pdone;
|
|
||||||
|
|
||||||
entry = HashLookOnly(htab, name);
|
|
||||||
if (entry != NULL)
|
|
||||||
{
|
|
||||||
proprec = (PropertyRecord *)HashGetValue(entry);
|
|
||||||
if (proprec->prop_type == PROPERTY_TYPE_STRING)
|
|
||||||
{
|
|
||||||
haveit = TRUE;
|
|
||||||
result = proprec->prop_value.prop_string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pdone:
|
|
||||||
if (found != (bool *) NULL) *found = haveit;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* DBPropGetDouble --
|
|
||||||
*
|
|
||||||
* Get a single double-long integer property from a celldef.
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* NULL if the property didn't exist, or if the property record was NULL.
|
|
||||||
* Otherwise, returns a pointer to the property's value record.
|
|
||||||
*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
dlong
|
|
||||||
DBPropGetDouble(cellDef, name, found)
|
|
||||||
CellDef *cellDef; /* Pointer to definition of cell. */
|
|
||||||
char *name; /* The name of the property desired. */
|
|
||||||
bool *found; /* If not NULL, filled in with TRUE iff the property
|
|
||||||
* exists.
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
dlong result = 0;
|
|
||||||
PropertyRecord *proprec;
|
|
||||||
bool haveit;
|
|
||||||
HashTable *htab;
|
|
||||||
HashEntry *entry;
|
|
||||||
|
|
||||||
haveit = FALSE;
|
|
||||||
htab = (HashTable *) cellDef->cd_props;
|
|
||||||
if (htab == (HashTable *) NULL) goto ddone;
|
|
||||||
|
|
||||||
entry = HashLookOnly(htab, name);
|
|
||||||
if (entry != NULL)
|
|
||||||
{
|
|
||||||
proprec = (PropertyRecord *)HashGetValue(entry);
|
|
||||||
if (proprec->prop_type == PROPERTY_TYPE_DOUBLE)
|
|
||||||
{
|
|
||||||
haveit = TRUE;
|
|
||||||
result = proprec->prop_value.prop_double[0];
|
|
||||||
}
|
|
||||||
else if (proprec->prop_type == PROPERTY_TYPE_STRING)
|
|
||||||
{
|
|
||||||
haveit = TRUE;
|
|
||||||
sscanf(proprec->prop_value.prop_string, "%"DLONG_PREFIX"d", &result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ddone:
|
|
||||||
if (found != (bool *) NULL) *found = haveit;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* DBPropEnum --
|
* DBPropEnum --
|
||||||
|
|
@ -292,7 +168,7 @@ DBPropEnum(cellDef, func, cdata)
|
||||||
*
|
*
|
||||||
* int foo(name, value, cdata)
|
* int foo(name, value, cdata)
|
||||||
* char *name;
|
* char *name;
|
||||||
* PropertyRecord *value;
|
* ClientData value;
|
||||||
* ClientData cdata;
|
* ClientData cdata;
|
||||||
* {
|
* {
|
||||||
* -- return 0 to continue,
|
* -- return 0 to continue,
|
||||||
|
|
@ -313,7 +189,7 @@ DBPropEnum(cellDef, func, cdata)
|
||||||
HashStartSearch(&hs);
|
HashStartSearch(&hs);
|
||||||
while ((entry = HashNext(htab, &hs)) != NULL)
|
while ((entry = HashNext(htab, &hs)) != NULL)
|
||||||
{
|
{
|
||||||
res = (*func)(entry->h_key.h_name, (PropertyRecord *)entry->h_pointer, cdata);
|
res = (*func)(entry->h_key.h_name, (ClientData) entry->h_pointer, cdata);
|
||||||
if (res != 0) return res;
|
if (res != 0) return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -704,25 +704,6 @@ struct conSrArg2
|
||||||
|
|
||||||
#define CSA2_LIST_SIZE 65536 /* Number of entries per list */
|
#define CSA2_LIST_SIZE 65536 /* Number of entries per list */
|
||||||
|
|
||||||
/* ------------------------ Properties ------------------------------ */
|
|
||||||
|
|
||||||
/* Note that the property record is a single allocated block large enough
|
|
||||||
* to hold the string or integer list, and can be freed as a single block.
|
|
||||||
* The array bounds, like those of lab_text for labels, are placeholders.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
int prop_type; /* See codes below; e.g., PROPERTY_TYPE_STRING */
|
|
||||||
int prop_len; /* String length or number of values */
|
|
||||||
union {
|
|
||||||
char prop_string[8]; /* For PROPERTY_TYPE_STRING */
|
|
||||||
int prop_integer[2]; /* For PROPERTY_TYPE_INTEGER or _DIMENSION */
|
|
||||||
dlong prop_double[1]; /* For PROPERTY_TYPE_DOUBLE */
|
|
||||||
Plane *prop_plane; /* For PROPERTY_TYPE_PLANE */
|
|
||||||
} prop_value;
|
|
||||||
} PropertyRecord;
|
|
||||||
|
|
||||||
/* -------------- Undo information passed to DBPaintPlane ------------- */
|
/* -------------- Undo information passed to DBPaintPlane ------------- */
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
@ -755,14 +736,6 @@ typedef struct
|
||||||
#define PAINT_MARK 1 /* Mark tiles that are painted */
|
#define PAINT_MARK 1 /* Mark tiles that are painted */
|
||||||
#define PAINT_XOR 2 /* Use with XOR function to prevent double-painting */
|
#define PAINT_XOR 2 /* Use with XOR function to prevent double-painting */
|
||||||
|
|
||||||
/* ---------------------- Codes for properties -------------------------*/
|
|
||||||
|
|
||||||
#define PROPERTY_TYPE_STRING 0 /* ASCII string property */
|
|
||||||
#define PROPERTY_TYPE_INTEGER 1 /* Fixed integer property */
|
|
||||||
#define PROPERTY_TYPE_DIMENSION 2 /* Integer property that scales with units */
|
|
||||||
#define PROPERTY_TYPE_DOUBLE 3 /* Double-long integer (for file positions) */
|
|
||||||
#define PROPERTY_TYPE_PLANE 4 /* A tile plane structure */
|
|
||||||
|
|
||||||
/* -------------------- Exported procedure headers -------------------- */
|
/* -------------------- Exported procedure headers -------------------- */
|
||||||
|
|
||||||
/* Painting/erasing */
|
/* Painting/erasing */
|
||||||
|
|
@ -948,9 +921,7 @@ extern void DBFreePaintPlane();
|
||||||
|
|
||||||
/* Cell properties */
|
/* Cell properties */
|
||||||
extern void DBPropPut();
|
extern void DBPropPut();
|
||||||
extern PropertyRecord *DBPropGet();
|
extern ClientData DBPropGet();
|
||||||
extern char *DBPropGetString();
|
|
||||||
extern dlong DBPropGetDouble();
|
|
||||||
extern int DBPropEnum();
|
extern int DBPropEnum();
|
||||||
extern void DBPropClearAll();
|
extern void DBPropClearAll();
|
||||||
|
|
||||||
|
|
@ -1048,7 +1019,6 @@ extern int DBLambda[2];
|
||||||
/* -------------------- Exported magic file suffix -------------------- */
|
/* -------------------- Exported magic file suffix -------------------- */
|
||||||
|
|
||||||
extern char *DBSuffix; /* Suffix appended to all Magic cell names */
|
extern char *DBSuffix; /* Suffix appended to all Magic cell names */
|
||||||
extern bool DBPropCompat; /* Backwards-compatible properties */
|
|
||||||
|
|
||||||
/* -------------------- User Interface Stuff -------------------------- */
|
/* -------------------- User Interface Stuff -------------------------- */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -182,13 +182,6 @@ Read GDSII input or generate GDSII output.
|
||||||
than to subsplit the internal grid to such a fine value.
|
than to subsplit the internal grid to such a fine value.
|
||||||
The "<B>cif limit</B>" function may also be used to limit
|
The "<B>cif limit</B>" function may also be used to limit
|
||||||
grid subdivision to a minimum value.
|
grid subdivision to a minimum value.
|
||||||
<DT> <B>savepaths</B> [<B>yes</B>|<B>no</B>]
|
|
||||||
<DD> When reading paths from a GDS file, record the centerline of
|
|
||||||
the path as a property in the cell. The default behavior is
|
|
||||||
<B>no</B>. If no argument is given, then return the status
|
|
||||||
of the <B>savepaths</B> option. The first path property is
|
|
||||||
named "<TT>path</TT>", followed by "<TT>path_0</TT>" and
|
|
||||||
increasing the suffix index for each individual path read.
|
|
||||||
<DT> <B>unique</B> [<B>yes</B>|<B>no</B>]
|
<DT> <B>unique</B> [<B>yes</B>|<B>no</B>]
|
||||||
<DD> When reading a GDS file, this option forces magic to rename
|
<DD> When reading a GDS file, this option forces magic to rename
|
||||||
cell definitions in the database when a cell of the same name
|
cell definitions in the database when a cell of the same name
|
||||||
|
|
|
||||||
|
|
@ -87,50 +87,6 @@ Place a label in the layout
|
||||||
to another layer. <P>
|
to another layer. <P>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<B>Attribute labels:</B> <P>
|
|
||||||
A handful of labels are referred to as "attribute" labels. These
|
|
||||||
label types are placed on devices and affect how the device is
|
|
||||||
extracted. <P>
|
|
||||||
|
|
||||||
A label that is placed inside a device (e.g., a MOSFET gate) which
|
|
||||||
ends with the character "<B>^</B>" is a <I>gate attribute</I>. A
|
|
||||||
gate attribute in the form of "<I>name</I><B>=</B><I>value</I><B>^</B>"
|
|
||||||
specifies an extra parameter to be passed to the device in addition
|
|
||||||
to the standard parameters calculated for that device. This is used
|
|
||||||
to capture parameters which cannot easily be inferred from the layout.
|
|
||||||
For example, an RF device model might be distinguished from a non-RF
|
|
||||||
device model by a parameter such as <B>rfmode=1</B>. Whether or not
|
|
||||||
a device is intended for RF use is not easily guessed from the layout,
|
|
||||||
and so "tagging" the gate with the parameter allows the correct model
|
|
||||||
parameters to be used for the device. <P>
|
|
||||||
|
|
||||||
A gate attribute that is not in the form of a parameter will be used
|
|
||||||
as the device's instance index in the netlist; e.g., a label of
|
|
||||||
"<B>1^</B>" on a MOSFET gate extracted as a MOSFET device would be an
|
|
||||||
entry "<B>M1</B>" in the netlist. This can be used to better track
|
|
||||||
device indexes between a schematic and layout. <P>
|
|
||||||
|
|
||||||
A label that is placed on the <I>edge</I> a device, specificlly a
|
|
||||||
MOSFET gate, and which ends with the character "<B>$</B>", is a
|
|
||||||
<I>terminal attribute</I>. The only terminal attributes recognized
|
|
||||||
by magic are <B>S$</B> and <B>D$</B>, which specify which side of the
|
|
||||||
gate is to be considered the source and which is to be considered the
|
|
||||||
drain. Generally, MOSFET devices are symmetric, and their use in a
|
|
||||||
simulation does not depend on which side is in the position of the
|
|
||||||
"source" and which is in the position of the "drain". To the extent
|
|
||||||
that it matters, the terminal attributes can be used to ensure that
|
|
||||||
the source and drain connections appear in the netlist in their
|
|
||||||
intended orientation. <P>
|
|
||||||
|
|
||||||
Labels ending with "<B>@</B>" are <I>node attributes</I>. There is
|
|
||||||
currently no functional application for node attributes. When one
|
|
||||||
is applied, it will appear in the output netlist in a SPICE comment
|
|
||||||
line indicating the node and attribute. This could be used, say,
|
|
||||||
by a post-processing script, but as it is in a comment line, it has
|
|
||||||
no impact on simulation or LVS.
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<H3>Implementation Notes:</H3>
|
<H3>Implementation Notes:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<B>label</B> is implemented as a built-in command in <B>magic</B>.
|
<B>label</B> is implemented as a built-in command in <B>magic</B>.
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,9 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
|
|
||||||
<H3>Usage:</H3>
|
<H3>Usage:</H3>
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
<B>property</B> [<I>list</I>] [<I>type</I>] [<I>key</I> [<I>value</I>]] <BR>
|
<B>property</B> [<I>key</I> [<I>value</I>]] <BR><BR>
|
||||||
or
|
|
||||||
<B>property</B> [<B>compat</B>] [<B>true</B>|<B>false</B>] <BR><BR>
|
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
where <I>key</I> and <I>value</I> are any text strings. <BR>
|
where <I>key</I> and <I>value</I> are any text strings.
|
||||||
<I>type</I> may be one of <B>string</B>, <B>integer</B>,
|
|
||||||
<B>dimension</B>, or <B>double</B>.
|
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
</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
|
with the key is returned. With both arguments, the string
|
||||||
<I>value</I> is associated with the string <I>key</I> as a
|
<I>value</I> is associated with the string <I>key</I> as a
|
||||||
property of the cell. If <I>key</I> is an existing key, then
|
property of the cell. If <I>key</I> is an existing key, then
|
||||||
its original value will be overwritten. <P>
|
its original value will be overwritten.
|
||||||
|
|
||||||
By default, properties are interpreted as verbatim string values,
|
|
||||||
with exceptions for the reserved types (see below). To force the
|
|
||||||
values of the property to be interpreted as a specific type, use
|
|
||||||
the <I>type</I> option. <P>
|
|
||||||
|
|
||||||
The <B>property compat</B> setting determines how properties are
|
|
||||||
written out to a .mag file. The default setting is <B>true</B>
|
|
||||||
(backwards compatibility mode), which writes all properties as
|
|
||||||
type "<TT>string</TT>". Properties which are reserved names
|
|
||||||
(see below) will be converted to the best type when reading the
|
|
||||||
.mag file. However, if the user wants to create a property that
|
|
||||||
is handled differently than a string (namely, to be a dimensional
|
|
||||||
value that scales), then comptability mode should be turned off. <P>
|
|
||||||
|
|
||||||
If the argument <I>list</I> is given as the first argument, and
|
|
||||||
<I>value</I> is not present, then if the property <I>key</I>
|
|
||||||
does not exist, then the command will return a NULL object to the
|
|
||||||
interpreter instead of printing an error message. This is the
|
|
||||||
"quiet" version of the command preferred for scripts that want to
|
|
||||||
query whether or not a specific property exists.
|
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<BLOCKQUOTE>
|
<BLOCKQUOTE>
|
||||||
Types are interpreted as follows:
|
Property names reserved by and used by magic:
|
||||||
<DL>
|
|
||||||
<DT> <B>string</B> type:
|
|
||||||
<DD> The property value is a character string. Character strings
|
|
||||||
may contain spaces, but if so, then the string should be quoted
|
|
||||||
or in braces, per Tcl syntax.
|
|
||||||
<DT> <B>integer</I> type:
|
|
||||||
<DD> The property value is an integer value or a list of integer
|
|
||||||
values. The values are not considered to be measurements and
|
|
||||||
do not scale. Multiple values may be passed on the command
|
|
||||||
line as additional arguments, or the set of values may be
|
|
||||||
given as a list.
|
|
||||||
<DT> <B>dimension</I> type:
|
|
||||||
<DD> The property value is an integer value or a list of integer
|
|
||||||
values. The values are considered to be (linear) dimensional
|
|
||||||
measurements and therefore scale with the database internal
|
|
||||||
units. They are interpreted as having the values currently
|
|
||||||
specified for <B>units</B>, and display back in the same
|
|
||||||
units. Multiple values may be passed on the command line as
|
|
||||||
additional arguments, or the set of values may be given as a
|
|
||||||
list.
|
|
||||||
<DT> <B>double</I> type:
|
|
||||||
<DD> The property value is a double-wide (64-bit) integer value or
|
|
||||||
a list of double-wide integer values. The values are not
|
|
||||||
considered to be measurements and do not scale. Multiple
|
|
||||||
values may be passed on the command line as additional arguments,
|
|
||||||
or the set of values may be given as a list.
|
|
||||||
</DL>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
Property names reserved by and used by magic (types are <B>string</B>
|
|
||||||
unless otherwise noted):
|
|
||||||
<DL>
|
<DL>
|
||||||
<DT> <B>GDS_FILE</B>
|
<DT> <B>GDS_FILE</B>
|
||||||
<DD> The value is the name of a GDS file which contains the mask
|
<DD> The value is the name of a GDS file which contains the mask
|
||||||
|
|
@ -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
|
<DD> If a <B>GDS_FILE</B> is defined, then this value indicates the
|
||||||
byte position of the start of mask data for this cell definition
|
byte position of the start of mask data for this cell definition
|
||||||
in the file. If set to value <B>0</B>, then the file will be
|
in the file. If set to value <B>0</B>, then the file will be
|
||||||
searched for the data bounds. This property is always of type
|
searched for the data bounds.
|
||||||
<B>double</B>.
|
|
||||||
<DT> <B>GDS_END</B>
|
<DT> <B>GDS_END</B>
|
||||||
<DD> If a <B>GDS_FILE</B> is defined, then this value indicates the
|
<DD> If a <B>GDS_FILE</B> is defined, then this value indicates the
|
||||||
byte position of the end of mask data for this cell definition
|
byte position of the end of mask data for this cell definition
|
||||||
in the file. If <B>GDS_START</B> is set to <B>0</B>, then this
|
in the file. If <B>GDS_START</B> is set to <B>0</B>, then this
|
||||||
property may be omitted. This property is always of type
|
property may be omitted.
|
||||||
<B>double</B>.
|
|
||||||
<DT> <B>LEFview</B>
|
<DT> <B>LEFview</B>
|
||||||
<DD> If set to <B>TRUE</B>, this cell is an abstract view such as that
|
<DD> If set to <B>TRUE</B>, this cell is an abstract view such as that
|
||||||
obtained from a LEF macro, and should not be used for extraction
|
obtained from a LEF macro, and should not be used for extraction
|
||||||
|
|
@ -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
|
corresponding to the abutment box of the cell, in magic's internal
|
||||||
units. The abutment box is automatically read from LEF files, but
|
units. The abutment box is automatically read from LEF files, but
|
||||||
may be defined for any file and can be used for placement alignment.
|
may be defined for any file and can be used for placement alignment.
|
||||||
This property is always of type <B>dimension</B> and must contain
|
|
||||||
exactly four values.
|
|
||||||
<DT> <B>OBS_BBOX</B>
|
<DT> <B>OBS_BBOX</B>
|
||||||
<DD> This property value is a space-sparated list of four integer values
|
<DD> This property value is a space-sparated list of four integer values
|
||||||
corresponding to a bounding box to be used when generating a LEF
|
corresponding to a bounding box to be used when generating a LEF
|
||||||
|
|
@ -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
|
will be entirely covered in obstruction layers (unless cut-outs
|
||||||
are required to accommodate pins). Any set-back applied by the
|
are required to accommodate pins). Any set-back applied by the
|
||||||
"lef write -hide <value>" option will be applied to this obstruction
|
"lef write -hide <value>" option will be applied to this obstruction
|
||||||
box. This property is always of type <B>dimension</B> and must
|
box.
|
||||||
contain exactly four values.
|
|
||||||
<DT> <B>flatten</B>
|
<DT> <B>flatten</B>
|
||||||
<DD> This property is used in conjunction with the "flatten -doproperty"
|
<DD> This property is used in conjunction with the "flatten -doproperty"
|
||||||
command option and marks the cell for flattening. Cells without
|
command option and marks the cell for flattening. Cells without
|
||||||
|
|
@ -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
|
always generate mask layer <I>type</I> in the specified rectangle
|
||||||
area when writing GDS or CIF output. <I>type</I> may be a templayer,
|
area when writing GDS or CIF output. <I>type</I> may be a templayer,
|
||||||
such that <I>type</I> could be defined as the absence of a mask layer,
|
such that <I>type</I> could be defined as the absence of a mask layer,
|
||||||
for example. This property is always of type <B>dimension</B> and
|
for example.
|
||||||
must have a multiple of four values.
|
|
||||||
</DL>
|
</DL>
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
|
|
@ -220,11 +157,6 @@ Attach a "property" (string key and value pair) to the edit cell
|
||||||
the cell definition structure.
|
the cell definition structure.
|
||||||
</BLOCKQUOTE>
|
</BLOCKQUOTE>
|
||||||
|
|
||||||
<H3>See Also:</H3>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
<A HREF=units.html><B>units</B></A> <BR>
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
|
|
||||||
<P><IMG SRC=graphics/line1.gif><P>
|
<P><IMG SRC=graphics/line1.gif><P>
|
||||||
<TABLE BORDER=0>
|
<TABLE BORDER=0>
|
||||||
<TR>
|
<TR>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
center and scale the screen view of the layout window to fit the layout. <P>
|
||||||
|
|
||||||
<B>view bbox</B> returns the bounding box dimensions of the layout,
|
<B>view bbox</B> returns the bounding box dimensions of the layout,
|
||||||
in the coordinate system of the layout (according to the units
|
in the coordinate system of the layout. <P>
|
||||||
set by the "units" command). <P>
|
|
||||||
|
|
||||||
<B>view get</B> returns the coordinates of the screen limits in
|
<B>view get</B> returns the coordinates of the screen limits in
|
||||||
the coordinate system of the layout (according to the units set
|
the coordinate system of the layout (internal database units). <P>
|
||||||
by the "units" command). <P>
|
|
||||||
|
|
||||||
<B>view</B> <I>llx lly urx ury</I> sets the view so that the
|
<B>view</B> <I>llx lly urx ury</I> sets the view so that the
|
||||||
corners of the screen are at the indicated positions in the
|
corners of the screen are at the indicated positions in the
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ extern int drcArrayYankFunc(), drcArrayOverlapFunc();
|
||||||
static DRCCookie drcArrayCookie = {
|
static DRCCookie drcArrayCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ {0} }, { {0} },
|
{ {0} }, { {0} },
|
||||||
0, DRC_EXCEPTION_NONE, 0, 0,
|
0, 0, 0,
|
||||||
DRC_ARRAY_OVERLAP_TAG,
|
DRC_ARRAY_OVERLAP_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
|
||||||
130
drc/DRCbasic.c
130
drc/DRCbasic.c
|
|
@ -27,8 +27,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h> // for memcpy()
|
#include <string.h> // for memcpy()
|
||||||
#include <math.h> // for sqrt() for diagonal check
|
#include <math.h> // for sqrt() for diagonal check
|
||||||
|
|
||||||
#include "tcltk/tclmagic.h"
|
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "tiles/tile.h"
|
#include "tiles/tile.h"
|
||||||
|
|
@ -38,9 +36,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "utils/signals.h"
|
#include "utils/signals.h"
|
||||||
#include "utils/maxrect.h"
|
#include "utils/maxrect.h"
|
||||||
#include "utils/malloc.h"
|
#include "utils/malloc.h"
|
||||||
#include "utils/undo.h"
|
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
#include "cif/CIFint.h"
|
|
||||||
|
|
||||||
int dbDRCDebug = 0;
|
int dbDRCDebug = 0;
|
||||||
|
|
||||||
|
|
@ -52,7 +48,7 @@ int dbDRCDebug = 0;
|
||||||
static DRCCookie drcOverlapCookie = {
|
static DRCCookie drcOverlapCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ {0} }, { {0} },
|
{ {0} }, { {0} },
|
||||||
0, DRC_EXCEPTION_NONE, 0, 0,
|
0, 0, 0,
|
||||||
DRC_OVERLAP_TAG,
|
DRC_OVERLAP_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
@ -66,33 +62,7 @@ extern MaxRectsData *drcCanonicalMaxwidth();
|
||||||
/*
|
/*
|
||||||
*-----------------------------------------------------------------------
|
*-----------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* drcFoundOneFunc --
|
* drcCifPointToSegment
|
||||||
*
|
|
||||||
* Simple callback for a plane search on a mask-hint plane inside
|
|
||||||
* a DRC check area.
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* Return 1 always, indicating that a tile has been found in the
|
|
||||||
* DRC search area, and the search can end.
|
|
||||||
*
|
|
||||||
* Side effects:
|
|
||||||
* None.
|
|
||||||
*
|
|
||||||
*-----------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
drcFoundOneFunc(Tile *tile,
|
|
||||||
TileType dinfo,
|
|
||||||
ClientData cdata)
|
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
*-----------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* drcCifPointToSegment --
|
|
||||||
*
|
*
|
||||||
* Euclidean-distance point-to-segment distance (squared)
|
* Euclidean-distance point-to-segment distance (squared)
|
||||||
* calculation (borrowed from XCircuit)
|
* calculation (borrowed from XCircuit)
|
||||||
|
|
@ -498,26 +468,6 @@ DRCBasicCheck (celldef, checkRect, clipRect, function, cdata)
|
||||||
DBResetTilePlane(celldef->cd_planes[planeNum], DRC_UNPROCESSED);
|
DBResetTilePlane(celldef->cd_planes[planeNum], DRC_UNPROCESSED);
|
||||||
(void) DBSrPaintArea ((Tile *) NULL, celldef->cd_planes[planeNum],
|
(void) DBSrPaintArea ((Tile *) NULL, celldef->cd_planes[planeNum],
|
||||||
checkRect, &DBAllTypeBits, drcTile, (ClientData) &arg);
|
checkRect, &DBAllTypeBits, drcTile, (ClientData) &arg);
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
|
||||||
/* Execute pending Tcl events, so the DRC process doesn't block. */
|
|
||||||
|
|
||||||
/* 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);
|
drcCifCheck(&arg);
|
||||||
if (arg.dCD_rlist != NULL) freeMagic(arg.dCD_rlist);
|
if (arg.dCD_rlist != NULL) freeMagic(arg.dCD_rlist);
|
||||||
|
|
@ -777,44 +727,6 @@ drcTile (tile, dinfo, arg)
|
||||||
for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL;
|
for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL;
|
||||||
cptr = cptr->drcc_next)
|
cptr = cptr->drcc_next)
|
||||||
{
|
{
|
||||||
/* Handle rule exceptions and exemptions */
|
|
||||||
if (cptr->drcc_exception != 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 */
|
/* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */
|
||||||
/* the code above for non-Manhattan shapes and do not */
|
/* the code above for non-Manhattan shapes and do not */
|
||||||
/* need to be processed again. */
|
/* need to be processed again. */
|
||||||
|
|
@ -1224,44 +1136,6 @@ drcTile (tile, dinfo, arg)
|
||||||
for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL;
|
for (cptr = DRCCurStyle->DRCRulesTbl[to][tt]; cptr != (DRCCookie *) NULL;
|
||||||
cptr = cptr->drcc_next)
|
cptr = cptr->drcc_next)
|
||||||
{
|
{
|
||||||
/* Handle rule exceptions and exemptions */
|
|
||||||
if (cptr->drcc_exception != 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 */
|
/* DRC_ANGLES_90 and DRC_SPLITTILE rules are handled by */
|
||||||
/* the code above for non-Manhattan shapes and do not */
|
/* the code above for non-Manhattan shapes and do not */
|
||||||
/* need to be processed again. */
|
/* need to be processed again. */
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ static ClientData drcSubClientData; /* To be passed to error function. */
|
||||||
static DRCCookie drcSubcellCookie = {
|
static DRCCookie drcSubcellCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ {0} }, { {0} },
|
{ {0} }, { {0} },
|
||||||
0, DRC_EXCEPTION_NONE, 0, 0,
|
0, 0, 0,
|
||||||
DRC_SUBCELL_OVERLAP_TAG,
|
DRC_SUBCELL_OVERLAP_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
@ -65,7 +65,7 @@ static DRCCookie drcSubcellCookie = {
|
||||||
static DRCCookie drcInSubCookie = {
|
static DRCCookie drcInSubCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ {0} }, { {0} },
|
{ {0} }, { {0} },
|
||||||
0, DRC_EXCEPTION_NONE, 0, 0,
|
0, 0, 0,
|
||||||
DRC_IN_SUBCELL_TAG,
|
DRC_IN_SUBCELL_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
@ -79,7 +79,7 @@ static DRCCookie drcInSubCookie = {
|
||||||
static DRCCookie drcOffGridCookie = {
|
static DRCCookie drcOffGridCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ {0} }, { {0} },
|
{ {0} }, { {0} },
|
||||||
0, DRC_EXCEPTION_NONE, 0, 0,
|
0, 0, 0,
|
||||||
DRC_OFFGRID_TAG,
|
DRC_OFFGRID_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
@ -826,7 +826,6 @@ DRCInteractionCheck(def, area, erasebox, func, cdarg)
|
||||||
*/
|
*/
|
||||||
subArea = *erasebox;
|
subArea = *erasebox;
|
||||||
GeoClip(&subArea, &cliparea);
|
GeoClip(&subArea, &cliparea);
|
||||||
if (GEO_RECTNULL(&subArea)) continue;
|
|
||||||
GEO_EXPAND(&subArea, DRCTechHalo, &intArea);
|
GEO_EXPAND(&subArea, DRCTechHalo, &intArea);
|
||||||
|
|
||||||
errorSaveType = DRCErrorType;
|
errorSaveType = DRCErrorType;
|
||||||
|
|
|
||||||
202
drc/DRCtech.c
202
drc/DRCtech.c
|
|
@ -72,12 +72,6 @@ static int drcRulesOptimized = 0;
|
||||||
|
|
||||||
static int DRCtag = 0;
|
static int DRCtag = 0;
|
||||||
|
|
||||||
/* Keep track of what rule exemption or exception is in effect
|
|
||||||
* while reading the DRC tech file section.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static unsigned char drcCurException = DRC_EXCEPTION_NONE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forward declarations.
|
* Forward declarations.
|
||||||
*/
|
*/
|
||||||
|
|
@ -85,7 +79,6 @@ int drcWidth(), drcSpacing(), drcEdge(), drcNoOverlap();
|
||||||
int drcExactOverlap(), drcExtend();
|
int drcExactOverlap(), drcExtend();
|
||||||
int drcSurround(), drcRectOnly(), drcOverhang();
|
int drcSurround(), drcRectOnly(), drcOverhang();
|
||||||
int drcStepSize(), drcOption(), drcOffGrid();
|
int drcStepSize(), drcOption(), drcOffGrid();
|
||||||
int drcException(), drcExemption();
|
|
||||||
int drcMaxwidth(), drcArea(), drcRectangle(), drcAngles();
|
int drcMaxwidth(), drcArea(), drcRectangle(), drcAngles();
|
||||||
int drcCifSetStyle(), drcCifWidth(), drcCifSpacing();
|
int drcCifSetStyle(), drcCifWidth(), drcCifSpacing();
|
||||||
int drcCifMaxwidth(), drcCifArea();
|
int drcCifMaxwidth(), drcCifArea();
|
||||||
|
|
@ -308,12 +301,6 @@ drcTechFreeStyle()
|
||||||
/* Clear the Why string list */
|
/* Clear the Why string list */
|
||||||
freeMagic(DRCCurStyle->DRCWhyList);
|
freeMagic(DRCCurStyle->DRCWhyList);
|
||||||
|
|
||||||
/* Clear the exception list */
|
|
||||||
for (i = 0; i < DRCCurStyle->DRCExceptionSize; i++)
|
|
||||||
freeMagic(DRCCurStyle->DRCExceptionList[i]);
|
|
||||||
if (DRCCurStyle->DRCExceptionList != (char **)NULL)
|
|
||||||
freeMagic(DRCCurStyle->DRCExceptionList);
|
|
||||||
|
|
||||||
freeMagic(DRCCurStyle);
|
freeMagic(DRCCurStyle);
|
||||||
DRCCurStyle = NULL;
|
DRCCurStyle = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -397,63 +384,6 @@ drcWhyCreate(whystring)
|
||||||
return DRCCurStyle->DRCWhySize;
|
return DRCCurStyle->DRCWhySize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
* drcExceptionCreate --
|
|
||||||
*
|
|
||||||
* Create an entry for a DRC rule exception/exemption type, if it does
|
|
||||||
* not already exist.
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* The index of the exception (which is 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->DRCStepSize = 0;
|
||||||
DRCCurStyle->DRCFlags = (char)0;
|
DRCCurStyle->DRCFlags = (char)0;
|
||||||
DRCCurStyle->DRCWhySize = 0;
|
DRCCurStyle->DRCWhySize = 0;
|
||||||
DRCCurStyle->DRCExceptionList = (char **)NULL;
|
|
||||||
DRCCurStyle->DRCExceptionSize = 0;
|
|
||||||
|
|
||||||
HashInit(&DRCWhyErrorTable, 16, HT_STRINGKEYS);
|
HashInit(&DRCWhyErrorTable, 16, HT_STRINGKEYS);
|
||||||
|
|
||||||
|
|
@ -735,7 +663,6 @@ DRCTechStyleInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
drcCifInit();
|
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_plane = planeto;
|
||||||
(cookie)->drcc_mod = 0;
|
(cookie)->drcc_mod = 0;
|
||||||
(cookie)->drcc_cmod = 0;
|
(cookie)->drcc_cmod = 0;
|
||||||
(cookie)->drcc_exception = drcCurException;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is like drcCifAssign, but checks for bad plane numbers in planeto and
|
// This is like drcCifAssign, but checks for bad plane numbers in planeto and
|
||||||
|
|
@ -1105,37 +1031,50 @@ DRCTechAddRule(sectionName, argc, argv)
|
||||||
int (*rk_proc)(); /* Procedure implementing this keyword */
|
int (*rk_proc)(); /* Procedure implementing this keyword */
|
||||||
const char *rk_err; /* Error message */
|
const char *rk_err; /* Error message */
|
||||||
} ruleKeys[] = {
|
} ruleKeys[] = {
|
||||||
{"angles", 4, 4, drcAngles, "layers 45|90 why"},
|
{"angles", 4, 4, drcAngles,
|
||||||
|
"layers 45|90 why"},
|
||||||
{"edge", 8, 10, drcEdge,
|
{"edge", 8, 10, drcEdge,
|
||||||
"layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"},
|
"layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"},
|
||||||
{"edge4way", 8, 10, drcEdge,
|
{"edge4way", 8, 10, drcEdge,
|
||||||
"layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"},
|
"layers1 layers2 distance okTypes cornerTypes cornerDistance [option] why [plane]"},
|
||||||
{"exact_overlap", 2, 2, drcExactOverlap, "layers"},
|
{"exact_overlap", 2, 2, drcExactOverlap,
|
||||||
{"exception", 2, 2, drcException, "name"},
|
"layers"},
|
||||||
{"exemption", 2, 2, drcExemption, "name"},
|
|
||||||
{"extend", 5, 6, drcExtend,
|
{"extend", 5, 6, drcExtend,
|
||||||
"layers1 layers2 distance [option] why"},
|
"layers1 layers2 distance [option] why"},
|
||||||
{"no_overlap", 3, 3, drcNoOverlap, "layers1 layers2"},
|
{"no_overlap", 3, 3, drcNoOverlap,
|
||||||
{"option", 2, 2, drcOption, "option_name option_value"},
|
"layers1 layers2"},
|
||||||
{"overhang", 5, 5, drcOverhang, "layers1 layers2 distance why"},
|
{"option", 2, 2, drcOption,
|
||||||
{"rect_only", 3, 3, drcRectOnly, "layers why"},
|
"option_name option_value"},
|
||||||
|
{"overhang", 5, 5, drcOverhang,
|
||||||
|
"layers1 layers2 distance why"},
|
||||||
|
{"rect_only", 3, 3, drcRectOnly,
|
||||||
|
"layers why"},
|
||||||
{"spacing", 6, 7, drcSpacing,
|
{"spacing", 6, 7, drcSpacing,
|
||||||
"layers1 layers2 separation [layers3] adjacency why"},
|
"layers1 layers2 separation [layers3] adjacency why"},
|
||||||
{"stepsize", 2, 2, drcStepSize, "step_size"},
|
{"stepsize", 2, 2, drcStepSize,
|
||||||
|
"step_size"},
|
||||||
{"surround", 6, 7, drcSurround,
|
{"surround", 6, 7, drcSurround,
|
||||||
"layers1 layers2 distance presence why"},
|
"layers1 layers2 distance presence why"},
|
||||||
{"width", 4, 5, drcWidth, "layers width why"},
|
{"width", 4, 5, drcWidth,
|
||||||
|
"layers width why"},
|
||||||
{"widespacing", 7, 8, drcSpacing,
|
{"widespacing", 7, 8, drcSpacing,
|
||||||
"layers1 width layers2 separation adjacency why"},
|
"layers1 width layers2 separation adjacency why"},
|
||||||
{"area", 5, 5, drcArea, "layers area horizon why"},
|
{"area", 5, 5, drcArea,
|
||||||
{"off_grid", 4, 4, drcOffGrid, "layers pitch why"},
|
"layers area horizon why"},
|
||||||
{"maxwidth", 4, 6, drcMaxwidth, "layers maxwidth bends why"},
|
{"off_grid", 4, 4, drcOffGrid,
|
||||||
{"cifstyle", 2, 2, drcCifSetStyle, "cif_style"},
|
"layers pitch why"},
|
||||||
{"cifwidth", 4, 4, drcCifWidth, "layers width 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,
|
{"cifspacing", 6, 6, drcCifSpacing,
|
||||||
"layers1 layers2 separation adjacency why"},
|
"layers1 layers2 separation adjacency why"},
|
||||||
{"cifarea", 5, 5, drcCifArea, "layers area horizon why"},
|
{"cifarea", 5, 5, drcCifArea,
|
||||||
{"cifmaxwidth", 5, 5, drcCifMaxwidth, "layers maxwidth bends why"},
|
"layers area horizon why"},
|
||||||
|
{"cifmaxwidth", 5, 5, drcCifMaxwidth,
|
||||||
|
"layers maxwidth bends why"},
|
||||||
{"rectangle", 5, 5, drcRectangle,
|
{"rectangle", 5, 5, drcRectangle,
|
||||||
"layers maxwidth [even|odd|any] why"},
|
"layers maxwidth [even|odd|any] why"},
|
||||||
{0}
|
{0}
|
||||||
|
|
@ -1756,7 +1695,7 @@ drcMaxwidth(argc, argv)
|
||||||
if (PlaneMaskHasPlane(pmask2, plane2))
|
if (PlaneMaskHasPlane(pmask2, plane2))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (PlaneMaskHasPlane(pmask, plane2))
|
if (plane2 == plane)
|
||||||
TechError("Warning: Exclude types for \"maxwidth\" are on the "
|
TechError("Warning: Exclude types for \"maxwidth\" are on the "
|
||||||
"same plane and so cannot be checked.\n");
|
"same plane and so cannot be checked.\n");
|
||||||
}
|
}
|
||||||
|
|
@ -3695,84 +3634,6 @@ drcRectangle(argc, argv)
|
||||||
return maxwidth;
|
return maxwidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* drcException, drcExemption --
|
|
||||||
*
|
|
||||||
* Process a DRC exception declaration
|
|
||||||
* This is of the form:
|
|
||||||
*
|
|
||||||
* exception exception_name|none
|
|
||||||
* or
|
|
||||||
* exemption exemption_name|none
|
|
||||||
*
|
|
||||||
* e.g,
|
|
||||||
*
|
|
||||||
* exception SRAM
|
|
||||||
* exemption SRAM
|
|
||||||
*
|
|
||||||
* The exception_name or exemption_name is the suffix part of a MASKHINTS_*
|
|
||||||
* property name; e.g., the name SRAM corresponds to a property called
|
|
||||||
* MASKHINTS_SRAM. This declaration is followed by a block of DRC rules
|
|
||||||
* that are subject to the exception or the exemption. An exception is the
|
|
||||||
* opposite of an exemption: If a rule is excepted, then the rule applies
|
|
||||||
* within areas delineated by bounding boxes defined by the
|
|
||||||
* MASKHINTS_<exception_name> property. If a rule is exempted, then the
|
|
||||||
* rule applies only outside of areas delineated by bounding boxes defined
|
|
||||||
* by the MASKHINTS_<exemption_name> property. The block of rules subject
|
|
||||||
* to the exemption or exception ends with another exception or exemption
|
|
||||||
* declaration. If the following rules are not to be excepted or exempted
|
|
||||||
* at all, then use "exception none" or "exemption none".
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* Returns 0.
|
|
||||||
*
|
|
||||||
* Side effects:
|
|
||||||
* Updates drcCurException. drcCurException 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_dist > next->drcc_dist) continue;
|
||||||
if (dp->drcc_cdist > next->drcc_cdist) continue;
|
if (dp->drcc_cdist > next->drcc_cdist) continue;
|
||||||
if (dp->drcc_plane != next->drcc_plane) continue;
|
if (dp->drcc_plane != next->drcc_plane) continue;
|
||||||
if (dp->drcc_exception != next->drcc_exception) continue;
|
|
||||||
if (dp->drcc_flags & DRC_REVERSE)
|
if (dp->drcc_flags & DRC_REVERSE)
|
||||||
{
|
{
|
||||||
if (!(next->drcc_flags & DRC_REVERSE)) continue;
|
if (!(next->drcc_flags & DRC_REVERSE)) continue;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ typedef struct drccookie
|
||||||
TileTypeBitMask drcc_mask; /* Legal types on RHS */
|
TileTypeBitMask drcc_mask; /* Legal types on RHS */
|
||||||
TileTypeBitMask drcc_corner; /* Types that trigger corner check */
|
TileTypeBitMask drcc_corner; /* Types that trigger corner check */
|
||||||
unsigned short drcc_flags; /* Miscellaneous flags, see below. */
|
unsigned short drcc_flags; /* Miscellaneous flags, see below. */
|
||||||
unsigned char drcc_exception; /* Index to list of exceptions */
|
|
||||||
int drcc_edgeplane; /* Plane of edge */
|
int drcc_edgeplane; /* Plane of edge */
|
||||||
int drcc_plane; /* Index of plane on which to check
|
int drcc_plane; /* Index of plane on which to check
|
||||||
* legal types. */
|
* legal types. */
|
||||||
|
|
@ -92,11 +91,6 @@ typedef struct drccookie
|
||||||
#define DRC_UNPROCESSED CLIENTDEFAULT
|
#define DRC_UNPROCESSED CLIENTDEFAULT
|
||||||
#define DRC_PROCESSED 1
|
#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
|
* Background DRC (DRC Idle proc) for Tcl-based Magic
|
||||||
*/
|
*/
|
||||||
|
|
@ -183,8 +177,6 @@ typedef struct drcstyle
|
||||||
unsigned short DRCFlags; /* Option flags */
|
unsigned short DRCFlags; /* Option flags */
|
||||||
char **DRCWhyList; /* Indexed list of "why" text strings */
|
char **DRCWhyList; /* Indexed list of "why" text strings */
|
||||||
int DRCWhySize; /* Length of DRCWhyList */
|
int DRCWhySize; /* Length of DRCWhyList */
|
||||||
char **DRCExceptionList; /* Indexed list of DRC exceptions */
|
|
||||||
int DRCExceptionSize; /* Length of DRCExceptionList */
|
|
||||||
PaintResultType DRCPaintTable[NP][NT][NT];
|
PaintResultType DRCPaintTable[NP][NT][NT];
|
||||||
} DRCStyle;
|
} DRCStyle;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -634,7 +634,7 @@ subcktHierVisit(
|
||||||
|
|
||||||
if (hasports || is_top)
|
if (hasports || is_top)
|
||||||
return subcktVisit(use, hierName, is_top);
|
return subcktVisit(use, hierName, is_top);
|
||||||
else if ((def->def_flags & DEF_NODEVICES) && (!isStub))
|
else if (def->def_flags & DEF_NODEVICES)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return subcktVisit(use, hierName, is_top);
|
return subcktVisit(use, hierName, is_top);
|
||||||
|
|
@ -1088,7 +1088,6 @@ spcdevHierVisit(
|
||||||
|
|
||||||
if (!has_model)
|
if (!has_model)
|
||||||
{
|
{
|
||||||
fprintf(esSpiceF, " ");
|
|
||||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||||
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
|
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
|
||||||
}
|
}
|
||||||
|
|
@ -1139,7 +1138,6 @@ spcdevHierVisit(
|
||||||
|
|
||||||
if (!has_model)
|
if (!has_model)
|
||||||
{
|
{
|
||||||
fprintf(esSpiceF, " ");
|
|
||||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||||
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
|
spcHierWriteParams(hc, dev, scale, l, w, sdM, FALSE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1689,43 +1689,23 @@ subcktVisit(
|
||||||
HashStartSearch(&hs);
|
HashStartSearch(&hs);
|
||||||
while ((he = HashNext(&def->def_nodes, &hs)))
|
while ((he = HashNext(&def->def_nodes, &hs)))
|
||||||
{
|
{
|
||||||
bool found = FALSE;
|
|
||||||
|
|
||||||
sname = (EFNodeName *) HashGetValue(he);
|
sname = (EFNodeName *) HashGetValue(he);
|
||||||
if (sname == NULL) continue;
|
if (sname == NULL) continue;
|
||||||
snode = sname->efnn_node;
|
snode = sname->efnn_node;
|
||||||
|
|
||||||
if ((snode == NULL) || !(snode->efnode_flags & EF_PORT)) continue;
|
if ((snode == NULL) || !(snode->efnode_flags & EF_PORT)) continue;
|
||||||
|
|
||||||
portidx = snode->efnode_name->efnn_port;
|
|
||||||
|
|
||||||
if (portidx >= 0)
|
|
||||||
{
|
|
||||||
if (nodeList[portidx] == NULL)
|
|
||||||
{
|
|
||||||
nodeList[portidx] = snode->efnode_name;
|
|
||||||
found = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Normally there should be a port associated with snode, but
|
|
||||||
* if not, go looking for one in the node name aliases.
|
|
||||||
*/
|
|
||||||
for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next)
|
for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next)
|
||||||
{
|
{
|
||||||
if (found == TRUE) break;
|
|
||||||
|
|
||||||
portidx = nodeName->efnn_port;
|
portidx = nodeName->efnn_port;
|
||||||
if (portidx < 0) continue;
|
if (portidx < 0) continue;
|
||||||
if (nodeList[portidx] == NULL)
|
if (nodeList[portidx] == NULL)
|
||||||
{
|
{
|
||||||
nodeList[portidx] = nodeName;
|
nodeList[portidx] = nodeName;
|
||||||
found = TRUE;
|
|
||||||
}
|
}
|
||||||
else if (EFHNBest(nodeName->efnn_hier, nodeList[portidx]->efnn_hier))
|
else if (EFHNBest(nodeName->efnn_hier, nodeList[portidx]->efnn_hier))
|
||||||
{
|
{
|
||||||
nodeList[portidx] = nodeName;
|
nodeList[portidx] = nodeName;
|
||||||
found = TRUE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1952,7 +1932,6 @@ topVisit(
|
||||||
{
|
{
|
||||||
char stmp[MAX_STR_SIZE];
|
char stmp[MAX_STR_SIZE];
|
||||||
int portidx;
|
int portidx;
|
||||||
bool found = FALSE;
|
|
||||||
|
|
||||||
sname = (EFNodeName *) HashGetValue(he);
|
sname = (EFNodeName *) HashGetValue(he);
|
||||||
if (sname == NULL) continue; /* Should not happen */
|
if (sname == NULL) continue; /* Should not happen */
|
||||||
|
|
@ -1960,68 +1939,33 @@ topVisit(
|
||||||
snode = sname->efnn_node;
|
snode = sname->efnn_node;
|
||||||
if ((!snode) || (!(snode->efnode_flags & EF_PORT))) continue;
|
if ((!snode) || (!(snode->efnode_flags & EF_PORT))) continue;
|
||||||
|
|
||||||
/* Found a node which is also a port */
|
|
||||||
|
|
||||||
portidx = snode->efnode_name->efnn_port;
|
|
||||||
if (portidx >= 0)
|
|
||||||
{
|
|
||||||
if (sorted_ports[portidx] == NULL)
|
|
||||||
{
|
|
||||||
if ((def->def_flags & DEF_ABSTRACT))
|
|
||||||
{
|
|
||||||
EFHNSprintf(stmp, sname->efnn_hier);
|
|
||||||
pname = stmp;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL);
|
|
||||||
|
|
||||||
hep = HashLookOnly(&portNameTable, pname);
|
|
||||||
if (hep == (HashEntry *)NULL)
|
|
||||||
{
|
|
||||||
hep = HashFind(&portNameTable, pname);
|
|
||||||
HashSetValue(hep, (ClientData)(pointertype)portidx);
|
|
||||||
sorted_ports[portidx] = StrDup((char **)NULL, pname);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Node that was unassigned has been found to be
|
|
||||||
* a repeat (see NOTE at top), so make sure its
|
|
||||||
* port number is set correctly.
|
|
||||||
*/
|
|
||||||
snode->efnode_name->efnn_port = (int)(pointertype)HashGetValue(hep);
|
|
||||||
}
|
|
||||||
found = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(def->def_flags & DEF_ABSTRACT))
|
|
||||||
heh = HashLookOnly(&efNodeHashTable, (char *)snode->efnode_name->efnn_hier);
|
|
||||||
|
|
||||||
/* Might need to check here for a port that was optimized out? */
|
|
||||||
|
|
||||||
/* If snode is flagged as a port but no port number was found, then
|
|
||||||
* check the all of the node's name entries to see if any of them has
|
|
||||||
* a port number.
|
|
||||||
*/
|
|
||||||
|
|
||||||
for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next)
|
for (nodeName = sname; nodeName != NULL; nodeName = nodeName->efnn_next)
|
||||||
{
|
{
|
||||||
if (found == TRUE) break;
|
|
||||||
portidx = nodeName->efnn_port;
|
portidx = nodeName->efnn_port;
|
||||||
if (portidx < 0) continue;
|
if (portidx < 0) continue;
|
||||||
|
|
||||||
|
/* Check if the same hierName is recorded in the flattened/optimized
|
||||||
|
* def's efNodeHashTable. If not, then it has been optimized out
|
||||||
|
* and should be removed from the port list.
|
||||||
|
*/
|
||||||
if (def->def_flags & DEF_ABSTRACT)
|
if (def->def_flags & DEF_ABSTRACT)
|
||||||
{
|
|
||||||
heh = HashLookOnly(&efNodeHashTable, (char *)nodeName->efnn_hier);
|
heh = HashLookOnly(&efNodeHashTable, (char *)nodeName->efnn_hier);
|
||||||
|
else
|
||||||
|
heh = HashLookOnly(&efNodeHashTable,
|
||||||
|
(char *)snode->efnode_name->efnn_hier);
|
||||||
|
|
||||||
/* If view is abstract, rely on the given port name, not
|
/* If view is abstract, rely on the given port name, not
|
||||||
* the node. Otherwise, artifacts of the abstract view
|
* the node. Otherwise, artifacts of the abstract view
|
||||||
* may cause nodes to be merged and the names lost.
|
* may cause nodes to be merged and the names lost.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (def->def_flags & DEF_ABSTRACT)
|
||||||
|
{
|
||||||
EFHNSprintf(stmp, nodeName->efnn_hier);
|
EFHNSprintf(stmp, nodeName->efnn_hier);
|
||||||
pname = stmp;
|
pname = stmp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
// pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL);
|
||||||
pname = nodeSpiceName(nodeName->efnn_hier, NULL);
|
pname = nodeSpiceName(nodeName->efnn_hier, NULL);
|
||||||
|
|
||||||
if (heh == (HashEntry *)NULL) /* pname now resolved for log output */
|
if (heh == (HashEntry *)NULL) /* pname now resolved for log output */
|
||||||
|
|
@ -2039,10 +1983,7 @@ topVisit(
|
||||||
hep = HashFind(&portNameTable, pname);
|
hep = HashFind(&portNameTable, pname);
|
||||||
HashSetValue(hep, (ClientData)(pointertype)nodeName->efnn_port);
|
HashSetValue(hep, (ClientData)(pointertype)nodeName->efnn_port);
|
||||||
if (sorted_ports[portidx] == NULL)
|
if (sorted_ports[portidx] == NULL)
|
||||||
{
|
|
||||||
sorted_ports[portidx] = StrDup((char **)NULL, pname);
|
sorted_ports[portidx] = StrDup((char **)NULL, pname);
|
||||||
found = TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -3140,7 +3081,6 @@ spcdevVisit(
|
||||||
|
|
||||||
if (!has_model)
|
if (!has_model)
|
||||||
{
|
{
|
||||||
fprintf(esSpiceF, " ");
|
|
||||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||||
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
|
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
|
||||||
}
|
}
|
||||||
|
|
@ -3187,7 +3127,6 @@ spcdevVisit(
|
||||||
|
|
||||||
if (!has_model)
|
if (!has_model)
|
||||||
{
|
{
|
||||||
fprintf(esSpiceF, " ");
|
|
||||||
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
esSIvalue(esSpiceF, 1.0E-15 * (double)sdM * (double)dev->dev_cap);
|
||||||
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
|
spcWriteParams(dev, hierName, scale, l, w, sdM, FALSE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -648,21 +648,8 @@ efBuildEquiv(def, nodeName1, nodeName2, resist, isspice)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!resist)
|
else if (!resist)
|
||||||
{
|
|
||||||
char *uptr1, *uptr2;
|
|
||||||
|
|
||||||
/* Do not generate an error message if one or both node names
|
|
||||||
* is made by "extract unique".
|
|
||||||
*/
|
|
||||||
if ((uptr1 = strstr(nodeName1, "_uq")) != 0) *uptr1 = '\0';
|
|
||||||
if ((uptr2 = strstr(nodeName2, "_uq")) != 0) *uptr2 = '\0';
|
|
||||||
if ((uptr1 == NULL && uptr2 == NULL) ||
|
|
||||||
strcmp(nodeName1, nodeName2))
|
|
||||||
TxError("Warning: Ports \"%s\" and \"%s\" are electrically "
|
TxError("Warning: Ports \"%s\" and \"%s\" are electrically "
|
||||||
"shorted.\n", nodeName1, nodeName2);
|
"shorted.\n", nodeName1, nodeName2);
|
||||||
if (uptr1) *uptr1 = '_';
|
|
||||||
if (uptr2) *uptr2 = '_';
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
/* Do not merge the nodes when folding in extresist parasitics */
|
/* Do not merge the nodes when folding in extresist parasitics */
|
||||||
return;
|
return;
|
||||||
|
|
@ -2116,7 +2103,7 @@ efNodeMerge(node1ptr, node2ptr)
|
||||||
/* Make all EFNodeNames point to "keeping" */
|
/* Make all EFNodeNames point to "keeping" */
|
||||||
if (removing->efnode_name)
|
if (removing->efnode_name)
|
||||||
{
|
{
|
||||||
bool topportk, topportr, bestname, swapnames;
|
bool topportk, topportr, bestname;
|
||||||
|
|
||||||
for (nn = removing->efnode_name; nn; nn = nn->efnn_next)
|
for (nn = removing->efnode_name; nn; nn = nn->efnn_next)
|
||||||
{
|
{
|
||||||
|
|
@ -2127,31 +2114,10 @@ efNodeMerge(node1ptr, node2ptr)
|
||||||
topportk = (keeping->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
|
topportk = (keeping->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
|
||||||
topportr = (removing->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
|
topportr = (removing->efnode_flags & EF_TOP_PORT) ? TRUE : FALSE;
|
||||||
|
|
||||||
/* The node "keeping" is being kept, but we need to decide which
|
/* Concatenate list of EFNodeNames, taking into account precedence */
|
||||||
* node name of the two will be the node name of "keeping". If
|
if ((!keeping->efnode_name) || (!topportk && topportr)
|
||||||
* "keeping" has the best node name, then we're good; otherwise,
|
|| EFHNBest(removing->efnode_name->efnn_hier,
|
||||||
* we need to copy the name from "removing" to "keeping".
|
keeping->efnode_name->efnn_hier))
|
||||||
*
|
|
||||||
* Order of precedence:
|
|
||||||
* 1) If one node does not have a name, then use the name of the other.
|
|
||||||
* 2) If one node is a port and the other isn't, then use the port name.
|
|
||||||
* 3) Use the one with the preferred lexigraphical order according to
|
|
||||||
* EFHNBest().
|
|
||||||
*/
|
|
||||||
if ((!keeping->efnode_name) && (removing->efnode_name))
|
|
||||||
swapnames = TRUE;
|
|
||||||
else if ((keeping->efnode_name) && (!removing->efnode_name))
|
|
||||||
swapnames = FALSE;
|
|
||||||
else if (!topportk && topportr)
|
|
||||||
swapnames = TRUE;
|
|
||||||
else if (topportk && !topportr)
|
|
||||||
swapnames = FALSE;
|
|
||||||
else
|
|
||||||
swapnames = EFHNBest(removing->efnode_name->efnn_hier,
|
|
||||||
keeping->efnode_name->efnn_hier);
|
|
||||||
|
|
||||||
/* Concatenate list of EFNodeNames */
|
|
||||||
if (swapnames)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* New official name is that of "removing".
|
* New official name is that of "removing".
|
||||||
|
|
@ -2238,14 +2204,6 @@ efNodeMerge(node1ptr, node2ptr)
|
||||||
if (removing->efnode_flags & EF_SUBS_NODE)
|
if (removing->efnode_flags & EF_SUBS_NODE)
|
||||||
keeping->efnode_flags |= EF_SUBS_NODE;
|
keeping->efnode_flags |= EF_SUBS_NODE;
|
||||||
|
|
||||||
/*
|
|
||||||
* If "removing" has the EF_GLOB_SUBS_NODE flag set, then copy the
|
|
||||||
* port record in the flags to "keeping".
|
|
||||||
*/
|
|
||||||
if (removing->efnode_flags & EF_GLOB_SUBS_NODE)
|
|
||||||
keeping->efnode_flags |= EF_GLOB_SUBS_NODE;
|
|
||||||
|
|
||||||
/* If EFSaveLocs is set, then merge any disjoint segments from
|
|
||||||
/* If EFSaveLocs is set, then merge any disjoint segments from
|
/* If EFSaveLocs is set, then merge any disjoint segments from
|
||||||
* removing to keeping.
|
* removing to keeping.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -61,17 +61,15 @@ int efFlatGlobHash(HierName *);
|
||||||
bool efFlatGlobCmp(HierName *, HierName *);
|
bool efFlatGlobCmp(HierName *, HierName *);
|
||||||
char *efFlatGlobCopy(HierName *);
|
char *efFlatGlobCopy(HierName *);
|
||||||
void efFlatGlobError(EFNodeName *nameGlob, EFNodeName *nameFlat);
|
void efFlatGlobError(EFNodeName *nameGlob, EFNodeName *nameFlat);
|
||||||
int efAddNodes(HierContext *hc, int flags);
|
int efAddNodes(HierContext *hc, bool stdcell);
|
||||||
int efAddConns(HierContext *hc, int flags);
|
int efAddConns(HierContext *hc, bool doWarn);
|
||||||
int efAddOneConn(HierContext *hc, char *name1, char *name2, Connection *conn, int flags);
|
int efAddOneConn(HierContext *hc, char *name1, char *name2, Connection *conn, bool doWarn);
|
||||||
|
|
||||||
/* Flags passed to efFlatNode() */
|
/* Flags passed to efFlatNode() */
|
||||||
|
|
||||||
#define FLATNODE_STDCELL 0x01
|
#define FLATNODE_STDCELL 0x01
|
||||||
#define FLATNODE_DOWARN 0x02
|
#define FLATNODE_DOWARN 0x02
|
||||||
#define FLATNODE_NOABSTRACT 0x04
|
#define FLATNODE_NOABSTRACT 0x04
|
||||||
#define FLATNODE_HIER 0x08
|
|
||||||
#define FLATNODE_CHILD 0x10
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -218,7 +216,7 @@ EFFlatBuildOneLevel(def, flags)
|
||||||
efFlatRootUse.use_def = efFlatRootDef;
|
efFlatRootUse.use_def = efFlatRootDef;
|
||||||
|
|
||||||
/* Record all nodes down the hierarchy from here */
|
/* Record all nodes down the hierarchy from here */
|
||||||
flatnodeflags = FLATNODE_HIER; /* No FLATNODE_DOWARN */
|
flatnodeflags = 0; /* No FLATNODE_DOWARN */
|
||||||
efFlatNodes(&efFlatContext, INT2CD(flatnodeflags));
|
efFlatNodes(&efFlatContext, INT2CD(flatnodeflags));
|
||||||
|
|
||||||
/* Expand all subcells that contain connectivity information but */
|
/* Expand all subcells that contain connectivity information but */
|
||||||
|
|
@ -322,7 +320,9 @@ efFlatNodes(hc, clientData)
|
||||||
ClientData clientData;
|
ClientData clientData;
|
||||||
{
|
{
|
||||||
int flags = (int)CD2INT(clientData);
|
int flags = (int)CD2INT(clientData);
|
||||||
int hierflags = 0;
|
|
||||||
|
bool stdcell = (flags & FLATNODE_STDCELL) ? TRUE : FALSE;
|
||||||
|
bool doWarn = (flags & FLATNODE_DOWARN) ? TRUE : FALSE;
|
||||||
|
|
||||||
if (flags & FLATNODE_NOABSTRACT)
|
if (flags & FLATNODE_NOABSTRACT)
|
||||||
{
|
{
|
||||||
|
|
@ -332,19 +332,13 @@ efFlatNodes(hc, clientData)
|
||||||
def->def_name);
|
def->def_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If called with FLATNODE_HIER set, then set the FLATNODE_CHILD
|
(void) efHierSrUses(hc, efFlatNodes, clientData);
|
||||||
* flag while calling efHierSrUses(), to prevent efAddNodes() from
|
|
||||||
* duplicating the capacitance of nodes in child cells.
|
|
||||||
*/
|
|
||||||
|
|
||||||
hierflags = flags | ((flags & FLATNODE_HIER) ? FLATNODE_CHILD : 0);
|
|
||||||
(void) efHierSrUses(hc, efFlatNodes, INT2CD(hierflags));
|
|
||||||
|
|
||||||
/* Add all our own nodes to the table */
|
/* Add all our own nodes to the table */
|
||||||
efAddNodes(hc, flags);
|
efAddNodes(hc, stdcell);
|
||||||
|
|
||||||
/* Process our own connections and adjustments */
|
/* Process our own connections and adjustments */
|
||||||
(void) efAddConns(hc, flags);
|
(void) efAddConns(hc, doWarn);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
@ -392,11 +386,11 @@ efFlatNodesStdCell(hc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add all our own nodes to the table */
|
/* Add all our own nodes to the table */
|
||||||
efAddNodes(hc, (int)FLATNODE_STDCELL);
|
efAddNodes(hc, TRUE);
|
||||||
|
|
||||||
/* Process our own connections and adjustments */
|
/* Process our own connections and adjustments */
|
||||||
if (!(hc->hc_use->use_def->def_flags & DEF_SUBCIRCUIT))
|
if (!(hc->hc_use->use_def->def_flags & DEF_SUBCIRCUIT))
|
||||||
(void) efAddConns(hc, (int)FLATNODE_DOWARN);
|
(void) efAddConns(hc, TRUE);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
@ -419,10 +413,10 @@ efFlatNodesDeviceless(hc, cdata)
|
||||||
if ((HashGetNumEntries(&hc->hc_use->use_def->def_devs) == 0) && (newcount == 0))
|
if ((HashGetNumEntries(&hc->hc_use->use_def->def_devs) == 0) && (newcount == 0))
|
||||||
{
|
{
|
||||||
/* Add all our own nodes to the table */
|
/* Add all our own nodes to the table */
|
||||||
efAddNodes(hc, (int)FLATNODE_STDCELL);
|
efAddNodes(hc, TRUE);
|
||||||
|
|
||||||
/* Process our own connections and adjustments */
|
/* 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 */
|
/* Mark this definition as having no devices, so it will not be visited */
|
||||||
hc->hc_use->use_def->def_flags |= DEF_NODEVICES;
|
hc->hc_use->use_def->def_flags |= DEF_NODEVICES;
|
||||||
|
|
@ -461,7 +455,7 @@ efFlatNodesDeviceless(hc, cdata)
|
||||||
int
|
int
|
||||||
efAddNodes(
|
efAddNodes(
|
||||||
HierContext *hc,
|
HierContext *hc,
|
||||||
int flags)
|
bool stdcell)
|
||||||
{
|
{
|
||||||
Def *def = hc->hc_use->use_def;
|
Def *def = hc->hc_use->use_def;
|
||||||
EFNodeName *nn, *newname, *oldname;
|
EFNodeName *nn, *newname, *oldname;
|
||||||
|
|
@ -471,8 +465,6 @@ efAddNodes(
|
||||||
HierName *hierName;
|
HierName *hierName;
|
||||||
int size, asize;
|
int size, asize;
|
||||||
HashEntry *he;
|
HashEntry *he;
|
||||||
bool stdcell = (flags & FLATNODE_STDCELL) ? TRUE : FALSE;
|
|
||||||
bool is_child = (flags & FLATNODE_CHILD) ? TRUE : FALSE;
|
|
||||||
bool is_subcircuit = (def->def_flags & DEF_SUBCIRCUIT) ? TRUE : FALSE;
|
bool is_subcircuit = (def->def_flags & DEF_SUBCIRCUIT) ? TRUE : FALSE;
|
||||||
|
|
||||||
size = sizeof (EFNode) + (efNumResistClasses-1) * sizeof (EFPerimArea);
|
size = sizeof (EFNode) + (efNumResistClasses-1) * sizeof (EFPerimArea);
|
||||||
|
|
@ -511,15 +503,12 @@ efAddNodes(
|
||||||
// If called with "hierarchy on", all local node caps and adjustments
|
// If called with "hierarchy on", all local node caps and adjustments
|
||||||
// have been output and should be ignored.
|
// have been output and should be ignored.
|
||||||
|
|
||||||
if (!stdcell && !is_child)
|
newnode->efnode_cap = (!stdcell) ? node->efnode_cap : (EFCapValue)0.0;
|
||||||
newnode->efnode_cap = node->efnode_cap;
|
|
||||||
else
|
|
||||||
newnode->efnode_cap = (EFCapValue)0.0;
|
|
||||||
newnode->efnode_client = (ClientData) NULL;
|
newnode->efnode_client = (ClientData) NULL;
|
||||||
newnode->efnode_flags = node->efnode_flags;
|
newnode->efnode_flags = node->efnode_flags;
|
||||||
newnode->efnode_type = node->efnode_type;
|
newnode->efnode_type = node->efnode_type;
|
||||||
newnode->efnode_num = 1;
|
newnode->efnode_num = 1;
|
||||||
if (!stdcell && !is_child)
|
if (!stdcell)
|
||||||
bcopy((char *) node->efnode_pa, (char *) newnode->efnode_pa,
|
bcopy((char *) node->efnode_pa, (char *) newnode->efnode_pa,
|
||||||
efNumResistClasses * sizeof (EFPerimArea));
|
efNumResistClasses * sizeof (EFPerimArea));
|
||||||
else
|
else
|
||||||
|
|
@ -612,7 +601,7 @@ efAddNodes(
|
||||||
int
|
int
|
||||||
efAddConns(
|
efAddConns(
|
||||||
HierContext *hc,
|
HierContext *hc,
|
||||||
int flags)
|
bool doWarn)
|
||||||
{
|
{
|
||||||
Connection *conn;
|
Connection *conn;
|
||||||
|
|
||||||
|
|
@ -625,9 +614,9 @@ efAddConns(
|
||||||
{
|
{
|
||||||
/* Special case for speed when no array info is present */
|
/* Special case for speed when no array info is present */
|
||||||
if (conn->conn_1.cn_nsubs == 0)
|
if (conn->conn_1.cn_nsubs == 0)
|
||||||
efAddOneConn(hc, conn->conn_name1, conn->conn_name2, conn, flags);
|
efAddOneConn(hc, conn->conn_name1, conn->conn_name2, conn, doWarn);
|
||||||
else
|
else
|
||||||
efHierSrArray(hc, conn, efAddOneConn, INT2CD(flags));
|
efHierSrArray(hc, conn, efAddOneConn, INT2CD(doWarn));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
@ -659,23 +648,18 @@ efAddOneConn(
|
||||||
char *name1, /* These are strings, not HierNames */
|
char *name1, /* These are strings, not HierNames */
|
||||||
char *name2,
|
char *name2,
|
||||||
Connection *conn,
|
Connection *conn,
|
||||||
int flags)
|
bool doWarn)
|
||||||
{
|
{
|
||||||
HashEntry *he1, *he2;
|
HashEntry *he1, *he2;
|
||||||
EFNode *node, *newnode;
|
EFNode *node, *newnode;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
bool doWarn = (flags & FLATNODE_DOWARN) ? TRUE : FALSE;
|
|
||||||
bool doHier = (flags & FLATNODE_HIER) ? TRUE : FALSE;
|
|
||||||
|
|
||||||
he1 = EFHNLook(hc->hc_hierName, name1, (doWarn) ? "connect(1)" : NULL);
|
he1 = EFHNLook(hc->hc_hierName, name1, (doWarn) ? "connect(1)" : NULL);
|
||||||
if (he1 == NULL)
|
if (he1 == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
node = ((EFNodeName *) HashGetValue(he1))->efnn_node;
|
|
||||||
|
|
||||||
/* Adjust the resistance and capacitance of its corresponding node */
|
/* Adjust the resistance and capacitance of its corresponding node */
|
||||||
|
node = ((EFNodeName *) HashGetValue(he1))->efnn_node;
|
||||||
node->efnode_cap += conn->conn_cap;
|
node->efnode_cap += conn->conn_cap;
|
||||||
for (n = 0; n < efNumResistClasses; n++)
|
for (n = 0; n < efNumResistClasses; n++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -82,12 +82,6 @@ extern void efHNRecord();
|
||||||
* variables cause nets named VDD and GND to become globals, which was
|
* variables cause nets named VDD and GND to become globals, which was
|
||||||
* not intended.
|
* not intended.
|
||||||
*
|
*
|
||||||
* Updated 1/2026: Also seems like a bad idea to treat the suffix "!"
|
|
||||||
* automatically as a global. By removing this, a global pin must be
|
|
||||||
* manually declared by putting it in the "globals" array variable.
|
|
||||||
* When not compiled with Tcl/Tk support, the original behavior is
|
|
||||||
* implemented.
|
|
||||||
*
|
|
||||||
* Results:
|
* Results:
|
||||||
* TRUE if the name is a global.
|
* TRUE if the name is a global.
|
||||||
*
|
*
|
||||||
|
|
@ -105,10 +99,12 @@ EFHNIsGlob(hierName)
|
||||||
char *retstr;
|
char *retstr;
|
||||||
retstr = (char *)Tcl_GetVar2(magicinterp, "globals", hierName->hn_name,
|
retstr = (char *)Tcl_GetVar2(magicinterp, "globals", hierName->hn_name,
|
||||||
TCL_GLOBAL_ONLY);
|
TCL_GLOBAL_ONLY);
|
||||||
return (retstr != NULL) ? TRUE : FALSE;
|
if (retstr != NULL) return TRUE;
|
||||||
#else
|
|
||||||
return hierName->hn_name[strlen(hierName->hn_name) - 1] == '!';
|
// retstr = (char *)Tcl_GetVar(magicinterp, hierName->hn_name, TCL_GLOBAL_ONLY);
|
||||||
|
// if (retstr != NULL) return TRUE;
|
||||||
#endif
|
#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];
|
last1 = hierName1->hn_name[strlen(hierName1->hn_name) - 1];
|
||||||
last2 = hierName2->hn_name[strlen(hierName2->hn_name) - 1];
|
last2 = hierName2->hn_name[strlen(hierName2->hn_name) - 1];
|
||||||
|
|
||||||
if (last1 != '!' || last2 != '!')
|
if (last1 != '!' || last2 != '!')
|
||||||
{
|
{
|
||||||
#if 0
|
|
||||||
/* NOTE (Jan. 31, 2026): The handling of trailing "!" as a global
|
|
||||||
* is at best incorrect; the node output should not consider the
|
|
||||||
* ancestor hierarchy, but it does. I am disabling the check here,
|
|
||||||
* and treating all names as local. It could be reinstated, but
|
|
||||||
* I think global names are just a bad idea altogether.
|
|
||||||
*/
|
|
||||||
/* Prefer global over local names */
|
/* Prefer global over local names */
|
||||||
if (last1 == '!') return TRUE;
|
if (last1 == '!') return TRUE;
|
||||||
if (last2 == '!') return FALSE;
|
if (last2 == '!') return FALSE;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Neither name is global, so choose label over generated name */
|
/* Neither name is global, so chose label over generated name */
|
||||||
if (last1 != '#' && last2 == '#') return TRUE;
|
if (last1 != '#' && last2 == '#') return TRUE;
|
||||||
if (last1 == '#' && last2 != '#') return FALSE;
|
if (last1 == '#' && last2 != '#') return FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,8 +86,6 @@ typedef struct /* Position of each terminal (below) tile position */
|
||||||
{
|
{
|
||||||
int pnum;
|
int pnum;
|
||||||
Point pt;
|
Point pt;
|
||||||
Tile *tile; /* Any tile beloging to the terminal */
|
|
||||||
TileType type; /* Type of "tile", including split information */
|
|
||||||
} TermTilePos;
|
} TermTilePos;
|
||||||
|
|
||||||
/* Field definitions for tr_devmatch */
|
/* Field definitions for tr_devmatch */
|
||||||
|
|
@ -150,7 +148,6 @@ int extTransTileFunc();
|
||||||
int extTransPerimFunc();
|
int extTransPerimFunc();
|
||||||
int extTransFindSubs();
|
int extTransFindSubs();
|
||||||
int extTransFindId();
|
int extTransFindId();
|
||||||
void extTermAPFunc();
|
|
||||||
|
|
||||||
int extAnnularTileFunc();
|
int extAnnularTileFunc();
|
||||||
int extResistorTileFunc();
|
int extResistorTileFunc();
|
||||||
|
|
@ -326,7 +323,7 @@ extBasic(def, outFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for "device", as it modifies handling of parasitics */
|
/* Check for "device", as it modifies handling of parasitics */
|
||||||
propptr = DBPropGetString(def, "device", &propfound);
|
propptr = (char *)DBPropGet(def, "device", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
/* Remove parasitics from local nodes */
|
/* Remove parasitics from local nodes */
|
||||||
|
|
@ -802,34 +799,14 @@ extOutputNodes(nodeList, outFile)
|
||||||
lastname = ll->ll_label->lab_text;
|
lastname = ll->ll_label->lab_text;
|
||||||
}
|
}
|
||||||
/* Don't print a warning unless both labels are
|
/* Don't print a warning unless both labels are
|
||||||
* really ports. Also, don't print a warning for
|
* really ports.
|
||||||
* names generated by "extract unique" vs. real
|
|
||||||
* pin names or another unique name---"extract
|
|
||||||
* unique" does not observe where nets pass through
|
|
||||||
* subcircuits, so it tends to over-generated
|
|
||||||
* unique names, which "ext2spice" will filter out.
|
|
||||||
* For a net to be shorted to itself is not an error.
|
|
||||||
* NOTE: Potentially the unique name could be removed
|
|
||||||
* here and save ext2spice the trouble.
|
|
||||||
*/
|
*/
|
||||||
if ((portname != NULL) &&
|
if ((portname != NULL) &&
|
||||||
(ll->ll_attr == LL_PORTATTR) &&
|
(ll->ll_attr == LL_PORTATTR) &&
|
||||||
(strcmp(ll->ll_label->lab_text, portname)))
|
(strcmp(ll->ll_label->lab_text, portname)))
|
||||||
{
|
|
||||||
char *uptr1, *uptr2;
|
|
||||||
uptr1 = strstr(text, "_uq");
|
|
||||||
uptr2 = strstr(ll->ll_label->lab_text, "_uq");
|
|
||||||
if (uptr1) *uptr1 = '\0';
|
|
||||||
if (uptr2) *uptr2 = '\0';
|
|
||||||
if (strcmp(text, ll->ll_label->lab_text))
|
|
||||||
{
|
|
||||||
TxError("Warning: Ports \"%s\" and \"%s\" are"
|
TxError("Warning: Ports \"%s\" and \"%s\" are"
|
||||||
" electrically shorted.\n",
|
" electrically shorted.\n",
|
||||||
text, ll->ll_label->lab_text);
|
text, ll->ll_label->lab_text);
|
||||||
}
|
|
||||||
if (uptr1) *uptr1 = '_';
|
|
||||||
if (uptr2) *uptr2 = '_';
|
|
||||||
}
|
|
||||||
if (!isPort && (ll->ll_attr == LL_PORTATTR))
|
if (!isPort && (ll->ll_attr == LL_PORTATTR))
|
||||||
portname = ll->ll_label->lab_text;
|
portname = ll->ll_label->lab_text;
|
||||||
}
|
}
|
||||||
|
|
@ -1702,7 +1679,7 @@ extOutputParameters(def, transList, outFile)
|
||||||
* and device name, and if detected, add the type corresponding to the
|
* and device name, and if detected, add the type corresponding to the
|
||||||
* device name to the mask so it gets handled, too.
|
* device name to the mask so it gets handled, too.
|
||||||
*/
|
*/
|
||||||
propptr = DBPropGetString(def, "device", &propfound);
|
propptr = DBPropGet(def, "device", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
char *devname;
|
char *devname;
|
||||||
|
|
@ -1835,8 +1812,6 @@ extOutputDevParams(reg, devptr, outFile, length, width, areavec, perimvec)
|
||||||
ParamList *chkParam;
|
ParamList *chkParam;
|
||||||
HashEntry *he;
|
HashEntry *he;
|
||||||
ResValue resvalue;
|
ResValue resvalue;
|
||||||
LabRegion *node; /* Node connected to gate terminal */
|
|
||||||
LabelList *ll; /* Gate's label list */
|
|
||||||
|
|
||||||
for (chkParam = devptr->exts_deviceParams; chkParam
|
for (chkParam = devptr->exts_deviceParams; chkParam
|
||||||
!= NULL; chkParam = chkParam->pl_next)
|
!= NULL; chkParam = chkParam->pl_next)
|
||||||
|
|
@ -1968,34 +1943,6 @@ extOutputDevParams(reg, devptr, outFile, length, width, areavec, perimvec)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there are device attribute labels (labels attached to the device
|
|
||||||
* type ending with "^") with "=" in them, then treat them as extra
|
|
||||||
* parameters. Output each one and remove the gate attribute property
|
|
||||||
* from the label.
|
|
||||||
*/
|
|
||||||
|
|
||||||
node = (LabRegion *)ExtGetRegion(reg->treg_tile, reg->treg_dinfo);
|
|
||||||
for (ll = node->lreg_labels; ll; ll = ll->ll_next)
|
|
||||||
{
|
|
||||||
if (ll->ll_attr == LL_GATEATTR)
|
|
||||||
{
|
|
||||||
char cs, *ct, *cp = ll->ll_label->lab_text;
|
|
||||||
if (strchr(cp, '=') != NULL)
|
|
||||||
{
|
|
||||||
/* Since this is an attribute label, it has a special character
|
|
||||||
* at the end, which needs to be stripped off while printing
|
|
||||||
* and then put back again.
|
|
||||||
*/
|
|
||||||
ct = ll->ll_label->lab_text + strlen(ll->ll_label->lab_text) - 1;
|
|
||||||
cs = *ct;
|
|
||||||
*ct = '\0';
|
|
||||||
fprintf(outFile, " %s", ll->ll_label->lab_text);
|
|
||||||
ll->ll_attr = LL_NOATTR;
|
|
||||||
*ct = cs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Structures used by extTermAPFunc() for storing area and perimeter data */
|
/* Structures used by extTermAPFunc() for storing area and perimeter data */
|
||||||
|
|
@ -2222,6 +2169,8 @@ extTransFindTermArea(tile, dinfo, eapd)
|
||||||
TileType dinfo;
|
TileType dinfo;
|
||||||
ExtAreaPerimData *eapd;
|
ExtAreaPerimData *eapd;
|
||||||
{
|
{
|
||||||
|
void extTermAPFunc(); /* Forward declaration */
|
||||||
|
|
||||||
extEnumTerminal(tile, dinfo, DBConnectTbl, extTermAPFunc, (ClientData)eapd);
|
extEnumTerminal(tile, dinfo, DBConnectTbl, extTermAPFunc, (ClientData)eapd);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -2309,8 +2258,6 @@ extOutputDevices(def, transList, outFile)
|
||||||
extTransRec.tr_termpos[i].pnum = 0;
|
extTransRec.tr_termpos[i].pnum = 0;
|
||||||
extTransRec.tr_termpos[i].pt.p_x = 0;
|
extTransRec.tr_termpos[i].pt.p_x = 0;
|
||||||
extTransRec.tr_termpos[i].pt.p_y = 0;
|
extTransRec.tr_termpos[i].pt.p_y = 0;
|
||||||
extTransRec.tr_termpos[i].tile = NULL;
|
|
||||||
extTransRec.tr_termpos[i].type = TT_SPACE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
arg.fra_def = def;
|
arg.fra_def = def;
|
||||||
|
|
@ -2335,58 +2282,6 @@ extOutputDevices(def, transList, outFile)
|
||||||
arg.fra_each = extTransTileFunc;
|
arg.fra_each = extTransTileFunc;
|
||||||
ntiles = ExtFindNeighbors(reg->treg_tile, reg->treg_dinfo, arg.fra_pNum, &arg);
|
ntiles = ExtFindNeighbors(reg->treg_tile, reg->treg_dinfo, arg.fra_pNum, &arg);
|
||||||
|
|
||||||
/* Once the entire device has been marked with the device region,
|
|
||||||
* replacing the node region, search each terminal to determine
|
|
||||||
* if the terminal is shared by multiple devices. Note that this
|
|
||||||
* algorithm is not foolproof: In the rare case that three or more
|
|
||||||
* devices share the same terminal, and more than one of them have
|
|
||||||
* the same gate, then those gates will have the same node record and
|
|
||||||
* will not be seen as individual devices.
|
|
||||||
*/
|
|
||||||
|
|
||||||
for (i = 0; i < MAXSD; i++)
|
|
||||||
{
|
|
||||||
Tile *termtile = extTransRec.tr_termpos[i].tile;
|
|
||||||
if (termtile != NULL)
|
|
||||||
{
|
|
||||||
/* Find the area and perimeter of the terminal area (connected
|
|
||||||
* area outside the boundary on a single plane). Note that
|
|
||||||
* this does not consider terminal area outside of the cell
|
|
||||||
* or how area or perimeter may be shared or overlap between
|
|
||||||
* devices.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int shared;
|
|
||||||
ExtAreaPerimData eapd;
|
|
||||||
TileType termtype = extTransRec.tr_termpos[i].type;
|
|
||||||
|
|
||||||
eapd.eapd_area = eapd.eapd_perim = 0;
|
|
||||||
TTMaskCom2(&eapd.eapd_mask, &DBConnectTbl[termtype & TT_LEFTMASK]);
|
|
||||||
eapd.eapd_gatemask = &ExtCurStyle->exts_deviceMask;
|
|
||||||
eapd.eapd_gatenode = (NodeRegion *)reg;
|
|
||||||
eapd.eapd_shared = NULL;
|
|
||||||
|
|
||||||
extEnumTerminal(termtile,
|
|
||||||
termtype & (TT_DIAGONAL | TT_SIDE | TT_DIRECTION),
|
|
||||||
DBConnectTbl, extTermAPFunc,
|
|
||||||
(ClientData)&eapd);
|
|
||||||
|
|
||||||
shared = 1; /* Count self since we divide by "shared" */
|
|
||||||
free_magic1_t mm1 = freeMagic1_init();
|
|
||||||
while (eapd.eapd_shared)
|
|
||||||
{
|
|
||||||
shared++;
|
|
||||||
freeMagic1(&mm1, eapd.eapd_shared);
|
|
||||||
eapd.eapd_shared = eapd.eapd_shared->nl_next;
|
|
||||||
}
|
|
||||||
freeMagic1_end(&mm1);
|
|
||||||
|
|
||||||
extTransRec.tr_termarea[i] = eapd.eapd_area;
|
|
||||||
extTransRec.tr_termperim[i] = eapd.eapd_perim;
|
|
||||||
extTransRec.tr_termshared[i] = shared;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Re-mark with extTransRec.tr_gatenode */
|
/* Re-mark with extTransRec.tr_gatenode */
|
||||||
arg.fra_uninit = (ClientData) reg;
|
arg.fra_uninit = (ClientData) reg;
|
||||||
arg.fra_region = (ExtRegion *) extTransRec.tr_gatenode;
|
arg.fra_region = (ExtRegion *) extTransRec.tr_gatenode;
|
||||||
|
|
@ -4017,11 +3912,8 @@ extTransPerimFunc(bp)
|
||||||
extTransRec.tr_termvector[thisterm].p_y = 0;
|
extTransRec.tr_termvector[thisterm].p_y = 0;
|
||||||
extTransRec.tr_termpos[thisterm].pnum = DBPlane(toutside);
|
extTransRec.tr_termpos[thisterm].pnum = DBPlane(toutside);
|
||||||
extTransRec.tr_termpos[thisterm].pt = bp->b_outside->ti_ll;
|
extTransRec.tr_termpos[thisterm].pt = bp->b_outside->ti_ll;
|
||||||
/* tile and dinfo need only be one valid terminal tile,
|
|
||||||
* and do not need to be updated.
|
/* Find the total area of this terminal */
|
||||||
*/
|
|
||||||
extTransRec.tr_termpos[thisterm].tile = bp->b_outside;
|
|
||||||
extTransRec.tr_termpos[thisterm].type = dinfo | toutside;
|
|
||||||
}
|
}
|
||||||
else if (extTransRec.tr_termnode[thisterm] == termNode)
|
else if (extTransRec.tr_termnode[thisterm] == termNode)
|
||||||
{
|
{
|
||||||
|
|
@ -4053,6 +3945,42 @@ extTransPerimFunc(bp)
|
||||||
/* Add the length to this terminal's perimeter */
|
/* Add the length to this terminal's perimeter */
|
||||||
extTransRec.tr_termlen[thisterm] += len;
|
extTransRec.tr_termlen[thisterm] += len;
|
||||||
|
|
||||||
|
if (extTransRec.tr_termarea[thisterm] == 0)
|
||||||
|
{
|
||||||
|
/* Find the area and perimeter of the terminal area (connected
|
||||||
|
* area outside the boundary on a single plane). Note that
|
||||||
|
* this does not consider terminal area outside of the cell
|
||||||
|
* or how area or perimeter may be shared or overlap between
|
||||||
|
* devices.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ExtAreaPerimData eapd;
|
||||||
|
int shared;
|
||||||
|
|
||||||
|
eapd.eapd_area = eapd.eapd_perim = 0;
|
||||||
|
TTMaskCom2(&eapd.eapd_mask, &DBConnectTbl[toutside]);
|
||||||
|
eapd.eapd_gatemask = &ExtCurStyle->exts_deviceMask;
|
||||||
|
eapd.eapd_gatenode = extTransRec.tr_gatenode;
|
||||||
|
eapd.eapd_shared = NULL;
|
||||||
|
|
||||||
|
extEnumTerminal(bp->b_outside, dinfo, DBConnectTbl,
|
||||||
|
extTermAPFunc, (ClientData)&eapd);
|
||||||
|
|
||||||
|
shared = 0;
|
||||||
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
|
while (eapd.eapd_shared)
|
||||||
|
{
|
||||||
|
shared++;
|
||||||
|
freeMagic1(&mm1, eapd.eapd_shared);
|
||||||
|
eapd.eapd_shared = eapd.eapd_shared->nl_next;
|
||||||
|
}
|
||||||
|
freeMagic1_end(&mm1);
|
||||||
|
|
||||||
|
extTransRec.tr_termarea[thisterm] = eapd.eapd_area;
|
||||||
|
extTransRec.tr_termperim[thisterm] = eapd.eapd_perim;
|
||||||
|
extTransRec.tr_termshared[thisterm] = shared;
|
||||||
|
}
|
||||||
|
|
||||||
/* Update the boundary traversal vector */
|
/* Update the boundary traversal vector */
|
||||||
switch(bp->b_direction) {
|
switch(bp->b_direction) {
|
||||||
case BD_LEFT:
|
case BD_LEFT:
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
#include "extract/extract.h"
|
#include "extract/extract.h"
|
||||||
#include "extract/extractInt.h"
|
#include "extract/extractInt.h"
|
||||||
|
#include "resis/resis.h"
|
||||||
#include "utils/signals.h"
|
#include "utils/signals.h"
|
||||||
#include "utils/stack.h"
|
#include "utils/stack.h"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
|
|
@ -50,6 +51,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
int extOutputUsesFunc();
|
int extOutputUsesFunc();
|
||||||
|
FILE *extFileOpen();
|
||||||
|
|
||||||
Plane* extCellFile();
|
Plane* extCellFile();
|
||||||
void extHeader();
|
void extHeader();
|
||||||
|
|
@ -95,7 +97,7 @@ ExtCell(def, outName, doLength)
|
||||||
if (def->cd_flags & CDNOEXTRACT)
|
if (def->cd_flags & CDNOEXTRACT)
|
||||||
return extPrepSubstrate(def);
|
return extPrepSubstrate(def);
|
||||||
|
|
||||||
f = ExtFileOpen(def, outName, "w", &filename);
|
f = extFileOpen(def, outName, "w", &filename);
|
||||||
|
|
||||||
TxPrintf("Extracting %s into %s:\n", def->cd_name, filename);
|
TxPrintf("Extracting %s into %s:\n", def->cd_name, filename);
|
||||||
|
|
||||||
|
|
@ -114,6 +116,25 @@ ExtCell(def, outName, doLength)
|
||||||
savePlane = extCellFile(def, f, doLength);
|
savePlane = extCellFile(def, f, doLength);
|
||||||
if (f != NULL) fclose(f);
|
if (f != NULL) fclose(f);
|
||||||
|
|
||||||
|
/* Integrated extresist --- Run "extresist" on the cell def just
|
||||||
|
* extracted and produce an annotation file "<file>.res.ext".
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (ExtOptions & EXT_DOEXTRESIST)
|
||||||
|
{
|
||||||
|
ResisData *resisdata = ResInit();
|
||||||
|
|
||||||
|
UndoDisable();
|
||||||
|
|
||||||
|
ResOptionsFlags |= ResOpt_Signal;
|
||||||
|
resisdata->mainDef = def;
|
||||||
|
resisdata->savePlanes = (struct saveList *)NULL; /* unused */
|
||||||
|
|
||||||
|
ExtResisForDef(def, resisdata);
|
||||||
|
|
||||||
|
UndoEnable();
|
||||||
|
}
|
||||||
|
|
||||||
if (extNumErrors > 0 || extNumWarnings > 0)
|
if (extNumErrors > 0 || extNumWarnings > 0)
|
||||||
{
|
{
|
||||||
TxPrintf("%s:", def->cd_name);
|
TxPrintf("%s:", def->cd_name);
|
||||||
|
|
@ -131,7 +152,7 @@ ExtCell(def, outName, doLength)
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* ExtFileOpen --
|
* extFileOpen --
|
||||||
*
|
*
|
||||||
* Open the .ext file corresponding to a .mag file.
|
* Open the .ext file corresponding to a .mag file.
|
||||||
* If def->cd_file is non-NULL, the .ext file is just def->cd_file with
|
* If def->cd_file is non-NULL, the .ext file is just def->cd_file with
|
||||||
|
|
@ -149,7 +170,7 @@ ExtCell(def, outName, doLength)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FILE *
|
FILE *
|
||||||
ExtFileOpen(def, file, mode, prealfile)
|
extFileOpen(def, file, mode, prealfile)
|
||||||
CellDef *def; /* Cell whose .ext file is to be written */
|
CellDef *def; /* Cell whose .ext file is to be written */
|
||||||
char *file; /* If non-NULL, open 'name'.ext; otherwise,
|
char *file; /* If non-NULL, open 'name'.ext; otherwise,
|
||||||
* derive filename from 'def' as described
|
* derive filename from 'def' as described
|
||||||
|
|
@ -594,7 +615,7 @@ extHeader(def, f)
|
||||||
/* are to be passed to instances of the cell */
|
/* are to be passed to instances of the cell */
|
||||||
/* (created by defining property "parameter") */
|
/* (created by defining property "parameter") */
|
||||||
|
|
||||||
propvalue = DBPropGetString(def, "parameter", &propfound);
|
propvalue = (char *)DBPropGet(def, "parameter", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
// Use device parameter table to store the cell def parameters,
|
// Use device parameter table to store the cell def parameters,
|
||||||
|
|
|
||||||
|
|
@ -1289,14 +1289,6 @@ extFindOverlap(tp, area, esws)
|
||||||
TileType tin = TiGetType(bp->b_inside);
|
TileType tin = TiGetType(bp->b_inside);
|
||||||
TileType tout = TiGetType(bp->b_outside);
|
TileType tout = TiGetType(bp->b_outside);
|
||||||
|
|
||||||
/* Get residues
|
|
||||||
* (Note: Isn't it better to include contacts in the tables?)
|
|
||||||
*/
|
|
||||||
if (DBIsContact(tin))
|
|
||||||
tin = DBPlaneToResidue(tin, esws->plane_of_boundary);
|
|
||||||
if (DBIsContact(tout))
|
|
||||||
tout = DBPlaneToResidue(tout, esws->plane_of_boundary);
|
|
||||||
|
|
||||||
pMask = ExtCurStyle->exts_sideOverlapOtherPlanes[tin][tout];
|
pMask = ExtCurStyle->exts_sideOverlapOtherPlanes[tin][tout];
|
||||||
extOverlapDef = esws->def;
|
extOverlapDef = esws->def;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -354,8 +354,8 @@ extHierConnections(ha, cumFlat, oneFlat)
|
||||||
if (!(lab->lab_flags & LABEL_STICKY)) continue;
|
if (!(lab->lab_flags & LABEL_STICKY)) continue;
|
||||||
|
|
||||||
r = lab->lab_rect;
|
r = lab->lab_rect;
|
||||||
if (!GEO_TOUCH(&r, &ha->ha_subArea)) continue;
|
|
||||||
GEOCLIP(&r, &ha->ha_subArea);
|
GEOCLIP(&r, &ha->ha_subArea);
|
||||||
|
if (GEO_RECTNULL(&r)) continue;
|
||||||
|
|
||||||
cumDef = cumFlat->et_use->cu_def;
|
cumDef = cumFlat->et_use->cu_def;
|
||||||
connected = &DBConnectTbl[lab->lab_type];
|
connected = &DBConnectTbl[lab->lab_type];
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "debug/debug.h"
|
#include "debug/debug.h"
|
||||||
#include "extract/extract.h"
|
#include "extract/extract.h"
|
||||||
#include "extract/extractInt.h"
|
#include "extract/extractInt.h"
|
||||||
#include "resis/resis.h"
|
|
||||||
#include "utils/signals.h"
|
#include "utils/signals.h"
|
||||||
#include "utils/stack.h"
|
#include "utils/stack.h"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
|
|
@ -44,6 +43,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "utils/main.h"
|
#include "utils/main.h"
|
||||||
#include "utils/undo.h"
|
#include "utils/undo.h"
|
||||||
|
|
||||||
|
/* Imports from elsewhere in this module */
|
||||||
|
extern FILE *extFileOpen();
|
||||||
|
|
||||||
/* ------------------------ Exported variables ------------------------ */
|
/* ------------------------ Exported variables ------------------------ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -81,6 +83,16 @@ typedef struct _linkedDef {
|
||||||
struct _linkedDef *ld_next;
|
struct _linkedDef *ld_next;
|
||||||
} LinkedDef;
|
} LinkedDef;
|
||||||
|
|
||||||
|
/* Linked list structure to use to store the substrate plane from each */
|
||||||
|
/* extracted CellDef so that they can be returned to the original after */
|
||||||
|
/* extraction. */
|
||||||
|
|
||||||
|
struct saveList {
|
||||||
|
Plane *sl_plane;
|
||||||
|
CellDef *sl_def;
|
||||||
|
struct saveList *sl_next;
|
||||||
|
};
|
||||||
|
|
||||||
/* Stack of defs pending extraction */
|
/* Stack of defs pending extraction */
|
||||||
Stack *extDefStack;
|
Stack *extDefStack;
|
||||||
|
|
||||||
|
|
@ -794,23 +806,6 @@ ExtractOneCell(def, outName, doLength)
|
||||||
|
|
||||||
savePlane = ExtCell(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 and modified labels */
|
||||||
|
|
||||||
if (savePlane != NULL) ExtRevertSubstrate(def, savePlane);
|
if (savePlane != NULL) ExtRevertSubstrate(def, savePlane);
|
||||||
|
|
@ -950,7 +945,7 @@ extTimestampMisMatch(def)
|
||||||
|
|
||||||
doLocal = (ExtLocalPath == NULL) ? FALSE : TRUE;
|
doLocal = (ExtLocalPath == NULL) ? FALSE : TRUE;
|
||||||
|
|
||||||
extFile = ExtFileOpen(def, (char *) NULL, "r", (char **) NULL);
|
extFile = extFileOpen(def, (char *) NULL, "r", (char **) NULL);
|
||||||
if (extFile == NULL)
|
if (extFile == NULL)
|
||||||
return (TRUE);
|
return (TRUE);
|
||||||
|
|
||||||
|
|
@ -996,18 +991,10 @@ extExtractStack(stack, doExtract, rootDef)
|
||||||
bool first = TRUE;
|
bool first = TRUE;
|
||||||
Plane *savePlane;
|
Plane *savePlane;
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
LinkedDef *savelist = NULL, *revlist = NULL, *newld;
|
|
||||||
struct saveList *newsl, *sl = (struct saveList *)NULL;
|
struct saveList *newsl, *sl = (struct saveList *)NULL;
|
||||||
|
|
||||||
while ((def = (CellDef *) StackPop(stack)))
|
while ((def = (CellDef *) StackPop(stack)))
|
||||||
{
|
{
|
||||||
if (ExtOptions & EXT_DOEXTRESIST)
|
|
||||||
{
|
|
||||||
newld = (LinkedDef *)mallocMagic(sizeof(LinkedDef));
|
|
||||||
newld->ld_def = def;
|
|
||||||
newld->ld_next = savelist;
|
|
||||||
savelist = newld;
|
|
||||||
}
|
|
||||||
def->cd_client = (ClientData) 0;
|
def->cd_client = (ClientData) 0;
|
||||||
if (!SigInterruptPending)
|
if (!SigInterruptPending)
|
||||||
{
|
{
|
||||||
|
|
@ -1040,44 +1027,6 @@ extExtractStack(stack, doExtract, rootDef)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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 and modified labels */
|
||||||
free_magic1_t mm1 = freeMagic1_init();
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (; sl; sl = sl->sl_next)
|
for (; sl; sl = sl->sl_next)
|
||||||
|
|
|
||||||
|
|
@ -614,7 +614,6 @@ termtop:
|
||||||
|
|
||||||
termdone:
|
termdone:
|
||||||
/* (continue) */
|
/* (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
|
/* Clean up---Put the ClientData entries in the tiles back to
|
||||||
|
|
|
||||||
|
|
@ -251,17 +251,6 @@ extSubtree(parentUse, reg, f)
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
/* If result == FALSE then ha.ha_interArea is invalid. */
|
/* If result == FALSE then ha.ha_interArea is invalid. */
|
||||||
ha.ha_interArea = rlab;
|
ha.ha_interArea = rlab;
|
||||||
/* Ensure that the interaction area is not zero */
|
|
||||||
if (ha.ha_interArea.r_xtop - ha.ha_interArea.r_xbot == 0)
|
|
||||||
{
|
|
||||||
ha.ha_interArea.r_xtop++;
|
|
||||||
ha.ha_interArea.r_xbot--;
|
|
||||||
}
|
|
||||||
if (ha.ha_interArea.r_ytop - ha.ha_interArea.r_ybot == 0)
|
|
||||||
{
|
|
||||||
ha.ha_interArea.r_ytop++;
|
|
||||||
ha.ha_interArea.r_ybot--;
|
|
||||||
}
|
|
||||||
result = 1;
|
result = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -790,7 +779,6 @@ extSubtreeFunc(scx, ha)
|
||||||
*/
|
*/
|
||||||
ha->ha_subArea = use->cu_bbox;
|
ha->ha_subArea = use->cu_bbox;
|
||||||
GEOCLIP(&ha->ha_subArea, &ha->ha_interArea);
|
GEOCLIP(&ha->ha_subArea, &ha->ha_interArea);
|
||||||
|
|
||||||
hy.hy_area = &ha->ha_subArea;
|
hy.hy_area = &ha->ha_subArea;
|
||||||
hy.hy_target = oneFlat->et_use;
|
hy.hy_target = oneFlat->et_use;
|
||||||
hy.hy_prefix = TRUE;
|
hy.hy_prefix = TRUE;
|
||||||
|
|
|
||||||
|
|
@ -1368,7 +1368,7 @@ ExtTechSimplePerimCap(argc, argv)
|
||||||
|
|
||||||
if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1376,14 +1376,9 @@ ExtTechSimplePerimCap(argc, argv)
|
||||||
TTMaskSetMask(allExtractTypes, &types);
|
TTMaskSetMask(allExtractTypes, &types);
|
||||||
plane1 = DBTechNoisyNamePlane(argv[2]);
|
plane1 = DBTechNoisyNamePlane(argv[2]);
|
||||||
|
|
||||||
/* As part of the "simple perimeter" simplifications, "nottypes" can
|
TTMaskCom2(¬types, &types);
|
||||||
* only be space. This prevents perimeter edges from being seen
|
|
||||||
* between, e.g., poly and transistor gates, or metal and metal
|
|
||||||
* resistors.
|
|
||||||
*/
|
|
||||||
TTMaskSetOnlyType(¬types, TT_SPACE);
|
|
||||||
|
|
||||||
TTMaskAndMask(&types, &DBPlaneTypes[plane1]);
|
TTMaskAndMask(&types, &DBPlaneTypes[plane1]);
|
||||||
|
TTMaskAndMask(¬types, &DBPlaneTypes[plane1]);
|
||||||
|
|
||||||
capVal = aToCap(argv[argc - 1]);
|
capVal = aToCap(argv[argc - 1]);
|
||||||
|
|
||||||
|
|
@ -1637,7 +1632,7 @@ ExtTechSimpleOverlapCap(argv)
|
||||||
|
|
||||||
if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1737,7 +1732,7 @@ ExtTechSimpleSideOverlapCap(argv)
|
||||||
|
|
||||||
if (ExtCurStyle->exts_planeOrderStatus != seenPlaneOrder)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1745,14 +1740,9 @@ ExtTechSimpleSideOverlapCap(argv)
|
||||||
TTMaskSetMask(allExtractTypes, &types);
|
TTMaskSetMask(allExtractTypes, &types);
|
||||||
plane1 = DBTechNoisyNamePlane(argv[2]);
|
plane1 = DBTechNoisyNamePlane(argv[2]);
|
||||||
|
|
||||||
/* As part of the "simple sideoverlap" simplifications, "nottypes"
|
TTMaskCom2(¬types, &types);
|
||||||
* can only be space. This prevents perimeter edges from being
|
|
||||||
* seen between, e.g., poly and transistor gates, or metal and
|
|
||||||
* metal resistors.
|
|
||||||
*/
|
|
||||||
TTMaskSetOnlyType(¬types, TT_SPACE);
|
|
||||||
|
|
||||||
TTMaskAndMask(&types, &DBPlaneTypes[plane1]);
|
TTMaskAndMask(&types, &DBPlaneTypes[plane1]);
|
||||||
|
TTMaskAndMask(¬types, &DBPlaneTypes[plane1]);
|
||||||
|
|
||||||
DBTechNoisyNameMask(argv[3], &ov);
|
DBTechNoisyNameMask(argv[3], &ov);
|
||||||
TTMaskSetMask(allExtractTypes, &ov);
|
TTMaskSetMask(allExtractTypes, &ov);
|
||||||
|
|
|
||||||
|
|
@ -113,8 +113,6 @@ extern void ExtDumpCaps();
|
||||||
|
|
||||||
extern int extEnumTilePerim(Tile *tpIn, TileType dinfo, const TileTypeBitMask *maskp, int pNum, int (*func)(), ClientData cdata);
|
extern int extEnumTilePerim(Tile *tpIn, TileType dinfo, const TileTypeBitMask *maskp, int pNum, int (*func)(), ClientData cdata);
|
||||||
extern Plane *extPrepSubstrate();
|
extern Plane *extPrepSubstrate();
|
||||||
extern FILE *ExtFileOpen(CellDef *def, char *file, char *mode, char **prealfile);
|
|
||||||
|
|
||||||
|
|
||||||
/* C99 compat */
|
/* C99 compat */
|
||||||
extern void ExtAll();
|
extern void ExtAll();
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "utils/hash.h"
|
#include "utils/hash.h"
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "windows/windows.h"
|
#include "windows/windows.h"
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "graphics/graphics.h"
|
#include "graphics/graphics.h"
|
||||||
#include "windows/windows.h"
|
#include "windows/windows.h"
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "graphics/graphics.h"
|
#include "graphics/graphics.h"
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
#include "utils/main.h"
|
#include "utils/main.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "utils/malloc.h"
|
#include "utils/malloc.h"
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "windows/windows.h"
|
#include "windows/windows.h"
|
||||||
#include "graphics/graphics.h"
|
#include "graphics/graphics.h"
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include "tcltk/tclmagic.h"
|
#include "tcltk/tclmagic.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "windows/windows.h"
|
#include "windows/windows.h"
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
#include "utils/main.h"
|
#include "utils/main.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "utils/malloc.h"
|
#include "utils/malloc.h"
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "windows/windows.h"
|
#include "windows/windows.h"
|
||||||
#include "graphics/graphics.h"
|
#include "graphics/graphics.h"
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "tcltk/tclmagic.h"
|
#include "tcltk/tclmagic.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "windows/windows.h"
|
#include "windows/windows.h"
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
#include "utils/main.h"
|
#include "utils/main.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "utils/malloc.h"
|
#include "utils/malloc.h"
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "windows/windows.h"
|
#include "windows/windows.h"
|
||||||
#include "graphics/graphics.h"
|
#include "graphics/graphics.h"
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
#include "tcltk/tclmagic.h"
|
#include "tcltk/tclmagic.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "windows/windows.h"
|
#include "windows/windows.h"
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#include <X11/Xutil.h>
|
#include <X11/Xutil.h>
|
||||||
|
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "textio/txcommands.h"
|
#include "textio/txcommands.h"
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "graphics/graphics.h"
|
#include "graphics/graphics.h"
|
||||||
|
|
|
||||||
|
|
@ -1359,24 +1359,18 @@ DefReadLocation(
|
||||||
|
|
||||||
if (use->cu_def->cd_flags & CDFIXEDBBOX)
|
if (use->cu_def->cd_flags & CDFIXEDBBOX)
|
||||||
{
|
{
|
||||||
PropertyRecord *proprec;
|
char *propval;
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
proprec = DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
propval = (char *)DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
if (sscanf(propval, "%d %d %d %d", &rect.r_xbot, &rect.r_ybot,
|
||||||
(proprec->prop_len == 4))
|
&rect.r_xtop, &rect.r_ytop) == 4)
|
||||||
{
|
|
||||||
rect.r_xbot = proprec->prop_value.prop_integer[0];
|
|
||||||
rect.r_ybot = proprec->prop_value.prop_integer[1];
|
|
||||||
rect.r_xtop = proprec->prop_value.prop_integer[2];
|
|
||||||
rect.r_ytop = proprec->prop_value.prop_integer[3];
|
|
||||||
r = ▭
|
r = ▭
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
r = &GeoNullRect;
|
r = &GeoNullRect;
|
||||||
|
|
||||||
|
|
@ -2459,7 +2453,7 @@ DefRead(
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char *filename;
|
char *filename;
|
||||||
const char *token;
|
const char *token;
|
||||||
PropertyRecord *proprec;
|
char *bboxstr;
|
||||||
int keyword, dscale, total;
|
int keyword, dscale, total;
|
||||||
float oscale;
|
float oscale;
|
||||||
Rect *dierect;
|
Rect *dierect;
|
||||||
|
|
@ -2611,17 +2605,14 @@ DefRead(
|
||||||
break;
|
break;
|
||||||
case DEF_DIEAREA:
|
case DEF_DIEAREA:
|
||||||
dierect = LefReadRect(f, 0, oscale);
|
dierect = LefReadRect(f, 0, oscale);
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
bboxstr = mallocMagic(40);
|
||||||
2 * sizeof(int));
|
sprintf(bboxstr, "%d %d %d %d",
|
||||||
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
dierect->r_xbot,
|
||||||
proprec->prop_len = 4;
|
dierect->r_ybot,
|
||||||
proprec->prop_value.prop_integer[0] = dierect->r_xbot;
|
dierect->r_xtop,
|
||||||
proprec->prop_value.prop_integer[1] = dierect->r_ybot;
|
dierect->r_ytop);
|
||||||
proprec->prop_value.prop_integer[2] = dierect->r_xtop;
|
|
||||||
proprec->prop_value.prop_integer[3] = dierect->r_ytop;
|
|
||||||
if (rootDef == NULL) rootDef = DefNewCell(inName);
|
if (rootDef == NULL) rootDef = DefNewCell(inName);
|
||||||
DBPropPut(rootDef, "FIXED_BBOX", proprec);
|
DBPropPut(rootDef, "FIXED_BBOX", bboxstr);
|
||||||
|
|
||||||
LefEndStatement(f);
|
LefEndStatement(f);
|
||||||
break;
|
break;
|
||||||
case DEF_PROPERTYDEFINITIONS:
|
case DEF_PROPERTYDEFINITIONS:
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ defWriteHeader(
|
||||||
float oscale,
|
float oscale,
|
||||||
int units) /* Units for UNITS; could be derived from oscale */
|
int units) /* Units for UNITS; could be derived from oscale */
|
||||||
{
|
{
|
||||||
PropertyRecord *proprec;
|
char *propvalue;
|
||||||
bool propfound;
|
bool propfound;
|
||||||
|
|
||||||
TxPrintf("Diagnostic: Write DEF header for cell %s\n", def->cd_name);
|
TxPrintf("Diagnostic: Write DEF header for cell %s\n", def->cd_name);
|
||||||
|
|
@ -141,20 +141,15 @@ defWriteHeader(
|
||||||
/* For DIEAREA, use the FIXED_BBOX property if present. Otherwise, */
|
/* For DIEAREA, use the FIXED_BBOX property if present. Otherwise, */
|
||||||
/* use the extents of geometry (CellDef bounding box) */
|
/* use the extents of geometry (CellDef bounding box) */
|
||||||
|
|
||||||
proprec = DBPropGet(def, "FIXED_BBOX", &propfound);
|
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
Rect bbox;
|
Rect bbox;
|
||||||
|
|
||||||
/* Die area, taken from the declared FIXED_BBOX. */
|
/* Die area, taken from the declared FIXED_BBOX. */
|
||||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||||
(proprec->prop_len == 4))
|
&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];
|
|
||||||
|
|
||||||
fprintf(f, " DIEAREA ( %.10g %.10g ) ( %.10g %.10g ) ;\n",
|
fprintf(f, " DIEAREA ( %.10g %.10g ) ( %.10g %.10g ) ;\n",
|
||||||
(float)bbox.r_xbot * oscale,
|
(float)bbox.r_xbot * oscale,
|
||||||
(float)bbox.r_ybot * oscale,
|
(float)bbox.r_ybot * oscale,
|
||||||
|
|
@ -2791,23 +2786,17 @@ arrayDefFunc(
|
||||||
|
|
||||||
if (use->cu_def->cd_flags & CDFIXEDBBOX)
|
if (use->cu_def->cd_flags & CDFIXEDBBOX)
|
||||||
{
|
{
|
||||||
PropertyRecord *proprec;
|
char *propval;
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
proprec = DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
propval = (char *)DBPropGet(use->cu_def, "FIXED_BBOX", &found);
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
if (sscanf(propval, "%d %d %d %d", &rect.r_xbot, &rect.r_ybot,
|
||||||
(proprec->prop_len == 4))
|
&rect.r_xtop, &rect.r_ytop) == 4)
|
||||||
{
|
|
||||||
rect.r_xbot = proprec->prop_value.prop_integer[0];
|
|
||||||
rect.r_ybot = proprec->prop_value.prop_integer[1];
|
|
||||||
rect.r_xtop = proprec->prop_value.prop_integer[2];
|
|
||||||
rect.r_ytop = proprec->prop_value.prop_integer[3];
|
|
||||||
r = ▭
|
r = ▭
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
GeoTransRect(transform, r, &box);
|
GeoTransRect(transform, r, &box);
|
||||||
|
|
||||||
|
|
@ -2855,20 +2844,15 @@ defComponentFunc(
|
||||||
xoff = yoff = 0;
|
xoff = yoff = 0;
|
||||||
if (cellUse->cu_def->cd_flags & CDFIXEDBBOX)
|
if (cellUse->cu_def->cd_flags & CDFIXEDBBOX)
|
||||||
{
|
{
|
||||||
PropertyRecord *proprec;
|
char *propval;
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
proprec = DBPropGet(cellUse->cu_def, "FIXED_BBOX", &found);
|
propval = (char *)DBPropGet(cellUse->cu_def, "FIXED_BBOX", &found);
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
if (sscanf(propval, "%d %d %d %d", &rect.r_xbot, &rect.r_ybot,
|
||||||
(proprec->prop_len == 4))
|
&rect.r_xtop, &rect.r_ytop) == 4)
|
||||||
{
|
{
|
||||||
rect.r_xbot = proprec->prop_value.prop_integer[0];
|
|
||||||
rect.r_ybot = proprec->prop_value.prop_integer[1];
|
|
||||||
rect.r_xtop = proprec->prop_value.prop_integer[2];
|
|
||||||
rect.r_ytop = proprec->prop_value.prop_integer[3];
|
|
||||||
|
|
||||||
r = ▭
|
r = ▭
|
||||||
GeoTransRect(&cellUse->cu_transform, &rect, &bbrect);
|
GeoTransRect(&cellUse->cu_transform, &rect, &bbrect);
|
||||||
GeoTransRect(&cellUse->cu_transform, &cellUse->cu_def->cd_bbox, &defrect);
|
GeoTransRect(&cellUse->cu_transform, &cellUse->cu_def->cd_bbox, &defrect);
|
||||||
|
|
|
||||||
|
|
@ -2150,7 +2150,6 @@ LefReadMacro(
|
||||||
int keyword, pinNum, propsize, result;
|
int keyword, pinNum, propsize, result;
|
||||||
float x, y;
|
float x, y;
|
||||||
bool has_size, is_imported = FALSE, propfound;
|
bool has_size, is_imported = FALSE, propfound;
|
||||||
PropertyRecord *proprec;
|
|
||||||
Rect lefBBox;
|
Rect lefBBox;
|
||||||
Point gdsOffset; /* Difference between GDS and LEF coordinates */
|
Point gdsOffset; /* Difference between GDS and LEF coordinates */
|
||||||
|
|
||||||
|
|
@ -2251,12 +2250,7 @@ LefReadMacro(
|
||||||
sprintf(tsave + strlen(tsave), " %s", token);
|
sprintf(tsave + strlen(tsave), " %s", token);
|
||||||
token = LefNextToken(f, TRUE);
|
token = LefNextToken(f, TRUE);
|
||||||
}
|
}
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
DBPropPut(lefMacro, "LEFclass", StrDup((char **)NULL, tsave + 1));
|
||||||
strlen(tsave + 1) - 7);
|
|
||||||
proprec->prop_type = PROPERTY_TYPE_STRING;
|
|
||||||
proprec->prop_len = strlen(tsave + 1);
|
|
||||||
strcpy(proprec->prop_value.prop_string, tsave + 1);
|
|
||||||
DBPropPut(lefMacro, "LEFclass", proprec);
|
|
||||||
break;
|
break;
|
||||||
case LEF_SIZE:
|
case LEF_SIZE:
|
||||||
token = LefNextToken(f, TRUE);
|
token = LefNextToken(f, TRUE);
|
||||||
|
|
@ -2300,12 +2294,7 @@ origin_error:
|
||||||
sprintf(tsave + strlen(tsave), " %s", token);
|
sprintf(tsave + strlen(tsave), " %s", token);
|
||||||
token = LefNextToken(f, TRUE);
|
token = LefNextToken(f, TRUE);
|
||||||
}
|
}
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
DBPropPut(lefMacro, "LEFsymmetry", StrDup((char **)NULL, tsave + 1));
|
||||||
strlen(tsave + 1) - 7);
|
|
||||||
proprec->prop_type = PROPERTY_TYPE_STRING;
|
|
||||||
proprec->prop_len = strlen(tsave + 1);
|
|
||||||
strcpy(proprec->prop_value.prop_string, tsave + 1);
|
|
||||||
DBPropPut(lefMacro, "LEFsymmetry", proprec);
|
|
||||||
break;
|
break;
|
||||||
case LEF_SOURCE:
|
case LEF_SOURCE:
|
||||||
token = LefNextToken(f, TRUE);
|
token = LefNextToken(f, TRUE);
|
||||||
|
|
@ -2316,19 +2305,12 @@ origin_error:
|
||||||
case LEF_SITE:
|
case LEF_SITE:
|
||||||
token = LefNextToken(f, TRUE);
|
token = LefNextToken(f, TRUE);
|
||||||
if (*token != '\n')
|
if (*token != '\n')
|
||||||
{
|
DBPropPut(lefMacro, "LEFsite", StrDup((char **)NULL, token));
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
|
||||||
strlen(token) - 7);
|
|
||||||
proprec->prop_type = PROPERTY_TYPE_STRING;
|
|
||||||
proprec->prop_len = strlen(token);
|
|
||||||
strcpy(proprec->prop_value.prop_string, token);
|
|
||||||
DBPropPut(lefMacro, "LEFsite", proprec);
|
|
||||||
}
|
|
||||||
LefEndStatement(f);
|
LefEndStatement(f);
|
||||||
break;
|
break;
|
||||||
case LEF_PROPERTY:
|
case LEF_PROPERTY:
|
||||||
/* Append property key:value pairs to the cell property LEFproperties */
|
/* Append property key:value pairs to the cell property LEFproperties */
|
||||||
propval = DBPropGetString(lefMacro, "LEFproperties", &propfound);
|
propval = (char *)DBPropGet(lefMacro, "LEFproperties", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
propsize = strlen(propval);
|
propsize = strlen(propval);
|
||||||
else
|
else
|
||||||
|
|
@ -2340,19 +2322,14 @@ origin_error:
|
||||||
char *propext;
|
char *propext;
|
||||||
sprintf(tsave, "%.127s", token);
|
sprintf(tsave, "%.127s", token);
|
||||||
token = LefNextToken(f, TRUE);
|
token = LefNextToken(f, TRUE);
|
||||||
|
propext = (char *)mallocMagic(propsize + strlen(tsave) +
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
strlen(token) + 4);
|
||||||
propsize + strlen(tsave) + strlen(token) - 3);
|
|
||||||
proprec->prop_type = PROPERTY_TYPE_STRING;
|
|
||||||
proprec->prop_len = propsize + strlen(tsave) + strlen(token) + 4;
|
|
||||||
|
|
||||||
if (propsize > 0)
|
if (propsize > 0)
|
||||||
sprintf(proprec->prop_value.prop_string, "%s %s %s",
|
sprintf(propext, "%s %s %s", propval, tsave, token);
|
||||||
propval, tsave, token);
|
|
||||||
else
|
else
|
||||||
sprintf(proprec->prop_value.prop_string, "%s %s", tsave, token);
|
sprintf(propext, "%s %s", tsave, token);
|
||||||
|
|
||||||
DBPropPut(lefMacro, "LEFproperties", proprec);
|
DBPropPut(lefMacro, "LEFproperties", StrDup((char **)NULL, propext));
|
||||||
}
|
}
|
||||||
LefEndStatement(f);
|
LefEndStatement(f);
|
||||||
break;
|
break;
|
||||||
|
|
@ -2428,16 +2405,11 @@ foreign_error:
|
||||||
if (has_size)
|
if (has_size)
|
||||||
{
|
{
|
||||||
lefMacro->cd_flags |= CDFIXEDBBOX;
|
lefMacro->cd_flags |= CDFIXEDBBOX;
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
propval = (char *)mallocMagic(40);
|
||||||
(2 * sizeof(int)));
|
sprintf(propval, "%d %d %d %d",
|
||||||
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
lefBBox.r_xbot, lefBBox.r_ybot,
|
||||||
proprec->prop_len = 4;
|
lefBBox.r_xtop, lefBBox.r_ytop);
|
||||||
proprec->prop_value.prop_integer[0] = lefBBox.r_xbot;
|
DBPropPut(lefMacro, "FIXED_BBOX", propval);
|
||||||
proprec->prop_value.prop_integer[1] = lefBBox.r_ybot;
|
|
||||||
proprec->prop_value.prop_integer[2] = lefBBox.r_xtop;
|
|
||||||
proprec->prop_value.prop_integer[3] = lefBBox.r_ytop;
|
|
||||||
|
|
||||||
DBPropPut(lefMacro, "FIXED_BBOX", proprec);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -2447,16 +2419,11 @@ foreign_error:
|
||||||
if (has_size)
|
if (has_size)
|
||||||
{
|
{
|
||||||
lefMacro->cd_flags |= CDFIXEDBBOX;
|
lefMacro->cd_flags |= CDFIXEDBBOX;
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
propval = (char *)mallocMagic(40);
|
||||||
(2 * sizeof(int)));
|
sprintf(propval, "%d %d %d %d",
|
||||||
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
lefBBox.r_xbot, lefBBox.r_ybot,
|
||||||
proprec->prop_len = 4;
|
lefBBox.r_xtop, lefBBox.r_ytop);
|
||||||
proprec->prop_value.prop_integer[0] = lefBBox.r_xbot;
|
DBPropPut(lefMacro, "FIXED_BBOX", propval);
|
||||||
proprec->prop_value.prop_integer[1] = lefBBox.r_ybot;
|
|
||||||
proprec->prop_value.prop_integer[2] = lefBBox.r_xtop;
|
|
||||||
proprec->prop_value.prop_integer[3] = lefBBox.r_ytop;
|
|
||||||
|
|
||||||
DBPropPut(lefMacro, "FIXED_BBOX", proprec);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -2465,17 +2432,13 @@ foreign_error:
|
||||||
|
|
||||||
/* Set the placement bounding box property to the current bounding box */
|
/* Set the placement bounding box property to the current bounding box */
|
||||||
lefMacro->cd_flags |= CDFIXEDBBOX;
|
lefMacro->cd_flags |= CDFIXEDBBOX;
|
||||||
lefMacro->cd_flags |= CDFIXEDBBOX;
|
propval = (char *)mallocMagic(40);
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord) +
|
sprintf(propval, "%d %d %d %d",
|
||||||
(2 * sizeof(int)));
|
lefMacro->cd_bbox.r_xbot,
|
||||||
proprec->prop_type = PROPERTY_TYPE_DIMENSION;
|
lefMacro->cd_bbox.r_ybot,
|
||||||
proprec->prop_len = 4;
|
lefMacro->cd_bbox.r_xtop,
|
||||||
proprec->prop_value.prop_integer[0] = lefMacro->cd_bbox.r_xbot;
|
lefMacro->cd_bbox.r_ytop);
|
||||||
proprec->prop_value.prop_integer[1] = lefMacro->cd_bbox.r_ybot;
|
DBPropPut(lefMacro, "FIXED_BBOX", propval);
|
||||||
proprec->prop_value.prop_integer[2] = lefMacro->cd_bbox.r_xtop;
|
|
||||||
proprec->prop_value.prop_integer[3] = lefMacro->cd_bbox.r_ytop;
|
|
||||||
|
|
||||||
DBPropPut(lefMacro, "FIXED_BBOX", proprec);
|
|
||||||
DRCCheckThis(lefMacro, TT_CHECKPAINT, &lefMacro->cd_bbox);
|
DRCCheckThis(lefMacro, TT_CHECKPAINT, &lefMacro->cd_bbox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2490,13 +2453,7 @@ foreign_error:
|
||||||
/* i.e., setting it to "FALSE" would be ineffective. */
|
/* i.e., setting it to "FALSE" would be ineffective. */
|
||||||
|
|
||||||
if (!is_imported)
|
if (!is_imported)
|
||||||
{
|
DBPropPut(lefMacro, "LEFview", StrDup((char **)NULL, "TRUE"));
|
||||||
proprec = (PropertyRecord *)mallocMagic(sizeof(PropertyRecord));
|
|
||||||
proprec->prop_type = PROPERTY_TYPE_STRING;
|
|
||||||
proprec->prop_len = 4;
|
|
||||||
strcpy(proprec->prop_value.prop_string, "TRUE");
|
|
||||||
DBPropPut(lefMacro, "LEFview", proprec);
|
|
||||||
}
|
|
||||||
|
|
||||||
DBWAreaChanged(lefMacro, &lefMacro->cd_bbox, DBW_ALLWINDOWS,
|
DBWAreaChanged(lefMacro, &lefMacro->cd_bbox, DBW_ALLWINDOWS,
|
||||||
&DBAllButSpaceBits);
|
&DBAllButSpaceBits);
|
||||||
|
|
|
||||||
|
|
@ -328,14 +328,14 @@ lefWriteHeader(
|
||||||
{
|
{
|
||||||
fprintf(f, "SITE %s\n", siteDef->cd_name);
|
fprintf(f, "SITE %s\n", siteDef->cd_name);
|
||||||
|
|
||||||
propvalue = DBPropGetString(siteDef, "LEFsymmetry", &propfound);
|
propvalue = (char *)DBPropGet(siteDef, "LEFsymmetry", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
fprintf(f, IN0 "SYMMETRY %s ;\n", propvalue);
|
fprintf(f, IN0 "SYMMETRY %s ;\n", propvalue);
|
||||||
else
|
else
|
||||||
/* Usually core cells have symmetry Y only. */
|
/* Usually core cells have symmetry Y only. */
|
||||||
fprintf(f, IN0 "SYMMETRY Y ;\n");
|
fprintf(f, IN0 "SYMMETRY Y ;\n");
|
||||||
|
|
||||||
propvalue = DBPropGetString(siteDef, "LEFclass", &propfound);
|
propvalue = (char *)DBPropGet(siteDef, "LEFclass", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
fprintf(f, IN0 "CLASS %s ;\n", propvalue);
|
fprintf(f, IN0 "CLASS %s ;\n", propvalue);
|
||||||
else
|
else
|
||||||
|
|
@ -345,20 +345,10 @@ lefWriteHeader(
|
||||||
boundary = siteDef->cd_bbox;
|
boundary = siteDef->cd_bbox;
|
||||||
if (siteDef->cd_flags & CDFIXEDBBOX)
|
if (siteDef->cd_flags & CDFIXEDBBOX)
|
||||||
{
|
{
|
||||||
PropertyRecord *proprec;
|
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &propfound);
|
||||||
|
|
||||||
proprec = DBPropGet(def, "FIXED_BBOX", &propfound);
|
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
sscanf(propvalue, "%d %d %d %d", &boundary.r_xbot,
|
||||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
&boundary.r_ybot, &boundary.r_xtop, &boundary.r_ytop);
|
||||||
(proprec->prop_len == 4))
|
|
||||||
{
|
|
||||||
boundary.r_xbot = proprec->prop_value.prop_integer[0];
|
|
||||||
boundary.r_ybot = proprec->prop_value.prop_integer[1];
|
|
||||||
boundary.r_xtop = proprec->prop_value.prop_integer[2];
|
|
||||||
boundary.r_ytop = proprec->prop_value.prop_integer[3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scale = CIFGetOutputScale(1000); /* conversion to microns */
|
scale = CIFGetOutputScale(1000); /* conversion to microns */
|
||||||
|
|
@ -1298,7 +1288,7 @@ lefWriteMacro(
|
||||||
/* default values are optional, so in this case we will leave those */
|
/* default values are optional, so in this case we will leave those */
|
||||||
/* entries blank. */
|
/* entries blank. */
|
||||||
|
|
||||||
propvalue = DBPropGetString(def, "LEFclass", &propfound);
|
propvalue = (char *)DBPropGet(def, "LEFclass", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
fprintf(f, IN0 "CLASS %s ;\n", propvalue);
|
fprintf(f, IN0 "CLASS %s ;\n", propvalue);
|
||||||
|
|
@ -1334,21 +1324,13 @@ lefWriteMacro(
|
||||||
|
|
||||||
if (def->cd_flags & CDFIXEDBBOX)
|
if (def->cd_flags & CDFIXEDBBOX)
|
||||||
{
|
{
|
||||||
PropertyRecord *proprec;
|
char *propvalue;
|
||||||
bool found;
|
bool found;
|
||||||
|
|
||||||
proprec = DBPropGet(def, "FIXED_BBOX", &found);
|
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &found);
|
||||||
if (found)
|
if (found)
|
||||||
{
|
sscanf(propvalue, "%d %d %d %d", &boundary.r_xbot,
|
||||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
&boundary.r_ybot, &boundary.r_xtop, &boundary.r_ytop);
|
||||||
(proprec->prop_len == 4))
|
|
||||||
{
|
|
||||||
boundary.r_xbot = proprec->prop_value.prop_integer[0];
|
|
||||||
boundary.r_ybot = proprec->prop_value.prop_integer[1];
|
|
||||||
boundary.r_xtop = proprec->prop_value.prop_integer[2];
|
|
||||||
boundary.r_ytop = proprec->prop_value.prop_integer[3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if (boundry less setback) is degenerate. If so, then */
|
/* Check if (boundry less setback) is degenerate. If so, then */
|
||||||
|
|
@ -1376,11 +1358,11 @@ lefWriteMacro(
|
||||||
lc.origin.p_x = 0;
|
lc.origin.p_x = 0;
|
||||||
lc.origin.p_y = 0;
|
lc.origin.p_y = 0;
|
||||||
|
|
||||||
propvalue = DBPropGetString(def, "LEFsymmetry", &propfound);
|
propvalue = (char *)DBPropGet(def, "LEFsymmetry", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
fprintf(f, IN0 "SYMMETRY %s ;\n", propvalue);
|
fprintf(f, IN0 "SYMMETRY %s ;\n", propvalue);
|
||||||
|
|
||||||
propvalue = DBPropGetString(def, "LEFsite", &propfound);
|
propvalue = (char *)DBPropGet(def, "LEFsite", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
fprintf(f, IN0 "SITE %s ;\n", propvalue);
|
fprintf(f, IN0 "SITE %s ;\n", propvalue);
|
||||||
|
|
||||||
|
|
@ -1839,24 +1821,20 @@ lefWriteMacro(
|
||||||
Rect layerBound, manualBound;
|
Rect layerBound, manualBound;
|
||||||
labelLinkedList *thislll;
|
labelLinkedList *thislll;
|
||||||
bool propfound;
|
bool propfound;
|
||||||
PropertyRecord *proprec;
|
char *propvalue;
|
||||||
|
|
||||||
/* If there is a property OBS_BBOX, then use the value of the */
|
/* If there is a property OBS_BBOX, then use the value of the */
|
||||||
/* defined box to set the minimum hidden area. This will still */
|
/* defined box to set the minimum hidden area. This will still */
|
||||||
/* get clipped to the setback. */
|
/* get clipped to the setback. */
|
||||||
|
|
||||||
proprec = DBPropGet(def, "OBS_BBOX", &propfound);
|
propvalue = (char *)DBPropGet(def, "OBS_BBOX", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
if (sscanf(propvalue, "%d %d %d %d",
|
||||||
(proprec->prop_len == 4))
|
&(manualBound.r_xbot),
|
||||||
{
|
&(manualBound.r_ybot),
|
||||||
manualBound.r_xbot = proprec->prop_value.prop_integer[0];
|
&(manualBound.r_xtop),
|
||||||
manualBound.r_ybot = proprec->prop_value.prop_integer[1];
|
&(manualBound.r_ytop)) != 4)
|
||||||
manualBound.r_xtop = proprec->prop_value.prop_integer[2];
|
|
||||||
manualBound.r_ytop = proprec->prop_value.prop_integer[3];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
TxError("Improper values for obstruction bounding box "
|
TxError("Improper values for obstruction bounding box "
|
||||||
"OBS_BBOX property");
|
"OBS_BBOX property");
|
||||||
|
|
@ -2038,7 +2016,7 @@ lefWriteMacro(
|
||||||
|
|
||||||
/* If there are any properties saved in LEFproperties, write them out */
|
/* If there are any properties saved in LEFproperties, write them out */
|
||||||
|
|
||||||
propvalue = DBPropGetString(def, "LEFproperties", &propfound);
|
propvalue = (char *)DBPropGet(def, "LEFproperties", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
char *delim;
|
char *delim;
|
||||||
|
|
@ -2116,7 +2094,7 @@ lefGetSites(
|
||||||
bool propfound;
|
bool propfound;
|
||||||
char *propvalue;
|
char *propvalue;
|
||||||
|
|
||||||
propvalue = DBPropGetString(def, "LEFsite", &propfound);
|
propvalue = (char *)DBPropGet(def, "LEFsite", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
he = HashFind(lefSiteTbl, propvalue); /* FIXME return value not used from call to function with no side-effects (reevaluate this entire func purpose?) */
|
he = HashFind(lefSiteTbl, propvalue); /* FIXME return value not used from call to function with no side-effects (reevaluate this entire func purpose?) */
|
||||||
|
|
||||||
|
|
@ -2146,7 +2124,7 @@ lefGetProperties(
|
||||||
bool propfound;
|
bool propfound;
|
||||||
char *propvalue;
|
char *propvalue;
|
||||||
|
|
||||||
propvalue = DBPropGetString(def, "LEFproperties", &propfound);
|
propvalue = (char *)DBPropGet(def, "LEFproperties", &propfound);
|
||||||
if (propfound)
|
if (propfound)
|
||||||
{
|
{
|
||||||
char *key;
|
char *key;
|
||||||
|
|
|
||||||
|
|
@ -120,61 +120,61 @@ macro Control_XK_space "tool wiring"
|
||||||
# Arrow keys (X11 versions only)
|
# Arrow keys (X11 versions only)
|
||||||
macro XK_Left "scroll l .1 w"
|
macro XK_Left "scroll l .1 w"
|
||||||
macro Shift_XK_Left "scroll l 1 w"
|
macro Shift_XK_Left "scroll l 1 w"
|
||||||
macro Control_XK_Left "box grow w 1i"
|
macro Control_XK_Left "box grow w 1"
|
||||||
macro Control_Shift_XK_Left "box shrink e 1i"
|
macro Control_Shift_XK_Left "box shrink e 1"
|
||||||
macro XK_Right "scroll r .1 w"
|
macro XK_Right "scroll r .1 w"
|
||||||
macro Shift_XK_Right "scroll r 1 w"
|
macro Shift_XK_Right "scroll r 1 w"
|
||||||
macro Control_XK_Right "box grow e 1i"
|
macro Control_XK_Right "box grow e 1"
|
||||||
macro Control_Shift_XK_Right "box shrink w 1i"
|
macro Control_Shift_XK_Right "box shrink w 1"
|
||||||
macro XK_Up "scroll u .1 w"
|
macro XK_Up "scroll u .1 w"
|
||||||
macro Shift_XK_Up "scroll u 1 w"
|
macro Shift_XK_Up "scroll u 1 w"
|
||||||
macro Control_XK_Up "box grow n 1i"
|
macro Control_XK_Up "box grow n 1"
|
||||||
macro Control_Shift_XK_Up "box shrink s 1i"
|
macro Control_Shift_XK_Up "box shrink s 1"
|
||||||
macro XK_Down "scroll d .1 w"
|
macro XK_Down "scroll d .1 w"
|
||||||
macro Shift_XK_Down "scroll d 1 w"
|
macro Shift_XK_Down "scroll d 1 w"
|
||||||
macro Control_XK_Down "box grow s 1i"
|
macro Control_XK_Down "box grow s 1"
|
||||||
macro Control_Shift_XK_Down "box shrink n 1i"
|
macro Control_Shift_XK_Down "box shrink n 1"
|
||||||
# Keypad keys (X11 versions only)
|
# Keypad keys (X11 versions only)
|
||||||
# Functions duplicated for use both with Num_Lock ON and OFF
|
# Functions duplicated for use both with Num_Lock ON and OFF
|
||||||
macro XK_KP_Delete "box size 0 0"
|
macro XK_KP_Delete "box size 0 0"
|
||||||
macro XK_KP_Insert "box size 4l 4l"
|
macro XK_KP_Insert "box size 4 4"
|
||||||
macro XK_KP_0 "box size 7l 2l"
|
macro XK_KP_0 "box size 7 2"
|
||||||
macro Shift_XK_KP_0 "box size 7l 2l"
|
macro Shift_XK_KP_0 "box size 7 2"
|
||||||
macro XK_0 "box size 7l 2l"
|
macro XK_0 "box size 7 2"
|
||||||
macro Control_XK_KP_0 "box size 2l 7l"
|
macro Control_XK_KP_0 "box size 2 7"
|
||||||
macro Control_XK_KP_Insert "box size 2l 7l"
|
macro Control_XK_KP_Insert "box size 2 7"
|
||||||
macro XK_KP_End "move sw 1i"
|
macro XK_KP_End "move sw 1"
|
||||||
macro XK_KP_Down "move d 1i"
|
macro XK_KP_Down "move d 1"
|
||||||
macro XK_KP_2 "stretch d 1i"
|
macro XK_KP_2 "stretch d 1"
|
||||||
macro Shift_XK_KP_2 "stretch d 1"
|
macro Shift_XK_KP_2 "stretch d 1"
|
||||||
macro Shift_XK_KP_Down "move d 1"
|
macro Shift_XK_KP_Down "stretch d 1"
|
||||||
macro Control_XK_KP_Down "stretch d 1i"
|
macro Control_XK_KP_Down "stretch d 1i"
|
||||||
macro XK_2 "stretch d 1i"
|
macro XK_2 "stretch d 1"
|
||||||
macro XK_KP_Next "move se 1i"
|
macro XK_KP_Next "move se 1"
|
||||||
macro XK_KP_Left "move l 1i"
|
macro XK_KP_Left "move l 1"
|
||||||
macro XK_KP_4 "stretch l 1i"
|
macro XK_KP_4 "stretch l 1"
|
||||||
macro Shift_XK_KP_4 "stretch l 1"
|
macro Shift_XK_KP_4 "stretch l 1"
|
||||||
macro Shift_XK_KP_Left "move l 1"
|
macro Shift_XK_KP_Left "stretch l 1"
|
||||||
macro Control_XK_KP_Left "stretch l 1i"
|
macro Control_XK_KP_Left "stretch l 1i"
|
||||||
macro XK_4 "stretch l 1i"
|
macro XK_4 "stretch l 1"
|
||||||
macro XK_KP_Begin "findbox zoom"
|
macro XK_KP_Begin "findbox zoom"
|
||||||
macro XK_KP_5 "findbox"
|
macro XK_KP_5 "findbox"
|
||||||
macro Shift_XK_KP_5 "findbox"
|
macro Shift_XK_KP_5 "findbox"
|
||||||
macro XK_5 "findbox"
|
macro XK_5 "findbox"
|
||||||
macro XK_KP_Right "move r 1i"
|
macro XK_KP_Right "move r 1"
|
||||||
macro XK_KP_6 "stretch r 1i"
|
macro XK_KP_6 "stretch r 1"
|
||||||
macro Shift_XK_KP_6 "stretch r 1"
|
macro Shift_XK_KP_6 "stretch r 1"
|
||||||
macro Shift_XK_KP_Right "move r 1"
|
macro Shift_XK_KP_Right "stretch r 1"
|
||||||
macro Control_XK_KP_Right "stretch r 1i"
|
macro Control_XK_KP_Right "stretch r 1i"
|
||||||
macro XK_6 "stretch r 1i"
|
macro XK_6 "stretch r 1"
|
||||||
macro XK_KP_Home "move nw 1i"
|
macro XK_KP_Home "move nw 1"
|
||||||
macro XK_KP_Up "move u 1i"
|
macro XK_KP_Up "move u 1"
|
||||||
macro XK_KP_8 "stretch u 1i"
|
macro XK_KP_8 "stretch u 1"
|
||||||
macro Shift_XK_KP_8 "stretch u 1"
|
macro Shift_XK_KP_8 "stretch u 1"
|
||||||
macro Shift_XK_KP_Up "move u 1"
|
macro Shift_XK_KP_Up "stretch u 1"
|
||||||
macro Control_XK_KP_Up "stretch u 1i"
|
macro Control_XK_KP_Up "stretch u 1i"
|
||||||
macro XK_8 "stretch u 1i"
|
macro XK_8 "stretch u 1"
|
||||||
macro XK_KP_Prior "move ne 1i"
|
macro XK_KP_Prior "move ne 1"
|
||||||
# Scroll wheel bindings
|
# Scroll wheel bindings
|
||||||
macro XK_Pointer_Button4 "scroll u .05 w"
|
macro XK_Pointer_Button4 "scroll u .05 w"
|
||||||
macro XK_Pointer_Button5 "scroll d .05 w"
|
macro XK_Pointer_Button5 "scroll d .05 w"
|
||||||
|
|
|
||||||
|
|
@ -58,8 +58,6 @@ MAGIC_8.0 {
|
||||||
DBPlaneTypes;
|
DBPlaneTypes;
|
||||||
DBPrintUseId;
|
DBPrintUseId;
|
||||||
DBPropGet;
|
DBPropGet;
|
||||||
DBPropGetString;
|
|
||||||
DBPropGetDouble;
|
|
||||||
DBPutLabel;
|
DBPutLabel;
|
||||||
DBReComputeBbox;
|
DBReComputeBbox;
|
||||||
DBSeeTypesAll;
|
DBSeeTypesAll;
|
||||||
|
|
|
||||||
|
|
@ -46,22 +46,22 @@ resNodeIsPort(node, x, y, tile)
|
||||||
Rect *rect;
|
Rect *rect;
|
||||||
Point p;
|
Point p;
|
||||||
resPort *pl, *lp;
|
resPort *pl, *lp;
|
||||||
resInfo *info = (resInfo *)TiGetClientPTR(tile);
|
tileJunk *junk = (tileJunk *)TiGetClientPTR(tile);
|
||||||
|
|
||||||
p.p_x = x;
|
p.p_x = x;
|
||||||
p.p_y = y;
|
p.p_y = y;
|
||||||
|
|
||||||
for (pl = info->portList; pl; pl = pl->rp_nextPort)
|
for (pl = junk->portList; pl; pl = pl->rp_nextPort)
|
||||||
{
|
{
|
||||||
rect = &(pl->rp_bbox);
|
rect = &(pl->rp_bbox);
|
||||||
if (GEO_ENCLOSE(&p, rect))
|
if (GEO_ENCLOSE(&p, rect))
|
||||||
{
|
{
|
||||||
node->rn_name = pl->rp_nodename;
|
node->rn_name = pl->rp_nodename;
|
||||||
if (info->portList == pl)
|
if (junk->portList == pl)
|
||||||
info->portList = pl->rp_nextPort;
|
junk->portList = pl->rp_nextPort;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (lp = info->portList; lp && (lp->rp_nextPort != pl);
|
for (lp = junk->portList; lp && (lp->rp_nextPort != pl);
|
||||||
lp = lp->rp_nextPort);
|
lp = lp->rp_nextPort);
|
||||||
lp->rp_nextPort = pl->rp_nextPort;
|
lp->rp_nextPort = pl->rp_nextPort;
|
||||||
}
|
}
|
||||||
|
|
@ -77,8 +77,7 @@ resNodeIsPort(node, x, y, tile)
|
||||||
* resAllPortNodes --
|
* resAllPortNodes --
|
||||||
*
|
*
|
||||||
* Generate new nodes and breakpoints for every unused port declared
|
* Generate new nodes and breakpoints for every unused port declared
|
||||||
* on a tile. However, if "startpoint" is inside the port position,
|
* on a tile.
|
||||||
* then it has already been processed, so ignore it.
|
|
||||||
*
|
*
|
||||||
*--------------------------------------------------------------------------
|
*--------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
@ -91,15 +90,15 @@ resAllPortNodes(tile, list)
|
||||||
int x, y;
|
int x, y;
|
||||||
resNode *resptr;
|
resNode *resptr;
|
||||||
resPort *pl;
|
resPort *pl;
|
||||||
resInfo *info = (resInfo *)TiGetClientPTR(tile);
|
tileJunk *junk = (tileJunk *)TiGetClientPTR(tile);
|
||||||
|
|
||||||
free_magic1_t mm1 = freeMagic1_init();
|
free_magic1_t mm1 = freeMagic1_init();
|
||||||
for (pl = info->portList; pl; pl = pl->rp_nextPort)
|
for (pl = junk->portList; pl; pl = pl->rp_nextPort)
|
||||||
{
|
{
|
||||||
x = pl->rp_loc.p_x;
|
x = pl->rp_loc.p_x;
|
||||||
y = pl->rp_loc.p_y;
|
y = pl->rp_loc.p_y;
|
||||||
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
||||||
InitializeResNode(resptr, x, y, RES_NODE_ORIGIN);
|
InitializeNode(resptr, x, y, RES_NODE_ORIGIN);
|
||||||
resptr->rn_status = TRUE;
|
resptr->rn_status = TRUE;
|
||||||
resptr->rn_noderes = 0;
|
resptr->rn_noderes = 0;
|
||||||
resptr->rn_name = pl->rp_nodename;
|
resptr->rn_name = pl->rp_nodename;
|
||||||
|
|
@ -226,7 +225,7 @@ ResEachTile(tile, startpoint)
|
||||||
int xj, yj, i;
|
int xj, yj, i;
|
||||||
bool merged;
|
bool merged;
|
||||||
tElement *tcell;
|
tElement *tcell;
|
||||||
resInfo *tstructs= (resInfo *)TiGetClientPTR(tile);
|
tileJunk *tstructs= (tileJunk *)TiGetClientPTR(tile);
|
||||||
ExtDevice *devptr;
|
ExtDevice *devptr;
|
||||||
int sides;
|
int sides;
|
||||||
|
|
||||||
|
|
@ -263,7 +262,7 @@ ResEachTile(tile, startpoint)
|
||||||
int x = startpoint->p_x;
|
int x = startpoint->p_x;
|
||||||
int y = startpoint->p_y;
|
int y = startpoint->p_y;
|
||||||
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
||||||
InitializeResNode(resptr, x, y, RES_NODE_ORIGIN);
|
InitializeNode(resptr, x, y, RES_NODE_ORIGIN);
|
||||||
resptr->rn_status = TRUE;
|
resptr->rn_status = TRUE;
|
||||||
resptr->rn_noderes = 0;
|
resptr->rn_noderes = 0;
|
||||||
ResAddToQueue(resptr, &ResNodeQueue);
|
ResAddToQueue(resptr, &ResNodeQueue);
|
||||||
|
|
@ -279,7 +278,7 @@ ResEachTile(tile, startpoint)
|
||||||
* for single tile device, but not as good for multiple ones.
|
* for single tile device, but not as good for multiple ones.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (tstructs->ri_status & RES_TILE_DEV)
|
if (tstructs->tj_status & RES_TILE_DEV)
|
||||||
{
|
{
|
||||||
if (tstructs->deviceList->rd_fet_gate == NULL)
|
if (tstructs->deviceList->rd_fet_gate == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -292,7 +291,7 @@ ResEachTile(tile, startpoint)
|
||||||
tcell->te_thist = tstructs->deviceList;
|
tcell->te_thist = tstructs->deviceList;
|
||||||
tcell->te_nextt = NULL;
|
tcell->te_nextt = NULL;
|
||||||
|
|
||||||
InitializeResNode(resptr, x, y, RES_NODE_JUNCTION);
|
InitializeNode(resptr, x, y, RES_NODE_JUNCTION);
|
||||||
resptr->rn_te = tcell;
|
resptr->rn_te = tcell;
|
||||||
ResAddToQueue(resptr, &ResNodeQueue);
|
ResAddToQueue(resptr, &ResNodeQueue);
|
||||||
resNodeIsPort(resptr, x, y, tile);
|
resNodeIsPort(resptr, x, y, tile);
|
||||||
|
|
@ -517,7 +516,7 @@ ResEachTile(tile, startpoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tstructs->ri_status |= RES_TILE_DONE;
|
tstructs->tj_status |= RES_TILE_DONE;
|
||||||
|
|
||||||
resAllPortNodes(tile, &ResNodeQueue);
|
resAllPortNodes(tile, &ResNodeQueue);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ ResSanityChecks(nodename, resistorList, nodeList, devlist)
|
||||||
for (node = nodeList; node != NULL; node=node->rn_more)
|
for (node = nodeList; node != NULL; node=node->rn_more)
|
||||||
{
|
{
|
||||||
node->rn_status &= ~RES_REACHED_NODE;
|
node->rn_status &= ~RES_REACHED_NODE;
|
||||||
if (node->rn_why & RES_NODE_ORIGIN)
|
if (node->rn_why == RES_NODE_ORIGIN)
|
||||||
STACKPUSH((ClientData) node, resSanityStack);
|
STACKPUSH((ClientData) node, resSanityStack);
|
||||||
}
|
}
|
||||||
for (resistor = resistorList; resistor != NULL; resistor = resistor->rr_nextResistor)
|
for (resistor = resistorList; resistor != NULL; resistor = resistor->rr_nextResistor)
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ ResNewSDDevice(tile, tp, xj, yj, direction, PendingList)
|
||||||
resDevice *resDev;
|
resDevice *resDev;
|
||||||
tElement *tcell;
|
tElement *tcell;
|
||||||
int newnode;
|
int newnode;
|
||||||
resInfo *ri;
|
tileJunk *j;
|
||||||
|
|
||||||
newnode = FALSE;
|
newnode = FALSE;
|
||||||
|
|
||||||
|
|
@ -62,9 +62,9 @@ ResNewSDDevice(tile, tp, xj, yj, direction, PendingList)
|
||||||
*/
|
*/
|
||||||
if (TiGetClient(tp) == CLIENTDEFAULT) return;
|
if (TiGetClient(tp) == CLIENTDEFAULT) return;
|
||||||
|
|
||||||
ri = (resInfo *) TiGetClientPTR(tp);
|
j = (tileJunk *) TiGetClientPTR(tp);
|
||||||
resDev = ri->deviceList;
|
resDev = j->deviceList;
|
||||||
if ((ri->sourceEdge & direction) != 0)
|
if ((j->sourceEdge & direction) != 0)
|
||||||
{
|
{
|
||||||
if (resDev->rd_fet_source == (resNode *) NULL)
|
if (resDev->rd_fet_source == (resNode *) NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -94,8 +94,8 @@ ResNewSDDevice(tile, tp, xj, yj, direction, PendingList)
|
||||||
{
|
{
|
||||||
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
|
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
|
||||||
tcell->te_nextt = NULL;
|
tcell->te_nextt = NULL;
|
||||||
tcell->te_thist = ri->deviceList;
|
tcell->te_thist = j->deviceList;
|
||||||
InitializeResNode(resptr, xj, yj, RES_NODE_DEVICE);
|
InitializeNode(resptr, xj, yj, RES_NODE_DEVICE);
|
||||||
resptr->rn_te = tcell;
|
resptr->rn_te = tcell;
|
||||||
ResAddToQueue(resptr, PendingList);
|
ResAddToQueue(resptr, PendingList);
|
||||||
}
|
}
|
||||||
|
|
@ -125,11 +125,11 @@ ResNewSubDevice(tile, tp, xj, yj, direction, PendingList)
|
||||||
resDevice *resDev;
|
resDevice *resDev;
|
||||||
tElement *tcell;
|
tElement *tcell;
|
||||||
int newnode;
|
int newnode;
|
||||||
resInfo *ri;
|
tileJunk *j;
|
||||||
|
|
||||||
newnode = FALSE;
|
newnode = FALSE;
|
||||||
ri = (resInfo *) TiGetClientPTR(tp);
|
j = (tileJunk *) TiGetClientPTR(tp);
|
||||||
resDev = ri->deviceList;
|
resDev = j->deviceList;
|
||||||
|
|
||||||
/* Arrived at a device that has a terminal connected to substrate */
|
/* Arrived at a device that has a terminal connected to substrate */
|
||||||
/* that is not a FET bulk terminal (e.g., varactor, diode). */
|
/* that is not a FET bulk terminal (e.g., varactor, diode). */
|
||||||
|
|
@ -150,8 +150,8 @@ ResNewSubDevice(tile, tp, xj, yj, direction, PendingList)
|
||||||
{
|
{
|
||||||
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
|
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
|
||||||
tcell->te_nextt = NULL;
|
tcell->te_nextt = NULL;
|
||||||
tcell->te_thist = ri->deviceList;
|
tcell->te_thist = j->deviceList;
|
||||||
InitializeResNode(resptr, xj, yj, RES_NODE_DEVICE);
|
InitializeNode(resptr, xj, yj, RES_NODE_DEVICE);
|
||||||
resptr->rn_te = tcell;
|
resptr->rn_te = tcell;
|
||||||
ResAddToQueue(resptr, PendingList);
|
ResAddToQueue(resptr, PendingList);
|
||||||
}
|
}
|
||||||
|
|
@ -181,8 +181,8 @@ ResProcessJunction(tile, tp, xj, yj, NodeList)
|
||||||
ResJunction *junction;
|
ResJunction *junction;
|
||||||
resNode *resptr;
|
resNode *resptr;
|
||||||
jElement *jcell;
|
jElement *jcell;
|
||||||
resInfo *ri0 = (resInfo *)TiGetClientPTR(tile);
|
tileJunk *j0 = (tileJunk *)TiGetClientPTR(tile);
|
||||||
resInfo *ri2 = (resInfo *)TiGetClientPTR(tp);
|
tileJunk *j2 = (tileJunk *)TiGetClientPTR(tp);
|
||||||
|
|
||||||
#ifdef PARANOID
|
#ifdef PARANOID
|
||||||
if (tile == tp)
|
if (tile == tp)
|
||||||
|
|
@ -191,12 +191,12 @@ ResProcessJunction(tile, tp, xj, yj, NodeList)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (ri2->ri_status & RES_TILE_DONE) return;
|
if (j2->tj_status & RES_TILE_DONE) return;
|
||||||
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
||||||
resptr->rn_te = (tElement *) NULL;
|
resptr->rn_te = (tElement *) NULL;
|
||||||
junction = (ResJunction *) mallocMagic((unsigned)(sizeof(ResJunction)));
|
junction = (ResJunction *) mallocMagic((unsigned)(sizeof(ResJunction)));
|
||||||
jcell = (jElement *) mallocMagic((unsigned)(sizeof(jElement)));
|
jcell = (jElement *) mallocMagic((unsigned)(sizeof(jElement)));
|
||||||
InitializeResNode(resptr, xj, yj, RES_NODE_JUNCTION);
|
InitializeNode(resptr, xj, yj, RES_NODE_JUNCTION);
|
||||||
resptr->rn_je = jcell;
|
resptr->rn_je = jcell;
|
||||||
ResAddToQueue(resptr, NodeList);
|
ResAddToQueue(resptr, NodeList);
|
||||||
|
|
||||||
|
|
@ -208,10 +208,10 @@ ResProcessJunction(tile, tp, xj, yj, NodeList)
|
||||||
junction->rj_Tile[1] = tp;
|
junction->rj_Tile[1] = tp;
|
||||||
junction->rj_loc.p_x =xj;
|
junction->rj_loc.p_x =xj;
|
||||||
junction->rj_loc.p_y =yj;
|
junction->rj_loc.p_y =yj;
|
||||||
junction->rj_nextjunction[0] = ri0->junctionList;
|
junction->rj_nextjunction[0] = j0->junctionList;
|
||||||
ri0->junctionList = junction;
|
j0->junctionList = junction;
|
||||||
junction->rj_nextjunction[1] = ri2->junctionList;
|
junction->rj_nextjunction[1] = j2->junctionList;
|
||||||
ri2->junctionList = junction;
|
j2->junctionList = junction;
|
||||||
|
|
||||||
NEWBREAK(junction->rj_jnode,tile, junction->rj_loc.p_x,
|
NEWBREAK(junction->rj_jnode,tile, junction->rj_loc.p_x,
|
||||||
junction->rj_loc.p_y, NULL);
|
junction->rj_loc.p_y, NULL);
|
||||||
|
|
|
||||||
122
resis/ResMain.c
122
resis/ResMain.c
|
|
@ -35,12 +35,13 @@ resNode *ResNodeList = NULL; /* Processed Nodes */
|
||||||
resDevice *ResDevList = NULL; /* Devices */
|
resDevice *ResDevList = NULL; /* Devices */
|
||||||
ResContactPoint *ResContactList = NULL; /* Contacts */
|
ResContactPoint *ResContactList = NULL; /* Contacts */
|
||||||
resNode *ResNodeQueue = NULL; /* Pending nodes */
|
resNode *ResNodeQueue = NULL; /* Pending nodes */
|
||||||
resNode *ResNodeAtOrigin = NULL; /* node where R=0 */
|
resNode *ResOriginNode = NULL; /* node where R=0 */
|
||||||
resNode *resCurrentNode;
|
resNode *resCurrentNode;
|
||||||
int ResTileCount = 0; /* Number of tiles rn_status */
|
int ResTileCount = 0; /* Number of tiles rn_status */
|
||||||
extern ExtRegion *ResFirst();
|
extern ExtRegion *ResFirst();
|
||||||
extern Tile *FindStartTile();
|
extern Tile *FindStartTile();
|
||||||
extern int ResEachTile();
|
extern int ResEachTile();
|
||||||
|
extern ResExtNode *ResInitializeNode();
|
||||||
TileTypeBitMask ResSDTypesBitMask;
|
TileTypeBitMask ResSDTypesBitMask;
|
||||||
TileTypeBitMask ResSubTypesBitMask;
|
TileTypeBitMask ResSubTypesBitMask;
|
||||||
|
|
||||||
|
|
@ -183,7 +184,7 @@ ResDissolveContacts(contacts)
|
||||||
* ResMakePortBreakpoints --
|
* ResMakePortBreakpoints --
|
||||||
*
|
*
|
||||||
* Search for nodes which are ports, and force them to be breakpoints
|
* Search for nodes which are ports, and force them to be breakpoints
|
||||||
* in the "resInfo" field of their respective tiles in ResUse. This
|
* in the "tileJunk" field of their respective tiles in ResUse. This
|
||||||
* ensures that connected nodes that stretch between two ports will
|
* ensures that connected nodes that stretch between two ports will
|
||||||
* not be assumed to be "hanging" nodes.
|
* not be assumed to be "hanging" nodes.
|
||||||
*
|
*
|
||||||
|
|
@ -265,7 +266,7 @@ ResMakePortBreakpoints(def)
|
||||||
* ResMakeLabelBreakpoints --
|
* ResMakeLabelBreakpoints --
|
||||||
*
|
*
|
||||||
* Search for labels that are part of a node, and force them to be
|
* Search for labels that are part of a node, and force them to be
|
||||||
* breakpoints in the "resInfo" field of their respective tiles in
|
* breakpoints in the "tileJunk" field of their respective tiles in
|
||||||
* ResUse. This ensures (among other things) that pins of a top level
|
* ResUse. This ensures (among other things) that pins of a top level
|
||||||
* cell will be retained and become the endpoint of a net.
|
* cell will be retained and become the endpoint of a net.
|
||||||
*
|
*
|
||||||
|
|
@ -291,7 +292,7 @@ ResMakeLabelBreakpoints(def, resisdata)
|
||||||
if (*(slab->lab_text) == '\0') continue;
|
if (*(slab->lab_text) == '\0') continue;
|
||||||
|
|
||||||
entry = HashFind(&ResNodeTable, slab->lab_text);
|
entry = HashFind(&ResNodeTable, slab->lab_text);
|
||||||
node = ResExtInitNode(entry);
|
node = ResInitializeNode(entry);
|
||||||
|
|
||||||
/* If the drivepoint position changes and the drivepoint is */
|
/* If the drivepoint position changes and the drivepoint is */
|
||||||
/* in the "resisdata" record, then make sure the tile type */
|
/* in the "resisdata" record, then make sure the tile type */
|
||||||
|
|
@ -343,7 +344,7 @@ ResMakeLabelBreakpoints(def, resisdata)
|
||||||
*
|
*
|
||||||
* ResAddBreakpointFunc --
|
* ResAddBreakpointFunc --
|
||||||
*
|
*
|
||||||
* Add a breakpoint to the "resInfo" structure of the tile
|
* Add a breakpoint to the "tileJunk" structure of the tile
|
||||||
*
|
*
|
||||||
*----------------------------------------------------------------------------
|
*----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
@ -354,7 +355,7 @@ ResAddBreakpointFunc(tile, dinfo, node)
|
||||||
TileType dinfo; /* (unused) */
|
TileType dinfo; /* (unused) */
|
||||||
ResExtNode *node;
|
ResExtNode *node;
|
||||||
{
|
{
|
||||||
resInfo *info;
|
tileJunk *junk;
|
||||||
|
|
||||||
if (TiGetClient(tile) == CLIENTDEFAULT)
|
if (TiGetClient(tile) == CLIENTDEFAULT)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -429,15 +430,15 @@ ResFindNewContactTiles(contacts)
|
||||||
if ((IsSplit(tile) && TTMaskHasType(&mask, TiGetRightType(tile)))
|
if ((IsSplit(tile) && TTMaskHasType(&mask, TiGetRightType(tile)))
|
||||||
|| TTMaskHasType(&mask, TiGetLeftType(tile)))
|
|| TTMaskHasType(&mask, TiGetLeftType(tile)))
|
||||||
{
|
{
|
||||||
resInfo *ri = (resInfo *)TiGetClientPTR(tile);
|
tileJunk *j = (tileJunk *)TiGetClientPTR(tile);
|
||||||
cElement *ce;
|
cElement *ce;
|
||||||
|
|
||||||
ce = (cElement *) mallocMagic((unsigned) (sizeof(cElement)));
|
ce = (cElement *) mallocMagic((unsigned) (sizeof(cElement)));
|
||||||
contacts->cp_tile[contacts->cp_currentcontact] = tile;
|
contacts->cp_tile[contacts->cp_currentcontact] = tile;
|
||||||
ce->ce_thisc = contacts;
|
ce->ce_thisc = contacts;
|
||||||
ce->ce_nextc = ri->contactList;
|
ce->ce_nextc = j->contactList;
|
||||||
(contacts->cp_currentcontact) += 1;
|
(contacts->cp_currentcontact) += 1;
|
||||||
ri->contactList = ce;
|
j->contactList = ce;
|
||||||
}
|
}
|
||||||
else if (!IsSplit(tile))
|
else if (!IsSplit(tile))
|
||||||
{
|
{
|
||||||
|
|
@ -451,15 +452,15 @@ ResFindNewContactTiles(contacts)
|
||||||
*/
|
*/
|
||||||
if (TTMaskIntersect(DBResidueMask(ttype), &mask))
|
if (TTMaskIntersect(DBResidueMask(ttype), &mask))
|
||||||
{
|
{
|
||||||
resInfo *ri = (resInfo *)TiGetClientPTR(tile);
|
tileJunk *j = (tileJunk *)TiGetClientPTR(tile);
|
||||||
cElement *ce;
|
cElement *ce;
|
||||||
|
|
||||||
ce = (cElement *) mallocMagic((unsigned) (sizeof(cElement)));
|
ce = (cElement *) mallocMagic((unsigned) (sizeof(cElement)));
|
||||||
contacts->cp_tile[contacts->cp_currentcontact] = tile;
|
contacts->cp_tile[contacts->cp_currentcontact] = tile;
|
||||||
ce->ce_thisc = contacts;
|
ce->ce_thisc = contacts;
|
||||||
ce->ce_nextc = ri->contactList;
|
ce->ce_nextc = j->contactList;
|
||||||
(contacts->cp_currentcontact) += 1;
|
(contacts->cp_currentcontact) += 1;
|
||||||
ri->contactList = ce;
|
j->contactList = ce;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -523,7 +524,7 @@ ResProcessTiles(resisdata, origin)
|
||||||
while (ResNodeQueue != NULL)
|
while (ResNodeQueue != NULL)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* "merged" keeps track of whether another node gets merged into
|
* merged keeps track of whether another node gets merged into
|
||||||
* the current one. If it does, then the node must be processed
|
* the current one. If it does, then the node must be processed
|
||||||
* because additional junctions or contacts were added
|
* because additional junctions or contacts were added
|
||||||
*/
|
*/
|
||||||
|
|
@ -541,14 +542,16 @@ ResProcessTiles(resisdata, origin)
|
||||||
for (tilenum = 0; tilenum < TILES_PER_JUNCTION; tilenum++)
|
for (tilenum = 0; tilenum < TILES_PER_JUNCTION; tilenum++)
|
||||||
{
|
{
|
||||||
Tile *tile = rj->rj_Tile[tilenum];
|
Tile *tile = rj->rj_Tile[tilenum];
|
||||||
resInfo *ri = (resInfo *)TiGetClientPTR(tile);
|
tileJunk *j = (tileJunk *)TiGetClientPTR(tile);
|
||||||
|
|
||||||
if ((ri->ri_status & RES_TILE_DONE) == 0)
|
if ((j->tj_status & RES_TILE_DONE) == 0)
|
||||||
{
|
{
|
||||||
resCurrentNode = resptr2;
|
resCurrentNode = resptr2;
|
||||||
merged |= ResEachTile(tile, (Point *)NULL);
|
merged |= ResEachTile(tile, (Point *)NULL);
|
||||||
}
|
}
|
||||||
|
if (merged & ORIGIN) break;
|
||||||
}
|
}
|
||||||
|
if (merged & ORIGIN) break;
|
||||||
rj->rj_status = TRUE;
|
rj->rj_status = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -559,15 +562,16 @@ ResProcessTiles(resisdata, origin)
|
||||||
{
|
{
|
||||||
ResContactPoint *cp = workingc->ce_thisc;
|
ResContactPoint *cp = workingc->ce_thisc;
|
||||||
|
|
||||||
|
if (merged & ORIGIN) break;
|
||||||
if (cp->cp_status == FALSE)
|
if (cp->cp_status == FALSE)
|
||||||
{
|
{
|
||||||
int newstatus = TRUE;
|
int newstatus = TRUE;
|
||||||
for (tilenum = 0; tilenum < cp->cp_currentcontact; tilenum++)
|
for (tilenum = 0; tilenum < cp->cp_currentcontact; tilenum++)
|
||||||
{
|
{
|
||||||
Tile *tile = cp->cp_tile[tilenum];
|
Tile *tile = cp->cp_tile[tilenum];
|
||||||
resInfo *ri = (resInfo *) TiGetClientPTR(tile);
|
tileJunk *j = (tileJunk *) TiGetClientPTR(tile);
|
||||||
|
|
||||||
if ((ri->ri_status & RES_TILE_DONE) == 0)
|
if ((j->tj_status & RES_TILE_DONE) == 0)
|
||||||
{
|
{
|
||||||
if (cp->cp_cnode[tilenum] == resptr2)
|
if (cp->cp_cnode[tilenum] == resptr2)
|
||||||
{
|
{
|
||||||
|
|
@ -579,7 +583,9 @@ ResProcessTiles(resisdata, origin)
|
||||||
newstatus = FALSE;
|
newstatus = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (merged & ORIGIN) break;
|
||||||
}
|
}
|
||||||
|
if (merged & ORIGIN) break;
|
||||||
cp->cp_status = newstatus;
|
cp->cp_status = newstatus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -595,15 +601,15 @@ ResProcessTiles(resisdata, origin)
|
||||||
ResRemoveFromQueue(resptr2, &ResNodeQueue);
|
ResRemoveFromQueue(resptr2, &ResNodeQueue);
|
||||||
resptr2->rn_more = ResNodeList;
|
resptr2->rn_more = ResNodeList;
|
||||||
resptr2->rn_less = NULL;
|
resptr2->rn_less = NULL;
|
||||||
resptr2->rn_status &= ~RES_PENDING;
|
resptr2->rn_status &= ~PENDING;
|
||||||
resptr2->rn_status |= RES_FINISHED | RES_MARKED;
|
resptr2->rn_status |= FINISHED | MARKED;
|
||||||
if (ResNodeList != NULL)
|
if (ResNodeList != NULL)
|
||||||
{
|
{
|
||||||
ResNodeList->rn_less = resptr2;
|
ResNodeList->rn_less = resptr2;
|
||||||
}
|
}
|
||||||
if (resptr2->rn_noderes == 0)
|
if (resptr2->rn_noderes == 0)
|
||||||
{
|
{
|
||||||
ResNodeAtOrigin = resptr2;
|
ResOriginNode=resptr2;
|
||||||
}
|
}
|
||||||
ResNodeList = resptr2;
|
ResNodeList = resptr2;
|
||||||
ResCleanNode(resptr2, FALSE, &ResNodeList, &ResNodeQueue);
|
ResCleanNode(resptr2, FALSE, &ResNodeList, &ResNodeQueue);
|
||||||
|
|
@ -682,7 +688,7 @@ ResCalcPerimOverlap(tile, dev)
|
||||||
* resMakeDevFunc --
|
* resMakeDevFunc --
|
||||||
*
|
*
|
||||||
* Callback function from ResExtractNet. For each device in a node's
|
* Callback function from ResExtractNet. For each device in a node's
|
||||||
* device list pulled from the .ext file, find the tile(s) corresponding
|
* device list pulled from the .sim file, find the tile(s) corresponding
|
||||||
* to the device in the source tree, and fill out the complete device
|
* to the device in the source tree, and fill out the complete device
|
||||||
* record (namely the full device area).
|
* record (namely the full device area).
|
||||||
*
|
*
|
||||||
|
|
@ -720,7 +726,7 @@ resMakeDevFunc(tile, dinfo, cx)
|
||||||
|
|
||||||
/* If more than one tile type extracts to the same device, then */
|
/* If more than one tile type extracts to the same device, then */
|
||||||
/* the device type may be different from what was recorded when */
|
/* the device type may be different from what was recorded when */
|
||||||
/* the .ext file was read. Restricted to the plane of the */
|
/* the sim file was read. Restricted to the plane of the */
|
||||||
/* original type to avoid conflict with completely different */
|
/* original type to avoid conflict with completely different */
|
||||||
/* devices (like transistors vs. MiM caps). */
|
/* devices (like transistors vs. MiM caps). */
|
||||||
|
|
||||||
|
|
@ -1008,7 +1014,7 @@ ResExtractNet(node, resisdata, cellname)
|
||||||
ResDevList = NULL;
|
ResDevList = NULL;
|
||||||
ResNodeQueue = NULL;
|
ResNodeQueue = NULL;
|
||||||
ResContactList = NULL;
|
ResContactList = NULL;
|
||||||
ResNodeAtOrigin = NULL;
|
ResOriginNode = NULL;
|
||||||
|
|
||||||
/* Pass back network pointers */
|
/* Pass back network pointers */
|
||||||
|
|
||||||
|
|
@ -1163,7 +1169,7 @@ ResExtractNet(node, resisdata, cellname)
|
||||||
|
|
||||||
ResDissolveContacts(ResContactList);
|
ResDissolveContacts(ResContactList);
|
||||||
|
|
||||||
/* Add "resInfo" fields to tiles */
|
/* Add "junk" fields to tiles */
|
||||||
|
|
||||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||||
{
|
{
|
||||||
|
|
@ -1176,17 +1182,10 @@ ResExtractNet(node, resisdata, cellname)
|
||||||
(ClientData) &ResDevList);
|
(ClientData) &ResDevList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this is a top-level cell, then determine where connections
|
/* Finish preprocessing. */
|
||||||
* are made into the cell from ports. Otherwise, determine points
|
|
||||||
* of entry by looking at how all parent cells connect to this
|
|
||||||
* cell.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ResMakePortBreakpoints(ResUse->cu_def);
|
ResMakePortBreakpoints(ResUse->cu_def);
|
||||||
ResMakeLabelBreakpoints(ResUse->cu_def, resisdata);
|
ResMakeLabelBreakpoints(ResUse->cu_def, resisdata);
|
||||||
|
|
||||||
/* Finish preprocessing. */
|
|
||||||
|
|
||||||
ResFindNewContactTiles(ResContactList);
|
ResFindNewContactTiles(ResContactList);
|
||||||
ResPreProcessDevices(DevTiles, ResDevList, ResUse->cu_def);
|
ResPreProcessDevices(DevTiles, ResDevList, ResUse->cu_def);
|
||||||
|
|
||||||
|
|
@ -1310,7 +1309,7 @@ ResGetTileFunc(tile, dinfo, tpptr)
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* FindStartTile-- To start the extraction, we need to find the first driver.
|
* FindStartTile-- To start the extraction, we need to find the first driver.
|
||||||
* The .ext file gives us the location of a point in or near (within 1
|
* The sim file gives us the location of a point in or near (within 1
|
||||||
* unit) of the device. FindStartTile looks for the device, then
|
* unit) of the device. FindStartTile looks for the device, then
|
||||||
* for adjoining diffusion. The diffusion tile is returned.
|
* for adjoining diffusion. The diffusion tile is returned.
|
||||||
*
|
*
|
||||||
|
|
@ -1451,9 +1450,8 @@ FindStartTile(resisdata, SourcePoint)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const ClientData ticlient = TiGetClient(tp);
|
const ClientData ticlient = TiGetClient(tp);
|
||||||
const resInfo *rinfo = (resInfo *)CD2PTR(ticlient);
|
const tileJunk *tj = (tileJunk *)CD2PTR(ticlient);
|
||||||
|
if (ticlient != CLIENTDEFAULT && tj->tj_status & RES_TILE_DEV)
|
||||||
if (ticlient != CLIENTDEFAULT && rinfo->ri_status & RES_TILE_DEV)
|
|
||||||
complex = TRUE;
|
complex = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1473,8 +1471,8 @@ FindStartTile(resisdata, SourcePoint)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const ClientData ticlient = TiGetClient(tp);
|
const ClientData ticlient = TiGetClient(tp);
|
||||||
const resInfo *rinfo = (resInfo *)CD2PTR(ticlient);
|
const tileJunk *tj = (tileJunk *)CD2PTR(ticlient);
|
||||||
if (ticlient != CLIENTDEFAULT && rinfo->ri_status & RES_TILE_DEV)
|
if (ticlient != CLIENTDEFAULT && tj->tj_status & RES_TILE_DEV)
|
||||||
complex = TRUE;
|
complex = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1494,8 +1492,8 @@ FindStartTile(resisdata, SourcePoint)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const ClientData ticlient = TiGetClient(tp);
|
const ClientData ticlient = TiGetClient(tp);
|
||||||
const resInfo *rinfo = (resInfo *)CD2PTR(ticlient);
|
const tileJunk *tj = (tileJunk *)CD2PTR(ticlient);
|
||||||
if (ticlient != CLIENTDEFAULT && rinfo->ri_status & RES_TILE_DEV)
|
if (ticlient != CLIENTDEFAULT && tj->tj_status & RES_TILE_DEV)
|
||||||
complex = TRUE;
|
complex = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1515,8 +1513,8 @@ FindStartTile(resisdata, SourcePoint)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const ClientData ticlient = TiGetClient(tp);
|
const ClientData ticlient = TiGetClient(tp);
|
||||||
const resInfo *rinfo = (resInfo *)CD2PTR(ticlient);
|
const tileJunk *tj = (tileJunk *)CD2PTR(ticlient);
|
||||||
if (ticlient != CLIENTDEFAULT && rinfo->ri_status & RES_TILE_DEV)
|
if (ticlient != CLIENTDEFAULT && tj->tj_status & RES_TILE_DEV)
|
||||||
complex = TRUE;
|
complex = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1529,7 +1527,7 @@ FindStartTile(resisdata, SourcePoint)
|
||||||
|
|
||||||
if (devStack == NULL) devStack = StackNew(8);
|
if (devStack == NULL) devStack = StackNew(8);
|
||||||
|
|
||||||
((resInfo *)TiGetClientPTR(tile))->ri_status |= RES_TILE_PUSHED;
|
((tileJunk *)TiGetClientPTR(tile))->tj_status |= RES_TILE_PUSHED;
|
||||||
STACKPUSH((ClientData)tile, devStack);
|
STACKPUSH((ClientData)tile, devStack);
|
||||||
while (!StackEmpty(devStack))
|
while (!StackEmpty(devStack))
|
||||||
{
|
{
|
||||||
|
|
@ -1556,12 +1554,12 @@ FindStartTile(resisdata, SourcePoint)
|
||||||
const ClientData ticlient = TiGetClient(tp);
|
const ClientData ticlient = TiGetClient(tp);
|
||||||
if (ticlient != CLIENTDEFAULT)
|
if (ticlient != CLIENTDEFAULT)
|
||||||
{
|
{
|
||||||
resInfo *rinfo = (resInfo *)CD2PTR(ticlient);
|
tileJunk *tj = (tileJunk *)CD2PTR(ticlient);
|
||||||
if (rinfo->ri_status & RES_TILE_DEV)
|
if (tj->tj_status & RES_TILE_DEV)
|
||||||
{
|
{
|
||||||
if (!(rinfo->ri_status & RES_TILE_PUSHED))
|
if (!(tj->tj_status & RES_TILE_PUSHED))
|
||||||
{
|
{
|
||||||
rinfo->ri_status |= RES_TILE_PUSHED;
|
tj->tj_status |= RES_TILE_PUSHED;
|
||||||
STACKPUSH((ClientData)tp, devStack);
|
STACKPUSH((ClientData)tp, devStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1590,12 +1588,12 @@ FindStartTile(resisdata, SourcePoint)
|
||||||
const ClientData ticlient = TiGetClient(tp);
|
const ClientData ticlient = TiGetClient(tp);
|
||||||
if (ticlient != CLIENTDEFAULT)
|
if (ticlient != CLIENTDEFAULT)
|
||||||
{
|
{
|
||||||
resInfo *rinfo = (resInfo *)CD2PTR(ticlient);
|
tileJunk *tj = (tileJunk *)CD2PTR(ticlient);
|
||||||
if (rinfo->ri_status & RES_TILE_DEV)
|
if (tj->tj_status & RES_TILE_DEV)
|
||||||
{
|
{
|
||||||
if (!(rinfo->ri_status & RES_TILE_PUSHED))
|
if (!(tj->tj_status & RES_TILE_PUSHED))
|
||||||
{
|
{
|
||||||
rinfo->ri_status |= RES_TILE_PUSHED;
|
tj->tj_status |= RES_TILE_PUSHED;
|
||||||
STACKPUSH((ClientData)tp, devStack);
|
STACKPUSH((ClientData)tp, devStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1624,12 +1622,12 @@ FindStartTile(resisdata, SourcePoint)
|
||||||
const ClientData ticlient = TiGetClient(tp);
|
const ClientData ticlient = TiGetClient(tp);
|
||||||
if (ticlient != CLIENTDEFAULT)
|
if (ticlient != CLIENTDEFAULT)
|
||||||
{
|
{
|
||||||
resInfo *rinfo = (resInfo *)CD2PTR(ticlient);
|
tileJunk *tj = (tileJunk *)CD2PTR(ticlient);
|
||||||
if (rinfo->ri_status & RES_TILE_DEV)
|
if (tj->tj_status & RES_TILE_DEV)
|
||||||
{
|
{
|
||||||
if (!(rinfo->ri_status & RES_TILE_PUSHED))
|
if (!(tj->tj_status & RES_TILE_PUSHED))
|
||||||
{
|
{
|
||||||
rinfo->ri_status |= RES_TILE_PUSHED;
|
tj->tj_status |= RES_TILE_PUSHED;
|
||||||
STACKPUSH((ClientData)tp, devStack);
|
STACKPUSH((ClientData)tp, devStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1658,12 +1656,12 @@ FindStartTile(resisdata, SourcePoint)
|
||||||
const ClientData ticlient = TiGetClient(tp);
|
const ClientData ticlient = TiGetClient(tp);
|
||||||
if (ticlient != CLIENTDEFAULT)
|
if (ticlient != CLIENTDEFAULT)
|
||||||
{
|
{
|
||||||
resInfo *rinfo = (resInfo *)CD2PTR(ticlient);
|
tileJunk *tj = (tileJunk *)CD2PTR(ticlient);
|
||||||
if (rinfo->ri_status & RES_TILE_DEV)
|
if (tj->tj_status & RES_TILE_DEV)
|
||||||
{
|
{
|
||||||
if (!(rinfo->ri_status & RES_TILE_PUSHED))
|
if (!(tj->tj_status & RES_TILE_PUSHED))
|
||||||
{
|
{
|
||||||
rinfo->ri_status |= RES_TILE_PUSHED;
|
tj->tj_status |= RES_TILE_PUSHED;
|
||||||
STACKPUSH((ClientData)tp, devStack);
|
STACKPUSH((ClientData)tp, devStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1722,7 +1720,7 @@ FindStartTile(resisdata, SourcePoint)
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* ResGetDevice -- Once the net is extracted, we still have to equate
|
* ResGetDevice -- Once the net is extracted, we still have to equate
|
||||||
* the .ext file devices with the layout devices. ResGetDevice
|
* the sim file devices with the layout devices. ResGetDevice
|
||||||
* looks for a device at the given location. "type" is also
|
* looks for a device at the given location. "type" is also
|
||||||
* specified to that the right plane will be searched.
|
* specified to that the right plane will be searched.
|
||||||
*
|
*
|
||||||
|
|
@ -1758,7 +1756,7 @@ ResGetDevice(pt, type)
|
||||||
{
|
{
|
||||||
if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetLeftType(tile))
|
if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetLeftType(tile))
|
||||||
|| TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetRightType(tile)))
|
|| TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetRightType(tile)))
|
||||||
return (((resInfo *)CD2PTR(ticlient))->deviceList);
|
return (((tileJunk *)CD2PTR(ticlient))->deviceList);
|
||||||
}
|
}
|
||||||
else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetType(tile)))
|
else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetType(tile)))
|
||||||
{
|
{
|
||||||
|
|
@ -1766,7 +1764,7 @@ ResGetDevice(pt, type)
|
||||||
* error and indicates a problem that needs debugging.
|
* error and indicates a problem that needs debugging.
|
||||||
*/
|
*/
|
||||||
if (ticlient != CLIENTDEFAULT)
|
if (ticlient != CLIENTDEFAULT)
|
||||||
return (((resInfo *)CD2PTR(ticlient))->deviceList);
|
return (((tileJunk *)CD2PTR(ticlient))->deviceList);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,9 +52,9 @@ bool ResCalcEastWest();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ResCalcTileResistance(tile, info, pendingList, doneList)
|
ResCalcTileResistance(tile, junk, pendingList, doneList)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
resInfo *info;
|
tileJunk *junk;
|
||||||
resNode **pendingList, **doneList;
|
resNode **pendingList, **doneList;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -67,7 +67,7 @@ ResCalcTileResistance(tile, info, pendingList, doneList)
|
||||||
merged = FALSE;
|
merged = FALSE;
|
||||||
device = FALSE;
|
device = FALSE;
|
||||||
|
|
||||||
if ((p1 = info->breakList) == NULL) return FALSE;
|
if ((p1 = junk->breakList) == NULL) return FALSE;
|
||||||
for (; p1; p1 = p1->br_next)
|
for (; p1; p1 = p1->br_next)
|
||||||
{
|
{
|
||||||
int x = p1->br_loc.p_x;
|
int x = p1->br_loc.p_x;
|
||||||
|
|
@ -133,7 +133,7 @@ ResCalcEastWest(tile, pendingList, doneList, resList)
|
||||||
resElement *element;
|
resElement *element;
|
||||||
resNode *currNode;
|
resNode *currNode;
|
||||||
float rArea;
|
float rArea;
|
||||||
resInfo *info = (resInfo *)TiGetClientPTR(tile);
|
tileJunk *junk = (tileJunk *)TiGetClientPTR(tile);
|
||||||
|
|
||||||
merged = FALSE;
|
merged = FALSE;
|
||||||
height = TOP(tile) - BOTTOM(tile);
|
height = TOP(tile) - BOTTOM(tile);
|
||||||
|
|
@ -143,12 +143,12 @@ ResCalcEastWest(tile, pendingList, doneList, resList)
|
||||||
* breakpoint, then return.
|
* breakpoint, then return.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
p1 = info->breakList;
|
p1 = junk->breakList;
|
||||||
if (p1->br_next == NULL)
|
if (p1->br_next == NULL)
|
||||||
{
|
{
|
||||||
p1->br_this->rn_float.rn_area += height * (LEFT(tile) - RIGHT(tile));
|
p1->br_this->rn_float.rn_area += height * (LEFT(tile) - RIGHT(tile));
|
||||||
freeMagic((char *)p1);
|
freeMagic((char *)p1);
|
||||||
info->breakList = NULL;
|
junk->breakList = NULL;
|
||||||
return(merged);
|
return(merged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -164,14 +164,14 @@ ResCalcEastWest(tile, pendingList, doneList, resList)
|
||||||
|
|
||||||
/* Re-sort nodes left to right. */
|
/* Re-sort nodes left to right. */
|
||||||
|
|
||||||
ResSortBreaks(&info->breakList, TRUE);
|
ResSortBreaks(&junk->breakList, TRUE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Eliminate breakpoints with the same X coordinate and merge
|
* Eliminate breakpoints with the same X coordinate and merge
|
||||||
* their nodes.
|
* their nodes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
p2= info->breakList;
|
p2= junk->breakList;
|
||||||
|
|
||||||
/* Add extra left area to leftmost node */
|
/* Add extra left area to leftmost node */
|
||||||
|
|
||||||
|
|
@ -213,7 +213,7 @@ ResCalcEastWest(tile, pendingList, doneList, resList)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Was the node used in another info or breakpoint?
|
* Was the node used in another junk or breakpoint?
|
||||||
* If so, replace the old node with the new one.
|
* If so, replace the old node with the new one.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
@ -278,7 +278,7 @@ ResCalcEastWest(tile, pendingList, doneList, resList)
|
||||||
|
|
||||||
p2->br_this->rn_float.rn_area += height * (RIGHT(tile) - p2->br_loc.p_x);
|
p2->br_this->rn_float.rn_area += height * (RIGHT(tile) - p2->br_loc.p_x);
|
||||||
freeMagic((char *)p2);
|
freeMagic((char *)p2);
|
||||||
info->breakList = NULL;
|
junk->breakList = NULL;
|
||||||
return merged;
|
return merged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -309,7 +309,7 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList)
|
||||||
resElement *element;
|
resElement *element;
|
||||||
resNode *currNode;
|
resNode *currNode;
|
||||||
float rArea;
|
float rArea;
|
||||||
resInfo *info = (resInfo *)TiGetClientPTR(tile);
|
tileJunk *junk = (tileJunk *)TiGetClientPTR(tile);
|
||||||
|
|
||||||
merged = FALSE;
|
merged = FALSE;
|
||||||
width = RIGHT(tile) - LEFT(tile);
|
width = RIGHT(tile) - LEFT(tile);
|
||||||
|
|
@ -319,17 +319,17 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList)
|
||||||
* breakpoint, then return.
|
* breakpoint, then return.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
p1 = info->breakList;
|
p1 = junk->breakList;
|
||||||
if (p1->br_next == NULL)
|
if (p1->br_next == NULL)
|
||||||
{
|
{
|
||||||
p1->br_this->rn_float.rn_area += width * (TOP(tile) - BOTTOM(tile));
|
p1->br_this->rn_float.rn_area += width * (TOP(tile) - BOTTOM(tile));
|
||||||
freeMagic((char *)p1);
|
freeMagic((char *)p1);
|
||||||
info->breakList = NULL;
|
junk->breakList = NULL;
|
||||||
return(merged);
|
return(merged);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Re-sort nodes south to north. */
|
/* Re-sort nodes south to north. */
|
||||||
ResSortBreaks(&info->breakList, FALSE);
|
ResSortBreaks(&junk->breakList, FALSE);
|
||||||
|
|
||||||
/* Simplified split tile handling */
|
/* Simplified split tile handling */
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
|
|
@ -346,7 +346,7 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList)
|
||||||
* their nodes.
|
* their nodes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
p2 = info->breakList;
|
p2 = junk->breakList;
|
||||||
|
|
||||||
/* Add extra left area to leftmost node */
|
/* Add extra left area to leftmost node */
|
||||||
|
|
||||||
|
|
@ -388,7 +388,7 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Was the node used in another info or breakpoint?
|
* Was the node used in another junk or breakpoint?
|
||||||
* If so, replace the old node with the new one.
|
* If so, replace the old node with the new one.
|
||||||
*/
|
*/
|
||||||
p3 = p2->br_next;
|
p3 = p2->br_next;
|
||||||
|
|
@ -449,7 +449,7 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList)
|
||||||
}
|
}
|
||||||
p2->br_this->rn_float.rn_area += width * (TOP(tile) - p2->br_loc.p_y);
|
p2->br_this->rn_float.rn_area += width * (TOP(tile) - p2->br_loc.p_y);
|
||||||
freeMagic((char *)p2);
|
freeMagic((char *)p2);
|
||||||
info->breakList = NULL;
|
junk->breakList = NULL;
|
||||||
return(merged);
|
return(merged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -482,7 +482,7 @@ ResCalcNearDevice(tile, pendingList, doneList, resList)
|
||||||
bool merged;
|
bool merged;
|
||||||
int devcount, devedge, deltax, deltay;
|
int devcount, devedge, deltax, deltay;
|
||||||
Breakpoint *p1, *p2, *p3;
|
Breakpoint *p1, *p2, *p3;
|
||||||
resInfo *info = (resInfo *)TiGetClientPTR(tile);
|
tileJunk *junk = (tileJunk *)TiGetClientPTR(tile);
|
||||||
|
|
||||||
merged = FALSE;
|
merged = FALSE;
|
||||||
|
|
||||||
|
|
@ -491,10 +491,10 @@ ResCalcNearDevice(tile, pendingList, doneList, resList)
|
||||||
* breakpoint, then return.
|
* breakpoint, then return.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (info->breakList->br_next == NULL)
|
if (junk->breakList->br_next == NULL)
|
||||||
{
|
{
|
||||||
freeMagic((char *)info->breakList);
|
freeMagic((char *)junk->breakList);
|
||||||
info->breakList = NULL;
|
junk->breakList = NULL;
|
||||||
return(merged);
|
return(merged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -503,7 +503,7 @@ ResCalcNearDevice(tile, pendingList, doneList, resList)
|
||||||
|
|
||||||
devcount = 0;
|
devcount = 0;
|
||||||
devedge = 0;
|
devedge = 0;
|
||||||
for (p1 = info->breakList; p1 != NULL; p1 = p1->br_next)
|
for (p1 = junk->breakList; p1 != NULL; p1 = p1->br_next)
|
||||||
{
|
{
|
||||||
if (p1->br_this->rn_why == RES_NODE_DEVICE)
|
if (p1->br_this->rn_why == RES_NODE_DEVICE)
|
||||||
{
|
{
|
||||||
|
|
@ -525,9 +525,9 @@ ResCalcNearDevice(tile, pendingList, doneList, resList)
|
||||||
(devedge & TOPEDGE) == devedge ||
|
(devedge & TOPEDGE) == devedge ||
|
||||||
(devedge & BOTTOMEDGE) == devedge)
|
(devedge & BOTTOMEDGE) == devedge)
|
||||||
{
|
{
|
||||||
ResSortBreaks(&info->breakList,TRUE);
|
ResSortBreaks(&junk->breakList,TRUE);
|
||||||
p2 = NULL;
|
p2 = NULL;
|
||||||
for (p1 = info->breakList; p1 != NULL; p1 = p1->br_next)
|
for (p1 = junk->breakList; p1 != NULL; p1 = p1->br_next)
|
||||||
{
|
{
|
||||||
if (p1->br_this->rn_why == RES_NODE_DEVICE)
|
if (p1->br_this->rn_why == RES_NODE_DEVICE)
|
||||||
break;
|
break;
|
||||||
|
|
@ -587,9 +587,9 @@ ResCalcNearDevice(tile, pendingList, doneList, resList)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Re-sort nodes south to north. */
|
/* Re-sort nodes south to north. */
|
||||||
ResSortBreaks(&info->breakList, FALSE);
|
ResSortBreaks(&junk->breakList, FALSE);
|
||||||
p2 = NULL;
|
p2 = NULL;
|
||||||
for (p1 = info->breakList; p1 != NULL; p1 = p1->br_next)
|
for (p1 = junk->breakList; p1 != NULL; p1 = p1->br_next)
|
||||||
{
|
{
|
||||||
if (p1->br_this->rn_why == RES_NODE_DEVICE)
|
if (p1->br_this->rn_why == RES_NODE_DEVICE)
|
||||||
{
|
{
|
||||||
|
|
@ -684,17 +684,17 @@ ResCalcNearDevice(tile, pendingList, doneList, resList)
|
||||||
(RIGHT(tile) - LEFT(tile)) > (TOP(tile) - BOTTOM(tile))))
|
(RIGHT(tile) - LEFT(tile)) > (TOP(tile) - BOTTOM(tile))))
|
||||||
{
|
{
|
||||||
/* re-sort nodes south to north. */
|
/* re-sort nodes south to north. */
|
||||||
ResSortBreaks(&info->breakList, FALSE);
|
ResSortBreaks(&junk->breakList, FALSE);
|
||||||
|
|
||||||
/* eliminate duplicate S/D pointers */
|
/* eliminate duplicate S/D pointers */
|
||||||
for (p1 = info->breakList; p1 != NULL; p1 = p1->br_next)
|
for (p1 = junk->breakList; p1 != NULL; p1 = p1->br_next)
|
||||||
{
|
{
|
||||||
if (p1->br_this->rn_why == RES_NODE_DEVICE &&
|
if (p1->br_this->rn_why == RES_NODE_DEVICE &&
|
||||||
(p1->br_loc.p_y == BOTTOM(tile) ||
|
(p1->br_loc.p_y == BOTTOM(tile) ||
|
||||||
p1->br_loc.p_y == TOP(tile)))
|
p1->br_loc.p_y == TOP(tile)))
|
||||||
{
|
{
|
||||||
p3 = NULL;
|
p3 = NULL;
|
||||||
p2 = info->breakList;
|
p2 = junk->breakList;
|
||||||
while (p2 != NULL)
|
while (p2 != NULL)
|
||||||
{
|
{
|
||||||
if (p2->br_this == p1->br_this && p2 != p1 &&
|
if (p2->br_this == p1->br_this && p2 != p1 &&
|
||||||
|
|
@ -703,9 +703,9 @@ ResCalcNearDevice(tile, pendingList, doneList, resList)
|
||||||
{
|
{
|
||||||
if (p3 == NULL)
|
if (p3 == NULL)
|
||||||
{
|
{
|
||||||
info->breakList = p2->br_next;
|
junk->breakList = p2->br_next;
|
||||||
freeMagic((char *) p2);
|
freeMagic((char *) p2);
|
||||||
p2 = info->breakList;
|
p2 = junk->breakList;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -727,14 +727,14 @@ ResCalcNearDevice(tile, pendingList, doneList, resList)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Eliminate duplicate S/D pointers */
|
/* Eliminate duplicate S/D pointers */
|
||||||
for (p1 = info->breakList; p1 != NULL; p1 = p1->br_next)
|
for (p1 = junk->breakList; p1 != NULL; p1 = p1->br_next)
|
||||||
{
|
{
|
||||||
if (p1->br_this->rn_why == RES_NODE_DEVICE &&
|
if (p1->br_this->rn_why == RES_NODE_DEVICE &&
|
||||||
(p1->br_loc.p_x == LEFT(tile) ||
|
(p1->br_loc.p_x == LEFT(tile) ||
|
||||||
p1->br_loc.p_x == RIGHT(tile)))
|
p1->br_loc.p_x == RIGHT(tile)))
|
||||||
{
|
{
|
||||||
p3 = NULL;
|
p3 = NULL;
|
||||||
p2 = info->breakList;
|
p2 = junk->breakList;
|
||||||
while (p2 != NULL)
|
while (p2 != NULL)
|
||||||
{
|
{
|
||||||
if (p2->br_this == p1->br_this && p2 != p1 &&
|
if (p2->br_this == p1->br_this && p2 != p1 &&
|
||||||
|
|
@ -743,9 +743,9 @@ ResCalcNearDevice(tile, pendingList, doneList, resList)
|
||||||
{
|
{
|
||||||
if (p3 == NULL)
|
if (p3 == NULL)
|
||||||
{
|
{
|
||||||
info->breakList = p2->br_next;
|
junk->breakList = p2->br_next;
|
||||||
freeMagic((char *) p2);
|
freeMagic((char *) p2);
|
||||||
p2 = info->breakList;
|
p2 = junk->breakList;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -805,7 +805,7 @@ ResDoContacts(contact, nodes, resList)
|
||||||
int y = contact->cp_center.p_y;
|
int y = contact->cp_center.p_y;
|
||||||
|
|
||||||
resptr = (resNode *) mallocMagic((unsigned) (sizeof(resNode)));
|
resptr = (resNode *) mallocMagic((unsigned) (sizeof(resNode)));
|
||||||
InitializeResNode(resptr, x, y, RES_NODE_CONTACT);
|
InitializeNode(resptr, x, y, RES_NODE_CONTACT);
|
||||||
ResAddToQueue(resptr, nodes);
|
ResAddToQueue(resptr, nodes);
|
||||||
|
|
||||||
ccell = (cElement *) mallocMagic((unsigned) (sizeof(cElement)));
|
ccell = (cElement *) mallocMagic((unsigned) (sizeof(cElement)));
|
||||||
|
|
@ -858,7 +858,7 @@ ResDoContacts(contact, nodes, resList)
|
||||||
Tile *tile = contact->cp_tile[tilenum];
|
Tile *tile = contact->cp_tile[tilenum];
|
||||||
|
|
||||||
resptr = (resNode *) mallocMagic((unsigned) (sizeof(resNode)));
|
resptr = (resNode *) mallocMagic((unsigned) (sizeof(resNode)));
|
||||||
InitializeResNode(resptr, x, y, RES_NODE_CONTACT);
|
InitializeNode(resptr, x, y, RES_NODE_CONTACT);
|
||||||
ResAddToQueue(resptr, nodes);
|
ResAddToQueue(resptr, nodes);
|
||||||
|
|
||||||
/* Add contact pointer to node */
|
/* Add contact pointer to node */
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ ResDoneWithNode(resptr)
|
||||||
resResistor *rr1;
|
resResistor *rr1;
|
||||||
|
|
||||||
resptr2 = NULL;
|
resptr2 = NULL;
|
||||||
resptr->rn_status |= RES_TRUE;
|
resptr->rn_status |= RESTRUE;
|
||||||
status = UNTOUCHED;
|
status = UNTOUCHED;
|
||||||
|
|
||||||
/* are there any resistors? */
|
/* are there any resistors? */
|
||||||
|
|
@ -93,9 +93,9 @@ ResDoneWithNode(resptr)
|
||||||
ResMergeNodes(resptr2, resptr, &ResNodeQueue, &ResNodeList);
|
ResMergeNodes(resptr2, resptr, &ResNodeQueue, &ResNodeList);
|
||||||
resptr2->rn_float.rn_area += rr1->rr_float.rr_area;
|
resptr2->rn_float.rn_area += rr1->rr_float.rr_area;
|
||||||
ResEliminateResistor(rr1, &ResResList);
|
ResEliminateResistor(rr1, &ResResList);
|
||||||
if ((resptr2->rn_status & RES_TRUE) == RES_TRUE)
|
if ((resptr2->rn_status & RESTRUE) == RESTRUE)
|
||||||
{
|
{
|
||||||
resptr2->rn_status &= ~RES_TRUE;
|
resptr2->rn_status &= ~RESTRUE;
|
||||||
ResDoneWithNode(resptr2);
|
ResDoneWithNode(resptr2);
|
||||||
}
|
}
|
||||||
resptr2 = NULL;
|
resptr2 = NULL;
|
||||||
|
|
@ -108,16 +108,14 @@ ResDoneWithNode(resptr)
|
||||||
/* Eliminations that can be only if there are no devices connected */
|
/* Eliminations that can be only if there are no devices connected */
|
||||||
/* to node. Series and dangling connections fall in this group. */
|
/* to node. Series and dangling connections fall in this group. */
|
||||||
|
|
||||||
if ((status == UNTOUCHED) && (resptr->rn_te == NULL) &&
|
if ((resptr->rn_te == NULL) && (resptr->rn_why != RES_NODE_ORIGIN)
|
||||||
!(resptr->rn_why & (RES_NODE_ORIGIN | RES_NODE_SINK)))
|
&& (status == UNTOUCHED))
|
||||||
status = ResSeriesCheck(resptr);
|
status = ResSeriesCheck(resptr);
|
||||||
|
|
||||||
if ((status == UNTOUCHED) &&
|
if ((status == UNTOUCHED) && (resptr->rn_why != RES_NODE_ORIGIN))
|
||||||
!(resptr->rn_why & (RES_NODE_ORIGIN | RES_NODE_SINK)))
|
|
||||||
status = ResParallelCheck(resptr);
|
status = ResParallelCheck(resptr);
|
||||||
|
|
||||||
if ((status == UNTOUCHED) &&
|
if ((status == UNTOUCHED) && (resptr->rn_why != RES_NODE_ORIGIN))
|
||||||
!(resptr->rn_why & (RES_NODE_ORIGIN | RES_NODE_SINK)))
|
|
||||||
status = ResTriangleCheck(resptr);
|
status = ResTriangleCheck(resptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -244,9 +242,9 @@ ResSeriesCheck(resptr)
|
||||||
ResEliminateResistor(rr1, &ResResList);
|
ResEliminateResistor(rr1, &ResResList);
|
||||||
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
|
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
|
||||||
status = SINGLE;
|
status = SINGLE;
|
||||||
if (resptr2->rn_status & RES_TRUE)
|
if (resptr2->rn_status & RESTRUE)
|
||||||
{
|
{
|
||||||
resptr2->rn_status &= ~RES_TRUE;
|
resptr2->rn_status &= ~RESTRUE;
|
||||||
ResDoneWithNode(resptr2);
|
ResDoneWithNode(resptr2);
|
||||||
}
|
}
|
||||||
resptr2 = NULL;
|
resptr2 = NULL;
|
||||||
|
|
@ -282,9 +280,9 @@ ResSeriesCheck(resptr)
|
||||||
rr1->rr_connection1 = rr2->rr_connection2;
|
rr1->rr_connection1 = rr2->rr_connection2;
|
||||||
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
|
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
|
||||||
}
|
}
|
||||||
if ((resptr2->rn_status & RES_TRUE) == RES_TRUE)
|
if ((resptr2->rn_status & RESTRUE) == RESTRUE)
|
||||||
{
|
{
|
||||||
resptr2->rn_status &= ~RES_TRUE;
|
resptr2->rn_status &= ~RESTRUE;
|
||||||
ResDoneWithNode(resptr2);
|
ResDoneWithNode(resptr2);
|
||||||
}
|
}
|
||||||
resptr2 = NULL;
|
resptr2 = NULL;
|
||||||
|
|
@ -313,9 +311,9 @@ ResSeriesCheck(resptr)
|
||||||
rr1->rr_connection1 = rr2->rr_connection1;
|
rr1->rr_connection1 = rr2->rr_connection1;
|
||||||
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
|
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
|
||||||
}
|
}
|
||||||
if ((resptr2->rn_status & RES_TRUE) == RES_TRUE)
|
if ((resptr2->rn_status & RESTRUE) == RESTRUE)
|
||||||
{
|
{
|
||||||
resptr2->rn_status &= ~RES_TRUE;
|
resptr2->rn_status &= ~RESTRUE;
|
||||||
ResDoneWithNode(resptr2);
|
ResDoneWithNode(resptr2);
|
||||||
}
|
}
|
||||||
resptr2 = NULL;
|
resptr2 = NULL;
|
||||||
|
|
@ -347,9 +345,9 @@ ResSeriesCheck(resptr)
|
||||||
rr1->rr_connection2 = rr2->rr_connection2;
|
rr1->rr_connection2 = rr2->rr_connection2;
|
||||||
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
|
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
|
||||||
}
|
}
|
||||||
if ((resptr2->rn_status & RES_TRUE) == RES_TRUE)
|
if ((resptr2->rn_status & RESTRUE) == RESTRUE)
|
||||||
{
|
{
|
||||||
resptr2->rn_status &= ~RES_TRUE;
|
resptr2->rn_status &= ~RESTRUE;
|
||||||
ResDoneWithNode(resptr2);
|
ResDoneWithNode(resptr2);
|
||||||
}
|
}
|
||||||
resptr2 = NULL;
|
resptr2 = NULL;
|
||||||
|
|
@ -378,9 +376,9 @@ ResSeriesCheck(resptr)
|
||||||
rr1->rr_connection2 = rr2->rr_connection1;
|
rr1->rr_connection2 = rr2->rr_connection1;
|
||||||
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
|
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
|
||||||
}
|
}
|
||||||
if ((resptr2->rn_status & RES_TRUE) == RES_TRUE)
|
if ((resptr2->rn_status & RESTRUE) == RESTRUE)
|
||||||
{
|
{
|
||||||
resptr2->rn_status &= ~RES_TRUE;
|
resptr2->rn_status &= ~RESTRUE;
|
||||||
ResDoneWithNode(resptr2);
|
ResDoneWithNode(resptr2);
|
||||||
}
|
}
|
||||||
resptr2 = NULL;
|
resptr2 = NULL;
|
||||||
|
|
@ -435,10 +433,10 @@ ResParallelCheck(resptr)
|
||||||
ResFixParallel(r1, r2);
|
ResFixParallel(r1, r2);
|
||||||
status = PARALLEL;
|
status = PARALLEL;
|
||||||
resptr2 = NULL;
|
resptr2 = NULL;
|
||||||
if (resptr3->rn_status & RES_TRUE)
|
if (resptr3->rn_status & RESTRUE)
|
||||||
{
|
{
|
||||||
resptr2 = resptr3;
|
resptr2 = resptr3;
|
||||||
resptr2->rn_status &= ~RES_TRUE;
|
resptr2->rn_status &= ~RESTRUE;
|
||||||
}
|
}
|
||||||
ResDoneWithNode(resptr);
|
ResDoneWithNode(resptr);
|
||||||
if (resptr2 != NULL) ResDoneWithNode(resptr2);
|
if (resptr2 != NULL) ResDoneWithNode(resptr2);
|
||||||
|
|
@ -533,8 +531,8 @@ ResTriangleCheck(resptr)
|
||||||
/* is arbitrarily assigned to the location */
|
/* is arbitrarily assigned to the location */
|
||||||
/* occupied by the first node. */
|
/* occupied by the first node. */
|
||||||
|
|
||||||
InitializeResNode(n3, resptr->rn_loc.p_x, resptr->rn_loc.p_y, TRIANGLE);
|
InitializeNode(n3, resptr->rn_loc.p_x, resptr->rn_loc.p_y, TRIANGLE);
|
||||||
n3->rn_status = RES_FINISHED | RES_TRUE | RES_MARKED;
|
n3->rn_status = FINISHED | RESTRUE | MARKED;
|
||||||
|
|
||||||
n3->rn_less = NULL;
|
n3->rn_less = NULL;
|
||||||
n3->rn_more = ResNodeList;
|
n3->rn_more = ResNodeList;
|
||||||
|
|
@ -582,13 +580,13 @@ ResTriangleCheck(resptr)
|
||||||
element->re_nextEl = n3->rn_re;
|
element->re_nextEl = n3->rn_re;
|
||||||
element->re_thisEl = rr3;
|
element->re_thisEl = rr3;
|
||||||
n3->rn_re = element;
|
n3->rn_re = element;
|
||||||
if ((n1->rn_status & RES_TRUE) == RES_TRUE)
|
if ((n1->rn_status & RESTRUE) == RESTRUE)
|
||||||
n1->rn_status &= ~RES_TRUE;
|
n1->rn_status &= ~RESTRUE;
|
||||||
else
|
else
|
||||||
n1 = NULL;
|
n1 = NULL;
|
||||||
|
|
||||||
if ((n2->rn_status & RES_TRUE) == RES_TRUE)
|
if ((n2->rn_status & RESTRUE) == RESTRUE)
|
||||||
n2->rn_status &= ~RES_TRUE;
|
n2->rn_status &= ~RESTRUE;
|
||||||
else
|
else
|
||||||
n2 = NULL;
|
n2 = NULL;
|
||||||
|
|
||||||
|
|
@ -639,18 +637,15 @@ ResMergeNodes(node1, node2, pendingList, doneList)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't want to merge away start or end points */
|
/* don't want to merge away startpoint */
|
||||||
if (node2->rn_why & RES_NODE_ORIGIN)
|
if (node2->rn_why & RES_NODE_ORIGIN)
|
||||||
node1->rn_why = RES_NODE_ORIGIN;
|
node1->rn_why = RES_NODE_ORIGIN;
|
||||||
|
|
||||||
if (node2->rn_why & RES_NODE_SINK)
|
|
||||||
node1->rn_why = RES_NODE_SINK;
|
|
||||||
|
|
||||||
/* set node resistance */
|
/* set node resistance */
|
||||||
if (node1->rn_noderes > node2->rn_noderes)
|
if (node1->rn_noderes > node2->rn_noderes)
|
||||||
{
|
{
|
||||||
node1->rn_noderes = node2->rn_noderes;
|
node1->rn_noderes = node2->rn_noderes;
|
||||||
if ((node1->rn_status & RES_FINISHED) != RES_FINISHED)
|
if ((node1->rn_status & FINISHED) != FINISHED)
|
||||||
{
|
{
|
||||||
ResRemoveFromQueue(node1, pendingList);
|
ResRemoveFromQueue(node1, pendingList);
|
||||||
ResAddToQueue(node1, pendingList);
|
ResAddToQueue(node1, pendingList);
|
||||||
|
|
@ -659,7 +654,7 @@ ResMergeNodes(node1, node2, pendingList, doneList)
|
||||||
node1->rn_float.rn_area += node2->rn_float.rn_area;
|
node1->rn_float.rn_area += node2->rn_float.rn_area;
|
||||||
|
|
||||||
/* combine relevant flags */
|
/* combine relevant flags */
|
||||||
node1->rn_status |= (node2->rn_status & RES_MAXTDI);
|
node1->rn_status |= (node2->rn_status & RN_MAXTDI);
|
||||||
|
|
||||||
/* merge device lists */
|
/* merge device lists */
|
||||||
workingDev = node2->rn_te;
|
workingDev = node2->rn_te;
|
||||||
|
|
@ -685,13 +680,13 @@ ResMergeNodes(node1, node2, pendingList, doneList)
|
||||||
tJunc = workingJunc;
|
tJunc = workingJunc;
|
||||||
for (i = 0; i < TILES_PER_JUNCTION; i++)
|
for (i = 0; i < TILES_PER_JUNCTION; i++)
|
||||||
{
|
{
|
||||||
resInfo *info;
|
tileJunk *junk;
|
||||||
|
|
||||||
tile = tJunc->je_thisj->rj_Tile[i];
|
tile = tJunc->je_thisj->rj_Tile[i];
|
||||||
info = (resInfo *) TiGetClientPTR(tile);
|
junk = (tileJunk *) TiGetClientPTR(tile);
|
||||||
|
|
||||||
if ((info->ri_status & RES_TILE_DONE) == FALSE)
|
if ((junk->tj_status & RES_TILE_DONE) == FALSE)
|
||||||
ResFixBreakPoint(&info->breakList, node2, node1);
|
ResFixBreakPoint(&junk->breakList, node2, node1);
|
||||||
}
|
}
|
||||||
tJunc->je_thisj->rj_jnode = node1;
|
tJunc->je_thisj->rj_jnode = node1;
|
||||||
workingJunc = workingJunc->je_nextj;
|
workingJunc = workingJunc->je_nextj;
|
||||||
|
|
@ -708,13 +703,13 @@ ResMergeNodes(node1, node2, pendingList, doneList)
|
||||||
{
|
{
|
||||||
if (workingCon->ce_thisc->cp_cnode[i] == node2)
|
if (workingCon->ce_thisc->cp_cnode[i] == node2)
|
||||||
{
|
{
|
||||||
resInfo *info;
|
tileJunk *junk;
|
||||||
|
|
||||||
workingCon->ce_thisc->cp_cnode[i] = node1;
|
workingCon->ce_thisc->cp_cnode[i] = node1;
|
||||||
tile =tCon->ce_thisc->cp_tile[i];
|
tile =tCon->ce_thisc->cp_tile[i];
|
||||||
info = (resInfo *) TiGetClientPTR(tile);
|
junk = (tileJunk *) TiGetClientPTR(tile);
|
||||||
if ((info->ri_status & RES_TILE_DONE) == FALSE)
|
if ((junk->tj_status & RES_TILE_DONE) == FALSE)
|
||||||
ResFixBreakPoint(&info->breakList, node2, node1);
|
ResFixBreakPoint(&junk->breakList, node2, node1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
workingCon = workingCon->ce_nextc;
|
workingCon = workingCon->ce_nextc;
|
||||||
|
|
@ -754,7 +749,7 @@ ResMergeNodes(node1, node2, pendingList, doneList)
|
||||||
tRes->re_nextEl = node1->rn_re;
|
tRes->re_nextEl = node1->rn_re;
|
||||||
node1->rn_re = tRes;
|
node1->rn_re = tRes;
|
||||||
}
|
}
|
||||||
if ((node2->rn_status & RES_FINISHED) == RES_FINISHED)
|
if ((node2->rn_status & FINISHED) == FINISHED)
|
||||||
ResRemoveFromQueue(node2, doneList);
|
ResRemoveFromQueue(node2, doneList);
|
||||||
else
|
else
|
||||||
ResRemoveFromQueue(node2, pendingList);
|
ResRemoveFromQueue(node2, pendingList);
|
||||||
|
|
@ -864,7 +859,7 @@ ResEliminateResistor(resistor, homelist)
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* ResCleanNode--removes the linked lists of junctions and contacts after
|
* ResCleanNode--removes the linked lists of junctions and contacts after
|
||||||
* they are no longer needed. If the 'info' option is used,
|
* they are no longer needed. If the 'junk' option is used,
|
||||||
* the node is eradicated.
|
* the node is eradicated.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
|
|
@ -876,9 +871,9 @@ ResEliminateResistor(resistor, homelist)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ResCleanNode(resptr, info, homelist1, homelist2)
|
ResCleanNode(resptr, junk, homelist1, homelist2)
|
||||||
resNode *resptr;
|
resNode *resptr;
|
||||||
int info;
|
int junk;
|
||||||
resNode **homelist1;
|
resNode **homelist1;
|
||||||
resNode **homelist2;
|
resNode **homelist2;
|
||||||
{
|
{
|
||||||
|
|
@ -901,7 +896,7 @@ ResCleanNode(resptr, info, homelist1, homelist2)
|
||||||
freeMagic((char *)jcell->je_thisj);
|
freeMagic((char *)jcell->je_thisj);
|
||||||
freeMagic((char *)jcell);
|
freeMagic((char *)jcell);
|
||||||
}
|
}
|
||||||
if (info == TRUE)
|
if (junk == TRUE)
|
||||||
{
|
{
|
||||||
if (resptr->rn_client != (ClientData)NULL)
|
if (resptr->rn_client != (ClientData)NULL)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,9 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#define MAXNAME 1000
|
#define MAXNAME 1000
|
||||||
#define KV_TO_mV 1000000
|
#define KV_TO_mV 1000000
|
||||||
|
|
||||||
|
extern ResExtNode *ResInitializeNode();
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -55,7 +58,7 @@ ResPrintExtRes(outextfile, resistors, nodename)
|
||||||
int nodenum=0;
|
int nodenum=0;
|
||||||
char newname[MAXNAME];
|
char newname[MAXNAME];
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
ResExtNode *node;
|
ResExtNode *node, *ResInitializeNode();
|
||||||
|
|
||||||
for (; resistors != NULL; resistors = resistors->rr_nextResistor)
|
for (; resistors != NULL; resistors = resistors->rr_nextResistor)
|
||||||
{
|
{
|
||||||
|
|
@ -70,7 +73,7 @@ ResPrintExtRes(outextfile, resistors, nodename)
|
||||||
{
|
{
|
||||||
(void)sprintf(newname, "%s%s%d", nodename, ".r", nodenum++);
|
(void)sprintf(newname, "%s%s%d", nodename, ".r", nodenum++);
|
||||||
entry = HashFind(&ResNodeTable, newname);
|
entry = HashFind(&ResNodeTable, newname);
|
||||||
node = ResExtInitNode(entry);
|
node = ResInitializeNode(entry);
|
||||||
resistors->rr_connection1->rn_name = node->name;
|
resistors->rr_connection1->rn_name = node->name;
|
||||||
node->oldname = nodename;
|
node->oldname = nodename;
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +81,7 @@ ResPrintExtRes(outextfile, resistors, nodename)
|
||||||
{
|
{
|
||||||
(void)sprintf(newname, "%s%s%d", nodename, ".r", nodenum++);
|
(void)sprintf(newname, "%s%s%d", nodename, ".r", nodenum++);
|
||||||
entry = HashFind(&ResNodeTable, newname);
|
entry = HashFind(&ResNodeTable, newname);
|
||||||
node = ResExtInitNode(entry);
|
node = ResInitializeNode(entry);
|
||||||
resistors->rr_connection2->rn_name = node->name;
|
resistors->rr_connection2->rn_name = node->name;
|
||||||
node->oldname = nodename;
|
node->oldname = nodename;
|
||||||
}
|
}
|
||||||
|
|
@ -219,7 +222,7 @@ ResPrintExtNode(outextfile, nodelist, node)
|
||||||
int nodenum = 0;
|
int nodenum = 0;
|
||||||
char newname[MAXNAME+32], tmpname[MAXNAME], *cp;
|
char newname[MAXNAME+32], tmpname[MAXNAME], *cp;
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
ResExtNode *newnode;
|
ResExtNode *newnode, *ResInitializeNode();
|
||||||
bool DoKillNode = TRUE;
|
bool DoKillNode = TRUE;
|
||||||
bool NeedFix = FALSE;
|
bool NeedFix = FALSE;
|
||||||
resNode *snode;
|
resNode *snode;
|
||||||
|
|
@ -268,7 +271,7 @@ ResPrintExtNode(outextfile, nodelist, node)
|
||||||
|
|
||||||
(void)sprintf(newname, "%s%s%d", tmpname, ".n", nodenum++);
|
(void)sprintf(newname, "%s%s%d", tmpname, ".n", nodenum++);
|
||||||
entry = HashFind(&ResNodeTable, newname);
|
entry = HashFind(&ResNodeTable, newname);
|
||||||
newnode = ResExtInitNode(entry);
|
newnode = ResInitializeNode(entry);
|
||||||
snode->rn_name = newnode->name;
|
snode->rn_name = newnode->name;
|
||||||
newnode->oldname = nodename;
|
newnode->oldname = nodename;
|
||||||
}
|
}
|
||||||
|
|
@ -416,16 +419,16 @@ ResPrintFHNodes(fp, nodelist, nodename, nidx, celldef)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
ResExtNode *extnode;
|
ResExtNode *simnode;
|
||||||
|
|
||||||
/* If we process another sim file node while doing this */
|
/* If we process another sim file node while doing this */
|
||||||
/* one, mark it as status "REDUNDANT" so we don't duplicate */
|
/* one, mark it as status "REDUNDANT" so we don't duplicate */
|
||||||
/* the entry. */
|
/* the entry. */
|
||||||
|
|
||||||
entry = HashFind(&ResNodeTable, nodeptr->rn_name);
|
entry = HashFind(&ResNodeTable, nodeptr->rn_name);
|
||||||
extnode = (ResExtNode *)HashGetValue(entry);
|
simnode = (ResExtNode *)HashGetValue(entry);
|
||||||
if (extnode != NULL)
|
if (simnode != NULL)
|
||||||
extnode->status |= REDUNDANT;
|
simnode->status |= REDUNDANT;
|
||||||
}
|
}
|
||||||
resWriteNodeName(fp, nodeptr);
|
resWriteNodeName(fp, nodeptr);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#define DEV_NAME 2
|
#define DEV_NAME 2
|
||||||
#define DEV_X 3
|
#define DEV_X 3
|
||||||
#define DEV_Y 4
|
#define DEV_Y 4
|
||||||
#define DEV_PARAM_START 7
|
|
||||||
|
|
||||||
#define NODES_NODENAME 1
|
#define NODES_NODENAME 1
|
||||||
#define NODES_NODEX 4
|
#define NODES_NODEX 4
|
||||||
|
|
@ -84,6 +83,8 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
|
|
||||||
#define MAXDIGIT 20
|
#define MAXDIGIT 20
|
||||||
|
|
||||||
|
ResExtNode *ResInitializeNode();
|
||||||
|
|
||||||
ResExtNode *ResOriginalNodes; /*Linked List of Nodes */
|
ResExtNode *ResOriginalNodes; /*Linked List of Nodes */
|
||||||
char RDEV_NOATTR[1] = {'0'};
|
char RDEV_NOATTR[1] = {'0'};
|
||||||
ResFixPoint *ResFixList;
|
ResFixPoint *ResFixList;
|
||||||
|
|
@ -101,7 +102,7 @@ ResFixPoint *ResFixList;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
ResReadExt(CellDef *def)
|
ResReadExt(char *extfile)
|
||||||
{
|
{
|
||||||
char *line = NULL, *argv[128];
|
char *line = NULL, *argv[128];
|
||||||
int result, locresult;
|
int result, locresult;
|
||||||
|
|
@ -110,12 +111,30 @@ ResReadExt(CellDef *def)
|
||||||
CellDef *dbdef;
|
CellDef *dbdef;
|
||||||
ResExtNode *curnode;
|
ResExtNode *curnode;
|
||||||
|
|
||||||
/* Search for the .ext file in the same way that efReadDef() does. */
|
/* Search for the .ext fie in the same way that efReadDef() does. */
|
||||||
|
|
||||||
|
fp = PaOpen(extfile, "r", ".ext", EFSearchPath, EFLibPath, (char **)NULL);
|
||||||
|
if ((fp == NULL) && (dbdef = DBCellLookDef(extfile)) != NULL)
|
||||||
|
{
|
||||||
|
char *filepath, *sptr;
|
||||||
|
|
||||||
|
filepath = StrDup((char **)NULL, dbdef->cd_file);
|
||||||
|
sptr = strrchr(filepath, '/');
|
||||||
|
if (sptr)
|
||||||
|
{
|
||||||
|
*sptr = '\0';
|
||||||
|
fp = PaOpen(extfile, "r", ".ext", filepath, EFLibPath, (char **)NULL);
|
||||||
|
}
|
||||||
|
freeMagic(filepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try with the standard search path */
|
||||||
|
if ((fp == NULL) && (EFSearchPath == NULL))
|
||||||
|
fp = PaOpen(extfile, "r", ".ext", Path, EFLibPath, (char **)NULL);
|
||||||
|
|
||||||
fp = ExtFileOpen(def, (char *)NULL, "r", (char **)NULL);
|
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
{
|
{
|
||||||
TxError("Cannot open file %s%s\n", def->cd_name, ".ext");
|
TxError("Cannot open file %s%s\n", extfile, ".ext");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,15 +165,6 @@ ResReadExt(CellDef *def)
|
||||||
*/
|
*/
|
||||||
switch (keyTable[n].k_key)
|
switch (keyTable[n].k_key)
|
||||||
{
|
{
|
||||||
case SCALE:
|
|
||||||
/* NOTE: Currently the code assumes that the .ext
|
|
||||||
* file is read back immediately and has the same
|
|
||||||
* scale values currently in the extraction style.
|
|
||||||
* However, this should be style-independent and
|
|
||||||
* scale values should be read back and used.
|
|
||||||
* (to be completed).
|
|
||||||
*/
|
|
||||||
break;
|
|
||||||
case DEVICE:
|
case DEVICE:
|
||||||
locresult = ResReadDevice(argc, argv);
|
locresult = ResReadDevice(argc, argv);
|
||||||
break;
|
break;
|
||||||
|
|
@ -209,18 +219,11 @@ ResReadNode(int argc, char *argv[])
|
||||||
ResExtNode *node;
|
ResExtNode *node;
|
||||||
|
|
||||||
entry = HashFind(&ResNodeTable, argv[NODES_NODENAME]);
|
entry = HashFind(&ResNodeTable, argv[NODES_NODENAME]);
|
||||||
node = ResExtInitNode(entry);
|
node = ResInitializeNode(entry);
|
||||||
|
|
||||||
node->location.p_x = atoi(argv[NODES_NODEX]);
|
node->location.p_x = atoi(argv[NODES_NODEX]);
|
||||||
node->location.p_y = atoi(argv[NODES_NODEY]);
|
node->location.p_y = atoi(argv[NODES_NODEY]);
|
||||||
|
|
||||||
/* If this node was previously read as a port, then don't change the
|
|
||||||
* node type, which is tracking the type at the drivepoint.
|
|
||||||
*/
|
|
||||||
if (!(node->status & PORTNODE))
|
|
||||||
{
|
|
||||||
node->type = DBTechNameType(argv[NODES_NODETYPE]);
|
node->type = DBTechNameType(argv[NODES_NODETYPE]);
|
||||||
}
|
|
||||||
|
|
||||||
if (node->type == -1)
|
if (node->type == -1)
|
||||||
{
|
{
|
||||||
|
|
@ -251,7 +254,7 @@ ResReadPort(int argc,
|
||||||
ResExtNode *node;
|
ResExtNode *node;
|
||||||
|
|
||||||
entry = HashFind(&ResNodeTable, argv[PORT_NAME]);
|
entry = HashFind(&ResNodeTable, argv[PORT_NAME]);
|
||||||
node = ResExtInitNode(entry);
|
node = ResInitializeNode(entry);
|
||||||
|
|
||||||
node->drivepoint.p_x = atoi(argv[PORT_LLX]);
|
node->drivepoint.p_x = atoi(argv[PORT_LLX]);
|
||||||
node->drivepoint.p_y = atoi(argv[PORT_LLY]);
|
node->drivepoint.p_y = atoi(argv[PORT_LLY]);
|
||||||
|
|
@ -331,11 +334,11 @@ ResReadDevice(int argc,
|
||||||
TileType ttype;
|
TileType ttype;
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
ResExtNode *node;
|
ResExtNode *node;
|
||||||
ResValue rpersquare;
|
|
||||||
float wval;
|
|
||||||
|
|
||||||
device = (RDev *)mallocMagic((unsigned)(sizeof(RDev)));
|
device = (RDev *)mallocMagic((unsigned)(sizeof(RDev)));
|
||||||
|
|
||||||
|
device->resistance = 0; /* Linear resistance from FET line, unused */
|
||||||
|
|
||||||
device->status = FALSE;
|
device->status = FALSE;
|
||||||
device->nextDev = ResRDevList;
|
device->nextDev = ResRDevList;
|
||||||
|
|
||||||
|
|
@ -361,25 +364,10 @@ ResReadDevice(int argc,
|
||||||
device->drain = (ResExtNode *)NULL;
|
device->drain = (ResExtNode *)NULL;
|
||||||
device->subs = (ResExtNode *)NULL;
|
device->subs = (ResExtNode *)NULL;
|
||||||
|
|
||||||
entry = HashLookOnly(&devptr->exts_deviceResist, "linear");
|
/* Pass over parameters and find the next argument */
|
||||||
if (entry != NULL)
|
|
||||||
rpersquare = (ResValue)(spointertype)HashGetValue(entry);
|
|
||||||
else
|
|
||||||
rpersquare = (ResValue)10000.0; /* Default to a sane value */
|
|
||||||
|
|
||||||
/* For devices, the device width is in the parameter list */
|
|
||||||
wval = 0.0;
|
|
||||||
for (i = DEV_Y; i < argc; i++)
|
for (i = DEV_Y; i < argc; i++)
|
||||||
{
|
if (!StrIsInt(argv[i]) && !(strchr(argv[i], '=')))
|
||||||
char *eptr;
|
|
||||||
if ((eptr = strchr(argv[i], '=')) != NULL)
|
|
||||||
{
|
|
||||||
if (*argv[i] == 'w')
|
|
||||||
sscanf(eptr + 1, "%f", &wval);
|
|
||||||
}
|
|
||||||
else if (!StrIsInt(argv[i]))
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
if (i == argc)
|
if (i == argc)
|
||||||
{
|
{
|
||||||
|
|
@ -387,8 +375,6 @@ ResReadDevice(int argc,
|
||||||
argv[DEV_NAME]);
|
argv[DEV_NAME]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
device->resistance = wval * rpersquare; /* Channel resistance */
|
|
||||||
|
|
||||||
/* Find and record the device terminal nodes */
|
/* Find and record the device terminal nodes */
|
||||||
/* Note that this only records up to two terminals matching FET
|
/* Note that this only records up to two terminals matching FET
|
||||||
|
|
@ -461,11 +447,11 @@ ResReadFET(int argc,
|
||||||
TileType ttype;
|
TileType ttype;
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
ResExtNode *node;
|
ResExtNode *node;
|
||||||
ResValue rpersquare;
|
|
||||||
float area, perim, wval, lval;
|
|
||||||
|
|
||||||
device = (RDev *)mallocMagic((unsigned)(sizeof(RDev)));
|
device = (RDev *)mallocMagic((unsigned)(sizeof(RDev)));
|
||||||
|
|
||||||
|
device->resistance = 0; /* Linear resistance from FET line, unused */
|
||||||
|
|
||||||
device->status = FALSE;
|
device->status = FALSE;
|
||||||
device->nextDev = ResRDevList;
|
device->nextDev = ResRDevList;
|
||||||
|
|
||||||
|
|
@ -487,20 +473,6 @@ ResReadFET(int argc,
|
||||||
device->rs_dattr=RDEV_NOATTR;
|
device->rs_dattr=RDEV_NOATTR;
|
||||||
device->rs_devptr = devptr;
|
device->rs_devptr = devptr;
|
||||||
|
|
||||||
entry = HashLookOnly(&devptr->exts_deviceResist, "linear");
|
|
||||||
if (entry != NULL)
|
|
||||||
rpersquare = (ResValue)(spointertype)HashGetValue(entry);
|
|
||||||
else
|
|
||||||
rpersquare = (ResValue)10000.0; /* Default to a sane value */
|
|
||||||
|
|
||||||
/* For old-style FETs, the width is determined from area and perimeter */
|
|
||||||
area = MagAtof(argv[FET_AREA]);
|
|
||||||
perim = MagAtof(argv[FET_PERIM]);
|
|
||||||
lval = 0.5 * (perim + sqrt(perim * perim - 4 * area));
|
|
||||||
wval = area / lval;
|
|
||||||
|
|
||||||
device->resistance = wval * rpersquare; /* Channel resistance */
|
|
||||||
|
|
||||||
/* Find and record the FET terminal nodes */
|
/* Find and record the FET terminal nodes */
|
||||||
|
|
||||||
entry = HashFind(&ResNodeTable, argv[FET_GATE]);
|
entry = HashFind(&ResNodeTable, argv[FET_GATE]);
|
||||||
|
|
@ -550,19 +522,19 @@ ResReadCapacitor(int argc,
|
||||||
ResExtNode *node1, *node2;
|
ResExtNode *node1, *node2;
|
||||||
|
|
||||||
entry1 = HashFind(&ResNodeTable, argv[COUPLETERMINAL1]);
|
entry1 = HashFind(&ResNodeTable, argv[COUPLETERMINAL1]);
|
||||||
node1 = ResExtInitNode(entry1);
|
node1 = ResInitializeNode(entry1);
|
||||||
|
|
||||||
if (ResOptionsFlags & ResOpt_Signal)
|
if (ResOptionsFlags & ResOpt_Signal)
|
||||||
{
|
{
|
||||||
node1->capacitance += MagAtof(argv[COUPLEVALUE]);
|
node1->capacitance += MagAtof(argv[COUPLEVALUE]);
|
||||||
entry2 = HashFind(&ResNodeTable, argv[COUPLETERMINAL2]);
|
entry2 = HashFind(&ResNodeTable, argv[COUPLETERMINAL2]);
|
||||||
node2 = ResExtInitNode(entry2);
|
node2 = ResInitializeNode(entry2);
|
||||||
node2->capacitance += MagAtof(argv[COUPLEVALUE]);
|
node2->capacitance += MagAtof(argv[COUPLEVALUE]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry2 = HashFind(&ResNodeTable, argv[COUPLETERMINAL2]);
|
entry2 = HashFind(&ResNodeTable, argv[COUPLETERMINAL2]);
|
||||||
node2 = ResExtInitNode(entry2);
|
node2 = ResInitializeNode(entry2);
|
||||||
|
|
||||||
node1->cap_couple += MagAtof(argv[COUPLEVALUE]);
|
node1->cap_couple += MagAtof(argv[COUPLEVALUE]);
|
||||||
node2->cap_couple += MagAtof(argv[COUPLEVALUE]);
|
node2->cap_couple += MagAtof(argv[COUPLEVALUE]);
|
||||||
|
|
@ -639,7 +611,7 @@ ResReadAttribute(ResExtNode *node,
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* ResExtInitNode --
|
* ResInitializeNode --
|
||||||
* Gets the node corresponding to a given hash table entry. If no
|
* Gets the node corresponding to a given hash table entry. If no
|
||||||
* such node exists, one is created.
|
* such node exists, one is created.
|
||||||
*
|
*
|
||||||
|
|
@ -651,7 +623,7 @@ ResReadAttribute(ResExtNode *node,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ResExtNode *
|
ResExtNode *
|
||||||
ResExtInitNode(entry)
|
ResInitializeNode(entry)
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
{
|
{
|
||||||
ResExtNode *node;
|
ResExtNode *node;
|
||||||
|
|
@ -665,6 +637,7 @@ ResExtInitNode(entry)
|
||||||
node->status = FALSE;
|
node->status = FALSE;
|
||||||
node->forward = (ResExtNode *) NULL;
|
node->forward = (ResExtNode *) NULL;
|
||||||
node->capacitance = 0;
|
node->capacitance = 0;
|
||||||
|
node->cap_vdd = 0;
|
||||||
node->cap_couple = 0;
|
node->cap_couple = 0;
|
||||||
node->resistance = 0;
|
node->resistance = 0;
|
||||||
node->type = 0;
|
node->type = 0;
|
||||||
|
|
@ -675,6 +648,8 @@ ResExtInitNode(entry)
|
||||||
node->drivepoint.p_y = INFINITY;
|
node->drivepoint.p_y = INFINITY;
|
||||||
node->location.p_x = INFINITY;
|
node->location.p_x = INFINITY;
|
||||||
node->location.p_y = INFINITY;
|
node->location.p_y = INFINITY;
|
||||||
|
node->rs_sublist[0] = NULL;
|
||||||
|
node->rs_sublist[1] = NULL;
|
||||||
}
|
}
|
||||||
while (node->status & FORWARD)
|
while (node->status & FORWARD)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
130
resis/ResRex.c
130
resis/ResRex.c
|
|
@ -30,7 +30,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
#include "utils/tech.h"
|
#include "utils/tech.h"
|
||||||
#include "textio/txcommands.h"
|
#include "textio/txcommands.h"
|
||||||
#include "commands/commands.h"
|
|
||||||
#include "resis/resis.h"
|
#include "resis/resis.h"
|
||||||
|
|
||||||
#define INITFLATSIZE 1024
|
#define INITFLATSIZE 1024
|
||||||
|
|
@ -71,6 +70,10 @@ FILE *ResFHFile;
|
||||||
|
|
||||||
int ResPortIndex; /* Port ordering to backannotate into magic */
|
int ResPortIndex; /* Port ordering to backannotate into magic */
|
||||||
|
|
||||||
|
/* external declarations */
|
||||||
|
extern ResExtNode *ResInitializeNode();
|
||||||
|
extern CellUse *CmdGetSelectedCell();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -111,7 +114,7 @@ ExtResisForDef(celldef, resisdata)
|
||||||
|
|
||||||
HashInit(&ResNodeTable, INITFLATSIZE, HT_STRINGKEYS);
|
HashInit(&ResNodeTable, INITFLATSIZE, HT_STRINGKEYS);
|
||||||
/* Read in the .ext file */
|
/* Read in the .ext file */
|
||||||
result = (ResReadExt(celldef) == 0);
|
result = (ResReadExt(celldef->cd_name) == 0);
|
||||||
|
|
||||||
/* Clean up the EFDevTypes table */
|
/* Clean up the EFDevTypes table */
|
||||||
for (idx = 0; idx < EFDevNumTypes; idx++) freeMagic(EFDevTypes[idx]);
|
for (idx = 0; idx < EFDevNumTypes; idx++) freeMagic(EFDevTypes[idx]);
|
||||||
|
|
@ -128,7 +131,7 @@ ExtResisForDef(celldef, resisdata)
|
||||||
DBIsSubcircuit(celldef))
|
DBIsSubcircuit(celldef))
|
||||||
ResCheckExtNodes(celldef, resisdata);
|
ResCheckExtNodes(celldef, resisdata);
|
||||||
|
|
||||||
if (ResOptionsFlags & ResOpt_Stats)
|
if (ResOptionsFlags & ResOpt_Stat)
|
||||||
ResPrintStats((ResisData *)NULL, "");
|
ResPrintStats((ResisData *)NULL, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -281,7 +284,6 @@ CmdExtResis(win, cmd)
|
||||||
"blackbox [on/off] treat subcircuits with ports as black boxes",
|
"blackbox [on/off] treat subcircuits with ports as black boxes",
|
||||||
"fasthenry [freq] extract subcircuit network geometry into .fh file",
|
"fasthenry [freq] extract subcircuit network geometry into .fh file",
|
||||||
"geometry extract network centerline geometry (experimental)",
|
"geometry extract network centerline geometry (experimental)",
|
||||||
"stats print extresist statistics",
|
|
||||||
"help print this message",
|
"help print this message",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
@ -291,8 +293,8 @@ typedef enum {
|
||||||
RES_THRESH, RES_TOL,
|
RES_THRESH, RES_TOL,
|
||||||
RES_SIMP, RES_EXTOUT, RES_LUMPED, RES_SILENT,
|
RES_SIMP, RES_EXTOUT, RES_LUMPED, RES_SILENT,
|
||||||
RES_SKIP, RES_IGNORE, RES_INCLUDE, RES_BOX, RES_CELL,
|
RES_SKIP, RES_IGNORE, RES_INCLUDE, RES_BOX, RES_CELL,
|
||||||
RES_BLACKBOX, RES_FASTHENRY, RES_GEOMETRY, RES_STATS,
|
RES_BLACKBOX, RES_FASTHENRY, RES_GEOMETRY, RES_HELP,
|
||||||
RES_HELP, RES_RUN
|
RES_RUN
|
||||||
} ResOptions;
|
} ResOptions;
|
||||||
|
|
||||||
resisdata = ResInit();
|
resisdata = ResInit();
|
||||||
|
|
@ -322,6 +324,7 @@ typedef enum {
|
||||||
switch (option)
|
switch (option)
|
||||||
{
|
{
|
||||||
case RES_TOL:
|
case RES_TOL:
|
||||||
|
ResOptionsFlags |= ResOpt_ExplicitRtol;
|
||||||
if (cmd->tx_argc > 2)
|
if (cmd->tx_argc > 2)
|
||||||
{
|
{
|
||||||
resisdata->tdiTolerance = MagAtof(cmd->tx_argv[2]);
|
resisdata->tdiTolerance = MagAtof(cmd->tx_argv[2]);
|
||||||
|
|
@ -409,23 +412,6 @@ typedef enum {
|
||||||
ResOptionsFlags &= ~ResOpt_Blackbox;
|
ResOptionsFlags &= ~ResOpt_Blackbox;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case RES_STATS:
|
|
||||||
if (cmd->tx_argc == 2)
|
|
||||||
{
|
|
||||||
value = (ResOptionsFlags & ResOpt_Stats) ?
|
|
||||||
TRUE : FALSE;
|
|
||||||
TxPrintf("%s\n", onOff[value]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value = Lookup(cmd->tx_argv[2], onOff);
|
|
||||||
|
|
||||||
if (value)
|
|
||||||
ResOptionsFlags |= ResOpt_Stats;
|
|
||||||
else
|
|
||||||
ResOptionsFlags &= ~ResOpt_Stats;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case RES_SIMP:
|
case RES_SIMP:
|
||||||
if (cmd->tx_argc == 2)
|
if (cmd->tx_argc == 2)
|
||||||
{
|
{
|
||||||
|
|
@ -798,7 +784,7 @@ resPortFunc(scx, lab, tpath, result)
|
||||||
sprintf(nodename, "%s/%s", scx->scx_use->cu_id, lab->lab_text);
|
sprintf(nodename, "%s/%s", scx->scx_use->cu_id, lab->lab_text);
|
||||||
|
|
||||||
entry = HashFind(&ResNodeTable, nodename);
|
entry = HashFind(&ResNodeTable, nodename);
|
||||||
node = ResExtInitNode(entry);
|
node = ResInitializeNode(entry);
|
||||||
|
|
||||||
/* Digital outputs are drivers */
|
/* Digital outputs are drivers */
|
||||||
if (pclass == PORT_CLASS_OUTPUT) node->status |= FORCE;
|
if (pclass == PORT_CLASS_OUTPUT) node->status |= FORCE;
|
||||||
|
|
@ -930,7 +916,7 @@ ResCheckPorts(cellDef)
|
||||||
/* We have to make sure it's listed as a separate node */
|
/* We have to make sure it's listed as a separate node */
|
||||||
/* and a drivepoint. */
|
/* and a drivepoint. */
|
||||||
|
|
||||||
node = ResExtInitNode(entry);
|
node = ResInitializeNode(entry);
|
||||||
TxPrintf("Port: name = %s is new node %p\n",
|
TxPrintf("Port: name = %s is new node %p\n",
|
||||||
lab->lab_text, (void *)node);
|
lab->lab_text, (void *)node);
|
||||||
TxPrintf("Location is (%d, %d); drivepoint (%d, %d)\n",
|
TxPrintf("Location is (%d, %d); drivepoint (%d, %d)\n",
|
||||||
|
|
@ -1057,16 +1043,19 @@ ResProcessNode(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Special handling for FORCE and DRIVELOC labels: */
|
/* special handling for FORCE and DRIVELOC labels: */
|
||||||
/* Set minRes = node->minsizeres if it exists, 0 otherwise. */
|
/* set minRes = node->minsizeres if it exists, 0 otherwise */
|
||||||
|
|
||||||
if (node->status & (FORCE|DRIVELOC))
|
if (node->status & (FORCE|DRIVELOC))
|
||||||
{
|
{
|
||||||
if (node->status & MINSIZE)
|
if (node->status & MINSIZE)
|
||||||
|
{
|
||||||
minRes = node->minsizeres;
|
minRes = node->minsizeres;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
minRes = 0;
|
minRes = 0;
|
||||||
|
}
|
||||||
if (node->status & DRIVELOC)
|
if (node->status & DRIVELOC)
|
||||||
{
|
{
|
||||||
resisdata->rg_devloc = &node->drivepoint;
|
resisdata->rg_devloc = &node->drivepoint;
|
||||||
|
|
@ -1285,27 +1274,25 @@ ResCheckExtNodes(celldef, resisdata)
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* ResFixUpConnections--
|
* ResFixUpConnections-- Changes the connection to a terminal of the sim
|
||||||
* Changes the connection to a terminal of a device.
|
* device. The new name is formed by appending .t# to the old name.
|
||||||
* The new name is formed by appending .t# to the old name.
|
|
||||||
* The new name is added to the hash table of node names.
|
* The new name is added to the hash table of node names.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:none
|
||||||
* None.
|
|
||||||
*
|
*
|
||||||
* Side Effects:
|
* Side Effects: Allocates new ResExtNodes. Modifies the terminal connections
|
||||||
* Allocates new ResExtNodes. Modifies the terminal connections
|
* of ext Devices.
|
||||||
* of devices.
|
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
ResFixUpConnections(simDev, layoutDev, simNode, nodename)
|
||||||
RDev *extDev;
|
RDev *simDev;
|
||||||
resDevice *layoutDev;
|
resDevice *layoutDev;
|
||||||
ResExtNode *extNode;
|
ResExtNode *simNode;
|
||||||
char *nodename;
|
char *nodename;
|
||||||
|
|
||||||
{
|
{
|
||||||
static char newname[MAXNAME], oldnodename[MAXNAME];
|
static char newname[MAXNAME], oldnodename[MAXNAME];
|
||||||
int notdecremented;
|
int notdecremented;
|
||||||
|
|
@ -1314,15 +1301,15 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
||||||
/* If we aren't doing output (i.e. this is just a statistical run) */
|
/* If we aren't doing output (i.e. this is just a statistical run) */
|
||||||
/* don't patch up networks. This cuts down on memory use. */
|
/* don't patch up networks. This cuts down on memory use. */
|
||||||
|
|
||||||
if ((ResOptionsFlags & ResOpt_DoExtFile) == 0)
|
if ((ResOptionsFlags & (ResOpt_DoRsmFile | ResOpt_DoExtFile)) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (extDev->layout == NULL)
|
if (simDev->layout == NULL)
|
||||||
{
|
{
|
||||||
layoutDev->rd_status |= RES_DEV_SAVE;
|
layoutDev->rd_status |= RES_DEV_SAVE;
|
||||||
extDev->layout = layoutDev;
|
simDev->layout = layoutDev;
|
||||||
}
|
}
|
||||||
extDev->status |= TRUE;
|
simDev->status |= TRUE;
|
||||||
if (strcmp(nodename, oldnodename) != 0)
|
if (strcmp(nodename, oldnodename) != 0)
|
||||||
{
|
{
|
||||||
strcpy(oldnodename, nodename);
|
strcpy(oldnodename, nodename);
|
||||||
|
|
@ -1330,7 +1317,7 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
||||||
sprintf(newname, "%s%s%d", nodename, ".t", resNodeNum++);
|
sprintf(newname, "%s%s%d", nodename, ".t", resNodeNum++);
|
||||||
notdecremented = TRUE;
|
notdecremented = TRUE;
|
||||||
|
|
||||||
if (extDev->gate == extNode)
|
if (simDev->gate == simNode)
|
||||||
{
|
{
|
||||||
if ((gate = layoutDev->rd_fet_gate) != NULL)
|
if ((gate = layoutDev->rd_fet_gate) != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -1342,8 +1329,8 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
||||||
notdecremented = FALSE;
|
notdecremented = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResFixDevName(newname, GATE, extDev, gate);
|
ResFixDevName(newname, GATE, simDev, gate);
|
||||||
gate->rn_name = extDev->gate->name;
|
gate->rn_name = simDev->gate->name;
|
||||||
sprintf(newname, "%s%s%d", nodename, ".t", resNodeNum++);
|
sprintf(newname, "%s%s%d", nodename, ".t", resNodeNum++);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1351,10 +1338,10 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
||||||
TxError("Missing gate connection of device at (%d %d) on net %s\n",
|
TxError("Missing gate connection of device at (%d %d) on net %s\n",
|
||||||
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
||||||
nodename);
|
nodename);
|
||||||
extNode->status |= DONTKILL;
|
simNode->status |= DONTKILL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (extDev->subs == extNode)
|
if (simDev->subs == simNode)
|
||||||
{
|
{
|
||||||
if ((subs = layoutDev->rd_fet_subs) != NULL)
|
if ((subs = layoutDev->rd_fet_subs) != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -1363,8 +1350,8 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
||||||
resNodeNum--;
|
resNodeNum--;
|
||||||
notdecremented = FALSE;
|
notdecremented = FALSE;
|
||||||
}
|
}
|
||||||
ResFixDevName(newname, SUBS, extDev, subs);
|
ResFixDevName(newname, SUBS, simDev, subs);
|
||||||
subs->rn_name = extDev->subs->name;
|
subs->rn_name = simDev->subs->name;
|
||||||
sprintf(newname, "%s%s%d", nodename, ".t", resNodeNum++);
|
sprintf(newname, "%s%s%d", nodename, ".t", resNodeNum++);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1372,11 +1359,11 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
||||||
TxError("Missing substrate connection of device at (%d %d) on net %s\n",
|
TxError("Missing substrate connection of device at (%d %d) on net %s\n",
|
||||||
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
||||||
nodename);
|
nodename);
|
||||||
extNode->status |= DONTKILL;
|
simNode->status |= DONTKILL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extDev->source == extNode)
|
if (simDev->source == simNode)
|
||||||
{
|
{
|
||||||
/* Check for devices with only one terminal. If it was cast as drain, */
|
/* Check for devices with only one terminal. If it was cast as drain, */
|
||||||
/* then swap it with the source so that the code below handles it */
|
/* then swap it with the source so that the code below handles it */
|
||||||
|
|
@ -1388,13 +1375,13 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
||||||
layoutDev->rd_fet_drain = (struct resnode *)NULL;
|
layoutDev->rd_fet_drain = (struct resnode *)NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extDev->drain == extNode)
|
if (simDev->drain == simNode)
|
||||||
{
|
{
|
||||||
if ((layoutDev->rd_fet_source != NULL) &&
|
if ((layoutDev->rd_fet_source != NULL) &&
|
||||||
(layoutDev->rd_fet_drain == NULL))
|
(layoutDev->rd_fet_drain == NULL))
|
||||||
{
|
{
|
||||||
/* Handle source/drain-tied devices */
|
/* Handle source/drain-tied devices */
|
||||||
if (extDev->drain == extDev->source)
|
if (simDev->drain == simDev->source)
|
||||||
layoutDev->rd_fet_drain = layoutDev->rd_fet_source;
|
layoutDev->rd_fet_drain = layoutDev->rd_fet_source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1406,12 +1393,12 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
||||||
resNodeNum--;
|
resNodeNum--;
|
||||||
notdecremented = FALSE;
|
notdecremented = FALSE;
|
||||||
}
|
}
|
||||||
ResFixDevName(newname, SOURCE, extDev, source);
|
ResFixDevName(newname, SOURCE, simDev, source);
|
||||||
source->rn_name = extDev->source->name;
|
source->rn_name = simDev->source->name;
|
||||||
(void)sprintf(newname, "%s%s%d", nodename, ".t", resNodeNum++);
|
(void)sprintf(newname, "%s%s%d", nodename, ".t", resNodeNum++);
|
||||||
if (drain->rn_name != NULL) resNodeNum--;
|
if (drain->rn_name != NULL) resNodeNum--;
|
||||||
ResFixDevName(newname, DRAIN, extDev, drain);
|
ResFixDevName(newname, DRAIN, simDev, drain);
|
||||||
drain->rn_name = extDev->drain->name;
|
drain->rn_name = simDev->drain->name;
|
||||||
/* one to each */
|
/* one to each */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1419,7 +1406,7 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
||||||
TxError("Missing terminal connection of device at (%d %d) on net %s\n",
|
TxError("Missing terminal connection of device at (%d %d) on net %s\n",
|
||||||
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
||||||
nodename);
|
nodename);
|
||||||
extNode->status |= DONTKILL;
|
simNode->status |= DONTKILL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1430,7 +1417,7 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
||||||
{
|
{
|
||||||
if (source != drain)
|
if (source != drain)
|
||||||
{
|
{
|
||||||
if (drain->rn_why & (RES_NODE_ORIGIN | RES_NODE_SINK))
|
if (drain->rn_why & RES_NODE_ORIGIN)
|
||||||
{
|
{
|
||||||
ResMergeNodes(drain, source, &ResNodeQueue,
|
ResMergeNodes(drain, source, &ResNodeQueue,
|
||||||
&ResNodeList);
|
&ResNodeList);
|
||||||
|
|
@ -1456,8 +1443,8 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
||||||
notdecremented = FALSE;
|
notdecremented = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResFixDevName(newname, SOURCE, extDev, source);
|
ResFixDevName(newname, SOURCE, simDev, source);
|
||||||
source->rn_name = extDev->source->name;
|
source->rn_name = simDev->source->name;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1465,11 +1452,11 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
||||||
TxError("Missing terminal connection of device at (%d %d) on net %s\n",
|
TxError("Missing terminal connection of device at (%d %d) on net %s\n",
|
||||||
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
||||||
nodename);
|
nodename);
|
||||||
extNode->status |= DONTKILL;
|
simNode->status |= DONTKILL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (extDev->drain == extNode)
|
else if (simDev->drain == simNode)
|
||||||
{
|
{
|
||||||
/* Check for devices with only one terminal. If it was cast as source, */
|
/* Check for devices with only one terminal. If it was cast as source, */
|
||||||
/* then swap it with the drain so that the code below handles it */
|
/* then swap it with the drain so that the code below handles it */
|
||||||
|
|
@ -1487,7 +1474,7 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
||||||
{
|
{
|
||||||
if (drain != source)
|
if (drain != source)
|
||||||
{
|
{
|
||||||
if (source->rn_why & (RES_NODE_ORIGIN | RES_NODE_SINK))
|
if (source->rn_why & ORIGIN)
|
||||||
{
|
{
|
||||||
ResMergeNodes(source, drain, &ResNodeQueue,
|
ResMergeNodes(source, drain, &ResNodeQueue,
|
||||||
&ResNodeList);
|
&ResNodeList);
|
||||||
|
|
@ -1517,15 +1504,15 @@ ResFixUpConnections(extDev, layoutDev, extNode, nodename)
|
||||||
notdecremented = FALSE;
|
notdecremented = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResFixDevName(newname, DRAIN, extDev, drain);
|
ResFixDevName(newname, DRAIN, simDev, drain);
|
||||||
drain->rn_name = extDev->drain->name;
|
drain->rn_name = simDev->drain->name;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TxError("Missing terminal connection of device at (%d %d) on net %s\n",
|
TxError("Missing terminal connection of device at (%d %d) on net %s\n",
|
||||||
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
layoutDev->rd_inside.r_xbot, layoutDev->rd_inside.r_ybot,
|
||||||
nodename);
|
nodename);
|
||||||
extNode->status |= DONTKILL;
|
simNode->status |= DONTKILL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1561,13 +1548,13 @@ ResFixDevName(line, type, device, layoutnode)
|
||||||
if (layoutnode->rn_name != NULL)
|
if (layoutnode->rn_name != NULL)
|
||||||
{
|
{
|
||||||
entry = HashFind(&ResNodeTable, layoutnode->rn_name);
|
entry = HashFind(&ResNodeTable, layoutnode->rn_name);
|
||||||
node = ResExtInitNode(entry);
|
node = ResInitializeNode(entry);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
entry = HashFind(&ResNodeTable, line);
|
entry = HashFind(&ResNodeTable, line);
|
||||||
node = ResExtInitNode(entry);
|
node = ResInitializeNode(entry);
|
||||||
}
|
}
|
||||||
tptr = (devPtr *) mallocMagic((unsigned) (sizeof(devPtr)));
|
tptr = (devPtr *) mallocMagic((unsigned) (sizeof(devPtr)));
|
||||||
tptr->thisDev = device;
|
tptr->thisDev = device;
|
||||||
|
|
@ -1838,9 +1825,6 @@ ResWriteExtFile(celldef, node, resisdata, nidx, eidx)
|
||||||
node->name, resisdata->rg_Tdi / Z_TO_P, RCdev / Z_TO_P);
|
node->name, resisdata->rg_Tdi / Z_TO_P, RCdev / Z_TO_P);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
TxPrintf("Adding %s\n", node->name);
|
|
||||||
|
|
||||||
for (ptr = node->firstDev; ptr != NULL; ptr=ptr->nextDev)
|
for (ptr = node->firstDev; ptr != NULL; ptr=ptr->nextDev)
|
||||||
{
|
{
|
||||||
if ((layoutDev = ResGetDevice(&ptr->thisDev->location, ptr->thisDev->rs_ttype)))
|
if ((layoutDev = ResGetDevice(&ptr->thisDev->location, ptr->thisDev->rs_ttype)))
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ ResSimplifyNet(nodelist, biglist, reslist, tolerance)
|
||||||
|
|
||||||
if (*nodelist == NULL) return;
|
if (*nodelist == NULL) return;
|
||||||
node = *nodelist;
|
node = *nodelist;
|
||||||
node->rn_status |= RES_MARKED | RES_FINISHED;
|
node->rn_status |= MARKED | FINISHED;
|
||||||
*nodelist = node->rn_more;
|
*nodelist = node->rn_more;
|
||||||
if (node->rn_more != NULL)
|
if (node->rn_more != NULL)
|
||||||
node->rn_more->rn_less = (resNode *) NULL;
|
node->rn_more->rn_less = (resNode *) NULL;
|
||||||
|
|
@ -138,8 +138,7 @@ ResSimplifyNet(nodelist, biglist, reslist, tolerance)
|
||||||
* more than 1, delete the current resistor to break the deadlock.
|
* more than 1, delete the current resistor to break the deadlock.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (numreceive == 0 && numdrive == 1 &&
|
if (numreceive == 0 && numdrive == 1 && node->rn_why != RES_NODE_ORIGIN)
|
||||||
!(node->rn_why & (RES_NODE_ORIGIN | RES_NODE_SINK)))
|
|
||||||
{
|
{
|
||||||
resistor1->rr_status |= RES_DEADEND;
|
resistor1->rr_status |= RES_DEADEND;
|
||||||
if (resistor1->rr_value < tolerance)
|
if (resistor1->rr_value < tolerance)
|
||||||
|
|
@ -156,8 +155,8 @@ ResSimplifyNet(nodelist, biglist, reslist, tolerance)
|
||||||
{
|
{
|
||||||
if (resisptr->re_thisEl->rr_connection1 == otherNode)
|
if (resisptr->re_thisEl->rr_connection1 == otherNode)
|
||||||
{
|
{
|
||||||
if ((resisptr->re_thisEl->rr_connection2->rn_status & RES_MARKED)
|
if ((resisptr->re_thisEl->rr_connection2->rn_status & MARKED)
|
||||||
!= RES_MARKED)
|
!= MARKED)
|
||||||
{
|
{
|
||||||
PendingReceivers++;
|
PendingReceivers++;
|
||||||
}
|
}
|
||||||
|
|
@ -181,9 +180,9 @@ ResSimplifyNet(nodelist, biglist, reslist, tolerance)
|
||||||
(UnMarkedReceivers == 0 && MarkedReceivers > 1 &&
|
(UnMarkedReceivers == 0 && MarkedReceivers > 1 &&
|
||||||
resistor2 == resistor1 && PendingReceivers == 0))
|
resistor2 == resistor1 && PendingReceivers == 0))
|
||||||
{
|
{
|
||||||
if (otherNode->rn_status & RES_MARKED)
|
if (otherNode->rn_status & MARKED)
|
||||||
{
|
{
|
||||||
otherNode->rn_status &= ~RES_MARKED;
|
otherNode->rn_status &= ~MARKED;
|
||||||
ResRemoveFromQueue(otherNode, biglist);
|
ResRemoveFromQueue(otherNode, biglist);
|
||||||
otherNode->rn_less = NULL;
|
otherNode->rn_less = NULL;
|
||||||
otherNode->rn_more = *nodelist;
|
otherNode->rn_more = *nodelist;
|
||||||
|
|
@ -209,9 +208,9 @@ ResSimplifyNet(nodelist, biglist, reslist, tolerance)
|
||||||
ResDeleteResPointer(resistor1->rr_connection2, resistor1);
|
ResDeleteResPointer(resistor1->rr_connection2, resistor1);
|
||||||
ResEliminateResistor(resistor1, reslist);
|
ResEliminateResistor(resistor1, reslist);
|
||||||
ResMergeNodes(otherNode, node, nodelist, biglist);
|
ResMergeNodes(otherNode, node, nodelist, biglist);
|
||||||
if (otherNode->rn_status & RES_MARKED)
|
if (otherNode->rn_status & MARKED)
|
||||||
{
|
{
|
||||||
otherNode->rn_status &= ~RES_MARKED;
|
otherNode->rn_status &= ~MARKED;
|
||||||
ResRemoveFromQueue(otherNode, biglist);
|
ResRemoveFromQueue(otherNode, biglist);
|
||||||
otherNode->rn_less= NULL;
|
otherNode->rn_less= NULL;
|
||||||
otherNode->rn_more = *nodelist;
|
otherNode->rn_more = *nodelist;
|
||||||
|
|
@ -288,12 +287,12 @@ ResSimplifyNet(nodelist, biglist, reslist, tolerance)
|
||||||
resisptr->re_nextEl = node2->rn_re;
|
resisptr->re_nextEl = node2->rn_re;
|
||||||
node2->rn_re = resisptr;
|
node2->rn_re = resisptr;
|
||||||
ResEliminateResistor(resistor2, reslist);
|
ResEliminateResistor(resistor2, reslist);
|
||||||
otherNode->rn_status |= (node->rn_status & RES_MAXTDI);
|
otherNode->rn_status |= (node->rn_status & RN_MAXTDI);
|
||||||
ResCleanNode(node, TRUE, biglist, nodelist);
|
ResCleanNode(node, TRUE, biglist, nodelist);
|
||||||
node1->rn_status &= ~RES_DONE_ONCE;
|
node1->rn_status &= ~RES_DONE_ONCE;
|
||||||
if (node1->rn_status & RES_MARKED)
|
if (node1->rn_status & MARKED)
|
||||||
{
|
{
|
||||||
node1->rn_status &= ~RES_MARKED;
|
node1->rn_status &= ~MARKED;
|
||||||
ResRemoveFromQueue(node1, biglist);
|
ResRemoveFromQueue(node1, biglist);
|
||||||
node1->rn_less = NULL;
|
node1->rn_less = NULL;
|
||||||
node1->rn_more = *nodelist;
|
node1->rn_more = *nodelist;
|
||||||
|
|
@ -302,9 +301,9 @@ ResSimplifyNet(nodelist, biglist, reslist, tolerance)
|
||||||
*nodelist = node1;
|
*nodelist = node1;
|
||||||
}
|
}
|
||||||
node2->rn_status &= ~RES_DONE_ONCE;
|
node2->rn_status &= ~RES_DONE_ONCE;
|
||||||
if (node2->rn_status & RES_MARKED)
|
if (node2->rn_status & MARKED)
|
||||||
{
|
{
|
||||||
node2->rn_status &= ~RES_MARKED;
|
node2->rn_status &= ~MARKED;
|
||||||
ResRemoveFromQueue(node2, biglist);
|
ResRemoveFromQueue(node2, biglist);
|
||||||
node2->rn_less = NULL;
|
node2->rn_less = NULL;
|
||||||
node2->rn_more = *nodelist;
|
node2->rn_more = *nodelist;
|
||||||
|
|
@ -335,7 +334,7 @@ ResSimplifyNet(nodelist, biglist, reslist, tolerance)
|
||||||
if (resisptr->re_thisEl->rr_status & RES_DONE_ONCE)
|
if (resisptr->re_thisEl->rr_status & RES_DONE_ONCE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (resisptr->re_thisEl->rr_connection2->rn_status & RES_MARKED)
|
if (resisptr->re_thisEl->rr_connection2->rn_status & MARKED)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Mark big resistors so we only process them
|
* Mark big resistors so we only process them
|
||||||
|
|
@ -344,7 +343,7 @@ ResSimplifyNet(nodelist, biglist, reslist, tolerance)
|
||||||
if (resisptr->re_thisEl->rr_value > tolerance)
|
if (resisptr->re_thisEl->rr_value > tolerance)
|
||||||
resisptr->re_thisEl->rr_status |= RES_DONE_ONCE;
|
resisptr->re_thisEl->rr_status |= RES_DONE_ONCE;
|
||||||
|
|
||||||
resisptr->re_thisEl->rr_connection2->rn_status &= ~RES_MARKED;
|
resisptr->re_thisEl->rr_connection2->rn_status &= ~MARKED;
|
||||||
ResRemoveFromQueue(resisptr->re_thisEl->rr_connection2, biglist);
|
ResRemoveFromQueue(resisptr->re_thisEl->rr_connection2, biglist);
|
||||||
resisptr->re_thisEl->rr_connection2->rn_less= NULL;
|
resisptr->re_thisEl->rr_connection2->rn_less= NULL;
|
||||||
resisptr->re_thisEl->rr_connection2->rn_more = *nodelist;
|
resisptr->re_thisEl->rr_connection2->rn_more = *nodelist;
|
||||||
|
|
@ -528,7 +527,7 @@ ResScrunchNet(reslist, pendingList, biglist, tolerance)
|
||||||
|
|
||||||
ResEliminateResistor(current, reslist);
|
ResEliminateResistor(current, reslist);
|
||||||
ResAddResistorToList(working, reslist);
|
ResAddResistorToList(working, reslist);
|
||||||
if (node2->rn_why & (RES_NODE_ORIGIN | RES_NODE_SINK))
|
if (node2->rn_why & RES_NODE_ORIGIN)
|
||||||
{
|
{
|
||||||
ResMergeNodes(node2, node1, pendingList, biglist);
|
ResMergeNodes(node2, node1, pendingList, biglist);
|
||||||
node1 = node2;
|
node1 = node2;
|
||||||
|
|
@ -542,7 +541,7 @@ ResScrunchNet(reslist, pendingList, biglist, tolerance)
|
||||||
*/
|
*/
|
||||||
ResRemoveFromQueue(node1, biglist);
|
ResRemoveFromQueue(node1, biglist);
|
||||||
ResAddToQueue(node1, pendingList);
|
ResAddToQueue(node1, pendingList);
|
||||||
node1->rn_status &= ~(RES_DONE_ONCE | RES_FINISHED);
|
node1->rn_status &= ~(RES_DONE_ONCE | FINISHED);
|
||||||
ResDoneWithNode(node1);
|
ResDoneWithNode(node1);
|
||||||
while (*pendingList != NULL)
|
while (*pendingList != NULL)
|
||||||
ResSimplifyNet(pendingList, biglist, reslist, tolerance);
|
ResSimplifyNet(pendingList, biglist, reslist, tolerance);
|
||||||
|
|
@ -641,7 +640,7 @@ ResDistributeCapacitance(nodelist, totalcap)
|
||||||
TxError("Error: Node with no area.\n");
|
TxError("Error: Node with no area.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
capperarea = totalcap / totalarea;
|
capperarea = FEMTOTOATTO * totalcap / totalarea;
|
||||||
|
|
||||||
for (workingNode = nodelist; workingNode != NULL; workingNode = workingNode->rn_more)
|
for (workingNode = nodelist; workingNode != NULL; workingNode = workingNode->rn_more)
|
||||||
workingNode->rn_float.rn_area *= capperarea;
|
workingNode->rn_float.rn_area *= capperarea;
|
||||||
|
|
@ -898,7 +897,7 @@ ResDoSimplify(tolerance,resisdata)
|
||||||
------*/
|
------*/
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ResNodeAtOrigin == NULL)
|
if (ResOriginNode == NULL)
|
||||||
{
|
{
|
||||||
TxError("Error: Network simplification: Failed to to get origin node.\n");
|
TxError("Error: Network simplification: Failed to to get origin node.\n");
|
||||||
resisdata->rg_Tdi = 0;
|
resisdata->rg_Tdi = 0;
|
||||||
|
|
@ -906,12 +905,12 @@ ResDoSimplify(tolerance,resisdata)
|
||||||
else if (ResOptionsFlags & ResOpt_Tdi)
|
else if (ResOptionsFlags & ResOpt_Tdi)
|
||||||
{
|
{
|
||||||
if ((resisdata->rg_nodecap != -1) &&
|
if ((resisdata->rg_nodecap != -1) &&
|
||||||
(totalcap = ResCalculateChildCapacitance(ResNodeAtOrigin)) != -1)
|
(totalcap = ResCalculateChildCapacitance(ResOriginNode)) != -1)
|
||||||
{
|
{
|
||||||
RCDelayStuff *rc = (RCDelayStuff *) ResNodeList->rn_client;
|
RCDelayStuff *rc = (RCDelayStuff *) ResNodeList->rn_client;
|
||||||
|
|
||||||
resisdata->rg_nodecap = totalcap;
|
resisdata->rg_nodecap = totalcap;
|
||||||
ResCalculateTDi(ResNodeAtOrigin, (resResistor *)NULL,
|
ResCalculateTDi(ResOriginNode, (resResistor *)NULL,
|
||||||
resisdata->rg_bigdevres);
|
resisdata->rg_bigdevres);
|
||||||
if (rc != (RCDelayStuff *)NULL)
|
if (rc != (RCDelayStuff *)NULL)
|
||||||
resisdata->rg_Tdi = rc->rc_Tdi;
|
resisdata->rg_Tdi = rc->rc_Tdi;
|
||||||
|
|
@ -928,7 +927,7 @@ ResDoSimplify(tolerance,resisdata)
|
||||||
resisdata->rg_Tdi = rc->rc_Tdi;
|
resisdata->rg_Tdi = rc->rc_Tdi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
slownode->rn_status |= RES_MAXTDI;
|
slownode->rn_status |= RN_MAXTDI;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
resisdata->rg_Tdi = -1;
|
resisdata->rg_Tdi = -1;
|
||||||
|
|
@ -958,11 +957,11 @@ ResDoSimplify(tolerance,resisdata)
|
||||||
for (node = ResNodeList; node != NULL; node = node->rn_more)
|
for (node = ResNodeList; node != NULL; node = node->rn_more)
|
||||||
{
|
{
|
||||||
if (node->rn_noderes == 0)
|
if (node->rn_noderes == 0)
|
||||||
ResNodeAtOrigin = node;
|
ResOriginNode = node;
|
||||||
|
|
||||||
node->rn_status |= RES_FINISHED;
|
node->rn_status |= FINISHED;
|
||||||
}
|
}
|
||||||
if (ResNodeAtOrigin != NULL)
|
if (ResOriginNode != NULL)
|
||||||
{
|
{
|
||||||
/* if Tdi is enabled, prune all branches whose end nodes */
|
/* if Tdi is enabled, prune all branches whose end nodes */
|
||||||
/* have time constants less than the tolerance. */
|
/* have time constants less than the tolerance. */
|
||||||
|
|
@ -971,22 +970,22 @@ ResDoSimplify(tolerance,resisdata)
|
||||||
resisdata->rg_Tdi != -1 &&
|
resisdata->rg_Tdi != -1 &&
|
||||||
rctol != 0)
|
rctol != 0)
|
||||||
{
|
{
|
||||||
ResPruneTree(ResNodeAtOrigin, (rctol + 1) *
|
ResPruneTree(ResOriginNode, (rctol + 1) *
|
||||||
resisdata->rg_bigdevres * resisdata->rg_nodecap / rctol,
|
resisdata->rg_bigdevres * resisdata->rg_nodecap / rctol,
|
||||||
&ResNodeList, &ResNodeQueue, &ResResList);
|
&ResNodeList, &ResNodeQueue, &ResResList);
|
||||||
}
|
}
|
||||||
ResNodeAtOrigin->rn_status &= ~RES_MARKED;
|
ResOriginNode->rn_status &= ~MARKED;
|
||||||
if (ResNodeAtOrigin->rn_less == NULL)
|
if (ResOriginNode->rn_less == NULL)
|
||||||
ResNodeList = ResNodeAtOrigin->rn_more;
|
ResNodeList = ResOriginNode->rn_more;
|
||||||
else
|
else
|
||||||
ResNodeAtOrigin->rn_less->rn_more = ResNodeAtOrigin->rn_more;
|
ResOriginNode->rn_less->rn_more = ResOriginNode->rn_more;
|
||||||
|
|
||||||
if (ResNodeAtOrigin->rn_more != NULL)
|
if (ResOriginNode->rn_more != NULL)
|
||||||
ResNodeAtOrigin->rn_more->rn_less = ResNodeAtOrigin->rn_less;
|
ResOriginNode->rn_more->rn_less = ResOriginNode->rn_less;
|
||||||
|
|
||||||
ResNodeAtOrigin->rn_more = NULL;
|
ResOriginNode->rn_more = NULL;
|
||||||
ResNodeAtOrigin->rn_less = NULL;
|
ResOriginNode->rn_less = NULL;
|
||||||
ResNodeQueue = ResNodeAtOrigin;
|
ResNodeQueue = ResOriginNode;
|
||||||
while (ResNodeQueue != NULL)
|
while (ResNodeQueue != NULL)
|
||||||
ResSimplifyNet(&ResNodeQueue, &ResNodeList, &ResResList, millitolerance);
|
ResSimplifyNet(&ResNodeQueue, &ResNodeList, &ResResList, millitolerance);
|
||||||
|
|
||||||
|
|
@ -1023,16 +1022,16 @@ ResSetPathRes(ResisData *resisdata)
|
||||||
{
|
{
|
||||||
if (node->rn_noderes == 0)
|
if (node->rn_noderes == 0)
|
||||||
{
|
{
|
||||||
ResNodeAtOrigin = node;
|
ResOriginNode = node;
|
||||||
node->rn_status |= RES_FINISHED;
|
node->rn_status |= FINISHED;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
node->rn_noderes = RES_INFINITY;
|
node->rn_noderes = RES_INFINITY;
|
||||||
node->rn_status &= ~RES_FINISHED;
|
node->rn_status &= ~FINISHED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ResNodeAtOrigin == NULL)
|
if (ResOriginNode == NULL)
|
||||||
{
|
{
|
||||||
resDevice *res = ResGetDevice(resisdata->rg_devloc, resisdata->rg_ttype);
|
resDevice *res = ResGetDevice(resisdata->rg_devloc, resisdata->rg_ttype);
|
||||||
if (res == (resDevice *)NULL)
|
if (res == (resDevice *)NULL)
|
||||||
|
|
@ -1043,12 +1042,12 @@ ResSetPathRes(ResisData *resisdata)
|
||||||
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow *)NULL, FALSE));
|
DBWPrintValue(resisdata->rg_devloc->p_y, (MagWindow *)NULL, FALSE));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ResNodeAtOrigin = res->rd_fet_source;
|
ResOriginNode = res->rd_fet_source;
|
||||||
ResNodeAtOrigin->rn_why = RES_NODE_ORIGIN;
|
ResOriginNode->rn_why = RES_NODE_ORIGIN;
|
||||||
ResNodeAtOrigin->rn_noderes = 0;
|
ResOriginNode->rn_noderes = 0;
|
||||||
}
|
}
|
||||||
ASSERT(ResNodeAtOrigin != NULL, "ResDoSimplify");
|
ASSERT(ResOriginNode != NULL, "ResDoSimplify");
|
||||||
resPathNode(ResNodeAtOrigin);
|
resPathNode(ResOriginNode);
|
||||||
while (HeapRemoveTop(&ResistorHeap,&he))
|
while (HeapRemoveTop(&ResistorHeap,&he))
|
||||||
resPathRes((resResistor *)he.he_id);
|
resPathRes((resResistor *)he.he_id);
|
||||||
}
|
}
|
||||||
|
|
@ -1059,7 +1058,7 @@ ResSetPathRes(ResisData *resisdata)
|
||||||
*
|
*
|
||||||
* Given node "node", add every resistor connected to the node, and
|
* Given node "node", add every resistor connected to the node, and
|
||||||
* for which the node on the other side has not been processed, to
|
* for which the node on the other side has not been processed, to
|
||||||
* the heap. Node is marked with RES_FINISHED to prevent going 'round
|
* the heap. Node is marked with FINISHED to prevent going 'round
|
||||||
* and 'round loops.
|
* and 'round loops.
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
@ -1071,7 +1070,7 @@ resPathNode(node)
|
||||||
{
|
{
|
||||||
resElement *re;
|
resElement *re;
|
||||||
|
|
||||||
node->rn_status |= RES_FINISHED;
|
node->rn_status |= FINISHED;
|
||||||
for (re = node->rn_re; re; re = re->re_nextEl)
|
for (re = node->rn_re; re; re = re->re_nextEl)
|
||||||
{
|
{
|
||||||
resResistor *res = re->re_thisEl;
|
resResistor *res = re->re_thisEl;
|
||||||
|
|
@ -1079,7 +1078,7 @@ resPathNode(node)
|
||||||
|
|
||||||
if (res->rr_status & RES_HEAP) continue;
|
if (res->rr_status & RES_HEAP) continue;
|
||||||
if ((node2 = res->rr_node[0]) == node) node2 = res->rr_node[1];
|
if ((node2 = res->rr_node[0]) == node) node2 = res->rr_node[1];
|
||||||
if ((node2->rn_status & RES_FINISHED) == 0)
|
if ((node2->rn_status & FINISHED) == 0)
|
||||||
HeapAddInt(&ResistorHeap, node->rn_noderes + res->rr_value,
|
HeapAddInt(&ResistorHeap, node->rn_noderes + res->rr_value,
|
||||||
(char *)res);
|
(char *)res);
|
||||||
}
|
}
|
||||||
|
|
@ -1115,8 +1114,8 @@ resPathRes(res)
|
||||||
res->rr_status &= ~RES_MARKED;
|
res->rr_status &= ~RES_MARKED;
|
||||||
node0 = res->rr_node[0];
|
node0 = res->rr_node[0];
|
||||||
node1 = res->rr_node[1];
|
node1 = res->rr_node[1];
|
||||||
flag0 = node0->rn_status & RES_FINISHED;
|
flag0 = node0->rn_status & FINISHED;
|
||||||
flag1 = node1->rn_status & RES_FINISHED;
|
flag1 = node1->rn_status & FINISHED;
|
||||||
if (flag0 && flag1)
|
if (flag0 && flag1)
|
||||||
{
|
{
|
||||||
res->rr_status |= RES_TDI_IGNORE;
|
res->rr_status |= RES_TDI_IGNORE;
|
||||||
|
|
|
||||||
184
resis/ResUtils.c
184
resis/ResUtils.c
|
|
@ -93,7 +93,7 @@ ResFirst(tile, dinfo, arg)
|
||||||
*
|
*
|
||||||
* resMultiPlaneTerm --
|
* resMultiPlaneTerm --
|
||||||
*
|
*
|
||||||
* Callback function to set a resInfo field
|
* Callback function to set a junk field
|
||||||
*
|
*
|
||||||
*--------------------------------------------------------------------------
|
*--------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
@ -102,13 +102,13 @@ int
|
||||||
resMultiPlaneTerm(
|
resMultiPlaneTerm(
|
||||||
Tile *tile,
|
Tile *tile,
|
||||||
TileType dinfo, // Unused (but should be handled)
|
TileType dinfo, // Unused (but should be handled)
|
||||||
resInfo *rinfo2)
|
tileJunk *junk2)
|
||||||
{
|
{
|
||||||
resInfo *Info;
|
tileJunk *Junk;
|
||||||
|
|
||||||
Info = resAddField(tile);
|
Junk = resAddField(tile);
|
||||||
Info->ri_status |= RES_TILE_SD;
|
Junk->tj_status |= RES_TILE_SD;
|
||||||
rinfo2->sourceEdge |= OTHERPLANE;
|
junk2->sourceEdge |= OTHERPLANE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,7 +117,7 @@ resMultiPlaneTerm(
|
||||||
*
|
*
|
||||||
* resSubstrateTerm --
|
* resSubstrateTerm --
|
||||||
*
|
*
|
||||||
* Callback function to set a resInfo field
|
* Callback function to set a junk field
|
||||||
*
|
*
|
||||||
*--------------------------------------------------------------------------
|
*--------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
@ -128,10 +128,10 @@ resSubstrateTerm(
|
||||||
TileType dinfo,
|
TileType dinfo,
|
||||||
ClientData clientdata) /* (unused) */
|
ClientData clientdata) /* (unused) */
|
||||||
{
|
{
|
||||||
resInfo *Info;
|
tileJunk *Junk;
|
||||||
|
|
||||||
Info = resAddField(tile);
|
Junk = resAddField(tile);
|
||||||
Info->ri_status |= RES_TILE_SUBS;
|
Junk->tj_status |= RES_TILE_SUBS;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -168,7 +168,7 @@ ResEach(tile, dinfo, pNum, arg)
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* ResAddPlumbing-- Each tile has a resInfo structure associated with it
|
* ResAddPlumbing-- Each tile is a tileJunk structure associated with it
|
||||||
* to keep track of various things used by the extractor. ResAddPlumbing
|
* to keep track of various things used by the extractor. ResAddPlumbing
|
||||||
* adds this structure and sets the tile's ClientData field to point to it.
|
* adds this structure and sets the tile's ClientData field to point to it.
|
||||||
* If the tile is a device, then a device structure is also added;
|
* If the tile is a device, then a device structure is also added;
|
||||||
|
|
@ -188,7 +188,7 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
TileType dinfo;
|
TileType dinfo;
|
||||||
ClientData *arg;
|
ClientData *arg;
|
||||||
{
|
{
|
||||||
resInfo *Info, *rinfo2;
|
tileJunk *Junk, *junk2;
|
||||||
static Stack *resDevStack = NULL;
|
static Stack *resDevStack = NULL;
|
||||||
TileType loctype, t1;
|
TileType loctype, t1;
|
||||||
Tile *tp1, *tp2, *source;
|
Tile *tp1, *tp2, *source;
|
||||||
|
|
@ -208,7 +208,7 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
loctype = TiGetTypeExact(tile);
|
loctype = TiGetTypeExact(tile);
|
||||||
|
|
||||||
devptr = ExtCurStyle->exts_device[loctype];
|
devptr = ExtCurStyle->exts_device[loctype];
|
||||||
rinfo2 = resAddField(tile);
|
junk2 = resAddField(tile);
|
||||||
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), loctype))
|
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), loctype))
|
||||||
{
|
{
|
||||||
int i, nterms, pNum;
|
int i, nterms, pNum;
|
||||||
|
|
@ -249,8 +249,8 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
resDev->rd_status = 0;
|
resDev->rd_status = 0;
|
||||||
resDev->rd_nextDev = (resDevice *)*arg;
|
resDev->rd_nextDev = (resDevice *)*arg;
|
||||||
*arg = (ClientData)resDev;
|
*arg = (ClientData)resDev;
|
||||||
rinfo2->deviceList = resDev;
|
junk2->deviceList = resDev;
|
||||||
rinfo2->ri_status |= RES_TILE_DEV;
|
junk2->tj_status |= RES_TILE_DEV;
|
||||||
|
|
||||||
for (i = 0; i < nterms - 2; i++)
|
for (i = 0; i < nterms - 2; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -263,10 +263,10 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
|
if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
|
||||||
TiGetBottomType(tp2))
|
TiGetBottomType(tp2))
|
||||||
{
|
{
|
||||||
rinfo2->sourceEdge |= TOPEDGE;
|
junk2->sourceEdge |= TOPEDGE;
|
||||||
source = tp2;
|
source = tp2;
|
||||||
Info = resAddField(source);
|
Junk = resAddField(source);
|
||||||
Info->ri_status |= RES_TILE_SD;
|
Junk->tj_status |= RES_TILE_SD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -278,10 +278,10 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
|
if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
|
||||||
TiGetTopType(tp2))
|
TiGetTopType(tp2))
|
||||||
{
|
{
|
||||||
rinfo2->sourceEdge |= BOTTOMEDGE;
|
junk2->sourceEdge |= BOTTOMEDGE;
|
||||||
source = tp2;
|
source = tp2;
|
||||||
Info = resAddField(source);
|
Junk = resAddField(source);
|
||||||
Info->ri_status |= RES_TILE_SD;
|
Junk->tj_status |= RES_TILE_SD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -293,10 +293,10 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
|
if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
|
||||||
TiGetLeftType(tp2))
|
TiGetLeftType(tp2))
|
||||||
{
|
{
|
||||||
rinfo2->sourceEdge |= RIGHTEDGE;
|
junk2->sourceEdge |= RIGHTEDGE;
|
||||||
source = tp2;
|
source = tp2;
|
||||||
Info = resAddField(source);
|
Junk = resAddField(source);
|
||||||
Info->ri_status |= RES_TILE_SD;
|
Junk->tj_status |= RES_TILE_SD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -309,9 +309,9 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
TiGetRightType(tp2))
|
TiGetRightType(tp2))
|
||||||
{
|
{
|
||||||
source = tp2;
|
source = tp2;
|
||||||
Info = resAddField(source);
|
Junk = resAddField(source);
|
||||||
Info->ri_status |= RES_TILE_SD;
|
Junk->tj_status |= RES_TILE_SD;
|
||||||
rinfo2->sourceEdge |= LEFTEDGE;
|
junk2->sourceEdge |= LEFTEDGE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -327,7 +327,7 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
DBSrPaintArea((Tile *)NULL,
|
DBSrPaintArea((Tile *)NULL,
|
||||||
ResUse->cu_def->cd_planes[pNum],
|
ResUse->cu_def->cd_planes[pNum],
|
||||||
&r, &(devptr->exts_deviceSDTypes[i]),
|
&r, &(devptr->exts_deviceSDTypes[i]),
|
||||||
resMultiPlaneTerm, (ClientData)rinfo2);
|
resMultiPlaneTerm, (ClientData)junk2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -360,10 +360,10 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
{
|
{
|
||||||
if (TiGetBottomType(tp2) == t1)
|
if (TiGetBottomType(tp2) == t1)
|
||||||
{
|
{
|
||||||
resInfo *re = resAddField(tp2);
|
tileJunk *j = resAddField(tp2);
|
||||||
if ((re->ri_status & RES_TILE_SD) == 0)
|
if ((j->tj_status & RES_TILE_SD) == 0)
|
||||||
{
|
{
|
||||||
re->ri_status |= RES_TILE_SD;
|
j->tj_status |= RES_TILE_SD;
|
||||||
STACKPUSH((ClientData)tp2, resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -373,10 +373,10 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
{
|
{
|
||||||
if (TiGetTopType(tp2) == t1)
|
if (TiGetTopType(tp2) == t1)
|
||||||
{
|
{
|
||||||
resInfo *re = resAddField(tp2);
|
tileJunk *j = resAddField(tp2);
|
||||||
if ((re->ri_status & RES_TILE_SD) == 0)
|
if ((j->tj_status & RES_TILE_SD) == 0)
|
||||||
{
|
{
|
||||||
re->ri_status |= RES_TILE_SD;
|
j->tj_status |= RES_TILE_SD;
|
||||||
STACKPUSH((ClientData)tp2, resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -386,10 +386,10 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
{
|
{
|
||||||
if (TiGetLeftType(tp2) == t1)
|
if (TiGetLeftType(tp2) == t1)
|
||||||
{
|
{
|
||||||
resInfo *re = resAddField(tp2);
|
tileJunk *j = resAddField(tp2);
|
||||||
if ((re->ri_status & RES_TILE_SD) == 0)
|
if ((j->tj_status & RES_TILE_SD) == 0)
|
||||||
{
|
{
|
||||||
re->ri_status |= RES_TILE_SD;
|
j->tj_status |= RES_TILE_SD;
|
||||||
STACKPUSH((ClientData)tp2, resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -399,10 +399,10 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
{
|
{
|
||||||
if (TiGetRightType(tp2) == t1)
|
if (TiGetRightType(tp2) == t1)
|
||||||
{
|
{
|
||||||
resInfo *re = resAddField(tp2);
|
tileJunk *j = resAddField(tp2);
|
||||||
if ((re->ri_status & RES_TILE_SD) == 0)
|
if ((j->tj_status & RES_TILE_SD) == 0)
|
||||||
{
|
{
|
||||||
re->ri_status |= RES_TILE_SD;
|
j->tj_status |= RES_TILE_SD;
|
||||||
STACKPUSH((ClientData)tp2, resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -430,7 +430,7 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
STACKPUSH((ClientData)tile, resDevStack);
|
STACKPUSH((ClientData)tile, resDevStack);
|
||||||
while (!StackEmpty(resDevStack))
|
while (!StackEmpty(resDevStack))
|
||||||
{
|
{
|
||||||
resInfo *re0;
|
tileJunk *j0;
|
||||||
|
|
||||||
tp1 = (Tile *) STACKPOP(resDevStack);
|
tp1 = (Tile *) STACKPOP(resDevStack);
|
||||||
if (IsSplit(tp1))
|
if (IsSplit(tp1))
|
||||||
|
|
@ -446,17 +446,17 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
t1 = TiGetTypeExact(tp1);
|
t1 = TiGetTypeExact(tp1);
|
||||||
|
|
||||||
devptr = ExtCurStyle->exts_device[t1];
|
devptr = ExtCurStyle->exts_device[t1];
|
||||||
re0 = (resInfo *) TiGetClientPTR(tp1);
|
j0 = (tileJunk *) TiGetClientPTR(tp1);
|
||||||
/* top */
|
/* top */
|
||||||
for (tp2 = RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2))
|
for (tp2 = RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2))
|
||||||
{
|
{
|
||||||
if ((TiGetBottomType(tp2) == t1) &&
|
if ((TiGetBottomType(tp2) == t1) &&
|
||||||
(TiGetClient(tp2) == CLIENTDEFAULT))
|
(TiGetClient(tp2) == CLIENTDEFAULT))
|
||||||
{
|
{
|
||||||
Info = resAddField(tp2);
|
Junk = resAddField(tp2);
|
||||||
STACKPUSH((ClientData)tp2, resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
Info->deviceList = resDev;
|
Junk->deviceList = resDev;
|
||||||
Info->ri_status |= RES_TILE_DEV;
|
Junk->tj_status |= RES_TILE_DEV;
|
||||||
|
|
||||||
/* Update device position to point to the lower-leftmost tile */
|
/* Update device position to point to the lower-leftmost tile */
|
||||||
if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) ||
|
if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) ||
|
||||||
|
|
@ -472,9 +472,9 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
|
else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
|
||||||
TiGetBottomType(tp2))
|
TiGetBottomType(tp2))
|
||||||
{
|
{
|
||||||
Info = resAddField(tp2);
|
Junk = resAddField(tp2);
|
||||||
if (Info->ri_status & RES_TILE_SD)
|
if (Junk->tj_status & RES_TILE_SD)
|
||||||
re0->sourceEdge |= TOPEDGE;
|
j0->sourceEdge |= TOPEDGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* bottom */
|
/* bottom */
|
||||||
|
|
@ -483,10 +483,10 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
if ((TiGetTopType(tp2) == t1) &&
|
if ((TiGetTopType(tp2) == t1) &&
|
||||||
(TiGetClient(tp2) == CLIENTDEFAULT))
|
(TiGetClient(tp2) == CLIENTDEFAULT))
|
||||||
{
|
{
|
||||||
Info = resAddField(tp2);
|
Junk = resAddField(tp2);
|
||||||
STACKPUSH((ClientData)tp2, resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
Info->deviceList = resDev;
|
Junk->deviceList = resDev;
|
||||||
Info->ri_status |= RES_TILE_DEV;
|
Junk->tj_status |= RES_TILE_DEV;
|
||||||
|
|
||||||
/* Update device position to point to the lower-leftmost tile */
|
/* Update device position to point to the lower-leftmost tile */
|
||||||
if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) ||
|
if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) ||
|
||||||
|
|
@ -502,9 +502,9 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
|
else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
|
||||||
TiGetTopType(tp2))
|
TiGetTopType(tp2))
|
||||||
{
|
{
|
||||||
Info = resAddField(tp2);
|
Junk = resAddField(tp2);
|
||||||
if (Info->ri_status & RES_TILE_SD)
|
if (Junk->tj_status & RES_TILE_SD)
|
||||||
re0->sourceEdge |= BOTTOMEDGE;
|
j0->sourceEdge |= BOTTOMEDGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* right */
|
/* right */
|
||||||
|
|
@ -513,10 +513,10 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
if ((TiGetLeftType(tp2) == t1) &&
|
if ((TiGetLeftType(tp2) == t1) &&
|
||||||
(TiGetClient(tp2) == CLIENTDEFAULT))
|
(TiGetClient(tp2) == CLIENTDEFAULT))
|
||||||
{
|
{
|
||||||
Info = resAddField(tp2);
|
Junk = resAddField(tp2);
|
||||||
STACKPUSH((ClientData)tp2, resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
Info->deviceList = resDev;
|
Junk->deviceList = resDev;
|
||||||
Info->ri_status |= RES_TILE_DEV;
|
Junk->tj_status |= RES_TILE_DEV;
|
||||||
|
|
||||||
/* Update device position to point to the lower-leftmost tile */
|
/* Update device position to point to the lower-leftmost tile */
|
||||||
if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) ||
|
if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) ||
|
||||||
|
|
@ -532,9 +532,9 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
|
else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
|
||||||
TiGetLeftType(tp2))
|
TiGetLeftType(tp2))
|
||||||
{
|
{
|
||||||
Info = resAddField(tp2);
|
Junk = resAddField(tp2);
|
||||||
if (Info->ri_status & RES_TILE_SD)
|
if (Junk->tj_status & RES_TILE_SD)
|
||||||
re0->sourceEdge |= RIGHTEDGE;
|
j0->sourceEdge |= RIGHTEDGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* left */
|
/* left */
|
||||||
|
|
@ -543,10 +543,10 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
if ((TiGetRightType(tp2) == t1) &&
|
if ((TiGetRightType(tp2) == t1) &&
|
||||||
(TiGetClient(tp2) == CLIENTDEFAULT))
|
(TiGetClient(tp2) == CLIENTDEFAULT))
|
||||||
{
|
{
|
||||||
Info = resAddField(tp2);
|
Junk = resAddField(tp2);
|
||||||
STACKPUSH((ClientData)tp2, resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
Info->deviceList = resDev;
|
Junk->deviceList = resDev;
|
||||||
Info->ri_status |= RES_TILE_DEV;
|
Junk->tj_status |= RES_TILE_DEV;
|
||||||
|
|
||||||
/* Update device position to point to the lower-leftmost tile */
|
/* Update device position to point to the lower-leftmost tile */
|
||||||
if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) ||
|
if ((tp2->ti_ll.p_x < resDev->rd_inside.r_ll.p_x) ||
|
||||||
|
|
@ -562,9 +562,9 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
|
else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
|
||||||
TiGetRightType(tp2))
|
TiGetRightType(tp2))
|
||||||
{
|
{
|
||||||
Info = resAddField(tp2);
|
Junk = resAddField(tp2);
|
||||||
if (Info->ri_status & RES_TILE_SD)
|
if (Junk->tj_status & RES_TILE_SD)
|
||||||
re0->sourceEdge |= LEFTEDGE;
|
j0->sourceEdge |= LEFTEDGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -573,10 +573,10 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
|
|
||||||
if (source != (Tile *) NULL)
|
if (source != (Tile *) NULL)
|
||||||
{
|
{
|
||||||
resInfo *re = (resInfo *) TiGetClientPTR(source);
|
tileJunk *j = (tileJunk *) TiGetClientPTR(source);
|
||||||
|
|
||||||
STACKPUSH((ClientData)source, resDevStack);
|
STACKPUSH((ClientData)source, resDevStack);
|
||||||
re->ri_status &= ~RES_TILE_SD;
|
j->tj_status &= ~RES_TILE_SD;
|
||||||
}
|
}
|
||||||
while (!StackEmpty(resDevStack))
|
while (!StackEmpty(resDevStack))
|
||||||
{
|
{
|
||||||
|
|
@ -592,12 +592,12 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
/* top */
|
/* top */
|
||||||
for (tp2 = RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2))
|
for (tp2 = RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2))
|
||||||
{
|
{
|
||||||
resInfo *re2 = (resInfo *) TiGetClientPTR(tp2);
|
tileJunk *j2 = (tileJunk *) TiGetClientPTR(tp2);
|
||||||
if (TiGetBottomType(tp2) == t1)
|
if (TiGetBottomType(tp2) == t1)
|
||||||
{
|
{
|
||||||
if (re2->ri_status & RES_TILE_SD)
|
if (j2->tj_status & RES_TILE_SD)
|
||||||
{
|
{
|
||||||
re2->ri_status &= ~RES_TILE_SD;
|
j2->tj_status &= ~RES_TILE_SD;
|
||||||
STACKPUSH((ClientData)tp2, resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -605,12 +605,12 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
/* bottom */
|
/* bottom */
|
||||||
for(tp2 = LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2))
|
for(tp2 = LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2))
|
||||||
{
|
{
|
||||||
resInfo *re2 = (resInfo *) TiGetClientPTR(tp2);
|
tileJunk *j2 = (tileJunk *) TiGetClientPTR(tp2);
|
||||||
if (TiGetTopType(tp2) == t1)
|
if (TiGetTopType(tp2) == t1)
|
||||||
{
|
{
|
||||||
if (re2->ri_status & RES_TILE_SD)
|
if (j2->tj_status & RES_TILE_SD)
|
||||||
{
|
{
|
||||||
re2->ri_status &= ~RES_TILE_SD;
|
j2->tj_status &= ~RES_TILE_SD;
|
||||||
STACKPUSH((ClientData)tp2, resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -618,12 +618,12 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
/* right */
|
/* right */
|
||||||
for (tp2 = TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2))
|
for (tp2 = TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2))
|
||||||
{
|
{
|
||||||
resInfo *re2 = (resInfo *) TiGetClientPTR(tp2);
|
tileJunk *j2 = (tileJunk *) TiGetClientPTR(tp2);
|
||||||
if (TiGetLeftType(tp2) == t1)
|
if (TiGetLeftType(tp2) == t1)
|
||||||
{
|
{
|
||||||
if (re2->ri_status & RES_TILE_SD)
|
if (j2->tj_status & RES_TILE_SD)
|
||||||
{
|
{
|
||||||
re2->ri_status &= ~RES_TILE_SD;
|
j2->tj_status &= ~RES_TILE_SD;
|
||||||
STACKPUSH((ClientData)tp2, resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -631,12 +631,12 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
/* left */
|
/* left */
|
||||||
for (tp2 = BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2))
|
for (tp2 = BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2))
|
||||||
{
|
{
|
||||||
resInfo *re2 = (resInfo *) TiGetClientPTR(tp2);
|
tileJunk *j2 = (tileJunk *) TiGetClientPTR(tp2);
|
||||||
if (TiGetRightType(tp2) == t1)
|
if (TiGetRightType(tp2) == t1)
|
||||||
{
|
{
|
||||||
if (re2->ri_status & RES_TILE_SD)
|
if (j2->tj_status & RES_TILE_SD)
|
||||||
{
|
{
|
||||||
re2->ri_status &= ~RES_TILE_SD;
|
j2->tj_status &= ~RES_TILE_SD;
|
||||||
STACKPUSH((ClientData)tp2, resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -650,7 +650,7 @@ ResAddPlumbing(tile, dinfo, arg)
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* ResRemovePlumbing-- Removes and deallocates all the resInfo fields.
|
* ResRemovePlumbing-- Removes and deallocates all the tileJunk fields.
|
||||||
*
|
*
|
||||||
* Results: returns 0
|
* Results: returns 0
|
||||||
*
|
*
|
||||||
|
|
@ -702,7 +702,7 @@ ResPreProcessDevices(TileList, DeviceList, Def)
|
||||||
{
|
{
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
ResDevTile *oldTile;
|
ResDevTile *oldTile;
|
||||||
resInfo *tstruct;
|
tileJunk *tstruct;
|
||||||
TileType tt, residue;
|
TileType tt, residue;
|
||||||
int pNum;
|
int pNum;
|
||||||
|
|
||||||
|
|
@ -735,9 +735,9 @@ ResPreProcessDevices(TileList, DeviceList, Def)
|
||||||
GOTOPOINT(tile, &(TileList->area.r_ll));
|
GOTOPOINT(tile, &(TileList->area.r_ll));
|
||||||
|
|
||||||
tt = TiGetType(tile);
|
tt = TiGetType(tile);
|
||||||
tstruct = (resInfo *) TiGetClientPTR(tile);
|
tstruct = (tileJunk *) TiGetClientPTR(tile);
|
||||||
|
|
||||||
if ((tstruct == (resInfo *)CLIENTDEFAULT) ||
|
if ((tstruct == (tileJunk *)CLIENTDEFAULT) ||
|
||||||
(tstruct->deviceList == NULL) ||
|
(tstruct->deviceList == NULL) ||
|
||||||
!TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt))
|
!TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt))
|
||||||
{
|
{
|
||||||
|
|
@ -745,11 +745,11 @@ ResPreProcessDevices(TileList, DeviceList, Def)
|
||||||
TileList->area.r_ll.p_x,
|
TileList->area.r_ll.p_x,
|
||||||
TileList->area.r_ll.p_y);
|
TileList->area.r_ll.p_y);
|
||||||
}
|
}
|
||||||
else if ((tstruct->ri_status & RES_TILE_MARK) == 0)
|
else if ((tstruct->tj_status & RES_TILE_MARK) == 0)
|
||||||
{
|
{
|
||||||
resDevice *rd = tstruct->deviceList;
|
resDevice *rd = tstruct->deviceList;
|
||||||
|
|
||||||
tstruct->ri_status |= RES_TILE_MARK;
|
tstruct->tj_status |= RES_TILE_MARK;
|
||||||
rd->rd_perim += TileList->perim;
|
rd->rd_perim += TileList->perim;
|
||||||
rd->rd_length += TileList->overlap;
|
rd->rd_length += TileList->overlap;
|
||||||
rd->rd_area += (TileList->area.r_xtop - TileList->area.r_xbot)
|
rd->rd_area += (TileList->area.r_xtop - TileList->area.r_xbot)
|
||||||
|
|
@ -851,17 +851,17 @@ ResRemoveFromQueue(node, list)
|
||||||
node->rn_less = NULL;
|
node->rn_less = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
resInfo *
|
tileJunk *
|
||||||
resAddField(tile)
|
resAddField(tile)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
{
|
{
|
||||||
ClientData ticlient = TiGetClient(tile);
|
ClientData ticlient = TiGetClient(tile);
|
||||||
resInfo *Info = (resInfo *)CD2PTR(ticlient);
|
tileJunk *Junk = (tileJunk *)CD2PTR(ticlient);
|
||||||
if (ticlient == CLIENTDEFAULT)
|
if (ticlient == CLIENTDEFAULT)
|
||||||
{
|
{
|
||||||
Info = (resInfo *) mallocMagic((unsigned) (sizeof(resInfo)));
|
Junk = (tileJunk *) mallocMagic((unsigned) (sizeof(tileJunk)));
|
||||||
ResInfoInit(Info);
|
ResJunkInit(Junk);
|
||||||
TiSetClientPTR(tile, Info);
|
TiSetClientPTR(tile, Junk);
|
||||||
}
|
}
|
||||||
return Info;
|
return Junk;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
303
resis/resis.h
303
resis/resis.h
|
|
@ -1,33 +1,44 @@
|
||||||
/* Header files for resistance extraction */
|
/* Header files for resistance extraction */
|
||||||
|
|
||||||
|
/* Type declarations */
|
||||||
|
|
||||||
|
/* contact points: keeps track where contacts are and what tiles they
|
||||||
|
refer to both before and after processing.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef _MAGIC__RESIS__RESIS_H
|
#ifndef _MAGIC__RESIS__RESIS_H
|
||||||
#define _MAGIC__RESIS__RESIS_H
|
#define _MAGIC__RESIS__RESIS_H
|
||||||
|
|
||||||
/*
|
|
||||||
* Contact points: keeps track where contacts are and what tiles they refer to both
|
|
||||||
* before and after processing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define LAYERS_PER_CONTACT 4
|
#define LAYERS_PER_CONTACT 4
|
||||||
#define TILES_PER_JUNCTION 2
|
#define TILES_PER_JUNCTION 2
|
||||||
|
|
||||||
typedef struct contactpoint
|
typedef struct contactpoint
|
||||||
{
|
{
|
||||||
struct contactpoint *cp_nextcontact; /* Next contact in linked list. */
|
struct contactpoint *cp_nextcontact;/* Next contact in linked */
|
||||||
|
/* list. */
|
||||||
Point cp_center; /*Center of contact */
|
Point cp_center; /*Center of contact */
|
||||||
Rect cp_rect; /* Tile rectangle */
|
Rect cp_rect; /* Tile rectangle */
|
||||||
Tile *cp_contactTile; /* The following two keep track of
|
Tile *cp_contactTile;
|
||||||
* the tiles where the contact was
|
/*
|
||||||
* before preprocessing, and the
|
The following two keep
|
||||||
* next contact in that tile's area.
|
track of the tiles where
|
||||||
|
the contact was before
|
||||||
|
preprocessing, and the
|
||||||
|
next contact in that tile's
|
||||||
|
area.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Tile *cp_tile[LAYERS_PER_CONTACT];
|
Tile *cp_tile[LAYERS_PER_CONTACT];
|
||||||
int cp_currentcontact; /* keeps track of tile being processed */
|
int cp_currentcontact; /* keeps track of tile
|
||||||
|
being processed
|
||||||
|
*/
|
||||||
TileType cp_type; /* Type of contact */
|
TileType cp_type; /* Type of contact */
|
||||||
int cp_width; /* Width (in x) of contact region */
|
int cp_width; /* Width (in x) of contact region */
|
||||||
int cp_height; /* Height (in y) of contact region */
|
int cp_height; /* Height (in y) of contact region */
|
||||||
struct resnode *cp_cnode[LAYERS_PER_CONTACT];/* this contact's nodes */
|
struct resnode *cp_cnode[LAYERS_PER_CONTACT];/* this contact's nodes */
|
||||||
int cp_status; /* status of processing on this contact */
|
int cp_status; /* status of processing on
|
||||||
|
this contact
|
||||||
|
*/
|
||||||
} ResContactPoint;
|
} ResContactPoint;
|
||||||
|
|
||||||
typedef struct resistor
|
typedef struct resistor
|
||||||
|
|
@ -70,7 +81,7 @@ typedef struct device
|
||||||
struct resnode **rd_terminals;
|
struct resnode **rd_terminals;
|
||||||
int rd_nterms; /* number of terminals in rt_terminals */
|
int rd_nterms; /* number of terminals in rt_terminals */
|
||||||
int rd_perim; /* info about device */
|
int rd_perim; /* info about device */
|
||||||
int rd_area; /* used in .ext file */
|
int rd_area; /* used in .ext and .sim file */
|
||||||
int rd_length; /* patches. */
|
int rd_length; /* patches. */
|
||||||
int rd_width;
|
int rd_width;
|
||||||
int rd_tiles; /* number of tiles in device */
|
int rd_tiles; /* number of tiles in device */
|
||||||
|
|
@ -80,7 +91,7 @@ typedef struct device
|
||||||
} resDevice;
|
} resDevice;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A junction is formed when two tiles that connect are next to one another.
|
a junction is formed when two tiles that connect are next to one another.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct junction
|
typedef struct junction
|
||||||
|
|
@ -93,8 +104,8 @@ typedef struct junction
|
||||||
} ResJunction;
|
} ResJunction;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A port is declared for subcircuits; its name overrides any locally-generated
|
* A port is declared for subcircuits; its name overrides any locally-
|
||||||
* node name.
|
* generated node name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct resport
|
typedef struct resport
|
||||||
|
|
@ -106,8 +117,8 @@ typedef struct resport
|
||||||
} resPort;
|
} resPort;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* *element are 'cons' (in the LISP sense) cells used to make linked lists of
|
?element are 'cons' cells used to make linked lists of their referential
|
||||||
* their referential structures.
|
structures.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct reselement
|
typedef struct reselement
|
||||||
|
|
@ -142,11 +153,10 @@ typedef struct celement
|
||||||
} cElement;
|
} cElement;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Nodes formed from network. These are linked both forwards and backwards
|
Nodes formed from network. These are linked both forwards and backwords
|
||||||
* to other nodes. Lists of devices, resistors, junctions, and contacts
|
to other nodes. Lists of devices, resistors, junctions, and contacts
|
||||||
* corresponding to this node are kept.
|
corresponding to this node are kept.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct resnode
|
typedef struct resnode
|
||||||
{
|
{
|
||||||
struct resnode *rn_more; /* doubly linked list pointers */
|
struct resnode *rn_more; /* doubly linked list pointers */
|
||||||
|
|
@ -184,9 +194,9 @@ typedef struct nelement
|
||||||
} nElement;
|
} nElement;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Breakpoints are places on a tile which may serve as sources/sinks of
|
Breakpoints are places on a tile which may serve as sources/sinks of
|
||||||
* current. When resistance is calculated for a tile. this is calculated
|
current. When resistance is calculated for a tile. this is calculated
|
||||||
* between these points.
|
between these points.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct breakpoint
|
typedef struct breakpoint
|
||||||
|
|
@ -198,30 +208,30 @@ typedef struct breakpoint
|
||||||
} Breakpoint;
|
} Breakpoint;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Each tile needs to keep track of the following things associated with it.
|
Each tile needs to keep track of the following things associated with it.
|
||||||
* Since there are too many things to fit in the single ti_client field,
|
Since there are too many things to fit in the single ti_client field,
|
||||||
* this 1 to 7 adaptor is used.
|
this 1 to 6 adaptor is used.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct resinfo
|
typedef struct tilejunk
|
||||||
{
|
{
|
||||||
cElement *contactList; /*widgets connected to this tile */
|
cElement *contactList; /*widgets connected to this tile */
|
||||||
resDevice *deviceList; /* devices this tile is part of */
|
resDevice *deviceList;
|
||||||
resPort *portList; /* ports connected to this tile */
|
resPort *portList;
|
||||||
ResJunction *junctionList; /* junctions inside the tile */
|
ResJunction *junctionList;
|
||||||
Breakpoint *breakList; /* breakpoints inside the tile */
|
Breakpoint *breakList;
|
||||||
int sourceEdge; /* used in device tiles to keep
|
int sourceEdge; /* used in device tiles to keep
|
||||||
* track of which diffusion edges
|
* of which diffusion edges are
|
||||||
* are a transistor's source
|
* a transistor's source
|
||||||
*/
|
*/
|
||||||
int ri_status; /* status of tile processing */
|
int tj_status; /* status of tile processing */
|
||||||
} resInfo;
|
} tileJunk;
|
||||||
|
|
||||||
/* ResDevTile keeps track of the location and type of devices.
|
/* ResDevTile keeps track of the location and type of devices.
|
||||||
* These areas are painted into our copied def after the tree is totally
|
These areas are painted into our copied def after the tree is totally
|
||||||
* flattened. (They can't be painted right away becasue the copy routine
|
flattened. (They can't be painted right away becasue the copy routine
|
||||||
* uses the new def to keep track of where it is in the design. It is also
|
uses the new def to keep track of where it is in the design. It is also
|
||||||
* used when devices are preproceesed.
|
used when devices are preproceesed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct resdevtile
|
typedef struct resdevtile
|
||||||
|
|
@ -234,11 +244,9 @@ typedef struct resdevtile
|
||||||
int overlap;
|
int overlap;
|
||||||
} ResDevTile;
|
} ResDevTile;
|
||||||
|
|
||||||
/*
|
/* Linked list structure to use to store the substrate plane from each */
|
||||||
* Linked list structure to use to store the substrate plane from each
|
/* extracted CellDef so that they can be returned to the original after */
|
||||||
* extracted CellDef so that they can be returned to the original after
|
/* extraction. */
|
||||||
* extraction.
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct saveList {
|
struct saveList {
|
||||||
Plane *sl_plane;
|
Plane *sl_plane;
|
||||||
|
|
@ -284,7 +292,8 @@ typedef struct rcdelaystuff
|
||||||
float rc_Tdi; /* Tdi for node */
|
float rc_Tdi; /* Tdi for node */
|
||||||
} RCDelayStuff;
|
} RCDelayStuff;
|
||||||
|
|
||||||
/* More type declarations */
|
|
||||||
|
/* Type declarations */
|
||||||
|
|
||||||
typedef struct rdev
|
typedef struct rdev
|
||||||
{
|
{
|
||||||
|
|
@ -315,27 +324,34 @@ typedef struct resextnode
|
||||||
int status;
|
int status;
|
||||||
struct resextnode *forward; /* If node has been merged, this */
|
struct resextnode *forward; /* If node has been merged, this */
|
||||||
/* points to the merged node. */
|
/* points to the merged node. */
|
||||||
float capacitance; /* Capacitance between node and */
|
float capacitance; /* capacitance between node and */
|
||||||
/* substrate */
|
/* GND for power connections */
|
||||||
float cap_couple; /* Coupling capacitance */
|
/* and all capacitance for every */
|
||||||
float resistance; /* Lumped resistance */
|
/* thing else. */
|
||||||
|
float cap_vdd; /* capacitance to VDD (used for */
|
||||||
|
/* power calculations only */
|
||||||
|
float cap_couple; /* coupling capacitance */
|
||||||
|
float resistance; /* lumped resistance */
|
||||||
float minsizeres; /* Minimum size resistor allowed */
|
float minsizeres; /* Minimum size resistor allowed */
|
||||||
Point drivepoint; /* optional, user specified drive */
|
Point drivepoint; /* optional, user specified drive */
|
||||||
/* point for network. */
|
/* point for network. */
|
||||||
TileType rs_ttype; /* Tiletype of drivepoint */
|
TileType rs_ttype; /* tiletype of drivepoint */
|
||||||
Point location; /* Location of bottom of leftmost */
|
Point location; /* location of bottom of leftmost */
|
||||||
/* tile in the lowest numbered */
|
/* tile in the lowest numbered */
|
||||||
/* plane contained in the node . */
|
/* plane contained in the node . */
|
||||||
Rect rs_bbox; /* Location of bottom of leftmost */
|
Rect rs_bbox; /* location of bottom of leftmost */
|
||||||
/* tile in the lowest numbered */
|
/* tile in the lowest numbered */
|
||||||
/* plane contained in the node . */
|
/* plane contained in the node . */
|
||||||
TileType type; /* Tile type of tile at location */
|
TileType type; /* Tile type of tile at location */
|
||||||
struct devptr *firstDev; /* Linked list of devices */
|
struct devptr *firstDev; /* linked list of devices */
|
||||||
/* connected to node. */
|
/* connected to node. */
|
||||||
char *name; /* Pointer to name of node stored */
|
char *name; /* Pointer to name of node stored */
|
||||||
/* in hash table. */
|
/* in hash table. */
|
||||||
char *oldname; /* Pointer to previous name of */
|
char *oldname; /* Pointer to previous name of */
|
||||||
/* node, if it exists */
|
/* node, if it exists */
|
||||||
|
tElement *rs_sublist[2]; /* pointers to Gnd and Vdd sub */
|
||||||
|
/* strate connections,
|
||||||
|
if they exist */
|
||||||
} ResExtNode;
|
} ResExtNode;
|
||||||
|
|
||||||
#define RES_SUB_GND 0
|
#define RES_SUB_GND 0
|
||||||
|
|
@ -362,75 +378,63 @@ typedef struct resfixpoint /* Keeps track of where voltage sources are */
|
||||||
char fp_name[1];
|
char fp_name[1];
|
||||||
} ResFixPoint;
|
} ResFixPoint;
|
||||||
|
|
||||||
/*
|
|
||||||
* Multipliers telling what portion of capacitance is to Vdd and what part is
|
|
||||||
* to ground. Right now, coupling capacitance is counted twice, so
|
|
||||||
* cap[0] + cap[1] = (c_vdd + c_gnd + 2 * c_couple) / (c_vdd + c_gnd + c_couple);
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct capval
|
typedef struct capval
|
||||||
{
|
{
|
||||||
float cap[1][2];
|
float cap[1][2]; /* multipliers telling what portion of capacitance is
|
||||||
|
to Vdd and what part is to ground. Right now,
|
||||||
|
coupling capacitance is counted twice, so
|
||||||
|
cap[0]+cap[1] = (c_vdd+c_gnd+2*c_couple)/
|
||||||
|
(c_vdd+c_gnd+c_couple);
|
||||||
|
*/
|
||||||
} ResCapVal;
|
} ResCapVal;
|
||||||
|
|
||||||
/* Node flags ("rn_status" field) */
|
/* node flags */
|
||||||
|
|
||||||
#define RES_TRUE 0x00000001
|
|
||||||
#define RES_PENDING 0x00000002
|
|
||||||
#define RES_FINISHED 0x00000004
|
|
||||||
#define RES_MARKED 0x00000100
|
|
||||||
#define RES_MAXTDI 0x00001000
|
|
||||||
#define RES_DONE_ONCE 0x00002000
|
|
||||||
#define RES_REACHED_NODE 0x00200000
|
#define RES_REACHED_NODE 0x00200000
|
||||||
#define RES_NODE_XADJ 0x00400000
|
#define RES_NODE_XADJ 0x00400000
|
||||||
#define RES_NODE_YADJ 0x00800000
|
#define RES_NODE_YADJ 0x00800000
|
||||||
|
|
||||||
/* Resistor flags ("rr_status" field) */
|
/* type of node flags */
|
||||||
|
|
||||||
#define RES_EW 0x00000200
|
|
||||||
#define RES_NS 0x00000400
|
|
||||||
#define RES_DIAGONAL 0x00000800
|
|
||||||
#define RES_DEADEND 0x00001000
|
|
||||||
#define RES_TDI_IGNORE 0x00010000
|
|
||||||
#define RES_REACHED_RESISTOR 0x00100000
|
|
||||||
#define RES_HEAP 0x00200000
|
|
||||||
|
|
||||||
/* Note that RES_DONE_ONCE and RES_MARKED are used both for rn_status and
|
|
||||||
* rr_status, and these bit values must not collide with any other field
|
|
||||||
* values.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Device flags ("rd_status" field) */
|
|
||||||
|
|
||||||
#define RES_DEV_SAVE 0x00000001
|
|
||||||
|
|
||||||
/* Type of node flags ("why" field) */
|
|
||||||
|
|
||||||
#define RES_NODE_JUNCTION 0x00000001
|
#define RES_NODE_JUNCTION 0x00000001
|
||||||
#define RES_NODE_DEVICE 0x00000002
|
#define RES_NODE_DEVICE 0x00000002
|
||||||
#define RES_NODE_CONTACT 0x00000004
|
#define RES_NODE_CONTACT 0x00000004
|
||||||
#define RES_NODE_ORIGIN 0x00000008
|
#define RES_NODE_ORIGIN 0x00000008
|
||||||
#define RES_NODE_SINK 0x00000010
|
|
||||||
|
|
||||||
/* Flags for tiles ("ri_status" field) */
|
/* resistor flags */
|
||||||
|
#define RES_DEADEND 0x00001000
|
||||||
|
#define RES_DONE_ONCE 0x00002000
|
||||||
|
#define RES_MARKED 0x00000100
|
||||||
|
#define RES_EW 0x00000200
|
||||||
|
#define RES_NS 0x00000400
|
||||||
|
#define RES_DIAGONAL 0x00000800
|
||||||
|
#define RES_TDI_IGNORE 0x00010000
|
||||||
|
#define RES_REACHED_RESISTOR 0x00100000
|
||||||
|
#define RES_HEAP 0x00200000
|
||||||
|
|
||||||
#define RES_TILE_SUBS 0x01 /* A tile which is part of a substrate region. */
|
/* device flags */
|
||||||
#define RES_TILE_SD 0x02 /* A tile which is part of a source/drain region. */
|
#define RES_DEV_SAVE 0x00000001
|
||||||
#define RES_TILE_DEV 0x04 /* A tile which is actually a device */
|
|
||||||
#define RES_TILE_DONE 0x08 /* Indicates whether tile has been processed */
|
|
||||||
#define RES_TILE_MARK 0x10 /* A temporary marking flag */
|
|
||||||
#define RES_TILE_PUSHED 0x20 /* Another temporary marking flag */
|
|
||||||
|
|
||||||
/* Tree walking flags */
|
|
||||||
|
|
||||||
|
/* flags for tiles */
|
||||||
|
/* A tile which is part of a substrate region. */
|
||||||
|
#define RES_TILE_SUBS 0x01
|
||||||
|
/* A tile which is part of a source/drain region. */
|
||||||
|
#define RES_TILE_SD 0x02
|
||||||
|
/* A tile which is actually a device */
|
||||||
|
#define RES_TILE_DEV 0x04
|
||||||
|
/* Indicates whether the tile has been processed or not */
|
||||||
|
#define RES_TILE_DONE 0x08
|
||||||
|
/*a temporary marking flag */
|
||||||
|
#define RES_TILE_MARK 0x10
|
||||||
|
/*another temporary marking flag */
|
||||||
|
#define RES_TILE_PUSHED 0x20
|
||||||
|
/* tree walking flags */
|
||||||
#define RES_LOOP_OK 1
|
#define RES_LOOP_OK 1
|
||||||
#define RES_NO_LOOP 1
|
#define RES_NO_LOOP 1
|
||||||
#define RES_DO_LAST 0
|
#define RES_DO_LAST 0
|
||||||
#define RES_DO_FIRST 1
|
#define RES_DO_FIRST 1
|
||||||
#define RES_NO_FLAGS 0
|
#define RES_NO_FLAGS 0
|
||||||
|
|
||||||
/* Constants (ResExtNode "status" field) */
|
|
||||||
|
|
||||||
|
/* Constants */
|
||||||
#define FORWARD 0x0000010
|
#define FORWARD 0x0000010
|
||||||
#define SKIP 0x0000020
|
#define SKIP 0x0000020
|
||||||
#define FORCE 0x0000040
|
#define FORCE 0x0000040
|
||||||
|
|
@ -441,8 +445,13 @@ typedef struct capval
|
||||||
#define DONTKILL 0x0000800
|
#define DONTKILL 0x0000800
|
||||||
|
|
||||||
/* Capacitance table constants */
|
/* Capacitance table constants */
|
||||||
|
#define RES_CAP_GND 0
|
||||||
|
#define RES_CAP_VDD 1
|
||||||
|
#define RES_CAP_COUPLE 2
|
||||||
|
|
||||||
#define OHMSTOMILLIOHMS 1000
|
#define OHMSTOMILLIOHMS 1000
|
||||||
|
#define FEMTOTOATTO 1000
|
||||||
|
#define ATTOTOFEMTO 0.001
|
||||||
|
|
||||||
#define UNTOUCHED 0
|
#define UNTOUCHED 0
|
||||||
#define SERIES 1
|
#define SERIES 1
|
||||||
|
|
@ -451,40 +460,62 @@ typedef struct capval
|
||||||
#define SINGLE 8
|
#define SINGLE 8
|
||||||
#define TRIANGLE 32
|
#define TRIANGLE 32
|
||||||
|
|
||||||
|
#define RESTRUE 1
|
||||||
|
#define PENDING 2
|
||||||
|
#define FINISHED 4
|
||||||
|
|
||||||
#define LEFTEDGE 1
|
#define LEFTEDGE 1
|
||||||
#define RIGHTEDGE 4
|
#define RIGHTEDGE 4
|
||||||
#define TOPEDGE 8
|
#define TOPEDGE 8
|
||||||
#define BOTTOMEDGE 16
|
#define BOTTOMEDGE 16
|
||||||
#define OTHERPLANE 32
|
#define OTHERPLANE 32
|
||||||
|
|
||||||
|
#define RN_MAXTDI 0x00001000
|
||||||
|
|
||||||
|
#define MARKED 0x00000100
|
||||||
|
|
||||||
#define GATE 1
|
#define GATE 1
|
||||||
#define SOURCE 2
|
#define SOURCE 2
|
||||||
#define DRAIN 3
|
#define DRAIN 3
|
||||||
#define SUBS 4
|
#define SUBS 4
|
||||||
|
|
||||||
/* "rg_status" flag */
|
|
||||||
|
|
||||||
#define DRIVEONLY 0x00001000
|
#define DRIVEONLY 0x00001000
|
||||||
|
#define ORIGIN 0x00000008
|
||||||
|
|
||||||
/* Magic's normal value of infinity is too small---67108863 is only 67K ohms. */
|
/* magic's normal value of infinity is too small- */
|
||||||
|
/* 67108863 is only 67K ohms. */
|
||||||
|
|
||||||
#define RES_INFINITY 0x3FFFFFFF
|
#define RES_INFINITY 0x3FFFFFFF
|
||||||
|
|
||||||
|
#define ResCheckIntegrity
|
||||||
|
|
||||||
/* The following turns on and off various options */
|
/* The following turns on and off various options */
|
||||||
|
|
||||||
#define ResOpt_ExtractAll 0x0001
|
#define ResOpt_ExtractAll 0x00000002
|
||||||
#define ResOpt_Simplify 0x0002
|
#define ResOpt_Simplify 0x00000004
|
||||||
#define ResOpt_DoExtFile 0x0004
|
#define ResOpt_DoExtFile 0x00000008
|
||||||
#define ResOpt_DoLumpFile 0x0008
|
#define ResOpt_DoRsmFile 0x00000010
|
||||||
#define ResOpt_RunSilent 0x0010
|
#define ResOpt_DoLumpFile 0x00000020
|
||||||
#define ResOpt_Stats 0x0020
|
#define ResOpt_RunSilent 0x00000040
|
||||||
#define ResOpt_Tdi 0x0040
|
#define ResOpt_ExplicitRtol 0x00000080
|
||||||
#define ResOpt_Signal 0x0080
|
#define ResOpt_ExplicitTditol 0x00000100
|
||||||
#define ResOpt_Geometry 0x0100
|
#define ResOpt_Tdi 0x00000200
|
||||||
#define ResOpt_FastHenry 0x0200
|
#define ResOpt_Stat 0x00000400
|
||||||
#define ResOpt_Blackbox 0x0300
|
#define ResOpt_Power 0x00000800
|
||||||
#define ResOpt_DoSubstrate 0x0800
|
#define ResOpt_Signal 0x00001000
|
||||||
#define ResOpt_Box 0x1000
|
#define ResOpt_Pname 0x00002000
|
||||||
|
#define ResOpt_Geometry 0x00004000
|
||||||
|
#define ResOpt_FastHenry 0x00008000
|
||||||
|
#define ResOpt_Blackbox 0x00010000
|
||||||
|
#define ResOpt_Dump 0x00020000
|
||||||
|
#define ResOpt_DoSubstrate 0x00040000
|
||||||
|
#define ResOpt_CMOS 0x00800000
|
||||||
|
#define ResOpt_Bipolar 0x01000000
|
||||||
|
#define ResOpt_Box 0x02000000
|
||||||
|
|
||||||
|
#define ResOpt_VDisplay 0x10000000
|
||||||
|
#define ResOpt_IDisplay 0x20000000
|
||||||
|
#define ResOpt_PDisplay 0x40000000
|
||||||
|
|
||||||
/* Assorted Variables */
|
/* Assorted Variables */
|
||||||
|
|
||||||
|
|
@ -502,7 +533,7 @@ extern resNode *ResNodeList;
|
||||||
extern resDevice *ResDevList;
|
extern resDevice *ResDevList;
|
||||||
extern ResContactPoint *ResContactList;
|
extern ResContactPoint *ResContactList;
|
||||||
extern resNode *ResNodeQueue;
|
extern resNode *ResNodeQueue;
|
||||||
extern resNode *ResNodeAtOrigin;
|
extern resNode *ResOriginNode;
|
||||||
extern resNode *resCurrentNode;
|
extern resNode *resCurrentNode;
|
||||||
extern HashTable ResNodeTable;
|
extern HashTable ResNodeTable;
|
||||||
extern HashTable ResExtDevTable;
|
extern HashTable ResExtDevTable;
|
||||||
|
|
@ -517,7 +548,6 @@ extern TileTypeBitMask ResNoMergeMask[NT];
|
||||||
extern int ResPortIndex;
|
extern int ResPortIndex;
|
||||||
|
|
||||||
/* Routines used by ResReadExt() */
|
/* Routines used by ResReadExt() */
|
||||||
|
|
||||||
extern ResisData *ResInit();
|
extern ResisData *ResInit();
|
||||||
extern int ResReadDevice();
|
extern int ResReadDevice();
|
||||||
extern int ResReadCapacitor();
|
extern int ResReadCapacitor();
|
||||||
|
|
@ -529,14 +559,12 @@ extern int ResReadSubckt();
|
||||||
extern int ResProcessNode();
|
extern int ResProcessNode();
|
||||||
extern int ResExtCombineParallel();
|
extern int ResExtCombineParallel();
|
||||||
extern int dbSrConnectStartFunc();
|
extern int dbSrConnectStartFunc();
|
||||||
extern int ResEach();
|
extern int ResEach(),ResAddPlumbing(),ResRemovePlumbing();
|
||||||
extern int ResAddPlumbing();
|
|
||||||
extern int ResRemovePlumbing();
|
|
||||||
extern float ResCalculateChildCapacitance();
|
extern float ResCalculateChildCapacitance();
|
||||||
extern ResDevTile *DBTreeCopyConnectDCS();
|
extern ResDevTile *DBTreeCopyConnectDCS();
|
||||||
extern Tile *ResFindTile();
|
extern Tile *ResFindTile();
|
||||||
extern resDevice *ResGetDevice();
|
extern resDevice *ResGetDevice();
|
||||||
extern resInfo *resAddField();
|
extern tileJunk *resAddField();
|
||||||
extern int ResCheckPorts();
|
extern int ResCheckPorts();
|
||||||
extern int ResCheckBlackbox();
|
extern int ResCheckBlackbox();
|
||||||
extern void ResCheckExtNodes();
|
extern void ResCheckExtNodes();
|
||||||
|
|
@ -547,14 +575,12 @@ extern void ResSortBreaks();
|
||||||
extern Plane *extResPrepSubstrate();
|
extern Plane *extResPrepSubstrate();
|
||||||
|
|
||||||
/* C99 compat */
|
/* C99 compat */
|
||||||
|
|
||||||
extern void ExtResisForDef(CellDef *celldef, ResisData *resisdata);
|
extern void ExtResisForDef(CellDef *celldef, ResisData *resisdata);
|
||||||
extern char *ResExtGetAttribute(char *sptr);
|
extern char *ResExtGetAttribute(char *sptr);
|
||||||
extern int ResReadFET(int argc, char *argv[]);
|
extern int ResReadFET(int argc, char *argv[]);
|
||||||
extern int ResReadPort(int argc, char *argv[]);
|
extern int ResReadPort(int argc, char *argv[]);
|
||||||
extern char *ResExtGetAttribute(char *sptr);
|
extern char *ResExtGetAttribute(char *sptr);
|
||||||
|
|
||||||
extern ResExtNode *ResExtInitNode();
|
|
||||||
extern void ResAddToQueue();
|
extern void ResAddToQueue();
|
||||||
extern bool ResCalcTileResistance();
|
extern bool ResCalcTileResistance();
|
||||||
extern void ResCleanNode();
|
extern void ResCleanNode();
|
||||||
|
|
@ -596,9 +622,10 @@ extern int resWalkleft();
|
||||||
extern int resWalkright();
|
extern int resWalkright();
|
||||||
extern int resWalkup();
|
extern int resWalkup();
|
||||||
|
|
||||||
/* Macros */
|
|
||||||
|
|
||||||
#define InitializeResNode(node,x,y,why) \
|
/* macros */
|
||||||
|
|
||||||
|
#define InitializeNode(node,x,y,why) \
|
||||||
{\
|
{\
|
||||||
(node)->rn_te = NULL;\
|
(node)->rn_te = NULL;\
|
||||||
(node)->rn_id=0;\
|
(node)->rn_id=0;\
|
||||||
|
|
@ -615,21 +642,21 @@ extern int resWalkup();
|
||||||
(node)->rn_re = (resElement *) NULL;\
|
(node)->rn_re = (resElement *) NULL;\
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ResInfoInit(Info) \
|
#define ResJunkInit(Junk) \
|
||||||
{ \
|
{ \
|
||||||
Info->contactList = (cElement *) NULL; \
|
Junk->contactList = (cElement *) NULL; \
|
||||||
Info->deviceList = (resDevice *) NULL; \
|
Junk->deviceList = (resDevice *) NULL; \
|
||||||
Info->junctionList = (ResJunction *) NULL; \
|
Junk->junctionList = (ResJunction *) NULL; \
|
||||||
Info->breakList = (Breakpoint *) NULL; \
|
Junk->breakList = (Breakpoint *) NULL; \
|
||||||
Info->portList = (resPort *) NULL; \
|
Junk->portList = (resPort *) NULL; \
|
||||||
Info->ri_status = FALSE; \
|
Junk->tj_status = FALSE; \
|
||||||
Info->sourceEdge = 0 ; \
|
Junk->sourceEdge = 0 ; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NEWBREAK(node,tile,px,py,crect)\
|
#define NEWBREAK(node,tile,px,py,crect)\
|
||||||
{\
|
{\
|
||||||
Breakpoint *bp;\
|
Breakpoint *bp;\
|
||||||
resInfo *jX_ = (resInfo *)((tile)->ti_client); \
|
tileJunk *jX_ = (tileJunk *)((tile)->ti_client); \
|
||||||
bp = (Breakpoint *) mallocMagic((unsigned)(sizeof(Breakpoint))); \
|
bp = (Breakpoint *) mallocMagic((unsigned)(sizeof(Breakpoint))); \
|
||||||
bp->br_next= jX_->breakList; \
|
bp->br_next= jX_->breakList; \
|
||||||
bp->br_this = (node); \
|
bp->br_this = (node); \
|
||||||
|
|
@ -642,7 +669,7 @@ extern int resWalkup();
|
||||||
#define NEWPORT(node,tile)\
|
#define NEWPORT(node,tile)\
|
||||||
{\
|
{\
|
||||||
resPort *rp;\
|
resPort *rp;\
|
||||||
resInfo *pX_ = (resInfo *)((tile)->ti_client); \
|
tileJunk *pX_ = (tileJunk *)((tile)->ti_client); \
|
||||||
rp = (resPort *) mallocMagic((unsigned)(sizeof(resPort))); \
|
rp = (resPort *) mallocMagic((unsigned)(sizeof(resPort))); \
|
||||||
rp->rp_nextPort = pX_->portList; \
|
rp->rp_nextPort = pX_->portList; \
|
||||||
rp->rp_bbox = node->rs_bbox; \
|
rp->rp_bbox = node->rs_bbox; \
|
||||||
|
|
|
||||||
|
|
@ -321,20 +321,14 @@ selRedisplayCellFunc(scx, window)
|
||||||
if (scx->scx_use->cu_def->cd_flags & CDFIXEDBBOX)
|
if (scx->scx_use->cu_def->cd_flags & CDFIXEDBBOX)
|
||||||
{
|
{
|
||||||
bool found;
|
bool found;
|
||||||
PropertyRecord *proprec;
|
char *propval;
|
||||||
|
|
||||||
proprec = DBPropGet(scx->scx_use->cu_def, "FIXED_BBOX", &found);
|
propval = (char *)DBPropGet(scx->scx_use->cu_def, "FIXED_BBOX", &found);
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
if ((proprec->prop_type == PROPERTY_TYPE_DIMENSION) &&
|
if (sscanf(propval, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
|
||||||
(proprec->prop_len == 4))
|
&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];
|
|
||||||
GeoTransRect(&scx->scx_trans, &bbox, &tmp);
|
GeoTransRect(&scx->scx_trans, &bbox, &tmp);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
found = FALSE;
|
found = FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,14 +46,14 @@ proc magic::drccallback {command} {
|
||||||
}
|
}
|
||||||
zoom {
|
zoom {
|
||||||
if {$value != {}} {
|
if {$value != {}} {
|
||||||
set curunits [units]
|
set snaptype [snap]
|
||||||
units internal
|
snap internal
|
||||||
box values {*}$value
|
box values {*}$value
|
||||||
magic::suspendall
|
magic::suspendall
|
||||||
magic::findbox zoom
|
magic::findbox zoom
|
||||||
magic::zoom 2
|
magic::zoom 2
|
||||||
magic::resumeall
|
magic::resumeall
|
||||||
units {*}$curunits
|
snap $snaptype
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -250,10 +250,10 @@ proc magic::change_label {} {
|
||||||
setlabel size ${lsize}um
|
setlabel size ${lsize}um
|
||||||
}
|
}
|
||||||
if {$loff != ""} {
|
if {$loff != ""} {
|
||||||
set oldunits [units]
|
set oldsnap [snap list]
|
||||||
units internal
|
snap internal
|
||||||
setlabel offset [join $loff]
|
setlabel offset [join $loff]
|
||||||
units $oldunits
|
snap $oldsnap
|
||||||
}
|
}
|
||||||
if {$lrot != ""} {
|
if {$lrot != ""} {
|
||||||
setlabel rotate $lrot
|
setlabel rotate $lrot
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,6 @@
|
||||||
# Revision 2 (names are hashed from properties)
|
# Revision 2 (names are hashed from properties)
|
||||||
# March 9, 2021
|
# March 9, 2021
|
||||||
# Added spice-to-layout procedure
|
# Added spice-to-layout procedure
|
||||||
# March 4, 2026
|
|
||||||
# Changed to make use of new "units" command
|
|
||||||
# March 26, 2026
|
|
||||||
# Added behavior to handle ideal devices (resistor, capacitor,
|
|
||||||
# inductor)
|
|
||||||
#--------------------------------------------------------------
|
#--------------------------------------------------------------
|
||||||
# Sets up the environment for a toolkit. The toolkit must
|
# Sets up the environment for a toolkit. The toolkit must
|
||||||
# supply a namespace that is the "library name". For each
|
# supply a namespace that is the "library name". For each
|
||||||
|
|
@ -123,8 +118,6 @@ magic::tag add select "magic::gencell_update %1"
|
||||||
|
|
||||||
proc magic::move_forward_by_width {instname} {
|
proc magic::move_forward_by_width {instname} {
|
||||||
select cell $instname
|
select cell $instname
|
||||||
set curunits [units]
|
|
||||||
units internal
|
|
||||||
set anum [lindex [array -list count] 1]
|
set anum [lindex [array -list count] 1]
|
||||||
set xpitch [lindex [array -list pitch] 0]
|
set xpitch [lindex [array -list pitch] 0]
|
||||||
set bbox [box values]
|
set bbox [box values]
|
||||||
|
|
@ -132,8 +125,7 @@ proc magic::move_forward_by_width {instname} {
|
||||||
set posy [lindex $bbox 1]
|
set posy [lindex $bbox 1]
|
||||||
set width [expr [lindex $bbox 2] - $posx]
|
set width [expr [lindex $bbox 2] - $posx]
|
||||||
set posx [expr $posx + $width + $xpitch * $anum]
|
set posx [expr $posx + $width + $xpitch * $anum]
|
||||||
box position ${posx} ${posy}
|
box position ${posx}i ${posy}i
|
||||||
units {*}$curunits
|
|
||||||
return [lindex $bbox 3]
|
return [lindex $bbox 3]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,13 +141,10 @@ proc magic::get_and_move_inst {cellname instname {anum 1}} {
|
||||||
if {$newinst == ""} {return}
|
if {$newinst == ""} {return}
|
||||||
identify $instname
|
identify $instname
|
||||||
if {$anum > 1} {array 1 $anum}
|
if {$anum > 1} {array 1 $anum}
|
||||||
set curunits [units]
|
|
||||||
units internal
|
|
||||||
set bbox [box values]
|
set bbox [box values]
|
||||||
set posx [lindex $bbox 2]
|
set posx [lindex $bbox 2]
|
||||||
set posy [lindex $bbox 1]
|
set posy [lindex $bbox 1]
|
||||||
box position ${posx} ${posy}
|
box position ${posx}i ${posy}i
|
||||||
units {*}$curunits
|
|
||||||
return [lindex $bbox 3]
|
return [lindex $bbox 3]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -166,14 +155,11 @@ proc magic::get_and_move_inst {cellname instname {anum 1}} {
|
||||||
# given layer. Otherwise, the pin is created on the m1 layer.
|
# given layer. Otherwise, the pin is created on the m1 layer.
|
||||||
|
|
||||||
proc magic::create_new_pin {pinname portnum {layer m1}} {
|
proc magic::create_new_pin {pinname portnum {layer m1}} {
|
||||||
set curunits [units]
|
box size 1um 1um
|
||||||
units microns
|
|
||||||
box size 1 1
|
|
||||||
paint $layer
|
paint $layer
|
||||||
label $pinname FreeSans 1 0 0 0 c $layer
|
label $pinname FreeSans 16 0 0 0 c $layer
|
||||||
port make $portnum
|
port make $portnum
|
||||||
box move s 2
|
box move s 2um
|
||||||
units {*}$curunits
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# generate_layout_add --
|
# generate_layout_add --
|
||||||
|
|
@ -186,9 +172,6 @@ proc magic::create_new_pin {pinname portnum {layer m1}} {
|
||||||
proc magic::generate_layout_add {subname subpins complist library} {
|
proc magic::generate_layout_add {subname subpins complist library} {
|
||||||
global PDKNAMESPACE
|
global PDKNAMESPACE
|
||||||
|
|
||||||
set curunits [units]
|
|
||||||
units internal
|
|
||||||
|
|
||||||
# Create a new subcircuit.
|
# Create a new subcircuit.
|
||||||
load $subname -quiet
|
load $subname -quiet
|
||||||
|
|
||||||
|
|
@ -258,7 +241,7 @@ proc magic::generate_layout_add {subname subpins complist library} {
|
||||||
box size 0 0
|
box size 0 0
|
||||||
set posx 0
|
set posx 0
|
||||||
set posy [expr {round(3 / [cif scale out])}]
|
set posy [expr {round(3 / [cif scale out])}]
|
||||||
box position ${posx} ${posy}
|
box position ${posx}i ${posy}i
|
||||||
|
|
||||||
# Find all instances in the circuit
|
# Find all instances in the circuit
|
||||||
select top cell
|
select top cell
|
||||||
|
|
@ -284,13 +267,8 @@ proc magic::generate_layout_add {subname subpins complist library} {
|
||||||
set paramlist {}
|
set paramlist {}
|
||||||
|
|
||||||
# NOTE: This routine deals with subcircuit calls and devices
|
# NOTE: This routine deals with subcircuit calls and devices
|
||||||
# with models. There are two exceptions, for toolkits which
|
# with models. It needs to determine when a device is instantiated
|
||||||
# wish to implement a way to generate unmodeled capacitors,
|
# without a model, and ignore such devices.
|
||||||
# resistors, or inductors based on value; for example, metal
|
|
||||||
# interdigitated capacitors. For those exceptions, the device
|
|
||||||
# value is recast as a parameter called "value", and the device
|
|
||||||
# is given a model "capacitor", "resistor", or "inductor",
|
|
||||||
# respectively.
|
|
||||||
|
|
||||||
# Parse SPICE line into pins, device name, and parameters. Make
|
# Parse SPICE line into pins, device name, and parameters. Make
|
||||||
# sure parameters incorporate quoted expressions as {} or ''.
|
# sure parameters incorporate quoted expressions as {} or ''.
|
||||||
|
|
@ -334,23 +312,6 @@ proc magic::generate_layout_add {subname subpins complist library} {
|
||||||
set devtype [lindex $pinlist end]
|
set devtype [lindex $pinlist end]
|
||||||
set pinlist [lrange $pinlist 0 end-1]
|
set pinlist [lrange $pinlist 0 end-1]
|
||||||
|
|
||||||
# Ideal device check: "devtype" will start with a digit.
|
|
||||||
# The instname will begin with "c", "r", or "l".
|
|
||||||
|
|
||||||
if {[regexp {^([0-9\.]+.*)} $devtype pval]} {
|
|
||||||
set comptype [string tolower [string range $instname 0 0]]
|
|
||||||
if {$comptype == "c"} {
|
|
||||||
lappend paramlist [list value $pval]
|
|
||||||
set devtype capacitor
|
|
||||||
} elseif {$comptype == "r"} {
|
|
||||||
lappend paramlist [list value $pval]
|
|
||||||
set devtype resistor
|
|
||||||
} elseif {$comptype == "l"} {
|
|
||||||
lappend paramlist [list value $pval]
|
|
||||||
set devtype inductor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
set mult 1
|
set mult 1
|
||||||
foreach param $paramlist {
|
foreach param $paramlist {
|
||||||
set parmname [lindex $param 0]
|
set parmname [lindex $param 0]
|
||||||
|
|
@ -362,27 +323,6 @@ proc magic::generate_layout_add {subname subpins complist library} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if devtype has routines by looking for ${devtype}_defaults.
|
|
||||||
# If not found, do a case-insensitive check against all devices
|
|
||||||
# before deciding that devtype is a subcircuit and not a device.
|
|
||||||
# If found by case-insensitive check, then change the device name
|
|
||||||
# to the one used in the library.
|
|
||||||
|
|
||||||
if {$library != ""} {
|
|
||||||
set alldevices [namespace eval ::${library} {info procs}]
|
|
||||||
} else {
|
|
||||||
set alldevices [namespace eval ::${PDKNAMESPACE} {info procs}]
|
|
||||||
}
|
|
||||||
set devdefault [lsearch $alldevices ${devtype}_defaults]
|
|
||||||
if {$devdefault == -1} {
|
|
||||||
set devdefault [lsearch -nocase $alldevices ${devtype}_defaults]
|
|
||||||
if {$devdefault != -1} {
|
|
||||||
set devprocname [lindex $alldevices $devdefault]
|
|
||||||
set devproclist [split $devprocname "_"]
|
|
||||||
set devtype [lindex $devproclist 0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# devtype is assumed to be in library. If not, it will attempt to
|
# devtype is assumed to be in library. If not, it will attempt to
|
||||||
# use 'getcell' on devtype. Note that this code depends on the
|
# use 'getcell' on devtype. Note that this code depends on the
|
||||||
# PDK setting varible PDKNAMESPACE.
|
# PDK setting varible PDKNAMESPACE.
|
||||||
|
|
@ -434,7 +374,6 @@ proc magic::generate_layout_add {subname subpins complist library} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
save $subname
|
save $subname
|
||||||
units {*}$curunits
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#--------------------------------------------------------------
|
#--------------------------------------------------------------
|
||||||
|
|
@ -546,7 +485,7 @@ proc magic::netlist_to_layout {netfile library} {
|
||||||
set subname [lindex $ftokens 1]
|
set subname [lindex $ftokens 1]
|
||||||
set subpins [lrange $ftokens 2 end]
|
set subpins [lrange $ftokens 2 end]
|
||||||
set insub true
|
set insub true
|
||||||
} elseif {[regexp -nocase {^[xmcrldq]([^ \t]+)[ \t](.*)$} $line \
|
} elseif {[regexp -nocase {^[xmcrdq]([^ \t]+)[ \t](.*)$} $line \
|
||||||
valid instname rest]} {
|
valid instname rest]} {
|
||||||
lappend toplist $line
|
lappend toplist $line
|
||||||
} elseif {[regexp -nocase {^[ivbe]([^ \t]+)[ \t](.*)$} $line \
|
} elseif {[regexp -nocase {^[ivbe]([^ \t]+)[ \t](.*)$} $line \
|
||||||
|
|
@ -561,7 +500,7 @@ proc magic::netlist_to_layout {netfile library} {
|
||||||
set subname ""
|
set subname ""
|
||||||
set subpins ""
|
set subpins ""
|
||||||
set complist {}
|
set complist {}
|
||||||
} elseif {[regexp -nocase {^[xmcrldq]([^ \t]+)[ \t](.*)$} $line \
|
} elseif {[regexp -nocase {^[xmcrdq]([^ \t]+)[ \t](.*)$} $line \
|
||||||
valid instname rest]} {
|
valid instname rest]} {
|
||||||
lappend complist $line
|
lappend complist $line
|
||||||
} elseif {[regexp -nocase {^[ivbe]([^ \t]+)[ \t](.*)$} $line \
|
} elseif {[regexp -nocase {^[ivbe]([^ \t]+)[ \t](.*)$} $line \
|
||||||
|
|
@ -874,8 +813,8 @@ proc magic::gencell_change {instname gencell_type library parameters} {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
set curunits [units]
|
set snaptype [snap list]
|
||||||
units internal
|
snap internal
|
||||||
set savebox [box values]
|
set savebox [box values]
|
||||||
|
|
||||||
catch {setpoint 0 0 $Opts(focus)}
|
catch {setpoint 0 0 $Opts(focus)}
|
||||||
|
|
@ -942,7 +881,7 @@ proc magic::gencell_change {instname gencell_type library parameters} {
|
||||||
}
|
}
|
||||||
identify $newinstname
|
identify $newinstname
|
||||||
eval "box values $savebox"
|
eval "box values $savebox"
|
||||||
units {*}$curunits
|
snap $snaptype
|
||||||
|
|
||||||
# Update window
|
# Update window
|
||||||
if {$gname != $old_gname} {
|
if {$gname != $old_gname} {
|
||||||
|
|
@ -1001,8 +940,8 @@ proc magic::gencell_change_orig {instname gencell_type library parameters} {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
set curunits [units]
|
set snaptype [snap list]
|
||||||
units internal
|
snap internal
|
||||||
set savebox [box values]
|
set savebox [box values]
|
||||||
|
|
||||||
catch {setpoint 0 0 $Opts(focus)}
|
catch {setpoint 0 0 $Opts(focus)}
|
||||||
|
|
@ -1030,7 +969,7 @@ proc magic::gencell_change_orig {instname gencell_type library parameters} {
|
||||||
}
|
}
|
||||||
identify $newinstname
|
identify $newinstname
|
||||||
eval "box values $savebox"
|
eval "box values $savebox"
|
||||||
units {*}$curunits
|
snap $snaptype
|
||||||
resumeall
|
resumeall
|
||||||
redraw
|
redraw
|
||||||
}
|
}
|
||||||
|
|
@ -1153,8 +1092,8 @@ proc magic::gencell_create {gencell_type library parameters {orient 0}} {
|
||||||
set parameters [dict remove $parameters gencell]
|
set parameters [dict remove $parameters gencell]
|
||||||
}
|
}
|
||||||
|
|
||||||
set curunits [units]
|
set snaptype [snap list]
|
||||||
units internal
|
snap internal
|
||||||
set savebox [box values]
|
set savebox [box values]
|
||||||
|
|
||||||
catch {setpoint 0 0 $Opts(focus)}
|
catch {setpoint 0 0 $Opts(focus)}
|
||||||
|
|
@ -1184,7 +1123,7 @@ proc magic::gencell_create {gencell_type library parameters {orient 0}} {
|
||||||
identify $newinstname
|
identify $newinstname
|
||||||
set instname $newinstname
|
set instname $newinstname
|
||||||
}
|
}
|
||||||
units {*}$curunits
|
snap $snaptype
|
||||||
resumeall
|
resumeall
|
||||||
redraw
|
redraw
|
||||||
return $instname
|
return $instname
|
||||||
|
|
@ -1224,7 +1163,17 @@ proc magic::add_entry {pname ptext parameters} {
|
||||||
proc magic::add_check_callbacks {gencell_type library} {
|
proc magic::add_check_callbacks {gencell_type library} {
|
||||||
set wlist [winfo children .params.body.area.edits]
|
set wlist [winfo children .params.body.area.edits]
|
||||||
foreach w $wlist {
|
foreach w $wlist {
|
||||||
if {[regexp {\.params\.body\.area\.edits\.(.+)_.+} $w valid pname]} {
|
if {[regexp {\.params\.body\.area\.edits\.(.+)_ent} $w valid pname]} {
|
||||||
|
# Add callback on enter or focus out
|
||||||
|
bind $w <Return> \
|
||||||
|
"magic::update_dialog {} $pname $gencell_type $library"
|
||||||
|
bind $w <FocusOut> \
|
||||||
|
"magic::update_dialog {} $pname $gencell_type $library"
|
||||||
|
}
|
||||||
|
if {[regexp {\.params\.body\.area\.edits\.(.+)_sel} $w valid pname]} {
|
||||||
|
magic::add_dependency \{\} $gencell_type $library $pname
|
||||||
|
}
|
||||||
|
if {[regexp {\.params\.body\.area\.edits\.(.+)_chk} $w valid pname]} {
|
||||||
magic::add_dependency \{\} $gencell_type $library $pname
|
magic::add_dependency \{\} $gencell_type $library $pname
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1243,11 +1192,6 @@ proc magic::add_check_callbacks {gencell_type library} {
|
||||||
# dictionary.
|
# dictionary.
|
||||||
#
|
#
|
||||||
# Also handle dependencies on checkboxes and selection lists
|
# Also handle dependencies on checkboxes and selection lists
|
||||||
#
|
|
||||||
# If dependency callbacks exist, then chain them together.
|
|
||||||
# A final default dependency will be added to all entries
|
|
||||||
# to run the "check" procedure for the device. Dependencies
|
|
||||||
# that are more targeted get run first.
|
|
||||||
#----------------------------------------------------------
|
#----------------------------------------------------------
|
||||||
|
|
||||||
proc magic::add_dependency {callback gencell_type library args} {
|
proc magic::add_dependency {callback gencell_type library args} {
|
||||||
|
|
@ -1262,28 +1206,21 @@ proc magic::add_dependency {callback gencell_type library args} {
|
||||||
foreach pname $args {
|
foreach pname $args {
|
||||||
if {[lsearch $clist .params.body.area.edits.${pname}_ent] >= 0} {
|
if {[lsearch $clist .params.body.area.edits.${pname}_ent] >= 0} {
|
||||||
# Add callback on enter or focus out
|
# Add callback on enter or focus out
|
||||||
set oldbind [bind .params.body.area.edits.${pname}_ent <Return>]
|
bind .params.body.area.edits.${pname}_ent <Return> \
|
||||||
set newbind "magic::update_dialog $callback $pname $gencell_type $library"
|
"magic::update_dialog $callback $pname $gencell_type $library"
|
||||||
if {$oldbind != {}} {set newbind "$oldbind ; $newbind"}
|
bind .params.body.area.edits.${pname}_ent <FocusOut> \
|
||||||
bind .params.body.area.edits.${pname}_ent <Return> $newbind
|
"magic::update_dialog $callback $pname $gencell_type $library"
|
||||||
set oldbind [bind .params.body.area.edits.${pname}_ent <FocusOut>]
|
|
||||||
set newbind "magic::update_dialog $callback $pname $gencell_type $library"
|
|
||||||
if {$oldbind != {}} {set newbind "$oldbind ; $newbind"}
|
|
||||||
bind .params.body.area.edits.${pname}_ent <FocusOut> $newbind
|
|
||||||
} elseif {[lsearch $clist .params.body.area.edits.${pname}_chk] >= 0} {
|
} elseif {[lsearch $clist .params.body.area.edits.${pname}_chk] >= 0} {
|
||||||
# Add callback on checkbox change state
|
# Add callback on checkbox change state
|
||||||
set oldcmd [.params.body.area.edits.${pname}_chk cget -command]
|
.params.body.area.edits.${pname}_chk configure -command \
|
||||||
set newcmd "magic::update_dialog $callback $pname $gencell_type $library"
|
"magic::update_dialog $callback $pname $gencell_type $library"
|
||||||
if {$oldcmd != {}} {set newcmd "$oldcmd ; $newcmd"}
|
|
||||||
.params.body.area.edits.${pname}_chk configure -command $newcmd
|
|
||||||
} elseif {[lsearch $clist .params.body.area.edits.${pname}_sel] >= 0} {
|
} elseif {[lsearch $clist .params.body.area.edits.${pname}_sel] >= 0} {
|
||||||
set smenu .params.body.area.edits.${pname}_sel.menu
|
set smenu .params.body.area.edits.${pname}_sel.menu
|
||||||
set sitems [${smenu} index end]
|
set sitems [${smenu} index end]
|
||||||
for {set idx 0} {$idx <= $sitems} {incr idx} {
|
for {set idx 0} {$idx <= $sitems} {incr idx} {
|
||||||
set oldcmd [${smenu} entrycget $idx -command]
|
set curcommand [${smenu} entrycget $idx -command]
|
||||||
set newcmd "magic::update_dialog $callback $pname $gencell_type $library"
|
${smenu} entryconfigure $idx -command "$curcommand ; \
|
||||||
if {$oldcmd != {}} {set newcmd "$oldcmd ; $newcmd"}
|
magic::update_dialog $callback $pname $gencell_type $library"
|
||||||
${smenu} entryconfigure $idx -command $newcmd
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,11 +138,7 @@ proc magic::pushstack {{name ""}} {
|
||||||
if {[catch {lindex $editstack end}]} {
|
if {[catch {lindex $editstack end}]} {
|
||||||
set editstack {}
|
set editstack {}
|
||||||
}
|
}
|
||||||
# Protect against changing units by always using internal units
|
|
||||||
set curunits [units]
|
|
||||||
units internal
|
|
||||||
lappend editstack [view get]
|
lappend editstack [view get]
|
||||||
units {*}$curunits
|
|
||||||
lappend editstack [cellname list window]
|
lappend editstack [cellname list window]
|
||||||
set ltag [tag load]
|
set ltag [tag load]
|
||||||
tag load {}
|
tag load {}
|
||||||
|
|
@ -162,11 +158,10 @@ proc magic::popstack {} {
|
||||||
tag load {}
|
tag load {}
|
||||||
suspendall
|
suspendall
|
||||||
load [lindex $editstack end]
|
load [lindex $editstack end]
|
||||||
# Protect against changing units by always using internal units
|
set snaptype [snap]
|
||||||
set curunits [units]
|
snap internal
|
||||||
units internal
|
|
||||||
view [lindex $editstack end-1]
|
view [lindex $editstack end-1]
|
||||||
units {*}$curunits
|
snap $snaptype
|
||||||
catch {magic::cellmanager}
|
catch {magic::cellmanager}
|
||||||
catch {magic::captions}
|
catch {magic::captions}
|
||||||
resumeall
|
resumeall
|
||||||
|
|
@ -191,8 +186,8 @@ proc magic::clearstack {} {
|
||||||
|
|
||||||
proc magic::pushbox {{values {}}} {
|
proc magic::pushbox {{values {}}} {
|
||||||
global boxstack
|
global boxstack
|
||||||
set curunits [units]
|
set snaptype [snap list]
|
||||||
units internal
|
snap internal
|
||||||
if {[catch {set boxstack}]} {
|
if {[catch {set boxstack}]} {
|
||||||
set boxstack {}
|
set boxstack {}
|
||||||
}
|
}
|
||||||
|
|
@ -201,7 +196,7 @@ proc magic::pushbox {{values {}}} {
|
||||||
} else {
|
} else {
|
||||||
lappend boxstack $values
|
lappend boxstack $values
|
||||||
}
|
}
|
||||||
units {*}$curunits
|
snap $snaptype
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -215,8 +210,8 @@ proc magic::pushbox {{values {}}} {
|
||||||
|
|
||||||
proc magic::popbox {{type values}} {
|
proc magic::popbox {{type values}} {
|
||||||
global boxstack
|
global boxstack
|
||||||
set curunits [units]
|
set snaptype [snap list]
|
||||||
units internal
|
snap internal
|
||||||
if {[catch {set boxstack}]} {
|
if {[catch {set boxstack}]} {
|
||||||
error "No stack"
|
error "No stack"
|
||||||
} elseif {$boxstack == {}} {
|
} elseif {$boxstack == {}} {
|
||||||
|
|
@ -236,7 +231,7 @@ proc magic::popbox {{type values}} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set boxstack [lrange $boxstack 0 end-1]
|
set boxstack [lrange $boxstack 0 end-1]
|
||||||
units {*}$curunits
|
snap $snaptype
|
||||||
return $b
|
return $b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -360,8 +355,8 @@ proc magic::ruler {{text {}} {orient auto}} {
|
||||||
set mmx [expr {($llx + $urx) / 2}]
|
set mmx [expr {($llx + $urx) / 2}]
|
||||||
set mmy [expr {($lly + $ury) / 2}]
|
set mmy [expr {($lly + $ury) / 2}]
|
||||||
|
|
||||||
set curunits [units]
|
set snapsave [snap]
|
||||||
units internal
|
snap internal
|
||||||
|
|
||||||
if {$orient == "horizontal"} {
|
if {$orient == "horizontal"} {
|
||||||
element add line l1_$Opts(rulers) black $llx $lly $llx $ury
|
element add line l1_$Opts(rulers) black $llx $lly $llx $ury
|
||||||
|
|
@ -415,7 +410,7 @@ proc magic::ruler {{text {}} {orient auto}} {
|
||||||
element configure l3_$Opts(rulers) flags arrowbottom
|
element configure l3_$Opts(rulers) flags arrowbottom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
units {*}$curunits
|
snap $snapsave
|
||||||
}
|
}
|
||||||
|
|
||||||
#---------------------------------------------------------------------
|
#---------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -684,10 +684,7 @@ proc magic::cursorview {win} {
|
||||||
*bypass crosshair ${olstx}um ${olsty}um
|
*bypass crosshair ${olstx}um ${olsty}um
|
||||||
}
|
}
|
||||||
|
|
||||||
# I do not know why the T/F result gets lost or overridden sometimes
|
if {[${win} box exists]} {
|
||||||
set gotbox [${win} box exists]
|
|
||||||
if {$gotbox == {}} {set gotbox false}
|
|
||||||
if {$gotbox} {
|
|
||||||
set curunits [${win} units list]
|
set curunits [${win} units list]
|
||||||
${win} units microns noprint
|
${win} units microns noprint
|
||||||
set dlst [${win} box position]
|
set dlst [${win} box position]
|
||||||
|
|
@ -828,9 +825,9 @@ proc magic::setscrollvalues {win} {
|
||||||
global Opts
|
global Opts
|
||||||
|
|
||||||
*bypass logcommands suspend
|
*bypass logcommands suspend
|
||||||
|
set svalues [${win} view get]
|
||||||
set curunits [units list]
|
set curunits [units list]
|
||||||
units internal noprint
|
units internal noprint
|
||||||
set svalues [${win} view get]
|
|
||||||
set bvalues [${win} view bbox]
|
set bvalues [${win} view bbox]
|
||||||
units {*}$curunits
|
units {*}$curunits
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,6 @@
|
||||||
#ifndef _MAGIC__TEXTIO__TEXTIO_H
|
#ifndef _MAGIC__TEXTIO__TEXTIO_H
|
||||||
#define _MAGIC__TEXTIO__TEXTIO_H
|
#define _MAGIC__TEXTIO__TEXTIO_H
|
||||||
|
|
||||||
#include <stdarg.h> /* va_list */
|
|
||||||
|
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "utils/dqueue.h" /* DQueue */
|
#include "utils/dqueue.h" /* DQueue */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,20 @@ typedef struct {
|
||||||
#define TX_PROMPT '>'
|
#define TX_PROMPT '>'
|
||||||
#define TX_CMD_PROMPT ":"
|
#define TX_CMD_PROMPT ":"
|
||||||
|
|
||||||
|
/* all of the state associated with a tty terminal */
|
||||||
|
#if !defined(SYSV) && !defined(CYGWIN) && !defined(__OpenBSD__) && !defined(EMSCRIPTEN)
|
||||||
|
#if defined(HAVE_SYS_IOCTL_COMPAT_H) || defined(HAVE_SGTTY_H)
|
||||||
|
#if defined(HAVE_SYS_IOCTL_COMPAT_H)
|
||||||
|
#include <sys/ioctl_compat.h> /* replaced sgtty.h */
|
||||||
|
#elif defined(HAVE_SGTTY_H)
|
||||||
|
#include <sgtty.h>/* legacy - struct sgttyb{} defn */
|
||||||
|
#endif
|
||||||
|
typedef struct {
|
||||||
|
struct sgttyb tx_i_sgtty;
|
||||||
|
struct tchars tx_i_tchars;
|
||||||
|
} txTermState;
|
||||||
|
#endif /* HAVE_SYS_IOCTL_COMPAT_H || HAVE_SGTTY_H */
|
||||||
|
#endif /* SYSV */
|
||||||
|
|
||||||
extern bool TxGetInputEvent(bool block, bool returnOnSigWinch);
|
extern bool TxGetInputEvent(bool block, bool returnOnSigWinch);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/t
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "tcltk/tclmagic.h"
|
#include "tcltk/tclmagic.h"
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
|
|
|
||||||
125
textio/txInput.c
125
textio/txInput.c
|
|
@ -32,13 +32,14 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "utils/main.h"
|
#include "utils/main.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "textio/txcommands.h"
|
#include "textio/txcommands.h"
|
||||||
#include "textio/textioInt.h"
|
#include "textio/textioInt.h"
|
||||||
#include "utils/magsgtty.h" /* txTermState */
|
|
||||||
#include "utils/dqueue.h"
|
#include "utils/dqueue.h"
|
||||||
#include "utils/macros.h"
|
#include "utils/macros.h"
|
||||||
#include "utils/hash.h"
|
#include "utils/hash.h"
|
||||||
|
|
@ -1224,21 +1225,36 @@ TxGetLine(
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(SYSV) || defined(CYGWIN)
|
||||||
|
|
||||||
|
void
|
||||||
|
txGetTermState(
|
||||||
|
struct termio *buf)
|
||||||
|
{
|
||||||
|
ioctl( fileno( stdin ), TCGETA, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
|
||||||
|
|
||||||
|
void
|
||||||
|
txGetTermState(
|
||||||
|
struct termios *buf)
|
||||||
|
{
|
||||||
|
(void) tcgetattr(fileno(stdin), buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
void
|
void
|
||||||
txGetTermState(
|
txGetTermState(
|
||||||
txTermState *buf)
|
txTermState *buf)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_TERMIOS_H)
|
|
||||||
(void) tcgetattr(fileno(stdin), &buf->termios);
|
|
||||||
#elif defined(HAVE_TERMIO_H)
|
|
||||||
ioctl(fileno(stdin), TCGETA, &buf->termio);
|
|
||||||
#else /* sgtty */
|
|
||||||
ASSERT(TxStdinIsatty, "txGetTermState");
|
ASSERT(TxStdinIsatty, "txGetTermState");
|
||||||
/* save the current terminal characteristics */
|
/* save the current terminal characteristics */
|
||||||
(void) ioctl(fileno(stdin), TIOCGETP, (char *) &buf->tx_i_sgtty);
|
(void) ioctl(fileno(stdin), TIOCGETP, (char *) &(buf->tx_i_sgtty) );
|
||||||
(void) ioctl(fileno(stdin), TIOCGETC, (char *) &buf->tx_i_tchars);
|
(void) ioctl(fileno(stdin), TIOCGETC, (char *) &(buf->tx_i_tchars) );
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif /* SYSV */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1257,17 +1273,24 @@ txGetTermState(
|
||||||
|
|
||||||
void
|
void
|
||||||
txSetTermState(
|
txSetTermState(
|
||||||
txTermState *buf)
|
#if defined(SYSV) || defined(CYGWIN)
|
||||||
|
struct termio *buf
|
||||||
|
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
|
||||||
|
struct termios *buf
|
||||||
|
#else
|
||||||
|
txTermState *buf
|
||||||
|
#endif /* SYSV */
|
||||||
|
)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_TERMIOS_H)
|
#if defined(SYSV) || defined(CYGWIN)
|
||||||
(void) tcsetattr(fileno(stdin), TCSANOW, &buf->termios);
|
ioctl( fileno(stdin), TCSETAF, buf );
|
||||||
#elif defined(HAVE_TERMIO_H)
|
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
|
||||||
ioctl(fileno(stdin), TCSETAF, &buf->termio);
|
(void) tcsetattr( fileno(stdin), TCSANOW, buf );
|
||||||
#else /* sgtty */
|
#else
|
||||||
/* set the current terminal characteristics */
|
/* set the current terminal characteristics */
|
||||||
(void) ioctl(fileno(stdin), TIOCSETN, (char *) &buf->tx_i_sgtty);
|
(void) ioctl(fileno(stdin), TIOCSETN, (char *) &(buf->tx_i_sgtty) );
|
||||||
(void) ioctl(fileno(stdin), TIOCSETC, (char *) &buf->tx_i_tchars);
|
(void) ioctl(fileno(stdin), TIOCSETC, (char *) &(buf->tx_i_tchars) );
|
||||||
#endif
|
#endif /* SYSV */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1290,27 +1313,37 @@ txSetTermState(
|
||||||
|
|
||||||
void
|
void
|
||||||
txInitTermRec(
|
txInitTermRec(
|
||||||
txTermState *buf)
|
#if defined(SYSV) || defined(CYGWIN)
|
||||||
|
struct termio *buf
|
||||||
|
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
|
||||||
|
struct termios *buf
|
||||||
|
#else
|
||||||
|
txTermState *buf
|
||||||
|
#endif /* SYSV */
|
||||||
|
)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_TERMIOS_H)
|
#if defined(SYSV) || defined(CYGWIN) || defined(__OpenBSD__) || defined(EMSCRIPTEN)
|
||||||
buf->termios.c_lflag = ISIG; /* raw: no echo and no processing, allow signals */
|
buf->c_lflag = ISIG; /* raw: no echo and no processing, allow signals */
|
||||||
buf->termios.c_cc[ VMIN ] = 1;
|
buf->c_cc[ VMIN ] = 1;
|
||||||
buf->termios.c_cc[ VTIME ] = 0;
|
buf->c_cc[ VTIME ] = 0;
|
||||||
#elif defined(HAVE_TERMIO_H)
|
#else
|
||||||
buf->termio.c_lflag = ISIG; /* raw: no echo and no processing, allow signals */
|
|
||||||
buf->termio.c_cc[ VMIN ] = 1;
|
|
||||||
buf->termio.c_cc[ VTIME ] = 0;
|
|
||||||
#else /* sgtty */
|
|
||||||
/* set things up for us, turn off echo, turn on cbreak, no EOF */
|
/* set things up for us, turn off echo, turn on cbreak, no EOF */
|
||||||
buf->tx_i_sgtty.sg_flags |= CBREAK;
|
buf->tx_i_sgtty.sg_flags |= CBREAK;
|
||||||
buf->tx_i_sgtty.sg_flags &= ~ECHO;
|
buf->tx_i_sgtty.sg_flags &= ~ECHO;
|
||||||
buf->tx_i_tchars.t_eofc = -1;
|
buf->tx_i_tchars.t_eofc = -1;
|
||||||
#endif
|
|
||||||
|
#endif /* SYSV */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(SYSV) || defined(CYGWIN)
|
||||||
|
struct termio closeTermState;
|
||||||
|
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
|
||||||
|
struct termios closeTermState;
|
||||||
|
#else
|
||||||
static txTermState closeTermState;
|
static txTermState closeTermState;
|
||||||
|
#endif /* SYSV */
|
||||||
|
|
||||||
static bool haveCloseState = FALSE;
|
static bool haveCloseState = FALSE;
|
||||||
|
|
||||||
|
|
@ -1333,21 +1366,21 @@ static bool haveCloseState = FALSE;
|
||||||
void
|
void
|
||||||
txSaveTerm(void)
|
txSaveTerm(void)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_TERMIOS_H)
|
#if defined(SYSV) || defined(CYGWIN)
|
||||||
(void) tcgetattr(fileno(stdin), &closeTermState.termios);
|
ioctl( fileno( stdin ), TCGETA, &closeTermState);
|
||||||
txEraseChar = closeTermState.termios.c_cc[VERASE];
|
txEraseChar = closeTermState.c_cc[VERASE];
|
||||||
txKillChar = closeTermState.termios.c_cc[VKILL];
|
txKillChar = closeTermState.c_cc[VKILL];
|
||||||
TxEOFChar = closeTermState.termios.c_cc[VEOF];
|
TxEOFChar = closeTermState.c_cc[VEOF];
|
||||||
TxInterruptChar = closeTermState.termios.c_cc[VINTR];
|
TxInterruptChar = closeTermState.c_cc[VINTR];
|
||||||
haveCloseState = TRUE;
|
haveCloseState = TRUE;
|
||||||
#elif defined(HAVE_TERMIO_H)
|
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
|
||||||
ioctl(fileno(stdin), TCGETA, &closeTermState.termio);
|
(void) tcgetattr( fileno( stdin ), &closeTermState);
|
||||||
txEraseChar = closeTermState.termio.c_cc[VERASE];
|
txEraseChar = closeTermState.c_cc[VERASE];
|
||||||
txKillChar = closeTermState.termio.c_cc[VKILL];
|
txKillChar = closeTermState.c_cc[VKILL];
|
||||||
TxEOFChar = closeTermState.termio.c_cc[VEOF];
|
TxEOFChar = closeTermState.c_cc[VEOF];
|
||||||
TxInterruptChar = closeTermState.termio.c_cc[VINTR];
|
TxInterruptChar = closeTermState.c_cc[VINTR];
|
||||||
haveCloseState = TRUE;
|
haveCloseState = TRUE;
|
||||||
#else /* sgtty */
|
#else
|
||||||
struct ltchars lt;
|
struct ltchars lt;
|
||||||
txGetTermState(&closeTermState);
|
txGetTermState(&closeTermState);
|
||||||
(void) ioctl(fileno(stdin), TIOCGLTC, (char *) <);
|
(void) ioctl(fileno(stdin), TIOCGLTC, (char *) <);
|
||||||
|
|
@ -1360,7 +1393,7 @@ txSaveTerm(void)
|
||||||
TxEOFChar = closeTermState.tx_i_tchars.t_eofc;
|
TxEOFChar = closeTermState.tx_i_tchars.t_eofc;
|
||||||
TxInterruptChar = closeTermState.tx_i_tchars.t_intrc;
|
TxInterruptChar = closeTermState.tx_i_tchars.t_intrc;
|
||||||
haveCloseState = TRUE;
|
haveCloseState = TRUE;
|
||||||
#endif
|
#endif /* SYSV */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1381,7 +1414,13 @@ txSaveTerm(void)
|
||||||
void
|
void
|
||||||
TxSetTerminal(void)
|
TxSetTerminal(void)
|
||||||
{
|
{
|
||||||
|
#if defined(SYSV) || defined(CYGWIN)
|
||||||
|
struct termio buf;
|
||||||
|
#elif defined (__OpenBSD__) || defined(EMSCRIPTEN)
|
||||||
|
struct termios buf;
|
||||||
|
#else
|
||||||
txTermState buf;
|
txTermState buf;
|
||||||
|
#endif /* SYSV */
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
/* If using Tk console, don't mess with the terminal settings; */
|
/* If using Tk console, don't mess with the terminal settings; */
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
|
|
|
||||||
|
|
@ -21,54 +21,44 @@
|
||||||
#ifndef _MAGIC__UTILS__MAGSGTTY_H
|
#ifndef _MAGIC__UTILS__MAGSGTTY_H
|
||||||
#define _MAGIC__UTILS__MAGSGTTY_H
|
#define _MAGIC__UTILS__MAGSGTTY_H
|
||||||
|
|
||||||
|
/* maybe this can be #ifndef HAVE_TERMIO_H */
|
||||||
|
#if !defined(SYSV) && !defined(CYGWIN)
|
||||||
|
|
||||||
#if defined(HAVE_TERMIOS_H)
|
# ifdef ALPHA
|
||||||
/* In modern times everything has POSIX */
|
# undef MAX
|
||||||
#include <termios.h>
|
# undef MIN
|
||||||
|
# endif
|
||||||
|
|
||||||
|
/* unclear what platform requires this OpenBSD/FreeBSD ? */
|
||||||
|
# ifndef COMPAT_43TTY
|
||||||
|
# define COMPAT_43TTY
|
||||||
|
# endif
|
||||||
|
|
||||||
#ifdef HAVE_SYS_IOCTL_H
|
#ifdef HAVE_SYS_IOCTL_H
|
||||||
/* Linux glibx 2.x - present
|
|
||||||
* FreeBSD 14.3-RELEASE - present
|
|
||||||
* Solaris 11.4 - present
|
|
||||||
*/
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif defined(HAVE_TERMIO_H)
|
#if defined(HAVE_TERMIOS_H)
|
||||||
/* Linux glibx 2.x - present (just includes termios.h & sys/ioctl.h)
|
#include <termios.h>
|
||||||
* Linux glibc 2.45+ - not present
|
#elif defined(HAVE_SYS_IOCTL_COMPAT_H)
|
||||||
* FreeBSD 14.3-RELEASE - not present
|
/* unclear which platform(s) require <sys/ioctl_compat.h> and the structure
|
||||||
* Solaris 11.4 - present
|
* of this file is such that it will try to include it by default, better
|
||||||
*/
|
* to invert the #if and only select this on the known platforms that need
|
||||||
#include <termio.h>
|
* it so that <termios.h> goes by default, which exists on MacOSX, Linux, etc..
|
||||||
#else /* sgtty */
|
* many possible solutions to make this work by default:
|
||||||
#if defined(HAVE_SYS_IOCTL_COMPAT_H)
|
* HAVE_SYS_IOCTL_COMPAT_H ? HAVE_TERMIOS_H ? !defined(linux) at top (MaxOSX is BSD type)
|
||||||
/* Linux glibc2.x - not present
|
|
||||||
* FreeBSD 14.3-RELEASE - not present
|
|
||||||
* Solaris 11.4 - not present
|
|
||||||
*/
|
*/
|
||||||
#include <sys/ioctl_compat.h> /* replaced sgtty.h */
|
#include <sys/ioctl_compat.h> /* replaced sgtty.h */
|
||||||
#elif defined(HAVE_SGTTY_H)
|
#elif defined(HAVE_SGTTY_H)
|
||||||
/* Linux glibc2.x - present (includes sys/ioctl.h)
|
|
||||||
* FreeBSD 14.3-RELEASE - not present
|
|
||||||
* Solaris 11.4 - present
|
|
||||||
*/
|
|
||||||
#include <sgtty.h> /* legacy - struct sgttyb{} defn */
|
#include <sgtty.h> /* legacy - struct sgttyb{} defn */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if defined(HAVE_TERMIO_H)
|
||||||
|
#include <termio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif /* !SYSV && !CYGWIN */
|
||||||
/* all of the state associated with a tty terminal */
|
|
||||||
typedef struct {
|
|
||||||
#if defined(HAVE_TERMIOS_H)
|
|
||||||
struct termios termios;
|
|
||||||
#elif defined(HAVE_TERMIO_H)
|
|
||||||
struct termio termio;
|
|
||||||
#else /* sgtty */
|
|
||||||
struct sgttyb tx_i_sgtty;
|
|
||||||
struct tchars tx_i_tchars;
|
|
||||||
#endif
|
|
||||||
} txTermState;
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _MAGIC__UTILS__MAGSGTTY_H */
|
#endif /* _MAGIC__UTILS__MAGSGTTY_H */
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "utils/main.h"
|
#include "utils/main.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "utils/malloc.h"
|
#include "utils/malloc.h"
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "utils/hash.h"
|
#include "utils/hash.h"
|
||||||
#include "utils/macros.h"
|
#include "utils/macros.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "tcltk/tclmagic.h"
|
#include "tcltk/tclmagic.h"
|
||||||
#include "utils/main.h"
|
#include "utils/main.h"
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
|
#include "utils/magsgtty.h"
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
#include "utils/signals.h"
|
#include "utils/signals.h"
|
||||||
|
|
|
||||||
30
utils/tech.c
30
utils/tech.c
|
|
@ -432,8 +432,7 @@ TechLoad(filename, initmask)
|
||||||
char suffix[20], line[MAXLINESIZE], *realname;
|
char suffix[20], line[MAXLINESIZE], *realname;
|
||||||
char *argv[MAXARGS];
|
char *argv[MAXARGS];
|
||||||
SectionID mask, badMask;
|
SectionID mask, badMask;
|
||||||
int argc, s, repeatcount = 0;
|
int argc, s;
|
||||||
off_t repeatpos;
|
|
||||||
bool retval, skip;
|
bool retval, skip;
|
||||||
filestack *fstack, *newstack;
|
filestack *fstack, *newstack;
|
||||||
filestack topfile;
|
filestack topfile;
|
||||||
|
|
@ -604,33 +603,6 @@ TechLoad(filename, initmask)
|
||||||
skip = FALSE;
|
skip = FALSE;
|
||||||
while ((argc = techGetTokens(line, sizeof line, &fstack, argv)) >= 0)
|
while ((argc = techGetTokens(line, sizeof line, &fstack, argv)) >= 0)
|
||||||
{
|
{
|
||||||
/* Check for end-of-loop */
|
|
||||||
if ((argc == 1) && (!strcmp(argv[0], "endrepeat")))
|
|
||||||
{
|
|
||||||
if (repeatcount > 0)
|
|
||||||
{
|
|
||||||
repeatcount--;
|
|
||||||
fseek(fstack->file, repeatpos, SEEK_SET);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* "repeat <number>" reads the lines until "endrepeat" <number> times */
|
|
||||||
else if ((argc == 2) && (!strcmp(argv[0], "repeat")))
|
|
||||||
{
|
|
||||||
|
|
||||||
if (!StrIsInt(argv[1]))
|
|
||||||
{
|
|
||||||
TechError("Error: \"repeat\" with invalid count %s\n", argv[1]);
|
|
||||||
repeatcount = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
repeatcount = atoi(argv[1]) - 1;
|
|
||||||
repeatpos = ftell(fstack->file);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check for file inclusions (can be nested) */
|
/* Check for file inclusions (can be nested) */
|
||||||
if ((argc > 1) && (!strcmp(argv[0], "include")))
|
if ((argc > 1) && (!strcmp(argv[0], "include")))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -820,27 +820,22 @@ windViewCmd(w, cmd)
|
||||||
|
|
||||||
if (!strncmp(cmd->tx_argv[1], "get", 3))
|
if (!strncmp(cmd->tx_argv[1], "get", 3))
|
||||||
{
|
{
|
||||||
char *vllx, *vlly, *vurx, *vury;
|
|
||||||
|
|
||||||
vllx = DBWPrintValue(w->w_surfaceArea.r_xbot, w, TRUE);
|
|
||||||
vlly = DBWPrintValue(w->w_surfaceArea.r_ybot, w, FALSE);
|
|
||||||
vurx = DBWPrintValue(w->w_surfaceArea.r_xtop, w, TRUE);
|
|
||||||
vury = DBWPrintValue(w->w_surfaceArea.r_ytop, w, FALSE);
|
|
||||||
|
|
||||||
/* NOTE: The surface area is in screen (pixel) coordinates
|
/* NOTE: The surface area is in screen (pixel) coordinates
|
||||||
* and so does not follow the "units" display type.
|
* and so does not follow the "units" display type.
|
||||||
*/
|
*/
|
||||||
#ifndef MAGIC_WRAPPER
|
#ifndef MAGIC_WRAPPER
|
||||||
TxPrintf("(%s, %s) to (%s, %s)\n", vllx, vlly, vurx, vury);
|
TxPrintf("(%d, %d) to (%d, %d)\n",
|
||||||
|
w->w_surfaceArea.r_xbot, w->w_surfaceArea.r_ybot,
|
||||||
|
w->w_surfaceArea.r_xtop, w->w_surfaceArea.r_ytop);
|
||||||
#else
|
#else
|
||||||
Tcl_ListObjAppendElement(magicinterp, listxy,
|
Tcl_ListObjAppendElement(magicinterp, listxy,
|
||||||
Tcl_NewStringObj(vllx, -1));
|
Tcl_NewIntObj((int)w->w_surfaceArea.r_xbot));
|
||||||
Tcl_ListObjAppendElement(magicinterp, listxy,
|
Tcl_ListObjAppendElement(magicinterp, listxy,
|
||||||
Tcl_NewStringObj(vlly, -1));
|
Tcl_NewIntObj((int)w->w_surfaceArea.r_ybot));
|
||||||
Tcl_ListObjAppendElement(magicinterp, listxy,
|
Tcl_ListObjAppendElement(magicinterp, listxy,
|
||||||
Tcl_NewStringObj(vurx, -1));
|
Tcl_NewIntObj((int)w->w_surfaceArea.r_xtop));
|
||||||
Tcl_ListObjAppendElement(magicinterp, listxy,
|
Tcl_ListObjAppendElement(magicinterp, listxy,
|
||||||
Tcl_NewStringObj(vury, -1));
|
Tcl_NewIntObj((int)w->w_surfaceArea.r_ytop));
|
||||||
Tcl_SetObjResult(magicinterp, listxy);
|
Tcl_SetObjResult(magicinterp, listxy);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue