Merge branch 'RTimothyEdwards:master' into spice_hier

This commit is contained in:
Dan Moore 2021-06-29 12:06:19 -07:00 committed by GitHub
commit f6b4671d96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 3944 additions and 4050 deletions

View File

@ -1 +1 @@
8.3.164
8.3.182

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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 */

View File

@ -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++)
{

View File

@ -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;
}

View File

@ -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,

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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();

View File

@ -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);
}

View File

@ -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.

View File

@ -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);

View File

@ -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 ||

View File

@ -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;

View File

@ -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;

View File

@ -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); \
}

View File

@ -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]);

View File

@ -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)

View File

@ -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 */

View File

@ -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

View File

@ -112,7 +112,7 @@ ExtCell(def, outName, doLength)
TxError("Cannot open output file: ");
perror(filename);
#endif
return;
return NULL;
}
extNumFatal = extNumWarnings = 0;

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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(&notConnectMask);
TTMaskSetMask(&notConnectMask, &DBNotConnectTbl[loctype]);
}
else
{
TTMaskCom2(&notConnectMask, connectMask);
}
def = csa2->csa2_use->cu_def;
if (DBSrPaintNMArea((Tile *) NULL, def->cd_planes[pNum],
dinfo, &newarea, &notConnectMask, 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 */

View File

@ -49,7 +49,6 @@ void
ResPrintNodeList(fp, list)
FILE *fp;
resNode *list;
{
for (; list != NULL; list = list->rn_more)

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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");
}
}
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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 *);
/*
*-------------------------------------------------------------------

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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"