Merge branch 'RTimothyEdwards:master' into spice_hier
This commit is contained in:
commit
f6b4671d96
|
|
@ -882,7 +882,8 @@ calmaElementSref(filename)
|
||||||
if (rtype == CALMA_PROPATTR)
|
if (rtype == CALMA_PROPATTR)
|
||||||
{
|
{
|
||||||
READI2(propAttrType);
|
READI2(propAttrType);
|
||||||
if (propAttrType == CALMA_PROP_USENAME)
|
if (propAttrType == CALMA_PROP_USENAME ||
|
||||||
|
propAttrType == CALMA_PROP_USENAME_STD)
|
||||||
{
|
{
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
|
|
@ -1262,7 +1263,19 @@ calmaFindCell(name, was_called, predefined)
|
||||||
if (was_called) *was_called = FALSE;
|
if (was_called) *was_called = FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (was_called) *was_called = TRUE;
|
{
|
||||||
|
if (was_called)
|
||||||
|
{
|
||||||
|
if (*was_called == TRUE)
|
||||||
|
{
|
||||||
|
def = DBCellLookDef(name);
|
||||||
|
if ((def != NULL) && (def->cd_flags & CDAVAILABLE))
|
||||||
|
if (CalmaNoDuplicates)
|
||||||
|
if (predefined) *predefined = TRUE;
|
||||||
|
}
|
||||||
|
*was_called = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
return (CellDef *) HashGetValue(h);
|
return (CellDef *) HashGetValue(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
#include "calma/calmaInt.h"
|
#include "calma/calmaInt.h"
|
||||||
#include "commands/commands.h" /* for CmdGetRootPoint */
|
#include "commands/commands.h" /* for CmdGetRootPoint */
|
||||||
|
#include "utils/main.h" /* for EditCellUse */
|
||||||
#include "utils/undo.h"
|
#include "utils/undo.h"
|
||||||
|
|
||||||
/* Globals for Calma reading */
|
/* Globals for Calma reading */
|
||||||
|
|
@ -164,6 +165,12 @@ CalmaReadFile(file, filename)
|
||||||
static int skipBeforeLib[] = { CALMA_LIBDIRSIZE, CALMA_SRFNAME,
|
static int skipBeforeLib[] = { CALMA_LIBDIRSIZE, CALMA_SRFNAME,
|
||||||
CALMA_LIBSECUR, -1 };
|
CALMA_LIBSECUR, -1 };
|
||||||
|
|
||||||
|
if (EditCellUse == (CellUse *)NULL)
|
||||||
|
{
|
||||||
|
TxError("Cannot read GDS: There is no edit cell.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* We will use full cell names as keys in this hash table */
|
/* We will use full cell names as keys in this hash table */
|
||||||
CIFReadCellInit(0);
|
CIFReadCellInit(0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/c
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <arpa/inet.h> /* for htons() */
|
||||||
#ifdef SYSV
|
#ifdef SYSV
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#else
|
#else
|
||||||
|
|
@ -146,6 +147,7 @@ int calmaPaintLayerType;
|
||||||
*/
|
*/
|
||||||
HashTable calmaLibHash;
|
HashTable calmaLibHash;
|
||||||
HashTable calmaPrefixHash;
|
HashTable calmaPrefixHash;
|
||||||
|
HashTable calmaUndefHash;
|
||||||
|
|
||||||
/* Imports */
|
/* Imports */
|
||||||
extern time_t time();
|
extern time_t time();
|
||||||
|
|
@ -285,6 +287,8 @@ CalmaWrite(rootDef, f)
|
||||||
int oldCount = DBWFeedbackCount, problems;
|
int oldCount = DBWFeedbackCount, problems;
|
||||||
bool good;
|
bool good;
|
||||||
CellUse dummy;
|
CellUse dummy;
|
||||||
|
HashEntry *he;
|
||||||
|
HashSearch hs;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do not attempt to write anything if a CIF/GDS output style
|
* Do not attempt to write anything if a CIF/GDS output style
|
||||||
|
|
@ -298,6 +302,7 @@ CalmaWrite(rootDef, f)
|
||||||
|
|
||||||
HashInit(&calmaLibHash, 32, 0);
|
HashInit(&calmaLibHash, 32, 0);
|
||||||
HashInit(&calmaPrefixHash, 32, 0);
|
HashInit(&calmaPrefixHash, 32, 0);
|
||||||
|
HashInit(&calmaUndefHash, 32, 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make sure that the entire hierarchy rooted at rootDef is
|
* Make sure that the entire hierarchy rooted at rootDef is
|
||||||
|
|
@ -337,7 +342,31 @@ CalmaWrite(rootDef, f)
|
||||||
* to insure that each child cell is output before it is used. The
|
* to insure that each child cell is output before it is used. The
|
||||||
* root cell is output last.
|
* root cell is output last.
|
||||||
*/
|
*/
|
||||||
(void) calmaProcessDef(rootDef, f, CalmaDoLibrary);
|
calmaProcessDef(rootDef, f, CalmaDoLibrary);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for any cells that were instanced in the output definition
|
||||||
|
* (by dumping a GDS file from a read-only view) but were never
|
||||||
|
* defined (because the dumped GDS contained undefined references).
|
||||||
|
* If these are in the database but were not part of the tree of
|
||||||
|
* rootDef, then output them at the end.
|
||||||
|
*/
|
||||||
|
HashStartSearch(&hs);
|
||||||
|
while ((he = HashNext(&calmaUndefHash, &hs)) != NULL)
|
||||||
|
{
|
||||||
|
char *refname = (char *)HashGetValue(he);
|
||||||
|
if (refname && (refname[0] == '0'))
|
||||||
|
{
|
||||||
|
CellDef *extraDef;
|
||||||
|
|
||||||
|
extraDef = DBCellLookDef((char *)he->h_key.h_name);
|
||||||
|
if (extraDef != NULL)
|
||||||
|
calmaProcessDef(extraDef, f, FALSE);
|
||||||
|
else
|
||||||
|
TxError("Error: Cell %s is not defined in the output file!\n",
|
||||||
|
refname + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Finish up by outputting the end-of-library marker */
|
/* Finish up by outputting the end-of-library marker */
|
||||||
calmaOutRH(4, CALMA_ENDLIB, CALMA_NODATA, f);
|
calmaOutRH(4, CALMA_ENDLIB, CALMA_NODATA, f);
|
||||||
|
|
@ -355,6 +384,7 @@ CalmaWrite(rootDef, f)
|
||||||
|
|
||||||
HashFreeKill(&calmaLibHash);
|
HashFreeKill(&calmaLibHash);
|
||||||
HashKill(&calmaPrefixHash);
|
HashKill(&calmaPrefixHash);
|
||||||
|
HashFreeKill(&calmaUndefHash);
|
||||||
return (good);
|
return (good);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -409,14 +439,47 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
|
||||||
calmaOutDate(def->cd_timestamp, outf);
|
calmaOutDate(def->cd_timestamp, outf);
|
||||||
calmaOutDate(time((time_t *) 0), outf);
|
calmaOutDate(time((time_t *) 0), outf);
|
||||||
|
|
||||||
/* Find the structure's unique prefix, in case structure calls subcells */
|
/* Do a quick check of the calmaUndefHash table to see if this cell */
|
||||||
/* that are not yet defined. */
|
/* was previously used in a GDS file that does not define it (a GDS */
|
||||||
|
/* addendum library). */
|
||||||
|
|
||||||
he2 = HashFind(&calmaLibHash, filename);
|
he = HashLookOnly(&calmaUndefHash, strname);
|
||||||
if (he2 == NULL)
|
if (he != NULL)
|
||||||
TxError("Fatal error: Library %s not recorded!\n", filename);
|
{
|
||||||
|
HashSearch hs;
|
||||||
|
char *undefname = (char *)HashGetValue(he);
|
||||||
|
|
||||||
|
HashStartSearch(&hs);
|
||||||
|
while ((he2 = HashNext(&calmaLibHash, &hs)) != NULL)
|
||||||
|
{
|
||||||
|
prefix = (char *)HashGetValue(he2);
|
||||||
|
if (!strncmp(prefix, undefname + 1, strlen(prefix)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (he2 == NULL)
|
||||||
|
{
|
||||||
|
prefix = (char *)NULL;
|
||||||
|
TxError("Error: Unreferenced cell %s prefix is unrecorded!\n",
|
||||||
|
undefname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Remove this entry from the hash table */
|
||||||
|
freeMagic(undefname);
|
||||||
|
HashRemove(&calmaUndefHash, strname);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
prefix = (char *)HashGetValue(he2);
|
{
|
||||||
|
/* Find the structure's unique prefix, in case structure calls */
|
||||||
|
/* subcells that are not yet defined. */
|
||||||
|
|
||||||
|
he2 = HashFind(&calmaLibHash, filename);
|
||||||
|
if (he2 == NULL)
|
||||||
|
TxError("Fatal error: Library %s not recorded!\n", filename);
|
||||||
|
else
|
||||||
|
prefix = (char *)HashGetValue(he2);
|
||||||
|
}
|
||||||
|
|
||||||
/* Prefix structure name with def name, and output new structure name */
|
/* Prefix structure name with def name, and output new structure name */
|
||||||
he = HashFind(calmaDefHash, strname);
|
he = HashFind(calmaDefHash, strname);
|
||||||
|
|
@ -456,16 +519,20 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
|
||||||
if (edef != NULL)
|
if (edef != NULL)
|
||||||
{
|
{
|
||||||
bool isAbstract, isReadOnly;
|
bool isAbstract, isReadOnly;
|
||||||
char *chklibname, *dotptr;
|
char *chklibname, *filenamesubbed = NULL;
|
||||||
|
|
||||||
/* Is view abstract? */
|
/* Is view abstract? */
|
||||||
DBPropGet(edef, "LEFview", &isAbstract);
|
DBPropGet(edef, "LEFview", &isAbstract);
|
||||||
chklibname = (char *)DBPropGet(edef, "GDS_FILE", &isReadOnly);
|
chklibname = (char *)DBPropGet(edef, "GDS_FILE", &isReadOnly);
|
||||||
dotptr = strrchr(filename, '.');
|
|
||||||
if (dotptr) *dotptr = '\0';
|
|
||||||
|
|
||||||
/* Is the library name the same as the filename (less extension)? */
|
if (isAbstract && isReadOnly)
|
||||||
if (isAbstract && isReadOnly && !strcmp(filename, chklibname))
|
{
|
||||||
|
filenamesubbed = StrDup(NULL, filename);
|
||||||
|
DBPathSubstitute(filename, filenamesubbed, edef);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is the library name the same as the filename? */
|
||||||
|
if (isAbstract && isReadOnly && !strcmp(filenamesubbed, chklibname))
|
||||||
{
|
{
|
||||||
/* Same library, so keep the cellname and mark the cell */
|
/* Same library, so keep the cellname and mark the cell */
|
||||||
/* as having been written to GDS. */
|
/* as having been written to GDS. */
|
||||||
|
|
@ -487,7 +554,7 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
|
||||||
HashSetValue(he, (char *)newnameptr);
|
HashSetValue(he, (char *)newnameptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dotptr) *dotptr = '.';
|
if (filenamesubbed) freeMagic(filenamesubbed);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -614,11 +681,12 @@ calmaFullDump(def, fi, outf, filename)
|
||||||
char *filename;
|
char *filename;
|
||||||
{
|
{
|
||||||
int version, rval;
|
int version, rval;
|
||||||
char *libname = NULL, uniqlibname[4];
|
char *libname = NULL, *testlib, uniqlibname[4];
|
||||||
char *sptr, *viewopts;
|
char *sptr, *viewopts;
|
||||||
bool isAbstract;
|
bool isAbstract;
|
||||||
HashTable calmaDefHash;
|
HashTable calmaDefHash;
|
||||||
HashEntry *he;
|
HashSearch hs;
|
||||||
|
HashEntry *he, *he2;
|
||||||
|
|
||||||
static int hdrSkip[] = { CALMA_FORMAT, CALMA_MASK, CALMA_ENDMASKS,
|
static int hdrSkip[] = { CALMA_FORMAT, CALMA_MASK, CALMA_ENDMASKS,
|
||||||
CALMA_REFLIBS, CALMA_FONTS, CALMA_ATTRTABLE,
|
CALMA_REFLIBS, CALMA_FONTS, CALMA_ATTRTABLE,
|
||||||
|
|
@ -645,6 +713,11 @@ calmaFullDump(def, fi, outf, filename)
|
||||||
|
|
||||||
// Record the GDS library so it will not be processed again.
|
// Record the GDS library so it will not be processed again.
|
||||||
he = HashFind(&calmaLibHash, filename);
|
he = HashFind(&calmaLibHash, filename);
|
||||||
|
if ((char *)HashGetValue(he) != NULL)
|
||||||
|
{
|
||||||
|
TxPrintf("Library %s has already been processed\n", libname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* If property LEFview is defined as "no_prefix" instead of "TRUE",
|
/* If property LEFview is defined as "no_prefix" instead of "TRUE",
|
||||||
* then do not create a unique prefix for subcells. This is generally
|
* then do not create a unique prefix for subcells. This is generally
|
||||||
|
|
@ -672,8 +745,6 @@ calmaFullDump(def, fi, outf, filename)
|
||||||
*/
|
*/
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
HashEntry *he2;
|
|
||||||
|
|
||||||
rval = random() % 26;
|
rval = random() % 26;
|
||||||
rval = 'A' + rval;
|
rval = 'A' + rval;
|
||||||
uniqlibname[0] = (char)(rval & 127);
|
uniqlibname[0] = (char)(rval & 127);
|
||||||
|
|
@ -700,6 +771,24 @@ calmaFullDump(def, fi, outf, filename)
|
||||||
calmaSkipExact(CALMA_ENDLIB);
|
calmaSkipExact(CALMA_ENDLIB);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
|
/* Check that all references were resolved. If not, then it is
|
||||||
|
* probably because a library was an "addendum"-type library
|
||||||
|
* referencing things in other libraries. Move those cell
|
||||||
|
* references to the calmaUndefHash before killing calmaDefHash.
|
||||||
|
*/
|
||||||
|
|
||||||
|
HashStartSearch(&hs);
|
||||||
|
while ((he = HashNext(&calmaDefHash, &hs)) != NULL)
|
||||||
|
{
|
||||||
|
char *refname = (char *)HashGetValue(he);
|
||||||
|
if (refname[0] == '0')
|
||||||
|
{
|
||||||
|
he2 = HashFind(&calmaUndefHash, (char *)he->h_key.h_name);
|
||||||
|
HashSetValue(he2, StrDup(NULL, refname));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
HashFreeKill(&calmaDefHash);
|
HashFreeKill(&calmaDefHash);
|
||||||
if (libname != NULL) freeMagic(libname);
|
if (libname != NULL) freeMagic(libname);
|
||||||
return;
|
return;
|
||||||
|
|
@ -1346,7 +1435,7 @@ calmaWriteUseFunc(use, f)
|
||||||
if (!calmaIsUseNameDefault(use->cu_def->cd_name, use->cu_id))
|
if (!calmaIsUseNameDefault(use->cu_def->cd_name, use->cu_id))
|
||||||
{
|
{
|
||||||
calmaOutRH(6, CALMA_PROPATTR, CALMA_I2, f);
|
calmaOutRH(6, CALMA_PROPATTR, CALMA_I2, f);
|
||||||
calmaOutI2(CALMA_PROP_USENAME, f);
|
calmaOutI2(CALMA_PROP_USENAME_STD, f);
|
||||||
calmaOutStringRecord(CALMA_PROPVALUE, use->cu_id, f);
|
calmaOutStringRecord(CALMA_PROPVALUE, use->cu_id, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@
|
||||||
#define CALMA_NUMRECORDTYPES 60 /* Number of above types */
|
#define CALMA_NUMRECORDTYPES 60 /* Number of above types */
|
||||||
|
|
||||||
/* Property types defined for magic */
|
/* Property types defined for magic */
|
||||||
|
#define CALMA_PROP_USENAME_STD 61 /* To record non-default cell use ids */
|
||||||
#define CALMA_PROP_USENAME 98 /* To record non-default cell use ids */
|
#define CALMA_PROP_USENAME 98 /* To record non-default cell use ids */
|
||||||
#define CALMA_PROP_ARRAY_LIMITS 99 /* To record non-default array limits */
|
#define CALMA_PROP_ARRAY_LIMITS 99 /* To record non-default array limits */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4896,13 +4896,14 @@ CIFGenLayer(op, area, cellDef, origDef, temps, hier, clientdata)
|
||||||
TxError("%s: Cannot read rectangle values.\n", propname);
|
TxError("%s: Cannot read rectangle values.\n", propname);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
cifPlane = curPlane;
|
||||||
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
|
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
|
||||||
bbox.r_xbot *= cifScale;
|
bbox.r_xbot *= cifScale;
|
||||||
bbox.r_xtop *= cifScale;
|
bbox.r_xtop *= cifScale;
|
||||||
bbox.r_ybot *= cifScale;
|
bbox.r_ybot *= cifScale;
|
||||||
bbox.r_ytop *= cifScale;
|
bbox.r_ytop *= cifScale;
|
||||||
cifScale = 1;
|
cifScale = 1;
|
||||||
DBNMPaintPlane(cifPlane, CIF_SOLIDTYPE, &bbox,
|
DBNMPaintPlane(curPlane, CIF_SOLIDTYPE, &bbox,
|
||||||
CIFPaintTable, (PaintUndoInfo *)NULL);
|
CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||||
for (j = 0; j < 4; j++)
|
for (j = 0; j < 4; j++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
288
cif/CIFhier.c
288
cif/CIFhier.c
|
|
@ -911,6 +911,52 @@ CIFGenSubcells(def, area, output)
|
||||||
UndoEnable();
|
UndoEnable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
cifHierElementFuncLow(use, transform, x, y, checkArea)
|
||||||
|
CellUse *use; /* CellUse being array-checked. */
|
||||||
|
Transform *transform; /* Transform from this instance to
|
||||||
|
* the parent.
|
||||||
|
*/
|
||||||
|
int x, y; /* Indices of this instance. */
|
||||||
|
Rect *checkArea; /* Area (in parent coords) to be
|
||||||
|
* CIF-generated.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
if (((x - use->cu_xlo) < 2) && ((y - use->cu_ylo) < 2))
|
||||||
|
return cifHierElementFunc(use, transform, x, y, checkArea);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
cifHierElementFuncHigh(use, transform, x, y, checkArea)
|
||||||
|
CellUse *use; /* CellUse being array-checked. */
|
||||||
|
Transform *transform; /* Transform from this instance to
|
||||||
|
* the parent.
|
||||||
|
*/
|
||||||
|
int x, y; /* Indices of this instance. */
|
||||||
|
Rect *checkArea; /* Area (in parent coords) to be
|
||||||
|
* CIF-generated.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
if (((use->cu_xhi - x) < 2) && ((use->cu_yhi - y) < 2))
|
||||||
|
return cifHierElementFunc(use, transform, x, y, checkArea);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -1139,7 +1185,6 @@ cifHierArrayFunc(scx, output)
|
||||||
Rect childArea, parentArea, A, B, C, D, expandedArea;
|
Rect childArea, parentArea, A, B, C, D, expandedArea;
|
||||||
CellUse *use;
|
CellUse *use;
|
||||||
int radius, xsep, ysep, xsize, ysize, nx, ny, i, oldTileOps;
|
int radius, xsep, ysep, xsize, ysize, nx, ny, i, oldTileOps;
|
||||||
int xhi, yhi;
|
|
||||||
bool anyInteractions = FALSE;
|
bool anyInteractions = FALSE;
|
||||||
|
|
||||||
use = scx->scx_use;
|
use = scx->scx_use;
|
||||||
|
|
@ -1147,17 +1192,9 @@ cifHierArrayFunc(scx, output)
|
||||||
if ((use->cu_xlo == use->cu_xhi) && (use->cu_ylo == use->cu_yhi))
|
if ((use->cu_xlo == use->cu_xhi) && (use->cu_ylo == use->cu_yhi))
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
/* We only want interactions between neighboring cells, so reduce */
|
/* We only want interactions between neighboring cells, so only */
|
||||||
/* the array size to at most 2x2, process, then restore the */
|
/* look at the bottom-left 2x2 set when calculating A and B, and */
|
||||||
/* original array count. */
|
/* only look at the top-right 2x2 set when calculating C and D. */
|
||||||
|
|
||||||
xhi = use->cu_xhi;
|
|
||||||
yhi = use->cu_yhi;
|
|
||||||
|
|
||||||
if (use->cu_xlo != use->cu_xhi)
|
|
||||||
use->cu_xhi = use->cu_xlo + ((use->cu_xlo < use->cu_xhi) ? 1 : -1);
|
|
||||||
if (use->cu_ylo != use->cu_yhi)
|
|
||||||
use->cu_yhi = use->cu_ylo + ((use->cu_ylo < use->cu_yhi) ? 1 : -1);
|
|
||||||
|
|
||||||
/* Compute the sizes and separations of elements, in coordinates
|
/* Compute the sizes and separations of elements, in coordinates
|
||||||
* of the parent. If the array is 1-dimensional, we set the
|
* of the parent. If the array is 1-dimensional, we set the
|
||||||
|
|
@ -1200,6 +1237,12 @@ cifHierArrayFunc(scx, output)
|
||||||
* into CIFTotalPlanes. Note: in each case we have to yank a larger
|
* into CIFTotalPlanes. Note: in each case we have to yank a larger
|
||||||
* area than we check, in order to include material that will be
|
* area than we check, in order to include material that will be
|
||||||
* bloated or shrunk.
|
* bloated or shrunk.
|
||||||
|
*
|
||||||
|
* (Updated 6/7/2021) A and B should be calculated and processed
|
||||||
|
* completely independently of C and D, or else if the array is
|
||||||
|
* small and the radius is large, then results from one will get
|
||||||
|
* picked up when making copies of the other, resulting in things
|
||||||
|
* getting painted out-of-bounds.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* A */
|
/* A */
|
||||||
|
|
@ -1211,7 +1254,7 @@ cifHierArrayFunc(scx, output)
|
||||||
A.r_ybot = use->cu_bbox.r_ybot + ysep - radius;
|
A.r_ybot = use->cu_bbox.r_ybot + ysep - radius;
|
||||||
A.r_ytop = use->cu_bbox.r_ybot + ysize + radius;
|
A.r_ytop = use->cu_bbox.r_ybot + ysize + radius;
|
||||||
GEO_EXPAND(&A, CIFCurStyle->cs_radius, &expandedArea);
|
GEO_EXPAND(&A, CIFCurStyle->cs_radius, &expandedArea);
|
||||||
(void) DBArraySr(use, &expandedArea, cifHierElementFunc,
|
(void) DBArraySr(use, &expandedArea, cifHierElementFuncLow,
|
||||||
(ClientData) &A);
|
(ClientData) &A);
|
||||||
CIFErrorDef = use->cu_parent;
|
CIFErrorDef = use->cu_parent;
|
||||||
CIFGen(CIFTotalDef, use->cu_def, &A, CIFTotalPlanes,
|
CIFGen(CIFTotalDef, use->cu_def, &A, CIFTotalPlanes,
|
||||||
|
|
@ -1220,24 +1263,6 @@ cifHierArrayFunc(scx, output)
|
||||||
anyInteractions = TRUE;
|
anyInteractions = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* C */
|
|
||||||
|
|
||||||
if (xsep < xsize + radius)
|
|
||||||
{
|
|
||||||
C.r_xbot = use->cu_bbox.r_xtop - xsize - radius;
|
|
||||||
C.r_xtop = use->cu_bbox.r_xtop - xsep + radius;
|
|
||||||
C.r_ybot = use->cu_bbox.r_ytop - ysize - radius;
|
|
||||||
C.r_ytop = use->cu_bbox.r_ytop + radius;
|
|
||||||
GEO_EXPAND(&C, CIFCurStyle->cs_radius, &expandedArea);
|
|
||||||
(void) DBArraySr(use, &expandedArea, cifHierElementFunc,
|
|
||||||
(ClientData) &C);
|
|
||||||
CIFErrorDef = use->cu_parent;
|
|
||||||
CIFGen(CIFTotalDef, use->cu_def, &C, CIFTotalPlanes,
|
|
||||||
&CIFCurStyle->cs_hierLayers, FALSE, TRUE, TRUE,
|
|
||||||
(ClientData)NULL);
|
|
||||||
anyInteractions = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((xsep < xsize + radius) && (ysep < ysize + radius))
|
if ((xsep < xsize + radius) && (ysep < ysize + radius))
|
||||||
{
|
{
|
||||||
/* B */
|
/* B */
|
||||||
|
|
@ -1247,31 +1272,16 @@ cifHierArrayFunc(scx, output)
|
||||||
B.r_ybot = use->cu_bbox.r_ybot - radius;
|
B.r_ybot = use->cu_bbox.r_ybot - radius;
|
||||||
B.r_ytop = use->cu_bbox.r_ybot + ysep - radius;
|
B.r_ytop = use->cu_bbox.r_ybot + ysep - radius;
|
||||||
GEO_EXPAND(&B, CIFCurStyle->cs_radius, &expandedArea);
|
GEO_EXPAND(&B, CIFCurStyle->cs_radius, &expandedArea);
|
||||||
(void) DBArraySr(use, &expandedArea, cifHierElementFunc,
|
(void) DBArraySr(use, &expandedArea, cifHierElementFuncLow,
|
||||||
(ClientData) &B);
|
(ClientData) &B);
|
||||||
CIFErrorDef = use->cu_parent;
|
CIFErrorDef = use->cu_parent;
|
||||||
CIFGen(CIFTotalDef, use->cu_def, &B, CIFTotalPlanes,
|
CIFGen(CIFTotalDef, use->cu_def, &B, CIFTotalPlanes,
|
||||||
&CIFCurStyle->cs_hierLayers, FALSE, TRUE, TRUE,
|
&CIFCurStyle->cs_hierLayers, FALSE, TRUE, TRUE,
|
||||||
(ClientData)NULL);
|
(ClientData)NULL);
|
||||||
|
|
||||||
/* D */
|
|
||||||
|
|
||||||
D.r_xbot = use->cu_bbox.r_xtop - xsep + radius;
|
|
||||||
D.r_xtop = use->cu_bbox.r_xtop + radius;
|
|
||||||
D.r_ybot = use->cu_bbox.r_ytop - ysize - radius;
|
|
||||||
D.r_ytop = use->cu_bbox.r_ytop - ysep + radius;
|
|
||||||
GEO_EXPAND(&D, CIFCurStyle->cs_radius, &expandedArea);
|
|
||||||
(void) DBArraySr(use, &expandedArea, cifHierElementFunc,
|
|
||||||
(ClientData) &D);
|
|
||||||
CIFErrorDef = use->cu_parent;
|
|
||||||
CIFGen(CIFTotalDef, use->cu_def, &D, CIFTotalPlanes,
|
|
||||||
&CIFCurStyle->cs_hierLayers, FALSE, TRUE, TRUE,
|
|
||||||
(ClientData)NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (anyInteractions)
|
if (anyInteractions)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Remove redundant CIF that's already in the children, and
|
/* Remove redundant CIF that's already in the children, and
|
||||||
* make sure everything in the kids is in the parent too.
|
* make sure everything in the kids is in the parent too.
|
||||||
*/
|
*/
|
||||||
|
|
@ -1308,6 +1318,155 @@ cifHierArrayFunc(scx, output)
|
||||||
(ClientData) NULL);
|
(ClientData) NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((nx > 1) && (ny > 1) && (xsep < xsize + radius)
|
||||||
|
&& (ysep < ysize + radius))
|
||||||
|
{
|
||||||
|
/* The bottom edge of the array (from B). */
|
||||||
|
|
||||||
|
cifHierXSpacing = xsep * scale;
|
||||||
|
cifHierYSpacing = 0;
|
||||||
|
cifHierXCount = nx-1;
|
||||||
|
cifHierYCount = 1;
|
||||||
|
SCALE(&B, scale, &cifArea);
|
||||||
|
(void) DBSrPaintArea((Tile *) NULL, CIFTotalPlanes[i],
|
||||||
|
&cifArea, &CIFSolidBits, cifHierPaintArrayFunc,
|
||||||
|
(ClientData) NULL);
|
||||||
|
|
||||||
|
/* The core of the array (copied from A and B). Copy area
|
||||||
|
* from A, but not to exceed 1/2 Y array separation, into the
|
||||||
|
* inside area of the array. If the expanded area is > 1/2
|
||||||
|
* the array separation, then there is no need to copy from
|
||||||
|
* area B. Otherwise, copy area from B, extending up to
|
||||||
|
* the bottom of the area just copied, and not to exceed
|
||||||
|
* 1/2 the X array separation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
cifHierXSpacing = xsep * scale;
|
||||||
|
cifHierYSpacing = ysep * scale;
|
||||||
|
cifHierXCount = nx-1;
|
||||||
|
cifHierYCount = ny-1;
|
||||||
|
|
||||||
|
/* Find top edge of cell */
|
||||||
|
A.r_xbot = use->cu_bbox.r_xbot;
|
||||||
|
A.r_xtop = use->cu_bbox.r_xbot + xsep;
|
||||||
|
A.r_ybot = use->cu_bbox.r_ybot + ysep;
|
||||||
|
A.r_ytop = use->cu_bbox.r_ybot + ysize;
|
||||||
|
/* Expand up/down but not by more than 1/2 ysep */
|
||||||
|
if ((2 * radius) > ysep)
|
||||||
|
{
|
||||||
|
A.r_ybot -= (ysep >> 1);
|
||||||
|
A.r_ytop += (ysep >> 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
A.r_ybot -= radius;
|
||||||
|
A.r_ytop += radius;
|
||||||
|
}
|
||||||
|
SCALE(&A, scale, &cifArea);
|
||||||
|
(void) DBSrPaintArea((Tile *) NULL, CIFTotalPlanes[i],
|
||||||
|
&cifArea, &CIFSolidBits, cifHierPaintArrayFunc,
|
||||||
|
(ClientData) NULL);
|
||||||
|
|
||||||
|
/* If the radius is more than half of ysep then there */
|
||||||
|
/* is nothing left that needs to be copied. */
|
||||||
|
|
||||||
|
if ((2 * radius) < ysep)
|
||||||
|
{
|
||||||
|
/* Find right edge of cell */
|
||||||
|
B.r_ybot = use->cu_bbox.r_ybot;
|
||||||
|
B.r_ytop = use->cu_bbox.r_ybot + ysep;
|
||||||
|
|
||||||
|
if (B.r_ytop > A.r_ybot) B.r_ytop = A.r_ybot;
|
||||||
|
|
||||||
|
B.r_xbot = use->cu_bbox.r_xbot + xsep;
|
||||||
|
B.r_xtop = use->cu_bbox.r_xbot + xsize;
|
||||||
|
/* Expand left/right but not by more than 1/2 xsep */
|
||||||
|
if ((2 * radius) > xsep)
|
||||||
|
{
|
||||||
|
B.r_xbot -= (xsep >> 1);
|
||||||
|
B.r_xtop += (xsep >> 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
B.r_xbot -= radius;
|
||||||
|
B.r_xtop += radius;
|
||||||
|
}
|
||||||
|
SCALE(&B, scale, &cifArea);
|
||||||
|
(void) DBSrPaintArea((Tile *) NULL, CIFTotalPlanes[i],
|
||||||
|
&cifArea, &CIFSolidBits, cifHierPaintArrayFunc,
|
||||||
|
(ClientData) NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CIFHierRects += CIFTileOps - oldTileOps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up from areas A and B */
|
||||||
|
cifHierCleanup();
|
||||||
|
anyInteractions = FALSE;
|
||||||
|
|
||||||
|
/* Now do areas C and D */
|
||||||
|
|
||||||
|
/* C */
|
||||||
|
|
||||||
|
if (xsep < xsize + radius)
|
||||||
|
{
|
||||||
|
C.r_xbot = use->cu_bbox.r_xtop - xsize - radius;
|
||||||
|
C.r_xtop = use->cu_bbox.r_xtop - xsep + radius;
|
||||||
|
C.r_ybot = use->cu_bbox.r_ytop - ysize - radius;
|
||||||
|
C.r_ytop = use->cu_bbox.r_ytop + radius;
|
||||||
|
GEO_EXPAND(&C, CIFCurStyle->cs_radius, &expandedArea);
|
||||||
|
(void) DBArraySr(use, &expandedArea, cifHierElementFuncHigh,
|
||||||
|
(ClientData) &C);
|
||||||
|
CIFErrorDef = use->cu_parent;
|
||||||
|
CIFGen(CIFTotalDef, use->cu_def, &C, CIFTotalPlanes,
|
||||||
|
&CIFCurStyle->cs_hierLayers, FALSE, TRUE, TRUE,
|
||||||
|
(ClientData)NULL);
|
||||||
|
anyInteractions = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((xsep < xsize + radius) && (ysep < ysize + radius))
|
||||||
|
{
|
||||||
|
/* D */
|
||||||
|
|
||||||
|
D.r_xbot = use->cu_bbox.r_xtop - xsep + radius;
|
||||||
|
D.r_xtop = use->cu_bbox.r_xtop + radius;
|
||||||
|
D.r_ybot = use->cu_bbox.r_ytop - ysize - radius;
|
||||||
|
D.r_ytop = use->cu_bbox.r_ytop - ysep + radius;
|
||||||
|
GEO_EXPAND(&D, CIFCurStyle->cs_radius, &expandedArea);
|
||||||
|
(void) DBArraySr(use, &expandedArea, cifHierElementFuncHigh,
|
||||||
|
(ClientData) &D);
|
||||||
|
CIFErrorDef = use->cu_parent;
|
||||||
|
CIFGen(CIFTotalDef, use->cu_def, &D, CIFTotalPlanes,
|
||||||
|
&CIFCurStyle->cs_hierLayers, FALSE, TRUE, TRUE,
|
||||||
|
(ClientData)NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anyInteractions)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Remove redundant CIF that's already in the children, and
|
||||||
|
* make sure everything in the kids is in the parent too.
|
||||||
|
*/
|
||||||
|
|
||||||
|
CIFErrorDef = use->cu_parent;
|
||||||
|
cifCheckAndErase(CIFCurStyle);
|
||||||
|
|
||||||
|
/* Lastly, paint everything back from our local planes into
|
||||||
|
* the planes of the caller. In doing this, stuff has to
|
||||||
|
* be replicated many times over to cover each of the array
|
||||||
|
* interaction areas.
|
||||||
|
*/
|
||||||
|
|
||||||
|
oldTileOps = CIFTileOps;
|
||||||
|
for (i=0; i<CIFCurStyle->cs_nLayers; i++)
|
||||||
|
{
|
||||||
|
int scale = CIFCurStyle->cs_scaleFactor;
|
||||||
|
Rect cifArea;
|
||||||
|
|
||||||
|
cifHierCurPlane = output[i];
|
||||||
|
CurCifLayer = CIFCurStyle->cs_layers[i]; /* for growSliver */
|
||||||
|
|
||||||
/* The top edge of the array (from C). */
|
/* The top edge of the array (from C). */
|
||||||
|
|
||||||
if ((nx > 1) && (xsep < xsize + radius))
|
if ((nx > 1) && (xsep < xsize + radius))
|
||||||
|
|
@ -1325,17 +1484,6 @@ cifHierArrayFunc(scx, output)
|
||||||
if ((nx > 1) && (ny > 1) && (xsep < xsize + radius)
|
if ((nx > 1) && (ny > 1) && (xsep < xsize + radius)
|
||||||
&& (ysep < ysize + radius))
|
&& (ysep < ysize + radius))
|
||||||
{
|
{
|
||||||
/* The bottom edge of the array (from B). */
|
|
||||||
|
|
||||||
cifHierXSpacing = xsep * scale;
|
|
||||||
cifHierYSpacing = 0;
|
|
||||||
cifHierXCount = nx-1;
|
|
||||||
cifHierYCount = 1;
|
|
||||||
SCALE(&B, scale, &cifArea);
|
|
||||||
(void) DBSrPaintArea((Tile *) NULL, CIFTotalPlanes[i],
|
|
||||||
&cifArea, &CIFSolidBits, cifHierPaintArrayFunc,
|
|
||||||
(ClientData) NULL);
|
|
||||||
|
|
||||||
/* The right edge of the array (from D). */
|
/* The right edge of the array (from D). */
|
||||||
|
|
||||||
cifHierXSpacing = 0;
|
cifHierXSpacing = 0;
|
||||||
|
|
@ -1346,36 +1494,12 @@ cifHierArrayFunc(scx, output)
|
||||||
(void) DBSrPaintArea((Tile *) NULL, CIFTotalPlanes[i],
|
(void) DBSrPaintArea((Tile *) NULL, CIFTotalPlanes[i],
|
||||||
&cifArea, &CIFSolidBits, cifHierPaintArrayFunc,
|
&cifArea, &CIFSolidBits, cifHierPaintArrayFunc,
|
||||||
(ClientData) NULL);
|
(ClientData) NULL);
|
||||||
|
|
||||||
/* The core of the array (from A and B). This code is a bit
|
|
||||||
* tricky in order to work correctly even for arrays where
|
|
||||||
* radius < ysep. The "if" statement handles this case.
|
|
||||||
*/
|
|
||||||
|
|
||||||
cifHierXSpacing = xsep * scale;
|
|
||||||
cifHierYSpacing = ysep * scale;
|
|
||||||
cifHierXCount = nx-1;
|
|
||||||
cifHierYCount = ny-1;
|
|
||||||
parentArea.r_xbot = A.r_xtop - xsep;
|
|
||||||
parentArea.r_ybot = A.r_ytop - ysep;
|
|
||||||
if (parentArea.r_ybot > B.r_ytop) parentArea.r_ybot = B.r_ytop;
|
|
||||||
parentArea.r_xtop = A.r_xtop;
|
|
||||||
parentArea.r_ytop = A.r_ytop;
|
|
||||||
SCALE(&parentArea, scale, &cifArea);
|
|
||||||
(void) DBSrPaintArea((Tile *) NULL, CIFTotalPlanes[i],
|
|
||||||
&cifArea, &CIFSolidBits, cifHierPaintArrayFunc,
|
|
||||||
(ClientData) NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CIFHierRects += CIFTileOps - oldTileOps;
|
CIFHierRects += CIFTileOps - oldTileOps;
|
||||||
}
|
}
|
||||||
|
|
||||||
cifHierCleanup();
|
cifHierCleanup();
|
||||||
|
|
||||||
/* Restore the array bounds of the array */
|
|
||||||
use->cu_xhi = xhi;
|
|
||||||
use->cu_yhi = yhi;
|
|
||||||
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4261,6 +4261,11 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
|
||||||
cellnameptr++;
|
cellnameptr++;
|
||||||
fullpathname = (char *)mallocMagic(strlen(cmd->tx_argv[1]) + 2);
|
fullpathname = (char *)mallocMagic(strlen(cmd->tx_argv[1]) + 2);
|
||||||
strcpy(fullpathname, cmd->tx_argv[1]);
|
strcpy(fullpathname, cmd->tx_argv[1]);
|
||||||
|
|
||||||
|
/* If the name still has ".mag" attached, then strip it. */
|
||||||
|
clen = strlen(fullpathname);
|
||||||
|
if ((clen > 4) && !strcmp(fullpathname + clen - 4, ".mag"))
|
||||||
|
*(fullpathname + clen - 4) = '\0';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -4307,8 +4312,8 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
|
||||||
def = DBCellLookDef(newcellname);
|
def = DBCellLookDef(newcellname);
|
||||||
uniqchar++;
|
uniqchar++;
|
||||||
}
|
}
|
||||||
TxError("Renaming cell to \"%s\" to avoid conflict.", newcellname);
|
TxError("Renaming cell to \"%s\" to avoid conflict.\n", newcellname);
|
||||||
def = DBCellNewDef(cellnameptr);
|
def = DBCellNewDef(newcellname);
|
||||||
StrDup(&def->cd_file, fullpathname);
|
StrDup(&def->cd_file, fullpathname);
|
||||||
freeMagic(newcellname);
|
freeMagic(newcellname);
|
||||||
}
|
}
|
||||||
|
|
@ -4396,15 +4401,10 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
|
||||||
TxError("Keyword must be followed by a reference point\n");
|
TxError("Keyword must be followed by a reference point\n");
|
||||||
goto usage;
|
goto usage;
|
||||||
}
|
}
|
||||||
if (StrIsInt(av[1]))
|
else if (ac == 3)
|
||||||
{
|
{
|
||||||
childPoint.p_x = atoi(av[1]);
|
childPoint.p_x = cmdParseCoord(w, av[1], TRUE, TRUE);
|
||||||
if (ac < 3 || !StrIsInt(av[2]))
|
childPoint.p_y = cmdParseCoord(w, av[2], TRUE, FALSE);
|
||||||
{
|
|
||||||
TxError("Must provide two coordinates\n");
|
|
||||||
goto usage;
|
|
||||||
}
|
|
||||||
childPoint.p_y = atoi(av[2]);
|
|
||||||
av += 3;
|
av += 3;
|
||||||
ac -= 3;
|
ac -= 3;
|
||||||
}
|
}
|
||||||
|
|
@ -4455,15 +4455,10 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
|
||||||
TxError("Keyword must be followed by a reference point\n");
|
TxError("Keyword must be followed by a reference point\n");
|
||||||
goto usage;
|
goto usage;
|
||||||
}
|
}
|
||||||
if (StrIsInt(av[1]))
|
else if (ac == 3)
|
||||||
{
|
{
|
||||||
editPoint.p_x = atoi(av[1]);
|
editPoint.p_x = cmdParseCoord(w, av[1], TRUE, TRUE);
|
||||||
if (ac < 3 || !StrIsInt(av[2]))
|
editPoint.p_y = cmdParseCoord(w, av[2], TRUE, FALSE);
|
||||||
{
|
|
||||||
TxError("Must provide two coordinates\n");
|
|
||||||
goto usage;
|
|
||||||
}
|
|
||||||
editPoint.p_y = atoi(av[2]);
|
|
||||||
av += 3;
|
av += 3;
|
||||||
ac -= 3;
|
ac -= 3;
|
||||||
GeoTransPoint(&EditToRootTransform, &editPoint,
|
GeoTransPoint(&EditToRootTransform, &editPoint,
|
||||||
|
|
|
||||||
|
|
@ -2008,14 +2008,18 @@ CmdFlatten(w, cmd)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* create the new def */
|
/* create the new def */
|
||||||
if (newdef = DBCellLookDef(destname))
|
newdef = DBCellLookDef(destname);
|
||||||
|
if ((newdef != NULL) && (dobox == FALSE))
|
||||||
{
|
{
|
||||||
TxError("%s already exists\n",destname);
|
TxError("%s already exists\n",destname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
newdef = DBCellNewDef(destname);
|
else if (newdef == NULL)
|
||||||
ASSERT(newdef, "CmdFlatten");
|
{
|
||||||
DBCellSetAvail(newdef);
|
newdef = DBCellNewDef(destname);
|
||||||
|
ASSERT(newdef, "CmdFlatten");
|
||||||
|
DBCellSetAvail(newdef);
|
||||||
|
}
|
||||||
newuse = DBCellNewUse(newdef, (char *) NULL);
|
newuse = DBCellNewUse(newdef, (char *) NULL);
|
||||||
(void) StrDup(&(newuse->cu_id), "Flattened cell");
|
(void) StrDup(&(newuse->cu_id), "Flattened cell");
|
||||||
DBSetTrans(newuse, &GeoIdentityTransform);
|
DBSetTrans(newuse, &GeoIdentityTransform);
|
||||||
|
|
@ -2063,5 +2067,6 @@ CmdFlatten(w, cmd)
|
||||||
if (xMask != CU_DESCEND_ALL)
|
if (xMask != CU_DESCEND_ALL)
|
||||||
DBCellCopyAllCells(&scx, xMask, flatDestUse, (Rect *)NULL);
|
DBCellCopyAllCells(&scx, xMask, flatDestUse, (Rect *)NULL);
|
||||||
|
|
||||||
|
DBCellDeleteUse(flatDestUse);
|
||||||
UndoEnable();
|
UndoEnable();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1612,8 +1612,9 @@ DBCellLookDef(cellName)
|
||||||
{
|
{
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
|
|
||||||
entry = HashFind(&dbCellDefTable, cellName);
|
entry = HashLookOnly(&dbCellDefTable, cellName);
|
||||||
return ((CellDef *) HashGetValue(entry));
|
if (entry == (HashEntry *)NULL) return (CellDef *)NULL;
|
||||||
|
return (CellDef *)HashGetValue(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -816,6 +816,7 @@ extern void DBTechInitContact();
|
||||||
extern void DBTechFinalContact();
|
extern void DBTechFinalContact();
|
||||||
extern void DBTechFinalConnect();
|
extern void DBTechFinalConnect();
|
||||||
extern void DBTechInitConnect();
|
extern void DBTechInitConnect();
|
||||||
|
extern bool DBIsContact();
|
||||||
|
|
||||||
/* Cell symbol table */
|
/* Cell symbol table */
|
||||||
extern void DBCellInit();
|
extern void DBCellInit();
|
||||||
|
|
|
||||||
|
|
@ -326,6 +326,7 @@ DBWloadWindow(window, name, flags)
|
||||||
{
|
{
|
||||||
deleteDef = ((CellUse *)window->w_surfaceID)->cu_def;
|
deleteDef = ((CellUse *)window->w_surfaceID)->cu_def;
|
||||||
if (strcmp(deleteDef->cd_name, "(UNNAMED)") ||
|
if (strcmp(deleteDef->cd_name, "(UNNAMED)") ||
|
||||||
|
(GrDisplayStatus == DISPLAY_SUSPEND) ||
|
||||||
deleteDef->cd_flags & (CDMODIFIED|CDBOXESCHANGED|CDSTAMPSCHANGED))
|
deleteDef->cd_flags & (CDMODIFIED|CDBOXESCHANGED|CDSTAMPSCHANGED))
|
||||||
deleteDef = NULL;
|
deleteDef = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -497,7 +498,7 @@ DBWloadWindow(window, name, flags)
|
||||||
|
|
||||||
if (newEdit)
|
if (newEdit)
|
||||||
{
|
{
|
||||||
if (EditCellUse && EditRootDef)
|
if ((EditCellUse && EditRootDef) && (deleteDef == NULL))
|
||||||
{
|
{
|
||||||
DBWUndoOldEdit(EditCellUse, EditRootDef,
|
DBWUndoOldEdit(EditCellUse, EditRootDef,
|
||||||
&EditToRootTransform, &RootToEditTransform);
|
&EditToRootTransform, &RootToEditTransform);
|
||||||
|
|
@ -549,6 +550,11 @@ DBWloadWindow(window, name, flags)
|
||||||
/* If the cell before loading was (UNNAMED) and it was */
|
/* If the cell before loading was (UNNAMED) and it was */
|
||||||
/* never modified, then delete it now. */
|
/* never modified, then delete it now. */
|
||||||
|
|
||||||
|
/* Caveat: The (UNNAMED) cell could be on a push stack; */
|
||||||
|
/* that is not fatal but should be avoided. Since the most */
|
||||||
|
/* common use is from the toolkit scripts, then make sure */
|
||||||
|
/* this doesn't happen within suspendall ... resumeall. */
|
||||||
|
|
||||||
if (deleteDef != NULL)
|
if (deleteDef != NULL)
|
||||||
DBCellDelete(deleteDef->cd_name, TRUE);
|
DBCellDelete(deleteDef->cd_name, TRUE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
drc/DRCcif.c
17
drc/DRCcif.c
|
|
@ -613,6 +613,14 @@ drcCifTile (tile, arg)
|
||||||
if (SigInterruptPending) return 1;
|
if (SigInterruptPending) return 1;
|
||||||
DRCstatTiles++;
|
DRCstatTiles++;
|
||||||
|
|
||||||
|
/* For non-Manhattan tiles, if the left side of tile is not the */
|
||||||
|
/* type that is declared by the rule, then skip the left-right */
|
||||||
|
/* check. */
|
||||||
|
|
||||||
|
if (IsSplit(tile))
|
||||||
|
if (SplitSide(tile))
|
||||||
|
goto tbcheck;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check design rules along a vertical boundary between two tiles.
|
* Check design rules along a vertical boundary between two tiles.
|
||||||
*
|
*
|
||||||
|
|
@ -801,6 +809,15 @@ drcCifTile (tile, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tbcheck:
|
||||||
|
|
||||||
|
/* For non-Manhattan tiles, if the bottom side of tile is not */
|
||||||
|
/* the type that is declared by the rule, then skip the top- */
|
||||||
|
/* bottom check. */
|
||||||
|
|
||||||
|
if (IsSplit(tile))
|
||||||
|
if (SplitSide(tile) == SplitDirection(tile))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check design rules along a horizontal boundary between two tiles.
|
* Check design rules along a horizontal boundary between two tiles.
|
||||||
|
|
|
||||||
|
|
@ -1836,6 +1836,7 @@ drcMaskSpacing(set1, set2, pmask1, pmask2, wwidth, distance, adjacency,
|
||||||
bool needtrigger = FALSE;
|
bool needtrigger = FALSE;
|
||||||
bool touchingok = TRUE;
|
bool touchingok = TRUE;
|
||||||
bool cornerok = FALSE;
|
bool cornerok = FALSE;
|
||||||
|
bool surroundok = FALSE;
|
||||||
|
|
||||||
if (!strcmp(adjacency, "surround_ok"))
|
if (!strcmp(adjacency, "surround_ok"))
|
||||||
{
|
{
|
||||||
|
|
@ -1858,6 +1859,7 @@ drcMaskSpacing(set1, set2, pmask1, pmask2, wwidth, distance, adjacency,
|
||||||
needtrigger = TRUE;
|
needtrigger = TRUE;
|
||||||
touchingok = FALSE;
|
touchingok = FALSE;
|
||||||
needReverse = TRUE;
|
needReverse = TRUE;
|
||||||
|
surroundok = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -2077,10 +2079,11 @@ drcMaskSpacing(set1, set2, pmask1, pmask2, wwidth, distance, adjacency,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now, if set1 and set2 are distinct apply the rule for LHS in set1
|
* Now, if set1 and set2 are distinct apply the rule for LHS in set1
|
||||||
* and RHS in set2.
|
* and RHS in set2. HOWEVER, "surround_ok" rules are asymmetrically
|
||||||
|
* triggered and cannot be reversed between set1 and set2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (pset = (DBTypesOnSamePlane(i, j) & pmask2))
|
if ((!surroundok) && (pset = (DBTypesOnSamePlane(i, j) & pmask2)))
|
||||||
{
|
{
|
||||||
plane = LowestMaskBit(pset);
|
plane = LowestMaskBit(pset);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,39 +97,39 @@ struct {
|
||||||
short resClassSub ; /* The resistance class of the substrate of the dev */
|
short resClassSub ; /* The resistance class of the substrate of the dev */
|
||||||
TileType devType ; /* Magic tile type of the device */
|
TileType devType ; /* Magic tile type of the device */
|
||||||
char *defSubs ; /* The default substrate node */
|
char *defSubs ; /* The default substrate node */
|
||||||
} fetInfo[MAXDEVTYPES];
|
} fetInfo[TT_MAXTYPES];
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
long visitMask:MAXDEVTYPES;
|
TileTypeBitMask visitMask;
|
||||||
} nodeClient;
|
} nodeClient;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
HierName *lastPrefix;
|
HierName *lastPrefix;
|
||||||
long visitMask:MAXDEVTYPES;
|
TileTypeBitMask visitMask;
|
||||||
} nodeClientHier;
|
} nodeClientHier;
|
||||||
|
|
||||||
#define NO_RESCLASS -1
|
#define NO_RESCLASS -1
|
||||||
|
|
||||||
#define markVisited(client, rclass) \
|
#define markVisited(client, rclass) \
|
||||||
{ (client)->visitMask |= (1<<rclass); }
|
{ TTMaskSetType(&((client)->visitMask), rclass); }
|
||||||
|
|
||||||
#define clearVisited(client) \
|
#define clearVisited(client) \
|
||||||
{ (client)->visitMask = (long)0; }
|
{ TTMaskZero(&((client)->visitMask)); }
|
||||||
|
|
||||||
#define beenVisited(client, rclass) \
|
#define beenVisited(client, rclass) \
|
||||||
( (client)->visitMask & (1<<rclass))
|
( TTMaskHasType(&((client)->visitMask), rclass) )
|
||||||
|
|
||||||
#define initNodeClient(node) \
|
#define initNodeClient(node) \
|
||||||
{ \
|
{ \
|
||||||
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClient))); \
|
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClient))); \
|
||||||
(( nodeClient *)(node)->efnode_client)->visitMask = (long) 0; \
|
TTMaskZero(&(( nodeClient *)(node)->efnode_client)->visitMask); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define initNodeClientHier(node) \
|
#define initNodeClientHier(node) \
|
||||||
{ \
|
{ \
|
||||||
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClientHier))); \
|
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClientHier))); \
|
||||||
((nodeClientHier *) (node)->efnode_client)->visitMask = (long) 0; \
|
TTMaskZero(&(( nodeClientHier *)(node)->efnode_client)->visitMask); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -572,7 +572,7 @@ runexttosim:
|
||||||
/* create default fetinfo entries (MOSIS) which can be overriden by
|
/* create default fetinfo entries (MOSIS) which can be overriden by
|
||||||
the command line arguments */
|
the command line arguments */
|
||||||
|
|
||||||
for ( i = 0 ; i < MAXDEVTYPES ; i++ )
|
for ( i = 0 ; i < TT_MAXTYPES ; i++ )
|
||||||
{
|
{
|
||||||
fetInfo[i].resClassSource = NO_RESCLASS;
|
fetInfo[i].resClassSource = NO_RESCLASS;
|
||||||
fetInfo[i].resClassDrain = NO_RESCLASS;
|
fetInfo[i].resClassDrain = NO_RESCLASS;
|
||||||
|
|
@ -589,12 +589,12 @@ runexttosim:
|
||||||
while (ExtGetDevInfo(idx++, &devname, &devtype, &s_rclass, &d_rclass,
|
while (ExtGetDevInfo(idx++, &devname, &devtype, &s_rclass, &d_rclass,
|
||||||
&sub_rclass, &subname))
|
&sub_rclass, &subname))
|
||||||
{
|
{
|
||||||
if (idx == MAXDEVTYPES)
|
if (idx == TT_MAXTYPES)
|
||||||
{
|
{
|
||||||
TxError("Error: Ran out of space for device types!\n");
|
TxError("Error: Ran out of space for device types!\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, devname);
|
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, devname);
|
||||||
|
|
||||||
if (EFStyle != NULL)
|
if (EFStyle != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -676,26 +676,26 @@ main(argc, argv)
|
||||||
EFInit();
|
EFInit();
|
||||||
/* create default fetinfo entries (MOSIS) which can be overriden by
|
/* create default fetinfo entries (MOSIS) which can be overriden by
|
||||||
the command line arguments */
|
the command line arguments */
|
||||||
for ( i = 0 ; i < MAXDEVTYPES ; i++ ) {
|
for ( i = 0 ; i < TT_MAXTYPES ; i++ ) {
|
||||||
fetInfo[i].resClassSource = NO_RESCLASS;
|
fetInfo[i].resClassSource = NO_RESCLASS;
|
||||||
fetInfo[i].resClassDrain = NO_RESCLASS;
|
fetInfo[i].resClassDrain = NO_RESCLASS;
|
||||||
fetInfo[i].resClassSub = NO_RESCLASS;
|
fetInfo[i].resClassSub = NO_RESCLASS;
|
||||||
fetInfo[i].defSubs = NULL;
|
fetInfo[i].defSubs = NULL;
|
||||||
fetInfo[i].devType = TT_SPACE;
|
fetInfo[i].devType = TT_SPACE;
|
||||||
}
|
}
|
||||||
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "nfet");
|
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, "nfet");
|
||||||
fetInfo[i].resClassSource = fetInfo[i].resClassDrain = 0 ;
|
fetInfo[i].resClassSource = fetInfo[i].resClassDrain = 0 ;
|
||||||
fetInfo[i].resClassSub = NO_RESCLASS ;
|
fetInfo[i].resClassSub = NO_RESCLASS ;
|
||||||
fetInfo[i].defSubs = "Gnd!";
|
fetInfo[i].defSubs = "Gnd!";
|
||||||
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "pfet");
|
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, "pfet");
|
||||||
fetInfo[i].resClassSource = fetInfo[i].resClassDrain = 1 ;
|
fetInfo[i].resClassSource = fetInfo[i].resClassDrain = 1 ;
|
||||||
fetInfo[i].resClassSub = 6 ;
|
fetInfo[i].resClassSub = 6 ;
|
||||||
fetInfo[i].defSubs = "Vdd!";
|
fetInfo[i].defSubs = "Vdd!";
|
||||||
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "nmos");
|
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, "nmos");
|
||||||
fetInfo[i].resClassSource = fetInfo[i].resClassDrain = 0 ;
|
fetInfo[i].resClassSource = fetInfo[i].resClassDrain = 0 ;
|
||||||
fetInfo[i].resClassSub = NO_RESCLASS ;
|
fetInfo[i].resClassSub = NO_RESCLASS ;
|
||||||
fetInfo[i].defSubs = "Gnd!";
|
fetInfo[i].defSubs = "Gnd!";
|
||||||
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "pmos");
|
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, "pmos");
|
||||||
fetInfo[i].resClassSource = fetInfo[i].resClassDrain = 1 ;
|
fetInfo[i].resClassSource = fetInfo[i].resClassDrain = 1 ;
|
||||||
fetInfo[i].resClassSub = 6 ;
|
fetInfo[i].resClassSub = 6 ;
|
||||||
fetInfo[i].defSubs = "Vdd!";
|
fetInfo[i].defSubs = "Vdd!";
|
||||||
|
|
@ -896,7 +896,7 @@ simmainArgs(pargc, pargv)
|
||||||
rClassSub = NO_RESCLASS ;
|
rClassSub = NO_RESCLASS ;
|
||||||
if ( sscanf(rp, "%d/%s", &rClass, subsNode) != 2 ) goto usage;
|
if ( sscanf(rp, "%d/%s", &rClass, subsNode) != 2 ) goto usage;
|
||||||
}
|
}
|
||||||
ndx = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, cp);
|
ndx = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, cp);
|
||||||
fetInfo[ndx].resClassSource = rClass;
|
fetInfo[ndx].resClassSource = rClass;
|
||||||
fetInfo[ndx].resClassDrain = rClass;
|
fetInfo[ndx].resClassDrain = rClass;
|
||||||
fetInfo[ndx].resClassSub = rClassSub;
|
fetInfo[ndx].resClassSub = rClassSub;
|
||||||
|
|
@ -1206,9 +1206,6 @@ simdevVisit(dev, hc, scale, trans)
|
||||||
/* Output length, width, and position as attributes */
|
/* Output length, width, and position as attributes */
|
||||||
fprintf(esSimF, " l=%g w=%g x=%g y=%g",
|
fprintf(esSimF, " l=%g w=%g x=%g y=%g",
|
||||||
l * scale, w * scale, r.r_xbot * scale, r.r_ybot * scale);
|
l * scale, w * scale, r.r_xbot * scale, r.r_ybot * scale);
|
||||||
|
|
||||||
/* Output tile type as an attribute for quick lookup by ResReadSim */
|
|
||||||
fprintf(esSimF, " t=%d", fetInfo[dev->dev_type].devType);
|
|
||||||
}
|
}
|
||||||
else if ((dev->dev_class != DEV_DIODE) && (dev->dev_class != DEV_PDIODE)
|
else if ((dev->dev_class != DEV_DIODE) && (dev->dev_class != DEV_PDIODE)
|
||||||
&& (dev->dev_class != DEV_NDIODE)) {
|
&& (dev->dev_class != DEV_NDIODE)) {
|
||||||
|
|
@ -1402,7 +1399,7 @@ bool simnAPHier(dterm, hierName, resClass, scale, outf)
|
||||||
initNodeClientHier(node);
|
initNodeClientHier(node);
|
||||||
nc = (nodeClientHier *)node->efnode_client;
|
nc = (nodeClientHier *)node->efnode_client;
|
||||||
if ( nc->lastPrefix != hierName ) {
|
if ( nc->lastPrefix != hierName ) {
|
||||||
nc->visitMask = 0;
|
TTMaskZero(&(nc->visitMask));
|
||||||
nc->lastPrefix = hierName;
|
nc->lastPrefix = hierName;
|
||||||
}
|
}
|
||||||
if ( resClass == NO_RESCLASS ||
|
if ( resClass == NO_RESCLASS ||
|
||||||
|
|
|
||||||
|
|
@ -1264,10 +1264,10 @@ spcnodeHierVisit(hc, node, res, cap)
|
||||||
|
|
||||||
if (node->efnode_client)
|
if (node->efnode_client)
|
||||||
{
|
{
|
||||||
isConnected = (esDistrJunct) ?
|
if (esDistrJunct)
|
||||||
(((nodeClient *)node->efnode_client)->m_w.widths != NULL) :
|
isConnected = (((nodeClient *)node->efnode_client)->m_w.widths != NULL);
|
||||||
((((nodeClient *)node->efnode_client)->m_w.visitMask
|
else
|
||||||
& DEV_CONNECT_MASK) != 0);
|
isConnected = !TTMaskIsZero(&((nodeClient *)node->efnode_client)->m_w.visitMask);
|
||||||
}
|
}
|
||||||
if (!isConnected && esDevNodesOnly)
|
if (!isConnected && esDevNodesOnly)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ int esNoModelType; /* index for device type "None" (model-less device) */
|
||||||
HashTable subcktNameTable ; /* the hash table itself */
|
HashTable subcktNameTable ; /* the hash table itself */
|
||||||
DQueue subcktNameQueue ; /* q used to print it sorted at the end*/
|
DQueue subcktNameQueue ; /* q used to print it sorted at the end*/
|
||||||
|
|
||||||
fetInfoList esFetInfo[MAXDEVTYPES];
|
fetInfoList esFetInfo[TT_MAXTYPES];
|
||||||
|
|
||||||
/* Record for keeping a list of global names */
|
/* Record for keeping a list of global names */
|
||||||
|
|
||||||
|
|
@ -90,7 +90,7 @@ typedef struct GLL {
|
||||||
char *gll_name;
|
char *gll_name;
|
||||||
} globalList;
|
} globalList;
|
||||||
|
|
||||||
unsigned long initMask = 0;
|
TileTypeBitMask initMask; /* Used for device types, not tile types */
|
||||||
|
|
||||||
bool esMergeDevsA = FALSE; /* aggressive merging of devs L1=L2 merge them */
|
bool esMergeDevsA = FALSE; /* aggressive merging of devs L1=L2 merge them */
|
||||||
bool esMergeDevsC = FALSE; /* conservative merging of devs L1=L2 and W1=W2 */
|
bool esMergeDevsC = FALSE; /* conservative merging of devs L1=L2 and W1=W2 */
|
||||||
|
|
@ -728,7 +728,7 @@ runexttospice:
|
||||||
/* create default devinfo entries (MOSIS) which can be overridden by
|
/* create default devinfo entries (MOSIS) which can be overridden by
|
||||||
the command line arguments */
|
the command line arguments */
|
||||||
|
|
||||||
for ( i = 0 ; i < MAXDEVTYPES ; i++ ) {
|
for ( i = 0 ; i < TT_MAXTYPES ; i++ ) {
|
||||||
esFetInfo[i].resClassSource = NO_RESCLASS;
|
esFetInfo[i].resClassSource = NO_RESCLASS;
|
||||||
esFetInfo[i].resClassDrain = NO_RESCLASS;
|
esFetInfo[i].resClassDrain = NO_RESCLASS;
|
||||||
esFetInfo[i].resClassSub = NO_RESCLASS;
|
esFetInfo[i].resClassSub = NO_RESCLASS;
|
||||||
|
|
@ -743,12 +743,12 @@ runexttospice:
|
||||||
while (ExtGetDevInfo(idx++, &devname, &devtype, &s_rclass, &d_rclass,
|
while (ExtGetDevInfo(idx++, &devname, &devtype, &s_rclass, &d_rclass,
|
||||||
&sub_rclass, &subname))
|
&sub_rclass, &subname))
|
||||||
{
|
{
|
||||||
if (idx == MAXDEVTYPES)
|
if (idx == TT_MAXTYPES)
|
||||||
{
|
{
|
||||||
TxError("Error: Ran out of space for device types!\n");
|
TxError("Error: Ran out of space for device types!\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, devname);
|
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, devname);
|
||||||
if (!strcmp(devname, "None"))
|
if (!strcmp(devname, "None"))
|
||||||
esNoModelType = i;
|
esNoModelType = i;
|
||||||
if (EFStyle != NULL)
|
if (EFStyle != NULL)
|
||||||
|
|
@ -908,7 +908,9 @@ runexttospice:
|
||||||
if (!esDoPorts)
|
if (!esDoPorts)
|
||||||
EFVisitSubcircuits(subcktUndef, (ClientData) NULL);
|
EFVisitSubcircuits(subcktUndef, (ClientData) NULL);
|
||||||
|
|
||||||
initMask = ( esDistrJunct ) ? (unsigned long)0 : DEV_CONNECT_MASK;
|
TTMaskZero(&initMask);
|
||||||
|
if (!esDistrJunct)
|
||||||
|
TTMaskCom(&initMask);
|
||||||
|
|
||||||
if (esMergeDevsA || esMergeDevsC)
|
if (esMergeDevsA || esMergeDevsC)
|
||||||
{
|
{
|
||||||
|
|
@ -924,7 +926,7 @@ runexttospice:
|
||||||
else if (esDistrJunct)
|
else if (esDistrJunct)
|
||||||
EFVisitDevs(devDistJunctVisit, (ClientData) NULL);
|
EFVisitDevs(devDistJunctVisit, (ClientData) NULL);
|
||||||
EFVisitDevs(spcdevVisit, (ClientData) NULL);
|
EFVisitDevs(spcdevVisit, (ClientData) NULL);
|
||||||
initMask = (unsigned long) 0;
|
TTMaskZero(&initMask);
|
||||||
if (flatFlags & EF_FLATCAPS)
|
if (flatFlags & EF_FLATCAPS)
|
||||||
{
|
{
|
||||||
(void) sprintf( esSpiceCapFormat, "C%%d %%s %%s %%.%dlffF\n",
|
(void) sprintf( esSpiceCapFormat, "C%%d %%s %%s %%.%dlffF\n",
|
||||||
|
|
@ -994,25 +996,25 @@ main(argc, argv)
|
||||||
EFResistThreshold = INFINITE_THRESHOLD ;
|
EFResistThreshold = INFINITE_THRESHOLD ;
|
||||||
/* create default devinfo entries (MOSIS) which can be overriden by
|
/* create default devinfo entries (MOSIS) which can be overriden by
|
||||||
the command line arguments */
|
the command line arguments */
|
||||||
for ( i = 0 ; i < MAXDEVTYPES ; i++ ) {
|
for ( i = 0 ; i < TT_MAXTYPES ; i++ ) {
|
||||||
esFetInfo[i].resClassSource = NO_RESCLASS;
|
esFetInfo[i].resClassSource = NO_RESCLASS;
|
||||||
esFetInfo[i].resClassDrain = NO_RESCLASS;
|
esFetInfo[i].resClassDrain = NO_RESCLASS;
|
||||||
esFetInfo[i].resClassSub = NO_RESCLASS;
|
esFetInfo[i].resClassSub = NO_RESCLASS;
|
||||||
esFetInfo[i].defSubs = NULL;
|
esFetInfo[i].defSubs = NULL;
|
||||||
}
|
}
|
||||||
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "ndev");
|
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, "ndev");
|
||||||
esFetInfo[i].resClassSource = esFetInfo[i].resClassDrain = 0 ;
|
esFetInfo[i].resClassSource = esFetInfo[i].resClassDrain = 0 ;
|
||||||
esFetInfo[i].resClassSub = NO_RESCLASS ;
|
esFetInfo[i].resClassSub = NO_RESCLASS ;
|
||||||
esFetInfo[i].defSubs = "Gnd!";
|
esFetInfo[i].defSubs = "Gnd!";
|
||||||
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "pdev");
|
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, "pdev");
|
||||||
esFetInfo[i].resClassSource = esFetInfo[i].resClassDrain = 1 ;
|
esFetInfo[i].resClassSource = esFetInfo[i].resClassDrain = 1 ;
|
||||||
esFetInfo[i].resClassSub = 8 ;
|
esFetInfo[i].resClassSub = 8 ;
|
||||||
esFetInfo[i].defSubs = "Vdd!";
|
esFetInfo[i].defSubs = "Vdd!";
|
||||||
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "nmos");
|
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, "nmos");
|
||||||
esFetInfo[i].resClassSource = esFetInfo[i].resClassDrain = 0 ;
|
esFetInfo[i].resClassSource = esFetInfo[i].resClassDrain = 0 ;
|
||||||
esFetInfo[i].resClassSub = NO_RESCLASS ;
|
esFetInfo[i].resClassSub = NO_RESCLASS ;
|
||||||
esFetInfo[i].defSubs = "Gnd!";
|
esFetInfo[i].defSubs = "Gnd!";
|
||||||
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, "pmos");
|
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, "pmos");
|
||||||
esFetInfo[i].resClassSource = esFetInfo[i].resClassDrain = 1 ;
|
esFetInfo[i].resClassSource = esFetInfo[i].resClassDrain = 1 ;
|
||||||
esFetInfo[i].resClassSub = 8 ;
|
esFetInfo[i].resClassSub = 8 ;
|
||||||
esFetInfo[i].defSubs = "Vdd!";
|
esFetInfo[i].defSubs = "Vdd!";
|
||||||
|
|
@ -1078,7 +1080,9 @@ main(argc, argv)
|
||||||
if (!esDoPorts)
|
if (!esDoPorts)
|
||||||
EFVisitSubcircuits(subcktUndef, (ClientData) NULL);
|
EFVisitSubcircuits(subcktUndef, (ClientData) NULL);
|
||||||
|
|
||||||
initMask = ( esDistrJunct ) ? (unsigned long)0 : DEV_CONNECT_MASK ;
|
TTMaskZero(&initMask);
|
||||||
|
if (!esDistrJunct)
|
||||||
|
TTMaskCom(&initMask);
|
||||||
|
|
||||||
if ( esMergeDevsA || esMergeDevsC ) {
|
if ( esMergeDevsA || esMergeDevsC ) {
|
||||||
EFVisitDevs(devMergeVisit, (ClientData) NULL);
|
EFVisitDevs(devMergeVisit, (ClientData) NULL);
|
||||||
|
|
@ -1092,7 +1096,7 @@ main(argc, argv)
|
||||||
} else if ( esDistrJunct )
|
} else if ( esDistrJunct )
|
||||||
EFVisitDevs(devDistJunctVisit, (ClientData) NULL);
|
EFVisitDevs(devDistJunctVisit, (ClientData) NULL);
|
||||||
EFVisitDevs(spcdevVisit, (ClientData) NULL);
|
EFVisitDevs(spcdevVisit, (ClientData) NULL);
|
||||||
initMask = (unsigned long) 0;
|
TTMaskZero(&initMask);
|
||||||
if (flatFlags & EF_FLATCAPS) {
|
if (flatFlags & EF_FLATCAPS) {
|
||||||
(void) sprintf( esSpiceCapFormat, "C%%d %%s %%s %%.%dlffF\n",esCapAccuracy);
|
(void) sprintf( esSpiceCapFormat, "C%%d %%s %%s %%.%dlffF\n",esCapAccuracy);
|
||||||
EFVisitCaps(spccapVisit, (ClientData) NULL);
|
EFVisitCaps(spccapVisit, (ClientData) NULL);
|
||||||
|
|
@ -1240,17 +1244,9 @@ spcmainArgs(pargc, pargv)
|
||||||
rClassSub = -1 ;
|
rClassSub = -1 ;
|
||||||
if ( sscanf(rp, "%d/%s", &rClass, subsNode) != 2 ) goto usage;
|
if ( sscanf(rp, "%d/%s", &rClass, subsNode) != 2 ) goto usage;
|
||||||
}
|
}
|
||||||
ndx = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, cp);
|
ndx = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, cp);
|
||||||
esFetInfo[ndx].resClassSource = esFetInfo[ndx].resClassDrain = rClass;
|
esFetInfo[ndx].resClassSource = esFetInfo[ndx].resClassDrain = rClass;
|
||||||
esFetInfo[ndx].resClassSub = rClassSub;
|
esFetInfo[ndx].resClassSub = rClassSub;
|
||||||
if ( ((1<<rClass) & DEV_CONNECT_MASK) ||
|
|
||||||
((1<<rClass) & DEV_CONNECT_MASK) ) {
|
|
||||||
TxError("Oops it seems that you have 31\n");
|
|
||||||
TxError("resistance classes. You will need to recompile");
|
|
||||||
TxError("the extflat package and change ext2sim/spice\n");
|
|
||||||
TxError("DEV_CONNECT_MASK and or nodeClient\n");
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
esFetInfo[ndx].defSubs = (char *)mallocMagic((unsigned)(strlen(subsNode)+1));
|
esFetInfo[ndx].defSubs = (char *)mallocMagic((unsigned)(strlen(subsNode)+1));
|
||||||
strcpy(esFetInfo[ndx].defSubs,subsNode);
|
strcpy(esFetInfo[ndx].defSubs,subsNode);
|
||||||
TxError("info: dev %s(%d) srcRclass=%d drnRclass=%d subRclass=%d dSub=%s\n",
|
TxError("info: dev %s(%d) srcRclass=%d drnRclass=%d subRclass=%d dSub=%s\n",
|
||||||
|
|
@ -2910,8 +2906,10 @@ FILE *outf;
|
||||||
initNodeClientHier(nn->efnn_node);
|
initNodeClientHier(nn->efnn_node);
|
||||||
|
|
||||||
if (!esDistrJunct)
|
if (!esDistrJunct)
|
||||||
((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |=
|
{
|
||||||
DEV_CONNECT_MASK;
|
TTMaskZero(&((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask);
|
||||||
|
TTMaskCom(&((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask);
|
||||||
|
}
|
||||||
return nn->efnn_node;
|
return nn->efnn_node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3126,7 +3124,10 @@ spcdevOutNode(prefix, suffix, name, outf)
|
||||||
|
|
||||||
/* Mark node as visited */
|
/* Mark node as visited */
|
||||||
if (!esDistrJunct)
|
if (!esDistrJunct)
|
||||||
((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= DEV_CONNECT_MASK;
|
{
|
||||||
|
TTMaskZero(&((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask);
|
||||||
|
TTMaskCom(&((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask);
|
||||||
|
}
|
||||||
|
|
||||||
return (1 + strlen(nname));
|
return (1 + strlen(nname));
|
||||||
}
|
}
|
||||||
|
|
@ -3279,8 +3280,7 @@ spcnodeVisit(node, res, cap)
|
||||||
{
|
{
|
||||||
isConnected = (esDistrJunct) ?
|
isConnected = (esDistrJunct) ?
|
||||||
(((nodeClient *)node->efnode_client)->m_w.widths != NULL) :
|
(((nodeClient *)node->efnode_client)->m_w.widths != NULL) :
|
||||||
((((nodeClient *)node->efnode_client)->m_w.visitMask
|
(!TTMaskIsZero(&((nodeClient *)node->efnode_client)->m_w.visitMask));
|
||||||
& DEV_CONNECT_MASK) != 0);
|
|
||||||
}
|
}
|
||||||
if (!isConnected && esDevNodesOnly)
|
if (!isConnected && esDevNodesOnly)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ extern FILE *esSpiceF;
|
||||||
extern float esScale; /* negative if hspice the EFScale/100 otherwise */
|
extern float esScale; /* negative if hspice the EFScale/100 otherwise */
|
||||||
|
|
||||||
extern unsigned short esFormat;
|
extern unsigned short esFormat;
|
||||||
extern unsigned long initMask;
|
extern TileTypeBitMask initMask;
|
||||||
|
|
||||||
extern int esCapNum, esDevNum, esResNum, esDiodeNum;
|
extern int esCapNum, esDevNum, esResNum, esDiodeNum;
|
||||||
extern int esNodeNum; /* just in case we're extracting spice2 */
|
extern int esNodeNum; /* just in case we're extracting spice2 */
|
||||||
|
|
@ -96,19 +96,15 @@ typedef struct {
|
||||||
char *defSubs ; /* the default substrate node */
|
char *defSubs ; /* the default substrate node */
|
||||||
} fetInfoList;
|
} fetInfoList;
|
||||||
|
|
||||||
extern fetInfoList esFetInfo[MAXDEVTYPES];
|
extern fetInfoList esFetInfo[TT_MAXTYPES];
|
||||||
|
|
||||||
#define MAX_STR_SIZE (1<<11) /* 2K should be enough for keeping temp
|
#define MAX_STR_SIZE (1<<11) /* 2K should be enough for keeping temp
|
||||||
names even of the most complicated design */
|
names even of the most complicated design */
|
||||||
|
|
||||||
/* Node clients for figuring out areas and perimeters of sources and drains */
|
/* Node clients for figuring out areas and perimeters of sources and drains */
|
||||||
typedef struct {
|
|
||||||
long _duml:MAXDEVTYPES;
|
|
||||||
} _dum; /* if you get an error here you should change
|
|
||||||
the data structures and visitMask */
|
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
long visitMask; /* mask for normal visits */
|
TileTypeBitMask visitMask; /* mask for normal visits */
|
||||||
float *widths; /* width used for distributing area perim */
|
float *widths; /* width used for distributing area perim */
|
||||||
} maskOrWidth ;
|
} maskOrWidth ;
|
||||||
|
|
||||||
|
|
@ -125,32 +121,27 @@ typedef struct {
|
||||||
#define NO_RESCLASS -1
|
#define NO_RESCLASS -1
|
||||||
|
|
||||||
#define markVisited(client, rclass) \
|
#define markVisited(client, rclass) \
|
||||||
{ (client)->m_w.visitMask |= (1<<rclass); }
|
{ TTMaskSetType(&((client)->m_w.visitMask), rclass); }
|
||||||
|
|
||||||
#define clearVisited(client) \
|
#define clearVisited(client) \
|
||||||
{ (client)->m_w.visitMask = (long)0; }
|
{ TTMaskZero(&((client)->m_w.visitMask)); }
|
||||||
|
|
||||||
#define beenVisited(client, rclass) \
|
#define beenVisited(client, rclass) \
|
||||||
( (client)->m_w.visitMask & (1<<rclass))
|
( TTMaskHasType(&((client)->m_w.visitMask), rclass) )
|
||||||
|
|
||||||
/*
|
|
||||||
* Used to mark the nodes which are connected to devs. initMask is set to
|
|
||||||
* DEV_CONNECT_MASK only when we are in visitDevs
|
|
||||||
*/
|
|
||||||
#define DEV_CONNECT_MASK ((unsigned long)1<<(sizeof(long)*BITSPERCHAR-1))
|
|
||||||
|
|
||||||
#define initNodeClient(node) \
|
#define initNodeClient(node) \
|
||||||
{ \
|
{ \
|
||||||
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClient))); \
|
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClient))); \
|
||||||
(( nodeClient *)(node)->efnode_client)->spiceNodeName = NULL; \
|
(( nodeClient *)(node)->efnode_client)->spiceNodeName = NULL; \
|
||||||
(( nodeClient *)(node)->efnode_client)->m_w.visitMask = (unsigned long)initMask; \
|
TTMaskZero (&((nodeClient *) (node)->efnode_client)->m_w.visitMask); \
|
||||||
|
TTMaskSetMask(&(((nodeClient *)(node)->efnode_client)->m_w.visitMask), &initMask);\
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define initNodeClientHier(node) \
|
#define initNodeClientHier(node) \
|
||||||
{ \
|
{ \
|
||||||
(node)->efnode_client = (ClientData) mallocMagic((unsigned)(sizeof(nodeClientHier))); \
|
(node)->efnode_client = (ClientData) mallocMagic((unsigned)(sizeof(nodeClientHier))); \
|
||||||
((nodeClientHier *) (node)->efnode_client)->m_w.visitMask = (unsigned long) 0; \
|
TTMaskZero (&((nodeClientHier *) (node)->efnode_client)->m_w.visitMask); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,36 +42,36 @@ int antennacheckArgs();
|
||||||
int antennacheckVisit();
|
int antennacheckVisit();
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
long visitMask:MAXDEVTYPES;
|
TileTypeBitMask visitMask;
|
||||||
} nodeClient;
|
} nodeClient;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
HierName *lastPrefix;
|
HierName *lastPrefix;
|
||||||
long visitMask:MAXDEVTYPES;
|
TileTypeBitMask visitMask;
|
||||||
} nodeClientHier;
|
} nodeClientHier;
|
||||||
|
|
||||||
#define NO_RESCLASS -1
|
#define NO_RESCLASS -1
|
||||||
|
|
||||||
#define markVisited(client, rclass) \
|
#define markVisited(client, rclass) \
|
||||||
{ (client)->visitMask |= (1<<rclass); }
|
{ TTMaskSetType(&((client)->visitMask), rclass); }
|
||||||
|
|
||||||
#define clearVisited(client) \
|
#define clearVisited(client) \
|
||||||
{ (client)->visitMask = (long)0; }
|
{ TTMaskZero(&((client)->visitMask); }
|
||||||
|
|
||||||
#define beenVisited(client, rclass) \
|
#define beenVisited(client, rclass) \
|
||||||
( (client)->visitMask & (1<<rclass))
|
( TTMaskHasType(&((client)->visitMask), rclass) )
|
||||||
|
|
||||||
#define initNodeClient(node) \
|
#define initNodeClient(node) \
|
||||||
{ \
|
{ \
|
||||||
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClient))); \
|
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClient))); \
|
||||||
(( nodeClient *)(node)->efnode_client)->visitMask = (long) 0; \
|
TTMaskZero(&(( nodeClient *)(node)->efnode_client)->visitMask); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define initNodeClientHier(node) \
|
#define initNodeClientHier(node) \
|
||||||
{ \
|
{ \
|
||||||
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClientHier))); \
|
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClientHier))); \
|
||||||
((nodeClientHier *) (node)->efnode_client)->visitMask = (long) 0; \
|
TTMaskZero(&(( nodeClientHier *)(node)->efnode_client)->visitMask); \
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Diagnostic */
|
/* Diagnostic */
|
||||||
|
|
@ -228,9 +228,21 @@ runantennacheck:
|
||||||
TxPrintf("Building flattened netlist.\n");
|
TxPrintf("Building flattened netlist.\n");
|
||||||
EFFlatBuild(inName, flatFlags);
|
EFFlatBuild(inName, flatFlags);
|
||||||
|
|
||||||
|
/* Get device information from the current extraction style */
|
||||||
|
idx = 0;
|
||||||
|
while (ExtGetDevInfo(idx++, &devname, NULL, NULL, NULL, NULL, NULL))
|
||||||
|
{
|
||||||
|
if (idx == TT_MAXTYPES)
|
||||||
|
{
|
||||||
|
TxError("Error: Ran out of space for device types!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, devname);
|
||||||
|
}
|
||||||
|
|
||||||
/* Build device lookup table */
|
/* Build device lookup table */
|
||||||
EFDeviceTypes = (TileType *)mallocMagic(MAXDEVTYPES * sizeof(TileType));
|
EFDeviceTypes = (TileType *)mallocMagic(EFDevNumTypes * sizeof(TileType));
|
||||||
for (i = 0; i < MAXDEVTYPES; i++)
|
for (i = 0; i < EFDevNumTypes; i++)
|
||||||
if (EFDevTypes[i])
|
if (EFDevTypes[i])
|
||||||
EFDeviceTypes[i] = extGetDevType(EFDevTypes[i]);
|
EFDeviceTypes[i] = extGetDevType(EFDevTypes[i]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,10 @@ static char rcsid[] __attribute__ ((unused)) = "$Header$";
|
||||||
#include "utils/hash.h"
|
#include "utils/hash.h"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
#include "utils/malloc.h"
|
#include "utils/malloc.h"
|
||||||
|
#include "tiles/tile.h"
|
||||||
|
#include "database/database.h" /* for TileType definition */
|
||||||
#include "extflat/extflat.h"
|
#include "extflat/extflat.h"
|
||||||
#include "extflat/EFint.h"
|
#include "extflat/EFint.h"
|
||||||
#include "tiles/tile.h"
|
|
||||||
#include "extract/extract.h" /* for device class list */
|
#include "extract/extract.h" /* for device class list */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -48,7 +49,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header$";
|
||||||
#define MAXTYPES 100
|
#define MAXTYPES 100
|
||||||
|
|
||||||
/* Table of transistor types */
|
/* Table of transistor types */
|
||||||
char *EFDevTypes[MAXDEVTYPES];
|
char *EFDevTypes[TT_MAXTYPES];
|
||||||
int EFDevNumTypes;
|
int EFDevNumTypes;
|
||||||
|
|
||||||
/* Table of Magic layers */
|
/* Table of Magic layers */
|
||||||
|
|
@ -656,6 +657,8 @@ efBuildDevice(def, class, type, r, argc, argv)
|
||||||
DevTerm *term;
|
DevTerm *term;
|
||||||
Dev *newdev, devtmp;
|
Dev *newdev, devtmp;
|
||||||
DevParam *newparm, *devp, *sparm;
|
DevParam *newparm, *devp, *sparm;
|
||||||
|
TileType ttype;
|
||||||
|
int dev_type;
|
||||||
char ptype, *pptr, **av;
|
char ptype, *pptr, **av;
|
||||||
char devhash[64];
|
char devhash[64];
|
||||||
int argstart = 1; /* start of terminal list in argv[] */
|
int argstart = 1; /* start of terminal list in argv[] */
|
||||||
|
|
@ -799,9 +802,18 @@ efBuildDevice(def, class, type, r, argc, argv)
|
||||||
|
|
||||||
nterminals = (argc - argstart) / 3;
|
nterminals = (argc - argstart) / 3;
|
||||||
|
|
||||||
/* Determine if this device has been seen before */
|
dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, type);
|
||||||
|
|
||||||
sprintf(devhash, "%dx%d%s", r->r_xbot, r->r_ybot, type);
|
/* Determine if this device has been seen before */
|
||||||
|
/* NOTE: This is done by tile type, not name, because the extresist
|
||||||
|
* device extraction is less sophisticated than the standard extraction
|
||||||
|
* and does not differentiate between different device names belonging
|
||||||
|
* to the same tile type. The extGetDevType() function is not efficient,
|
||||||
|
* and all of this needs to be done better.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ttype = extGetDevType(type);
|
||||||
|
sprintf(devhash, "%dx%d_%d", r->r_xbot, r->r_ybot, ttype);
|
||||||
he = HashFind(&def->def_devs, devhash);
|
he = HashFind(&def->def_devs, devhash);
|
||||||
newdev = (Dev *)HashGetValue(he);
|
newdev = (Dev *)HashGetValue(he);
|
||||||
if (newdev)
|
if (newdev)
|
||||||
|
|
@ -813,10 +825,14 @@ efBuildDevice(def, class, type, r, argc, argv)
|
||||||
*
|
*
|
||||||
* Check that the device is actually the same device type and number
|
* Check that the device is actually the same device type and number
|
||||||
* of terminals. If not, throw an error and abandon the new device.
|
* of terminals. If not, throw an error and abandon the new device.
|
||||||
|
*
|
||||||
|
* NOTE: Quick check is made on dev_type, but for the reason stated
|
||||||
|
* above for the calculation of ttype, only the tile types need to
|
||||||
|
* match, so make an additional (expensive) check on tile type.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((newdev->dev_class != class) ||
|
if ((newdev->dev_class != class) || ((newdev->dev_type != dev_type)
|
||||||
(strcmp(EFDevTypes[newdev->dev_type], type)))
|
&& (ttype != extGetDevType(EFDevTypes[newdev->dev_type]))))
|
||||||
{
|
{
|
||||||
TxError("Device %s %s at (%d, %d) overlaps incompatible device %s %s!\n",
|
TxError("Device %s %s at (%d, %d) overlaps incompatible device %s %s!\n",
|
||||||
extDevTable[class], type, r->r_xbot, r->r_ybot,
|
extDevTable[class], type, r->r_xbot, r->r_ybot,
|
||||||
|
|
@ -849,7 +865,7 @@ efBuildDevice(def, class, type, r, argc, argv)
|
||||||
|
|
||||||
newdev->dev_nterm = nterminals;
|
newdev->dev_nterm = nterminals;
|
||||||
newdev->dev_rect = *r;
|
newdev->dev_rect = *r;
|
||||||
newdev->dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, type);
|
newdev->dev_type = dev_type;
|
||||||
newdev->dev_class = class;
|
newdev->dev_class = class;
|
||||||
|
|
||||||
switch (class)
|
switch (class)
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,7 @@ EFDone()
|
||||||
|
|
||||||
/* Misc cleanup */
|
/* Misc cleanup */
|
||||||
for (n = 0; n < EFDevNumTypes; n++) freeMagic(EFDevTypes[n]);
|
for (n = 0; n < EFDevNumTypes; n++) freeMagic(EFDevTypes[n]);
|
||||||
|
EFDevNumTypes = 0;
|
||||||
|
|
||||||
/* Changed from n = 0 to n = 1; First entry "space" is predefined, */
|
/* Changed from n = 0 to n = 1; First entry "space" is predefined, */
|
||||||
/* not malloc'd. ---Tim 9/3/02 */
|
/* not malloc'd. ---Tim 9/3/02 */
|
||||||
|
|
|
||||||
|
|
@ -342,9 +342,6 @@ extern char *EFHNToStr();
|
||||||
extern int EFGetPortMax();
|
extern int EFGetPortMax();
|
||||||
|
|
||||||
/* ------------------------- constants used by clients -------------- */
|
/* ------------------------- constants used by clients -------------- */
|
||||||
/* This gives us a 32 or 64 dev types which should be ok */
|
|
||||||
#define BITSPERCHAR 8
|
|
||||||
#define MAXDEVTYPES (sizeof(long)*BITSPERCHAR)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ANSI C definitions of arguments to EFvisit procedures
|
* ANSI C definitions of arguments to EFvisit procedures
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ ExtCell(def, outName, doLength)
|
||||||
TxError("Cannot open output file: ");
|
TxError("Cannot open output file: ");
|
||||||
perror(filename);
|
perror(filename);
|
||||||
#endif
|
#endif
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
extNumFatal = extNumWarnings = 0;
|
extNumFatal = extNumWarnings = 0;
|
||||||
|
|
|
||||||
|
|
@ -203,15 +203,32 @@ extHierSubstrate(ha, use, x, y)
|
||||||
|
|
||||||
if (node1 != node2)
|
if (node1 != node2)
|
||||||
{
|
{
|
||||||
/*
|
if (node1->node_len < node2->node_len)
|
||||||
* Both sets of names will now point to node1.
|
{
|
||||||
*/
|
/*
|
||||||
for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next)
|
* Both sets of names will now point to node2.
|
||||||
|
*/
|
||||||
|
for (nn = node1->node_names; nn->nn_next; nn = nn->nn_next)
|
||||||
|
nn->nn_node = node2;
|
||||||
|
nn->nn_node = node2;
|
||||||
|
nn->nn_next = node2->node_names->nn_next;
|
||||||
|
node2->node_names->nn_next = node1->node_names;
|
||||||
|
node2->node_len += node1->node_len;
|
||||||
|
freeMagic((char *)node1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Both sets of names will now point to node1.
|
||||||
|
*/
|
||||||
|
for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next)
|
||||||
nn->nn_node = node1;
|
nn->nn_node = node1;
|
||||||
nn->nn_node = node1;
|
nn->nn_node = node1;
|
||||||
nn->nn_next = node1->node_names;
|
nn->nn_next = node1->node_names;
|
||||||
node1->node_names = node2->node_names;
|
node1->node_names = node2->node_names;
|
||||||
freeMagic((char *) node2);
|
node1->node_len += node2->node_len;
|
||||||
|
freeMagic((char *)node2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
freeMagic(nodeList);
|
freeMagic(nodeList);
|
||||||
}
|
}
|
||||||
|
|
@ -385,17 +402,36 @@ extHierConnectFunc1(oneTile, ha)
|
||||||
|
|
||||||
if (node1 != node2)
|
if (node1 != node2)
|
||||||
{
|
{
|
||||||
/*
|
if (node1->node_len < node2->node_len)
|
||||||
* Both sets of names will now point to node1.
|
{
|
||||||
* We don't need to update node_cap since it
|
/*
|
||||||
* hasn't been computed yet.
|
* Both sets of names will now point to node2.
|
||||||
*/
|
* We don't need to update node_cap since it
|
||||||
for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next)
|
* hasn't been computed yet.
|
||||||
nn->nn_node = node1;
|
*/
|
||||||
nn->nn_node = node1;
|
for (nn = node1->node_names; nn->nn_next; nn = nn->nn_next)
|
||||||
nn->nn_next = node1->node_names;
|
nn->nn_node = node2;
|
||||||
node1->node_names = node2->node_names;
|
nn->nn_node = node2;
|
||||||
freeMagic((char *) node2);
|
nn->nn_next = node2->node_names->nn_next;
|
||||||
|
node2->node_names->nn_next = node1->node_names;
|
||||||
|
node2->node_len += node1->node_len;
|
||||||
|
freeMagic((char *) node1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Both sets of names will now point to node1.
|
||||||
|
* We don't need to update node_cap since it
|
||||||
|
* hasn't been computed yet.
|
||||||
|
*/
|
||||||
|
for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next)
|
||||||
|
nn->nn_node = node1;
|
||||||
|
nn->nn_node = node1;
|
||||||
|
nn->nn_next = node1->node_names;
|
||||||
|
node1->node_names = node2->node_names;
|
||||||
|
node1->node_len += node2->node_len;
|
||||||
|
freeMagic((char *) node2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -470,17 +506,36 @@ extHierConnectFunc2(cum, ha)
|
||||||
|
|
||||||
if (node1 != node2)
|
if (node1 != node2)
|
||||||
{
|
{
|
||||||
/*
|
if (node1->node_len < node2->node_len)
|
||||||
* Both sets of names will now point to node1.
|
{
|
||||||
* We don't need to update node_cap since it
|
/*
|
||||||
* hasn't been computed yet.
|
* Both sets of names will now point to node2.
|
||||||
*/
|
* We don't need to update node_cap since it
|
||||||
for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next)
|
* hasn't been computed yet.
|
||||||
nn->nn_node = node1;
|
*/
|
||||||
nn->nn_node = node1;
|
for (nn = node1->node_names; nn->nn_next; nn = nn->nn_next)
|
||||||
nn->nn_next = node1->node_names;
|
nn->nn_node = node2;
|
||||||
node1->node_names = node2->node_names;
|
nn->nn_node = node2;
|
||||||
freeMagic((char *) node2);
|
nn->nn_next = node2->node_names->nn_next;
|
||||||
|
node2->node_names->nn_next = node1->node_names;
|
||||||
|
node2->node_len += node1->node_len;
|
||||||
|
freeMagic((char *) node1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Both sets of names will now point to node1.
|
||||||
|
* We don't need to update node_cap since it
|
||||||
|
* hasn't been computed yet.
|
||||||
|
*/
|
||||||
|
for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next)
|
||||||
|
nn->nn_node = node1;
|
||||||
|
nn->nn_node = node1;
|
||||||
|
nn->nn_next = node1->node_names;
|
||||||
|
node1->node_names = node2->node_names;
|
||||||
|
node1->node_len += node2->node_len;
|
||||||
|
freeMagic((char *) node2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (r.r_xtop > r.r_xbot && r.r_ytop > r.r_ybot)
|
else if (r.r_xtop > r.r_xbot && r.r_ytop > r.r_ybot)
|
||||||
|
|
@ -553,17 +608,36 @@ extHierConnectFunc3(cum, ha)
|
||||||
|
|
||||||
if (node1 != node2)
|
if (node1 != node2)
|
||||||
{
|
{
|
||||||
/*
|
if (node1->node_len < node2->node_len)
|
||||||
* Both sets of names will now point to node1.
|
{
|
||||||
* We don't need to update node_cap since it
|
/*
|
||||||
* hasn't been computed yet.
|
* Both sets of names will now point to node2.
|
||||||
*/
|
* We don't need to update node_cap since it
|
||||||
for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next)
|
* hasn't been computed yet.
|
||||||
nn->nn_node = node1;
|
*/
|
||||||
nn->nn_node = node1;
|
for (nn = node1->node_names; nn->nn_next; nn = nn->nn_next)
|
||||||
nn->nn_next = node1->node_names;
|
nn->nn_node = node2;
|
||||||
node1->node_names = node2->node_names;
|
nn->nn_node = node2;
|
||||||
freeMagic((char *) node2);
|
nn->nn_next = node2->node_names->nn_next;
|
||||||
|
node2->node_names->nn_next = node1->node_names;
|
||||||
|
node2->node_len += node1->node_len;
|
||||||
|
freeMagic((char *) node1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Both sets of names will now point to node1.
|
||||||
|
* We don't need to update node_cap since it
|
||||||
|
* hasn't been computed yet.
|
||||||
|
*/
|
||||||
|
for (nn = node2->node_names; nn->nn_next; nn = nn->nn_next)
|
||||||
|
nn->nn_node = node1;
|
||||||
|
nn->nn_node = node1;
|
||||||
|
nn->nn_next = node1->node_names;
|
||||||
|
node1->node_names = node2->node_names;
|
||||||
|
node1->node_len += node2->node_len;
|
||||||
|
freeMagic((char *) node2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (r.r_xtop > r.r_xbot && r.r_ytop > r.r_ybot)
|
else if (r.r_xtop > r.r_xbot && r.r_ytop > r.r_ybot)
|
||||||
|
|
@ -810,6 +884,7 @@ extHierNewNode(he)
|
||||||
nn->nn_name = he->h_key.h_name;
|
nn->nn_name = he->h_key.h_name;
|
||||||
node->node_names = nn;
|
node->node_names = nn;
|
||||||
node->node_cap = (CapValue) 0;
|
node->node_cap = (CapValue) 0;
|
||||||
|
node->node_len = 1;
|
||||||
for (n = 0; n < nclasses; n++)
|
for (n = 0; n < nclasses; n++)
|
||||||
node->node_pa[n].pa_perim = node->node_pa[n].pa_area = 0;
|
node->node_pa[n].pa_perim = node->node_pa[n].pa_area = 0;
|
||||||
HashSetValue(he, (char *) nn);
|
HashSetValue(he, (char *) nn);
|
||||||
|
|
|
||||||
|
|
@ -354,54 +354,63 @@ ExtGetDevInfo(idx, devnameptr, devtypeptr, s_rclassptr, d_rclassptr,
|
||||||
if (t == DBNumTypes) return FALSE;
|
if (t == DBNumTypes) return FALSE;
|
||||||
if (devptr == NULL) return FALSE;
|
if (devptr == NULL) return FALSE;
|
||||||
|
|
||||||
*devnameptr = locdname;
|
if (devnameptr) *devnameptr = locdname;
|
||||||
*subnameptr = devptr->exts_deviceSubstrateName;
|
if (subnameptr) *subnameptr = devptr->exts_deviceSubstrateName;
|
||||||
*devtypeptr = t;
|
if (devtypeptr) *devtypeptr = t;
|
||||||
|
|
||||||
tmask = &devptr->exts_deviceSDTypes[0];
|
tmask = &devptr->exts_deviceSDTypes[0];
|
||||||
*s_rclassptr = (short)(-1); /* NO_RESCLASS */
|
if (s_rclassptr)
|
||||||
|
|
||||||
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
|
|
||||||
{
|
{
|
||||||
rmask = &ExtCurStyle->exts_typesByResistClass[n];
|
*s_rclassptr = (short)(-1); /* NO_RESCLASS */
|
||||||
if (TTMaskIntersect(rmask, tmask))
|
|
||||||
{
|
|
||||||
*s_rclassptr = (short)n;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tmask = &devptr->exts_deviceSDTypes[1];
|
|
||||||
if (TTMaskIsZero(tmask))
|
|
||||||
{
|
|
||||||
/* Set source and drain resistance classes to be the same */
|
|
||||||
*d_rclassptr = (short)n;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*d_rclassptr = (short)(-1); /* NO_RESCLASS */
|
|
||||||
|
|
||||||
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
|
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
|
||||||
{
|
{
|
||||||
rmask = &ExtCurStyle->exts_typesByResistClass[n];
|
rmask = &ExtCurStyle->exts_typesByResistClass[n];
|
||||||
if (TTMaskIntersect(rmask, tmask))
|
if (TTMaskIntersect(rmask, tmask))
|
||||||
{
|
{
|
||||||
*d_rclassptr = (short)n;
|
*s_rclassptr = (short)n;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tmask = &devptr->exts_deviceSubstrateTypes;
|
if (d_rclassptr)
|
||||||
*sub_rclassptr = (short)(-1); /* NO_RESCLASS */
|
|
||||||
|
|
||||||
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
|
|
||||||
{
|
{
|
||||||
rmask = &ExtCurStyle->exts_typesByResistClass[n];
|
tmask = &devptr->exts_deviceSDTypes[1];
|
||||||
if (TTMaskIntersect(rmask, tmask))
|
if (TTMaskIsZero(tmask))
|
||||||
{
|
{
|
||||||
*sub_rclassptr = (short)(n);
|
/* Set source and drain resistance classes to be the same */
|
||||||
break;
|
*d_rclassptr = (short)n;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*d_rclassptr = (short)(-1); /* NO_RESCLASS */
|
||||||
|
|
||||||
|
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
|
||||||
|
{
|
||||||
|
rmask = &ExtCurStyle->exts_typesByResistClass[n];
|
||||||
|
if (TTMaskIntersect(rmask, tmask))
|
||||||
|
{
|
||||||
|
*d_rclassptr = (short)n;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sub_rclassptr)
|
||||||
|
{
|
||||||
|
tmask = &devptr->exts_deviceSubstrateTypes;
|
||||||
|
*sub_rclassptr = (short)(-1); /* NO_RESCLASS */
|
||||||
|
|
||||||
|
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
|
||||||
|
{
|
||||||
|
rmask = &ExtCurStyle->exts_typesByResistClass[n];
|
||||||
|
if (TTMaskIntersect(rmask, tmask))
|
||||||
|
{
|
||||||
|
*sub_rclassptr = (short)(n);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -943,6 +943,7 @@ typedef struct node
|
||||||
NodeName *node_names; /* List of names for this node. The first name
|
NodeName *node_names; /* List of names for this node. The first name
|
||||||
* in the list is the "official" node name.
|
* in the list is the "official" node name.
|
||||||
*/
|
*/
|
||||||
|
int node_len; /* Number of entries in node_names */
|
||||||
CapValue node_cap; /* Capacitance to substrate */
|
CapValue node_cap; /* Capacitance to substrate */
|
||||||
PerimArea node_pa[1]; /* Dummy; each node actually has
|
PerimArea node_pa[1]; /* Dummy; each node actually has
|
||||||
* ExtCurStyle->exts_numResistClasses
|
* ExtCurStyle->exts_numResistClasses
|
||||||
|
|
|
||||||
|
|
@ -776,7 +776,7 @@ lefWriteGeometry(tile, cdata)
|
||||||
lefClient *lefdata = (lefClient *)cdata;
|
lefClient *lefdata = (lefClient *)cdata;
|
||||||
FILE *f = lefdata->file;
|
FILE *f = lefdata->file;
|
||||||
float scale = lefdata->oscale;
|
float scale = lefdata->oscale;
|
||||||
char leffmt[6][10];
|
char leffmt[6][16];
|
||||||
TileType ttype, otype = TiGetTypeExact(tile);
|
TileType ttype, otype = TiGetTypeExact(tile);
|
||||||
LefMapping *lefMagicToLefLayer = lefdata->lefMagicMap;
|
LefMapping *lefMagicToLefLayer = lefdata->lefMagicMap;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
MODULE = resis
|
MODULE = resis
|
||||||
MAGICDIR = ..
|
MAGICDIR = ..
|
||||||
SRCS = ResMain.c ResJunct.c ResMakeRes.c ResSimple.c ResPrint.c \
|
SRCS = ResMain.c ResJunct.c ResMakeRes.c ResSimple.c ResPrint.c \
|
||||||
ResReadSim.c ResConDCS.c ResRex.c ResBasic.c ResMerge.c ResChecks.c \
|
ResReadSim.c ResRex.c ResBasic.c ResMerge.c ResChecks.c \
|
||||||
ResFract.c ResUtils.c ResDebug.c
|
ResFract.c ResUtils.c ResDebug.c
|
||||||
|
|
||||||
include ${MAGICDIR}/defs.mak
|
include ${MAGICDIR}/defs.mak
|
||||||
|
|
|
||||||
|
|
@ -43,111 +43,113 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ResSanityChecks(nodename,resistorList,nodeList,devlist)
|
ResSanityChecks(nodename, resistorList, nodeList, devlist)
|
||||||
char *nodename;
|
char *nodename;
|
||||||
resResistor *resistorList;
|
resResistor *resistorList;
|
||||||
resNode *nodeList;
|
resNode *nodeList;
|
||||||
resDevice *devlist;
|
resDevice *devlist;
|
||||||
|
|
||||||
{
|
{
|
||||||
resResistor *resistor;
|
resResistor *resistor;
|
||||||
resNode *node;
|
resNode *node;
|
||||||
resDevice *dev;
|
resDevice *dev;
|
||||||
resElement *rcell;
|
resElement *rcell;
|
||||||
static Stack *resSanityStack = NULL;
|
static Stack *resSanityStack = NULL;
|
||||||
int reached,foundorigin;
|
int reached, foundorigin;
|
||||||
|
|
||||||
if (resSanityStack == NULL)
|
if (resSanityStack == NULL)
|
||||||
{
|
{
|
||||||
resSanityStack = StackNew(64);
|
resSanityStack = StackNew(64);
|
||||||
}
|
}
|
||||||
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)
|
||||||
{
|
{
|
||||||
resistor->rr_status &= ~RES_REACHED_RESISTOR;
|
resistor->rr_status &= ~RES_REACHED_RESISTOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check 1- Are the resistors and nodes all connected? */
|
/* Check: Are the resistors and nodes all connected? */
|
||||||
while (!StackEmpty(resSanityStack))
|
while (!StackEmpty(resSanityStack))
|
||||||
{
|
{
|
||||||
node = (resNode *)STACKPOP(resSanityStack);
|
node = (resNode *)STACKPOP(resSanityStack);
|
||||||
if (node->rn_status & RES_REACHED_NODE) continue;
|
if (node->rn_status & RES_REACHED_NODE) continue;
|
||||||
node->rn_status |= RES_REACHED_NODE;
|
node->rn_status |= RES_REACHED_NODE;
|
||||||
for (rcell = node->rn_re; rcell != NULL; rcell=rcell->re_nextEl)
|
for (rcell = node->rn_re; rcell != NULL; rcell = rcell->re_nextEl)
|
||||||
{
|
{
|
||||||
resistor = rcell->re_thisEl;
|
resistor = rcell->re_thisEl;
|
||||||
if (resistor->rr_status & RES_REACHED_RESISTOR) continue;
|
if (resistor->rr_status & RES_REACHED_RESISTOR) continue;
|
||||||
resistor->rr_status |= RES_REACHED_RESISTOR;
|
resistor->rr_status |= RES_REACHED_RESISTOR;
|
||||||
if (resistor->rr_connection1 != node &&
|
if (resistor->rr_connection1 != node &&
|
||||||
resistor->rr_connection2 != node)
|
resistor->rr_connection2 != node)
|
||||||
{
|
{
|
||||||
TxError("Stray resElement pointer- node %s, pointer %d\n",nodename,rcell);
|
TxError("Stray resElement pointer- node %s, pointer %d\n",
|
||||||
continue;
|
nodename, rcell);
|
||||||
}
|
continue;
|
||||||
if ((resistor->rr_connection1->rn_status & RES_REACHED_NODE) == 0)
|
}
|
||||||
{
|
if ((resistor->rr_connection1->rn_status & RES_REACHED_NODE) == 0)
|
||||||
STACKPUSH((ClientData)resistor->rr_connection1,resSanityStack);
|
{
|
||||||
}
|
STACKPUSH((ClientData)resistor->rr_connection1, resSanityStack);
|
||||||
if ((resistor->rr_connection2->rn_status & RES_REACHED_NODE) == 0)
|
}
|
||||||
{
|
if ((resistor->rr_connection2->rn_status & RES_REACHED_NODE) == 0)
|
||||||
STACKPUSH((ClientData)resistor->rr_connection2,resSanityStack);
|
{
|
||||||
}
|
STACKPUSH((ClientData)resistor->rr_connection2, resSanityStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (resistor = resistorList; resistor != NULL; resistor = resistor->rr_nextResistor)
|
}
|
||||||
{
|
for (resistor = resistorList; resistor != NULL; resistor = resistor->rr_nextResistor)
|
||||||
if ((resistor->rr_status & RES_REACHED_RESISTOR) == 0)
|
{
|
||||||
{
|
if ((resistor->rr_status & RES_REACHED_RESISTOR) == 0)
|
||||||
TxError("Unreached resistor in %s\n",nodename);
|
{
|
||||||
}
|
TxError("Unreached resistor in %s\n", nodename);
|
||||||
resistor->rr_status &= ~RES_REACHED_RESISTOR;
|
}
|
||||||
|
resistor->rr_status &= ~RES_REACHED_RESISTOR;
|
||||||
}
|
}
|
||||||
for (dev = devlist; dev != NULL; dev = dev->rd_nextDev)
|
for (dev = devlist; dev != NULL; dev = dev->rd_nextDev)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (dev->rd_status & RES_DEV_PLUG) continue;
|
if (dev->rd_status & RES_DEV_PLUG) continue;
|
||||||
reached = FALSE;
|
reached = FALSE;
|
||||||
for (i=0;i != dev->rd_nterms;i++)
|
for (i = 0; i != dev->rd_nterms; i++)
|
||||||
{
|
{
|
||||||
if (dev->rd_terminals[i] != NULL)
|
if (dev->rd_terminals[i] != NULL)
|
||||||
{
|
{
|
||||||
reached = TRUE;
|
reached = TRUE;
|
||||||
if ((dev->rd_terminals[i]->rn_status & RES_REACHED_NODE) == 0)
|
if ((dev->rd_terminals[i]->rn_status & RES_REACHED_NODE) == 0)
|
||||||
{
|
{
|
||||||
TxError("Device node %d unreached in %s\n",i,nodename);
|
TxError("Device node %d unreached in %s\n", i, nodename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (reached == 0)
|
if (reached == 0)
|
||||||
{
|
{
|
||||||
TxError("Unreached device in %s at %d %d\n",
|
TxError("Unreached device in %s at %d %d\n",
|
||||||
nodename,
|
nodename,
|
||||||
dev->rd_inside.r_xbot,
|
dev->rd_inside.r_xbot,
|
||||||
dev->rd_inside.r_ybot);
|
dev->rd_inside.r_ybot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foundorigin = 0;
|
foundorigin = 0;
|
||||||
for (node = nodeList; node != NULL; node=node->rn_more)
|
for (node = nodeList; node != NULL; node=node->rn_more)
|
||||||
{
|
{
|
||||||
if ((node->rn_status & RES_REACHED_NODE) == 0)
|
if ((node->rn_status & RES_REACHED_NODE) == 0)
|
||||||
{
|
{
|
||||||
TxError("Unreached node in %s at %d, %d\n",nodename,node->rn_loc.p_x,node->rn_loc.p_y);
|
TxError("Unreached node in %s at %d, %d\n", nodename,
|
||||||
}
|
node->rn_loc.p_x, node->rn_loc.p_y);
|
||||||
node->rn_status &= ~RES_REACHED_NODE;
|
}
|
||||||
if (node->rn_why & RES_NODE_ORIGIN)
|
node->rn_status &= ~RES_REACHED_NODE;
|
||||||
{
|
if (node->rn_why & RES_NODE_ORIGIN)
|
||||||
foundorigin = 1;
|
{
|
||||||
}
|
foundorigin = 1;
|
||||||
}
|
}
|
||||||
if (foundorigin == 0)
|
}
|
||||||
{
|
if (foundorigin == 0)
|
||||||
TxError("Starting node not found in %s\n",nodename);
|
{
|
||||||
}
|
TxError("Starting node not found in %s\n", nodename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,547 +0,0 @@
|
||||||
/* ResConnectDCS.c --
|
|
||||||
*
|
|
||||||
* This contains a slightly modified version of DBTreeCopyConnect.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef lint
|
|
||||||
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/resis/ResConDCS.c,v 1.5 2010/06/24 12:37:56 tim Exp $";
|
|
||||||
#endif /* not lint */
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include "utils/magic.h"
|
|
||||||
#include "utils/geometry.h"
|
|
||||||
#include "utils/geofast.h"
|
|
||||||
#include "tiles/tile.h"
|
|
||||||
#include "utils/hash.h"
|
|
||||||
#include "utils/stack.h"
|
|
||||||
#include "database/database.h"
|
|
||||||
#include "utils/malloc.h"
|
|
||||||
#include "textio/textio.h"
|
|
||||||
#include "extract/extract.h"
|
|
||||||
#include "extract/extractInt.h"
|
|
||||||
#include "utils/signals.h"
|
|
||||||
#include "windows/windows.h"
|
|
||||||
#include "dbwind/dbwind.h"
|
|
||||||
#include "utils/tech.h"
|
|
||||||
#include "textio/txcommands.h"
|
|
||||||
#include "resis/resis.h"
|
|
||||||
|
|
||||||
extern int dbcUnconnectFunc();
|
|
||||||
extern int dbcConnectLabelFunc();
|
|
||||||
extern int dbcConnectFuncDCS();
|
|
||||||
#ifdef ARIEL
|
|
||||||
extern int resSubSearchFunc();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static ResDevTile *DevList = NULL;
|
|
||||||
static TileTypeBitMask DiffTypeBitMask;
|
|
||||||
TileTypeBitMask ResSubsTypeBitMask;
|
|
||||||
|
|
||||||
/* Forward declarations */
|
|
||||||
extern void ResCalcPerimOverlap();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* dbcConnectFuncDCS -- the same as dbcConnectFunc, except that it does
|
|
||||||
* some extra searching around diffusion tiles looking for
|
|
||||||
* devices.
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* Always returns 0 to keep the search from aborting.
|
|
||||||
*
|
|
||||||
* Side effects:
|
|
||||||
* Adds a new record to the current check list. May also add new
|
|
||||||
* ResDevTile structures.
|
|
||||||
*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
dbcConnectFuncDCS(tile, cx)
|
|
||||||
Tile *tile;
|
|
||||||
TreeContext *cx;
|
|
||||||
|
|
||||||
{
|
|
||||||
struct conSrArg2 *csa2;
|
|
||||||
Rect tileArea, *srArea, devArea, newarea;
|
|
||||||
ResDevTile *thisDev;
|
|
||||||
TileTypeBitMask notConnectMask, *connectMask;
|
|
||||||
Tile *tp;
|
|
||||||
TileType t2, t1, loctype, ctype;
|
|
||||||
TileType dinfo = 0;
|
|
||||||
SearchContext *scx = cx->tc_scx;
|
|
||||||
SearchContext scx2;
|
|
||||||
int i, pNum;
|
|
||||||
CellDef *def;
|
|
||||||
ExtDevice *devptr;
|
|
||||||
TerminalPath tpath;
|
|
||||||
char pathstring[FLATTERMSIZE];
|
|
||||||
|
|
||||||
TiToRect(tile, &tileArea);
|
|
||||||
srArea = &scx->scx_area;
|
|
||||||
|
|
||||||
if (((tileArea.r_xbot >= srArea->r_xtop-1) ||
|
|
||||||
(tileArea.r_xtop <= srArea->r_xbot+1)) &&
|
|
||||||
((tileArea.r_ybot >= srArea->r_ytop-1) ||
|
|
||||||
(tileArea.r_ytop <= srArea->r_ybot+1)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
t1 = TiGetType(tile);
|
|
||||||
if TTMaskHasType(&DiffTypeBitMask,t1)
|
|
||||||
{
|
|
||||||
/* left */
|
|
||||||
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp))
|
|
||||||
{
|
|
||||||
t2 = TiGetType(tp);
|
|
||||||
devptr = ExtCurStyle->exts_device[t2];
|
|
||||||
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) &&
|
|
||||||
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1))
|
|
||||||
{
|
|
||||||
TiToRect(tp, &devArea);
|
|
||||||
thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile)));
|
|
||||||
ResCalcPerimOverlap(thisDev,tp);
|
|
||||||
GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area);
|
|
||||||
thisDev->type = TiGetType(tp);
|
|
||||||
thisDev->nextDev = DevList;
|
|
||||||
DevList = thisDev;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*right*/
|
|
||||||
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp))
|
|
||||||
{
|
|
||||||
t2 = TiGetType(tp);
|
|
||||||
devptr = ExtCurStyle->exts_device[t2];
|
|
||||||
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) &&
|
|
||||||
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1))
|
|
||||||
{
|
|
||||||
TiToRect(tp, &devArea);
|
|
||||||
thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile)));
|
|
||||||
GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area);
|
|
||||||
thisDev->type = TiGetType(tp);
|
|
||||||
thisDev->nextDev = DevList;
|
|
||||||
DevList = thisDev;
|
|
||||||
ResCalcPerimOverlap(thisDev,tp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*top*/
|
|
||||||
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp))
|
|
||||||
{
|
|
||||||
t2 = TiGetType(tp);
|
|
||||||
devptr = ExtCurStyle->exts_device[t2];
|
|
||||||
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) &&
|
|
||||||
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1))
|
|
||||||
{
|
|
||||||
TiToRect(tp, &devArea);
|
|
||||||
thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile)));
|
|
||||||
GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area);
|
|
||||||
thisDev->type = TiGetType(tp);
|
|
||||||
thisDev->nextDev = DevList;
|
|
||||||
DevList = thisDev;
|
|
||||||
ResCalcPerimOverlap(thisDev,tp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*bottom */
|
|
||||||
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp))
|
|
||||||
{
|
|
||||||
t2 = TiGetType(tp);
|
|
||||||
devptr = ExtCurStyle->exts_device[t2];
|
|
||||||
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) &&
|
|
||||||
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1))
|
|
||||||
{
|
|
||||||
TiToRect(tp, &devArea);
|
|
||||||
thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile)));
|
|
||||||
GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area);
|
|
||||||
thisDev->type = TiGetType(tp);
|
|
||||||
thisDev->nextDev = DevList;
|
|
||||||
DevList = thisDev;
|
|
||||||
ResCalcPerimOverlap(thisDev,tp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t1)
|
|
||||||
{
|
|
||||||
TiToRect(tile, &devArea);
|
|
||||||
thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile)));
|
|
||||||
ResCalcPerimOverlap(thisDev,tile);
|
|
||||||
GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area);
|
|
||||||
thisDev->type = TiGetType(tile);
|
|
||||||
thisDev->nextDev = DevList;
|
|
||||||
DevList = thisDev;
|
|
||||||
}
|
|
||||||
/* in some cases (primarily bipolar technology), we'll want to extract
|
|
||||||
devices whose substrate terminals are part of the given region.
|
|
||||||
The following does that check. (10-11-88)
|
|
||||||
*/
|
|
||||||
#ifdef ARIEL
|
|
||||||
if (TTMaskHasType(&ResSubsTypeBitMask,t1) && (ResOptionsFlags & ResOpt_DoSubstrate))
|
|
||||||
{
|
|
||||||
TileTypeBitMask *mask = &ExtCurStyle->exts_subsTransistorTypes[t1];
|
|
||||||
|
|
||||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
|
||||||
{
|
|
||||||
if (TTMaskIntersect(&DBPlaneTypes[pNum], mask))
|
|
||||||
{
|
|
||||||
(void)DBSrPaintArea((Tile *) NULL,
|
|
||||||
scx->scx_use->cu_def->cd_planes[pNum],
|
|
||||||
&tileArea,mask,resSubSearchFunc, (ClientData) cx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
GeoTransRect(&scx->scx_trans, &tileArea, &newarea);
|
|
||||||
|
|
||||||
csa2 = (struct conSrArg2 *)cx->tc_filter->tf_arg;
|
|
||||||
GeoClip(&newarea, csa2->csa2_bounds);
|
|
||||||
if (GEO_RECTNULL(&newarea)) return 0;
|
|
||||||
|
|
||||||
loctype = TiGetTypeExact(tile);
|
|
||||||
|
|
||||||
/* Resolve geometric transformations on diagonally-split tiles */
|
|
||||||
|
|
||||||
if (IsSplit(tile))
|
|
||||||
{
|
|
||||||
dinfo = DBTransformDiagonal(loctype, &scx->scx_trans);
|
|
||||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
pNum = cx->tc_plane;
|
|
||||||
connectMask = &csa2->csa2_connect[loctype];
|
|
||||||
|
|
||||||
if (DBIsContact(loctype))
|
|
||||||
{
|
|
||||||
/* The mask of contact types must include all stacked contacts */
|
|
||||||
|
|
||||||
TTMaskZero(¬ConnectMask);
|
|
||||||
TTMaskSetMask(¬ConnectMask, &DBNotConnectTbl[loctype]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TTMaskCom2(¬ConnectMask, connectMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
def = csa2->csa2_use->cu_def;
|
|
||||||
|
|
||||||
if (DBSrPaintNMArea((Tile *) NULL, def->cd_planes[pNum],
|
|
||||||
dinfo, &newarea, ¬ConnectMask, dbcUnconnectFunc,
|
|
||||||
(ClientData)NULL) == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
DBNMPaintPlane(def->cd_planes[pNum], dinfo,
|
|
||||||
&newarea, DBStdPaintTbl(loctype, pNum),
|
|
||||||
(PaintUndoInfo *) NULL);
|
|
||||||
|
|
||||||
/* Check the source def for any labels belonging to this */
|
|
||||||
/* tile area and plane, and add them to the destination */
|
|
||||||
|
|
||||||
scx2 = *csa2->csa2_topscx;
|
|
||||||
scx2.scx_area = newarea;
|
|
||||||
|
|
||||||
pathstring[0] = '\0';
|
|
||||||
tpath.tp_first = tpath.tp_next = pathstring;
|
|
||||||
tpath.tp_last = pathstring + FLATTERMSIZE;
|
|
||||||
|
|
||||||
DBTreeSrLabels(&scx2, connectMask, csa2->csa2_xMask, &tpath,
|
|
||||||
TF_LABEL_ATTACH, dbcConnectLabelFunc,
|
|
||||||
(ClientData)csa2);
|
|
||||||
// DBCellCopyLabels(&scx2, connectMask, csa2->csa2_xMask, csa2->csa2_use, NULL);
|
|
||||||
|
|
||||||
/* Only extend those sides bordering the diagonal tile */
|
|
||||||
|
|
||||||
if (dinfo & TT_DIAGONAL)
|
|
||||||
{
|
|
||||||
if (dinfo & TT_SIDE) /* right */
|
|
||||||
newarea.r_xtop += 1;
|
|
||||||
else /* left */
|
|
||||||
newarea.r_xbot -= 1;
|
|
||||||
if (((dinfo & TT_SIDE) >> 1)
|
|
||||||
== (dinfo & TT_DIRECTION)) /* top */
|
|
||||||
newarea.r_ytop += 1;
|
|
||||||
else /* bottom */
|
|
||||||
newarea.r_ybot -= 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newarea.r_xbot -= 1;
|
|
||||||
newarea.r_ybot -= 1;
|
|
||||||
newarea.r_xtop += 1;
|
|
||||||
newarea.r_ytop += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if any of the last 5 entries has the same type and */
|
|
||||||
/* area. If so, don't duplicate the existing entry. */
|
|
||||||
/* (NOTE: Connect masks are all from the same table, so */
|
|
||||||
/* they can be compared by address, no need for TTMaskEqual)*/
|
|
||||||
|
|
||||||
for (i = csa2->csa2_lasttop; (i >= 0) && (i > csa2->csa2_lasttop - 5); i--)
|
|
||||||
if (connectMask == csa2->csa2_list[i].connectMask)
|
|
||||||
if (GEO_SURROUND(&csa2->csa2_list[i].area, &newarea))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Register the area and connection mask as needing to be processed */
|
|
||||||
|
|
||||||
if (++csa2->csa2_top == CSA2_LIST_SIZE)
|
|
||||||
{
|
|
||||||
/* Reached list size limit---need to enlarge the list */
|
|
||||||
/* Double the size of the list every time we hit the limit */
|
|
||||||
|
|
||||||
conSrArea *newlist;
|
|
||||||
|
|
||||||
newlist = (conSrArea *)mallocMagic(CSA2_LIST_SIZE * sizeof(conSrArea));
|
|
||||||
StackPush((ClientData)csa2->csa2_list, csa2->csa2_stack);
|
|
||||||
csa2->csa2_list = newlist;
|
|
||||||
csa2->csa2_top = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
csa2->csa2_list[csa2->csa2_top].area = newarea;
|
|
||||||
csa2->csa2_list[csa2->csa2_top].connectMask = connectMask;
|
|
||||||
csa2->csa2_list[csa2->csa2_top].dinfo = dinfo;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
*-------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* ResCalcPerimOverlap--
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* None.
|
|
||||||
*
|
|
||||||
* Side Effects:
|
|
||||||
*
|
|
||||||
*-------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
ResCalcPerimOverlap(dev, tile)
|
|
||||||
ResDevTile *dev;
|
|
||||||
Tile *tile;
|
|
||||||
|
|
||||||
{
|
|
||||||
Tile *tp;
|
|
||||||
int t1;
|
|
||||||
int overlap;
|
|
||||||
|
|
||||||
dev->perim = (TOP(tile)-BOTTOM(tile)-LEFT(tile)+RIGHT(tile))<<1;
|
|
||||||
overlap =0;
|
|
||||||
|
|
||||||
t1 = TiGetType(tile);
|
|
||||||
/* left */
|
|
||||||
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp))
|
|
||||||
{
|
|
||||||
if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]),TiGetType(tp))
|
|
||||||
{
|
|
||||||
overlap += MIN(TOP(tile),TOP(tp))-
|
|
||||||
MAX(BOTTOM(tile),BOTTOM(tp));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
/*right*/
|
|
||||||
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp))
|
|
||||||
{
|
|
||||||
if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]),TiGetType(tp))
|
|
||||||
{
|
|
||||||
overlap += MIN(TOP(tile),TOP(tp))-
|
|
||||||
MAX(BOTTOM(tile),BOTTOM(tp));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
/*top*/
|
|
||||||
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp))
|
|
||||||
{
|
|
||||||
if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]),TiGetType(tp))
|
|
||||||
{
|
|
||||||
overlap += MIN(RIGHT(tile),RIGHT(tp))-
|
|
||||||
MAX(LEFT(tile),LEFT(tp));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
/*bottom */
|
|
||||||
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp))
|
|
||||||
{
|
|
||||||
if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]),TiGetType(tp))
|
|
||||||
{
|
|
||||||
overlap += MIN(RIGHT(tile),RIGHT(tp))-
|
|
||||||
MAX(LEFT(tile),LEFT(tp));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
dev->overlap = overlap;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* DBTreeCopyConnectDCS --
|
|
||||||
*
|
|
||||||
* Basically the same as DBTreeCopyConnect, except it calls
|
|
||||||
* dbcConnectFuncDCS.
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* Linked list of devices.
|
|
||||||
*
|
|
||||||
* Side effects:
|
|
||||||
* The contents of the result cell are modified.
|
|
||||||
*
|
|
||||||
* ----------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
ResDevTile *
|
|
||||||
DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse)
|
|
||||||
SearchContext *scx;
|
|
||||||
TileTypeBitMask *mask;
|
|
||||||
int xMask;
|
|
||||||
TileTypeBitMask *connect;
|
|
||||||
Rect *area;
|
|
||||||
CellUse *destUse;
|
|
||||||
|
|
||||||
{
|
|
||||||
static int first = 1;
|
|
||||||
struct conSrArg2 csa2;
|
|
||||||
int dev, pNum;
|
|
||||||
char *dev_name;
|
|
||||||
TileTypeBitMask *newmask;
|
|
||||||
ResDevTile *CurrentT;
|
|
||||||
CellDef *def = destUse->cu_def;
|
|
||||||
TileType newtype;
|
|
||||||
ExtDevice *devptr;
|
|
||||||
|
|
||||||
csa2.csa2_use = destUse;
|
|
||||||
csa2.csa2_xMask = xMask;
|
|
||||||
csa2.csa2_bounds = area;
|
|
||||||
csa2.csa2_connect = connect;
|
|
||||||
csa2.csa2_topscx = scx;
|
|
||||||
|
|
||||||
csa2.csa2_list = (conSrArea *)mallocMagic(CSA2_LIST_SIZE * sizeof(conSrArea));
|
|
||||||
csa2.csa2_top = -1;
|
|
||||||
csa2.csa2_lasttop = -1;
|
|
||||||
|
|
||||||
csa2.csa2_stack = StackNew(100);
|
|
||||||
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
TTMaskZero(&DiffTypeBitMask);
|
|
||||||
TTMaskZero(&ResSubsTypeBitMask);
|
|
||||||
for (dev = TT_TECHDEPBASE; dev < TT_MAXTYPES; dev++)
|
|
||||||
{
|
|
||||||
devptr = ExtCurStyle->exts_device[dev];
|
|
||||||
if ((devptr != NULL) && ((dev_name = devptr->exts_deviceName) != NULL)
|
|
||||||
&& (strcmp(dev_name, "None")))
|
|
||||||
{
|
|
||||||
TTMaskSetMask(&DiffTypeBitMask,
|
|
||||||
&(devptr->exts_deviceSDTypes[0]));
|
|
||||||
TTMaskSetMask(&ResSubsTypeBitMask,
|
|
||||||
&(devptr->exts_deviceSubstrateTypes));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DevList = NULL;
|
|
||||||
DBTreeSrTiles(scx, mask, xMask, dbcConnectFuncDCS, (ClientData) &csa2);
|
|
||||||
while (csa2.csa2_top >= 0)
|
|
||||||
{
|
|
||||||
newmask = csa2.csa2_list[csa2.csa2_top].connectMask;
|
|
||||||
scx->scx_area = csa2.csa2_list[csa2.csa2_top].area;
|
|
||||||
newtype = csa2.csa2_list[csa2.csa2_top].dinfo;
|
|
||||||
if (csa2.csa2_top == 0)
|
|
||||||
{
|
|
||||||
if (StackLook(csa2.csa2_stack) != (ClientData)NULL)
|
|
||||||
{
|
|
||||||
freeMagic(csa2.csa2_list);
|
|
||||||
csa2.csa2_list = (conSrArea *)StackPop(csa2.csa2_stack);
|
|
||||||
csa2.csa2_top = CSA2_LIST_SIZE - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
csa2.csa2_top--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
csa2.csa2_top--;
|
|
||||||
|
|
||||||
csa2.csa2_lasttop = csa2.csa2_top;
|
|
||||||
|
|
||||||
if (newtype & TT_DIAGONAL)
|
|
||||||
DBTreeSrNMTiles(scx, newtype, newmask, xMask, dbcConnectFuncDCS,
|
|
||||||
(ClientData) &csa2);
|
|
||||||
else
|
|
||||||
DBTreeSrTiles(scx, newmask, xMask, dbcConnectFuncDCS, (ClientData) &csa2);
|
|
||||||
}
|
|
||||||
freeMagic((char *)csa2.csa2_list);
|
|
||||||
StackFree(csa2.csa2_stack);
|
|
||||||
|
|
||||||
for (CurrentT = DevList; CurrentT != NULL; CurrentT=CurrentT->nextDev)
|
|
||||||
{
|
|
||||||
TileType t = CurrentT->type;
|
|
||||||
TileType nt;
|
|
||||||
TileTypeBitMask *residues = DBResidueMask(t);
|
|
||||||
|
|
||||||
for (nt = TT_TECHDEPBASE; nt < DBNumTypes; nt++)
|
|
||||||
{
|
|
||||||
if (TTMaskHasType(residues, nt))
|
|
||||||
{
|
|
||||||
pNum = DBPlane(nt);
|
|
||||||
DBPaintPlane(def->cd_planes[pNum], &CurrentT->area,
|
|
||||||
DBStdPaintTbl(nt, pNum), (PaintUndoInfo *) NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DBReComputeBbox(def);
|
|
||||||
return(DevList);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ARIEL
|
|
||||||
/*
|
|
||||||
*-------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* resSubSearchFunc --
|
|
||||||
*
|
|
||||||
* called when DBSrPaintArea finds a device within
|
|
||||||
* a substrate area.
|
|
||||||
*
|
|
||||||
* Results:
|
|
||||||
* Always return 0 to keep the search alive.
|
|
||||||
*
|
|
||||||
* Side Effects:
|
|
||||||
*
|
|
||||||
*-------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
resSubSearchFunc(tile,cx)
|
|
||||||
Tile *tile;
|
|
||||||
TreeContext *cx;
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
ResDevTile *thisDev;
|
|
||||||
Rect devArea;
|
|
||||||
TileType t = TiGetType(tile);
|
|
||||||
ExtDevice *devptr;
|
|
||||||
|
|
||||||
/* Right now, we're only going to extract substrate terminals for
|
|
||||||
devices with only one diffusion terminal, principally bipolar
|
|
||||||
devices.
|
|
||||||
*/
|
|
||||||
devptr = ExtCurStyle->exts_device[t]
|
|
||||||
if (devptr->exts_deviceSDCount >1) return 0;
|
|
||||||
TiToRect(tile, &devArea);
|
|
||||||
thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile)));
|
|
||||||
GeoTransRect(&cx->tc_scx->scx_trans, &devArea, &thisDev->area);
|
|
||||||
thisDev->type = t;
|
|
||||||
thisDev->nextDev = DevList;
|
|
||||||
DevList = thisDev;
|
|
||||||
ResCalcPerimOverlap(thisDev,tile);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* ARIEL */
|
|
||||||
|
|
@ -46,17 +46,16 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ResPrintNodeList(fp,list)
|
ResPrintNodeList(fp, list)
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
resNode *list;
|
resNode *list;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
for (; list != NULL; list = list->rn_more)
|
for (; list != NULL; list = list->rn_more)
|
||||||
{
|
{
|
||||||
fprintf(fp, "node %p: (%d %d) r= %d\n",
|
fprintf(fp, "node %p: (%d %d) r= %d\n",
|
||||||
list,list->rn_loc.p_x,list->rn_loc.p_y,list->rn_noderes);
|
list, list->rn_loc.p_x, list->rn_loc.p_y, list->rn_noderes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -73,7 +72,7 @@ ResPrintNodeList(fp,list)
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ResPrintResistorList(fp,list)
|
ResPrintResistorList(fp, list)
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
resResistor *list;
|
resResistor *list;
|
||||||
|
|
||||||
|
|
@ -112,9 +111,9 @@ ResPrintResistorList(fp,list)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ResPrintDeviceList(fp,list)
|
ResPrintDeviceList(fp, list)
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
resDevice *list;
|
resDevice *list;
|
||||||
|
|
||||||
{
|
{
|
||||||
static char termtype[] = {'g','s','d','c'};
|
static char termtype[] = {'g','s','d','c'};
|
||||||
|
|
|
||||||
565
resis/ResFract.c
565
resis/ResFract.c
|
|
@ -81,31 +81,30 @@ enumerate:
|
||||||
if (SigInterruptPending)
|
if (SigInterruptPending)
|
||||||
return (1);
|
return (1);
|
||||||
|
|
||||||
if ((tt=TiGetType(resSrTile)) != TT_SPACE)
|
if ((tt = TiGetType(resSrTile)) != TT_SPACE)
|
||||||
{
|
{
|
||||||
resTopTile = RT(resSrTile);
|
resTopTile = RT(resSrTile);
|
||||||
while (RIGHT(resTopTile) > LEFT(resSrTile))
|
while (RIGHT(resTopTile) > LEFT(resSrTile))
|
||||||
{
|
{
|
||||||
TileType ntt = TiGetType(resTopTile);
|
TileType ntt = TiGetType(resTopTile);
|
||||||
|
|
||||||
if (ntt != tt)
|
|
||||||
{
|
|
||||||
resTopTile=BL(resTopTile);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* ok, we may have found a concave corner */
|
|
||||||
ResCheckConcavity(resSrTile,resTopTile,tt);
|
|
||||||
if (resTopTile == NULL) break;
|
|
||||||
if (BOTTOM(resTopTile) != TOP(resSrTile))
|
|
||||||
{
|
|
||||||
resTopTile = RT(resSrTile);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
resTopTile=BL(resTopTile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (ntt != tt)
|
||||||
|
{
|
||||||
|
resTopTile = BL(resTopTile);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
/* ok, we may have found a concave corner */
|
||||||
|
ResCheckConcavity(resSrTile, resTopTile, tt);
|
||||||
|
if (resTopTile == NULL) break;
|
||||||
|
if (BOTTOM(resTopTile) != TOP(resSrTile))
|
||||||
|
{
|
||||||
|
resTopTile = RT(resSrTile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resTopTile=BL(resTopTile);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tpnew = TR(resSrTile);
|
tpnew = TR(resSrTile);
|
||||||
|
|
@ -134,7 +133,8 @@ enumerate:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At left edge -- walk down to next tile along the left edge */
|
/* At left edge -- walk down to next tile along the left edge */
|
||||||
for (resSrTile = LB(resSrTile); RIGHT(resSrTile) <= rect->r_xbot; resSrTile = TR(resSrTile))
|
for (resSrTile = LB(resSrTile); RIGHT(resSrTile) <= rect->r_xbot;
|
||||||
|
resSrTile = TR(resSrTile))
|
||||||
/* Nothing */;
|
/* Nothing */;
|
||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
|
|
@ -157,88 +157,96 @@ enumerate:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ResCheckConcavity(bot,top,tt)
|
ResCheckConcavity(bot, top, tt)
|
||||||
Tile *bot,*top;
|
Tile *bot, *top;
|
||||||
TileType tt;
|
TileType tt;
|
||||||
|
|
||||||
{
|
{
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
int xlen,ylen;
|
int xlen, ylen;
|
||||||
/* corner #1:
|
|
||||||
XXXXXXX
|
/* corner #1:
|
||||||
YYYYYYY
|
* XXXXXXX
|
||||||
^--here
|
* YYYYYYY
|
||||||
*/
|
* ^--here
|
||||||
if (RIGHT(top) > RIGHT(bot) && TiGetType(TR(bot)) != tt)
|
|
||||||
{
|
|
||||||
int xpos = RIGHT(bot);
|
|
||||||
int ypos = BOTTOM(top);
|
|
||||||
xlen = xpos - resWalkleft(top,tt,xpos,ypos,NULL);
|
|
||||||
ylen = resWalkup(top,tt,xpos,ypos,NULL) - ypos;
|
|
||||||
if (xlen > ylen)
|
|
||||||
{
|
|
||||||
(void) resWalkup(top,tt,xpos,ypos,ResSplitX);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (resTopTile == NULL) return;
|
|
||||||
/* corner #2:
|
|
||||||
v--here
|
|
||||||
XXXXXXX
|
|
||||||
YYYYYYY
|
|
||||||
*/
|
|
||||||
if (RIGHT(top) < RIGHT(bot))
|
|
||||||
{
|
|
||||||
for (tp = TR(top);BOTTOM(tp) > BOTTOM(top);tp=LB(tp));
|
|
||||||
if (TiGetType(tp) != tt)
|
|
||||||
{
|
|
||||||
int xpos = RIGHT(top);
|
|
||||||
int ypos = BOTTOM(top);
|
|
||||||
xlen = xpos-resWalkleft(top,tt,xpos,ypos,NULL);
|
|
||||||
ylen = ypos-resWalkdown(bot,tt,xpos,ypos,NULL);
|
|
||||||
if (xlen > ylen)
|
|
||||||
{
|
|
||||||
(void) resWalkdown(bot,tt,xpos,ypos,ResSplitX);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (resTopTile == NULL) return;
|
|
||||||
/* corner #3:
|
|
||||||
XXXXXXX
|
|
||||||
YYYYYYY
|
|
||||||
^--here
|
|
||||||
*/
|
|
||||||
if (LEFT(top) < LEFT(bot))
|
|
||||||
{
|
|
||||||
for (tp = BL(bot);TOP(tp) < TOP(bot);tp=RT(tp));
|
|
||||||
if (TiGetType(tp) != tt)
|
|
||||||
{
|
|
||||||
int xpos = LEFT(bot);
|
|
||||||
int ypos = BOTTOM(top);
|
|
||||||
xlen = resWalkright(top,tt,xpos,ypos,NULL)- xpos;
|
|
||||||
ylen = resWalkup(top,tt,xpos,ypos,NULL) - ypos;
|
|
||||||
if (xlen > ylen)
|
|
||||||
{
|
|
||||||
(void) resWalkup(top,tt,xpos,ypos,ResSplitX);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (resTopTile == NULL) return;
|
|
||||||
/* corner #4:
|
|
||||||
v--here
|
|
||||||
XXXXXXX
|
|
||||||
YYYYYYY
|
|
||||||
*/
|
*/
|
||||||
if (LEFT(top) > LEFT(bot) && TiGetType(BL(top)) != tt)
|
|
||||||
{
|
if (RIGHT(top) > RIGHT(bot) && TiGetType(TR(bot)) != tt)
|
||||||
int xpos = LEFT(top);
|
{
|
||||||
int ypos = BOTTOM(top);
|
int xpos = RIGHT(bot);
|
||||||
xlen = resWalkright(top,tt,xpos,ypos,NULL)- xpos;
|
int ypos = BOTTOM(top);
|
||||||
ylen = ypos-resWalkdown(bot,tt,xpos,ypos,NULL);
|
xlen = xpos - resWalkleft(top, tt, xpos, ypos, NULL);
|
||||||
if (xlen > ylen)
|
ylen = resWalkup(top, tt, xpos, ypos, NULL) - ypos;
|
||||||
{
|
if (xlen > ylen)
|
||||||
(void) resWalkdown(bot,tt,xpos,ypos,ResSplitX);
|
{
|
||||||
}
|
(void) resWalkup(top, tt, xpos, ypos, ResSplitX);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (resTopTile == NULL) return;
|
||||||
|
|
||||||
|
/* corner #2:
|
||||||
|
* v--here
|
||||||
|
* XXXXXXX
|
||||||
|
* YYYYYYY
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (RIGHT(top) < RIGHT(bot))
|
||||||
|
{
|
||||||
|
for (tp = TR(top); BOTTOM(tp) > BOTTOM(top); tp = LB(tp));
|
||||||
|
if (TiGetType(tp) != tt)
|
||||||
|
{
|
||||||
|
int xpos = RIGHT(top);
|
||||||
|
int ypos = BOTTOM(top);
|
||||||
|
xlen = xpos - resWalkleft(top, tt, xpos, ypos, NULL);
|
||||||
|
ylen = ypos - resWalkdown(bot, tt, xpos, ypos, NULL);
|
||||||
|
if (xlen > ylen)
|
||||||
|
{
|
||||||
|
(void) resWalkdown(bot,tt,xpos,ypos,ResSplitX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resTopTile == NULL) return;
|
||||||
|
|
||||||
|
/* corner #3:
|
||||||
|
* XXXXXXX
|
||||||
|
* YYYYYYY
|
||||||
|
* ^--here
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (LEFT(top) < LEFT(bot))
|
||||||
|
{
|
||||||
|
for (tp = BL(bot); TOP(tp) < TOP(bot); tp = RT(tp));
|
||||||
|
if (TiGetType(tp) != tt)
|
||||||
|
{
|
||||||
|
int xpos = LEFT(bot);
|
||||||
|
int ypos = BOTTOM(top);
|
||||||
|
xlen = resWalkright(top, tt, xpos, ypos, NULL) - xpos;
|
||||||
|
ylen = resWalkup(top, tt, xpos, ypos, NULL) - ypos;
|
||||||
|
if (xlen > ylen)
|
||||||
|
{
|
||||||
|
(void) resWalkup(top, tt, xpos, ypos, ResSplitX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resTopTile == NULL) return;
|
||||||
|
|
||||||
|
/* corner #4:
|
||||||
|
* v--here
|
||||||
|
* XXXXXXX
|
||||||
|
* YYYYYYY
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (LEFT(top) > LEFT(bot) && TiGetType(BL(top)) != tt)
|
||||||
|
{
|
||||||
|
int xpos = LEFT(top);
|
||||||
|
int ypos = BOTTOM(top);
|
||||||
|
xlen = resWalkright(top, tt, xpos, ypos, NULL) - xpos;
|
||||||
|
ylen = ypos - resWalkdown(bot, tt, xpos, ypos, NULL);
|
||||||
|
if (xlen > ylen)
|
||||||
|
{
|
||||||
|
(void) resWalkdown(bot, tt, xpos, ypos, ResSplitX);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -259,151 +267,151 @@ ResCheckConcavity(bot,top,tt)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
resWalkup(tile,tt,xpos,ypos,func)
|
resWalkup(tile, tt, xpos, ypos, func)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
TileType tt;
|
TileType tt;
|
||||||
int xpos,ypos;
|
int xpos,ypos;
|
||||||
Tile * (*func)();
|
Tile * (*func)();
|
||||||
|
|
||||||
{
|
{
|
||||||
Point pt;
|
Point pt;
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
|
|
||||||
pt.p_x = xpos;
|
pt.p_x = xpos;
|
||||||
while (TiGetType(tile) == tt)
|
while (TiGetType(tile) == tt)
|
||||||
{
|
{
|
||||||
if (xpos == LEFT(tile))
|
if (xpos == LEFT(tile))
|
||||||
{
|
{
|
||||||
/* walk up left edge */
|
/* walk up left edge */
|
||||||
for (tp = BL(tile);TOP(tp) <= ypos;tp=RT(tp));
|
for (tp = BL(tile); TOP(tp) <= ypos; tp = RT(tp));
|
||||||
for (;BOTTOM(tp) < TOP(tile);tp=RT(tp))
|
for (; BOTTOM(tp) < TOP(tile); tp = RT(tp))
|
||||||
{
|
{
|
||||||
if (TiGetType(tp) != tt) return(BOTTOM(tp));
|
if (TiGetType(tp) != tt) return(BOTTOM(tp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (func) tile = (*func)(tile,xpos);
|
if (func) tile = (*func)(tile,xpos);
|
||||||
}
|
}
|
||||||
pt.p_y = TOP(tile);
|
pt.p_y = TOP(tile);
|
||||||
GOTOPOINT(tile,&pt);
|
GOTOPOINT(tile, &pt);
|
||||||
}
|
}
|
||||||
return(BOTTOM(tile));
|
return(BOTTOM(tile));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
resWalkdown(tile,tt,xpos,ypos,func)
|
resWalkdown(tile, tt, xpos, ypos, func)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
TileType tt;
|
TileType tt;
|
||||||
int xpos,ypos;
|
int xpos, ypos;
|
||||||
Tile * (*func)();
|
Tile * (*func)();
|
||||||
|
|
||||||
{
|
{
|
||||||
Point pt;
|
Point pt;
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
Tile *endt;
|
Tile *endt;
|
||||||
|
|
||||||
pt.p_x = xpos;
|
pt.p_x = xpos;
|
||||||
while (TiGetType(tile) == tt)
|
while (TiGetType(tile) == tt)
|
||||||
{
|
{
|
||||||
if (xpos == LEFT(tile))
|
if (xpos == LEFT(tile))
|
||||||
{
|
{
|
||||||
/* walk up left edge */
|
/* walk up left edge */
|
||||||
endt = NULL;
|
endt = NULL;
|
||||||
for (tp = BL(tile);BOTTOM(tp) < TOP(tile);tp=RT(tp))
|
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
|
||||||
{
|
{
|
||||||
if (TiGetType(tp) != tt)
|
if (TiGetType(tp) != tt)
|
||||||
{
|
{
|
||||||
if (BOTTOM(tp) < ypos) endt = tp;
|
if (BOTTOM(tp) < ypos) endt = tp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (endt)
|
if (endt)
|
||||||
{
|
{
|
||||||
return TOP(endt);
|
return TOP(endt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (func) tile = (*func)(tile,xpos);
|
if (func) tile = (*func)(tile, xpos);
|
||||||
}
|
}
|
||||||
pt.p_y = BOTTOM(tile)-1;
|
pt.p_y = BOTTOM(tile) - 1;
|
||||||
GOTOPOINT(tile,&pt);
|
GOTOPOINT(tile, &pt);
|
||||||
}
|
}
|
||||||
return(TOP(tile));
|
return(TOP(tile));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
resWalkright(tile,tt,xpos,ypos,func)
|
resWalkright(tile, tt, xpos, ypos, func)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
TileType tt;
|
TileType tt;
|
||||||
int xpos,ypos;
|
int xpos, ypos;
|
||||||
Tile * (*func)();
|
Tile * (*func)();
|
||||||
|
|
||||||
{
|
{
|
||||||
Point pt;
|
Point pt;
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
|
|
||||||
pt.p_y = ypos;
|
pt.p_y = ypos;
|
||||||
while (TiGetType(tile) == tt)
|
while (TiGetType(tile) == tt)
|
||||||
{
|
{
|
||||||
if (ypos == BOTTOM(tile))
|
if (ypos == BOTTOM(tile))
|
||||||
{
|
{
|
||||||
/* walk along bottom edge */
|
/* walk along bottom edge */
|
||||||
for (tp = LB(tile);LEFT(tp) < xpos;tp=TR(tp));
|
for (tp = LB(tile); LEFT(tp) < xpos; tp = TR(tp));
|
||||||
for (;LEFT(tp) < RIGHT(tile);tp=TR(tp))
|
for (; LEFT(tp) < RIGHT(tile); tp = TR(tp))
|
||||||
{
|
{
|
||||||
if (TiGetType(tp) != tt) return(LEFT(tp));
|
if (TiGetType(tp) != tt) return(LEFT(tp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (func) tile = (*func)(tile,ypos);
|
if (func) tile = (*func)(tile, ypos);
|
||||||
}
|
}
|
||||||
pt.p_x = RIGHT(tile);
|
pt.p_x = RIGHT(tile);
|
||||||
GOTOPOINT(tile,&pt);
|
GOTOPOINT(tile, &pt);
|
||||||
}
|
}
|
||||||
return(LEFT(tile));
|
return(LEFT(tile));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
resWalkleft(tile,tt,xpos,ypos,func)
|
resWalkleft(tile, tt, xpos, ypos, func)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
TileType tt;
|
TileType tt;
|
||||||
int xpos,ypos;
|
int xpos, ypos;
|
||||||
Tile * (*func)();
|
Tile * (*func)();
|
||||||
|
|
||||||
{
|
{
|
||||||
Point pt;
|
Point pt;
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
Tile *endt;
|
Tile *endt;
|
||||||
|
|
||||||
pt.p_y = ypos;
|
pt.p_y = ypos;
|
||||||
while (TiGetType(tile) == tt)
|
while (TiGetType(tile) == tt)
|
||||||
{
|
{
|
||||||
if (ypos == BOTTOM(tile))
|
if (ypos == BOTTOM(tile))
|
||||||
{
|
{
|
||||||
/* walk along bottom edge */
|
/* walk along bottom edge */
|
||||||
endt = NULL;
|
endt = NULL;
|
||||||
for (tp = LB(tile);LEFT(tp) < RIGHT(tile);tp=TR(tp))
|
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
|
||||||
{
|
{
|
||||||
if (TiGetType(tp) != tt)
|
if (TiGetType(tp) != tt)
|
||||||
{
|
{
|
||||||
if (LEFT(tp) < xpos) endt = tp;
|
if (LEFT(tp) < xpos) endt = tp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (endt)
|
if (endt)
|
||||||
{
|
{
|
||||||
return RIGHT(endt);
|
return RIGHT(endt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (func) tile = (*func)(tile,ypos);
|
if (func) tile = (*func)(tile, ypos);
|
||||||
}
|
}
|
||||||
pt.p_x = LEFT(tile)-1;
|
pt.p_x = LEFT(tile) - 1;
|
||||||
GOTOPOINT(tile,&pt);
|
GOTOPOINT(tile, &pt);
|
||||||
}
|
}
|
||||||
return(RIGHT(tile));
|
return(RIGHT(tile));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -419,59 +427,60 @@ resWalkleft(tile,tt,xpos,ypos,func)
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Tile *
|
Tile *
|
||||||
ResSplitX(tile,x)
|
ResSplitX(tile, x)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
{
|
{
|
||||||
TileType tt = TiGetType(tile);
|
TileType tt = TiGetType(tile);
|
||||||
Tile *tp = TiSplitX(tile,x);
|
Tile *tp = TiSplitX(tile, x);
|
||||||
Tile *tp2;
|
Tile *tp2;
|
||||||
|
|
||||||
TiSetBody(tp,tt);
|
TiSetBody(tp,tt);
|
||||||
/* check to see if we can combine with the tiles above or below us */
|
/* check to see if we can combine with the tiles above or below us */
|
||||||
tp2 = RT(tile);
|
tp2 = RT(tile);
|
||||||
if (TiGetType(tp2) == tt && LEFT(tp2) == LEFT(tile) && RIGHT(tp2) == RIGHT(tile))
|
if (TiGetType(tp2) == tt && LEFT(tp2) == LEFT(tile) && RIGHT(tp2) == RIGHT(tile))
|
||||||
{
|
{
|
||||||
if (tp2 == resSrTile)
|
if (tp2 == resSrTile)
|
||||||
{
|
{
|
||||||
if (resTopTile == tile) resTopTile = NULL;
|
if (resTopTile == tile) resTopTile = NULL;
|
||||||
TiJoinY(tp2,tile,resFracPlane);
|
TiJoinY(tp2, tile, resFracPlane);
|
||||||
tile = tp2;
|
tile = tp2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (resTopTile == tp2) resTopTile = NULL;
|
if (resTopTile == tp2) resTopTile = NULL;
|
||||||
TiJoinY(tile,tp2,resFracPlane);
|
TiJoinY(tile, tp2, resFracPlane);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tp2 = LB(tile);
|
tp2 = LB(tile);
|
||||||
if (TiGetType(tp2) == tt && LEFT(tp2) == LEFT(tile) && RIGHT(tp2) == RIGHT(tile))
|
if (TiGetType(tp2) == tt && LEFT(tp2) == LEFT(tile) && RIGHT(tp2) == RIGHT(tile))
|
||||||
{
|
{
|
||||||
if (tp2 == resSrTile)
|
if (tp2 == resSrTile)
|
||||||
{
|
{
|
||||||
if (resTopTile == tile) resTopTile = NULL;
|
if (resTopTile == tile) resTopTile = NULL;
|
||||||
TiJoinY(tp2,tile,resFracPlane);
|
TiJoinY(tp2, tile, resFracPlane);
|
||||||
tile = tp2;
|
tile = tp2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (resTopTile == tp2) resTopTile = NULL;
|
if (resTopTile == tp2) resTopTile = NULL;
|
||||||
TiJoinY(tile,tp2,resFracPlane);
|
TiJoinY(tile, tp2, resFracPlane);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* do the same checks with the newly created tile */
|
/* do the same checks with the newly created tile */
|
||||||
tp2 = RT(tp);
|
tp2 = RT(tp);
|
||||||
if (TiGetType(tp2) == tt && LEFT(tp2) == LEFT(tp) && RIGHT(tp2) == RIGHT(tp))
|
if (TiGetType(tp2) == tt && LEFT(tp2) == LEFT(tp) && RIGHT(tp2) == RIGHT(tp))
|
||||||
{
|
{
|
||||||
TiJoinY(tp2,tp,resFracPlane);
|
TiJoinY(tp2, tp, resFracPlane);
|
||||||
tp = tp2;
|
tp = tp2;
|
||||||
}
|
}
|
||||||
tp2 = LB(tp);
|
tp2 = LB(tp);
|
||||||
if (TiGetType(tp2) == tt && LEFT(tp2) == LEFT(tp) && RIGHT(tp2) == RIGHT(tp))
|
if (TiGetType(tp2) == tt && LEFT(tp2) == LEFT(tp) && RIGHT(tp2) == RIGHT(tp))
|
||||||
{
|
{
|
||||||
TiJoinY(tp2,tp,resFracPlane);
|
TiJoinY(tp2, tp, resFracPlane);
|
||||||
}
|
}
|
||||||
return tile;
|
return tile;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
158
resis/ResJunct.c
158
resis/ResJunct.c
|
|
@ -26,8 +26,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "textio/txcommands.h"
|
#include "textio/txcommands.h"
|
||||||
#include "resis/resis.h"
|
#include "resis/resis.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -45,56 +43,56 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ResNewSDDevice(tile,tp,xj,yj,direction,PendingList)
|
ResNewSDDevice(tile, tp, xj, yj, direction, PendingList)
|
||||||
Tile *tile,*tp;
|
Tile *tile, *tp;
|
||||||
int xj,yj,direction;
|
int xj, yj, direction;
|
||||||
resNode **PendingList;
|
resNode **PendingList;
|
||||||
{
|
{
|
||||||
resNode *resptr;
|
resNode *resptr;
|
||||||
resDevice *resDev;
|
resDevice *resDev;
|
||||||
tElement *tcell;
|
tElement *tcell;
|
||||||
int newnode;
|
int newnode;
|
||||||
tileJunk *j;
|
tileJunk *j;
|
||||||
|
|
||||||
newnode = FALSE;
|
newnode = FALSE;
|
||||||
j = (tileJunk *) tp->ti_client;
|
j = (tileJunk *) tp->ti_client;
|
||||||
resDev = j->deviceList;
|
resDev = j->deviceList;
|
||||||
if ((j->sourceEdge & direction) != 0)
|
if ((j->sourceEdge & direction) != 0)
|
||||||
|
{
|
||||||
|
if (resDev->rd_fet_source == (resNode *) NULL)
|
||||||
{
|
{
|
||||||
if (resDev->rd_fet_source == (resNode *) NULL)
|
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
||||||
{
|
newnode = TRUE;
|
||||||
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
resDev->rd_fet_source = resptr;
|
||||||
newnode = TRUE;
|
|
||||||
resDev->rd_fet_source = resptr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
resptr = resDev->rd_fet_source;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (resDev->rd_fet_drain == (resNode *) NULL)
|
resptr = resDev->rd_fet_source;
|
||||||
{
|
|
||||||
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
|
||||||
newnode = TRUE;
|
|
||||||
resDev->rd_fet_drain = resptr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
resptr = resDev->rd_fet_drain;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (newnode)
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (resDev->rd_fet_drain == (resNode *) NULL)
|
||||||
{
|
{
|
||||||
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
|
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
||||||
tcell->te_nextt = NULL;
|
newnode = TRUE;
|
||||||
tcell->te_thist = j->deviceList;
|
resDev->rd_fet_drain = resptr;
|
||||||
InitializeNode(resptr,xj,yj,RES_NODE_DEVICE);
|
|
||||||
resptr->rn_te = tcell;
|
|
||||||
ResAddToQueue(resptr,PendingList);
|
|
||||||
}
|
}
|
||||||
NEWBREAK(resptr,tile,xj,yj,NULL);
|
else
|
||||||
|
{
|
||||||
|
resptr = resDev->rd_fet_drain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newnode)
|
||||||
|
{
|
||||||
|
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
|
||||||
|
tcell->te_nextt = NULL;
|
||||||
|
tcell->te_thist = j->deviceList;
|
||||||
|
InitializeNode(resptr, xj, yj, RES_NODE_DEVICE);
|
||||||
|
resptr->rn_te = tcell;
|
||||||
|
ResAddToQueue(resptr, PendingList);
|
||||||
|
}
|
||||||
|
NEWBREAK(resptr, tile, xj, yj, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -113,49 +111,49 @@ ResNewSDDevice(tile,tp,xj,yj,direction,PendingList)
|
||||||
|
|
||||||
void
|
void
|
||||||
ResProcessJunction(tile, tp, xj, yj, NodeList)
|
ResProcessJunction(tile, tp, xj, yj, NodeList)
|
||||||
Tile *tile, *tp;
|
Tile *tile, *tp;
|
||||||
int xj,yj;
|
int xj, yj;
|
||||||
resNode **NodeList;
|
resNode **NodeList;
|
||||||
{
|
{
|
||||||
ResJunction *junction;
|
ResJunction *junction;
|
||||||
resNode *resptr;
|
resNode *resptr;
|
||||||
jElement *jcell;
|
jElement *jcell;
|
||||||
tileJunk *j0 = (tileJunk *)tile->ti_client;
|
tileJunk *j0 = (tileJunk *)tile->ti_client;
|
||||||
tileJunk *j2 = (tileJunk *)tp->ti_client;
|
tileJunk *j2 = (tileJunk *)tp->ti_client;
|
||||||
|
|
||||||
#ifdef PARANOID
|
#ifdef PARANOID
|
||||||
if (tile == tp)
|
if (tile == tp)
|
||||||
{
|
{
|
||||||
TxError("Junction being made between tile and itself \n");
|
TxError("Junction being made between tile and itself \n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (j2->tj_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)));
|
||||||
InitializeNode(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);
|
||||||
|
|
||||||
jcell->je_thisj = junction;
|
jcell->je_thisj = junction;
|
||||||
jcell->je_nextj = NULL;
|
jcell->je_nextj = NULL;
|
||||||
junction->rj_status = FALSE;
|
junction->rj_status = FALSE;
|
||||||
junction->rj_jnode = resptr;
|
junction->rj_jnode = resptr;
|
||||||
junction->rj_Tile[0] = tile;
|
junction->rj_Tile[0] = tile;
|
||||||
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] = j0->junctionList;
|
junction->rj_nextjunction[0] = j0->junctionList;
|
||||||
j0->junctionList = junction;
|
j0->junctionList = junction;
|
||||||
junction->rj_nextjunction[1] = j2->junctionList;
|
junction->rj_nextjunction[1] = j2->junctionList;
|
||||||
j2->junctionList = junction;
|
j2->junctionList = junction;
|
||||||
|
|
||||||
NEWBREAK(junction->rj_jnode,tile,
|
NEWBREAK(junction->rj_jnode,tile, junction->rj_loc.p_x,
|
||||||
junction->rj_loc.p_x,junction->rj_loc.p_y,NULL);
|
junction->rj_loc.p_y, NULL);
|
||||||
|
|
||||||
NEWBREAK(junction->rj_jnode,tp,
|
NEWBREAK(junction->rj_jnode,tp, junction->rj_loc.p_x,
|
||||||
junction->rj_loc.p_x,junction->rj_loc.p_y,NULL);
|
junction->rj_loc.p_y, NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
714
resis/ResMain.c
714
resis/ResMain.c
|
|
@ -20,23 +20,24 @@ 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 "utils/tech.h"
|
#include "utils/tech.h"
|
||||||
|
#include "select/select.h"
|
||||||
#include "textio/txcommands.h"
|
#include "textio/txcommands.h"
|
||||||
#include "resis/resis.h"
|
#include "resis/resis.h"
|
||||||
|
|
||||||
CellUse *ResUse=NULL; /* Our use and def */
|
CellUse *ResUse = NULL; /* Our use and def */
|
||||||
CellDef *ResDef=NULL;
|
CellDef *ResDef = NULL;
|
||||||
TileTypeBitMask ResConnectWithSD[NT]; /* A mask that goes from */
|
TileTypeBitMask ResConnectWithSD[NT]; /* A mask that goes from */
|
||||||
/* SD's to devices. */
|
/* SD's to devices. */
|
||||||
TileTypeBitMask ResCopyMask[NT]; /* Indicates which tiles */
|
TileTypeBitMask ResCopyMask[NT]; /* Indicates which tiles */
|
||||||
/* are to be copied. */
|
/* are to be copied. */
|
||||||
resResistor *ResResList=NULL; /* Resistor list */
|
resResistor *ResResList = NULL; /* Resistor list */
|
||||||
resNode *ResNodeList=NULL; /* Processed Nodes */
|
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 *ResOriginNode=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 Region *ResFirst();
|
extern Region *ResFirst();
|
||||||
extern Tile *FindStartTile();
|
extern Tile *FindStartTile();
|
||||||
extern int ResEachTile();
|
extern int ResEachTile();
|
||||||
|
|
@ -45,8 +46,6 @@ extern ResSimNode *ResInitializeNode();
|
||||||
|
|
||||||
extern HashTable ResNodeTable;
|
extern HashTable ResNodeTable;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*--------------------------------------------------------------------------
|
*--------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -78,13 +77,13 @@ ResInitializeConn()
|
||||||
for (diff = TT_TECHDEPBASE; diff < TT_MAXTYPES; diff++)
|
for (diff = TT_TECHDEPBASE; diff < TT_MAXTYPES; diff++)
|
||||||
{
|
{
|
||||||
if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), diff)
|
if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), diff)
|
||||||
TTMaskSetType(&ResConnectWithSD[diff],dev);
|
TTMaskSetType(&ResConnectWithSD[diff], dev);
|
||||||
|
|
||||||
if TTMaskHasType(&(devptr->exts_deviceSubstrateTypes),diff)
|
if TTMaskHasType(&(devptr->exts_deviceSubstrateTypes), diff)
|
||||||
TTMaskSetType(&ResConnectWithSD[diff],dev);
|
TTMaskSetType(&ResConnectWithSD[diff], dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TTMaskSetMask(&ResConnectWithSD[dev],&DBConnectTbl[dev]);
|
TTMaskSetMask(&ResConnectWithSD[dev], &DBConnectTbl[dev]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,7 +120,6 @@ ResGetReCell()
|
||||||
ResUse = DBCellNewUse(ResDef, (char *) NULL);
|
ResUse = DBCellNewUse(ResDef, (char *) NULL);
|
||||||
DBSetTrans(ResUse, &GeoIdentityTransform);
|
DBSetTrans(ResUse, &GeoIdentityTransform);
|
||||||
ResUse->cu_expandMask = CU_DESCEND_SPECIAL;
|
ResUse->cu_expandMask = CU_DESCEND_SPECIAL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -172,7 +170,7 @@ ResDissolveContacts(contacts)
|
||||||
}
|
}
|
||||||
|
|
||||||
tp = ResDef->cd_planes[DBPlane(contacts->cp_type)]->pl_hint;
|
tp = ResDef->cd_planes[DBPlane(contacts->cp_type)]->pl_hint;
|
||||||
GOTOPOINT(tp,&(contacts->cp_rect.r_ll));
|
GOTOPOINT(tp, &(contacts->cp_rect.r_ll));
|
||||||
#ifdef PARANOID
|
#ifdef PARANOID
|
||||||
if (TiGetTypeExact(tp) == contacts->cp_type)
|
if (TiGetTypeExact(tp) == contacts->cp_type)
|
||||||
{
|
{
|
||||||
|
|
@ -325,46 +323,46 @@ ResAddBreakpointFunc(tile, node)
|
||||||
|
|
||||||
void
|
void
|
||||||
ResFindNewContactTiles(contacts)
|
ResFindNewContactTiles(contacts)
|
||||||
ResContactPoint *contacts;
|
ResContactPoint *contacts;
|
||||||
{
|
{
|
||||||
int pNum;
|
int pNum;
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
TileTypeBitMask mask;
|
TileTypeBitMask mask;
|
||||||
|
|
||||||
for (; contacts != (ResContactPoint *) NULL; contacts = contacts->cp_nextcontact)
|
for (; contacts != (ResContactPoint *) NULL; contacts = contacts->cp_nextcontact)
|
||||||
{
|
{
|
||||||
DBFullResidueMask(contacts->cp_type, &mask);
|
DBFullResidueMask(contacts->cp_type, &mask);
|
||||||
for (pNum=PL_TECHDEPBASE; pNum<DBNumPlanes; pNum++)
|
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||||
{
|
{
|
||||||
tile = ResDef->cd_planes[pNum]->pl_hint;
|
tile = ResDef->cd_planes[pNum]->pl_hint;
|
||||||
GOTOPOINT(tile, &(contacts->cp_center));
|
GOTOPOINT(tile, &(contacts->cp_center));
|
||||||
#ifdef PARANOID
|
#ifdef PARANOID
|
||||||
if (tile == (Tile *) NULL)
|
if (tile == (Tile *) NULL)
|
||||||
{
|
{
|
||||||
TxError("Error: setting contact tile to null\n");
|
TxError("Error: setting contact tile to null\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if ((IsSplit(tile) && TTMaskHasType(&mask, TiGetRightType(tile)))
|
if ((IsSplit(tile) && TTMaskHasType(&mask, TiGetRightType(tile)))
|
||||||
|| TTMaskHasType(&mask, TiGetType(tile)))
|
|| TTMaskHasType(&mask, TiGetType(tile)))
|
||||||
{
|
{
|
||||||
tileJunk *j = (tileJunk *)tile->ti_client;
|
tileJunk *j = (tileJunk *)tile->ti_client;
|
||||||
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 = j->contactList;
|
ce->ce_nextc = j->contactList;
|
||||||
(contacts->cp_currentcontact) += 1;
|
(contacts->cp_currentcontact) += 1;
|
||||||
j->contactList = ce;
|
j->contactList = ce;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef PARANOID
|
#ifdef PARANOID
|
||||||
if (contacts->cp_currentcontact > LAYERS_PER_CONTACT)
|
if (contacts->cp_currentcontact > LAYERS_PER_CONTACT)
|
||||||
{
|
{
|
||||||
TxError("Error: Not enough space allocated for contact nodes\n");
|
TxError("Error: Not enough space allocated for contact nodes\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -388,78 +386,77 @@ ResProcessTiles(goodies, origin)
|
||||||
ResGlobalParams *goodies;
|
ResGlobalParams *goodies;
|
||||||
|
|
||||||
{
|
{
|
||||||
Tile *startTile;
|
Tile *startTile;
|
||||||
int tilenum,merged;
|
int tilenum, merged;
|
||||||
resNode *resptr2;
|
resNode *resptr2;
|
||||||
jElement *workingj;
|
jElement *workingj;
|
||||||
cElement *workingc;
|
cElement *workingc;
|
||||||
ResFixPoint *fix;
|
ResFixPoint *fix;
|
||||||
resNode *resptr;
|
resNode *resptr;
|
||||||
int (*tilefunc)();
|
int (*tilefunc)();
|
||||||
|
|
||||||
#ifdef LAPLACE
|
#ifdef LAPLACE
|
||||||
tilefunc = (ResOptionsFlags & ResOpt_DoLaplace)?ResLaplaceTile:ResEachTile;
|
tilefunc = (ResOptionsFlags & ResOpt_DoLaplace) ? ResLaplaceTile : ResEachTile;
|
||||||
#else
|
#else
|
||||||
tilefunc = ResEachTile;
|
tilefunc = ResEachTile;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ResOptionsFlags & ResOpt_Signal)
|
if (ResOptionsFlags & ResOpt_Signal)
|
||||||
{
|
{
|
||||||
startTile = FindStartTile(goodies, origin);
|
startTile = FindStartTile(goodies, origin);
|
||||||
if (startTile == NULL) return(1);
|
if (startTile == NULL) return(1);
|
||||||
resCurrentNode = NULL;
|
resCurrentNode = NULL;
|
||||||
(void) (*tilefunc)(startTile, origin);
|
(void) (*tilefunc)(startTile, origin);
|
||||||
}
|
}
|
||||||
#ifdef ARIEL
|
#ifdef ARIEL
|
||||||
else if (ResOptionsFlags & ResOpt_Power)
|
else if (ResOptionsFlags & ResOpt_Power)
|
||||||
{
|
{
|
||||||
for (fix = ResFixList; fix != NULL;fix=fix->fp_next)
|
for (fix = ResFixList; fix != NULL; fix = fix->fp_next)
|
||||||
{
|
{
|
||||||
Tile *tile = fix->fp_tile;
|
Tile *tile = fix->fp_tile;
|
||||||
if (tile == NULL)
|
if (tile == NULL)
|
||||||
{
|
{
|
||||||
|
tile = ResDef->cd_planes[DBPlane(fix->fp_ttype)]->pl_hint;
|
||||||
|
GOTOPOINT(tile, &(fix->fp_loc));
|
||||||
|
if (TiGetTypeExact(tile) != TT_SPACE)
|
||||||
|
{
|
||||||
|
fix->fp_tile = tile;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tile = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tile != NULL)
|
||||||
|
{
|
||||||
|
int x = fix->fp_loc.p_x;
|
||||||
|
int y = fix->fp_loc.p_y;
|
||||||
|
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
||||||
|
InitializeNode(resptr, x, y, RES_NODE_ORIGIN);
|
||||||
|
resptr->rn_status = TRUE;
|
||||||
|
resptr->rn_noderes = 0;
|
||||||
|
ResAddToQueue(resptr, &ResNodeQueue);
|
||||||
|
fix->fp_node = resptr;
|
||||||
|
NEWBREAK(resptr, tile, x, y, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (fix = ResFixList; fix != NULL; fix = fix->fp_next)
|
||||||
|
{
|
||||||
|
Tile *tile = fix->fp_tile;
|
||||||
|
|
||||||
tile = ResDef->cd_planes[DBPlane(fix->fp_ttype)]->pl_hint;
|
if (tile != NULL && (((tileJunk *)tile->ti_client)->tj_status &
|
||||||
GOTOPOINT(tile, &(fix->fp_loc));
|
|
||||||
if (TiGetTypeExact(tile) != TT_SPACE)
|
|
||||||
{
|
|
||||||
fix->fp_tile = tile;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tile = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (tile != NULL)
|
|
||||||
{
|
|
||||||
int x = fix->fp_loc.p_x;
|
|
||||||
int y = fix->fp_loc.p_y;
|
|
||||||
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
|
||||||
InitializeNode(resptr, x, y, RES_NODE_ORIGIN);
|
|
||||||
resptr->rn_status = TRUE;
|
|
||||||
resptr->rn_noderes = 0;
|
|
||||||
ResAddToQueue(resptr, &ResNodeQueue);
|
|
||||||
fix->fp_node = resptr;
|
|
||||||
NEWBREAK(resptr, tile, x, y, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (fix = ResFixList; fix != NULL; fix = fix->fp_next)
|
|
||||||
{
|
|
||||||
Tile *tile = fix->fp_tile;
|
|
||||||
|
|
||||||
if (tile != NULL && (((tileJunk *)tile->ti_client)->tj_status &
|
|
||||||
RES_TILE_DONE) == 0)
|
RES_TILE_DONE) == 0)
|
||||||
{
|
{
|
||||||
resCurrentNode = fix->fp_node;
|
resCurrentNode = fix->fp_node;
|
||||||
(void) (*tilefunc)(tile, (Point *)NULL);
|
(void) (*tilefunc)(tile, (Point *)NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef PARANOID
|
#ifdef PARANOID
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TxError("Unknown analysis type in ResProcessTiles\n");
|
TxError("Unknown analysis type in ResProcessTiles\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -467,103 +464,199 @@ ResProcessTiles(goodies, 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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
resptr2 = ResNodeQueue;
|
resptr2 = ResNodeQueue;
|
||||||
merged = FALSE;
|
merged = FALSE;
|
||||||
|
|
||||||
/* Process all junctions associated with node */
|
/* Process all junctions associated with node */
|
||||||
|
|
||||||
for (workingj = resptr2->rn_je; workingj != NULL; workingj = workingj->je_nextj)
|
for (workingj = resptr2->rn_je; workingj != NULL; workingj = workingj->je_nextj)
|
||||||
{
|
{
|
||||||
ResJunction *rj = workingj->je_thisj;
|
ResJunction *rj = workingj->je_thisj;
|
||||||
if (rj->rj_status == FALSE)
|
if (rj->rj_status == FALSE)
|
||||||
{
|
{
|
||||||
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];
|
||||||
tileJunk *j = (tileJunk *) tile->ti_client;
|
tileJunk *j = (tileJunk *)tile->ti_client;
|
||||||
|
|
||||||
if ((j->tj_status & RES_TILE_DONE) == 0)
|
if ((j->tj_status & RES_TILE_DONE) == 0)
|
||||||
|
{
|
||||||
|
resCurrentNode = resptr2;
|
||||||
|
merged |= (*tilefunc)(tile,(Point *)NULL);
|
||||||
|
}
|
||||||
|
if (merged & ORIGIN) break;
|
||||||
|
}
|
||||||
|
if (merged & ORIGIN) break;
|
||||||
|
rj->rj_status = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next, Process all contacts. */
|
||||||
|
|
||||||
|
for (workingc = resptr2->rn_ce;workingc != NULL;workingc = workingc->ce_nextc)
|
||||||
|
{
|
||||||
|
ResContactPoint *cp = workingc->ce_thisc;
|
||||||
|
|
||||||
|
if (merged & ORIGIN) break;
|
||||||
|
if (cp->cp_status == FALSE)
|
||||||
|
{
|
||||||
|
int newstatus = TRUE;
|
||||||
|
for (tilenum = 0; tilenum < cp->cp_currentcontact; tilenum++)
|
||||||
|
{
|
||||||
|
Tile *tile = cp->cp_tile[tilenum];
|
||||||
|
tileJunk *j = (tileJunk *) tile->ti_client;
|
||||||
|
|
||||||
|
if ((j->tj_status & RES_TILE_DONE) == 0)
|
||||||
|
{
|
||||||
|
if (cp->cp_cnode[tilenum] == resptr2)
|
||||||
{
|
{
|
||||||
resCurrentNode = resptr2;
|
resCurrentNode = resptr2;
|
||||||
merged |= (*tilefunc)(tile,(Point *)NULL);
|
merged |= (*tilefunc)(tile,(Point *)NULL);
|
||||||
}
|
}
|
||||||
if (merged & ORIGIN) break;
|
else
|
||||||
}
|
|
||||||
if (merged & ORIGIN) break;
|
|
||||||
rj->rj_status = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Next, Process all contacts. */
|
|
||||||
|
|
||||||
for (workingc = resptr2->rn_ce;workingc != NULL;workingc = workingc->ce_nextc)
|
|
||||||
{
|
|
||||||
ResContactPoint *cp = workingc->ce_thisc;
|
|
||||||
|
|
||||||
if (merged & ORIGIN) break;
|
|
||||||
if (cp->cp_status == FALSE)
|
|
||||||
{
|
|
||||||
int newstatus = TRUE;
|
|
||||||
for (tilenum = 0; tilenum < cp->cp_currentcontact; tilenum++)
|
|
||||||
{
|
|
||||||
Tile *tile = cp->cp_tile[tilenum];
|
|
||||||
tileJunk *j = (tileJunk *) tile->ti_client;
|
|
||||||
|
|
||||||
if ((j->tj_status & RES_TILE_DONE) == 0)
|
|
||||||
{
|
{
|
||||||
if (cp->cp_cnode[tilenum] == resptr2)
|
newstatus = FALSE;
|
||||||
{
|
|
||||||
resCurrentNode = resptr2;
|
|
||||||
merged |= (*tilefunc)(tile,(Point *)NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newstatus = FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (merged & ORIGIN) break;
|
}
|
||||||
}
|
if (merged & ORIGIN) break;
|
||||||
if (merged & ORIGIN) break;
|
}
|
||||||
cp->cp_status = newstatus;
|
if (merged & ORIGIN) break;
|
||||||
}
|
cp->cp_status = newstatus;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If nothing new has been added via a merge, then the node is
|
* If nothing new has been added via a merge, then the node is
|
||||||
* finished. It is removed from the pending queue, added to the
|
* finished. It is removed from the pending queue, added to the
|
||||||
* done list, cleaned up, and passed to ResDoneWithNode
|
* done list, cleaned up, and passed to ResDoneWithNode
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (merged == FALSE)
|
if (merged == FALSE)
|
||||||
{
|
{
|
||||||
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 &= ~PENDING;
|
resptr2->rn_status &= ~PENDING;
|
||||||
resptr2->rn_status |= FINISHED | 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)
|
||||||
{
|
{
|
||||||
ResOriginNode=resptr2;
|
ResOriginNode=resptr2;
|
||||||
}
|
}
|
||||||
ResNodeList = resptr2;
|
ResNodeList = resptr2;
|
||||||
ResCleanNode(resptr2, FALSE, &ResNodeList, &ResNodeQueue);
|
ResCleanNode(resptr2, FALSE, &ResNodeList, &ResNodeQueue);
|
||||||
ResDoneWithNode(resptr2);
|
ResDoneWithNode(resptr2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* ResCalcPerimOverlap ---
|
||||||
|
*
|
||||||
|
* Given a device tile, compute simple perimeter and overlap of the device
|
||||||
|
* by the net under consideration.
|
||||||
|
*
|
||||||
|
* Results:
|
||||||
|
* None.
|
||||||
|
*
|
||||||
|
* Side Effects:
|
||||||
|
* The ResDevTile structure is updated with the overlap and perimeter
|
||||||
|
* values.
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
ResCalcPerimOverlap(tile, dev)
|
||||||
|
Tile *tile;
|
||||||
|
ResDevTile *dev;
|
||||||
|
{
|
||||||
|
Tile *tp;
|
||||||
|
int t1;
|
||||||
|
int overlap;
|
||||||
|
TileTypeBitMask *omask;
|
||||||
|
|
||||||
|
dev->perim = (TOP(tile) - BOTTOM(tile) - LEFT(tile) + RIGHT(tile)) << 1;
|
||||||
|
overlap = 0;
|
||||||
|
|
||||||
|
t1 = TiGetType(tile);
|
||||||
|
omask = &(ExtCurStyle->exts_nodeConn[t1]);
|
||||||
|
|
||||||
|
/* left */
|
||||||
|
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
|
||||||
|
{
|
||||||
|
if TTMaskHasType(omask, TiGetType(tp))
|
||||||
|
overlap += MIN(TOP(tile), TOP(tp)) - MAX(BOTTOM(tile), BOTTOM(tp));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* right */
|
||||||
|
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp))
|
||||||
|
{
|
||||||
|
if TTMaskHasType(omask, TiGetType(tp))
|
||||||
|
overlap += MIN(TOP(tile), TOP(tp)) - MAX(BOTTOM(tile), BOTTOM(tp));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* top */
|
||||||
|
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp))
|
||||||
|
{
|
||||||
|
if TTMaskHasType(omask, TiGetType(tp))
|
||||||
|
overlap += MIN(RIGHT(tile), RIGHT(tp)) - MAX(LEFT(tile), LEFT(tp));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bottom */
|
||||||
|
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp))
|
||||||
|
{
|
||||||
|
if TTMaskHasType(omask, TiGetType(tp))
|
||||||
|
overlap += MIN(RIGHT(tile), RIGHT(tp)) - MAX(LEFT(tile), LEFT(tp));
|
||||||
|
}
|
||||||
|
dev->overlap = overlap;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* resMakeDevFunc --
|
||||||
|
*
|
||||||
|
* Callback function from ResExtractNet. For each device in a node's
|
||||||
|
* device list pulled from the .sim file, find the tile corresponding
|
||||||
|
* to the device in the source tree, and fill out the complete device
|
||||||
|
* record (namely the full device area).
|
||||||
|
*
|
||||||
|
* Result:
|
||||||
|
* Return 1 to stop the search because the device has been found.
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
resMakeDevFunc(tile, cx)
|
||||||
|
Tile *tile;
|
||||||
|
TreeContext *cx;
|
||||||
|
{
|
||||||
|
ResDevTile *thisDev = (ResDevTile *)cx->tc_filter->tf_arg;
|
||||||
|
Rect devArea;
|
||||||
|
|
||||||
|
TiToRect(tile, &devArea);
|
||||||
|
GeoTransRect(&cx->tc_scx->scx_trans, &devArea, &thisDev->area);
|
||||||
|
ResCalcPerimOverlap(tile, thisDev);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* ResExtractNet-- extracts the resistance net at the specified
|
* ResExtractNet-- extracts the resistance net at the specified
|
||||||
* rn_loc. If the resulting net is greater than the tolerance,
|
* rn_loc. If the resulting net is greater than the tolerance,
|
||||||
|
|
@ -577,18 +670,20 @@ ResProcessTiles(goodies, origin)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ResExtractNet(startlist, goodies, cellname)
|
ResExtractNet(node, goodies, cellname)
|
||||||
ResFixPoint *startlist;
|
ResSimNode *node;
|
||||||
ResGlobalParams *goodies;
|
ResGlobalParams *goodies;
|
||||||
char *cellname;
|
char *cellname;
|
||||||
{
|
{
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
int pNum;
|
int pNum;
|
||||||
ResDevTile *DevTiles, *lasttile;
|
|
||||||
TileTypeBitMask FirstTileMask;
|
TileTypeBitMask FirstTileMask;
|
||||||
Point startpoint;
|
Point startpoint;
|
||||||
ResFixPoint *fix;
|
|
||||||
static int first = 1;
|
static int first = 1;
|
||||||
|
ResDevTile *DevTiles, *thisDev;
|
||||||
|
ResFixPoint *fix;
|
||||||
|
devPtr *tptr;
|
||||||
|
int resMakeDevFunc();
|
||||||
|
|
||||||
/* Make sure all global network variables are reset */
|
/* Make sure all global network variables are reset */
|
||||||
|
|
||||||
|
|
@ -599,18 +694,18 @@ ResExtractNet(startlist, goodies, cellname)
|
||||||
ResContactList = NULL;
|
ResContactList = NULL;
|
||||||
ResOriginNode = NULL;
|
ResOriginNode = NULL;
|
||||||
|
|
||||||
/* Pass back network pointers */
|
/* Pass back network pointers */
|
||||||
|
|
||||||
goodies->rg_maxres = 0;
|
goodies->rg_maxres = 0;
|
||||||
goodies->rg_tilecount = 0;
|
goodies->rg_tilecount = 0;
|
||||||
|
|
||||||
/*set up internal stuff if this is the first time through */
|
/* Set up internal stuff if this is the first time through */
|
||||||
|
|
||||||
if (first)
|
if (first)
|
||||||
{
|
{
|
||||||
ResInitializeConn();
|
ResInitializeConn();
|
||||||
first = 0;
|
first = 0;
|
||||||
ResGetReCell();
|
ResGetReCell();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize Cell */
|
/* Initialize Cell */
|
||||||
|
|
@ -618,7 +713,7 @@ ResExtractNet(startlist, goodies, cellname)
|
||||||
if (cellname)
|
if (cellname)
|
||||||
{
|
{
|
||||||
CellDef *def = DBCellLookDef(cellname);
|
CellDef *def = DBCellLookDef(cellname);
|
||||||
if (def == (CellDef *) NULL)
|
if (def == (CellDef *)NULL)
|
||||||
{
|
{
|
||||||
TxError("Error: No such cell \"%s\"\n", cellname);
|
TxError("Error: No such cell \"%s\"\n", cellname);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
@ -629,8 +724,8 @@ ResExtractNet(startlist, goodies, cellname)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MagWindow *w = ToolGetBoxWindow(&scx.scx_area, (int *) NULL);
|
MagWindow *w = ToolGetBoxWindow(&scx.scx_area, (int *)NULL);
|
||||||
if (w == (MagWindow *) NULL)
|
if (w == (MagWindow *)NULL)
|
||||||
{
|
{
|
||||||
TxError("Sorry, the box must appear in one of the windows.\n");
|
TxError("Sorry, the box must appear in one of the windows.\n");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
@ -641,49 +736,59 @@ ResExtractNet(startlist, goodies, cellname)
|
||||||
|
|
||||||
DBCellClearDef(ResUse->cu_def);
|
DBCellClearDef(ResUse->cu_def);
|
||||||
|
|
||||||
/* Copy Paint */
|
|
||||||
DevTiles = NULL;
|
|
||||||
lasttile = NULL;
|
|
||||||
for (fix = startlist; fix != NULL; fix = fix->fp_next)
|
|
||||||
{
|
|
||||||
ResDevTile *newdevtiles, *tmp;
|
|
||||||
|
|
||||||
#ifdef ARIEL
|
#ifdef ARIEL
|
||||||
if ((ResOptionsFlags & ResOpt_Power) &&
|
if ((ResOptionsFlags & ResOpt_Power) &&
|
||||||
strcmp(fix->fp_name, goodies->rg_name) != 0) continue;
|
strcmp(node->name, goodies->rg_name) != 0) continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
scx.scx_area.r_ll.p_x = fix->fp_loc.p_x-2;
|
/* Copy Paint */
|
||||||
scx.scx_area.r_ll.p_y = fix->fp_loc.p_y-2;
|
|
||||||
scx.scx_area.r_ur.p_x = fix->fp_loc.p_x+2;
|
|
||||||
scx.scx_area.r_ur.p_y = fix->fp_loc.p_y+2;
|
|
||||||
startpoint = fix->fp_loc;
|
|
||||||
|
|
||||||
/* Because fix->fp_ttype might come from a label with a sticky type
|
scx.scx_area.r_ll.p_x = node->location.p_x - 2;
|
||||||
* that does not correspond exactly to the layer underneath, include
|
scx.scx_area.r_ll.p_y = node->location.p_y - 2;
|
||||||
* all connecting types.
|
scx.scx_area.r_ur.p_x = node->location.p_x + 2;
|
||||||
*/
|
scx.scx_area.r_ur.p_y = node->location.p_y + 2;
|
||||||
TTMaskSetMask(&FirstTileMask, &DBConnectTbl[fix->fp_ttype]);
|
startpoint = node->location;
|
||||||
|
|
||||||
newdevtiles = DBTreeCopyConnectDCS(&scx, &FirstTileMask, 0,
|
/* Because node->type might come from a label with a sticky type
|
||||||
ResCopyMask, &TiPlaneRect, ResUse);
|
* that does not correspond exactly to the layer underneath, include
|
||||||
|
* all connecting types.
|
||||||
|
*/
|
||||||
|
TTMaskZero(&FirstTileMask);
|
||||||
|
TTMaskSetMask(&FirstTileMask, &DBConnectTbl[node->type]);
|
||||||
|
|
||||||
for (tmp = newdevtiles; tmp && tmp->nextDev; tmp = tmp->nextDev);
|
DBTreeCopyConnect(&scx, &FirstTileMask, 0, ResCopyMask, &TiPlaneRect,
|
||||||
if (newdevtiles)
|
SEL_DO_LABELS, ResUse);
|
||||||
{
|
|
||||||
if (DevTiles)
|
/* Add devices to ResUse from list in node */
|
||||||
lasttile->nextDev = newdevtiles;
|
DevTiles = NULL;
|
||||||
else
|
for (tptr = node->firstDev; tptr; tptr = tptr->nextDev)
|
||||||
DevTiles = newdevtiles;
|
{
|
||||||
lasttile = tmp;
|
TileTypeBitMask devMask;
|
||||||
}
|
|
||||||
|
TTMaskSetOnlyType(&devMask, tptr->thisDev->rs_ttype);
|
||||||
|
thisDev = (ResDevTile *)mallocMagic(sizeof(ResDevTile));
|
||||||
|
thisDev->devptr = tptr->thisDev->rs_devptr;
|
||||||
|
thisDev->type = tptr->thisDev->rs_ttype;
|
||||||
|
scx.scx_area.r_ll.p_x = tptr->thisDev->location.p_x;
|
||||||
|
scx.scx_area.r_ll.p_y = tptr->thisDev->location.p_y;
|
||||||
|
scx.scx_area.r_xtop = scx.scx_area.r_xbot + 1;
|
||||||
|
scx.scx_area.r_ytop = scx.scx_area.r_ybot + 1;
|
||||||
|
DBTreeSrTiles(&scx, &devMask, 0, resMakeDevFunc, (ClientData)thisDev);
|
||||||
|
thisDev->nextDev = DevTiles;
|
||||||
|
DevTiles = thisDev;
|
||||||
|
|
||||||
|
/* Paint the type into ResUse */
|
||||||
|
pNum = DBPlane(thisDev->type);
|
||||||
|
DBPaintPlane(ResUse->cu_def->cd_planes[pNum], &thisDev->area,
|
||||||
|
DBStdPaintTbl(thisDev->type, pNum), (PaintUndoInfo *)NULL);
|
||||||
}
|
}
|
||||||
|
DBReComputeBbox(ResUse->cu_def);
|
||||||
|
|
||||||
ExtResetTiles(scx.scx_use->cu_def, extUnInit);
|
ExtResetTiles(scx.scx_use->cu_def, extUnInit);
|
||||||
|
|
||||||
/* find all contacts in design and note their position */
|
/* Find all contacts in design and note their position */
|
||||||
|
|
||||||
ResContactList = (ResContactPoint *) ExtFindRegions(ResUse->cu_def,
|
ResContactList = (ResContactPoint *)ExtFindRegions(ResUse->cu_def,
|
||||||
&(ResUse->cu_def->cd_bbox),
|
&(ResUse->cu_def->cd_bbox),
|
||||||
&DBAllButSpaceAndDRCBits,
|
&DBAllButSpaceAndDRCBits,
|
||||||
ResConnectWithSD, extUnInit, ResFirst,
|
ResConnectWithSD, extUnInit, ResFirst,
|
||||||
|
|
@ -701,16 +806,16 @@ ResExtractNet(startlist, goodies, cellname)
|
||||||
|
|
||||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||||
{
|
{
|
||||||
Plane *plane = ResUse->cu_def->cd_planes[pNum];
|
Plane *plane = ResUse->cu_def->cd_planes[pNum];
|
||||||
Rect *rect = &ResUse->cu_def->cd_bbox;
|
Rect *rect = &ResUse->cu_def->cd_bbox;
|
||||||
ResFracture(plane, rect);
|
ResFracture(plane, rect);
|
||||||
(void) DBSrPaintClient((Tile *) NULL,plane,rect,
|
(void) DBSrPaintClient((Tile *) NULL, plane, rect,
|
||||||
&DBAllButSpaceAndDRCBits,
|
&DBAllButSpaceAndDRCBits,
|
||||||
(ClientData) CLIENTDEFAULT, ResAddPlumbing,
|
(ClientData) CLIENTDEFAULT, ResAddPlumbing,
|
||||||
(ClientData) &ResDevList);
|
(ClientData) &ResDevList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finish preprocessing. */
|
/* Finish preprocessing. */
|
||||||
|
|
||||||
ResMakePortBreakpoints(ResUse->cu_def);
|
ResMakePortBreakpoints(ResUse->cu_def);
|
||||||
ResMakeLabelBreakpoints(ResUse->cu_def);
|
ResMakeLabelBreakpoints(ResUse->cu_def);
|
||||||
|
|
@ -720,24 +825,24 @@ ResExtractNet(startlist, goodies, cellname)
|
||||||
#ifdef LAPLACE
|
#ifdef LAPLACE
|
||||||
if (ResOptionsFlags & ResOpt_DoLaplace)
|
if (ResOptionsFlags & ResOpt_DoLaplace)
|
||||||
{
|
{
|
||||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||||
{
|
{
|
||||||
Plane *plane = ResUse->cu_def->cd_planes[pNum];
|
Plane *plane = ResUse->cu_def->cd_planes[pNum];
|
||||||
Rect *rect = &ResUse->cu_def->cd_bbox;
|
Rect *rect = &ResUse->cu_def->cd_bbox;
|
||||||
Res1d(plane,rect);
|
Res1d(plane, rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ARIEL
|
#ifdef ARIEL
|
||||||
if (ResOptionsFlags & ResOpt_Power)
|
if (ResOptionsFlags & ResOpt_Power)
|
||||||
{
|
{
|
||||||
for (fix = startlist; fix != NULL;fix=fix->fp_next)
|
for (fix = startlist; fix != NULL; fix = fix->fp_next)
|
||||||
{
|
{
|
||||||
fix->fp_tile = ResUse->cu_def->cd_planes[DBPlane(fix->fp_ttype)]->pl_hint;
|
fix->fp_tile = ResUse->cu_def->cd_planes[DBPlane(fix->fp_ttype)]->pl_hint;
|
||||||
GOTOPOINT(fix->fp_tile,&fix->fp_loc);
|
GOTOPOINT(fix->fp_tile, &fix->fp_loc);
|
||||||
if (TiGetTypeExact(fix->fp_tile) == TT_SPACE) fix->fp_tile = NULL;
|
if (TiGetTypeExact(fix->fp_tile) == TT_SPACE) fix->fp_tile = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -765,25 +870,24 @@ void
|
||||||
ResCleanUpEverything()
|
ResCleanUpEverything()
|
||||||
{
|
{
|
||||||
|
|
||||||
int pNum;
|
int pNum;
|
||||||
resResistor *oldRes;
|
resResistor *oldRes;
|
||||||
resDevice *oldDev;
|
resDevice *oldDev;
|
||||||
ResContactPoint *oldCon;
|
ResContactPoint *oldCon;
|
||||||
|
|
||||||
/* check integrity of internal database. Free up lists. */
|
/* Check integrity of internal database. Free up lists. */
|
||||||
|
|
||||||
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||||
{
|
{
|
||||||
(void) DBSrPaintClient((Tile *) NULL,ResUse->cu_def->cd_planes[pNum],
|
(void) DBSrPaintClient((Tile *)NULL, ResUse->cu_def->cd_planes[pNum],
|
||||||
&(ResUse->cu_def->cd_bbox),&DBAllButSpaceAndDRCBits,
|
&(ResUse->cu_def->cd_bbox), &DBAllButSpaceAndDRCBits,
|
||||||
(ClientData) CLIENTDEFAULT,ResRemovePlumbing,
|
(ClientData)CLIENTDEFAULT, ResRemovePlumbing,
|
||||||
(ClientData) NULL);
|
(ClientData)NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ResNodeList != NULL)
|
while (ResNodeList != NULL)
|
||||||
{
|
{
|
||||||
ResCleanNode(ResNodeList,TRUE,&ResNodeList,&ResNodeQueue);
|
ResCleanNode(ResNodeList, TRUE, &ResNodeList, &ResNodeQueue);
|
||||||
}
|
}
|
||||||
while (ResContactList != NULL)
|
while (ResContactList != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -807,12 +911,9 @@ ResCleanUpEverything()
|
||||||
freeMagic((char *)oldDev);
|
freeMagic((char *)oldDev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DBCellClearDef(ResUse->cu_def);
|
DBCellClearDef(ResUse->cu_def);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -849,10 +950,10 @@ FindStartTile(goodies, SourcePoint)
|
||||||
TileType savtype = goodies->rg_ttype;
|
TileType savtype = goodies->rg_ttype;
|
||||||
TileType rtype;
|
TileType rtype;
|
||||||
|
|
||||||
savtype = goodies->rg_ttype;
|
|
||||||
for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++)
|
for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++)
|
||||||
if (TTMaskHasType(rmask, rtype))
|
if (TTMaskHasType(rmask, rtype))
|
||||||
{
|
{
|
||||||
|
goodies->rg_ttype = rtype;
|
||||||
if ((tile = FindStartTile(goodies, SourcePoint)) != NULL)
|
if ((tile = FindStartTile(goodies, SourcePoint)) != NULL)
|
||||||
{
|
{
|
||||||
goodies->rg_ttype = savtype;
|
goodies->rg_ttype = savtype;
|
||||||
|
|
@ -934,54 +1035,55 @@ FindStartTile(goodies, SourcePoint)
|
||||||
t1 = TiGetType(tile);
|
t1 = TiGetType(tile);
|
||||||
|
|
||||||
devptr = ExtCurStyle->exts_device[t1];
|
devptr = ExtCurStyle->exts_device[t1];
|
||||||
|
|
||||||
/* left */
|
/* left */
|
||||||
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp))
|
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
|
||||||
{
|
{
|
||||||
t2 = TiGetRightType(tp);
|
t2 = TiGetRightType(tp);
|
||||||
if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t2))
|
if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t2))
|
||||||
{
|
{
|
||||||
SourcePoint->p_x = LEFT(tile);
|
SourcePoint->p_x = LEFT(tile);
|
||||||
SourcePoint->p_y = (MIN(TOP(tile),TOP(tp))+
|
SourcePoint->p_y = (MIN(TOP(tile),TOP(tp)) +
|
||||||
MAX(BOTTOM(tile),BOTTOM(tp)))>>1;
|
MAX(BOTTOM(tile), BOTTOM(tp))) >> 1;
|
||||||
return(tp);
|
return(tp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* right */
|
/* right */
|
||||||
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp))
|
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp))
|
||||||
{
|
{
|
||||||
t2 = TiGetLeftType(tp);
|
t2 = TiGetLeftType(tp);
|
||||||
if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t2))
|
if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t2))
|
||||||
{
|
{
|
||||||
SourcePoint->p_x = RIGHT(tile);
|
SourcePoint->p_x = RIGHT(tile);
|
||||||
SourcePoint->p_y = (MIN(TOP(tile),TOP(tp))+
|
SourcePoint->p_y = (MIN(TOP(tile), TOP(tp))+
|
||||||
MAX(BOTTOM(tile),BOTTOM(tp)))>>1;
|
MAX(BOTTOM(tile), BOTTOM(tp))) >> 1;
|
||||||
return(tp);
|
return(tp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* top */
|
/* top */
|
||||||
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp))
|
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp))
|
||||||
{
|
{
|
||||||
t2 = TiGetBottomType(tp);
|
t2 = TiGetBottomType(tp);
|
||||||
if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t2))
|
if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t2))
|
||||||
{
|
{
|
||||||
SourcePoint->p_y = TOP(tile);
|
SourcePoint->p_y = TOP(tile);
|
||||||
SourcePoint->p_x = (MIN(RIGHT(tile),RIGHT(tp))+
|
SourcePoint->p_x = (MIN(RIGHT(tile),RIGHT(tp)) +
|
||||||
MAX(LEFT(tile),LEFT(tp)))>>1;
|
MAX(LEFT(tile), LEFT(tp))) >> 1;
|
||||||
return(tp);
|
return(tp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bottom */
|
/* bottom */
|
||||||
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp))
|
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
|
||||||
{
|
{
|
||||||
t2 = TiGetTopType(tp);
|
t2 = TiGetTopType(tp);
|
||||||
if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t2))
|
if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t2))
|
||||||
{
|
{
|
||||||
SourcePoint->p_y = BOTTOM(tile);
|
SourcePoint->p_y = BOTTOM(tile);
|
||||||
SourcePoint->p_x = (MIN(RIGHT(tile),RIGHT(tp))+
|
SourcePoint->p_x = (MIN(RIGHT(tile), RIGHT(tp)) +
|
||||||
MAX(LEFT(tile),LEFT(tp)))>>1;
|
MAX(LEFT(tile), LEFT(tp))) >> 1;
|
||||||
return(tp);
|
return(tp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1005,36 +1107,36 @@ FindStartTile(goodies, SourcePoint)
|
||||||
|
|
||||||
resDevice *
|
resDevice *
|
||||||
ResGetDevice(pt)
|
ResGetDevice(pt)
|
||||||
Point *pt;
|
Point *pt;
|
||||||
|
|
||||||
{
|
{
|
||||||
Point workingPoint;
|
Point workingPoint;
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
int pnum;
|
int pnum;
|
||||||
|
|
||||||
workingPoint.p_x = (*pt).p_x;
|
workingPoint.p_x = (*pt).p_x;
|
||||||
workingPoint.p_y = (*pt).p_y;
|
workingPoint.p_y = (*pt).p_y;
|
||||||
|
|
||||||
for (pnum= PL_TECHDEPBASE; pnum < DBNumPlanes; pnum++)
|
for (pnum = PL_TECHDEPBASE; pnum < DBNumPlanes; pnum++)
|
||||||
{
|
{
|
||||||
if (TTMaskIntersect(&ExtCurStyle->exts_deviceMask,&DBPlaneTypes[pnum]) == 0)
|
if (TTMaskIntersect(&ExtCurStyle->exts_deviceMask, &DBPlaneTypes[pnum]) == 0)
|
||||||
{
|
continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/*start at hint tile for device plane */
|
|
||||||
tile = ResUse->cu_def->cd_planes[pnum]->pl_hint;
|
|
||||||
GOTOPOINT(tile,&workingPoint);
|
|
||||||
|
|
||||||
if (IsSplit(tile))
|
/* Start at hint tile for device plane */
|
||||||
{
|
|
||||||
if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetLeftType(tile))
|
tile = ResUse->cu_def->cd_planes[pnum]->pl_hint;
|
||||||
|
GOTOPOINT(tile, &workingPoint);
|
||||||
|
|
||||||
|
if (IsSplit(tile))
|
||||||
|
{
|
||||||
|
if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetLeftType(tile))
|
||||||
|| TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetRightType(tile)))
|
|| TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetRightType(tile)))
|
||||||
return(((tileJunk *)tile->ti_client)->deviceList);
|
return (((tileJunk *)tile->ti_client)->deviceList);
|
||||||
}
|
}
|
||||||
else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetType(tile)))
|
else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetType(tile)))
|
||||||
{
|
{
|
||||||
return(((tileJunk *)tile->ti_client)->deviceList);
|
return (((tileJunk *)tile->ti_client)->deviceList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (NULL);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -311,7 +311,7 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
p1 = junk->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);
|
||||||
|
|
|
||||||
1333
resis/ResMerge.c
1333
resis/ResMerge.c
File diff suppressed because it is too large
Load Diff
|
|
@ -171,16 +171,25 @@ ResPrintExtDev(outextfile, devices)
|
||||||
else
|
else
|
||||||
fprintf(outextfile, " \"%s\"", subsName);
|
fprintf(outextfile, " \"%s\"", subsName);
|
||||||
|
|
||||||
fprintf(outextfile, " \"%s\" %d %s \"%s\" %d %s \"%s\" %d %s\n",
|
if (devices->gate != NULL)
|
||||||
devices->gate->name,
|
fprintf(outextfile, " \"%s\" %d %s",
|
||||||
devices->layout->rd_length * 2,
|
devices->gate->name,
|
||||||
devices->rs_gattr,
|
devices->layout->rd_length * 2,
|
||||||
devices->source->name,
|
devices->rs_gattr);
|
||||||
devices->layout->rd_width,
|
|
||||||
devices->rs_sattr,
|
if (devices->source != NULL)
|
||||||
devices->drain->name,
|
fprintf(outextfile, " \"%s\" %d %s",
|
||||||
devices->layout->rd_width,
|
devices->source->name,
|
||||||
devices->rs_dattr);
|
devices->layout->rd_width,
|
||||||
|
devices->rs_sattr);
|
||||||
|
|
||||||
|
if (devices->drain != NULL)
|
||||||
|
fprintf(outextfile, " \"%s\" %d %s",
|
||||||
|
devices->drain->name,
|
||||||
|
devices->layout->rd_width,
|
||||||
|
devices->rs_dattr);
|
||||||
|
|
||||||
|
fprintf(outextfile, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1043
resis/ResReadSim.c
1043
resis/ResReadSim.c
File diff suppressed because it is too large
Load Diff
114
resis/ResRex.c
114
resis/ResRex.c
|
|
@ -22,6 +22,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "textio/textio.h"
|
#include "textio/textio.h"
|
||||||
#include "extract/extract.h"
|
#include "extract/extract.h"
|
||||||
#include "extract/extractInt.h"
|
#include "extract/extractInt.h"
|
||||||
|
#include "extflat/extflat.h"
|
||||||
#include "windows/windows.h"
|
#include "windows/windows.h"
|
||||||
#include "dbwind/dbwind.h"
|
#include "dbwind/dbwind.h"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
|
|
@ -52,9 +53,10 @@ extern ResSimNode *ResOriginalNodes; /*Linked List of Nodes */
|
||||||
int resNodeNum;
|
int resNodeNum;
|
||||||
|
|
||||||
#ifdef LAPLACE
|
#ifdef LAPLACE
|
||||||
int ResOptionsFlags = ResOpt_Simplify|ResOpt_Tdi|ResOpt_DoExtFile|ResOpt_CacheLaplace;
|
int ResOptionsFlags = ResOpt_Simplify | ResOpt_Tdi | ResOpt_DoExtFile
|
||||||
|
| ResOpt_CacheLaplace;
|
||||||
#else
|
#else
|
||||||
int ResOptionsFlags = ResOpt_Simplify|ResOpt_Tdi|ResOpt_DoExtFile;
|
int ResOptionsFlags = ResOpt_Simplify | ResOpt_Tdi | ResOpt_DoExtFile;
|
||||||
#endif
|
#endif
|
||||||
char *ResCurrentNode;
|
char *ResCurrentNode;
|
||||||
|
|
||||||
|
|
@ -97,17 +99,34 @@ ExtResisForDef(celldef, resisdata)
|
||||||
HashEntry *entry;
|
HashEntry *entry;
|
||||||
devPtr *tptr,*oldtptr;
|
devPtr *tptr,*oldtptr;
|
||||||
ResSimNode *node;
|
ResSimNode *node;
|
||||||
int result;
|
int result, idx;
|
||||||
|
char *devname;
|
||||||
|
|
||||||
ResRDevList = NULL;
|
ResRDevList = NULL;
|
||||||
ResOriginalNodes = NULL;
|
ResOriginalNodes = NULL;
|
||||||
|
|
||||||
|
/* Get device information from the current extraction style */
|
||||||
|
idx = 0;
|
||||||
|
while (ExtGetDevInfo(idx++, &devname, NULL, NULL, NULL, NULL, NULL))
|
||||||
|
{
|
||||||
|
if (idx == TT_MAXTYPES)
|
||||||
|
{
|
||||||
|
TxError("Error: Ran out of space for device types!\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, devname);
|
||||||
|
}
|
||||||
|
|
||||||
HashInit(&ResNodeTable, INITFLATSIZE, HT_STRINGKEYS);
|
HashInit(&ResNodeTable, INITFLATSIZE, HT_STRINGKEYS);
|
||||||
/* read in .sim file */
|
/* read in .sim file */
|
||||||
result = (ResReadSim(celldef->cd_name,
|
result = (ResReadSim(celldef->cd_name,
|
||||||
ResSimDevice, ResSimCapacitor, ResSimResistor,
|
ResSimDevice, ResSimCapacitor, ResSimResistor,
|
||||||
ResSimAttribute, ResSimMerge, ResSimSubckt) == 0);
|
ResSimAttribute, ResSimMerge, ResSimSubckt) == 0);
|
||||||
|
|
||||||
|
/* Clean up the EFDevTypes table */
|
||||||
|
for (idx = 0; idx < EFDevNumTypes; idx++) freeMagic(EFDevTypes[idx]);
|
||||||
|
EFDevNumTypes = 0;
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
/* read in .nodes file */
|
/* read in .nodes file */
|
||||||
result = (ResReadNode(celldef->cd_name) == 0);
|
result = (ResReadNode(celldef->cd_name) == 0);
|
||||||
|
|
@ -185,7 +204,7 @@ CmdExtResis(win, cmd)
|
||||||
TxCommand *cmd;
|
TxCommand *cmd;
|
||||||
{
|
{
|
||||||
int i, j, k, option, value, saveFlags;
|
int i, j, k, option, value, saveFlags;
|
||||||
static int init=1;
|
static int init = 1;
|
||||||
static float tolerance, tdiTolerance, fhFrequency;
|
static float tolerance, tdiTolerance, fhFrequency;
|
||||||
CellDef *mainDef;
|
CellDef *mainDef;
|
||||||
CellUse *selectedUse;
|
CellUse *selectedUse;
|
||||||
|
|
@ -246,6 +265,17 @@ typedef enum {
|
||||||
init = 0;
|
init = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initialize ResGlobalParams */
|
||||||
|
gparams.rg_ttype = TT_SPACE;
|
||||||
|
gparams.rg_Tdi = 0.0;
|
||||||
|
gparams.rg_nodecap = 0.0;
|
||||||
|
gparams.rg_maxres = 0.0;
|
||||||
|
gparams.rg_bigdevres = 0;
|
||||||
|
gparams.rg_tilecount = 0;
|
||||||
|
gparams.rg_status = 0;
|
||||||
|
gparams.rg_devloc = NULL;
|
||||||
|
gparams.rg_name = NULL;
|
||||||
|
|
||||||
option = (cmd->tx_argc > 1) ? Lookup(cmd->tx_argv[1], cmdExtresisCmd)
|
option = (cmd->tx_argc > 1) ? Lookup(cmd->tx_argv[1], cmdExtresisCmd)
|
||||||
: RES_RUN;
|
: RES_RUN;
|
||||||
|
|
||||||
|
|
@ -434,7 +464,7 @@ typedef enum {
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
Rect rect;
|
Rect rect;
|
||||||
int oldoptions;
|
int oldoptions;
|
||||||
ResFixPoint fp;
|
ResSimNode lnode;
|
||||||
|
|
||||||
if (ToolGetBoxWindow((Rect *) NULL, (int *) NULL) == NULL)
|
if (ToolGetBoxWindow((Rect *) NULL, (int *) NULL) == NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -449,23 +479,23 @@ typedef enum {
|
||||||
gparams.rg_ttype = tt;
|
gparams.rg_ttype = tt;
|
||||||
gparams.rg_status = DRIVEONLY;
|
gparams.rg_status = DRIVEONLY;
|
||||||
oldoptions = ResOptionsFlags;
|
oldoptions = ResOptionsFlags;
|
||||||
ResOptionsFlags = ResOpt_DoSubstrate|ResOpt_Signal|ResOpt_Box;
|
ResOptionsFlags = ResOpt_DoSubstrate | ResOpt_Signal | ResOpt_Box;
|
||||||
#ifdef LAPLACE
|
#ifdef LAPLACE
|
||||||
ResOptionsFlags |= (oldoptions & (ResOpt_CacheLaplace|ResOpt_DoLaplace));
|
ResOptionsFlags |= (oldoptions &
|
||||||
|
(ResOpt_CacheLaplace | ResOpt_DoLaplace));
|
||||||
LaplaceMatchCount = 0;
|
LaplaceMatchCount = 0;
|
||||||
LaplaceMissCount = 0;
|
LaplaceMissCount = 0;
|
||||||
#endif
|
#endif
|
||||||
fp.fp_ttype = tt;
|
lnode.location = rect.r_ll;
|
||||||
fp.fp_loc = rect.r_ll;
|
lnode.type = tt;
|
||||||
fp.fp_next = NULL;
|
if (ResExtractNet(&lnode, &gparams, NULL) != 0) return;
|
||||||
if (ResExtractNet(&fp, &gparams, NULL) != 0) return;
|
ResPrintResistorList(stdout, ResResList);
|
||||||
ResPrintResistorList(stdout,ResResList);
|
ResPrintDeviceList(stdout, ResRDevList);
|
||||||
ResPrintDeviceList(stdout,ResRDevList);
|
|
||||||
#ifdef LAPLACE
|
#ifdef LAPLACE
|
||||||
if (ResOptionsFlags & ResOpt_DoLaplace)
|
if (ResOptionsFlags & ResOpt_DoLaplace)
|
||||||
{
|
{
|
||||||
TxPrintf("Laplace solved: %d matched %d\n",
|
TxPrintf("Laplace solved: %d matched %d\n",
|
||||||
LaplaceMissCount,LaplaceMatchCount);
|
LaplaceMissCount, LaplaceMatchCount);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -492,11 +522,11 @@ typedef enum {
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
case RES_AMBIG:
|
case RES_AMBIG:
|
||||||
TxPrintf("Ambiguous option: %s\n",cmd->tx_argv[1]);
|
TxPrintf("Ambiguous option: %s\n", cmd->tx_argv[1]);
|
||||||
TxFlushOut();
|
TxFlushOut();
|
||||||
return;
|
return;
|
||||||
case RES_BAD:
|
case RES_BAD:
|
||||||
TxPrintf("Unknown option: %s\n",cmd->tx_argv[1]);
|
TxPrintf("Unknown option: %s\n", cmd->tx_argv[1]);
|
||||||
TxFlushOut();
|
TxFlushOut();
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
|
|
@ -519,7 +549,7 @@ typedef enum {
|
||||||
}
|
}
|
||||||
ResOptionsFlags |= ResOpt_Signal;
|
ResOptionsFlags |= ResOpt_Signal;
|
||||||
#ifdef ARIEL
|
#ifdef ARIEL
|
||||||
ResOptionsFlags &= ~ResOpt_Power;
|
ResOptionsFlags &= ~ResOpt_Power;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
resisdata.tolerance = tolerance;
|
resisdata.tolerance = tolerance;
|
||||||
|
|
@ -581,8 +611,6 @@ resSubcircuitFunc(cellDef, rdata)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -841,7 +869,7 @@ ResCheckSimNodes(celldef, resisdata)
|
||||||
}
|
}
|
||||||
if (ResOptionsFlags & ResOpt_DoLumpFile)
|
if (ResOptionsFlags & ResOpt_DoLumpFile)
|
||||||
{
|
{
|
||||||
ResLumpFile = PaOpen(outfile,"w",".res.lump",".",(char *) NULL, (char **) NULL);
|
ResLumpFile = PaOpen(outfile, "w", ".res.lump", ".", (char *)NULL, (char **)NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -850,7 +878,7 @@ ResCheckSimNodes(celldef, resisdata)
|
||||||
if (ResOptionsFlags & ResOpt_FastHenry)
|
if (ResOptionsFlags & ResOpt_FastHenry)
|
||||||
{
|
{
|
||||||
char *geofilename;
|
char *geofilename;
|
||||||
ResFHFile = PaOpen(outfile,"w",".fh",".",(char *) NULL, &geofilename);
|
ResFHFile = PaOpen(outfile, "w", ".fh", ".", (char *)NULL, &geofilename);
|
||||||
TxPrintf("Writing FastHenry-format geometry file \"%s\"\n", geofilename);
|
TxPrintf("Writing FastHenry-format geometry file \"%s\"\n", geofilename);
|
||||||
ResPortIndex = 0;
|
ResPortIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -961,7 +989,7 @@ ResCheckSimNodes(celldef, resisdata)
|
||||||
t1->drain != t2->source)) break;
|
t1->drain != t2->source)) break;
|
||||||
|
|
||||||
/* do parallel combination */
|
/* do parallel combination */
|
||||||
if (cumRes != 0.0 && t2->resistance != 0.0)
|
if ((cumRes != 0.0) && (t2->resistance != 0.0))
|
||||||
{
|
{
|
||||||
cumRes = (cumRes * t2->resistance) /
|
cumRes = (cumRes * t2->resistance) /
|
||||||
(cumRes + t2->resistance);
|
(cumRes + t2->resistance);
|
||||||
|
|
@ -998,32 +1026,32 @@ ResCheckSimNodes(celldef, resisdata)
|
||||||
gparams.rg_devloc = &node->drivepoint;
|
gparams.rg_devloc = &node->drivepoint;
|
||||||
gparams.rg_status |= DRIVEONLY;
|
gparams.rg_status |= DRIVEONLY;
|
||||||
}
|
}
|
||||||
if (node->status & PORTNODE)
|
if (node->status & PORTNODE)
|
||||||
{
|
{
|
||||||
/* The node is a port, not a device, so make */
|
/* The node is a port, not a device, so make */
|
||||||
/* sure rg_ttype is set accordingly. */
|
/* sure rg_ttype is set accordingly. */
|
||||||
gparams.rg_ttype = node->rs_ttype;
|
gparams.rg_ttype = node->rs_ttype;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (gparams.rg_devloc == NULL && node->status & FORCE)
|
if ((gparams.rg_devloc == NULL) && (node->status & FORCE))
|
||||||
{
|
{
|
||||||
TxError("Node %s has force label but no drive point or "
|
TxError("Node %s has force label but no drive point or "
|
||||||
"driving device\n",node->name);
|
"driving device\n",node->name);
|
||||||
}
|
}
|
||||||
if (minRes == FLT_MAX || gparams.rg_devloc == NULL)
|
if ((minRes == FLT_MAX) || (gparams.rg_devloc == NULL))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
gparams.rg_bigdevres = (int)minRes*OHMSTOMILLIOHMS;
|
gparams.rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS;
|
||||||
if (rctol == 0.0 || tol == 0.0)
|
if ((rctol == 0.0) || (tol == 0.0))
|
||||||
{
|
{
|
||||||
ftolerance = 0.0;
|
ftolerance = 0.0;
|
||||||
rctolerance = 0.0;
|
rctolerance = 0.0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ftolerance = minRes/tol;
|
ftolerance = minRes / tol;
|
||||||
rctolerance = minRes/rctol;
|
rctolerance = minRes / rctol;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1031,19 +1059,16 @@ ResCheckSimNodes(celldef, resisdata)
|
||||||
* resistance? If so, extract net.
|
* resistance? If so, extract net.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (node->resistance > ftolerance || node->status & FORCE ||
|
if ((node->resistance > ftolerance) || (node->status & FORCE) ||
|
||||||
(ResOpt_ExtractAll & ResOptionsFlags))
|
(ResOpt_ExtractAll & ResOptionsFlags))
|
||||||
{
|
{
|
||||||
ResFixPoint fp;
|
ResFixPoint fp;
|
||||||
|
|
||||||
failed1++;
|
failed1++;
|
||||||
fp.fp_loc = node->location;
|
if (ResExtractNet(node, &gparams, outfile) != 0)
|
||||||
fp.fp_ttype = node->type;
|
|
||||||
fp.fp_next = NULL;
|
|
||||||
if (ResExtractNet(&fp, &gparams, outfile) != 0)
|
|
||||||
{
|
{
|
||||||
TxError("Error in extracting node %s\n",node->name);
|
/* On error, don't output this net, but keep going */
|
||||||
// break; // Don't stop for one error. . .
|
TxError("Error in extracting node %s\n", node->name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1062,7 +1087,7 @@ ResCheckSimNodes(celldef, resisdata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef PARANOID
|
#ifdef PARANOID
|
||||||
ResSanityChecks(node->name,ResResList,ResNodeList,ResDevList);
|
ResSanityChecks(node->name, ResResList, ResNodeList, ResDevList);
|
||||||
#endif
|
#endif
|
||||||
ResCleanUpEverything();
|
ResCleanUpEverything();
|
||||||
}
|
}
|
||||||
|
|
@ -1075,7 +1100,7 @@ ResCheckSimNodes(celldef, resisdata)
|
||||||
|
|
||||||
if (ResOptionsFlags & ResOpt_DoExtFile)
|
if (ResOptionsFlags & ResOpt_DoExtFile)
|
||||||
{
|
{
|
||||||
ResPrintExtDev(ResExtFile,ResRDevList);
|
ResPrintExtDev(ResExtFile, ResRDevList);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -1182,7 +1207,7 @@ ResFixUpConnections(simDev, layoutDev, simNode, nodename)
|
||||||
|
|
||||||
if (simDev->gate == simNode)
|
if (simDev->gate == simNode)
|
||||||
{
|
{
|
||||||
if ((gate=layoutDev->rd_fet_gate) != NULL)
|
if ((gate = layoutDev->rd_fet_gate) != NULL)
|
||||||
{
|
{
|
||||||
/* Cosmetic addition: If the layout device already has a */
|
/* Cosmetic addition: If the layout device already has a */
|
||||||
/* name, the new one won't be used, so we decrement resNodeNum */
|
/* name, the new one won't be used, so we decrement resNodeNum */
|
||||||
|
|
@ -1398,9 +1423,10 @@ void
|
||||||
ResSortByGate(DevpointerList)
|
ResSortByGate(DevpointerList)
|
||||||
devPtr **DevpointerList;
|
devPtr **DevpointerList;
|
||||||
{
|
{
|
||||||
int changed=TRUE;
|
int changed = TRUE;
|
||||||
int localchange=TRUE;
|
int localchange = TRUE;
|
||||||
devPtr *working, *last=NULL, *current, *gatelist=NULL;
|
devPtr *working, *current;
|
||||||
|
devPtr *last = NULL, *gatelist = NULL;
|
||||||
|
|
||||||
working = *DevpointerList;
|
working = *DevpointerList;
|
||||||
while (working != NULL)
|
while (working != NULL)
|
||||||
|
|
@ -1526,7 +1552,7 @@ ResWriteLumpFile(node)
|
||||||
{
|
{
|
||||||
lumpedres = gparams.rg_maxres;
|
lumpedres = gparams.rg_maxres;
|
||||||
}
|
}
|
||||||
fprintf(ResLumpFile,"R %s %d\n", node->name, lumpedres);
|
fprintf(ResLumpFile, "R %s %d\n", node->name, lumpedres);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
1625
resis/ResSimple.c
1625
resis/ResSimple.c
File diff suppressed because it is too large
Load Diff
423
resis/ResUtils.c
423
resis/ResUtils.c
|
|
@ -62,27 +62,27 @@ ResFirst(tile, arg)
|
||||||
|
|
||||||
if (DBIsContact(t))
|
if (DBIsContact(t))
|
||||||
{
|
{
|
||||||
reg = (ResContactPoint *) mallocMagic((unsigned) (sizeof(ResContactPoint)));
|
reg = (ResContactPoint *) mallocMagic((unsigned) (sizeof(ResContactPoint)));
|
||||||
reg->cp_center.p_x = (LEFT(tile)+RIGHT(tile))>>1;
|
reg->cp_center.p_x = (LEFT(tile) + RIGHT(tile)) >> 1;
|
||||||
reg->cp_center.p_y = (TOP(tile)+BOTTOM(tile))>>1;
|
reg->cp_center.p_y = (TOP(tile) + BOTTOM(tile)) >> 1;
|
||||||
reg->cp_status = FALSE;
|
reg->cp_status = FALSE;
|
||||||
reg->cp_type = t;
|
reg->cp_type = t;
|
||||||
reg->cp_width = RIGHT(tile)-LEFT(tile);
|
reg->cp_width = RIGHT(tile) - LEFT(tile);
|
||||||
reg->cp_height = TOP(tile)-BOTTOM(tile);
|
reg->cp_height = TOP(tile) - BOTTOM(tile);
|
||||||
for (i=0; i< LAYERS_PER_CONTACT; i++)
|
for (i = 0; i < LAYERS_PER_CONTACT; i++)
|
||||||
{
|
{
|
||||||
reg->cp_tile[i] = (Tile *) NULL;
|
reg->cp_tile[i] = (Tile *) NULL;
|
||||||
reg->cp_cnode[i] = (resNode *) NULL;
|
reg->cp_cnode[i] = (resNode *) NULL;
|
||||||
}
|
}
|
||||||
reg->cp_currentcontact = 0;
|
reg->cp_currentcontact = 0;
|
||||||
reg->cp_rect.r_ll.p_x = tile->ti_ll.p_x;
|
reg->cp_rect.r_ll.p_x = tile->ti_ll.p_x;
|
||||||
reg->cp_rect.r_ll.p_y = tile->ti_ll.p_y;
|
reg->cp_rect.r_ll.p_y = tile->ti_ll.p_y;
|
||||||
reg->cp_rect.r_ur.p_x = RIGHT(tile);
|
reg->cp_rect.r_ur.p_x = RIGHT(tile);
|
||||||
reg->cp_rect.r_ur.p_y = TOP(tile);
|
reg->cp_rect.r_ur.p_y = TOP(tile);
|
||||||
reg->cp_contactTile = tile;
|
reg->cp_contactTile = tile;
|
||||||
/* Prepend it to the region list */
|
/* Prepend it to the region list */
|
||||||
reg->cp_nextcontact = (ResContactPoint *) arg->fra_region;
|
reg->cp_nextcontact = (ResContactPoint *) arg->fra_region;
|
||||||
arg->fra_region = (Region *) reg;
|
arg->fra_region = (Region *) reg;
|
||||||
}
|
}
|
||||||
return((Region *) NULL);
|
return((Region *) NULL);
|
||||||
}
|
}
|
||||||
|
|
@ -104,16 +104,16 @@ ResFirst(tile, arg)
|
||||||
|
|
||||||
int
|
int
|
||||||
ResEach(tile, pNum, arg)
|
ResEach(tile, pNum, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
int pNum;
|
int pNum;
|
||||||
FindRegion *arg;
|
FindRegion *arg;
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( ((ResContactPoint *)(arg->fra_region))->cp_contactTile != tile)
|
if (((ResContactPoint *)(arg->fra_region))->cp_contactTile != tile)
|
||||||
{
|
{
|
||||||
(void) ResFirst(tile, arg);
|
ResFirst(tile, arg);
|
||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -135,22 +135,21 @@ ResEach(tile, pNum, arg)
|
||||||
|
|
||||||
int
|
int
|
||||||
ResAddPlumbing(tile, arg)
|
ResAddPlumbing(tile, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
ClientData *arg;
|
ClientData *arg;
|
||||||
|
|
||||||
{
|
{
|
||||||
tileJunk *Junk,*junk2;
|
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;
|
||||||
resDevice *resDev;
|
resDevice *resDev;
|
||||||
ExtDevice *devptr;
|
ExtDevice *devptr;
|
||||||
|
|
||||||
if (resDevStack == NULL)
|
if (resDevStack == NULL)
|
||||||
resDevStack = StackNew(64);
|
resDevStack = StackNew(64);
|
||||||
|
|
||||||
if (tile->ti_client == (ClientData) CLIENTDEFAULT)
|
if (tile->ti_client == (ClientData) CLIENTDEFAULT)
|
||||||
{
|
{
|
||||||
if (IsSplit(tile))
|
if (IsSplit(tile))
|
||||||
loctype = (SplitSide(tile)) ? SplitRightType(tile) :
|
loctype = (SplitSide(tile)) ? SplitRightType(tile) :
|
||||||
SplitLeftType(tile);
|
SplitLeftType(tile);
|
||||||
|
|
@ -165,7 +164,7 @@ ResAddPlumbing(tile, arg)
|
||||||
|
|
||||||
/* Count SD terminals of the device */
|
/* Count SD terminals of the device */
|
||||||
nterms = 0;
|
nterms = 0;
|
||||||
for (i = 0; ; i++)
|
for (i = 0;; i++)
|
||||||
{
|
{
|
||||||
if (TTMaskIsZero(&(devptr->exts_deviceSDTypes[i]))) break;
|
if (TTMaskIsZero(&(devptr->exts_deviceSDTypes[i]))) break;
|
||||||
nterms++;
|
nterms++;
|
||||||
|
|
@ -181,7 +180,7 @@ ResAddPlumbing(tile, arg)
|
||||||
resDev = (resDevice *) mallocMagic((unsigned)(sizeof(resDevice)));
|
resDev = (resDevice *) mallocMagic((unsigned)(sizeof(resDevice)));
|
||||||
resDev->rd_nterms = nterms;
|
resDev->rd_nterms = nterms;
|
||||||
resDev->rd_terminals = (resNode **) mallocMagic(nterms * sizeof(resNode *));
|
resDev->rd_terminals = (resNode **) mallocMagic(nterms * sizeof(resNode *));
|
||||||
for (i=0; i != nterms;i++)
|
for (i = 0; i != nterms; i++)
|
||||||
resDev->rd_terminals[i] = (resNode *) NULL;
|
resDev->rd_terminals[i] = (resNode *) NULL;
|
||||||
|
|
||||||
resDev->rd_tile = tile;
|
resDev->rd_tile = tile;
|
||||||
|
|
@ -201,79 +200,91 @@ ResAddPlumbing(tile, arg)
|
||||||
junk2->deviceList = resDev;
|
junk2->deviceList = resDev;
|
||||||
junk2->tj_status |= RES_TILE_DEV;
|
junk2->tj_status |= RES_TILE_DEV;
|
||||||
|
|
||||||
source = NULL;
|
for (i = 0; i < nterms - 2; i++)
|
||||||
/* find diffusion (if present) to be source contact */
|
|
||||||
|
|
||||||
/* top */
|
|
||||||
for (tp2= RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2))
|
|
||||||
{
|
{
|
||||||
if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
|
source = NULL;
|
||||||
|
/* find diffusion (if present) to be source contact */
|
||||||
|
|
||||||
|
/* top */
|
||||||
|
for (tp2 = RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2))
|
||||||
|
{
|
||||||
|
if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
|
||||||
TiGetBottomType(tp2))
|
TiGetBottomType(tp2))
|
||||||
{
|
{
|
||||||
junk2->sourceEdge |= TOPEDGE;
|
junk2->sourceEdge |= TOPEDGE;
|
||||||
source = tp2;
|
source = tp2;
|
||||||
Junk = resAddField(source);
|
Junk = resAddField(source);
|
||||||
Junk->tj_status |= RES_TILE_SD;
|
Junk->tj_status |= RES_TILE_SD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*bottom*/
|
/* bottom */
|
||||||
if (source == NULL)
|
if (source == NULL)
|
||||||
for (tp2= LB(tile); LEFT(tp2) < RIGHT(tile); tp2 = TR(tp2))
|
for (tp2 = LB(tile); LEFT(tp2) < RIGHT(tile); tp2 = TR(tp2))
|
||||||
{
|
{
|
||||||
if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
|
if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
|
||||||
TiGetTopType(tp2))
|
TiGetTopType(tp2))
|
||||||
{
|
{
|
||||||
junk2->sourceEdge |= BOTTOMEDGE;
|
junk2->sourceEdge |= BOTTOMEDGE;
|
||||||
source = tp2;
|
source = tp2;
|
||||||
Junk = resAddField(source);
|
Junk = resAddField(source);
|
||||||
Junk->tj_status |= RES_TILE_SD;
|
Junk->tj_status |= RES_TILE_SD;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*right*/
|
/* right */
|
||||||
if (source == NULL)
|
if (source == NULL)
|
||||||
for (tp2= TR(tile); TOP(tp2) > BOTTOM(tile); tp2 = LB(tp2))
|
for (tp2 = TR(tile); TOP(tp2) > BOTTOM(tile); tp2 = LB(tp2))
|
||||||
{
|
{
|
||||||
if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
|
if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
|
||||||
TiGetLeftType(tp2))
|
TiGetLeftType(tp2))
|
||||||
{
|
{
|
||||||
junk2->sourceEdge |= RIGHTEDGE;
|
junk2->sourceEdge |= RIGHTEDGE;
|
||||||
source = tp2;
|
source = tp2;
|
||||||
Junk = resAddField(source);
|
Junk = resAddField(source);
|
||||||
Junk->tj_status |= RES_TILE_SD;
|
Junk->tj_status |= RES_TILE_SD;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*left*/
|
/* left */
|
||||||
if (source == NULL)
|
if (source == NULL)
|
||||||
for (tp2= BL(tile); BOTTOM(tp2) < TOP(tile); tp2 = RT(tp2))
|
for (tp2 = BL(tile); BOTTOM(tp2) < TOP(tile); tp2 = RT(tp2))
|
||||||
{
|
{
|
||||||
if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
|
if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
|
||||||
TiGetRightType(tp2))
|
TiGetRightType(tp2))
|
||||||
{
|
{
|
||||||
source = tp2;
|
source = tp2;
|
||||||
Junk = resAddField(source);
|
Junk = resAddField(source);
|
||||||
Junk->tj_status |= RES_TILE_SD;
|
Junk->tj_status |= RES_TILE_SD;
|
||||||
junk2->sourceEdge |= LEFTEDGE;
|
junk2->sourceEdge |= LEFTEDGE;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* other plane (in ResUse) */
|
||||||
|
if (source == NULL)
|
||||||
|
{
|
||||||
|
int pNum;
|
||||||
|
for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++)
|
||||||
|
{
|
||||||
|
/* XXX */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* We need to know whether a given diffusion tile connects to
|
/* We need to know whether a given diffusion tile connects to
|
||||||
* the source or to the drain of a device. A single
|
* the source or to the drain of a device. A single
|
||||||
* diffusion tile is marked, and all connecting diffusion tiles
|
* diffusion tile is marked, and all connecting diffusion tiles
|
||||||
* are enumerated and called the source. Any other SD tiles
|
* are enumerated and called the source. Any other SD tiles
|
||||||
* are assumed to be the drain. BUG: this does not work
|
* are assumed to be the drain. BUG: this does not work
|
||||||
* correctly with multi SD structures.
|
* correctly with multi SD structures.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (source != (Tile *) NULL)
|
if (source != (Tile *) NULL)
|
||||||
{
|
{
|
||||||
STACKPUSH((ClientData) (source),resDevStack);
|
STACKPUSH((ClientData)source, resDevStack);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while (!StackEmpty(resDevStack))
|
while (!StackEmpty(resDevStack))
|
||||||
{
|
{
|
||||||
|
|
@ -287,54 +298,54 @@ ResAddPlumbing(tile, arg)
|
||||||
t1 = TiGetTypeExact(tp1);
|
t1 = TiGetTypeExact(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)
|
||||||
{
|
{
|
||||||
tileJunk *j= resAddField(tp2);
|
tileJunk *j = resAddField(tp2);
|
||||||
if ((j->tj_status & RES_TILE_SD) ==0)
|
if ((j->tj_status & RES_TILE_SD) ==0)
|
||||||
{
|
{
|
||||||
j->tj_status |= RES_TILE_SD;
|
j->tj_status |= RES_TILE_SD;
|
||||||
STACKPUSH((ClientData)tp2,resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*bottom*/
|
/* bottom */
|
||||||
for (tp2= LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2))
|
for (tp2 = LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2))
|
||||||
{
|
{
|
||||||
if (TiGetTopType(tp2) == t1)
|
if (TiGetTopType(tp2) == t1)
|
||||||
{
|
{
|
||||||
tileJunk *j= resAddField(tp2);
|
tileJunk *j = resAddField(tp2);
|
||||||
if ((j->tj_status & RES_TILE_SD) == 0)
|
if ((j->tj_status & RES_TILE_SD) == 0)
|
||||||
{
|
{
|
||||||
j->tj_status |= RES_TILE_SD;
|
j->tj_status |= RES_TILE_SD;
|
||||||
STACKPUSH((ClientData) (tp2),resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*right*/
|
/* right */
|
||||||
for (tp2= TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2))
|
for (tp2 = TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2))
|
||||||
{
|
{
|
||||||
if (TiGetLeftType(tp2) == t1)
|
if (TiGetLeftType(tp2) == t1)
|
||||||
{
|
{
|
||||||
tileJunk *j= resAddField(tp2);
|
tileJunk *j = resAddField(tp2);
|
||||||
if ((j->tj_status & RES_TILE_SD) == 0)
|
if ((j->tj_status & RES_TILE_SD) == 0)
|
||||||
{
|
{
|
||||||
j->tj_status |= RES_TILE_SD;
|
j->tj_status |= RES_TILE_SD;
|
||||||
STACKPUSH((ClientData) (tp2),resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*left*/
|
/* left */
|
||||||
for (tp2= BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2))
|
for (tp2 = BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2))
|
||||||
{
|
{
|
||||||
if (TiGetRightType(tp2) == t1)
|
if (TiGetRightType(tp2) == t1)
|
||||||
{
|
{
|
||||||
tileJunk *j= resAddField(tp2);
|
tileJunk *j = resAddField(tp2);
|
||||||
if ((j->tj_status & RES_TILE_SD) == 0)
|
if ((j->tj_status & RES_TILE_SD) == 0)
|
||||||
{
|
{
|
||||||
j->tj_status |= RES_TILE_SD;
|
j->tj_status |= RES_TILE_SD;
|
||||||
STACKPUSH((ClientData) (tp2),resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -342,12 +353,12 @@ ResAddPlumbing(tile, arg)
|
||||||
|
|
||||||
/* find rest of device; search for source edges */
|
/* find rest of device; search for source edges */
|
||||||
|
|
||||||
STACKPUSH((ClientData) (tile), resDevStack);
|
STACKPUSH((ClientData)tile, resDevStack);
|
||||||
while (!StackEmpty(resDevStack))
|
while (!StackEmpty(resDevStack))
|
||||||
{
|
{
|
||||||
tileJunk *j0;
|
tileJunk *j0;
|
||||||
|
|
||||||
tp1= (Tile *) STACKPOP(resDevStack);
|
tp1 = (Tile *) STACKPOP(resDevStack);
|
||||||
if (IsSplit(tp1))
|
if (IsSplit(tp1))
|
||||||
{
|
{
|
||||||
t1 = (SplitSide(tp1)) ? SplitRightType(tp1) :
|
t1 = (SplitSide(tp1)) ? SplitRightType(tp1) :
|
||||||
|
|
@ -359,14 +370,14 @@ ResAddPlumbing(tile, arg)
|
||||||
devptr = ExtCurStyle->exts_device[t1];
|
devptr = ExtCurStyle->exts_device[t1];
|
||||||
j0 = (tileJunk *) tp1->ti_client;
|
j0 = (tileJunk *) tp1->ti_client;
|
||||||
/* 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) &&
|
||||||
(tp2->ti_client == (ClientData) CLIENTDEFAULT))
|
(tp2->ti_client == (ClientData) CLIENTDEFAULT))
|
||||||
{
|
{
|
||||||
Junk = resAddField(tp2);
|
Junk = resAddField(tp2);
|
||||||
STACKPUSH((ClientData)(tp2),resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
Junk->deviceList = resDev;
|
Junk->deviceList = resDev;
|
||||||
Junk->tj_status |= RES_TILE_DEV;
|
Junk->tj_status |= RES_TILE_DEV;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -378,14 +389,14 @@ ResAddPlumbing(tile, arg)
|
||||||
j0->sourceEdge |= TOPEDGE;
|
j0->sourceEdge |= TOPEDGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*bottom*/
|
/* bottom */
|
||||||
for (tp2= LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2))
|
for (tp2 = LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2))
|
||||||
{
|
{
|
||||||
if ((TiGetTopType(tp2) == t1) &&
|
if ((TiGetTopType(tp2) == t1) &&
|
||||||
(tp2->ti_client == (ClientData) CLIENTDEFAULT))
|
(tp2->ti_client == (ClientData) CLIENTDEFAULT))
|
||||||
{
|
{
|
||||||
Junk = resAddField(tp2);
|
Junk = resAddField(tp2);
|
||||||
STACKPUSH((ClientData)(tp2),resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
Junk->deviceList = resDev;
|
Junk->deviceList = resDev;
|
||||||
Junk->tj_status |= RES_TILE_DEV;
|
Junk->tj_status |= RES_TILE_DEV;
|
||||||
}
|
}
|
||||||
|
|
@ -397,33 +408,33 @@ ResAddPlumbing(tile, arg)
|
||||||
j0->sourceEdge |= BOTTOMEDGE;
|
j0->sourceEdge |= BOTTOMEDGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*right*/
|
/* right */
|
||||||
for (tp2= TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2))
|
for (tp2 = TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2))
|
||||||
{
|
{
|
||||||
if ((TiGetLeftType(tp2) == t1) &&
|
if ((TiGetLeftType(tp2) == t1) &&
|
||||||
(tp2->ti_client == (ClientData) CLIENTDEFAULT))
|
(tp2->ti_client == (ClientData) CLIENTDEFAULT))
|
||||||
{
|
{
|
||||||
Junk = resAddField(tp2);
|
Junk = resAddField(tp2);
|
||||||
STACKPUSH((ClientData)(tp2),resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
Junk->deviceList = resDev;
|
Junk->deviceList = resDev;
|
||||||
Junk->tj_status |= RES_TILE_DEV;
|
Junk->tj_status |= RES_TILE_DEV;
|
||||||
}
|
}
|
||||||
else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
|
else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),
|
||||||
TiGetLeftType(tp2))
|
TiGetLeftType(tp2))
|
||||||
{
|
{
|
||||||
Junk = resAddField(tp2);
|
Junk = resAddField(tp2);
|
||||||
if (Junk->tj_status & RES_TILE_SD)
|
if (Junk->tj_status & RES_TILE_SD)
|
||||||
j0->sourceEdge |= RIGHTEDGE;
|
j0->sourceEdge |= RIGHTEDGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*left*/
|
/* left */
|
||||||
for (tp2= BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2))
|
for (tp2 = BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2))
|
||||||
{
|
{
|
||||||
if ((TiGetRightType(tp2) == t1) &&
|
if ((TiGetRightType(tp2) == t1) &&
|
||||||
(tp2->ti_client == (ClientData) CLIENTDEFAULT))
|
(tp2->ti_client == (ClientData) CLIENTDEFAULT))
|
||||||
{
|
{
|
||||||
Junk = resAddField(tp2);
|
Junk = resAddField(tp2);
|
||||||
STACKPUSH((ClientData)(tp2),resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
Junk->deviceList = resDev;
|
Junk->deviceList = resDev;
|
||||||
Junk->tj_status |= RES_TILE_DEV;
|
Junk->tj_status |= RES_TILE_DEV;
|
||||||
}
|
}
|
||||||
|
|
@ -441,9 +452,9 @@ ResAddPlumbing(tile, arg)
|
||||||
|
|
||||||
if (source != (Tile *) NULL)
|
if (source != (Tile *) NULL)
|
||||||
{
|
{
|
||||||
tileJunk *j = (tileJunk *) source->ti_client;
|
tileJunk *j = (tileJunk *) source->ti_client;
|
||||||
|
|
||||||
STACKPUSH((ClientData) (source),resDevStack);
|
STACKPUSH((ClientData)source, resDevStack);
|
||||||
j->tj_status &= ~RES_TILE_SD;
|
j->tj_status &= ~RES_TILE_SD;
|
||||||
}
|
}
|
||||||
while (!StackEmpty(resDevStack))
|
while (!StackEmpty(resDevStack))
|
||||||
|
|
@ -458,54 +469,54 @@ ResAddPlumbing(tile, arg)
|
||||||
t1 = TiGetTypeExact(tp1);
|
t1 = TiGetTypeExact(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))
|
||||||
{
|
{
|
||||||
tileJunk *j2 = (tileJunk *) tp2->ti_client;
|
tileJunk *j2 = (tileJunk *) tp2->ti_client;
|
||||||
if (TiGetBottomType(tp2) == t1)
|
if (TiGetBottomType(tp2) == t1)
|
||||||
{
|
{
|
||||||
if (j2->tj_status & RES_TILE_SD)
|
if (j2->tj_status & RES_TILE_SD)
|
||||||
{
|
{
|
||||||
j2->tj_status &= ~RES_TILE_SD;
|
j2->tj_status &= ~RES_TILE_SD;
|
||||||
STACKPUSH((ClientData) tp2,resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*bottom*/
|
/* bottom */
|
||||||
for(tp2= LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2))
|
for(tp2 = LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2))
|
||||||
{
|
{
|
||||||
tileJunk *j2 = (tileJunk *) tp2->ti_client;
|
tileJunk *j2 = (tileJunk *) tp2->ti_client;
|
||||||
if (TiGetTopType(tp2) == t1)
|
if (TiGetTopType(tp2) == t1)
|
||||||
{
|
{
|
||||||
if (j2->tj_status & RES_TILE_SD)
|
if (j2->tj_status & RES_TILE_SD)
|
||||||
{
|
{
|
||||||
j2->tj_status &= ~RES_TILE_SD;
|
j2->tj_status &= ~RES_TILE_SD;
|
||||||
STACKPUSH((ClientData) tp2,resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*right*/
|
/* right */
|
||||||
for (tp2= TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2))
|
for (tp2 = TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2))
|
||||||
{
|
{
|
||||||
tileJunk *j2 = (tileJunk *) tp2->ti_client;
|
tileJunk *j2 = (tileJunk *) tp2->ti_client;
|
||||||
if (TiGetLeftType(tp2) == t1)
|
if (TiGetLeftType(tp2) == t1)
|
||||||
{
|
{
|
||||||
if (j2->tj_status & RES_TILE_SD)
|
if (j2->tj_status & RES_TILE_SD)
|
||||||
{
|
{
|
||||||
j2->tj_status &= ~RES_TILE_SD;
|
j2->tj_status &= ~RES_TILE_SD;
|
||||||
STACKPUSH((ClientData) tp2,resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*left*/
|
/* left */
|
||||||
for (tp2= BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2))
|
for (tp2 = BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2))
|
||||||
{
|
{
|
||||||
tileJunk *j2 = (tileJunk *) tp2->ti_client;
|
tileJunk *j2 = (tileJunk *) tp2->ti_client;
|
||||||
if (TiGetRightType(tp2) == t1)
|
if (TiGetRightType(tp2) == t1)
|
||||||
{
|
{
|
||||||
if (j2->tj_status & RES_TILE_SD)
|
if (j2->tj_status & RES_TILE_SD)
|
||||||
{
|
{
|
||||||
j2->tj_status &= ~RES_TILE_SD;
|
j2->tj_status &= ~RES_TILE_SD;
|
||||||
STACKPUSH((ClientData) tp2,resDevStack);
|
STACKPUSH((ClientData)tp2, resDevStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -529,24 +540,24 @@ ResAddPlumbing(tile, arg)
|
||||||
|
|
||||||
int
|
int
|
||||||
ResRemovePlumbing(tile, arg)
|
ResRemovePlumbing(tile, arg)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
ClientData *arg;
|
ClientData *arg;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
if (tile->ti_client != (ClientData) CLIENTDEFAULT)
|
if (tile->ti_client != (ClientData) CLIENTDEFAULT)
|
||||||
{
|
{
|
||||||
freeMagic(((char *)(tile->ti_client)));
|
freeMagic(((char *)(tile->ti_client)));
|
||||||
tile->ti_client = (ClientData) CLIENTDEFAULT;
|
tile->ti_client = (ClientData) CLIENTDEFAULT;
|
||||||
}
|
}
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* ResPreprocessDevices-- Given a list of all the device tiles and
|
* ResPreProcessDevices-- Given a list of all the device tiles and
|
||||||
* a list of all the devices, this procedure calculates the width and
|
* a list of all the devices, this procedure calculates the width and
|
||||||
* length. The width is set equal to the sum of all edges that touch
|
* length. The width is set equal to the sum of all edges that touch
|
||||||
* diffusion divided by 2. The length is the remaining perimeter divided by
|
* diffusion divided by 2. The length is the remaining perimeter divided by
|
||||||
|
|
@ -604,8 +615,9 @@ ResPreProcessDevices(TileList, DeviceList, Def)
|
||||||
tt = TiGetType(tile);
|
tt = TiGetType(tile);
|
||||||
tstruct = (tileJunk *) tile->ti_client;
|
tstruct = (tileJunk *) tile->ti_client;
|
||||||
|
|
||||||
if (!TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt) ||
|
if ((tstruct == (tileJunk *)CLIENTDEFAULT) ||
|
||||||
tstruct->deviceList == NULL)
|
(tstruct->deviceList == NULL) ||
|
||||||
|
!TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt))
|
||||||
{
|
{
|
||||||
TxError("Bad Device Location at %d,%d\n",
|
TxError("Bad Device Location at %d,%d\n",
|
||||||
TileList->area.r_ll.p_x,
|
TileList->area.r_ll.p_x,
|
||||||
|
|
@ -627,7 +639,7 @@ ResPreProcessDevices(TileList, DeviceList, Def)
|
||||||
freeMagic((char *)oldTile);
|
freeMagic((char *)oldTile);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(; DeviceList != NULL;DeviceList = DeviceList->rd_nextDev)
|
for (; DeviceList != NULL; DeviceList = DeviceList->rd_nextDev)
|
||||||
{
|
{
|
||||||
int width = DeviceList->rd_perim;
|
int width = DeviceList->rd_perim;
|
||||||
int length = DeviceList->rd_length;
|
int length = DeviceList->rd_length;
|
||||||
|
|
@ -666,18 +678,17 @@ ResPreProcessDevices(TileList, DeviceList, Def)
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ResAddToQueue(node,list)
|
ResAddToQueue(node, list)
|
||||||
resNode *node,**list;
|
resNode *node, **list;
|
||||||
{
|
{
|
||||||
|
node->rn_more = *list;
|
||||||
node->rn_more = *list;
|
node->rn_less = NULL;
|
||||||
node->rn_less = NULL;
|
if (*list) (*list)->rn_less = node;
|
||||||
if (*list) (*list)->rn_less = node;
|
*list = node;
|
||||||
*list = node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -692,44 +703,42 @@ ResAddToQueue(node,list)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ResRemoveFromQueue(node,list)
|
ResRemoveFromQueue(node, list)
|
||||||
resNode *node,**list;
|
resNode *node, **list;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
if (node->rn_less != NULL)
|
||||||
if (node->rn_less != NULL)
|
{
|
||||||
{
|
node->rn_less->rn_more = node->rn_more;
|
||||||
node->rn_less->rn_more = node->rn_more;
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
if (node != (*list))
|
||||||
if (node != (*list))
|
{
|
||||||
{
|
TxError("Error: Attempt to remove node from wrong list\n");
|
||||||
TxError("Error: Attempt to remove node from wrong list\n");
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
*list = node->rn_more;
|
||||||
*list = node->rn_more;
|
}
|
||||||
}
|
}
|
||||||
}
|
if (node->rn_more != NULL)
|
||||||
if (node->rn_more != NULL)
|
{
|
||||||
{
|
node->rn_more->rn_less = node->rn_less;
|
||||||
node->rn_more->rn_less = node->rn_less;
|
}
|
||||||
}
|
node->rn_more = NULL;
|
||||||
node->rn_more = NULL;
|
node->rn_less = NULL;
|
||||||
node->rn_less = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tileJunk *
|
tileJunk *
|
||||||
resAddField(tile)
|
resAddField(tile)
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
|
||||||
{
|
{
|
||||||
tileJunk *Junk;
|
tileJunk *Junk;
|
||||||
if ((Junk=(tileJunk *)tile->ti_client) == (tileJunk *) CLIENTDEFAULT)
|
if ((Junk = (tileJunk *)tile->ti_client) == (tileJunk *) CLIENTDEFAULT)
|
||||||
{
|
{
|
||||||
Junk = (tileJunk *) mallocMagic((unsigned) (sizeof(tileJunk)));
|
Junk = (tileJunk *) mallocMagic((unsigned) (sizeof(tileJunk)));
|
||||||
ResJunkInit(Junk);
|
ResJunkInit(Junk);
|
||||||
tile->ti_client = (ClientData) Junk;
|
tile->ti_client = (ClientData) Junk;
|
||||||
}
|
}
|
||||||
return Junk;
|
return Junk;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
246
resis/ResWrite.c
246
resis/ResWrite.c
|
|
@ -47,78 +47,76 @@ ResPrintNetwork(filename, reslist)
|
||||||
resResistor *reslist;
|
resResistor *reslist;
|
||||||
|
|
||||||
{
|
{
|
||||||
char bigname[255],name1[255],name2[255];
|
char bigname[255], name1[255], name2[255];
|
||||||
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int i=1;
|
int i = 1;
|
||||||
|
|
||||||
sprintf(bigname,"%s.%s",filename,"res");
|
sprintf(bigname, "%s.%s", filename, "res");
|
||||||
fp = fopen(bigname,"w");
|
fp = fopen(bigname, "w");
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
{
|
{
|
||||||
for (;reslist;reslist=reslist->rr_nextResistor)
|
for (; reslist; reslist = reslist->rr_nextResistor)
|
||||||
{
|
{
|
||||||
if (reslist->rr_connection1->rn_id == 0)
|
if (reslist->rr_connection1->rn_id == 0)
|
||||||
{
|
{
|
||||||
reslist->rr_connection1->rn_id = i++;
|
reslist->rr_connection1->rn_id = i++;
|
||||||
}
|
}
|
||||||
if (reslist->rr_connection2->rn_id == 0)
|
if (reslist->rr_connection2->rn_id == 0)
|
||||||
{
|
{
|
||||||
reslist->rr_connection2->rn_id = i++;
|
reslist->rr_connection2->rn_id = i++;
|
||||||
}
|
}
|
||||||
if (reslist->rr_connection1->rn_why == RES_NODE_ORIGIN)
|
if (reslist->rr_connection1->rn_why == RES_NODE_ORIGIN)
|
||||||
{
|
{
|
||||||
sprintf(name1,"gnd");
|
sprintf(name1, "gnd");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf(name1,"n%d_%d_%d",
|
sprintf(name1, "n%d_%d_%d",
|
||||||
reslist->rr_connection1->rn_id,
|
reslist->rr_connection1->rn_id,
|
||||||
reslist->rr_connection1->rn_loc.p_x,
|
reslist->rr_connection1->rn_loc.p_x,
|
||||||
reslist->rr_connection1->rn_loc.p_y);
|
reslist->rr_connection1->rn_loc.p_y);
|
||||||
}
|
}
|
||||||
if (reslist->rr_connection2->rn_why == RES_NODE_ORIGIN)
|
if (reslist->rr_connection2->rn_why == RES_NODE_ORIGIN)
|
||||||
{
|
{
|
||||||
sprintf(name2,"gnd");
|
sprintf(name2,"gnd");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf(name2,"n%d_%d_%d",
|
sprintf(name2, "n%d_%d_%d",
|
||||||
reslist->rr_connection2->rn_id,
|
reslist->rr_connection2->rn_id,
|
||||||
reslist->rr_connection2->rn_loc.p_x,
|
reslist->rr_connection2->rn_loc.p_x,
|
||||||
reslist->rr_connection2->rn_loc.p_y);
|
reslist->rr_connection2->rn_loc.p_y);
|
||||||
}
|
}
|
||||||
fprintf(fp,"r %s %s %f\n",name1,name2,
|
fprintf(fp, "r %s %s %f\n", name1, name2,
|
||||||
(float)(reslist->rr_value)*MILLITOKILO);
|
(float)(reslist->rr_value) * MILLITOKILO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ResPrintCurrents(filename,extension,node)
|
ResPrintCurrents(filename, extension, node)
|
||||||
char *filename;
|
char *filename;
|
||||||
float extension;
|
float extension;
|
||||||
resNode *node;
|
resNode *node;
|
||||||
|
|
||||||
{
|
{
|
||||||
char bigname[255];
|
char bigname[255];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int resCurrentPrintFunc();
|
int resCurrentPrintFunc();
|
||||||
|
|
||||||
sprintf(bigname,"%s.%d",filename,abs((int)(extension)));
|
sprintf(bigname, "%s.%d", filename, abs((int)(extension)));
|
||||||
|
|
||||||
fp = fopen(bigname,"w");
|
fp = fopen(bigname, "w");
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
{
|
{
|
||||||
(void) ResTreeWalk(node,NULL,resCurrentPrintFunc,
|
(void) ResTreeWalk(node, NULL, resCurrentPrintFunc,
|
||||||
RES_DO_FIRST,RES_NO_LOOP,RES_NO_FLAGS,fp);
|
RES_DO_FIRST, RES_NO_LOOP, RES_NO_FLAGS, fp);
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -130,100 +128,98 @@ ResPrintCurrents(filename,extension,node)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
resCurrentPrintFunc(node,resistor,filename)
|
resCurrentPrintFunc(node, resistor, filename)
|
||||||
resNode *node;
|
resNode *node;
|
||||||
resResistor *resistor;
|
resResistor *resistor;
|
||||||
FILE *filename;
|
FILE *filename;
|
||||||
|
|
||||||
{
|
{
|
||||||
tElement *workingDev;
|
tElement *workingDev;
|
||||||
float i_sum=0.0;
|
float i_sum = 0.0;
|
||||||
|
|
||||||
for (workingDev = node->rn_te; workingDev != NULL;
|
for (workingDev = node->rn_te; workingDev != NULL;
|
||||||
workingDev=workingDev->te_nextt)
|
workingDev = workingDev->te_nextt)
|
||||||
{
|
{
|
||||||
if ((workingDev->te_thist->rd_status & RES_DEV_PLUG) ||
|
if ((workingDev->te_thist->rd_status & RES_DEV_PLUG) ||
|
||||||
workingDev->te_thist->rd_gate != node)
|
workingDev->te_thist->rd_gate != node)
|
||||||
i_sum += workingDev->te_thist->rd_i;
|
i_sum += workingDev->te_thist->rd_i;
|
||||||
}
|
}
|
||||||
if (i_sum != 0.0)
|
if (i_sum != 0.0)
|
||||||
{
|
{
|
||||||
if (node->rn_why == RES_NODE_ORIGIN)
|
if (node->rn_why == RES_NODE_ORIGIN)
|
||||||
{
|
{
|
||||||
fprintf(filename,"i gnd %f\n",i_sum);
|
fprintf(filename, "i gnd %f\n", i_sum);
|
||||||
|
}
|
||||||
}
|
else
|
||||||
else
|
{
|
||||||
{
|
fprintf(filename, "i n%d_%d %f\n", node->rn_loc.p_x,
|
||||||
fprintf(filename,"i n%d_%d %f\n",node->rn_loc.p_x,
|
node->rn_loc.p_y, i_sum);
|
||||||
node->rn_loc.p_y,i_sum);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ResDeviceCounts()
|
ResDeviceCounts()
|
||||||
{
|
{
|
||||||
int i,j,k;
|
int i,j,k;
|
||||||
resNode *n;
|
resNode *n;
|
||||||
resDevice *t;
|
resDevice *t;
|
||||||
resResistor *r;
|
resResistor *r;
|
||||||
|
|
||||||
for (n=ResNodeList,i=0;n!=NULL;n=n->rn_more,i++);
|
for (n = ResNodeList, i = 0; n != NULL; n = n->rn_more, i++);
|
||||||
for (t=ResDevList,j=0;t!=NULL;t=t->rd_nextDev,j++);
|
for (t = ResDevList, j = 0; t != NULL; t = t->rd_nextDev, j++);
|
||||||
for (r=ResResList,k=0;r!=NULL;r=r->rr_nextResistor,k++);
|
for (r = ResResList, k = 0; r != NULL; r = r->rr_nextResistor, k++);
|
||||||
TxError("n=%d t=%d r=%d\n",i,j,k);
|
TxError("n=%d t=%d r=%d\n", i, j, k);
|
||||||
TxFlushErr();
|
TxFlushErr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ResWriteECLFile(filename,reslist,nodelist)
|
ResWriteECLFile(filename, reslist, nodelist)
|
||||||
char *filename;
|
char *filename;
|
||||||
resResistor *reslist;
|
resResistor *reslist;
|
||||||
resNode *nodelist;
|
resNode *nodelist;
|
||||||
|
|
||||||
{
|
{
|
||||||
char newname[100],*tmpname,*per;
|
char newname[100], *tmpname, *per;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int nodenum = 0;
|
int nodenum = 0;
|
||||||
|
|
||||||
strcpy(newname,filename);
|
strcpy(newname, filename);
|
||||||
if (per = strrchr(newname,'.')) *per = '\0';
|
if (per = strrchr(newname,'.')) *per = '\0';
|
||||||
strcat(newname,".res");
|
strcat(newname, ".res");
|
||||||
|
|
||||||
if ((fp = fopen(newname,"w")) == NULL)
|
if ((fp = fopen(newname, "w")) == NULL)
|
||||||
{
|
{
|
||||||
TxError("Can't open %s\n",newname);
|
TxError("Can't open %s\n", newname);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (;nodelist;nodelist=nodelist->rn_more)
|
for (; nodelist; nodelist = nodelist->rn_more)
|
||||||
{
|
{
|
||||||
if (nodelist->rn_name == NULL)
|
if (nodelist->rn_name == NULL)
|
||||||
{
|
{
|
||||||
if (nodelist->rn_noderes == 0)
|
if (nodelist->rn_noderes == 0)
|
||||||
{
|
{
|
||||||
strcpy(newname,"gnd");
|
strcpy(newname, "gnd");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
(void)sprintf(newname,"n%d_%d_%d",nodelist->rn_loc.p_x,
|
(void)sprintf(newname, "n%d_%d_%d", nodelist->rn_loc.p_x,
|
||||||
nodelist->rn_loc.p_y,nodenum++);
|
nodelist->rn_loc.p_y, nodenum++);
|
||||||
}
|
}
|
||||||
tmpname = (char *) mallocMagic((unsigned) (strlen(newname)+1));
|
tmpname = (char *)mallocMagic((unsigned) (strlen(newname) + 1));
|
||||||
strcpy(tmpname,newname);
|
strcpy(tmpname, newname);
|
||||||
nodelist->rn_name = tmpname;
|
nodelist->rn_name = tmpname;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (;reslist;reslist = reslist->rr_nextResistor)
|
for (; reslist; reslist = reslist->rr_nextResistor)
|
||||||
{
|
{
|
||||||
|
fprintf(fp, "r %s %s %f %s %d\n",
|
||||||
fprintf(fp,"r %s %s %f %s %d\n",
|
reslist->rr_node[0]->rn_name,
|
||||||
reslist->rr_node[0]->rn_name,reslist->rr_node[1]->rn_name,
|
reslist->rr_node[1]->rn_name,
|
||||||
/* /1000.0 gets ohms from milliohms */
|
/* /1000.0 gets ohms from milliohms */
|
||||||
(float)(reslist->rr_value)/1000.0,
|
(float)(reslist->rr_value) / 1000.0,
|
||||||
DBTypeShortName(reslist->rr_tt),reslist->rr_csArea);
|
DBTypeShortName(reslist->rr_tt), reslist->rr_csArea);
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -247,6 +247,7 @@ typedef struct resdevtile
|
||||||
struct resdevtile *nextDev;
|
struct resdevtile *nextDev;
|
||||||
Rect area;
|
Rect area;
|
||||||
TileType type;
|
TileType type;
|
||||||
|
ExtDevice *devptr;
|
||||||
int perim;
|
int perim;
|
||||||
int overlap;
|
int overlap;
|
||||||
} ResDevTile;
|
} ResDevTile;
|
||||||
|
|
@ -297,7 +298,8 @@ typedef struct rdev
|
||||||
Point location; /* Location of lower left point of */
|
Point location; /* Location of lower left point of */
|
||||||
/* device. */
|
/* device. */
|
||||||
float resistance; /* "Resistance" of device. */
|
float resistance; /* "Resistance" of device. */
|
||||||
int rs_ttype; /* device type */
|
TileType rs_ttype; /* tile type for device */
|
||||||
|
ExtDevice *rs_devptr; /* device extraction record */
|
||||||
char *rs_gattr; /* Gate attributes, if any */
|
char *rs_gattr; /* Gate attributes, if any */
|
||||||
char *rs_sattr;
|
char *rs_sattr;
|
||||||
char *rs_dattr;
|
char *rs_dattr;
|
||||||
|
|
@ -512,6 +514,7 @@ typedef struct capval
|
||||||
#define RIGHTEDGE 4
|
#define RIGHTEDGE 4
|
||||||
#define TOPEDGE 8
|
#define TOPEDGE 8
|
||||||
#define BOTTOMEDGE 16
|
#define BOTTOMEDGE 16
|
||||||
|
#define OTHERPLANE 32
|
||||||
|
|
||||||
#define RN_MAXTDI 0x00001000
|
#define RN_MAXTDI 0x00001000
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,8 @@ extern int GeoRectPointSide(Rect *, Point *);
|
||||||
extern int GeoRectRectSide(Rect *, Rect *);
|
extern int GeoRectRectSide(Rect *, Rect *);
|
||||||
extern void GeoIncludePoint(Point *, Rect *);
|
extern void GeoIncludePoint(Point *, Rect *);
|
||||||
extern void GeoDecomposeTransform(Transform *, bool *, int *);
|
extern void GeoDecomposeTransform(Transform *, bool *, int *);
|
||||||
extern void GeoIncludeRectInBBox(Rect *, Rect *bbox);
|
extern void GeoIncludeRectInBBox(Rect *, Rect *);
|
||||||
|
extern void GeoCanonicalRect(Rect *, Rect *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------
|
*-------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -417,11 +417,12 @@ HeapAdd(heap, pKey, id)
|
||||||
{
|
{
|
||||||
/* If odd then new entry is the right half of a pair */
|
/* If odd then new entry is the right half of a pair */
|
||||||
cmp = i;
|
cmp = i;
|
||||||
if (i & 1)
|
if ((i & 1) && (i != 1))
|
||||||
KEY_LE_COND(keyType, list, i, i-1, cmp = i-1);
|
KEY_LE_COND(keyType, list, i, i-1, cmp = i-1);
|
||||||
|
|
||||||
/* Find parent. If 0 then at the root so quit */
|
/* Find parent. If 0 then at the root so quit */
|
||||||
if ((i >>= 1) == 0) return;
|
if ((i >>= 1) == 0) return;
|
||||||
|
|
||||||
KEY_LE_COND(keyType, list, cmp, i, return);
|
KEY_LE_COND(keyType, list, cmp, i, return);
|
||||||
list[0] = list[cmp]; list[cmp] = list[i]; list[i] = list[0];
|
list[0] = list[cmp]; list[cmp] = list[i]; list[i] = list[0];
|
||||||
heapify(heap, cmp);
|
heapify(heap, cmp);
|
||||||
|
|
@ -434,11 +435,12 @@ HeapAdd(heap, pKey, id)
|
||||||
{
|
{
|
||||||
/* If odd then new entry is the right half of a pair */
|
/* If odd then new entry is the right half of a pair */
|
||||||
cmp = i;
|
cmp = i;
|
||||||
if (i & 1)
|
if ((i & 1) && (i != 1))
|
||||||
KEY_GE_COND(keyType, list, i, i-1, cmp = i-1);
|
KEY_GE_COND(keyType, list, i, i-1, cmp = i-1);
|
||||||
|
|
||||||
/* Find parent. If 0 then at the root so quit */
|
/* Find parent. If 0 then at the root so quit */
|
||||||
if ((i >>= 1) == 0) return;
|
if ((i >>= 1) == 0) return;
|
||||||
|
|
||||||
KEY_GE_COND(keyType, list, cmp, i, return);
|
KEY_GE_COND(keyType, list, cmp, i, return);
|
||||||
list[0] = list[cmp]; list[cmp] = list[i]; list[i] = list[0];
|
list[0] = list[cmp]; list[cmp] = list[i]; list[i] = list[0];
|
||||||
heapify(heap, cmp);
|
heapify(heap, cmp);
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ static __inline__ int IHashAlignedSize(int size)
|
||||||
int result;
|
int result;
|
||||||
/* Expand size to be double-word (64 bit) aligned */
|
/* Expand size to be double-word (64 bit) aligned */
|
||||||
result = ((size + 7) / 8) * 8;
|
result = ((size + 7) / 8) * 8;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The IHashTable struct should not be manipulated directly by clients */
|
/* The IHashTable struct should not be manipulated directly by clients */
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,7 @@ TechSectionGetMask(sectionName, depend)
|
||||||
{
|
{
|
||||||
invid |= tsp->ts_thisSect;
|
invid |= tsp->ts_thisSect;
|
||||||
if (tsp->ts_prevSects & thissect->ts_thisSect)
|
if (tsp->ts_prevSects & thissect->ts_thisSect)
|
||||||
if (depend != NULL) *depend != tsp->ts_thisSect;
|
if (depend != NULL) *depend = tsp->ts_thisSect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return invid;
|
return invid;
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header$";
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <ctype.h> /* for isalnum() */
|
||||||
|
|
||||||
#include "utils/magic.h"
|
#include "utils/magic.h"
|
||||||
#include "utils/geometry.h"
|
#include "utils/geometry.h"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue