Merge branch 'RTimothyEdwards:master' into spice_hier
This commit is contained in:
commit
f6b4671d96
|
|
@ -882,7 +882,8 @@ calmaElementSref(filename)
|
|||
if (rtype == CALMA_PROPATTR)
|
||||
{
|
||||
READI2(propAttrType);
|
||||
if (propAttrType == CALMA_PROP_USENAME)
|
||||
if (propAttrType == CALMA_PROP_USENAME ||
|
||||
propAttrType == CALMA_PROP_USENAME_STD)
|
||||
{
|
||||
char *s;
|
||||
|
||||
|
|
@ -1262,7 +1263,19 @@ calmaFindCell(name, was_called, predefined)
|
|||
if (was_called) *was_called = FALSE;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "textio/textio.h"
|
||||
#include "calma/calmaInt.h"
|
||||
#include "commands/commands.h" /* for CmdGetRootPoint */
|
||||
#include "utils/main.h" /* for EditCellUse */
|
||||
#include "utils/undo.h"
|
||||
|
||||
/* Globals for Calma reading */
|
||||
|
|
@ -164,6 +165,12 @@ CalmaReadFile(file, filename)
|
|||
static int skipBeforeLib[] = { CALMA_LIBDIRSIZE, CALMA_SRFNAME,
|
||||
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 */
|
||||
CIFReadCellInit(0);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ static char rcsid[] __attribute__ ((unused)) ="$Header: /usr/cvsroot/magic-8.0/c
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <arpa/inet.h> /* for htons() */
|
||||
#ifdef SYSV
|
||||
#include <time.h>
|
||||
#else
|
||||
|
|
@ -146,6 +147,7 @@ int calmaPaintLayerType;
|
|||
*/
|
||||
HashTable calmaLibHash;
|
||||
HashTable calmaPrefixHash;
|
||||
HashTable calmaUndefHash;
|
||||
|
||||
/* Imports */
|
||||
extern time_t time();
|
||||
|
|
@ -285,6 +287,8 @@ CalmaWrite(rootDef, f)
|
|||
int oldCount = DBWFeedbackCount, problems;
|
||||
bool good;
|
||||
CellUse dummy;
|
||||
HashEntry *he;
|
||||
HashSearch hs;
|
||||
|
||||
/*
|
||||
* Do not attempt to write anything if a CIF/GDS output style
|
||||
|
|
@ -298,6 +302,7 @@ CalmaWrite(rootDef, f)
|
|||
|
||||
HashInit(&calmaLibHash, 32, 0);
|
||||
HashInit(&calmaPrefixHash, 32, 0);
|
||||
HashInit(&calmaUndefHash, 32, 0);
|
||||
|
||||
/*
|
||||
* 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
|
||||
* 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 */
|
||||
calmaOutRH(4, CALMA_ENDLIB, CALMA_NODATA, f);
|
||||
|
|
@ -355,6 +384,7 @@ CalmaWrite(rootDef, f)
|
|||
|
||||
HashFreeKill(&calmaLibHash);
|
||||
HashKill(&calmaPrefixHash);
|
||||
HashFreeKill(&calmaUndefHash);
|
||||
return (good);
|
||||
}
|
||||
|
||||
|
|
@ -409,14 +439,47 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
|
|||
calmaOutDate(def->cd_timestamp, outf);
|
||||
calmaOutDate(time((time_t *) 0), outf);
|
||||
|
||||
/* Find the structure's unique prefix, in case structure calls subcells */
|
||||
/* that are not yet defined. */
|
||||
/* Do a quick check of the calmaUndefHash table to see if this cell */
|
||||
/* was previously used in a GDS file that does not define it (a GDS */
|
||||
/* addendum library). */
|
||||
|
||||
he = HashLookOnly(&calmaUndefHash, strname);
|
||||
if (he != NULL)
|
||||
{
|
||||
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
|
||||
{
|
||||
/* 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 */
|
||||
he = HashFind(calmaDefHash, strname);
|
||||
|
|
@ -456,16 +519,20 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
|
|||
if (edef != NULL)
|
||||
{
|
||||
bool isAbstract, isReadOnly;
|
||||
char *chklibname, *dotptr;
|
||||
char *chklibname, *filenamesubbed = NULL;
|
||||
|
||||
/* Is view abstract? */
|
||||
DBPropGet(edef, "LEFview", &isAbstract);
|
||||
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 && !strcmp(filename, chklibname))
|
||||
if (isAbstract && isReadOnly)
|
||||
{
|
||||
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 */
|
||||
/* as having been written to GDS. */
|
||||
|
|
@ -487,7 +554,7 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
|
|||
HashSetValue(he, (char *)newnameptr);
|
||||
}
|
||||
}
|
||||
if (dotptr) *dotptr = '.';
|
||||
if (filenamesubbed) freeMagic(filenamesubbed);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -614,11 +681,12 @@ calmaFullDump(def, fi, outf, filename)
|
|||
char *filename;
|
||||
{
|
||||
int version, rval;
|
||||
char *libname = NULL, uniqlibname[4];
|
||||
char *libname = NULL, *testlib, uniqlibname[4];
|
||||
char *sptr, *viewopts;
|
||||
bool isAbstract;
|
||||
HashTable calmaDefHash;
|
||||
HashEntry *he;
|
||||
HashSearch hs;
|
||||
HashEntry *he, *he2;
|
||||
|
||||
static int hdrSkip[] = { CALMA_FORMAT, CALMA_MASK, CALMA_ENDMASKS,
|
||||
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.
|
||||
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",
|
||||
* then do not create a unique prefix for subcells. This is generally
|
||||
|
|
@ -672,8 +745,6 @@ calmaFullDump(def, fi, outf, filename)
|
|||
*/
|
||||
while (TRUE)
|
||||
{
|
||||
HashEntry *he2;
|
||||
|
||||
rval = random() % 26;
|
||||
rval = 'A' + rval;
|
||||
uniqlibname[0] = (char)(rval & 127);
|
||||
|
|
@ -700,6 +771,24 @@ calmaFullDump(def, fi, outf, filename)
|
|||
calmaSkipExact(CALMA_ENDLIB);
|
||||
|
||||
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);
|
||||
if (libname != NULL) freeMagic(libname);
|
||||
return;
|
||||
|
|
@ -1346,7 +1435,7 @@ calmaWriteUseFunc(use, f)
|
|||
if (!calmaIsUseNameDefault(use->cu_def->cd_name, use->cu_id))
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@
|
|||
#define CALMA_NUMRECORDTYPES 60 /* Number of above types */
|
||||
|
||||
/* 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_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);
|
||||
break;
|
||||
}
|
||||
cifPlane = curPlane;
|
||||
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
|
||||
bbox.r_xbot *= cifScale;
|
||||
bbox.r_xtop *= cifScale;
|
||||
bbox.r_ybot *= cifScale;
|
||||
bbox.r_ytop *= cifScale;
|
||||
cifScale = 1;
|
||||
DBNMPaintPlane(cifPlane, CIF_SOLIDTYPE, &bbox,
|
||||
DBNMPaintPlane(curPlane, CIF_SOLIDTYPE, &bbox,
|
||||
CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
|
|
|
|||
288
cif/CIFhier.c
288
cif/CIFhier.c
|
|
@ -911,6 +911,52 @@ CIFGenSubcells(def, area, output)
|
|||
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;
|
||||
CellUse *use;
|
||||
int radius, xsep, ysep, xsize, ysize, nx, ny, i, oldTileOps;
|
||||
int xhi, yhi;
|
||||
bool anyInteractions = FALSE;
|
||||
|
||||
use = scx->scx_use;
|
||||
|
|
@ -1147,17 +1192,9 @@ cifHierArrayFunc(scx, output)
|
|||
if ((use->cu_xlo == use->cu_xhi) && (use->cu_ylo == use->cu_yhi))
|
||||
return 2;
|
||||
|
||||
/* We only want interactions between neighboring cells, so reduce */
|
||||
/* the array size to at most 2x2, process, then restore the */
|
||||
/* original array count. */
|
||||
|
||||
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);
|
||||
/* We only want interactions between neighboring cells, so only */
|
||||
/* look at the bottom-left 2x2 set when calculating A and B, and */
|
||||
/* only look at the top-right 2x2 set when calculating C and D. */
|
||||
|
||||
/* Compute the sizes and separations of elements, in coordinates
|
||||
* 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
|
||||
* area than we check, in order to include material that will be
|
||||
* 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 */
|
||||
|
|
@ -1211,7 +1254,7 @@ cifHierArrayFunc(scx, output)
|
|||
A.r_ybot = use->cu_bbox.r_ybot + ysep - radius;
|
||||
A.r_ytop = use->cu_bbox.r_ybot + ysize + radius;
|
||||
GEO_EXPAND(&A, CIFCurStyle->cs_radius, &expandedArea);
|
||||
(void) DBArraySr(use, &expandedArea, cifHierElementFunc,
|
||||
(void) DBArraySr(use, &expandedArea, cifHierElementFuncLow,
|
||||
(ClientData) &A);
|
||||
CIFErrorDef = use->cu_parent;
|
||||
CIFGen(CIFTotalDef, use->cu_def, &A, CIFTotalPlanes,
|
||||
|
|
@ -1220,24 +1263,6 @@ cifHierArrayFunc(scx, output)
|
|||
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))
|
||||
{
|
||||
/* B */
|
||||
|
|
@ -1247,31 +1272,16 @@ cifHierArrayFunc(scx, output)
|
|||
B.r_ybot = use->cu_bbox.r_ybot - radius;
|
||||
B.r_ytop = use->cu_bbox.r_ybot + ysep - radius;
|
||||
GEO_EXPAND(&B, CIFCurStyle->cs_radius, &expandedArea);
|
||||
(void) DBArraySr(use, &expandedArea, cifHierElementFunc,
|
||||
(void) DBArraySr(use, &expandedArea, cifHierElementFuncLow,
|
||||
(ClientData) &B);
|
||||
CIFErrorDef = use->cu_parent;
|
||||
CIFGen(CIFTotalDef, use->cu_def, &B, CIFTotalPlanes,
|
||||
&CIFCurStyle->cs_hierLayers, FALSE, TRUE, TRUE,
|
||||
(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)
|
||||
{
|
||||
|
||||
/* Remove redundant CIF that's already in the children, and
|
||||
* make sure everything in the kids is in the parent too.
|
||||
*/
|
||||
|
|
@ -1308,6 +1318,155 @@ cifHierArrayFunc(scx, output)
|
|||
(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). */
|
||||
|
||||
if ((nx > 1) && (xsep < xsize + radius))
|
||||
|
|
@ -1325,17 +1484,6 @@ cifHierArrayFunc(scx, output)
|
|||
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 right edge of the array (from D). */
|
||||
|
||||
cifHierXSpacing = 0;
|
||||
|
|
@ -1346,36 +1494,12 @@ cifHierArrayFunc(scx, output)
|
|||
(void) DBSrPaintArea((Tile *) NULL, CIFTotalPlanes[i],
|
||||
&cifArea, &CIFSolidBits, cifHierPaintArrayFunc,
|
||||
(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;
|
||||
}
|
||||
|
||||
cifHierCleanup();
|
||||
|
||||
/* Restore the array bounds of the array */
|
||||
use->cu_xhi = xhi;
|
||||
use->cu_yhi = yhi;
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4261,6 +4261,11 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
|
|||
cellnameptr++;
|
||||
fullpathname = (char *)mallocMagic(strlen(cmd->tx_argv[1]) + 2);
|
||||
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
|
||||
{
|
||||
|
|
@ -4307,8 +4312,8 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
|
|||
def = DBCellLookDef(newcellname);
|
||||
uniqchar++;
|
||||
}
|
||||
TxError("Renaming cell to \"%s\" to avoid conflict.", newcellname);
|
||||
def = DBCellNewDef(cellnameptr);
|
||||
TxError("Renaming cell to \"%s\" to avoid conflict.\n", newcellname);
|
||||
def = DBCellNewDef(newcellname);
|
||||
StrDup(&def->cd_file, fullpathname);
|
||||
freeMagic(newcellname);
|
||||
}
|
||||
|
|
@ -4396,15 +4401,10 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
|
|||
TxError("Keyword must be followed by a reference point\n");
|
||||
goto usage;
|
||||
}
|
||||
if (StrIsInt(av[1]))
|
||||
else if (ac == 3)
|
||||
{
|
||||
childPoint.p_x = atoi(av[1]);
|
||||
if (ac < 3 || !StrIsInt(av[2]))
|
||||
{
|
||||
TxError("Must provide two coordinates\n");
|
||||
goto usage;
|
||||
}
|
||||
childPoint.p_y = atoi(av[2]);
|
||||
childPoint.p_x = cmdParseCoord(w, av[1], TRUE, TRUE);
|
||||
childPoint.p_y = cmdParseCoord(w, av[2], TRUE, FALSE);
|
||||
av += 3;
|
||||
ac -= 3;
|
||||
}
|
||||
|
|
@ -4455,15 +4455,10 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
|
|||
TxError("Keyword must be followed by a reference point\n");
|
||||
goto usage;
|
||||
}
|
||||
if (StrIsInt(av[1]))
|
||||
else if (ac == 3)
|
||||
{
|
||||
editPoint.p_x = atoi(av[1]);
|
||||
if (ac < 3 || !StrIsInt(av[2]))
|
||||
{
|
||||
TxError("Must provide two coordinates\n");
|
||||
goto usage;
|
||||
}
|
||||
editPoint.p_y = atoi(av[2]);
|
||||
editPoint.p_x = cmdParseCoord(w, av[1], TRUE, TRUE);
|
||||
editPoint.p_y = cmdParseCoord(w, av[2], TRUE, FALSE);
|
||||
av += 3;
|
||||
ac -= 3;
|
||||
GeoTransPoint(&EditToRootTransform, &editPoint,
|
||||
|
|
|
|||
|
|
@ -2008,14 +2008,18 @@ CmdFlatten(w, cmd)
|
|||
return;
|
||||
}
|
||||
/* create the new def */
|
||||
if (newdef = DBCellLookDef(destname))
|
||||
newdef = DBCellLookDef(destname);
|
||||
if ((newdef != NULL) && (dobox == FALSE))
|
||||
{
|
||||
TxError("%s already exists\n",destname);
|
||||
return;
|
||||
}
|
||||
else if (newdef == NULL)
|
||||
{
|
||||
newdef = DBCellNewDef(destname);
|
||||
ASSERT(newdef, "CmdFlatten");
|
||||
DBCellSetAvail(newdef);
|
||||
}
|
||||
newuse = DBCellNewUse(newdef, (char *) NULL);
|
||||
(void) StrDup(&(newuse->cu_id), "Flattened cell");
|
||||
DBSetTrans(newuse, &GeoIdentityTransform);
|
||||
|
|
@ -2063,5 +2067,6 @@ CmdFlatten(w, cmd)
|
|||
if (xMask != CU_DESCEND_ALL)
|
||||
DBCellCopyAllCells(&scx, xMask, flatDestUse, (Rect *)NULL);
|
||||
|
||||
DBCellDeleteUse(flatDestUse);
|
||||
UndoEnable();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1612,8 +1612,9 @@ DBCellLookDef(cellName)
|
|||
{
|
||||
HashEntry *entry;
|
||||
|
||||
entry = HashFind(&dbCellDefTable, cellName);
|
||||
return ((CellDef *) HashGetValue(entry));
|
||||
entry = HashLookOnly(&dbCellDefTable, cellName);
|
||||
if (entry == (HashEntry *)NULL) return (CellDef *)NULL;
|
||||
return (CellDef *)HashGetValue(entry);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -816,6 +816,7 @@ extern void DBTechInitContact();
|
|||
extern void DBTechFinalContact();
|
||||
extern void DBTechFinalConnect();
|
||||
extern void DBTechInitConnect();
|
||||
extern bool DBIsContact();
|
||||
|
||||
/* Cell symbol table */
|
||||
extern void DBCellInit();
|
||||
|
|
|
|||
|
|
@ -326,6 +326,7 @@ DBWloadWindow(window, name, flags)
|
|||
{
|
||||
deleteDef = ((CellUse *)window->w_surfaceID)->cu_def;
|
||||
if (strcmp(deleteDef->cd_name, "(UNNAMED)") ||
|
||||
(GrDisplayStatus == DISPLAY_SUSPEND) ||
|
||||
deleteDef->cd_flags & (CDMODIFIED|CDBOXESCHANGED|CDSTAMPSCHANGED))
|
||||
deleteDef = NULL;
|
||||
}
|
||||
|
|
@ -497,7 +498,7 @@ DBWloadWindow(window, name, flags)
|
|||
|
||||
if (newEdit)
|
||||
{
|
||||
if (EditCellUse && EditRootDef)
|
||||
if ((EditCellUse && EditRootDef) && (deleteDef == NULL))
|
||||
{
|
||||
DBWUndoOldEdit(EditCellUse, EditRootDef,
|
||||
&EditToRootTransform, &RootToEditTransform);
|
||||
|
|
@ -549,6 +550,11 @@ DBWloadWindow(window, name, flags)
|
|||
/* If the cell before loading was (UNNAMED) and it was */
|
||||
/* 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)
|
||||
DBCellDelete(deleteDef->cd_name, TRUE);
|
||||
}
|
||||
|
|
|
|||
17
drc/DRCcif.c
17
drc/DRCcif.c
|
|
@ -613,6 +613,14 @@ drcCifTile (tile, arg)
|
|||
if (SigInterruptPending) return 1;
|
||||
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.
|
||||
*
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -1836,6 +1836,7 @@ drcMaskSpacing(set1, set2, pmask1, pmask2, wwidth, distance, adjacency,
|
|||
bool needtrigger = FALSE;
|
||||
bool touchingok = TRUE;
|
||||
bool cornerok = FALSE;
|
||||
bool surroundok = FALSE;
|
||||
|
||||
if (!strcmp(adjacency, "surround_ok"))
|
||||
{
|
||||
|
|
@ -1858,6 +1859,7 @@ drcMaskSpacing(set1, set2, pmask1, pmask2, wwidth, distance, adjacency,
|
|||
needtrigger = TRUE;
|
||||
touchingok = FALSE;
|
||||
needReverse = TRUE;
|
||||
surroundok = TRUE;
|
||||
}
|
||||
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
|
||||
* 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);
|
||||
|
||||
|
|
|
|||
|
|
@ -97,39 +97,39 @@ struct {
|
|||
short resClassSub ; /* The resistance class of the substrate of the dev */
|
||||
TileType devType ; /* Magic tile type of the device */
|
||||
char *defSubs ; /* The default substrate node */
|
||||
} fetInfo[MAXDEVTYPES];
|
||||
} fetInfo[TT_MAXTYPES];
|
||||
|
||||
typedef struct {
|
||||
long visitMask:MAXDEVTYPES;
|
||||
TileTypeBitMask visitMask;
|
||||
} nodeClient;
|
||||
|
||||
typedef struct {
|
||||
HierName *lastPrefix;
|
||||
long visitMask:MAXDEVTYPES;
|
||||
TileTypeBitMask visitMask;
|
||||
} nodeClientHier;
|
||||
|
||||
#define NO_RESCLASS -1
|
||||
|
||||
#define markVisited(client, rclass) \
|
||||
{ (client)->visitMask |= (1<<rclass); }
|
||||
{ TTMaskSetType(&((client)->visitMask), rclass); }
|
||||
|
||||
#define clearVisited(client) \
|
||||
{ (client)->visitMask = (long)0; }
|
||||
{ TTMaskZero(&((client)->visitMask)); }
|
||||
|
||||
#define beenVisited(client, rclass) \
|
||||
( (client)->visitMask & (1<<rclass))
|
||||
( TTMaskHasType(&((client)->visitMask), rclass) )
|
||||
|
||||
#define initNodeClient(node) \
|
||||
{ \
|
||||
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClient))); \
|
||||
(( nodeClient *)(node)->efnode_client)->visitMask = (long) 0; \
|
||||
TTMaskZero(&(( nodeClient *)(node)->efnode_client)->visitMask); \
|
||||
}
|
||||
|
||||
|
||||
#define initNodeClientHier(node) \
|
||||
{ \
|
||||
(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
|
||||
the command line arguments */
|
||||
|
||||
for ( i = 0 ; i < MAXDEVTYPES ; i++ )
|
||||
for ( i = 0 ; i < TT_MAXTYPES ; i++ )
|
||||
{
|
||||
fetInfo[i].resClassSource = NO_RESCLASS;
|
||||
fetInfo[i].resClassDrain = NO_RESCLASS;
|
||||
|
|
@ -589,12 +589,12 @@ runexttosim:
|
|||
while (ExtGetDevInfo(idx++, &devname, &devtype, &s_rclass, &d_rclass,
|
||||
&sub_rclass, &subname))
|
||||
{
|
||||
if (idx == MAXDEVTYPES)
|
||||
if (idx == TT_MAXTYPES)
|
||||
{
|
||||
TxError("Error: Ran out of space for device types!\n");
|
||||
break;
|
||||
}
|
||||
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, devname);
|
||||
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, devname);
|
||||
|
||||
if (EFStyle != NULL)
|
||||
{
|
||||
|
|
@ -676,26 +676,26 @@ main(argc, argv)
|
|||
EFInit();
|
||||
/* create default fetinfo entries (MOSIS) which can be overriden by
|
||||
the command line arguments */
|
||||
for ( i = 0 ; i < MAXDEVTYPES ; i++ ) {
|
||||
for ( i = 0 ; i < TT_MAXTYPES ; i++ ) {
|
||||
fetInfo[i].resClassSource = NO_RESCLASS;
|
||||
fetInfo[i].resClassDrain = NO_RESCLASS;
|
||||
fetInfo[i].resClassSub = NO_RESCLASS;
|
||||
fetInfo[i].defSubs = NULL;
|
||||
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].resClassSub = NO_RESCLASS ;
|
||||
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].resClassSub = 6 ;
|
||||
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].resClassSub = NO_RESCLASS ;
|
||||
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].resClassSub = 6 ;
|
||||
fetInfo[i].defSubs = "Vdd!";
|
||||
|
|
@ -896,7 +896,7 @@ simmainArgs(pargc, pargv)
|
|||
rClassSub = NO_RESCLASS ;
|
||||
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].resClassDrain = rClass;
|
||||
fetInfo[ndx].resClassSub = rClassSub;
|
||||
|
|
@ -1206,9 +1206,6 @@ simdevVisit(dev, hc, scale, trans)
|
|||
/* Output length, width, and position as attributes */
|
||||
fprintf(esSimF, " l=%g w=%g x=%g y=%g",
|
||||
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)
|
||||
&& (dev->dev_class != DEV_NDIODE)) {
|
||||
|
|
@ -1402,7 +1399,7 @@ bool simnAPHier(dterm, hierName, resClass, scale, outf)
|
|||
initNodeClientHier(node);
|
||||
nc = (nodeClientHier *)node->efnode_client;
|
||||
if ( nc->lastPrefix != hierName ) {
|
||||
nc->visitMask = 0;
|
||||
TTMaskZero(&(nc->visitMask));
|
||||
nc->lastPrefix = hierName;
|
||||
}
|
||||
if ( resClass == NO_RESCLASS ||
|
||||
|
|
|
|||
|
|
@ -1264,10 +1264,10 @@ spcnodeHierVisit(hc, node, res, cap)
|
|||
|
||||
if (node->efnode_client)
|
||||
{
|
||||
isConnected = (esDistrJunct) ?
|
||||
(((nodeClient *)node->efnode_client)->m_w.widths != NULL) :
|
||||
((((nodeClient *)node->efnode_client)->m_w.visitMask
|
||||
& DEV_CONNECT_MASK) != 0);
|
||||
if (esDistrJunct)
|
||||
isConnected = (((nodeClient *)node->efnode_client)->m_w.widths != NULL);
|
||||
else
|
||||
isConnected = !TTMaskIsZero(&((nodeClient *)node->efnode_client)->m_w.visitMask);
|
||||
}
|
||||
if (!isConnected && esDevNodesOnly)
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ int esNoModelType; /* index for device type "None" (model-less device) */
|
|||
HashTable subcktNameTable ; /* the hash table itself */
|
||||
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 */
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ typedef struct GLL {
|
|||
char *gll_name;
|
||||
} 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 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
|
||||
the command line arguments */
|
||||
|
||||
for ( i = 0 ; i < MAXDEVTYPES ; i++ ) {
|
||||
for ( i = 0 ; i < TT_MAXTYPES ; i++ ) {
|
||||
esFetInfo[i].resClassSource = NO_RESCLASS;
|
||||
esFetInfo[i].resClassDrain = NO_RESCLASS;
|
||||
esFetInfo[i].resClassSub = NO_RESCLASS;
|
||||
|
|
@ -743,12 +743,12 @@ runexttospice:
|
|||
while (ExtGetDevInfo(idx++, &devname, &devtype, &s_rclass, &d_rclass,
|
||||
&sub_rclass, &subname))
|
||||
{
|
||||
if (idx == MAXDEVTYPES)
|
||||
if (idx == TT_MAXTYPES)
|
||||
{
|
||||
TxError("Error: Ran out of space for device types!\n");
|
||||
break;
|
||||
}
|
||||
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, devname);
|
||||
i = efBuildAddStr(EFDevTypes, &EFDevNumTypes, TT_MAXTYPES, devname);
|
||||
if (!strcmp(devname, "None"))
|
||||
esNoModelType = i;
|
||||
if (EFStyle != NULL)
|
||||
|
|
@ -908,7 +908,9 @@ runexttospice:
|
|||
if (!esDoPorts)
|
||||
EFVisitSubcircuits(subcktUndef, (ClientData) NULL);
|
||||
|
||||
initMask = ( esDistrJunct ) ? (unsigned long)0 : DEV_CONNECT_MASK;
|
||||
TTMaskZero(&initMask);
|
||||
if (!esDistrJunct)
|
||||
TTMaskCom(&initMask);
|
||||
|
||||
if (esMergeDevsA || esMergeDevsC)
|
||||
{
|
||||
|
|
@ -924,7 +926,7 @@ runexttospice:
|
|||
else if (esDistrJunct)
|
||||
EFVisitDevs(devDistJunctVisit, (ClientData) NULL);
|
||||
EFVisitDevs(spcdevVisit, (ClientData) NULL);
|
||||
initMask = (unsigned long) 0;
|
||||
TTMaskZero(&initMask);
|
||||
if (flatFlags & EF_FLATCAPS)
|
||||
{
|
||||
(void) sprintf( esSpiceCapFormat, "C%%d %%s %%s %%.%dlffF\n",
|
||||
|
|
@ -994,25 +996,25 @@ main(argc, argv)
|
|||
EFResistThreshold = INFINITE_THRESHOLD ;
|
||||
/* create default devinfo entries (MOSIS) which can be overriden by
|
||||
the command line arguments */
|
||||
for ( i = 0 ; i < MAXDEVTYPES ; i++ ) {
|
||||
for ( i = 0 ; i < TT_MAXTYPES ; i++ ) {
|
||||
esFetInfo[i].resClassSource = NO_RESCLASS;
|
||||
esFetInfo[i].resClassDrain = NO_RESCLASS;
|
||||
esFetInfo[i].resClassSub = NO_RESCLASS;
|
||||
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].resClassSub = NO_RESCLASS ;
|
||||
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].resClassSub = 8 ;
|
||||
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].resClassSub = NO_RESCLASS ;
|
||||
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].resClassSub = 8 ;
|
||||
esFetInfo[i].defSubs = "Vdd!";
|
||||
|
|
@ -1078,7 +1080,9 @@ main(argc, argv)
|
|||
if (!esDoPorts)
|
||||
EFVisitSubcircuits(subcktUndef, (ClientData) NULL);
|
||||
|
||||
initMask = ( esDistrJunct ) ? (unsigned long)0 : DEV_CONNECT_MASK ;
|
||||
TTMaskZero(&initMask);
|
||||
if (!esDistrJunct)
|
||||
TTMaskCom(&initMask);
|
||||
|
||||
if ( esMergeDevsA || esMergeDevsC ) {
|
||||
EFVisitDevs(devMergeVisit, (ClientData) NULL);
|
||||
|
|
@ -1092,7 +1096,7 @@ main(argc, argv)
|
|||
} else if ( esDistrJunct )
|
||||
EFVisitDevs(devDistJunctVisit, (ClientData) NULL);
|
||||
EFVisitDevs(spcdevVisit, (ClientData) NULL);
|
||||
initMask = (unsigned long) 0;
|
||||
TTMaskZero(&initMask);
|
||||
if (flatFlags & EF_FLATCAPS) {
|
||||
(void) sprintf( esSpiceCapFormat, "C%%d %%s %%s %%.%dlffF\n",esCapAccuracy);
|
||||
EFVisitCaps(spccapVisit, (ClientData) NULL);
|
||||
|
|
@ -1240,17 +1244,9 @@ spcmainArgs(pargc, pargv)
|
|||
rClassSub = -1 ;
|
||||
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].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));
|
||||
strcpy(esFetInfo[ndx].defSubs,subsNode);
|
||||
TxError("info: dev %s(%d) srcRclass=%d drnRclass=%d subRclass=%d dSub=%s\n",
|
||||
|
|
@ -2910,8 +2906,10 @@ FILE *outf;
|
|||
initNodeClientHier(nn->efnn_node);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -3126,7 +3124,10 @@ spcdevOutNode(prefix, suffix, name, outf)
|
|||
|
||||
/* Mark node as visited */
|
||||
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));
|
||||
}
|
||||
|
|
@ -3279,8 +3280,7 @@ spcnodeVisit(node, res, cap)
|
|||
{
|
||||
isConnected = (esDistrJunct) ?
|
||||
(((nodeClient *)node->efnode_client)->m_w.widths != NULL) :
|
||||
((((nodeClient *)node->efnode_client)->m_w.visitMask
|
||||
& DEV_CONNECT_MASK) != 0);
|
||||
(!TTMaskIsZero(&((nodeClient *)node->efnode_client)->m_w.visitMask));
|
||||
}
|
||||
if (!isConnected && esDevNodesOnly)
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ extern FILE *esSpiceF;
|
|||
extern float esScale; /* negative if hspice the EFScale/100 otherwise */
|
||||
|
||||
extern unsigned short esFormat;
|
||||
extern unsigned long initMask;
|
||||
extern TileTypeBitMask initMask;
|
||||
|
||||
extern int esCapNum, esDevNum, esResNum, esDiodeNum;
|
||||
extern int esNodeNum; /* just in case we're extracting spice2 */
|
||||
|
|
@ -96,19 +96,15 @@ typedef struct {
|
|||
char *defSubs ; /* the default substrate node */
|
||||
} fetInfoList;
|
||||
|
||||
extern fetInfoList esFetInfo[MAXDEVTYPES];
|
||||
extern fetInfoList esFetInfo[TT_MAXTYPES];
|
||||
|
||||
#define MAX_STR_SIZE (1<<11) /* 2K should be enough for keeping temp
|
||||
names even of the most complicated design */
|
||||
|
||||
/* 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 {
|
||||
long visitMask; /* mask for normal visits */
|
||||
TileTypeBitMask visitMask; /* mask for normal visits */
|
||||
float *widths; /* width used for distributing area perim */
|
||||
} maskOrWidth ;
|
||||
|
||||
|
|
@ -125,32 +121,27 @@ typedef struct {
|
|||
#define NO_RESCLASS -1
|
||||
|
||||
#define markVisited(client, rclass) \
|
||||
{ (client)->m_w.visitMask |= (1<<rclass); }
|
||||
{ TTMaskSetType(&((client)->m_w.visitMask), rclass); }
|
||||
|
||||
#define clearVisited(client) \
|
||||
{ (client)->m_w.visitMask = (long)0; }
|
||||
{ TTMaskZero(&((client)->m_w.visitMask)); }
|
||||
|
||||
#define beenVisited(client, rclass) \
|
||||
( (client)->m_w.visitMask & (1<<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))
|
||||
( TTMaskHasType(&((client)->m_w.visitMask), rclass) )
|
||||
|
||||
#define initNodeClient(node) \
|
||||
{ \
|
||||
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClient))); \
|
||||
(( 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) \
|
||||
{ \
|
||||
(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();
|
||||
|
||||
typedef struct {
|
||||
long visitMask:MAXDEVTYPES;
|
||||
TileTypeBitMask visitMask;
|
||||
} nodeClient;
|
||||
|
||||
typedef struct {
|
||||
HierName *lastPrefix;
|
||||
long visitMask:MAXDEVTYPES;
|
||||
TileTypeBitMask visitMask;
|
||||
} nodeClientHier;
|
||||
|
||||
#define NO_RESCLASS -1
|
||||
|
||||
#define markVisited(client, rclass) \
|
||||
{ (client)->visitMask |= (1<<rclass); }
|
||||
{ TTMaskSetType(&((client)->visitMask), rclass); }
|
||||
|
||||
#define clearVisited(client) \
|
||||
{ (client)->visitMask = (long)0; }
|
||||
{ TTMaskZero(&((client)->visitMask); }
|
||||
|
||||
#define beenVisited(client, rclass) \
|
||||
( (client)->visitMask & (1<<rclass))
|
||||
( TTMaskHasType(&((client)->visitMask), rclass) )
|
||||
|
||||
#define initNodeClient(node) \
|
||||
{ \
|
||||
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClient))); \
|
||||
(( nodeClient *)(node)->efnode_client)->visitMask = (long) 0; \
|
||||
TTMaskZero(&(( nodeClient *)(node)->efnode_client)->visitMask); \
|
||||
}
|
||||
|
||||
|
||||
#define initNodeClientHier(node) \
|
||||
{ \
|
||||
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClientHier))); \
|
||||
((nodeClientHier *) (node)->efnode_client)->visitMask = (long) 0; \
|
||||
TTMaskZero(&(( nodeClientHier *)(node)->efnode_client)->visitMask); \
|
||||
}
|
||||
|
||||
/* Diagnostic */
|
||||
|
|
@ -228,9 +228,21 @@ runantennacheck:
|
|||
TxPrintf("Building flattened netlist.\n");
|
||||
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 */
|
||||
EFDeviceTypes = (TileType *)mallocMagic(MAXDEVTYPES * sizeof(TileType));
|
||||
for (i = 0; i < MAXDEVTYPES; i++)
|
||||
EFDeviceTypes = (TileType *)mallocMagic(EFDevNumTypes * sizeof(TileType));
|
||||
for (i = 0; i < EFDevNumTypes; i++)
|
||||
if (EFDevTypes[i])
|
||||
EFDeviceTypes[i] = extGetDevType(EFDevTypes[i]);
|
||||
|
||||
|
|
|
|||
|
|
@ -30,9 +30,10 @@ static char rcsid[] __attribute__ ((unused)) = "$Header$";
|
|||
#include "utils/hash.h"
|
||||
#include "utils/utils.h"
|
||||
#include "utils/malloc.h"
|
||||
#include "tiles/tile.h"
|
||||
#include "database/database.h" /* for TileType definition */
|
||||
#include "extflat/extflat.h"
|
||||
#include "extflat/EFint.h"
|
||||
#include "tiles/tile.h"
|
||||
#include "extract/extract.h" /* for device class list */
|
||||
|
||||
/*
|
||||
|
|
@ -48,7 +49,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header$";
|
|||
#define MAXTYPES 100
|
||||
|
||||
/* Table of transistor types */
|
||||
char *EFDevTypes[MAXDEVTYPES];
|
||||
char *EFDevTypes[TT_MAXTYPES];
|
||||
int EFDevNumTypes;
|
||||
|
||||
/* Table of Magic layers */
|
||||
|
|
@ -656,6 +657,8 @@ efBuildDevice(def, class, type, r, argc, argv)
|
|||
DevTerm *term;
|
||||
Dev *newdev, devtmp;
|
||||
DevParam *newparm, *devp, *sparm;
|
||||
TileType ttype;
|
||||
int dev_type;
|
||||
char ptype, *pptr, **av;
|
||||
char devhash[64];
|
||||
int argstart = 1; /* start of terminal list in argv[] */
|
||||
|
|
@ -799,9 +802,18 @@ efBuildDevice(def, class, type, r, argc, argv)
|
|||
|
||||
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);
|
||||
newdev = (Dev *)HashGetValue(he);
|
||||
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
|
||||
* 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) ||
|
||||
(strcmp(EFDevTypes[newdev->dev_type], type)))
|
||||
if ((newdev->dev_class != class) || ((newdev->dev_type != dev_type)
|
||||
&& (ttype != extGetDevType(EFDevTypes[newdev->dev_type]))))
|
||||
{
|
||||
TxError("Device %s %s at (%d, %d) overlaps incompatible device %s %s!\n",
|
||||
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_rect = *r;
|
||||
newdev->dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, type);
|
||||
newdev->dev_type = dev_type;
|
||||
newdev->dev_class = class;
|
||||
|
||||
switch (class)
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ EFDone()
|
|||
|
||||
/* Misc cleanup */
|
||||
for (n = 0; n < EFDevNumTypes; n++) freeMagic(EFDevTypes[n]);
|
||||
EFDevNumTypes = 0;
|
||||
|
||||
/* Changed from n = 0 to n = 1; First entry "space" is predefined, */
|
||||
/* not malloc'd. ---Tim 9/3/02 */
|
||||
|
|
|
|||
|
|
@ -342,9 +342,6 @@ extern char *EFHNToStr();
|
|||
extern int EFGetPortMax();
|
||||
|
||||
/* ------------------------- 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
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ ExtCell(def, outName, doLength)
|
|||
TxError("Cannot open output file: ");
|
||||
perror(filename);
|
||||
#endif
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extNumFatal = extNumWarnings = 0;
|
||||
|
|
|
|||
|
|
@ -202,6 +202,21 @@ extHierSubstrate(ha, use, x, y)
|
|||
freeMagic(childname);
|
||||
|
||||
if (node1 != node2)
|
||||
{
|
||||
if (node1->node_len < node2->node_len)
|
||||
{
|
||||
/*
|
||||
* 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.
|
||||
|
|
@ -211,8 +226,10 @@ extHierSubstrate(ha, use, x, y)
|
|||
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);
|
||||
}
|
||||
}
|
||||
freeMagic(nodeList);
|
||||
}
|
||||
|
||||
|
|
@ -384,6 +401,23 @@ extHierConnectFunc1(oneTile, ha)
|
|||
node2 = nn ? nn->nn_node : extHierNewNode(he);
|
||||
|
||||
if (node1 != node2)
|
||||
{
|
||||
if (node1->node_len < node2->node_len)
|
||||
{
|
||||
/*
|
||||
* Both sets of names will now point to node2.
|
||||
* We don't need to update node_cap since it
|
||||
* hasn't been computed yet.
|
||||
*/
|
||||
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.
|
||||
|
|
@ -395,10 +429,12 @@ extHierConnectFunc1(oneTile, ha)
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
@ -469,6 +505,23 @@ extHierConnectFunc2(cum, ha)
|
|||
node2 = nn ? nn->nn_node : extHierNewNode(he);
|
||||
|
||||
if (node1 != node2)
|
||||
{
|
||||
if (node1->node_len < node2->node_len)
|
||||
{
|
||||
/*
|
||||
* Both sets of names will now point to node2.
|
||||
* We don't need to update node_cap since it
|
||||
* hasn't been computed yet.
|
||||
*/
|
||||
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.
|
||||
|
|
@ -480,9 +533,11 @@ extHierConnectFunc2(cum, ha)
|
|||
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)
|
||||
{
|
||||
extNumFatal++;
|
||||
|
|
@ -552,6 +607,23 @@ extHierConnectFunc3(cum, ha)
|
|||
node2 = nn ? nn->nn_node : extHierNewNode(he);
|
||||
|
||||
if (node1 != node2)
|
||||
{
|
||||
if (node1->node_len < node2->node_len)
|
||||
{
|
||||
/*
|
||||
* Both sets of names will now point to node2.
|
||||
* We don't need to update node_cap since it
|
||||
* hasn't been computed yet.
|
||||
*/
|
||||
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.
|
||||
|
|
@ -563,9 +635,11 @@ extHierConnectFunc3(cum, ha)
|
|||
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)
|
||||
{
|
||||
extNumFatal++;
|
||||
|
|
@ -810,6 +884,7 @@ extHierNewNode(he)
|
|||
nn->nn_name = he->h_key.h_name;
|
||||
node->node_names = nn;
|
||||
node->node_cap = (CapValue) 0;
|
||||
node->node_len = 1;
|
||||
for (n = 0; n < nclasses; n++)
|
||||
node->node_pa[n].pa_perim = node->node_pa[n].pa_area = 0;
|
||||
HashSetValue(he, (char *) nn);
|
||||
|
|
|
|||
|
|
@ -354,11 +354,13 @@ ExtGetDevInfo(idx, devnameptr, devtypeptr, s_rclassptr, d_rclassptr,
|
|||
if (t == DBNumTypes) return FALSE;
|
||||
if (devptr == NULL) return FALSE;
|
||||
|
||||
*devnameptr = locdname;
|
||||
*subnameptr = devptr->exts_deviceSubstrateName;
|
||||
*devtypeptr = t;
|
||||
if (devnameptr) *devnameptr = locdname;
|
||||
if (subnameptr) *subnameptr = devptr->exts_deviceSubstrateName;
|
||||
if (devtypeptr) *devtypeptr = t;
|
||||
|
||||
tmask = &devptr->exts_deviceSDTypes[0];
|
||||
if (s_rclassptr)
|
||||
{
|
||||
*s_rclassptr = (short)(-1); /* NO_RESCLASS */
|
||||
|
||||
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
|
||||
|
|
@ -370,7 +372,10 @@ ExtGetDevInfo(idx, devnameptr, devtypeptr, s_rclassptr, d_rclassptr,
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (d_rclassptr)
|
||||
{
|
||||
tmask = &devptr->exts_deviceSDTypes[1];
|
||||
if (TTMaskIsZero(tmask))
|
||||
{
|
||||
|
|
@ -391,7 +396,10 @@ ExtGetDevInfo(idx, devnameptr, devtypeptr, s_rclassptr, d_rclassptr,
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sub_rclassptr)
|
||||
{
|
||||
tmask = &devptr->exts_deviceSubstrateTypes;
|
||||
*sub_rclassptr = (short)(-1); /* NO_RESCLASS */
|
||||
|
||||
|
|
@ -404,6 +412,7 @@ ExtGetDevInfo(idx, devnameptr, devtypeptr, s_rclassptr, d_rclassptr,
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
freeMagic(uniquenamelist);
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -943,6 +943,7 @@ typedef struct node
|
|||
NodeName *node_names; /* List of names for this node. The first name
|
||||
* in the list is the "official" node name.
|
||||
*/
|
||||
int node_len; /* Number of entries in node_names */
|
||||
CapValue node_cap; /* Capacitance to substrate */
|
||||
PerimArea node_pa[1]; /* Dummy; each node actually has
|
||||
* ExtCurStyle->exts_numResistClasses
|
||||
|
|
|
|||
|
|
@ -776,7 +776,7 @@ lefWriteGeometry(tile, cdata)
|
|||
lefClient *lefdata = (lefClient *)cdata;
|
||||
FILE *f = lefdata->file;
|
||||
float scale = lefdata->oscale;
|
||||
char leffmt[6][10];
|
||||
char leffmt[6][16];
|
||||
TileType ttype, otype = TiGetTypeExact(tile);
|
||||
LefMapping *lefMagicToLefLayer = lefdata->lefMagicMap;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
MODULE = resis
|
||||
MAGICDIR = ..
|
||||
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
|
||||
|
||||
include ${MAGICDIR}/defs.mak
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ ResSanityChecks(nodename,resistorList,nodeList,devlist)
|
|||
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))
|
||||
{
|
||||
node = (resNode *)STACKPOP(resSanityStack);
|
||||
|
|
@ -86,7 +86,8 @@ ResSanityChecks(nodename,resistorList,nodeList,devlist)
|
|||
if (resistor->rr_connection1 != 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",
|
||||
nodename, rcell);
|
||||
continue;
|
||||
}
|
||||
if ((resistor->rr_connection1->rn_status & RES_REACHED_NODE) == 0)
|
||||
|
|
@ -137,7 +138,8 @@ ResSanityChecks(nodename,resistorList,nodeList,devlist)
|
|||
{
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
@ -49,7 +49,6 @@ void
|
|||
ResPrintNodeList(fp, list)
|
||||
FILE *fp;
|
||||
resNode *list;
|
||||
|
||||
{
|
||||
|
||||
for (; list != NULL; list = list->rn_more)
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ enumerate:
|
|||
resTopTile=BL(resTopTile);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tpnew = TR(resSrTile);
|
||||
|
|
@ -134,7 +133,8 @@ enumerate:
|
|||
}
|
||||
|
||||
/* 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 */;
|
||||
}
|
||||
return (0);
|
||||
|
|
@ -164,11 +164,13 @@ ResCheckConcavity(bot,top,tt)
|
|||
{
|
||||
Tile *tp;
|
||||
int xlen, ylen;
|
||||
|
||||
/* corner #1:
|
||||
XXXXXXX
|
||||
YYYYYYY
|
||||
^--here
|
||||
* XXXXXXX
|
||||
* YYYYYYY
|
||||
* ^--here
|
||||
*/
|
||||
|
||||
if (RIGHT(top) > RIGHT(bot) && TiGetType(TR(bot)) != tt)
|
||||
{
|
||||
int xpos = RIGHT(bot);
|
||||
|
|
@ -181,11 +183,13 @@ ResCheckConcavity(bot,top,tt)
|
|||
}
|
||||
}
|
||||
if (resTopTile == NULL) return;
|
||||
|
||||
/* corner #2:
|
||||
v--here
|
||||
XXXXXXX
|
||||
YYYYYYY
|
||||
* v--here
|
||||
* XXXXXXX
|
||||
* YYYYYYY
|
||||
*/
|
||||
|
||||
if (RIGHT(top) < RIGHT(bot))
|
||||
{
|
||||
for (tp = TR(top); BOTTOM(tp) > BOTTOM(top); tp = LB(tp));
|
||||
|
|
@ -202,11 +206,13 @@ ResCheckConcavity(bot,top,tt)
|
|||
}
|
||||
}
|
||||
if (resTopTile == NULL) return;
|
||||
|
||||
/* corner #3:
|
||||
XXXXXXX
|
||||
YYYYYYY
|
||||
^--here
|
||||
* XXXXXXX
|
||||
* YYYYYYY
|
||||
* ^--here
|
||||
*/
|
||||
|
||||
if (LEFT(top) < LEFT(bot))
|
||||
{
|
||||
for (tp = BL(bot); TOP(tp) < TOP(bot); tp = RT(tp));
|
||||
|
|
@ -223,11 +229,13 @@ ResCheckConcavity(bot,top,tt)
|
|||
}
|
||||
}
|
||||
if (resTopTile == NULL) return;
|
||||
|
||||
/* corner #4:
|
||||
v--here
|
||||
XXXXXXX
|
||||
YYYYYYY
|
||||
* v--here
|
||||
* XXXXXXX
|
||||
* YYYYYYY
|
||||
*/
|
||||
|
||||
if (LEFT(top) > LEFT(bot) && TiGetType(BL(top)) != tt)
|
||||
{
|
||||
int xpos = LEFT(top);
|
||||
|
|
@ -419,6 +427,7 @@ resWalkleft(tile,tt,xpos,ypos,func)
|
|||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
Tile *
|
||||
ResSplitX(tile, x)
|
||||
Tile *tile;
|
||||
|
|
|
|||
|
|
@ -26,8 +26,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "textio/txcommands.h"
|
||||
#include "resis/resis.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -152,10 +150,10 @@ ResProcessJunction(tile, tp, xj, yj, NodeList)
|
|||
junction->rj_nextjunction[1] = j2->junctionList;
|
||||
j2->junctionList = junction;
|
||||
|
||||
NEWBREAK(junction->rj_jnode,tile,
|
||||
junction->rj_loc.p_x,junction->rj_loc.p_y,NULL);
|
||||
NEWBREAK(junction->rj_jnode,tile, junction->rj_loc.p_x,
|
||||
junction->rj_loc.p_y, NULL);
|
||||
|
||||
NEWBREAK(junction->rj_jnode,tp,
|
||||
junction->rj_loc.p_x,junction->rj_loc.p_y,NULL);
|
||||
NEWBREAK(junction->rj_jnode,tp, junction->rj_loc.p_x,
|
||||
junction->rj_loc.p_y, NULL);
|
||||
|
||||
}
|
||||
|
|
|
|||
194
resis/ResMain.c
194
resis/ResMain.c
|
|
@ -20,6 +20,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "windows/windows.h"
|
||||
#include "dbwind/dbwind.h"
|
||||
#include "utils/tech.h"
|
||||
#include "select/select.h"
|
||||
#include "textio/txcommands.h"
|
||||
#include "resis/resis.h"
|
||||
|
||||
|
|
@ -45,8 +46,6 @@ extern ResSimNode *ResInitializeNode();
|
|||
|
||||
extern HashTable ResNodeTable;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*--------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -121,7 +120,6 @@ ResGetReCell()
|
|||
ResUse = DBCellNewUse(ResDef, (char *) NULL);
|
||||
DBSetTrans(ResUse, &GeoIdentityTransform);
|
||||
ResUse->cu_expandMask = CU_DESCEND_SPECIAL;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -418,7 +416,6 @@ ResProcessTiles(goodies, origin)
|
|||
Tile *tile = fix->fp_tile;
|
||||
if (tile == NULL)
|
||||
{
|
||||
|
||||
tile = ResDef->cd_planes[DBPlane(fix->fp_ttype)]->pl_hint;
|
||||
GOTOPOINT(tile, &(fix->fp_loc));
|
||||
if (TiGetTypeExact(tile) != TT_SPACE)
|
||||
|
|
@ -563,7 +560,103 @@ ResProcessTiles(goodies, origin)
|
|||
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
|
||||
* rn_loc. If the resulting net is greater than the tolerance,
|
||||
|
|
@ -577,18 +670,20 @@ ResProcessTiles(goodies, origin)
|
|||
*/
|
||||
|
||||
bool
|
||||
ResExtractNet(startlist, goodies, cellname)
|
||||
ResFixPoint *startlist;
|
||||
ResExtractNet(node, goodies, cellname)
|
||||
ResSimNode *node;
|
||||
ResGlobalParams *goodies;
|
||||
char *cellname;
|
||||
{
|
||||
SearchContext scx;
|
||||
int pNum;
|
||||
ResDevTile *DevTiles, *lasttile;
|
||||
TileTypeBitMask FirstTileMask;
|
||||
Point startpoint;
|
||||
ResFixPoint *fix;
|
||||
static int first = 1;
|
||||
ResDevTile *DevTiles, *thisDev;
|
||||
ResFixPoint *fix;
|
||||
devPtr *tptr;
|
||||
int resMakeDevFunc();
|
||||
|
||||
/* Make sure all global network variables are reset */
|
||||
|
||||
|
|
@ -604,7 +699,7 @@ ResExtractNet(startlist, goodies, cellname)
|
|||
goodies->rg_maxres = 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)
|
||||
{
|
||||
|
|
@ -641,47 +736,57 @@ ResExtractNet(startlist, goodies, cellname)
|
|||
|
||||
DBCellClearDef(ResUse->cu_def);
|
||||
|
||||
/* Copy Paint */
|
||||
DevTiles = NULL;
|
||||
lasttile = NULL;
|
||||
for (fix = startlist; fix != NULL; fix = fix->fp_next)
|
||||
{
|
||||
ResDevTile *newdevtiles, *tmp;
|
||||
|
||||
#ifdef ARIEL
|
||||
if ((ResOptionsFlags & ResOpt_Power) &&
|
||||
strcmp(fix->fp_name, goodies->rg_name) != 0) continue;
|
||||
strcmp(node->name, goodies->rg_name) != 0) continue;
|
||||
#endif
|
||||
|
||||
scx.scx_area.r_ll.p_x = fix->fp_loc.p_x-2;
|
||||
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;
|
||||
/* Copy Paint */
|
||||
|
||||
/* 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;
|
||||
scx.scx_area.r_ll.p_y = node->location.p_y - 2;
|
||||
scx.scx_area.r_ur.p_x = node->location.p_x + 2;
|
||||
scx.scx_area.r_ur.p_y = node->location.p_y + 2;
|
||||
startpoint = node->location;
|
||||
|
||||
/* Because node->type might come from a label with a sticky type
|
||||
* that does not correspond exactly to the layer underneath, include
|
||||
* all connecting types.
|
||||
*/
|
||||
TTMaskSetMask(&FirstTileMask, &DBConnectTbl[fix->fp_ttype]);
|
||||
TTMaskZero(&FirstTileMask);
|
||||
TTMaskSetMask(&FirstTileMask, &DBConnectTbl[node->type]);
|
||||
|
||||
newdevtiles = DBTreeCopyConnectDCS(&scx, &FirstTileMask, 0,
|
||||
ResCopyMask, &TiPlaneRect, ResUse);
|
||||
DBTreeCopyConnect(&scx, &FirstTileMask, 0, ResCopyMask, &TiPlaneRect,
|
||||
SEL_DO_LABELS, ResUse);
|
||||
|
||||
for (tmp = newdevtiles; tmp && tmp->nextDev; tmp = tmp->nextDev);
|
||||
if (newdevtiles)
|
||||
/* Add devices to ResUse from list in node */
|
||||
DevTiles = NULL;
|
||||
for (tptr = node->firstDev; tptr; tptr = tptr->nextDev)
|
||||
{
|
||||
if (DevTiles)
|
||||
lasttile->nextDev = newdevtiles;
|
||||
else
|
||||
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);
|
||||
|
||||
/* find all contacts in design and note their position */
|
||||
/* Find all contacts in design and note their position */
|
||||
|
||||
ResContactList = (ResContactPoint *)ExtFindRegions(ResUse->cu_def,
|
||||
&(ResUse->cu_def->cd_bbox),
|
||||
|
|
@ -770,7 +875,7 @@ ResCleanUpEverything()
|
|||
resDevice *oldDev;
|
||||
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++)
|
||||
{
|
||||
|
|
@ -778,7 +883,6 @@ ResCleanUpEverything()
|
|||
&(ResUse->cu_def->cd_bbox), &DBAllButSpaceAndDRCBits,
|
||||
(ClientData)CLIENTDEFAULT, ResRemovePlumbing,
|
||||
(ClientData)NULL);
|
||||
|
||||
}
|
||||
|
||||
while (ResNodeList != NULL)
|
||||
|
|
@ -807,12 +911,9 @@ ResCleanUpEverything()
|
|||
freeMagic((char *)oldDev);
|
||||
}
|
||||
}
|
||||
|
||||
DBCellClearDef(ResUse->cu_def);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -849,10 +950,10 @@ FindStartTile(goodies, SourcePoint)
|
|||
TileType savtype = goodies->rg_ttype;
|
||||
TileType rtype;
|
||||
|
||||
savtype = goodies->rg_ttype;
|
||||
for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++)
|
||||
if (TTMaskHasType(rmask, rtype))
|
||||
{
|
||||
goodies->rg_ttype = rtype;
|
||||
if ((tile = FindStartTile(goodies, SourcePoint)) != NULL)
|
||||
{
|
||||
goodies->rg_ttype = savtype;
|
||||
|
|
@ -934,6 +1035,7 @@ FindStartTile(goodies, SourcePoint)
|
|||
t1 = TiGetType(tile);
|
||||
|
||||
devptr = ExtCurStyle->exts_device[t1];
|
||||
|
||||
/* left */
|
||||
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
|
||||
{
|
||||
|
|
@ -1018,10 +1120,10 @@ ResGetDevice(pt)
|
|||
for (pnum = PL_TECHDEPBASE; pnum < DBNumPlanes; pnum++)
|
||||
{
|
||||
if (TTMaskIntersect(&ExtCurStyle->exts_deviceMask, &DBPlaneTypes[pnum]) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
/*start at hint tile for device plane */
|
||||
|
||||
/* Start at hint tile for device plane */
|
||||
|
||||
tile = ResUse->cu_def->cd_planes[pnum]->pl_hint;
|
||||
GOTOPOINT(tile, &workingPoint);
|
||||
|
||||
|
|
@ -1036,5 +1138,5 @@ ResGetDevice(pt)
|
|||
return (((tileJunk *)tile->ti_client)->deviceList);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
195
resis/ResMerge.c
195
resis/ResMerge.c
|
|
@ -13,6 +13,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "database/database.h"
|
||||
#include "utils/malloc.h"
|
||||
#include "textio/textio.h"
|
||||
#include "extract/extractInt.h"
|
||||
#include "resis/resis.h"
|
||||
|
||||
TileTypeBitMask ResNoMergeMask[NT];
|
||||
|
|
@ -29,9 +30,10 @@ extern void ResFixBreakPoint();
|
|||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* ResDoneWithNode--After all connections to node are made, ResDoneWithNode
|
||||
* is called. It checks for parallel, series, loop, triangle,
|
||||
* and single conections, and simplifies the network where possible.
|
||||
* ResDoneWithNode--
|
||||
* After all connections to node are made, ResDoneWithNode is
|
||||
* called. It checks for parallel, series, loop, triangle, and
|
||||
* single conections, and simplifies the network where possible.
|
||||
*
|
||||
* Results: none
|
||||
*
|
||||
|
|
@ -56,10 +58,7 @@ ResDoneWithNode(resptr)
|
|||
|
||||
/* are there any resistors? */
|
||||
|
||||
if (resptr->rn_re == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (resptr->rn_re == NULL) return;
|
||||
|
||||
/* Special handling for geometry option */
|
||||
|
||||
|
|
@ -106,24 +105,21 @@ ResDoneWithNode(resptr)
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (status != UNTOUCHED) return; /* resptr may be invalid */
|
||||
|
||||
/* Eliminations that can be only if there are no devices connected */
|
||||
/* to node. Series and dangling connections fall in this group. */
|
||||
|
||||
if ((resptr->rn_te == NULL) && (resptr->rn_why != RES_NODE_ORIGIN)
|
||||
&& (status == UNTOUCHED))
|
||||
{
|
||||
status = ResSeriesCheck(resptr);
|
||||
}
|
||||
|
||||
if ((status == UNTOUCHED) && (resptr->rn_why != RES_NODE_ORIGIN))
|
||||
{
|
||||
status = ResParallelCheck(resptr);
|
||||
}
|
||||
|
||||
if ((status == UNTOUCHED) && (resptr->rn_why != RES_NODE_ORIGIN))
|
||||
{
|
||||
status = ResTriangleCheck(resptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -148,13 +144,17 @@ ResFixRes(resptr,resptr2,resptr3,elimResis,newResis)
|
|||
{
|
||||
resElement *thisREl;
|
||||
|
||||
resptr3->rn_float.rn_area += newResis->rr_value*resptr->rn_float.rn_area/((float)(newResis->rr_value+elimResis->rr_value));
|
||||
resptr2->rn_float.rn_area += elimResis->rr_value*resptr->rn_float.rn_area/((float)(newResis->rr_value+elimResis->rr_value));
|
||||
resptr3->rn_float.rn_area += newResis->rr_value*resptr->rn_float.rn_area
|
||||
/ ((float)(newResis->rr_value + elimResis->rr_value));
|
||||
resptr2->rn_float.rn_area += elimResis->rr_value*resptr->rn_float.rn_area
|
||||
/ ((float)(newResis->rr_value + elimResis->rr_value));
|
||||
newResis->rr_value += elimResis->rr_value;
|
||||
ASSERT(newResis->rr_value > 0, "series");
|
||||
newResis->rr_float.rr_area += elimResis->rr_float.rr_area;
|
||||
|
||||
#ifdef ARIEL
|
||||
if (elimResis->rr_csArea && elimResis->rr_csArea < newResis->rr_csArea || newResis->rr_csArea == 0)
|
||||
if (elimResis->rr_csArea && elimResis->rr_csArea < newResis->rr_csArea
|
||||
|| newResis->rr_csArea == 0)
|
||||
{
|
||||
newResis->rr_csArea = elimResis->rr_csArea;
|
||||
newResis->rr_tt = elimResis->rr_tt;
|
||||
|
|
@ -220,7 +220,7 @@ ResFixParallel(elimResis,newResis)
|
|||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* ResSeriesCheck -- for nodes with no devices, sees if a series
|
||||
or loop combination is possible.
|
||||
* or loop combination is possible.
|
||||
*
|
||||
* Results: returns SINGLE,LOOP,or SERIES if succesful.
|
||||
*
|
||||
|
|
@ -269,12 +269,10 @@ ResSeriesCheck(resptr)
|
|||
{
|
||||
if (rr1->rr_connection1 == resptr)
|
||||
{
|
||||
|
||||
if (rr2->rr_connection1 == resptr)
|
||||
{
|
||||
resptr2 = rr1->rr_connection2;
|
||||
if (rr1->rr_connection2 ==
|
||||
rr2->rr_connection2)
|
||||
if (rr1->rr_connection2 == rr2->rr_connection2)
|
||||
{
|
||||
status = LOOP;
|
||||
ResDeleteResPointer(rr1->rr_connection1, rr1);
|
||||
|
|
@ -287,7 +285,8 @@ ResSeriesCheck(resptr)
|
|||
ResEliminateResistor(rr1, &ResResList);
|
||||
ResEliminateResistor(rr2, &ResResList);
|
||||
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
|
||||
}else
|
||||
}
|
||||
else
|
||||
{
|
||||
status = SERIES;
|
||||
resptr3 = rr2->rr_connection2;
|
||||
|
|
@ -300,7 +299,8 @@ ResSeriesCheck(resptr)
|
|||
ResDoneWithNode(resptr2);
|
||||
}
|
||||
resptr2 = NULL;
|
||||
}else
|
||||
}
|
||||
else
|
||||
{
|
||||
resptr2 = rr1->rr_connection2;
|
||||
if (rr1->rr_connection2 == rr2->rr_connection1)
|
||||
|
|
@ -316,7 +316,8 @@ ResSeriesCheck(resptr)
|
|||
ResEliminateResistor(rr1, &ResResList);
|
||||
ResEliminateResistor(rr2, &ResResList);
|
||||
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
|
||||
}else
|
||||
}
|
||||
else
|
||||
{
|
||||
status = SERIES;
|
||||
resptr3 = rr2->rr_connection1;
|
||||
|
|
@ -330,7 +331,8 @@ ResSeriesCheck(resptr)
|
|||
}
|
||||
resptr2 = NULL;
|
||||
}
|
||||
}else
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rr2->rr_connection1 == resptr)
|
||||
{
|
||||
|
|
@ -348,12 +350,12 @@ ResSeriesCheck(resptr)
|
|||
ResEliminateResistor(rr1, &ResResList);
|
||||
ResEliminateResistor(rr2, &ResResList);
|
||||
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
|
||||
}else
|
||||
}
|
||||
else
|
||||
{
|
||||
status = SERIES;
|
||||
resptr3 = rr2->rr_connection2;
|
||||
rr1->rr_connection2 =
|
||||
rr2->rr_connection2;
|
||||
rr1->rr_connection2 = rr2->rr_connection2;
|
||||
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
|
||||
}
|
||||
if ((resptr2->rn_status & TRUE) == TRUE)
|
||||
|
|
@ -362,7 +364,8 @@ ResSeriesCheck(resptr)
|
|||
ResDoneWithNode(resptr2);
|
||||
}
|
||||
resptr2 = NULL;
|
||||
}else
|
||||
}
|
||||
else
|
||||
{
|
||||
resptr2 = rr1->rr_connection1;
|
||||
if (rr1->rr_connection1 == rr2->rr_connection1)
|
||||
|
|
@ -378,12 +381,12 @@ ResSeriesCheck(resptr)
|
|||
ResEliminateResistor(rr1, &ResResList);
|
||||
ResEliminateResistor(rr2, &ResResList);
|
||||
ResCleanNode(resptr, TRUE, &ResNodeList, &ResNodeQueue);
|
||||
}else
|
||||
}
|
||||
else
|
||||
{
|
||||
status = SERIES;
|
||||
resptr3 = rr2->rr_connection1;
|
||||
rr1->rr_connection2 =
|
||||
rr2->rr_connection1;
|
||||
rr1->rr_connection2 = rr2->rr_connection1;
|
||||
ResFixRes(resptr, resptr2, resptr3, rr2, rr1);
|
||||
}
|
||||
if ((resptr2->rn_status & TRUE) == TRUE)
|
||||
|
|
@ -399,7 +402,6 @@ ResSeriesCheck(resptr)
|
|||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -423,13 +425,13 @@ ResParallelCheck(resptr)
|
|||
resElement *rcell1, *rcell2;
|
||||
|
||||
|
||||
for (rcell1 = resptr->rn_re;
|
||||
rcell1->re_nextEl != NULL; rcell1 = rcell1->re_nextEl)
|
||||
for (rcell1 = resptr->rn_re; rcell1->re_nextEl != NULL;
|
||||
rcell1 = rcell1->re_nextEl)
|
||||
{
|
||||
r1 = rcell1->re_thisEl;
|
||||
|
||||
for (rcell2 = rcell1->re_nextEl;
|
||||
rcell2 != NULL; rcell2 = rcell2->re_nextEl)
|
||||
for (rcell2 = rcell1->re_nextEl; rcell2 != NULL;
|
||||
rcell2 = rcell2->re_nextEl)
|
||||
|
||||
{
|
||||
r2 = rcell2->re_thisEl;
|
||||
|
|
@ -483,23 +485,23 @@ ResTriangleCheck(resptr)
|
|||
resNode *n1, *n2, *n3;
|
||||
resElement *rcell1, *rcell2, *rcell3, *element;
|
||||
|
||||
for (rcell1 = resptr->rn_re;
|
||||
rcell1->re_nextEl != NULL; rcell1 = rcell1->re_nextEl)
|
||||
for (rcell1 = resptr->rn_re; rcell1->re_nextEl != NULL;
|
||||
rcell1 = rcell1->re_nextEl)
|
||||
{
|
||||
rr1 = rcell1->re_thisEl;
|
||||
n1 = (rr1->rr_connection1 == resptr) ? rr1->rr_connection2:
|
||||
rr1->rr_connection1;
|
||||
|
||||
for (rcell2 = rcell1->re_nextEl;
|
||||
rcell2 != NULL; rcell2 = rcell2->re_nextEl)
|
||||
for (rcell2 = rcell1->re_nextEl; rcell2 != NULL;
|
||||
rcell2 = rcell2->re_nextEl)
|
||||
{
|
||||
rr2 = rcell2->re_thisEl;
|
||||
if (TTMaskHasType(ResNoMergeMask + rr1->rr_tt, rr2->rr_tt))
|
||||
continue;
|
||||
n2 = (rr2->rr_connection1 == resptr) ? rr2->rr_connection2 :
|
||||
rr2->rr_connection1;
|
||||
for (rcell3 = n1->rn_re;
|
||||
rcell3 != NULL; rcell3 = rcell3->re_nextEl)
|
||||
for (rcell3 = n1->rn_re; rcell3 != NULL;
|
||||
rcell3 = rcell3->re_nextEl)
|
||||
{
|
||||
rr3 = rcell3->re_thisEl;
|
||||
if (TTMaskHasType(ResNoMergeMask + rr1->rr_tt, rr3->rr_tt))
|
||||
|
|
@ -517,14 +519,11 @@ ResTriangleCheck(resptr)
|
|||
{
|
||||
denom = 1.0 /denom;
|
||||
/* calculate new values for resistors */
|
||||
r1 = (((float) rr1->rr_value)*
|
||||
((float) rr2->rr_value))*denom;
|
||||
r1 = (((float)rr1->rr_value) * ((float)rr2->rr_value)) * denom;
|
||||
|
||||
r2 = (((float) rr2->rr_value)*
|
||||
((float) rr3->rr_value))*denom;
|
||||
r2 = (((float)rr2->rr_value) * ((float)rr3->rr_value)) * denom;
|
||||
|
||||
r3 = (((float) rr1->rr_value)*
|
||||
((float) rr3->rr_value))*denom;
|
||||
r3 = (((float)rr1->rr_value) * ((float)rr3->rr_value)) * denom;
|
||||
|
||||
rr1->rr_value = r1 + 0.5;
|
||||
rr2->rr_value = r2 + 0.5;
|
||||
|
|
@ -540,6 +539,7 @@ ResTriangleCheck(resptr)
|
|||
rr3->rr_value = 0;
|
||||
}
|
||||
n3 = (resNode *)mallocMagic((unsigned)(sizeof(resNode)));
|
||||
|
||||
/* Where should the new node be `put'? It */
|
||||
/* is arbitrarily assigned to the location */
|
||||
/* occupied by the first node. */
|
||||
|
|
@ -594,21 +594,15 @@ ResTriangleCheck(resptr)
|
|||
element->re_thisEl = rr3;
|
||||
n3->rn_re = element;
|
||||
if ((n1->rn_status & TRUE) == TRUE)
|
||||
{
|
||||
n1->rn_status &= ~TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
n1 = NULL;
|
||||
}
|
||||
|
||||
if ((n2->rn_status & TRUE) == TRUE)
|
||||
{
|
||||
n2->rn_status &= ~TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
n2 = NULL;
|
||||
}
|
||||
|
||||
ResDoneWithNode(resptr);
|
||||
if (n1 != NULL) ResDoneWithNode(n1);
|
||||
if (n2 != NULL) ResDoneWithNode(n2);
|
||||
|
|
@ -637,8 +631,8 @@ ResTriangleCheck(resptr)
|
|||
|
||||
void
|
||||
ResMergeNodes(node1, node2, pendingList, doneList)
|
||||
resNode *node1,*node2,**pendingList,**doneList;
|
||||
|
||||
resNode *node1, *node2;
|
||||
resNode **pendingList, **doneList;
|
||||
{
|
||||
resElement *workingRes, *tRes;
|
||||
tElement *workingDev, *tDev;
|
||||
|
|
@ -649,6 +643,7 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
|||
|
||||
/* sanity check */
|
||||
if (node1 == node2) return;
|
||||
|
||||
if (node1 == NULL || node2 == NULL)
|
||||
{
|
||||
TxError("Attempt to merge NULL node\n");
|
||||
|
|
@ -657,9 +652,7 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
|||
|
||||
/* don't want to merge away startpoint */
|
||||
if (node2->rn_why & RES_NODE_ORIGIN)
|
||||
{
|
||||
node1->rn_why = RES_NODE_ORIGIN;
|
||||
}
|
||||
|
||||
/* set node resistance */
|
||||
if (node1->rn_noderes > node2->rn_noderes)
|
||||
|
|
@ -673,7 +666,6 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
|||
}
|
||||
node1->rn_float.rn_area += node2->rn_float.rn_area;
|
||||
|
||||
|
||||
/* combine relevant flags */
|
||||
node1->rn_status |= (node2->rn_status & RN_MAXTDI);
|
||||
|
||||
|
|
@ -685,9 +677,7 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
|||
{
|
||||
ResPlug *plug = (ResPlug *) workingDev->te_thist;
|
||||
if (plug->rpl_node == node2)
|
||||
{
|
||||
plug->rpl_node = node1;
|
||||
}
|
||||
else
|
||||
{
|
||||
TxError("Bad plug node: is (%d %d), should be (%d %d)\n",
|
||||
|
|
@ -701,10 +691,8 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
|||
|
||||
for (j = 0; j != workingDev->te_thist->rd_nterms; j++)
|
||||
if (workingDev->te_thist->rd_terminals[j] == node2)
|
||||
{
|
||||
workingDev->te_thist->rd_terminals[j] = node1;
|
||||
}
|
||||
}
|
||||
tDev = workingDev;
|
||||
workingDev = workingDev->te_nextt;
|
||||
tDev->te_nextt = node1->rn_te;
|
||||
|
|
@ -712,6 +700,7 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
|||
}
|
||||
|
||||
/* append junction lists */
|
||||
|
||||
workingJunc = node2->rn_je;
|
||||
while (workingJunc != NULL)
|
||||
{
|
||||
|
|
@ -724,10 +713,8 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
|||
junk = (tileJunk *) tile->ti_client;
|
||||
|
||||
if ((junk->tj_status & RES_TILE_DONE) == FALSE)
|
||||
{
|
||||
ResFixBreakPoint(&junk->breakList, node2, node1);
|
||||
}
|
||||
}
|
||||
tJunc->je_thisj->rj_jnode = node1;
|
||||
workingJunc = workingJunc->je_nextj;
|
||||
tJunc->je_nextj = node1->rn_je;
|
||||
|
|
@ -749,62 +736,51 @@ ResMergeNodes(node1,node2,pendingList,doneList)
|
|||
tile =tCon->ce_thisc->cp_tile[i];
|
||||
junk = (tileJunk *) tile->ti_client;
|
||||
if ((junk->tj_status & RES_TILE_DONE) == FALSE)
|
||||
{
|
||||
ResFixBreakPoint(&junk->breakList, node2, node1);
|
||||
}
|
||||
}
|
||||
}
|
||||
workingCon = workingCon->ce_nextc;
|
||||
tCon->ce_nextc = node1->rn_ce;
|
||||
node1->rn_ce = tCon;
|
||||
}
|
||||
|
||||
/* Moves resistors to new node */
|
||||
|
||||
workingRes = node2->rn_re;
|
||||
while (workingRes != NULL)
|
||||
{
|
||||
if (workingRes->re_thisEl->rr_connection1 == node2)
|
||||
{
|
||||
workingRes->re_thisEl->rr_connection1 = node1;
|
||||
}
|
||||
else if (workingRes->re_thisEl->rr_connection2 == node2)
|
||||
{
|
||||
workingRes->re_thisEl->rr_connection2 = node1;
|
||||
}
|
||||
else
|
||||
{
|
||||
TxError("Resistor not found.\n");
|
||||
}
|
||||
|
||||
tRes = workingRes;
|
||||
workingRes = workingRes->re_nextEl;
|
||||
tRes->re_nextEl = node1->rn_re;
|
||||
node1->rn_re = tRes;
|
||||
}
|
||||
if ((node2->rn_status & FINISHED) == FINISHED)
|
||||
{
|
||||
ResRemoveFromQueue(node2, doneList);
|
||||
}
|
||||
else
|
||||
{
|
||||
ResRemoveFromQueue(node2, pendingList);
|
||||
}
|
||||
|
||||
if (node2->rn_client != (ClientData)NULL)
|
||||
{
|
||||
freeMagic((char *)node2->rn_client);
|
||||
node2->rn_client = (ClientData)NULL;
|
||||
}
|
||||
{
|
||||
|
||||
node2->rn_re = (resElement *)CLIENTDEFAULT;
|
||||
node2->rn_ce = (cElement *)CLIENTDEFAULT;
|
||||
node2->rn_je = (jElement *)CLIENTDEFAULT;
|
||||
node2->rn_te = (tElement *)CLIENTDEFAULT;
|
||||
node2->rn_more = (resNode *)CLIENTDEFAULT;
|
||||
node2->rn_less = (resNode *)CLIENTDEFAULT;
|
||||
}
|
||||
freeMagic((char *)node2);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -835,12 +811,10 @@ ResDeleteResPointer(node,resistor)
|
|||
{
|
||||
notfound = FALSE;
|
||||
if (rcell1 != NULL)
|
||||
{
|
||||
rcell1->re_nextEl = rcell2->re_nextEl;
|
||||
}else
|
||||
{
|
||||
else
|
||||
node->rn_re = rcell2->re_nextEl;
|
||||
}
|
||||
|
||||
/* Set fields to null just in case there are any stray */
|
||||
/* pointers to structure. */
|
||||
rcell2->re_thisEl = NULL;
|
||||
|
|
@ -852,11 +826,9 @@ ResDeleteResPointer(node,resistor)
|
|||
rcell2 = rcell2->re_nextEl;
|
||||
}
|
||||
if (notfound)
|
||||
{
|
||||
TxError("Missing rptr at (%d %d).\n",
|
||||
node->rn_loc.p_x, node->rn_loc.p_y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -878,19 +850,16 @@ ResEliminateResistor(resistor,homelist)
|
|||
|
||||
{
|
||||
if (resistor->rr_lastResistor == NULL)
|
||||
{
|
||||
*homelist = resistor->rr_nextResistor;
|
||||
}else
|
||||
{
|
||||
else
|
||||
resistor->rr_lastResistor->rr_nextResistor = resistor->rr_nextResistor;
|
||||
}
|
||||
|
||||
if (resistor->rr_nextResistor != NULL)
|
||||
{
|
||||
resistor->rr_nextResistor->rr_lastResistor = resistor->rr_lastResistor;
|
||||
}
|
||||
|
||||
/* set everything to null so that any stray pointers will cause */
|
||||
/* immediate death instead of a slow lingering one. */
|
||||
|
||||
resistor->rr_nextResistor = NULL;
|
||||
resistor->rr_lastResistor = NULL;
|
||||
resistor->rr_connection1 = NULL;
|
||||
|
|
@ -898,7 +867,6 @@ ResEliminateResistor(resistor,homelist)
|
|||
freeMagic((char *)resistor);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -960,36 +928,26 @@ ResCleanNode(resptr,junk,homelist1,homelist2)
|
|||
freeMagic((char *)rcell);
|
||||
}
|
||||
if (resptr->rn_less != NULL)
|
||||
{
|
||||
resptr->rn_less->rn_more = resptr->rn_more;
|
||||
}else
|
||||
{
|
||||
if (*homelist1 == resptr)
|
||||
{
|
||||
*homelist1 = resptr->rn_more;
|
||||
}
|
||||
else if (*homelist2 == resptr)
|
||||
{
|
||||
*homelist2 = resptr->rn_more;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*homelist1 == resptr)
|
||||
*homelist1 = resptr->rn_more;
|
||||
else if (*homelist2 == resptr)
|
||||
*homelist2 = resptr->rn_more;
|
||||
else
|
||||
TxError("Error: Attempted to eliminate node from wrong list.\n");
|
||||
}
|
||||
}
|
||||
if (resptr->rn_more != NULL)
|
||||
{
|
||||
resptr->rn_more->rn_less = resptr->rn_less;
|
||||
}
|
||||
|
||||
{
|
||||
resptr->rn_re = (resElement *) CLIENTDEFAULT;
|
||||
resptr->rn_ce = (cElement *) CLIENTDEFAULT;
|
||||
resptr->rn_je = (jElement *) CLIENTDEFAULT;
|
||||
resptr->rn_te = (tElement *) CLIENTDEFAULT;
|
||||
resptr->rn_more = (resNode *) CLIENTDEFAULT;
|
||||
resptr->rn_less = (resNode *) CLIENTDEFAULT;
|
||||
}
|
||||
|
||||
freeMagic((char *)resptr);
|
||||
}
|
||||
}
|
||||
|
|
@ -1036,28 +994,23 @@ ResFixBreakPoint(sourcelist,origNode,newNode)
|
|||
if (alreadypresent)
|
||||
{
|
||||
if (bp2 == NULL)
|
||||
{
|
||||
*sourcelist = bp->br_next;
|
||||
}else
|
||||
{
|
||||
else
|
||||
bp2->br_next = bp->br_next;
|
||||
}
|
||||
|
||||
bp3 = bp;
|
||||
bp = bp->br_next;
|
||||
|
||||
if (bp3->br_crect != NULL && bp4->br_crect == NULL)
|
||||
{
|
||||
bp4->br_crect = bp3->br_crect;
|
||||
}
|
||||
|
||||
freeMagic((char *)bp3);
|
||||
continue;
|
||||
}else
|
||||
{
|
||||
(bp->br_this = newNode);
|
||||
}
|
||||
else
|
||||
bp->br_this = newNode;
|
||||
}
|
||||
bp2 = bp;
|
||||
bp = bp->br_next;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -171,16 +171,25 @@ ResPrintExtDev(outextfile, devices)
|
|||
else
|
||||
fprintf(outextfile, " \"%s\"", subsName);
|
||||
|
||||
fprintf(outextfile, " \"%s\" %d %s \"%s\" %d %s \"%s\" %d %s\n",
|
||||
if (devices->gate != NULL)
|
||||
fprintf(outextfile, " \"%s\" %d %s",
|
||||
devices->gate->name,
|
||||
devices->layout->rd_length * 2,
|
||||
devices->rs_gattr,
|
||||
devices->rs_gattr);
|
||||
|
||||
if (devices->source != NULL)
|
||||
fprintf(outextfile, " \"%s\" %d %s",
|
||||
devices->source->name,
|
||||
devices->layout->rd_width,
|
||||
devices->rs_sattr,
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ ResFixPoint *ResFixList;
|
|||
|
||||
extern void ResSimProcessDrivePoints();
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -133,11 +132,11 @@ ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
|
|||
if (fp == NULL)
|
||||
{
|
||||
TxError("Cannot open file %s%s\n", simfile, ".sim");
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
extfile = 0;
|
||||
|
||||
/*read in file */
|
||||
/* Read in file */
|
||||
while (gettokens(line, fp) != 0)
|
||||
{
|
||||
fettype = MINFINITY;
|
||||
|
|
@ -151,34 +150,45 @@ ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
|
|||
}
|
||||
result=0;
|
||||
break;
|
||||
case 'e': fettype = DBTechNameType("efet");
|
||||
case 'e':
|
||||
fettype = DBTechNameType("efet");
|
||||
break;
|
||||
case 'd': fettype = DBTechNameType("dfet");
|
||||
case 'd':
|
||||
fettype = DBTechNameType("dfet");
|
||||
break;
|
||||
case 'n': fettype = DBTechNameType("nfet");
|
||||
case 'n':
|
||||
fettype = DBTechNameType("nfet");
|
||||
break;
|
||||
case 'p': fettype = DBTechNameType("pfet");
|
||||
case 'p':
|
||||
fettype = DBTechNameType("pfet");
|
||||
break;
|
||||
case 'b': fettype = DBTechNameType("bnpn");
|
||||
case 'b':
|
||||
fettype = DBTechNameType("bnpn");
|
||||
break;
|
||||
case 'C': if (capproc) result = (*capproc)(line);
|
||||
case 'C':
|
||||
if (capproc) result = (*capproc)(line);
|
||||
break;
|
||||
case 'R': if (resproc)result = (*resproc)(line);
|
||||
case 'R':
|
||||
if (resproc) result = (*resproc)(line);
|
||||
break;
|
||||
case '=': if (mergeproc)result = (*mergeproc)(line);
|
||||
case '=':
|
||||
if (mergeproc) result = (*mergeproc)(line);
|
||||
break;
|
||||
case 'A': if (attrproc) result =
|
||||
(*attrproc)(line[ATTRIBUTENODENAME],
|
||||
line[ATTRIBUTEVALUE],
|
||||
simfile, &extfile);
|
||||
case 'A':
|
||||
if (attrproc)
|
||||
result = (*attrproc)(line[ATTRIBUTENODENAME],
|
||||
line[ATTRIBUTEVALUE], simfile, &extfile);
|
||||
break;
|
||||
case 'x': fettype = DBNumTypes;
|
||||
case 'x':
|
||||
fettype = DBNumTypes;
|
||||
break;
|
||||
case 'D':
|
||||
case 'c':
|
||||
case 'r': break;
|
||||
default: result = 1;
|
||||
(void)fclose(fp);
|
||||
case 'r':
|
||||
break;
|
||||
default:
|
||||
result = 1;
|
||||
fclose(fp);
|
||||
break;
|
||||
}
|
||||
if (fettype == -1)
|
||||
|
|
@ -197,15 +207,15 @@ ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
|
|||
|
||||
devptr = ExtCurStyle->exts_device[fettype];
|
||||
sheetr = (float)devptr->exts_linearResist;
|
||||
result = (*fetproc)(line,sheetr,fettype);
|
||||
result = (*fetproc)(line, sheetr, devptr);
|
||||
}
|
||||
if (result != 0)
|
||||
{
|
||||
TxError("Error in sim file %s\n", line[0]);
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
(void)fclose(fp);
|
||||
fclose(fp);
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
|
@ -226,7 +236,6 @@ ResReadSim(simfile, fetproc, capproc, resproc, attrproc, mergeproc, subproc)
|
|||
int
|
||||
ResReadNode(nodefile)
|
||||
char *nodefile;
|
||||
|
||||
{
|
||||
char line[MAXLINE][MAXTOKEN];
|
||||
FILE *fp, *fopen();
|
||||
|
|
@ -239,7 +248,7 @@ ResReadNode(nodefile)
|
|||
if (fp == NULL)
|
||||
{
|
||||
TxError("Cannot open file %s%s\n", nodefile, ".nodes");
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
while (gettokens(line,fp) != 0)
|
||||
{
|
||||
|
|
@ -259,14 +268,15 @@ ResReadNode(nodefile)
|
|||
|
||||
if (node->type == -1)
|
||||
{
|
||||
TxError("Bad tile type name in %s.nodes file for node %s\n",nodefile,node->name);
|
||||
TxError("Bad tile type name in %s.nodes file for node %s\n",
|
||||
nodefile, node->name);
|
||||
TxError("Did you use the newest version of ext2sim?\n");
|
||||
(void)fclose(fp);
|
||||
return(1);
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
(void)fclose(fp);
|
||||
return(0);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -286,7 +296,6 @@ int
|
|||
gettokens(line, fp)
|
||||
char line[][MAXTOKEN];
|
||||
FILE *fp;
|
||||
|
||||
{
|
||||
int i = 0, j = 0;
|
||||
int c;
|
||||
|
|
@ -296,10 +305,12 @@ gettokens(line,fp)
|
|||
switch(c)
|
||||
{
|
||||
case ' ':
|
||||
case ' ' : line[i++][j] = '\0';
|
||||
case ' ' :
|
||||
line[i++][j] = '\0';
|
||||
j = 0;
|
||||
break;
|
||||
default: line[i][j++] = c;
|
||||
default:
|
||||
line[i][j++] = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -309,12 +320,10 @@ gettokens(line,fp)
|
|||
j = 0;
|
||||
}
|
||||
for (j = i; j < MAXLINE; j++)
|
||||
{
|
||||
line[j][0] = '\0';
|
||||
}
|
||||
return(i);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
|
|
@ -342,6 +351,7 @@ ResSimSubckt(line)
|
|||
float lambda;
|
||||
TileType ttype = TT_SPACE;
|
||||
char *lptr = NULL, *wptr = NULL;
|
||||
ExtDevice *devptr;
|
||||
|
||||
device = (RDev *) mallocMagic((unsigned) (sizeof(RDev)));
|
||||
|
||||
|
|
@ -358,11 +368,14 @@ ResSimSubckt(line)
|
|||
|
||||
ResRDevList = device;
|
||||
device->layout = NULL;
|
||||
device->source = device->drain = device->gate = device->subs = NULL;
|
||||
|
||||
/* The last argument is the name of the device */
|
||||
for (i = 1; line[i][0] != '\0'; i++);
|
||||
i--;
|
||||
|
||||
/* To do: Replace this search with a pre-prepared hash */
|
||||
/* table to key off of the device name. */
|
||||
for (j = 0; j < EFDevNumTypes; j++)
|
||||
if (!strcmp(EFDevTypes[j], line[i]))
|
||||
break;
|
||||
|
|
@ -391,34 +404,35 @@ ResSimSubckt(line)
|
|||
case 'y':
|
||||
device->location.p_y = (int)((float)atof(eqptr) / lambda);
|
||||
break;
|
||||
case 't':
|
||||
ttype = (int)(atoi(eqptr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This should not be needed, as ext2sim should encode device type */
|
||||
/* in the attributes list. */
|
||||
if (ttype == TT_SPACE)
|
||||
{
|
||||
if (j == EFDevNumTypes)
|
||||
{
|
||||
TxError("Failure to find device type %s\n", line[i]);
|
||||
return 1;
|
||||
}
|
||||
ttype = extGetDevType(EFDevTypes[j]);
|
||||
}
|
||||
|
||||
/* Find the device record that corresponds to the device name */
|
||||
for (devptr = ExtCurStyle->exts_device[ttype]; devptr; devptr = devptr->exts_next)
|
||||
if (!strcmp(devptr->exts_deviceName, EFDevTypes[j]))
|
||||
break;
|
||||
|
||||
device->rs_devptr = devptr;
|
||||
device->rs_ttype = ttype;
|
||||
|
||||
if (lptr != NULL && wptr != NULL)
|
||||
{
|
||||
float rpersquare;
|
||||
ExtDevice *devptr;
|
||||
|
||||
devptr = ExtCurStyle->exts_device[ttype];
|
||||
rpersquare =(float)devptr->exts_linearResist;
|
||||
/* Subcircuit types may not have a length or width value, in which */
|
||||
/* case it is zero. Don't induce a divide-by-zero error. */
|
||||
if (MagAtof(wptr) == 0)
|
||||
device->resistance = 0;
|
||||
else
|
||||
device->resistance = MagAtof(lptr) * rpersquare/MagAtof(wptr);
|
||||
}
|
||||
else
|
||||
|
|
@ -438,8 +452,6 @@ ResSimSubckt(line)
|
|||
return rvalue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -453,10 +465,10 @@ ResSimSubckt(line)
|
|||
*/
|
||||
|
||||
int
|
||||
ResSimDevice(line, rpersquare, ttype)
|
||||
ResSimDevice(line, rpersquare, devptr)
|
||||
char line[][MAXTOKEN];
|
||||
float rpersquare;
|
||||
TileType ttype;
|
||||
ExtDevice *devptr;
|
||||
|
||||
{
|
||||
RDev *device;
|
||||
|
|
@ -465,22 +477,26 @@ ResSimDevice(line, rpersquare, ttype)
|
|||
static int nowarning = TRUE;
|
||||
float lambda;
|
||||
|
||||
device = (RDev *) mallocMagic((unsigned) (sizeof(RDev)));
|
||||
if ((line[RDEV_WIDTH][0] == '\0') || (line[RDEV_LENGTH][0] == '\0'))
|
||||
{
|
||||
TxError("error in input file:\n");
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
device = (RDev *)mallocMagic((unsigned)(sizeof(RDev)));
|
||||
if (nowarning && rpersquare == 0)
|
||||
{
|
||||
TxError("Warning- FET resistance not included or set to zero in technology file-\n");
|
||||
TxError("Warning: FET resistance not included or "
|
||||
"set to zero in technology file-\n");
|
||||
TxError("All driven nodes will be extracted\n");
|
||||
nowarning = FALSE;
|
||||
}
|
||||
device->resistance = MagAtof(line[RDEV_LENGTH]) * rpersquare/MagAtof(line[RDEV_WIDTH]);
|
||||
}
|
||||
if (MagAtof(line[RDEV_WIDTH]) != 0)
|
||||
device->resistance = MagAtof(line[RDEV_LENGTH]) * rpersquare /
|
||||
MagAtof(line[RDEV_WIDTH]);
|
||||
else
|
||||
device->resistance = 0;
|
||||
|
||||
device->status = FALSE;
|
||||
device->nextDev = ResRDevList;
|
||||
|
||||
|
|
@ -491,7 +507,9 @@ ResSimDevice(line, rpersquare, ttype)
|
|||
device->rs_gattr=RDEV_NOATTR;
|
||||
device->rs_sattr=RDEV_NOATTR;
|
||||
device->rs_dattr=RDEV_NOATTR;
|
||||
device->rs_ttype = ttype;
|
||||
device->rs_devptr = devptr;
|
||||
|
||||
device->gate = device->source = device->drain = device->subs = NULL;
|
||||
|
||||
/* sim attributes look like g=a1,a2 */
|
||||
/* ext attributes are "a1","a2" */
|
||||
|
|
@ -521,10 +539,17 @@ ResSimDevice(line, rpersquare, ttype)
|
|||
strncpy(newattr, tmpattr, k);
|
||||
switch (line[i][0])
|
||||
{
|
||||
case 'g': device->rs_gattr = newattr; break;
|
||||
case 's': device->rs_sattr = newattr; break;
|
||||
case 'd': device->rs_dattr = newattr; break;
|
||||
default: TxError("Bad fet attribute\n");
|
||||
case 'g':
|
||||
device->rs_gattr = newattr;
|
||||
break;
|
||||
case 's':
|
||||
device->rs_sattr = newattr;
|
||||
break;
|
||||
case 'd':
|
||||
device->rs_dattr = newattr;
|
||||
break;
|
||||
default:
|
||||
TxError("Bad fet attribute\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -534,10 +559,9 @@ ResSimDevice(line, rpersquare, ttype)
|
|||
ResSimNewNode(line[SOURCE], SOURCE, device) +
|
||||
ResSimNewNode(line[DRAIN], DRAIN, device);
|
||||
|
||||
return(rvalue);
|
||||
return rvalue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -564,7 +588,7 @@ ResSimNewNode(line, type, device)
|
|||
if (line[0] == '\0')
|
||||
{
|
||||
TxError("Missing device connection\n");
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
entry = HashFind(&ResNodeTable, line);
|
||||
node = ResInitializeNode(entry);
|
||||
|
|
@ -575,21 +599,25 @@ ResSimNewNode(line, type, device)
|
|||
tptr->terminal = type;
|
||||
switch(type)
|
||||
{
|
||||
case GATE: device->gate = node;
|
||||
case GATE:
|
||||
device->gate = node;
|
||||
break;
|
||||
case SOURCE: device->source = node;
|
||||
case SOURCE:
|
||||
device->source = node;
|
||||
break;
|
||||
case DRAIN: device->drain = node;
|
||||
case DRAIN:
|
||||
device->drain = node;
|
||||
break;
|
||||
case SUBS: device->subs = node;
|
||||
case SUBS:
|
||||
device->subs = node;
|
||||
break;
|
||||
default: TxError("Bad Terminal Specifier\n");
|
||||
default:
|
||||
TxError("Bad Terminal Specifier\n");
|
||||
break;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -626,39 +654,38 @@ ResSimCapacitor(line)
|
|||
if (strcmp(line[COUPLETERMINAL2], "GND") == 0 ||
|
||||
strcmp(line[COUPLETERMINAL2], "Vdd") == 0)
|
||||
{
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
entry2 = HashFind(&ResNodeTable, line[COUPLETERMINAL2]);
|
||||
node2 = ResInitializeNode(entry2);
|
||||
node2->capacitance += MagAtof(line[COUPLEVALUE]);
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(line[COUPLETERMINAL2], "GND") == 0)
|
||||
{
|
||||
node1->capacitance += MagAtof(line[COUPLEVALUE]);
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(line[COUPLETERMINAL2], "Vdd") == 0)
|
||||
{
|
||||
node1->cap_vdd += MagAtof(line[COUPLEVALUE]);
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
entry2 = HashFind(&ResNodeTable, line[COUPLETERMINAL2]);
|
||||
node2 = ResInitializeNode(entry2);
|
||||
if (strcmp(line[COUPLETERMINAL1], "GND") == 0)
|
||||
{
|
||||
node2->capacitance += MagAtof(line[COUPLEVALUE]);
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
if (strcmp(line[COUPLETERMINAL1], "Vdd") == 0)
|
||||
{
|
||||
node2->cap_vdd += MagAtof(line[COUPLEVALUE]);
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
node1->cap_couple += MagAtof(line[COUPLEVALUE]);
|
||||
node2->cap_couple += MagAtof(line[COUPLEVALUE]);
|
||||
return(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -679,7 +706,6 @@ ResSimCapacitor(line)
|
|||
int
|
||||
ResSimResistor(line)
|
||||
char line[][MAXTOKEN];
|
||||
|
||||
{
|
||||
HashEntry *entry;
|
||||
ResSimNode *node;
|
||||
|
|
@ -687,21 +713,19 @@ ResSimResistor(line)
|
|||
if (line[RESNODENAME][0] == 0)
|
||||
{
|
||||
TxError("Bad Resistor\n");
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
entry = HashFind(&ResNodeTable, line[RESNODENAME]);
|
||||
node = ResInitializeNode(entry);
|
||||
if (node->resistance != 0)
|
||||
{
|
||||
TxError("Duplicate Resistance Entries\n");
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
node->resistance = MagAtof(line[NODERESISTANCE]);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -732,7 +756,7 @@ ResSimAttribute(aname,avalue,rootname,readextfile)
|
|||
if (aname[0] == 0)
|
||||
{
|
||||
TxError("Bad Resistor\n");
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
entry = HashFind(&ResNodeTable, aname);
|
||||
node = ResInitializeNode(entry);
|
||||
|
|
@ -784,7 +808,8 @@ ResSimAttribute(aname,avalue,rootname,readextfile)
|
|||
else
|
||||
{
|
||||
if (notwarned)
|
||||
TxError("Drivepoint for %s not defined in %s.ext; is it defined in a child cell?\n",node->name,rootname);
|
||||
TxError("Drivepoint for %s not defined in %s.ext; is it "
|
||||
"defined in a child cell?\n", node->name, rootname);
|
||||
notwarned = FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -801,12 +826,11 @@ ResSimAttribute(aname,avalue,rootname,readextfile)
|
|||
#endif
|
||||
if (avalue = strchr(avalue, ','))
|
||||
{
|
||||
(void) ResSimAttribute(aname,avalue+1,rootname,readextfile);
|
||||
ResSimAttribute(aname, avalue + 1, rootname, readextfile);
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -844,7 +868,8 @@ ResSimProcessDrivePoints(filename)
|
|||
while (gettokens(line,fp) != 0)
|
||||
{
|
||||
if (strncmp(line[RES_EXT_ATTR], "attr", 4) != 0 ||
|
||||
strncmp(line[RES_EXT_ATTR_TEXT],"\"res:drive\"",11) != 0) continue;
|
||||
strncmp(line[RES_EXT_ATTR_TEXT], "\"res:drive\"", 11) != 0)
|
||||
continue;
|
||||
|
||||
entry = HashFind(&ResNodeTable, line[RES_EXT_ATTR_NAME]);
|
||||
node = ResInitializeNode(entry);
|
||||
|
|
@ -854,7 +879,6 @@ ResSimProcessDrivePoints(filename)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -890,19 +914,20 @@ ResSimProcessFixPoints(filename)
|
|||
while (gettokens(line, fp) != 0)
|
||||
{
|
||||
if (strncmp(line[RES_EXT_ATTR], "attr", 4) != 0 ||
|
||||
strncmp(line[RES_EXT_ATTR_TEXT],"\"res:fix",8) != 0) continue;
|
||||
strncmp(line[RES_EXT_ATTR_TEXT], "\"res:fix", 8) != 0)
|
||||
continue;
|
||||
label = line[RES_EXT_ATTR_TEXT];
|
||||
label += 8;
|
||||
if (*label == ':') label++;
|
||||
if ((c=strrchr(label, '"')) != NULL) *c = '\0';
|
||||
else if (*label == '\0');
|
||||
else
|
||||
else if (*label != '\0')
|
||||
{
|
||||
TxError("Bad res:fix attribute label %s\n",
|
||||
line[RES_EXT_ATTR_TEXT]);
|
||||
*label ='\0';
|
||||
}
|
||||
thisfix = (ResFixPoint *) mallocMagic((unsigned) (sizeof(ResFixPoint)+strlen(label)));
|
||||
thisfix = (ResFixPoint *)mallocMagic((unsigned)(sizeof(ResFixPoint)
|
||||
+ strlen(label)));
|
||||
thisfix->fp_next = ResFixList;
|
||||
ResFixList = thisfix;
|
||||
thisfix->fp_loc.p_x = atoi(line[RES_EXT_ATTR_X]);
|
||||
|
|
@ -953,7 +978,7 @@ ResSimMerge(line)
|
|||
ptr->nextDev = node->forward->firstDev;
|
||||
node->forward->firstDev = ptr;
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1002,5 +1027,5 @@ ResInitializeNode(entry)
|
|||
{
|
||||
node = node->forward;
|
||||
}
|
||||
return(node);
|
||||
return node;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
|||
#include "textio/textio.h"
|
||||
#include "extract/extract.h"
|
||||
#include "extract/extractInt.h"
|
||||
#include "extflat/extflat.h"
|
||||
#include "windows/windows.h"
|
||||
#include "dbwind/dbwind.h"
|
||||
#include "utils/utils.h"
|
||||
|
|
@ -52,7 +53,8 @@ extern ResSimNode *ResOriginalNodes; /*Linked List of Nodes */
|
|||
int resNodeNum;
|
||||
|
||||
#ifdef LAPLACE
|
||||
int ResOptionsFlags = ResOpt_Simplify|ResOpt_Tdi|ResOpt_DoExtFile|ResOpt_CacheLaplace;
|
||||
int ResOptionsFlags = ResOpt_Simplify | ResOpt_Tdi | ResOpt_DoExtFile
|
||||
| ResOpt_CacheLaplace;
|
||||
#else
|
||||
int ResOptionsFlags = ResOpt_Simplify | ResOpt_Tdi | ResOpt_DoExtFile;
|
||||
#endif
|
||||
|
|
@ -97,17 +99,34 @@ ExtResisForDef(celldef, resisdata)
|
|||
HashEntry *entry;
|
||||
devPtr *tptr,*oldtptr;
|
||||
ResSimNode *node;
|
||||
int result;
|
||||
int result, idx;
|
||||
char *devname;
|
||||
|
||||
ResRDevList = 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);
|
||||
/* read in .sim file */
|
||||
result = (ResReadSim(celldef->cd_name,
|
||||
ResSimDevice, ResSimCapacitor, ResSimResistor,
|
||||
ResSimAttribute, ResSimMerge, ResSimSubckt) == 0);
|
||||
|
||||
/* Clean up the EFDevTypes table */
|
||||
for (idx = 0; idx < EFDevNumTypes; idx++) freeMagic(EFDevTypes[idx]);
|
||||
EFDevNumTypes = 0;
|
||||
|
||||
if (result)
|
||||
/* read in .nodes file */
|
||||
result = (ResReadNode(celldef->cd_name) == 0);
|
||||
|
|
@ -246,6 +265,17 @@ typedef enum {
|
|||
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)
|
||||
: RES_RUN;
|
||||
|
||||
|
|
@ -434,7 +464,7 @@ typedef enum {
|
|||
CellDef *def;
|
||||
Rect rect;
|
||||
int oldoptions;
|
||||
ResFixPoint fp;
|
||||
ResSimNode lnode;
|
||||
|
||||
if (ToolGetBoxWindow((Rect *) NULL, (int *) NULL) == NULL)
|
||||
{
|
||||
|
|
@ -451,14 +481,14 @@ typedef enum {
|
|||
oldoptions = ResOptionsFlags;
|
||||
ResOptionsFlags = ResOpt_DoSubstrate | ResOpt_Signal | ResOpt_Box;
|
||||
#ifdef LAPLACE
|
||||
ResOptionsFlags |= (oldoptions & (ResOpt_CacheLaplace|ResOpt_DoLaplace));
|
||||
ResOptionsFlags |= (oldoptions &
|
||||
(ResOpt_CacheLaplace | ResOpt_DoLaplace));
|
||||
LaplaceMatchCount = 0;
|
||||
LaplaceMissCount = 0;
|
||||
#endif
|
||||
fp.fp_ttype = tt;
|
||||
fp.fp_loc = rect.r_ll;
|
||||
fp.fp_next = NULL;
|
||||
if (ResExtractNet(&fp, &gparams, NULL) != 0) return;
|
||||
lnode.location = rect.r_ll;
|
||||
lnode.type = tt;
|
||||
if (ResExtractNet(&lnode, &gparams, NULL) != 0) return;
|
||||
ResPrintResistorList(stdout, ResResList);
|
||||
ResPrintDeviceList(stdout, ResRDevList);
|
||||
#ifdef LAPLACE
|
||||
|
|
@ -581,8 +611,6 @@ resSubcircuitFunc(cellDef, rdata)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -961,7 +989,7 @@ ResCheckSimNodes(celldef, resisdata)
|
|||
t1->drain != t2->source)) break;
|
||||
|
||||
/* do parallel combination */
|
||||
if (cumRes != 0.0 && t2->resistance != 0.0)
|
||||
if ((cumRes != 0.0) && (t2->resistance != 0.0))
|
||||
{
|
||||
cumRes = (cumRes * t2->resistance) /
|
||||
(cumRes + t2->resistance);
|
||||
|
|
@ -1005,17 +1033,17 @@ ResCheckSimNodes(celldef, resisdata)
|
|||
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 "
|
||||
"driving device\n",node->name);
|
||||
}
|
||||
if (minRes == FLT_MAX || gparams.rg_devloc == NULL)
|
||||
if ((minRes == FLT_MAX) || (gparams.rg_devloc == NULL))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
gparams.rg_bigdevres = (int)minRes * OHMSTOMILLIOHMS;
|
||||
if (rctol == 0.0 || tol == 0.0)
|
||||
if ((rctol == 0.0) || (tol == 0.0))
|
||||
{
|
||||
ftolerance = 0.0;
|
||||
rctolerance = 0.0;
|
||||
|
|
@ -1031,19 +1059,16 @@ ResCheckSimNodes(celldef, resisdata)
|
|||
* resistance? If so, extract net.
|
||||
*/
|
||||
|
||||
if (node->resistance > ftolerance || node->status & FORCE ||
|
||||
if ((node->resistance > ftolerance) || (node->status & FORCE) ||
|
||||
(ResOpt_ExtractAll & ResOptionsFlags))
|
||||
{
|
||||
ResFixPoint fp;
|
||||
|
||||
failed1++;
|
||||
fp.fp_loc = node->location;
|
||||
fp.fp_ttype = node->type;
|
||||
fp.fp_next = NULL;
|
||||
if (ResExtractNet(&fp, &gparams, outfile) != 0)
|
||||
if (ResExtractNet(node, &gparams, outfile) != 0)
|
||||
{
|
||||
/* On error, don't output this net, but keep going */
|
||||
TxError("Error in extracting node %s\n", node->name);
|
||||
// break; // Don't stop for one error. . .
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1400,7 +1425,8 @@ ResSortByGate(DevpointerList)
|
|||
{
|
||||
int changed = TRUE;
|
||||
int localchange = TRUE;
|
||||
devPtr *working, *last=NULL, *current, *gatelist=NULL;
|
||||
devPtr *working, *current;
|
||||
devPtr *last = NULL, *gatelist = NULL;
|
||||
|
||||
working = *DevpointerList;
|
||||
while (working != NULL)
|
||||
|
|
|
|||
|
|
@ -48,8 +48,6 @@ int resRemoveLoops = FALSE;
|
|||
extern void ResMoveDevices();
|
||||
extern void ResAddResistorToList();
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -75,27 +73,26 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
|||
resNode *node, *otherNode, *node1, *node2;
|
||||
resResistor *resistor1 = NULL, *resistor2 = NULL;
|
||||
int numdrive = 0, numreceive = 0;
|
||||
int MarkedReceivers,UnMarkedReceivers,NumberOfDrivers,PendingReceivers;
|
||||
int MarkedReceivers, UnMarkedReceivers;
|
||||
int NumberOfDrivers, PendingReceivers;
|
||||
|
||||
if (*nodelist == NULL) return;
|
||||
node = *nodelist;
|
||||
node->rn_status |= MARKED | FINISHED;
|
||||
*nodelist = node->rn_more;
|
||||
if (node->rn_more != NULL)
|
||||
{
|
||||
node->rn_more->rn_less = (resNode *) NULL;
|
||||
}
|
||||
|
||||
node->rn_more = *biglist;
|
||||
if (*biglist != (resNode *) NULL)
|
||||
{
|
||||
(*biglist)->rn_less = node;
|
||||
}
|
||||
|
||||
*biglist = node;
|
||||
|
||||
/*
|
||||
Walk though resistors. Mark uninitialized ones and assign them
|
||||
A direction. Keep track of the number of resistors pointing in
|
||||
each direction.
|
||||
* Walk though resistors. Mark uninitialized ones and assign them
|
||||
* a direction. Keep track of the number of resistors pointing in
|
||||
* each direction.
|
||||
*/
|
||||
for (resisptr = node->rn_re; resisptr != NULL; resisptr = resisptr->re_nextEl)
|
||||
{
|
||||
|
|
@ -103,65 +100,64 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
|||
(resisptr->re_thisEl->rr_connection2 == node))
|
||||
{
|
||||
if (resistor1 == NULL)
|
||||
{
|
||||
resistor1 = resisptr->re_thisEl;
|
||||
}
|
||||
else
|
||||
{
|
||||
resistor2 = resisptr->re_thisEl;
|
||||
}
|
||||
|
||||
numdrive++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Resistor direction is from node1 to node2. If the resistor
|
||||
is not marked, mark it and make sure the direction is
|
||||
set properly.
|
||||
* Resistor direction is from node1 to node2. If the resistor
|
||||
* is not marked, mark it and make sure the direction is
|
||||
* set properly.
|
||||
*/
|
||||
|
||||
if ((resisptr->re_thisEl->rr_status & RES_MARKED) != RES_MARKED)
|
||||
{
|
||||
if (resisptr->re_thisEl->rr_connection2 == node)
|
||||
{
|
||||
resisptr->re_thisEl->rr_connection2 = resisptr->re_thisEl->rr_connection1;
|
||||
resisptr->re_thisEl->rr_connection2 =
|
||||
resisptr->re_thisEl->rr_connection1;
|
||||
resisptr->re_thisEl->rr_connection1 = node;
|
||||
}
|
||||
resisptr->re_thisEl->rr_status |= RES_MARKED;
|
||||
}
|
||||
if (resistor1 == NULL)
|
||||
{
|
||||
resistor1 = resisptr->re_thisEl;
|
||||
}
|
||||
else
|
||||
{
|
||||
resistor2 = resisptr->re_thisEl;
|
||||
}
|
||||
|
||||
numreceive++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Is the node reached by one resistor? If it is, check the resistor's
|
||||
other end. Check the number of drivers at the other end. If it is
|
||||
more than 1, delete the current resistor to break the deadlock.
|
||||
* Is the node reached by one resistor? If it is, check the resistor's
|
||||
* other end. Check the number of drivers at the other end. If it is
|
||||
* more than 1, delete the current resistor to break the deadlock.
|
||||
*/
|
||||
|
||||
if (numreceive == 0 && numdrive == 1 && node->rn_why != RES_NODE_ORIGIN)
|
||||
{
|
||||
resistor1->rr_status |= RES_DEADEND;
|
||||
if (resistor1->rr_value < tolerance)
|
||||
{
|
||||
otherNode = (resistor1->rr_connection1 == node) ? resistor1->rr_connection2 : resistor1->rr_connection1;
|
||||
otherNode = (resistor1->rr_connection1 == node) ?
|
||||
resistor1->rr_connection2 : resistor1->rr_connection1;
|
||||
MarkedReceivers = 0;
|
||||
UnMarkedReceivers = 0;
|
||||
NumberOfDrivers = 0;
|
||||
PendingReceivers = 0;
|
||||
resistor2 = resistor1;
|
||||
for (resisptr = otherNode->rn_re; resisptr != NULL; resisptr=resisptr->re_nextEl)
|
||||
for (resisptr = otherNode->rn_re; resisptr != NULL;
|
||||
resisptr = resisptr->re_nextEl)
|
||||
{
|
||||
if (resisptr->re_thisEl->rr_connection1 == otherNode)
|
||||
{
|
||||
if ((resisptr->re_thisEl->rr_connection2->rn_status & MARKED) != MARKED)
|
||||
if ((resisptr->re_thisEl->rr_connection2->rn_status & MARKED)
|
||||
!= MARKED)
|
||||
{
|
||||
PendingReceivers++;
|
||||
}
|
||||
|
|
@ -169,23 +165,21 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
|||
resisptr->re_thisEl->rr_value > tolerance)
|
||||
{
|
||||
MarkedReceivers++;
|
||||
resistor2 = (resisptr->re_thisEl->rr_value >= resistor2->rr_value) ? resisptr->re_thisEl : resistor2;
|
||||
resistor2 = (resisptr->re_thisEl->rr_value >=
|
||||
resistor2->rr_value) ? resisptr->re_thisEl : resistor2;
|
||||
}
|
||||
else
|
||||
{
|
||||
UnMarkedReceivers++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NumberOfDrivers++;
|
||||
}
|
||||
}
|
||||
/* other recievers at far end? If so, reschedule other node;
|
||||
deadlock will be settled from that node.
|
||||
* deadlock will be settled from that node.
|
||||
*/
|
||||
if ((MarkedReceivers+UnMarkedReceivers+NumberOfDrivers == 2) ||
|
||||
(UnMarkedReceivers == 0 && MarkedReceivers > 1 && resistor2 == resistor1 && PendingReceivers == 0))
|
||||
(UnMarkedReceivers == 0 && MarkedReceivers > 1 &&
|
||||
resistor2 == resistor1 && PendingReceivers == 0))
|
||||
{
|
||||
if (otherNode->rn_status & MARKED)
|
||||
{
|
||||
|
|
@ -194,19 +188,19 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
|||
otherNode->rn_less = NULL;
|
||||
otherNode->rn_more = *nodelist;
|
||||
if (*nodelist != NULL)
|
||||
{
|
||||
(*nodelist)->rn_less = otherNode;
|
||||
}
|
||||
|
||||
*nodelist = otherNode;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Break loop here. More than one driver indicates a loop;
|
||||
remove deadend, allowing drivers to be merged
|
||||
* Break loop here. More than one driver indicates a loop;
|
||||
* remove deadend, allowing drivers to be merged
|
||||
*/
|
||||
else if (UnMarkedReceivers == 0 && (MarkedReceivers == 1 && NumberOfDrivers > 1 || resistor2 != resistor1))
|
||||
else if (UnMarkedReceivers == 0 && (MarkedReceivers == 1 &&
|
||||
NumberOfDrivers > 1 || resistor2 != resistor1))
|
||||
|
||||
{
|
||||
otherNode->rn_float.rn_area += resistor1->rr_float.rr_area;
|
||||
|
|
@ -222,77 +216,73 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
|||
otherNode->rn_less= NULL;
|
||||
otherNode->rn_more = *nodelist;
|
||||
if (*nodelist != NULL)
|
||||
{
|
||||
(*nodelist)->rn_less = otherNode;
|
||||
}
|
||||
|
||||
*nodelist = otherNode;
|
||||
}
|
||||
ResDoneWithNode(otherNode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
Two resistors in series? Combine them and move devices to
|
||||
appropriate end.
|
||||
* Two resistors in series? Combine them and move devices to
|
||||
* appropriate end.
|
||||
*/
|
||||
else if (numdrive+numreceive == 2 &&
|
||||
(resistor1->rr_value < tolerance && resistor2->rr_value < tolerance))
|
||||
else if (numdrive+numreceive == 2 && (resistor1->rr_value < tolerance &&
|
||||
resistor2->rr_value < tolerance))
|
||||
{
|
||||
if ((resistor1->rr_status & RES_MARKED) == 0 && (resistor1->rr_connection2 == node))
|
||||
if ((resistor1->rr_status & RES_MARKED) == 0 &&
|
||||
(resistor1->rr_connection2 == node))
|
||||
{
|
||||
resistor1->rr_connection2 = resistor1->rr_connection1;
|
||||
resistor1->rr_connection1 = node;
|
||||
}
|
||||
resistor1->rr_status |= RES_MARKED;
|
||||
if ((resistor2->rr_status & RES_MARKED) == 0 && (resistor2->rr_connection2 == node))
|
||||
if ((resistor2->rr_status & RES_MARKED) == 0 &&
|
||||
(resistor2->rr_connection2 == node))
|
||||
{
|
||||
resistor2->rr_connection2 = resistor2->rr_connection1;
|
||||
resistor2->rr_connection1 = node;
|
||||
}
|
||||
resistor2->rr_status |= RES_MARKED;
|
||||
node1 = (resistor1->rr_connection1 == node) ? resistor1->rr_connection2 : resistor1->rr_connection1;
|
||||
node2 = (resistor2->rr_connection1 == node) ? resistor2->rr_connection2 : resistor2->rr_connection1;
|
||||
node1 = (resistor1->rr_connection1 == node) ? resistor1->rr_connection2 :
|
||||
resistor1->rr_connection1;
|
||||
node2 = (resistor2->rr_connection1 == node) ? resistor2->rr_connection2 :
|
||||
resistor2->rr_connection1;
|
||||
otherNode = (resistor1->rr_status & RES_DEADEND &&
|
||||
resistor1->rr_value < tolerance / 2) ||
|
||||
((resistor2->rr_status & RES_DEADEND) == 0 &&
|
||||
resistor1->rr_value < resistor2->rr_value) ? node1 : node2;
|
||||
|
||||
/*
|
||||
make one big resistor out of two little ones, eliminating
|
||||
the current node. Devices connected to this node are
|
||||
moved to either end depending on their resistance.
|
||||
* Make one big resistor out of two little ones, eliminating
|
||||
* the current node. Devices connected to this node are
|
||||
* moved to either end depending on their resistance.
|
||||
*/
|
||||
ResMoveDevices(node,otherNode);
|
||||
otherNode->rn_noderes = MIN(node->rn_noderes, otherNode->rn_noderes);
|
||||
node2->rn_float.rn_area += resistor1->rr_value*node->rn_float.rn_area/(resistor1->rr_value+resistor2->rr_value);
|
||||
node1->rn_float.rn_area += resistor2->rr_value*node->rn_float.rn_area/(resistor1->rr_value+resistor2->rr_value);
|
||||
node2->rn_float.rn_area += resistor1->rr_value * node->rn_float.rn_area /
|
||||
(resistor1->rr_value + resistor2->rr_value);
|
||||
node1->rn_float.rn_area += resistor2->rr_value * node->rn_float.rn_area /
|
||||
(resistor1->rr_value + resistor2->rr_value);
|
||||
resistor1->rr_value += resistor2->rr_value;
|
||||
resistor1->rr_float.rr_area +=resistor2->rr_float.rr_area;
|
||||
if (resistor1 == *reslist)
|
||||
{
|
||||
*reslist = resistor1->rr_nextResistor;
|
||||
}
|
||||
else
|
||||
{
|
||||
resistor1->rr_lastResistor->rr_nextResistor = resistor1->rr_nextResistor;
|
||||
}
|
||||
|
||||
if (resistor1->rr_nextResistor != NULL)
|
||||
{
|
||||
resistor1->rr_nextResistor->rr_lastResistor = resistor1->rr_lastResistor;
|
||||
}
|
||||
|
||||
ResAddResistorToList(resistor1, reslist);
|
||||
ResDeleteResPointer(node, resistor1);
|
||||
ResDeleteResPointer(node, resistor2);
|
||||
ResDeleteResPointer(node2, resistor2);
|
||||
if (resistor1->rr_connection1 == node)
|
||||
{
|
||||
resistor1->rr_connection1 = node2;
|
||||
}
|
||||
else
|
||||
{
|
||||
resistor1->rr_connection2 = node2;
|
||||
}
|
||||
|
||||
resisptr = (resElement *)mallocMagic((unsigned)(sizeof(resElement)));
|
||||
resisptr->re_thisEl = resistor1;
|
||||
resisptr->re_nextEl = node2->rn_re;
|
||||
|
|
@ -308,9 +298,7 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
|||
node1->rn_less = NULL;
|
||||
node1->rn_more = *nodelist;
|
||||
if (*nodelist != NULL)
|
||||
{
|
||||
(*nodelist)->rn_less = node1;
|
||||
}
|
||||
*nodelist = node1;
|
||||
}
|
||||
node2->rn_status &= ~RES_DONE_ONCE;
|
||||
|
|
@ -321,18 +309,16 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
|||
node2->rn_less = NULL;
|
||||
node2->rn_more = *nodelist;
|
||||
if (*nodelist != NULL)
|
||||
{
|
||||
(*nodelist)->rn_less = node2;
|
||||
}
|
||||
*nodelist = node2;
|
||||
}
|
||||
ResDoneWithNode(node1);
|
||||
}
|
||||
|
||||
/*
|
||||
Last resort- keep propagating down the tree. To avoid looping,
|
||||
mark each node when it is reached. Don't reschedule node if
|
||||
none of the connections to it have changed since it was marked
|
||||
* Last resort- keep propagating down the tree. To avoid looping,
|
||||
* mark each node when it is reached. Don't reschedule node if
|
||||
* none of the connections to it have changed since it was marked
|
||||
*/
|
||||
else if (numreceive > 0 && (node->rn_status & RES_DONE_ONCE) == 0)
|
||||
{
|
||||
|
|
@ -342,32 +328,29 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
|||
if (resisptr->re_thisEl->rr_connection1 == node)
|
||||
{
|
||||
/*
|
||||
elements with a resistance greater than the
|
||||
tolerance should only be propagated past once-
|
||||
loops may occur otherwise.
|
||||
* Elements with a resistance greater than the
|
||||
* tolerance should only be propagated past once-
|
||||
* loops may occur otherwise.
|
||||
*/
|
||||
if (resisptr->re_thisEl->rr_status & RES_DONE_ONCE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (resisptr->re_thisEl->rr_connection2->rn_status & MARKED)
|
||||
{
|
||||
/*
|
||||
mark big resistors so we only process them
|
||||
once.
|
||||
* Mark big resistors so we only process them
|
||||
* once.
|
||||
*/
|
||||
if (resisptr->re_thisEl->rr_value > tolerance)
|
||||
{
|
||||
resisptr->re_thisEl->rr_status |= RES_DONE_ONCE;
|
||||
}
|
||||
|
||||
resisptr->re_thisEl->rr_connection2->rn_status &= ~MARKED;
|
||||
ResRemoveFromQueue(resisptr->re_thisEl->rr_connection2, biglist);
|
||||
resisptr->re_thisEl->rr_connection2->rn_less= NULL;
|
||||
resisptr->re_thisEl->rr_connection2->rn_more = *nodelist;
|
||||
if (*nodelist != NULL)
|
||||
{
|
||||
(*nodelist)->rn_less = resisptr->re_thisEl->rr_connection2;
|
||||
}
|
||||
|
||||
*nodelist = resisptr->re_thisEl->rr_connection2;
|
||||
}
|
||||
}
|
||||
|
|
@ -375,8 +358,6 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -406,32 +387,21 @@ ResMoveDevices(node1,node2)
|
|||
if (device->rd_status & RES_DEV_PLUG)
|
||||
{
|
||||
if (((ResPlug *)(device))->rpl_node == node1)
|
||||
{
|
||||
((ResPlug *)(device))->rpl_node = node2;
|
||||
}
|
||||
else
|
||||
{
|
||||
TxError("Bad node connection in plug\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (device->rd_fet_gate == node1)
|
||||
{
|
||||
device->rd_fet_gate = node2;
|
||||
}
|
||||
else if (device->rd_fet_source == node1)
|
||||
{
|
||||
device->rd_fet_source = node2;
|
||||
}
|
||||
else if (device->rd_fet_drain == node1)
|
||||
{
|
||||
device->rd_fet_drain = node2;
|
||||
}
|
||||
else
|
||||
{
|
||||
TxError("Missing Device connection in squish routines at %d, %d\n",node1->rn_loc.p_x,node1->rn_loc.p_y);
|
||||
}
|
||||
TxError("Missing Device connection in squish routines"
|
||||
" at %d, %d\n", node1->rn_loc.p_x, node1->rn_loc.p_y);
|
||||
}
|
||||
oldptr->te_nextt = node2->rn_te;
|
||||
node2->rn_te = oldptr;
|
||||
|
|
@ -439,7 +409,6 @@ ResMoveDevices(node1,node2)
|
|||
node1->rn_te = NULL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -468,42 +437,37 @@ ResScrunchNet(reslist,pendingList,biglist,tolerance)
|
|||
resElement *rcell1;
|
||||
int c1, c2;
|
||||
|
||||
/* sort resistors by size */
|
||||
/* Sort resistors by size */
|
||||
current = *reslist;
|
||||
while (current != NULL)
|
||||
{
|
||||
working = current;
|
||||
current = current->rr_nextResistor;
|
||||
if (working == *reslist)
|
||||
{
|
||||
*reslist = current;
|
||||
}
|
||||
else
|
||||
{
|
||||
working->rr_lastResistor->rr_nextResistor = current;
|
||||
}
|
||||
|
||||
if (current != NULL)
|
||||
{
|
||||
current->rr_lastResistor = working->rr_lastResistor;
|
||||
}
|
||||
|
||||
ResAddResistorToList(working, &locallist);
|
||||
}
|
||||
|
||||
|
||||
*reslist = locallist;
|
||||
while (*reslist != NULL && (*reslist)->rr_value < tolerance)
|
||||
{
|
||||
current = *reslist;
|
||||
if (current->rr_nextResistor == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
working = NULL;
|
||||
c1 = 0;
|
||||
c2 = 0;
|
||||
|
||||
/* search for next smallest adjoining resistor */
|
||||
for (rcell1 = current->rr_connection1->rn_re; rcell1 != NULL; rcell1 = rcell1->re_nextEl)
|
||||
/* Search for next smallest adjoining resistor */
|
||||
for (rcell1 = current->rr_connection1->rn_re; rcell1 != NULL;
|
||||
rcell1 = rcell1->re_nextEl)
|
||||
{
|
||||
if (rcell1->re_thisEl != current)
|
||||
{
|
||||
|
|
@ -523,7 +487,8 @@ ResScrunchNet(reslist,pendingList,biglist,tolerance)
|
|||
}
|
||||
}
|
||||
}
|
||||
for (rcell1 = current->rr_connection2->rn_re; rcell1 != NULL; rcell1 = rcell1->re_nextEl)
|
||||
for (rcell1 = current->rr_connection2->rn_re; rcell1 != NULL;
|
||||
rcell1 = rcell1->re_nextEl)
|
||||
{
|
||||
if (rcell1->re_thisEl != current)
|
||||
{
|
||||
|
|
@ -544,9 +509,9 @@ ResScrunchNet(reslist,pendingList,biglist,tolerance)
|
|||
}
|
||||
}
|
||||
/*
|
||||
if the current resistor isn't a deadend, add its value and
|
||||
area to that of the next smallest one. If it is a deadend,
|
||||
simply add its area to its node.
|
||||
* If the current resistor isn't a deadend, add its value and
|
||||
* area to that of the next smallest one. If it is a deadend,
|
||||
* simply add its area to its node.
|
||||
*/
|
||||
if (c1 != 0 && c2 != 0)
|
||||
{
|
||||
|
|
@ -558,17 +523,17 @@ ResScrunchNet(reslist,pendingList,biglist,tolerance)
|
|||
node1->rn_float.rn_area += current->rr_float.rr_area;
|
||||
}
|
||||
/*
|
||||
Move everything from from one end of the ressistor to the
|
||||
other and eliminate the resistor.
|
||||
* Move everything from from one end of the ressistor to the
|
||||
* other and eliminate the resistor.
|
||||
*/
|
||||
node2 = (current->rr_connection1 == node1) ? current->rr_connection2 : current->rr_connection1;
|
||||
node2 = (current->rr_connection1 == node1) ? current->rr_connection2 :
|
||||
current->rr_connection1;
|
||||
ResDeleteResPointer(current->rr_connection1, current);
|
||||
ResDeleteResPointer(current->rr_connection2, current);
|
||||
working->rr_lastResistor->rr_nextResistor = working->rr_nextResistor;
|
||||
if (working->rr_nextResistor != NULL)
|
||||
{
|
||||
working->rr_nextResistor->rr_lastResistor = working->rr_lastResistor;
|
||||
}
|
||||
|
||||
ResEliminateResistor(current, reslist);
|
||||
ResAddResistorToList(working, reslist);
|
||||
if (node2->rn_why & RES_NODE_ORIGIN)
|
||||
|
|
@ -577,25 +542,20 @@ ResScrunchNet(reslist,pendingList,biglist,tolerance)
|
|||
node1 = node2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ResMergeNodes(node1,node2,pendingList,biglist);
|
||||
}
|
||||
|
||||
/*
|
||||
Try further simplification on net using ResDoneWithNode and
|
||||
ResSimplifyNet.
|
||||
* Try further simplification on net using ResDoneWithNode and
|
||||
* ResSimplifyNet.
|
||||
*/
|
||||
ResRemoveFromQueue(node1, biglist);
|
||||
ResAddToQueue(node1, pendingList);
|
||||
node1->rn_status &= ~(RES_DONE_ONCE | FINISHED);
|
||||
ResDoneWithNode(node1);
|
||||
while (*pendingList != NULL)
|
||||
{
|
||||
ResSimplifyNet(pendingList,biglist,reslist,tolerance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
|
|
@ -620,9 +580,7 @@ ResAddResistorToList(resistor,locallist)
|
|||
for (local = *locallist; local != NULL; local = local->rr_nextResistor)
|
||||
{
|
||||
if (local->rr_value >= resistor->rr_value)
|
||||
{
|
||||
break;
|
||||
}
|
||||
last = local;
|
||||
}
|
||||
if (local != NULL)
|
||||
|
|
@ -630,13 +588,10 @@ ResAddResistorToList(resistor,locallist)
|
|||
resistor->rr_nextResistor = local;
|
||||
resistor->rr_lastResistor = local->rr_lastResistor;
|
||||
if (local->rr_lastResistor == NULL)
|
||||
{
|
||||
*locallist = resistor;
|
||||
}
|
||||
else
|
||||
{
|
||||
local->rr_lastResistor->rr_nextResistor = resistor;
|
||||
}
|
||||
|
||||
local->rr_lastResistor = resistor;
|
||||
}
|
||||
else
|
||||
|
|
@ -656,7 +611,6 @@ ResAddResistorToList(resistor,locallist)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -685,13 +639,9 @@ ResDistributeCapacitance(nodelist,totalcap)
|
|||
for (workingNode = nodelist; workingNode != NULL; workingNode = workingNode->rn_more)
|
||||
{
|
||||
for (rptr = workingNode->rn_re; rptr != NULL; rptr=rptr->re_nextEl)
|
||||
{
|
||||
if (rptr->re_thisEl->rr_float.rr_area != 0.0)
|
||||
{
|
||||
TxError("Nonnull resistor area\n");
|
||||
}
|
||||
/* workingNode->rn_float.rn_area += rptr->re_thisEl->rr_float.rr_area/2; */
|
||||
}
|
||||
|
||||
totalarea += workingNode->rn_float.rn_area;
|
||||
}
|
||||
if (totalarea == 0)
|
||||
|
|
@ -700,12 +650,10 @@ ResDistributeCapacitance(nodelist,totalcap)
|
|||
return;
|
||||
}
|
||||
capperarea = FEMTOTOATTO * totalcap / totalarea;
|
||||
|
||||
for (workingNode = nodelist; workingNode != NULL; workingNode=workingNode->rn_more)
|
||||
{
|
||||
workingNode->rn_float.rn_area *= capperarea;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
|
|
@ -734,17 +682,16 @@ ResCalculateChildCapacitance(me)
|
|||
int t;
|
||||
ExtDevice *devptr;
|
||||
|
||||
|
||||
if (me->rn_client != (ClientData) NULL) /* we have a loop */
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
|
||||
myC = (RCDelayStuff *) mallocMagic((unsigned) (sizeof(RCDelayStuff)));
|
||||
me->rn_client = (ClientData) myC;
|
||||
|
||||
/* This following assumes that ResDistributeCapacitance has been run */
|
||||
/* and the the resulting capacitance value is stored in the area field */
|
||||
myC->rc_Cdownstream = me->rn_float.rn_area;
|
||||
myC->rc_Tdi = 0.0;
|
||||
|
||||
/* get capacitance for all connected gates */
|
||||
for (tptr = me->rn_te; tptr != NULL; tptr = tptr->te_nextt)
|
||||
|
|
@ -763,9 +710,7 @@ ResCalculateChildCapacitance(me)
|
|||
if (dev->rd_fet_gate == me)
|
||||
{
|
||||
devptr = ExtCurStyle->exts_device[t];
|
||||
myC->rc_Cdownstream +=
|
||||
dev->rd_length*
|
||||
dev->rd_width*
|
||||
myC->rc_Cdownstream += dev->rd_length * dev->rd_width *
|
||||
devptr->exts_deviceGateCap +
|
||||
(dev->rd_width + dev->rd_width) *
|
||||
devptr->exts_deviceSDCap;
|
||||
|
|
@ -781,16 +726,14 @@ ResCalculateChildCapacitance(me)
|
|||
{
|
||||
childcap = ResCalculateChildCapacitance(workingRes->re_thisEl->rr_connection2);
|
||||
if (childcap == -1)
|
||||
{
|
||||
return(-1);
|
||||
}
|
||||
|
||||
myC->rc_Cdownstream += childcap;
|
||||
}
|
||||
}
|
||||
return (myC->rc_Cdownstream);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -817,29 +760,24 @@ ResCalculateTDi(node,resistor,resistorvalue)
|
|||
|
||||
ASSERT(rcd != NULL, "ResCalculateTdi");
|
||||
if (resistor == NULL)
|
||||
{
|
||||
rcd->rc_Tdi = rcd->rc_Cdownstream*(float)resistorvalue;
|
||||
}
|
||||
else
|
||||
{
|
||||
rcd2 = (RCDelayStuff *)resistor->rr_connection1->rn_client;
|
||||
ASSERT(rcd2 != NULL,"ResCalculateTdi");
|
||||
rcd->rc_Tdi = rcd->rc_Cdownstream * (float)resistor->rr_value +
|
||||
rcd2->rc_Tdi;
|
||||
|
||||
}
|
||||
|
||||
for (workingRes = node->rn_re; workingRes != NULL; workingRes = workingRes->re_nextEl)
|
||||
{
|
||||
if (workingRes->re_thisEl->rr_connection1 == node &&
|
||||
(workingRes->re_thisEl->rr_status & RES_TDI_IGNORE) == 0)
|
||||
{
|
||||
ResCalculateTDi(workingRes->re_thisEl->rr_connection2,
|
||||
workingRes->re_thisEl,
|
||||
workingRes->re_thisEl->rr_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
|
|
@ -872,16 +810,18 @@ ResPruneTree(node,minTdi,nodelist1,nodelist2,resistorlist)
|
|||
current = current->re_nextEl;
|
||||
/* if branch points outward, call routine on subtrees */
|
||||
if (currentRes->rr_connection1 == node)
|
||||
{
|
||||
ResPruneTree(currentRes->rr_connection2, minTdi,nodelist1,nodelist2,resistorlist);
|
||||
ResPruneTree(currentRes->rr_connection2, minTdi, nodelist1,
|
||||
nodelist2, resistorlist);
|
||||
}
|
||||
}
|
||||
/* We eliminate this branch if */
|
||||
/* 1. It is a terminal node, i.e. it is the connected */
|
||||
/* to only one resistor. */
|
||||
/* 2. The direction of this resistor is toward the node */
|
||||
/* (This prevents the root from being eliminated */
|
||||
/* 3. The time constant TDI is less than the tolerance. */
|
||||
|
||||
/* We eliminate this branch if:
|
||||
* 1. It is a terminal node, i.e. it is the connected
|
||||
* to only one resistor.
|
||||
* 2. The direction of this resistor is toward the node
|
||||
* (This prevents the root from being eliminated
|
||||
* 3. The time constant TDI is less than the tolerance.
|
||||
*/
|
||||
|
||||
if (node->rn_re != NULL &&
|
||||
node->rn_re->re_nextEl == NULL &&
|
||||
node->rn_re->re_thisEl->rr_connection2 == node)
|
||||
|
|
@ -895,12 +835,19 @@ ResPruneTree(node,minTdi,nodelist1,nodelist2,resistorlist)
|
|||
currentRes = node->rn_re->re_thisEl;
|
||||
ResDeleteResPointer(currentRes->rr_connection1, currentRes);
|
||||
ResDeleteResPointer(currentRes->rr_connection2, currentRes);
|
||||
ResMergeNodes(currentRes->rr_connection1,currentRes->rr_connection2,nodelist2,nodelist1); /* Patched 7/5/94 */
|
||||
ResMergeNodes(currentRes->rr_connection1, currentRes->rr_connection2,
|
||||
nodelist2, nodelist1);
|
||||
ResEliminateResistor(currentRes, resistorlist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
ResDoSimplify(tolerance, rctol, goodies)
|
||||
float tolerance;
|
||||
|
|
@ -914,13 +861,10 @@ ResDoSimplify(tolerance,rctol,goodies)
|
|||
float totalcap;
|
||||
resResistor *res;
|
||||
|
||||
|
||||
resRemoveLoops = FALSE;
|
||||
ResSetPathRes();
|
||||
for (node = ResNodeList; node != NULL; node = node->rn_more)
|
||||
{
|
||||
bigres = MAX(bigres,node->rn_noderes);
|
||||
}
|
||||
|
||||
bigres /= OHMSTOMILLIOHMS; /* convert from milliohms to ohms */
|
||||
goodies->rg_maxres = bigres;
|
||||
|
|
@ -936,11 +880,10 @@ ResDoSimplify(tolerance,rctol,goodies)
|
|||
|
||||
(void) ResDistributeCapacitance(ResNodeList,goodies->rg_nodecap);
|
||||
|
||||
if ((tolerance > bigres || (ResOptionsFlags &ResOpt_Simplify)==0) &&
|
||||
(ResOptionsFlags &ResOpt_DoLumpFile)==0)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
if (((tolerance > bigres) || ((ResOptionsFlags & ResOpt_Simplify) == 0)) &&
|
||||
((ResOptionsFlags & ResOpt_DoLumpFile) == 0))
|
||||
return 0;
|
||||
|
||||
res = ResResList;
|
||||
while (res)
|
||||
{
|
||||
|
|
@ -975,7 +918,7 @@ ResDoSimplify(tolerance,rctol,goodies)
|
|||
for (node = ResNodeList; node != NULL; node = node->rn_more)
|
||||
{
|
||||
rc = (RCDelayStuff *)node->rn_client;
|
||||
if (rc && (goodies->rg_Tdi < rc->rc_Tdi))
|
||||
if ((rc != NULL) && (goodies->rg_Tdi < rc->rc_Tdi))
|
||||
{
|
||||
slownode = node;
|
||||
goodies->rg_Tdi = rc->rc_Tdi;
|
||||
|
|
@ -984,93 +927,85 @@ ResDoSimplify(tolerance,rctol,goodies)
|
|||
slownode->rn_status |= RN_MAXTDI;
|
||||
}
|
||||
else
|
||||
{
|
||||
goodies->rg_Tdi = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goodies->rg_Tdi = 0;
|
||||
}
|
||||
|
||||
if ((rctol+1) * goodies->rg_bigdevres * goodies->rg_nodecap >
|
||||
rctol * goodies->rg_Tdi &&
|
||||
(ResOptionsFlags & ResOpt_Tdi) &&
|
||||
goodies->rg_Tdi != -1)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
||||
/* Simplify network; resistors are still in milliohms, so use
|
||||
millitolerance.
|
||||
* millitolerance.
|
||||
*/
|
||||
|
||||
if (ResOptionsFlags & ResOpt_Simplify)
|
||||
{
|
||||
|
||||
millitolerance = tolerance * MILLIOHMSPEROHM;
|
||||
|
||||
/*
|
||||
Start simplification at driver (R=0). Remove it from the done list
|
||||
and add it to the pending list. Call ResSimplifyNet as long as nodes
|
||||
remain in the pending list.
|
||||
* Start simplification at driver (R=0). Remove it from the done list
|
||||
* and add it to the pending list. Call ResSimplifyNet as long as
|
||||
* nodes remain in the pending list.
|
||||
*/
|
||||
for (node = ResNodeList; node != NULL; node = node->rn_more)
|
||||
{
|
||||
if (node->rn_noderes == 0)
|
||||
{
|
||||
ResOriginNode = node;
|
||||
}
|
||||
|
||||
node->rn_status |= FINISHED;
|
||||
}
|
||||
if (ResOriginNode != NULL)
|
||||
{
|
||||
|
||||
/* if Tdi is enabled, prune all branches whose end nodes have */
|
||||
/* time constants less than the tolerance. */
|
||||
/* if Tdi is enabled, prune all branches whose end nodes */
|
||||
/* have time constants less than the tolerance. */
|
||||
|
||||
if ((ResOptionsFlags & ResOpt_Tdi) &&
|
||||
goodies->rg_Tdi != -1 &&
|
||||
rctol != 0)
|
||||
{
|
||||
ResPruneTree(ResOriginNode,
|
||||
(rctol+1)*goodies->rg_bigdevres*goodies->rg_nodecap/rctol,
|
||||
ResPruneTree(ResOriginNode, (rctol + 1) *
|
||||
goodies->rg_bigdevres * goodies->rg_nodecap / rctol,
|
||||
&ResNodeList, &ResNodeQueue, &ResResList);
|
||||
}
|
||||
ResOriginNode->rn_status &= ~MARKED;
|
||||
if (ResOriginNode->rn_less == NULL)
|
||||
{
|
||||
ResNodeList = ResOriginNode->rn_more;
|
||||
}
|
||||
else
|
||||
{
|
||||
ResOriginNode->rn_less->rn_more = ResOriginNode->rn_more;
|
||||
}
|
||||
|
||||
if (ResOriginNode->rn_more != NULL)
|
||||
{
|
||||
ResOriginNode->rn_more->rn_less = ResOriginNode->rn_less;
|
||||
}
|
||||
|
||||
ResOriginNode->rn_more = NULL;
|
||||
ResOriginNode->rn_less = NULL;
|
||||
ResNodeQueue = ResOriginNode;
|
||||
while (ResNodeQueue != NULL)
|
||||
{
|
||||
ResSimplifyNet(&ResNodeQueue,&ResNodeList,&ResResList,millitolerance);
|
||||
}
|
||||
|
||||
/*
|
||||
Call ResScrunchNet to eliminate any remaining under tolerance
|
||||
resistors.
|
||||
* Call ResScrunchNet to eliminate any remaining under tolerance
|
||||
* resistors.
|
||||
*/
|
||||
ResScrunchNet(&ResResList,&ResNodeQueue,&ResNodeList,millitolerance);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
ResSetPathRes()
|
||||
|
||||
{
|
||||
HeapEntry he;
|
||||
resNode *node;
|
||||
|
|
@ -1105,10 +1040,14 @@ ResSetPathRes()
|
|||
ASSERT(ResOriginNode != NULL, "ResDoSimplify");
|
||||
resPathNode(ResOriginNode);
|
||||
while (HeapRemoveTop(&ResistorHeap,&he))
|
||||
{
|
||||
resPathRes((resResistor *)he.he_id);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
resPathNode(node)
|
||||
|
|
@ -1126,12 +1065,16 @@ resPathNode(node)
|
|||
if (res->rr_status & RES_HEAP) continue;
|
||||
if ((node2 = res->rr_node[0]) == node) node2 = res->rr_node[1];
|
||||
if ((node2->rn_status & FINISHED) == 0)
|
||||
{
|
||||
HeapAddInt(&ResistorHeap, node->rn_noderes + res->rr_value,
|
||||
(char *)res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
resPathRes(res)
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ ResEach(tile, pNum, arg)
|
|||
|
||||
if (((ResContactPoint *)(arg->fra_region))->cp_contactTile != tile)
|
||||
{
|
||||
(void) ResFirst(tile, arg);
|
||||
ResFirst(tile, arg);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
|
@ -137,7 +137,6 @@ int
|
|||
ResAddPlumbing(tile, arg)
|
||||
Tile *tile;
|
||||
ClientData *arg;
|
||||
|
||||
{
|
||||
tileJunk *Junk, *junk2;
|
||||
static Stack *resDevStack = NULL;
|
||||
|
|
@ -201,13 +200,15 @@ ResAddPlumbing(tile, arg)
|
|||
junk2->deviceList = resDev;
|
||||
junk2->tj_status |= RES_TILE_DEV;
|
||||
|
||||
for (i = 0; i < nterms - 2; i++)
|
||||
{
|
||||
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[0]),
|
||||
if TTMaskHasType(&(devptr->exts_deviceSDTypes[i]),
|
||||
TiGetBottomType(tp2))
|
||||
{
|
||||
junk2->sourceEdge |= TOPEDGE;
|
||||
|
|
@ -222,7 +223,7 @@ ResAddPlumbing(tile, arg)
|
|||
if (source == NULL)
|
||||
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))
|
||||
{
|
||||
junk2->sourceEdge |= BOTTOMEDGE;
|
||||
|
|
@ -237,7 +238,7 @@ ResAddPlumbing(tile, arg)
|
|||
if (source == NULL)
|
||||
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))
|
||||
{
|
||||
junk2->sourceEdge |= RIGHTEDGE;
|
||||
|
|
@ -252,7 +253,7 @@ ResAddPlumbing(tile, arg)
|
|||
if (source == NULL)
|
||||
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))
|
||||
{
|
||||
source = tp2;
|
||||
|
|
@ -262,6 +263,15 @@ ResAddPlumbing(tile, arg)
|
|||
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
|
||||
* the source or to the drain of a device. A single
|
||||
|
|
@ -273,7 +283,8 @@ ResAddPlumbing(tile, arg)
|
|||
|
||||
if (source != (Tile *) NULL)
|
||||
{
|
||||
STACKPUSH((ClientData) (source),resDevStack);
|
||||
STACKPUSH((ClientData)source, resDevStack);
|
||||
}
|
||||
}
|
||||
while (!StackEmpty(resDevStack))
|
||||
{
|
||||
|
|
@ -308,7 +319,7 @@ ResAddPlumbing(tile, arg)
|
|||
if ((j->tj_status & RES_TILE_SD) == 0)
|
||||
{
|
||||
j->tj_status |= RES_TILE_SD;
|
||||
STACKPUSH((ClientData) (tp2),resDevStack);
|
||||
STACKPUSH((ClientData)tp2, resDevStack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -321,7 +332,7 @@ ResAddPlumbing(tile, arg)
|
|||
if ((j->tj_status & RES_TILE_SD) == 0)
|
||||
{
|
||||
j->tj_status |= RES_TILE_SD;
|
||||
STACKPUSH((ClientData) (tp2),resDevStack);
|
||||
STACKPUSH((ClientData)tp2, resDevStack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -334,7 +345,7 @@ ResAddPlumbing(tile, arg)
|
|||
if ((j->tj_status & RES_TILE_SD) == 0)
|
||||
{
|
||||
j->tj_status |= RES_TILE_SD;
|
||||
STACKPUSH((ClientData) (tp2),resDevStack);
|
||||
STACKPUSH((ClientData)tp2, resDevStack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -342,7 +353,7 @@ ResAddPlumbing(tile, arg)
|
|||
|
||||
/* find rest of device; search for source edges */
|
||||
|
||||
STACKPUSH((ClientData) (tile), resDevStack);
|
||||
STACKPUSH((ClientData)tile, resDevStack);
|
||||
while (!StackEmpty(resDevStack))
|
||||
{
|
||||
tileJunk *j0;
|
||||
|
|
@ -365,7 +376,7 @@ ResAddPlumbing(tile, arg)
|
|||
(tp2->ti_client == (ClientData) CLIENTDEFAULT))
|
||||
{
|
||||
Junk = resAddField(tp2);
|
||||
STACKPUSH((ClientData)(tp2),resDevStack);
|
||||
STACKPUSH((ClientData)tp2, resDevStack);
|
||||
Junk->deviceList = resDev;
|
||||
Junk->tj_status |= RES_TILE_DEV;
|
||||
|
||||
|
|
@ -385,7 +396,7 @@ ResAddPlumbing(tile, arg)
|
|||
(tp2->ti_client == (ClientData) CLIENTDEFAULT))
|
||||
{
|
||||
Junk = resAddField(tp2);
|
||||
STACKPUSH((ClientData)(tp2),resDevStack);
|
||||
STACKPUSH((ClientData)tp2, resDevStack);
|
||||
Junk->deviceList = resDev;
|
||||
Junk->tj_status |= RES_TILE_DEV;
|
||||
}
|
||||
|
|
@ -404,7 +415,7 @@ ResAddPlumbing(tile, arg)
|
|||
(tp2->ti_client == (ClientData) CLIENTDEFAULT))
|
||||
{
|
||||
Junk = resAddField(tp2);
|
||||
STACKPUSH((ClientData)(tp2),resDevStack);
|
||||
STACKPUSH((ClientData)tp2, resDevStack);
|
||||
Junk->deviceList = resDev;
|
||||
Junk->tj_status |= RES_TILE_DEV;
|
||||
}
|
||||
|
|
@ -423,7 +434,7 @@ ResAddPlumbing(tile, arg)
|
|||
(tp2->ti_client == (ClientData) CLIENTDEFAULT))
|
||||
{
|
||||
Junk = resAddField(tp2);
|
||||
STACKPUSH((ClientData)(tp2),resDevStack);
|
||||
STACKPUSH((ClientData)tp2, resDevStack);
|
||||
Junk->deviceList = resDev;
|
||||
Junk->tj_status |= RES_TILE_DEV;
|
||||
}
|
||||
|
|
@ -443,7 +454,7 @@ ResAddPlumbing(tile, arg)
|
|||
{
|
||||
tileJunk *j = (tileJunk *) source->ti_client;
|
||||
|
||||
STACKPUSH((ClientData) (source),resDevStack);
|
||||
STACKPUSH((ClientData)source, resDevStack);
|
||||
j->tj_status &= ~RES_TILE_SD;
|
||||
}
|
||||
while (!StackEmpty(resDevStack))
|
||||
|
|
@ -546,7 +557,7 @@ ResRemovePlumbing(tile, arg)
|
|||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
|
|
@ -604,8 +615,9 @@ ResPreProcessDevices(TileList, DeviceList, Def)
|
|||
tt = TiGetType(tile);
|
||||
tstruct = (tileJunk *) tile->ti_client;
|
||||
|
||||
if (!TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt) ||
|
||||
tstruct->deviceList == NULL)
|
||||
if ((tstruct == (tileJunk *)CLIENTDEFAULT) ||
|
||||
(tstruct->deviceList == NULL) ||
|
||||
!TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt))
|
||||
{
|
||||
TxError("Bad Device Location at %d,%d\n",
|
||||
TileList->area.r_ll.p_x,
|
||||
|
|
@ -666,18 +678,17 @@ ResPreProcessDevices(TileList, DeviceList, Def)
|
|||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
ResAddToQueue(node, list)
|
||||
resNode *node, **list;
|
||||
{
|
||||
|
||||
node->rn_more = *list;
|
||||
node->rn_less = NULL;
|
||||
if (*list) (*list)->rn_less = node;
|
||||
*list = node;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -694,9 +705,7 @@ ResAddToQueue(node,list)
|
|||
void
|
||||
ResRemoveFromQueue(node, list)
|
||||
resNode *node, **list;
|
||||
|
||||
{
|
||||
|
||||
if (node->rn_less != NULL)
|
||||
{
|
||||
node->rn_less->rn_more = node->rn_more;
|
||||
|
|
@ -719,10 +728,10 @@ ResRemoveFromQueue(node,list)
|
|||
node->rn_more = NULL;
|
||||
node->rn_less = NULL;
|
||||
}
|
||||
|
||||
tileJunk *
|
||||
resAddField(tile)
|
||||
Tile *tile;
|
||||
|
||||
{
|
||||
tileJunk *Junk;
|
||||
if ((Junk = (tileJunk *)tile->ti_client) == (tileJunk *) CLIENTDEFAULT)
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ ResPrintNetwork(filename, reslist)
|
|||
|
||||
{
|
||||
char bigname[255], name1[255], name2[255];
|
||||
|
||||
FILE *fp;
|
||||
int i = 1;
|
||||
|
||||
|
|
@ -118,7 +117,6 @@ ResPrintCurrents(filename,extension,node)
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*-------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -151,7 +149,6 @@ resCurrentPrintFunc(node,resistor,filename)
|
|||
if (node->rn_why == RES_NODE_ORIGIN)
|
||||
{
|
||||
fprintf(filename, "i gnd %f\n", i_sum);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -159,7 +156,6 @@ resCurrentPrintFunc(node,resistor,filename)
|
|||
node->rn_loc.p_y, i_sum);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -218,9 +214,9 @@ ResWriteECLFile(filename,reslist,nodelist)
|
|||
}
|
||||
for (; reslist; reslist = reslist->rr_nextResistor)
|
||||
{
|
||||
|
||||
fprintf(fp, "r %s %s %f %s %d\n",
|
||||
reslist->rr_node[0]->rn_name,reslist->rr_node[1]->rn_name,
|
||||
reslist->rr_node[0]->rn_name,
|
||||
reslist->rr_node[1]->rn_name,
|
||||
/* /1000.0 gets ohms from milliohms */
|
||||
(float)(reslist->rr_value) / 1000.0,
|
||||
DBTypeShortName(reslist->rr_tt), reslist->rr_csArea);
|
||||
|
|
|
|||
|
|
@ -247,6 +247,7 @@ typedef struct resdevtile
|
|||
struct resdevtile *nextDev;
|
||||
Rect area;
|
||||
TileType type;
|
||||
ExtDevice *devptr;
|
||||
int perim;
|
||||
int overlap;
|
||||
} ResDevTile;
|
||||
|
|
@ -297,7 +298,8 @@ typedef struct rdev
|
|||
Point location; /* Location of lower left point 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_sattr;
|
||||
char *rs_dattr;
|
||||
|
|
@ -512,6 +514,7 @@ typedef struct capval
|
|||
#define RIGHTEDGE 4
|
||||
#define TOPEDGE 8
|
||||
#define BOTTOMEDGE 16
|
||||
#define OTHERPLANE 32
|
||||
|
||||
#define RN_MAXTDI 0x00001000
|
||||
|
||||
|
|
|
|||
|
|
@ -190,7 +190,8 @@ extern int GeoRectPointSide(Rect *, Point *);
|
|||
extern int GeoRectRectSide(Rect *, Rect *);
|
||||
extern void GeoIncludePoint(Point *, Rect *);
|
||||
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 */
|
||||
cmp = i;
|
||||
if (i & 1)
|
||||
if ((i & 1) && (i != 1))
|
||||
KEY_LE_COND(keyType, list, i, i-1, cmp = i-1);
|
||||
|
||||
/* Find parent. If 0 then at the root so quit */
|
||||
if ((i >>= 1) == 0) return;
|
||||
|
||||
KEY_LE_COND(keyType, list, cmp, i, return);
|
||||
list[0] = list[cmp]; list[cmp] = list[i]; list[i] = list[0];
|
||||
heapify(heap, cmp);
|
||||
|
|
@ -434,11 +435,12 @@ HeapAdd(heap, pKey, id)
|
|||
{
|
||||
/* If odd then new entry is the right half of a pair */
|
||||
cmp = i;
|
||||
if (i & 1)
|
||||
if ((i & 1) && (i != 1))
|
||||
KEY_GE_COND(keyType, list, i, i-1, cmp = i-1);
|
||||
|
||||
/* Find parent. If 0 then at the root so quit */
|
||||
if ((i >>= 1) == 0) return;
|
||||
|
||||
KEY_GE_COND(keyType, list, cmp, i, return);
|
||||
list[0] = list[cmp]; list[cmp] = list[i]; list[i] = list[0];
|
||||
heapify(heap, cmp);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ static __inline__ int IHashAlignedSize(int size)
|
|||
int result;
|
||||
/* Expand size to be double-word (64 bit) aligned */
|
||||
result = ((size + 7) / 8) * 8;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* The IHashTable struct should not be manipulated directly by clients */
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ TechSectionGetMask(sectionName, depend)
|
|||
{
|
||||
invid |= tsp->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;
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header$";
|
|||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h> /* for isalnum() */
|
||||
|
||||
#include "utils/magic.h"
|
||||
#include "utils/geometry.h"
|
||||
|
|
|
|||
Loading…
Reference in New Issue