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