Merge branch 'master' into bplane

Conflicts:
	VERSION
	database/DBcellsrch.c
	database/DBconnect.c
	extract/ExtInter.c
	lef/Depend
	utils/Depend

Updated bplane branch with all changes to master since the bplane branch
was last modified.
This commit is contained in:
Tim Edwards 2020-03-12 08:29:33 -04:00
commit cd87b08b21
144 changed files with 10590 additions and 8165 deletions

17
.gitignore vendored
View File

@ -10,5 +10,18 @@ scripts/defs.mak
*.so
*~
scmos/cif_template/objs/*
UPDATE_ME
VERSION
database/database.h
install.log
magic/proto.magicrc
make.log
readline/readline
scmos/gdsquery.tech
scmos/minimum.tech
scmos/scmos-sub.tech
scmos/scmos-tm.tech
scmos/scmos.tech
scmos/scmosWR.tech
tcltk/magic.sh
tcltk/magic.tcl
tcltk/magicdnull
tcltk/magicexec

View File

@ -7,6 +7,8 @@ Autoconf Capsule Summary:
make
make install
Note: Remember to use 'gmake' on FreeBSD.
Autoconf options (use "./configure --help" for a complete list):
--prefix=DIR Indicates the install directory. Determines the

10
LICENSE Normal file
View File

@ -0,0 +1,10 @@
Copyright (C) 1985, 1990 Regents of the University of California.
Permission to use, copy, modify, and distribute this
software and its documentation for any purpose and without
fee is hereby granted, provided that the above copyright
notice appear in all copies. The University of California
makes no representations about the suitability of this
software for any purpose. It is provided "as is" without
express or implied warranty. Export of this software outside
of the United States of America may require an export license.

View File

@ -13,7 +13,7 @@ MODULES = bplane cmwind commands database dbwind debug drc extflat \
MAKEFLAGS =
INSTALL_CAD_DIRS = windows doc ${TECH}
include defs.mak
-include defs.mak
all: $(ALL_TARGET)
@ -66,8 +66,8 @@ depend: database/database.h
install: $(INSTALL_TARGET)
install-magic:
@echo --- installing executable to $(DESTDIR)${BINDIR}
@echo --- installing runtime files to $(DESTDIR)${LIBDIR}
@echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR}
@echo --- installing runtime files to $(DESTDIR)${INSTALL_LIBDIR}
@${MAKE} install-real 2>&1 >> install.log
install-real: install-dirs
@ -77,16 +77,18 @@ install-real: install-dirs
(cd $$dir && ${MAKE} install); done
install-tcl-dirs:
${MAGICDIR}/scripts/mkdirs $(DESTDIR)${BINDIR} $(DESTDIR)${MANDIR} \
$(DESTDIR)${SYSDIR} $(DESTDIR)${TCLDIR} $(DESTDIR)${TCLDIR}/bitmaps
${MAGICDIR}/scripts/mkdirs $(DESTDIR)${INSTALL_BINDIR} \
$(DESTDIR)${INSTALL_MANDIR} $(DESTDIR)${INSTALL_SYSDIR} \
$(DESTDIR)${INSTALL_TCLDIR} $(DESTDIR)${INSTALL_TCLDIR}/bitmaps
install-dirs:
${MAGICDIR}/scripts/mkdirs $(DESTDIR)${BINDIR} $(DESTDIR)${MANDIR} \
$(DESTDIR)${SYSDIR} $(DESTDIR)${SCMDIR}
${MAGICDIR}/scripts/mkdirs $(DESTDIR)${INSTALL_BINDIR} \
$(DESTDIR)${INSTALL_MANDIR} $(DESTDIR)${INSTALL_SYSDIR} \
$(DESTDIR)${INSTALL_SCMDIR}
install-tcl:
@echo --- installing executable to $(DESTDIR)${BINDIR}
@echo --- installing runtime files to $(DESTDIR)${LIBDIR}
@echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR}
@echo --- installing runtime files to $(DESTDIR)${INSTALL_LIBDIR}
@${MAKE} install-tcl-real 2>&1 >> install.log
install-tcl-real: install-tcl-dirs

20
TODO
View File

@ -1,8 +1,16 @@
I. Bugs to fix (also in magic-7.5 [stable]):
I. Bugs to fix
1. The "extresist" code only recognizes original "fet" types, not
the new "device" types in the extract file.
1. The "extresist" code needs to extract substrate networks. Moreover,
the "extresist" code really needs to have the dependence on
ext2sim removed, and instead read directly from .ext files. The
.sim format has no substrate connections, so this cannot be properly
represented. Also, there is nothing that is read from the .sim file
that is not already present in the .ext file.
2. "plow" has been broken for some time. It should derive its rules
from the DRC decks (using the new routines that are meant for just
that sort of thing).
2. "plow" should derive its rules from the DRC decks (using the new
routines that are meant for just that sort of thing).
3. It is possible to trick the net selection into an infinite loop in
unusual geometry situations. That these situations would be DRC
errors does not excuse the infinite loop behavior. The geometry
required is unusual enough that this is not a high priority item.

View File

@ -1 +1 @@
8.4.0
8.3.0

View File

@ -282,7 +282,7 @@ calmaParseStructure(filename)
{
static int structs[] = { CALMA_STRCLASS, CALMA_STRTYPE, -1 };
int nbytes, rtype, nsrefs, osrefs, npaths;
char *strname = NULL, newname[CALMANAMELENGTH*2];
char *strname = NULL;
HashEntry *he;
int suffix;
int mfactor;
@ -327,15 +327,21 @@ calmaParseStructure(filename)
}
else
{
char *newname;
CalmaReadError("Cell \"%s\" was already defined in this file.\n",
strname);
newname = (char *)mallocMagic(strlen(strname) + 20);
for (suffix = 1; HashGetValue(he) != NULL; suffix++)
{
(void) sprintf(newname, "%s_%d", strname, suffix);
he = HashFind(&calmaDefInitHash, newname);
}
CalmaReadError("Giving this cell a new name: %s\n", newname);
strncpy(strname, newname, CALMANAMELENGTH*2);
freeMagic(strname);
strname = mallocMagic(strlen(newname) + 1);
strcpy(strname, newname);
freeMagic(newname);
}
}
cifReadCellDef = calmaFindCell(strname, &was_called);
@ -405,17 +411,18 @@ calmaParseStructure(filename)
*/
if (CalmaFlattenUses && (!was_called) && (npaths < 10) && (nsrefs == 0))
{
/* To-do: If CDFLATGDS is already set, need to remove */
/* If CDFLATGDS is already set, may need to remove */
/* existing planes and free memory. */
if (cifReadCellDef->cd_flags & CDFLATGDS)
if ((cifReadCellDef->cd_client != (ClientData)CLIENTDEFAULT) &&
(cifReadCellDef->cd_flags & CDFLATGDS))
{
Plane **cifplanes = (Plane **)cifReadCellDef->cd_client;
int pNum;
for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++)
{
if (cifplanes[pNum] != NULL)
if (cifplanes[pNum] != NULL)
{
DBFreePaintPlane(cifplanes[pNum]);
TiFreePlane(cifplanes[pNum]);
@ -903,7 +910,8 @@ calmaElementSref(filename)
for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++)
{
if (gdsplanes[pNum] != NULL)
if ((def->cd_client != (ClientData)CLIENTDEFAULT) &&
(gdsplanes[pNum] != NULL))
{
gdsCopyRec.plane = cifCurReadPlanes[pNum];
if (isArray)

View File

@ -291,10 +291,10 @@ calmaElementBoundary()
/* Convert rp to magic database units to compare to label rects */
rpc = rp->r_r;
rpc.r_xbot /= calmaReadScale1;
rpc.r_xtop /= calmaReadScale1;
rpc.r_ybot /= calmaReadScale1;
rpc.r_ytop /= calmaReadScale1;
rpc.r_xbot /= cifCurReadStyle->crs_scaleFactor;
rpc.r_xtop /= cifCurReadStyle->crs_scaleFactor;
rpc.r_ybot /= cifCurReadStyle->crs_scaleFactor;
rpc.r_ytop /= cifCurReadStyle->crs_scaleFactor;
if ((ciftype >= 0) &&
(cifCurReadStyle->crs_labelSticky[ciftype] != LABEL_TYPE_NONE))

View File

@ -227,7 +227,7 @@ done:
if (mw != NULL)
{
if (calmaLookCell(libname, NULL) != (CellDef *)NULL)
DBWloadWindow(mw, libname, FALSE);
DBWloadWindow(mw, libname, FALSE, FALSE);
}
freeMagic(libname);
}

View File

@ -372,10 +372,10 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
char *filename;
{
int nbytes, rtype;
char *strname = NULL, *newnameptr, newname[CALMANAMELENGTH*2];
char *strname = NULL, *newnameptr;
HashEntry *he, *he2;
CellDef *edef;
char *prefix;
char *prefix = NULL;
/* Make sure this is a structure; if not, let the caller know we're done */
PEEKRH(nbytes, rtype);
@ -397,23 +397,35 @@ 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. */
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);
if ((newnameptr = (char *)HashGetValue(he)) != NULL)
{
/* Structure is defined more than once */
TxError("Structure %s defined redundantly in GDS\n", strname);
if (*newnameptr != '0')
TxError("Structure %s defined redundantly in GDS\n", strname);
else
*newnameptr = '1';
/* To be considered: Should the structure be output more than once? */
calmaOutStringRecord(CALMA_STRNAME, newnameptr, outf);
calmaOutStringRecord(CALMA_STRNAME, newnameptr + 1, outf);
}
else if (!strcmp(strname, def->cd_name))
{
/* This is the top level cell being defined. Its name */
/* does not get modified. */
newnameptr = mallocMagic(strlen(strname) + 1);
sprintf(newnameptr, "%s", strname);
calmaOutStringRecord(CALMA_STRNAME, newnameptr, outf);
newnameptr = mallocMagic(strlen(strname) + 2);
sprintf(newnameptr, "1%s", strname);
calmaOutStringRecord(CALMA_STRNAME, newnameptr + 1, outf);
HashSetValue(he, (char *)newnameptr);
}
else
@ -444,26 +456,20 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
/* Same library, so keep the cellname and mark the cell */
/* as having been written to GDS. */
newnameptr = mallocMagic(strlen(strname) + 1);
sprintf(newnameptr, "%s", strname);
newnameptr = mallocMagic(strlen(strname) + 2);
sprintf(newnameptr, "1%s", strname);
HashSetValue(he, (char *)newnameptr);
}
else
{
/* Find the unique library prefix and prepend it to the cell name */
he2 = HashFind(&calmaLibHash, filename);
if (he2 == NULL)
{
/* Should never happen */
TxError("Fatal error: Library %s not recorded!\n", filename);
newnameptr = strname;
}
if (prefix == NULL)
newnameptr = strname; /* Should never happen */
else
{
prefix = (char *)HashGetValue(he2);
newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 8);
sprintf(newnameptr, "%s_%s", prefix, strname);
newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 9);
sprintf(newnameptr, "1%s_%s", prefix, strname);
HashSetValue(he, (char *)newnameptr);
}
}
@ -472,22 +478,16 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
{
/* Find the unique library prefix and prepend it to the cell name */
he2 = HashFind(&calmaLibHash, filename);
if (he2 == NULL)
{
/* Should never happen */
TxError("Fatal error: Library %s not recorded!\n", filename);
newnameptr = strname;
}
if (prefix == NULL)
newnameptr = strname; /* Should never happen */
else
{
prefix = (char *)HashGetValue(he2);
newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 8);
sprintf(newnameptr, "%s_%s", prefix, strname);
newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 9);
sprintf(newnameptr, "1%s_%s", prefix, strname);
HashSetValue(he, (char *)newnameptr);
}
}
calmaOutStringRecord(CALMA_STRNAME, newnameptr, outf);
calmaOutStringRecord(CALMA_STRNAME, newnameptr + 1, outf);
}
freeMagic(strname);
@ -525,7 +525,7 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
newnameptr = (char *)HashGetValue(he);
if (newnameptr != NULL)
{
calmaOutStringRecord(CALMA_SNAME, newnameptr, outf);
calmaOutStringRecord(CALMA_SNAME, newnameptr + 1, outf);
}
else
{
@ -535,14 +535,14 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
/* the same way used for structure definitions. */
newnameptr = (char *)mallocMagic(strlen(strname) +
strlen(prefix) + 8);
sprintf(newnameptr, "%s_%s", prefix, strname);
strlen(prefix) + 9);
sprintf(newnameptr, "0%s_%s", prefix, strname);
edef = DBCellLookDef(newnameptr);
edef = DBCellLookDef(newnameptr + 1);
if (edef != NULL)
sprintf(newnameptr, "%s_%s[[0]]", prefix, strname);
sprintf(newnameptr, "0%s_%s[[0]]", prefix, strname);
HashSetValue(he, (char *)newnameptr);
calmaOutStringRecord(CALMA_SNAME, newnameptr, outf);
calmaOutStringRecord(CALMA_SNAME, newnameptr + 1, outf);
}
break;
@ -746,8 +746,11 @@ calmaProcessDef(def, outf)
/* Read the cell in if it is not already available. */
if ((def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(def, (char *) NULL, TRUE, NULL))
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL))
return (0);
}
/*
* Output the definitions for any of our descendants that have
@ -1024,7 +1027,7 @@ calmaOutFunc(def, f, cliprect)
((lab->lab_flags & PORT_NUM_MASK) == i))
{
calmaWriteLabelFunc(lab, type, f);
break;
/* break; */ /* Do not limit to unique labels! */
}
}
}
@ -1316,7 +1319,7 @@ calmaOutStructName(type, def, f)
CellDef *def;
FILE *f;
{
char defname[CALMANAMELENGTH+1];
char *defname;
unsigned char c;
char *cp;
int calmanum;
@ -1341,10 +1344,11 @@ calmaOutStructName(type, def, f)
}
/* We really should ensure that the new name is unique. . . */
}
if (cp <= def->cd_name + CALMANAMELENGTH)
if ((!(CIFCurStyle->cs_flags & CWF_STRING_LIMIT)) ||
(cp <= def->cd_name + CALMANAMELENGTH))
{
/* Yes, it's legal: use it */
(void) strcpy(defname, def->cd_name);
defname = StrDup(NULL, def->cd_name);
}
else
{
@ -1352,12 +1356,14 @@ calmaOutStructName(type, def, f)
bad:
calmanum = (int) def->cd_client;
if (calmanum < 0) calmanum = -calmanum;
defname = (char *)mallocMagic(32);
(void) sprintf(defname, "XXXXX%d", calmanum);
TxError("Warning: string in output unprintable; changed to \'%s\'\n",
defname);
}
calmaOutStringRecord(type, defname, f);
freeMagic(defname);
}
/* Added by NP 8/21/2004 */
@ -2734,7 +2740,7 @@ calmaOutDate(t, f)
void
calmaOutStringRecord(type, str, f)
int type; /* Type of this record (data type is ASCII string) */
char *str; /* String to be output (<= CALMANAMELENGTH chars) */
char *str; /* String to be output */
FILE *f; /* Stream file */
{
int len;
@ -2759,9 +2765,16 @@ calmaOutStringRecord(type, str, f)
* last CALMANAMELENGTH characters (since cell names are more
* likely to be unique in the last characters than in the first
* characters).
*
* NOTE: GDS format has not used CALMANAMELENGTH restrictions
* for ages. Since this is a 2-byte record, then is it not
* worth checking the 65536 - 4 character limit. The CALMANAMELENGTH
* restriction must be enabled in the cifoutput flags.
*/
if (len & 01) len++;
if (len > CALMANAMELENGTH)
if ((CIFCurStyle->cs_flags & CWF_STRING_LIMIT) && (len > CALMANAMELENGTH))
{
TxError("Warning: Cellname %s truncated ", str);
TxError("to %s (GDS format limit)\n", str + len - CALMANAMELENGTH);

View File

@ -111,6 +111,177 @@ cifPaintFunc(tile, table)
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* cifGrowMinFunc --
*
* Called for each relevant tile during grow-min operations.
*
* Results:
* Always returns 0 to keep the search alive.
*
* Side effects:
* May paint into cifNewPlane
*
* Algorithm (based on maximum horizontal stripes rule):
* Scan top and bottom boundaries from left to right. For any
* distance (including distance zero) sharing the same type (0 or 1)
* on both the tile top and bottom, find the diagonal length. If
* less than co_distance, then expand this area and paint.
* NOTE: This algorithm does not cover a number of geometry cases
* and needs to be reworked. It should be restricted to cases of
* layers that have "rect_only" DRC rules. Since the rule is usually
* needed for implants on FET gates to maintain the implant width for
* small gates, the "rect_only" requirement is not particularly
* constraining.
*
* ----------------------------------------------------------------------------
*/
int
cifGrowMinFunc(tile, table)
Tile *tile;
PaintResultType *table; /* Table to be used for painting. */
{
Rect area, parea;
int locDist, width, height, h;
TileType type, tptype;
Tile *tp, *tp2;
TiToRect(tile, &area);
area.r_xbot *= cifScale;
area.r_xtop *= cifScale;
area.r_ybot *= cifScale;
area.r_ytop *= cifScale;
parea = area;
/* Check whole tile for minimum width */
width = area.r_xtop - area.r_xbot;
if (width < growDistance)
{
locDist = (growDistance - width) / 2;
area.r_xbot -= locDist;
area.r_xtop += locDist;
/* If there is another tile on top or bottom, and the height is */
/* less than minimum, then extend height in the direction of */
/* the bordering tile. Otherwise, if the height is less than */
/* minimum, then grow halfway in both directions. */
height = area.r_ytop - area.r_ybot;
if (height < growDistance)
{
bool freeTop, freeBot;
freeTop = freeBot = TRUE;
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
if (TiGetTopType(tp) == TiGetBottomType(tile))
{
freeBot = FALSE;
break;
}
for (tp2 = RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2))
if (TiGetBottomType(tp2) == TiGetTopType(tile))
{
freeTop = FALSE;
break;
}
/* In the following, value h ensures that the euclidean */
/* distance between inside corners of the layer */
/* satisfies growDistance. */
if (freeTop == TRUE && freeBot == FALSE)
{
locDist = (growDistance - height) / 2;
h = (int)sqrt((double)(growDistance * growDistance) -
0.25 * (double)((growDistance + width) *
(growDistance + width)) + 0.5);
area.r_ybot -= h;
}
else if (freeTop == FALSE && freeBot == TRUE)
{
h = (int)sqrt((double)(growDistance * growDistance) -
0.25 * (double)((growDistance + width) *
(growDistance + width)) + 0.5);
area.r_ytop += h;
}
else {
locDist = (growDistance - height) / 2;
area.r_ybot -= locDist;
area.r_ytop += locDist;
}
}
}
DBPaintPlane(cifPlane, &area, table, (PaintUndoInfo *) NULL);
area = parea;
/* Scan bottom from left to right */
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
{
tptype = TiGetTopType(tp);
/* Scan top from right to left across range of tp */
for (tp2 = RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2))
if (TiGetBottomType(tp2) == tptype)
{
/* Set range to length of overlap */
if ((LEFT(tp2) <= RIGHT(tp)) && (LEFT(tp2) >= LEFT(tp)))
{
area.r_xbot = LEFT(tp2) < LEFT(tile) ? LEFT(tile) : LEFT(tp2);
area.r_xtop = RIGHT(tp) > RIGHT(tile) ? RIGHT(tile) : RIGHT(tp);
}
else if ((RIGHT(tp2) >= LEFT(tp)) && (RIGHT(tp2) <= RIGHT(tp)))
{
area.r_xbot = LEFT(tp) < LEFT(tile) ? LEFT(tile) : LEFT(tp);
area.r_xtop = RIGHT(tp2) > RIGHT(tile) ? RIGHT(tile) : RIGHT(tp2);
}
else continue;
area.r_xbot *= cifScale;
area.r_xtop *= cifScale;
/* Does area violate minimum width requirement? */
width = area.r_xtop - area.r_xbot;
height = area.r_ytop - area.r_ybot;
/* Manhattan requirement (to-do: Euclidean) */
if (width < growDistance)
{
locDist = (growDistance - width) / 2;
parea.r_xbot = area.r_xbot - locDist;
parea.r_xtop = area.r_xtop + locDist;
}
else
{
parea.r_xbot = area.r_xbot;
parea.r_xtop = area.r_xtop;
}
if (height < growDistance)
{
locDist = (growDistance - height) / 2;
parea.r_ybot = area.r_ybot - locDist;
parea.r_ytop = area.r_ytop + locDist;
}
else
{
parea.r_ybot = area.r_ybot;
parea.r_ytop = area.r_ytop;
}
if ((width < growDistance) || (height < growDistance))
DBPaintPlane(cifPlane, &parea, table, (PaintUndoInfo *) NULL);
}
}
CIFTileOps += 1;
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -514,7 +685,7 @@ cifGrowFunc(tile, table)
CIFTileOps += 1;
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -842,6 +1013,46 @@ endbloat:
return 0;
}
#define CIF_PENDING 0
#define CIF_UNPROCESSED CLIENTDEFAULT
#define CIF_PROCESSED 1
#define CIF_IGNORE 2
#define PUSHTILE(tp, stack) \
if ((tp)->ti_client == (ClientData) CIF_UNPROCESSED) { \
(tp)->ti_client = (ClientData) CIF_PENDING; \
STACKPUSH((ClientData) (tp), stack); \
}
/*
*-------------------------------------------------------
*
* cifFoundFunc --
*
* Find the first tile in the given area.
*
* Results:
* Return 1 to stop the search and process.
* Set clientData to the tile found.
*
*-------------------------------------------------------
*/
int
cifFoundFunc(tile, BloatStackPtr)
Tile *tile;
Stack **BloatStackPtr;
{
PUSHTILE(tile, *BloatStackPtr);
return 0;
}
/* Data structure for bloat-all function */
typedef struct _bloatStruct {
CIFOp *op;
CellDef *def;
} BloatStruct;
/*
* ----------------------------------------------------------------------------
*
@ -861,30 +1072,26 @@ endbloat:
* ----------------------------------------------------------------------------
*/
#define CIF_PENDING 0
#define CIF_UNPROCESSED CLIENTDEFAULT
#define CIF_PROCESSED 1
#define CIF_IGNORE 2
#define PUSHTILE(tp, stack) \
if ((tp)->ti_client == (ClientData) CIF_UNPROCESSED) { \
(tp)->ti_client = (ClientData) CIF_PENDING; \
STACKPUSH((ClientData) (tp), stack); \
}
int
cifBloatAllFunc(tile, op)
cifBloatAllFunc(tile, bls)
Tile *tile; /* The tile to be processed. */
CIFOp *op; /* Describes the operation to be performed */
BloatStruct *bls;
{
Rect area;
TileTypeBitMask connect;
Tile *t, *tp;
TileType type;
BloatData *bloats = (BloatData *)op->co_client;
int i;
BloatData *bloats;
int i, locScale;
PlaneMask pmask;
CIFOp *op;
CellDef *def;
static Stack *BloatStack = (Stack *)NULL;
op = bls->op;
def = bls->def;
bloats = (BloatData *)op->co_client;
/* Create a mask of all connecting types (these must be in a single
* plane), then call a search function to find all connecting material
* of these types.
@ -900,7 +1107,38 @@ cifBloatAllFunc(tile, op)
if (BloatStack == (Stack *)NULL)
BloatStack = StackNew(64);
PUSHTILE(tile, BloatStack);
/* If the type of the tile to be processed is not in the same plane */
/* as the bloat type(s), then find any tile under the tile to be */
/* processed that belongs to the connect mask, and use that as the */
/* starting tile. */
t = tile;
type = TiGetType(tile);
if (type == CIF_SOLIDTYPE)
{
pmask = 0;
locScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
/* Get the tile into magic database coordinates if it's in CIF coords */
TiToRect(tile, &area);
area.r_xbot /= locScale;
area.r_xtop /= locScale;
area.r_ybot /= locScale;
area.r_ytop /= locScale;
}
else
{
int pNum = DBPlane(type);
pmask = CoincidentPlanes(&connect, PlaneNumToMaskBit(pNum));
if (pmask == 0) TiToRect(tile, &area);
locScale = cifScale;
}
if (pmask == 0)
DBSrPaintArea((Tile *)NULL, def->cd_planes[bloats->bl_plane], &area,
&connect, cifFoundFunc, (ClientData)(&BloatStack));
else
PUSHTILE(t, BloatStack);
while (!StackEmpty(BloatStack))
{
t = (Tile *) STACKPOP(BloatStack);
@ -910,10 +1148,10 @@ cifBloatAllFunc(tile, op)
/* Get the tile into CIF coordinates. */
TiToRect(t, &area);
area.r_xbot *= cifScale;
area.r_ybot *= cifScale;
area.r_xtop *= cifScale;
area.r_ytop *= cifScale;
area.r_xbot *= locScale;
area.r_ybot *= locScale;
area.r_xtop *= locScale;
area.r_ytop *= locScale;
DBNMPaintPlane(cifPlane, TiGetTypeExact(t), &area,
CIFPaintTable, (PaintUndoInfo *) NULL);
@ -982,6 +1220,134 @@ cifBloatAllFunc(tile, op)
return 0; /* Keep the search alive. . . */
}
/*
* ----------------------------------------------------------------------------
*
* cifCloseFunc --
*
* Called for each relevant tile during close operations.
*
* Results:
* Always returns 0 to keep the search alive.
*
* Side effects:
* Paints into cifNewPlane. Tiles in old plane are tagged with
* a static value in ClientData, which does not need to be reset
* since the old plane will be free'd.
* ----------------------------------------------------------------------------
*/
#define CLOSE_SEARCH 0
#define CLOSE_FILL 1
#define CLOSE_DONE 2
int
cifCloseFunc(tile, plane)
Tile *tile;
Plane *plane;
{
Rect area, newarea;
int atotal;
int cifGatherFunc();
/* If tile is marked, then it has been handled, so ignore it */
if (tile->ti_client != (ClientData)CIF_UNPROCESSED) return 0;
atotal = 0;
/* Search all sides for connected space tiles, and accumulate the total */
/* area. If any connected tile borders infinity, then stop searching */
/* because the area is not enclosed. */
cifGatherFunc(tile, &atotal, CLOSE_SEARCH);
/* If the total area is smaller than the rule area, then paint all the */
/* tile areas into the destination plane. */
if ((atotal != INFINITY) && (atotal < growDistance))
cifGatherFunc(tile, &atotal, CLOSE_FILL);
else
cifGatherFunc(tile, &atotal, CLOSE_DONE);
return 0;
}
int
cifGatherFunc(tile, atotal, mode)
Tile *tile;
int *atotal;
bool mode;
{
Tile *tp;
TileType type;
dlong locarea;
Rect area, newarea;
ClientData cdata = (mode == CLOSE_SEARCH) ? (ClientData)CIF_UNPROCESSED :
(ClientData)CIF_PENDING;
/* Ignore if tile has already been processed */
if (tile->ti_client != cdata) return 0;
TiToRect(tile, &area);
/* Boundary tiles indicate an unclosed area, so set the area total to */
/* INFINITY and don't try to run calculations on it. */
if ((area.r_xbot == TiPlaneRect.r_xbot) || (area.r_ybot == TiPlaneRect.r_ybot) ||
(area.r_xtop == TiPlaneRect.r_xtop) || (area.r_ytop == TiPlaneRect.r_ytop))
*atotal = INFINITY;
/* Stop accumulating if already larger than growDistance to avoid the */
/* possibility of integer overflow. */
if (mode == CLOSE_SEARCH)
{
if ((*atotal != INFINITY) && (*atotal < growDistance))
locarea = (dlong)(area.r_xtop - area.r_xbot)
* (dlong)(area.r_ytop - area.r_ybot);
if (locarea > (dlong)INFINITY)
*atotal = INFINITY;
else
*atotal += (int)locarea;
}
else if (mode == CLOSE_FILL)
{
DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *)NULL);
CIFTileOps++;
}
if (mode == CLOSE_SEARCH)
tile->ti_client = (ClientData)CIF_PENDING;
else
tile->ti_client = (ClientData)CIF_PROCESSED;
/* Look for additional neighboring space tiles */
/* Check top */
if (area.r_ytop != TiPlaneRect.r_ytop)
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp))
if (tp->ti_client == cdata && TiGetType(tp) == TT_SPACE)
cifGatherFunc(tp, atotal, mode);
/* Check bottom */
if (area.r_ybot != TiPlaneRect.r_ybot)
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
if (tp->ti_client == cdata && TiGetType(tp) == TT_SPACE)
cifGatherFunc(tp, atotal, mode);
/* Check left */
if (area.r_xbot != TiPlaneRect.r_xbot)
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
if (tp->ti_client == cdata && TiGetType(tp) == TT_SPACE)
cifGatherFunc(tp, atotal, mode);
/* Check right */
if (area.r_xtop != TiPlaneRect.r_xtop)
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp))
if (tp->ti_client == cdata && TiGetType(tp) == TT_SPACE)
cifGatherFunc(tp, atotal, mode);
return 0;
}
/*--------------------------------------------------------------*/
/* Support routines and definitions for cifSquaresFillArea */
/*--------------------------------------------------------------*/
@ -1310,7 +1676,7 @@ cifRectBoundingBox(op, cellDef, plane)
}
else
{
maxr = FindMaxRectangle2(&bbox, tile, plane);
maxr = FindMaxRectangle2(&bbox, tile, plane, NULL);
DBPaintPlane(cifPlane, maxr, CIFPaintTable, (PaintUndoInfo *)NULL);
CIFTileOps++;
}
@ -1723,7 +2089,7 @@ cifSlotsFillArea(op, cellDef, plane)
{
Tile *tile, *t, *tp;
Rect bbox, area, square, cut, llcut;
int nAcross, nUp, left, spitch, lpitch, ssize, lsize;
int nAcross, nUp, left, spitch, lpitch, ssize, lsize, offset;
int diff, right;
int xpitch, ypitch, xborder, yborder, xdiff, ydiff;
int i, j, k, savecount;
@ -1944,16 +2310,17 @@ cifSlotsFillArea(op, cellDef, plane)
cifSlotFunc(&bbox, op, &nUp, &nAcross, &llcut, vertical);
cut.r_ybot = llcut.r_ybot;
cut.r_ytop = llcut.r_ytop;
cut.r_ybot = llcut.r_ybot + slots->sl_start;
cut.r_ytop = llcut.r_ytop + slots->sl_start;
/* For each contact cut area, check that there is */
/* no whitespace */
offset = slots->sl_start;
for (i = 0; i < nUp; i++)
{
cut.r_xbot = llcut.r_xbot;
cut.r_xtop = llcut.r_xtop;
cut.r_xbot = llcut.r_xbot + offset;
cut.r_xtop = llcut.r_xtop + offset;
square.r_ybot = cut.r_ybot - yborder;
square.r_ytop = cut.r_ytop + yborder;
@ -1980,6 +2347,8 @@ cifSlotsFillArea(op, cellDef, plane)
}
cut.r_ybot += ypitch;
cut.r_ytop += ypitch;
offset += slots->sl_offset;
if (offset >= xpitch) offset -= xpitch;
}
if (savecount != CIFTileOps) break;
@ -2688,6 +3057,7 @@ cifSrTiles(cifOp, area, cellDef, temps, func, cdArg)
{
TileTypeBitMask maskBits;
TileType t;
Tile *tp;
int i;
BloatData *bloats;
@ -2699,7 +3069,7 @@ cifSrTiles(cifOp, area, cellDef, temps, func, cdArg)
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
/* Bloat operations have to be in a single plane */
/* Bloat operations (except bloat-all) have to be in a single plane */
switch (cifOp->co_opcode) {
case CIFOP_BLOAT:
@ -2783,6 +3153,7 @@ CIFGenLayer(op, area, cellDef, temps, clientdata)
SearchContext scx;
TileType ttype;
char *netname;
BloatStruct bls;
int (*cifGrowFuncPtr)() = (CIFCurStyle->cs_flags & CWF_GROW_EUCLIDEAN) ?
cifGrowEuclideanFunc : cifGrowFunc;
@ -2926,6 +3297,20 @@ CIFGenLayer(op, area, cellDef, temps, clientdata)
nextPlane = temp;
break;
/* GROWMIN grows non-uniformly to ensure minimum dimensions */
case CIFOP_GROWMIN:
growDistance = op->co_distance;
DBClearPaintPlane(nextPlane);
cifPlane = nextPlane;
cifScale = 1;
(void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect,
&CIFSolidBits, cifGrowMinFunc, (ClientData)CIFPaintTable);
temp = curPlane;
curPlane = nextPlane;
nextPlane = temp;
break;
/* GROW_G grows non-uniformly to the indicated grid. */
case CIFOP_GROW_G:
@ -2956,6 +3341,22 @@ CIFGenLayer(op, area, cellDef, temps, clientdata)
nextPlane = temp;
break;
case CIFOP_CLOSE:
growDistance = op->co_distance;
DBClearPaintPlane(nextPlane);
cifPlane = nextPlane;
cifScale = 1;
/* First copy the existing paint into the target plane */
(void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect,
&CIFSolidBits, cifPaintFunc, (ClientData)CIFPaintTable);
(void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect,
&DBSpaceBits, cifCloseFunc, (ClientData)&curPlane);
temp = curPlane;
curPlane = nextPlane;
nextPlane = temp;
break;
case CIFOP_BLOAT:
cifPlane = curPlane;
cifSrTiles(op, area, cellDef, temps,
@ -2971,8 +3372,10 @@ CIFGenLayer(op, area, cellDef, temps, clientdata)
case CIFOP_BLOATALL:
cifPlane = curPlane;
bls.op = op;
bls.def = cellDef;
cifSrTiles(op, area, cellDef, temps,
cifBloatAllFunc, (ClientData) op);
cifBloatAllFunc, (ClientData)&bls);
break;
case CIFOP_SQUARES:

3980
cif/CIFgen.c.test Normal file

File diff suppressed because it is too large Load Diff

View File

@ -69,6 +69,7 @@ typedef struct slots_data
int sl_lsize;
int sl_lsep;
int sl_offset;
int sl_start;
} SlotsData;
typedef struct cifop
@ -95,6 +96,7 @@ typedef struct cifop
* the masks.
* CIFOP_GROW - Grow the current results uniformly by co_distance.
* CIFOP_GROW_G - Grow the current results to snap to the indicated grid.
* CIFOP_GROWMIN - Grow result such that no dimension is less than co_distance.
* CIFOP_SHRINK - Shrink the current results uniformly by co_distance.
* CIFOP_BLOAT - Find layers in paintMask, then bloat selectively
* according to bl_distance, and OR the results into
@ -130,26 +132,29 @@ typedef struct cifop
* CIFOP_COPYUP - Added 5/5/16---make and keep a copy the resulting layer,
* which will be painted into parent cells instead of the
* current cell. This replaces the "fault" method.
* CIFOP_CLOSE - Added 11/25/19---close up areas smaller than indicated
*/
#define CIFOP_AND 1
#define CIFOP_OR 2
#define CIFOP_GROW 3
#define CIFOP_GROW_G 4
#define CIFOP_SHRINK 5
#define CIFOP_BLOAT 6
#define CIFOP_SQUARES 7
#define CIFOP_SLOTS 8
#define CIFOP_BLOATMAX 9
#define CIFOP_BLOATMIN 10
#define CIFOP_BLOATALL 11
#define CIFOP_ANDNOT 12
#define CIFOP_SQUARES_G 13
#define CIFOP_BBOX 14
#define CIFOP_BOUNDARY 15
#define CIFOP_NET 16
#define CIFOP_MAXRECT 17
#define CIFOP_COPYUP 18
#define CIFOP_GROWMIN 4
#define CIFOP_GROW_G 5
#define CIFOP_SHRINK 6
#define CIFOP_BLOAT 7
#define CIFOP_SQUARES 8
#define CIFOP_SLOTS 9
#define CIFOP_BLOATMAX 10
#define CIFOP_BLOATMIN 11
#define CIFOP_BLOATALL 12
#define CIFOP_ANDNOT 13
#define CIFOP_SQUARES_G 14
#define CIFOP_BBOX 15
#define CIFOP_BOUNDARY 16
#define CIFOP_NET 17
#define CIFOP_MAXRECT 18
#define CIFOP_COPYUP 19
#define CIFOP_CLOSE 20
/* Added by Tim 10/21/2004 */
/* The following structure is used to pass information on how to draw
@ -292,6 +297,7 @@ typedef struct cifstyle
#define CWF_GROW_EUCLIDEAN 0x08
#define CWF_SEE_VENDOR 0x10 /* Override vendor GDS flag in cells */
#define CWF_NO_ERRORS 0x20 /* Do not generate error msgs and fdbk */
#define CWF_STRING_LIMIT 0x40 /* Use older Calma format character limit */
/* procedures */
@ -310,6 +316,7 @@ extern void CIFLoadStyle();
extern Plane *CIFPlanes[]; /* Normal place to store CIF. */
extern CIFKeep *CIFStyleList; /* List of all CIF styles. */
extern CIFStyle *CIFCurStyle; /* Current style being used. */
extern CIFStyle *CIFDRCStyle; /* CIF style for DRC checking (optional) */
extern CellUse *CIFComponentUse; /* Flatten stuff in here if needed. */
extern CellDef *CIFComponentDef; /* Corresponds to CIFComponentUse. */
extern CellUse *CIFDummyUse; /* Used to dummy up a CellUse for a

View File

@ -752,7 +752,7 @@ cifMakeBoundaryFunc(tile, clientdata)
CIFReadError("Warning: Cell %s boundary was redefined.\n",
cifReadCellDef->cd_name);
else
CalmaError("Warning: Cell %s boundary was redefined.\n",
CalmaReadError("Warning: Cell %s boundary was redefined.\n",
cifReadCellDef->cd_name);
}
}
@ -1508,13 +1508,18 @@ CIFReadCellCleanup(filetype)
freeMagic((char *)def->cd_client);
def->cd_client = (ClientData)CLIENTDEFAULT;
#if 0
/* If the CDFLATTENED flag was not set, then this geometry */
/* was never instantiated, and should generate a warning. */
/* was never instantiated, and should generate a message. */
/* However, this is not an error condition as there are a */
/* number of useful reasons to copy lots of information up */
/* the GDS hierarchy for "just in case" scenarios. */
if (!(def->cd_flags & CDFLATTENED))
CIFReadError("%s read error: Unresolved geometry in cell"
CIFReadWarning("%s read: Unresolved geometry in cell"
" %s maps to no magic layers\n",
(filetype == FILE_CIF) ? "CIF" : "GDS", def->cd_name);
#endif
#if 0
/* Remove the cell if it has no parents, no children, and no geometry */

View File

@ -621,8 +621,10 @@ CIFReadTechLine(sectionName, argc, argv)
if (argc >= 3)
{
if(!strncmp(argv[argc - 1], "nanom", 5))
if (!strncmp(argv[argc - 1], "nanom", 5))
cifCurReadStyle->crs_multiplier = 10;
else if (!strncmp(argv[argc - 1], "angstr", 6))
cifCurReadStyle->crs_multiplier = 100;
}
if (cifCurReadStyle->crs_scaleFactor <= 0)

View File

@ -120,7 +120,10 @@ CIFReadError(char *format, ...)
if (CIFWarningLevel == CIF_WARN_NONE) return;
if ((cifTotalErrors < 100) || (CIFWarningLevel != CIF_WARN_LIMIT))
{
TxError("Error at line %d of CIF file: ", cifLineNumber);
if (cifLineNumber > 0)
TxError("Error at line %d of CIF file: ", cifLineNumber);
else
TxError("CIF file read error: ", cifLineNumber);
va_start(args, format);
Vfprintf(stderr, format, args);
va_end(args);
@ -141,7 +144,10 @@ CIFReadWarning(char *format, ...)
if (CIFWarningLevel == CIF_WARN_NONE) return;
if ((cifTotalWarnings < 100) || (CIFWarningLevel != CIF_WARN_LIMIT))
{
TxError("Warning at line %d of CIF file: ", cifLineNumber);
if (cifLineNumber > 0)
TxError("Warning at line %d of CIF file: ", cifLineNumber);
else
TxError("CIF file read warning: ");
va_start(args, format);
Vfprintf(stderr, format, args);
va_end(args);

View File

@ -994,6 +994,8 @@ CIFTechLine(sectionName, argc, argv)
CIFCurStyle->cs_flags |= CWF_SEE_VENDOR;
else if (strcmp(argv[i], "no-errors") == 0)
CIFCurStyle->cs_flags |= CWF_NO_ERRORS;
else if (strcmp(argv[i], "string-limit") == 0)
CIFCurStyle->cs_flags |= CWF_STRING_LIMIT;
}
return TRUE;
}
@ -1023,6 +1025,8 @@ CIFTechLine(sectionName, argc, argv)
newOp->co_opcode = CIFOP_OR;
else if (strcmp(argv[0], "grow") == 0)
newOp->co_opcode = CIFOP_GROW;
else if (strcmp(argv[0], "grow-min") == 0)
newOp->co_opcode = CIFOP_GROWMIN;
else if (strcmp(argv[0], "grow-grid") == 0)
newOp->co_opcode = CIFOP_GROW_G;
else if (strcmp(argv[0], "shrink") == 0)
@ -1049,6 +1053,8 @@ CIFTechLine(sectionName, argc, argv)
newOp->co_opcode = CIFOP_MAXRECT;
else if (strcmp(argv[0], "boundary") == 0)
newOp->co_opcode = CIFOP_BOUNDARY;
else if (strcmp(argv[0], "close") == 0)
newOp->co_opcode = CIFOP_CLOSE;
else
{
TechError("Unknown statement \"%s\".\n", argv[0]);
@ -1066,8 +1072,10 @@ CIFTechLine(sectionName, argc, argv)
break;
case CIFOP_GROW:
case CIFOP_GROWMIN:
case CIFOP_GROW_G:
case CIFOP_SHRINK:
case CIFOP_CLOSE:
if (argc != 2) goto wrongNumArgs;
newOp->co_distance = atoi(argv[1]);
if (newOp->co_distance <= 0)
@ -1080,14 +1088,18 @@ CIFTechLine(sectionName, argc, argv)
case CIFOP_BLOATALL:
if (argc != 3) goto wrongNumArgs;
cifParseLayers(argv[1], CIFCurStyle, &newOp->co_paintMask,
(TileTypeBitMask *)NULL, FALSE);
bloatLayers = newOp->co_paintMask;
&newOp->co_cifMask, FALSE);
bloats = (BloatData *)mallocMagic(sizeof(BloatData));
for (i = 0; i < TT_MAXTYPES; i++)
bloats->bl_distance[i] = 0;
newOp->co_client = (ClientData)bloats;
cifParseLayers(argv[2], CIFCurStyle, &mask, &tempMask, TRUE);
/* 10/15/2019: Lifting restriction that the types that */
/* trigger the bloating must be in the same plane as the */
/* types that are bloated into. */
TTMaskZero(&bloatLayers);
TTMaskSetMask(&bloatLayers, &mask);
if (!TTMaskEqual(&tempMask, &DBZeroTypeBits))
TechError("Can't use templayers in bloat statement.\n");
@ -1323,6 +1335,7 @@ bloatCheck:
slots->sl_lsize = 0;
slots->sl_lsep = 0;
slots->sl_offset = 0;
slots->sl_start = 0;
}
if (argc >= 5)
{
@ -1357,7 +1370,7 @@ bloatCheck:
goto errorReturn;
}
}
if (argc == 8)
if (argc >= 8)
{
i = atoi(argv[7]);
slots->sl_offset = i;
@ -1367,7 +1380,17 @@ bloatCheck:
goto errorReturn;
}
}
if ((argc < 4) || (argc == 6) || (argc > 8))
if (argc == 9)
{
i = atoi(argv[8]);
slots->sl_start = i;
if (i < 0)
{
TechError("Slot start must be non-negative.\n");
goto errorReturn;
}
}
if ((argc < 4) || (argc == 6) || (argc > 9))
goto wrongNumArgs;
break;
}
@ -1481,6 +1504,7 @@ cifComputeRadii(layer, des)
case CIFOP_OR: break;
case CIFOP_GROW:
case CIFOP_GROWMIN:
case CIFOP_GROW_G:
grow += op->co_distance;
break;
@ -1681,7 +1705,7 @@ CIFTechFinal()
{
slots = (SlotsData *)op->co_client;
for (j = 0; j < 7; j++)
for (j = 0; j < 8; j++)
{
switch (j) {
case 0: bvalue = slots->sl_sborder; break;
@ -1691,6 +1715,7 @@ CIFTechFinal()
case 4: bvalue = slots->sl_lsize; break;
case 5: bvalue = slots->sl_lsep; break;
case 6: bvalue = slots->sl_offset; break;
case 7: bvalue = slots->sl_start; break;
}
if (bvalue != 0)
{
@ -1945,7 +1970,7 @@ CIFLoadStyle(stylename)
{
SectionID invcif;
if (CIFCurStyle->cs_name == stylename) return;
if (CIFCurStyle && (CIFCurStyle->cs_name == stylename)) return;
cifTechNewStyle();
CIFCurStyle->cs_name = stylename;
@ -2092,7 +2117,7 @@ CIFTechOutputScale(n, d)
SquaresData *squares;
SlotsData *slots;
BloatData *bloats;
bool has_odd_space;
bool has_odd_space = FALSE;
if (ostyle == NULL) return;
@ -2189,7 +2214,7 @@ CIFTechOutputScale(n, d)
else if (op->co_opcode == CIFOP_SLOTS)
{
slots = (SlotsData *)op->co_client;
for (j = 0; j < 7; j++)
for (j = 0; j < 8; j++)
{
switch (j) {
case 0: bptr = &slots->sl_sborder; break;
@ -2199,6 +2224,7 @@ CIFTechOutputScale(n, d)
case 4: bptr = &slots->sl_lsize; break;
case 5: bptr = &slots->sl_lsep; break;
case 6: bptr = &slots->sl_offset; break;
case 7: bptr = &slots->sl_start; break;
}
if (*bptr != 0)
{
@ -2315,6 +2341,8 @@ CIFTechOutputScale(n, d)
slots->sl_lsep /= lexpand;
if (slots->sl_offset != 0)
slots->sl_offset /= lexpand;
if (slots->sl_start != 0)
slots->sl_start /= lexpand;
break;
case CIFOP_SQUARES_G:
squares = (SquaresData *)op->co_client;

View File

@ -312,7 +312,8 @@ cifOut(outf)
/* Read the cell in if it is not already available. */
if ((def->cd_flags & CDAVAILABLE) == 0)
{
if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) continue;
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) continue;
}
/* Add any subcells to the stack. This must be done before

View File

@ -1434,7 +1434,7 @@ CmdCif(w, cmd)
if (!ToolGetBox(&rootDef, &box))
{
TxError("Use the box to select the area in");
TxError(" which you want to see CIF.\n");
TxError(" which you want to paint CIF.\n");
return;
}
if (argc == 5)
@ -3079,7 +3079,7 @@ CmdDown(w, cmd)
GeoTransRect(&EditToRootTransform, &(EditCellUse->cu_def->cd_bbox), &area);
(void) WindSearch(DBWclientID, (ClientData) NULL,
(Rect *) NULL, cmdEditRedisplayFunc, (ClientData) &area);
DBWloadWindow(w, EditCellUse->cu_def->cd_name, TRUE, FALSE);
DBWloadWindow(w, EditCellUse->cu_def->cd_name, TRUE, FALSE, FALSE);
}
/* Search function to find the new edit cell: look for a cell use
@ -3182,7 +3182,7 @@ CmdDrc(w, cmd)
bool doforall = FALSE;
bool dolist = FALSE;
int count_total;
DRCCountList *dcl, *dclsrch;
DRCCountList *dcl;
int argc = cmd->tx_argc;
char **argv = cmd->tx_argv;
#ifdef MAGIC_WRAPPER
@ -3197,9 +3197,9 @@ CmdDrc(w, cmd)
"*stepsize [d] change DRC step size to d units",
"catchup run checker and wait for it to complete",
"check recheck area under box in all cells",
"count count error tiles in each cell under box",
"count [total] count error tiles in each cell under box",
"euclidean on|off enable/disable Euclidean geometry checking",
"find [nth] locate next (or nth) error in the layout",
"find [nth] locate next (or nth) error in the layout",
"help print this help information",
"off turn off background checker",
"on reenable background checker",
@ -3313,7 +3313,6 @@ CmdDrc(w, cmd)
#ifdef MAGIC_WRAPPER
if (count_total == -1) lobj = Tcl_NewListObj(0, NULL);
#endif
if ((window = w) == NULL)
{
window = ToolGetBoxWindow(&rootArea, (int *) NULL);
@ -3323,7 +3322,7 @@ CmdDrc(w, cmd)
rootArea = w->w_surfaceArea;
rootUse = (CellUse *) window->w_surfaceID;
dcl = DRCCount(rootUse, &rootArea);
dcl = DRCCount(rootUse, &rootArea, doforall);
while (dcl != NULL)
{
if (count_total >= 0)
@ -3343,7 +3342,6 @@ CmdDrc(w, cmd)
else
{
#endif
if (dcl->dcl_count > 1)
TxPrintf("Cell %s has %d error tiles.\n",
dcl->dcl_def->cd_name, dcl->dcl_count);
@ -3372,11 +3370,12 @@ CmdDrc(w, cmd)
}
}
else if (dolist)
Tcl_SetObjResult(magicinterp, lobj);
Tcl_SetObjResult(magicinterp, lobj);
#else
if ((DRCBackGround != DRC_SET_OFF) && (count_total == -1))
count_total = 0;
if (count_total >= 0)
if (count_gotal >= 0)
TxPrintf("Total DRC errors found: %d\n", count_total);
#endif
break;
@ -3677,7 +3676,7 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
{
Point childPoint, editPoint, rootPoint;
CellDef *def, *rootDef, *editDef;
bool hasChild, hasRoot, hasTrans;
bool hasChild, hasRoot, hasTrans, dereference;
Rect rootBox, bbox;
Transform *tx_cell, trans_cell;
char **av;
@ -3777,7 +3776,8 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
* looked for then no new error message will be printed.
*/
def->cd_flags &= ~CDNOTFOUND;
if (!DBCellRead(def, (char *) NULL, TRUE, NULL))
dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL))
return (FALSE);
DBReComputeBbox(def);
dummy->cu_def = def;

View File

@ -130,7 +130,11 @@ CmdEdit(w, cmd)
return;
}
else if (!(EditCellUse->cu_def->cd_flags & CDAVAILABLE))
DBCellRead(EditCellUse->cu_def, (char *)NULL, TRUE, NULL);
{
bool dereference = (EditCellUse->cu_def->cd_flags & CDDEREFERENCE) ?
TRUE : FALSE;
DBCellRead(EditCellUse->cu_def, (char *)NULL, TRUE, dereference, NULL);
}
if (EditCellUse->cu_def->cd_flags & CDNOEDIT)
{

View File

@ -1452,7 +1452,11 @@ CmdIdentify(w, cmd)
return;
}
if (CmdIllegalChars(cmd->tx_argv[1], "[],/", "Cell use id"))
/* NOTE: Relaxing the definition of illegal characters in cell use IDs */
/* by allowing brackets. Possibly the list can be reduced further. */
/* if (CmdIllegalChars(cmd->tx_argv[1], "[],/", "Cell use id")) */
if (CmdIllegalChars(cmd->tx_argv[1], ",/", "Cell use id"))
return;
if (SelEnumCells(FALSE, (int *) NULL, (SearchContext *) NULL,
@ -1789,6 +1793,7 @@ FlatCopyAllLabels(scx, mask, xMask, targetUse)
char pathstring[FLATTERMSIZE];
TerminalPath tpath;
pathstring[0] = '\0';
tpath.tp_first = tpath.tp_next = pathstring;
tpath.tp_last = pathstring + FLATTERMSIZE;

View File

@ -318,7 +318,7 @@ CmdLabel(w, cmd)
* Implement the "load" command.
*
* Usage:
* load [name [scaled n [d]]] [-force]
* load [name [scaled n [d]]] [-force] [-nowindow] [-dereference]
*
* If name is supplied, then the window containing the point tool is
* remapped so as to edit the cell with the given name.
@ -331,6 +331,13 @@ CmdLabel(w, cmd)
* An input file can be scaled by specifying the "scaled" option, for
* which the geometry of the input file is multiplied by n/d.
*
* Magic saves the path to instances to ensure correct versioning. But
* this interferes with attempts to re-link instances from a different
* location (such as an abstract view instead of a full view, or vice
* versa). So the "-dereference" option strips the instance paths from
* the input file and relies only on the search locations set up by the
* "path" command to find the location of instances.
*
* Results:
* None.
*
@ -350,6 +357,7 @@ CmdLoad(w, cmd)
int locargc = cmd->tx_argc;
bool ignoreTech = FALSE;
bool noWindow = FALSE;
bool dereference = FALSE;
int keepGoing(); /* forward declaration */
if (locargc > 2)
@ -359,29 +367,38 @@ CmdLoad(w, cmd)
locargc--;
noWindow = TRUE;
}
if (!strncmp(cmd->tx_argv[locargc - 1], "-deref", 5))
{
locargc--;
dereference = TRUE;
}
if (!strncmp(cmd->tx_argv[locargc - 1], "-force", 6))
{
locargc--;
ignoreTech = TRUE;
}
if (locargc >= 4 && !strncmp(cmd->tx_argv[2], "scale", 5) &&
if ((locargc >= 4) && !strncmp(cmd->tx_argv[2], "scale", 5) &&
StrIsInt(cmd->tx_argv[3]))
{
n = atoi(cmd->tx_argv[3]);
if (cmd->tx_argc == 5 && StrIsInt(cmd->tx_argv[4]))
if ((locargc == 5) && StrIsInt(cmd->tx_argv[4]))
d = atoi(cmd->tx_argv[4]);
else if (locargc != 4)
{
TxError("Usage: %s name scaled n [d]\n", cmd->tx_argv[0]);
TxError("Usage: %s name scaled n [d] [-force] "
"[-nowindow] [-dereference]\n",
cmd->tx_argv[0]);
return;
}
DBLambda[0] *= d;
DBLambda[1] *= n;
ReduceFraction(&DBLambda[0], &DBLambda[1]);
}
else if (!ignoreTech && !noWindow)
else if (!ignoreTech && !noWindow && !dereference)
{
TxError("Usage: %s [name [scaled n [d]]]\n", cmd->tx_argv[0]);
TxError("Usage: %s name [scaled n [d]] [-force] "
"[-nowindow] [-dereference]\n",
cmd->tx_argv[0]);
return;
}
}
@ -406,7 +423,7 @@ CmdLoad(w, cmd)
}
#endif
DBWloadWindow((noWindow == TRUE) ? NULL : w, cmd->tx_argv[1],
ignoreTech, FALSE);
ignoreTech, FALSE, dereference);
if ((n > 1) || (d > 1))
{
@ -439,7 +456,7 @@ CmdLoad(w, cmd)
ReduceFraction(&DBLambda[0], &DBLambda[1]);
}
}
else DBWloadWindow(w, (char *) NULL, TRUE, FALSE);
else DBWloadWindow(w, (char *) NULL, TRUE, FALSE, FALSE);
}
/*
@ -1882,8 +1899,16 @@ printPropertiesFunc(name, value)
#ifdef MAGIC_WRAPPER
char *keyvalue;
keyvalue = (char *)mallocMagic(strlen(name) + strlen((char *)value) + 2);
sprintf(keyvalue, "%s %s", name, (char *)value);
if (value == NULL)
{
keyvalue = (char *)mallocMagic(strlen(name) + 4);
sprintf(keyvalue, "%s {}", name);
}
else
{
keyvalue = (char *)mallocMagic(strlen(name) + strlen((char *)value) + 2);
sprintf(keyvalue, "%s %s", name, (char *)value);
}
Tcl_AppendElement(magicinterp, keyvalue);
freeMagic(keyvalue);

View File

@ -288,6 +288,7 @@ cmdFlushCell(def)
CellDef *def;
{
CellUse *parentUse;
bool dereference;
/* Disallow flushing a cell that contains the edit cell as a child */
if (EditCellUse && (EditCellUse->cu_parent == def))
@ -309,7 +310,8 @@ cmdFlushCell(def)
}
DBCellClearDef(def);
DBCellClearAvail(def);
(void) DBCellRead(def, (char *) NULL, TRUE, NULL);
dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
(void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL);
DBCellSetAvail(def);
DBReComputeBbox(def);
DBCellSetModified(def, FALSE);

View File

@ -1885,9 +1885,9 @@ CmdXload(w, cmd)
{
if (CmdIllegalChars(cmd->tx_argv[1], "[],", "Cell name"))
return;
DBWloadWindow(w, cmd->tx_argv[1], FALSE, TRUE);
DBWloadWindow(w, cmd->tx_argv[1], FALSE, TRUE, FALSE);
}
else DBWloadWindow(w, (char *) NULL, FALSE, TRUE);
else DBWloadWindow(w, (char *) NULL, FALSE, TRUE, FALSE);
}
/*

View File

@ -234,7 +234,10 @@ dbCellPlaneSrFunc(scx, fp)
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask))
return 0;
if ((def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0;
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
context.tc_scx = scx;
context.tc_filter = fp;
@ -353,7 +356,10 @@ dbCellUniqueTileSrFunc(scx, fp)
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask))
return 0;
if ((def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0;
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
context.tc_scx = scx;
context.tc_filter = fp;
@ -462,7 +468,10 @@ DBNoTreeSrTiles(scx, mask, xMask, func, cdarg)
return 0;
if ((def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0;
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
filter.tf_func = func;
filter.tf_arg = cdarg;
@ -570,7 +579,10 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
ASSERT(def != (CellDef *) NULL, "DBTreeSrLabels");
if (!DBDescendSubcell(cellUse, xMask)) return 0;
if ((def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0;
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
for (lab = def->cd_labels; lab; lab = lab->lab_next)
{
@ -613,8 +625,11 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
else
is_touching = GEO_TOUCH(&lab->lab_rect, r);
}
if (!is_touching && (flags & TF_LABEL_DISPLAY) && (lab->lab_font >= 0))
if (!is_touching && (flags & TF_LABEL_DISPLAY) && lab->lab_font >= 0)
{
/* Check against bounds of the rendered label text */
is_touching = GEO_TOUCH(&lab->lab_bbox, r);
}
if (is_touching && TTMaskHasType(mask, lab->lab_type))
if ((*func)(scx, lab, tpath, cdarg))
@ -671,7 +686,10 @@ dbCellLabelSrFunc(scx, fp)
ASSERT(def != (CellDef *) NULL, "dbCellLabelSrFunc");
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0;
if ((def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0;
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
if (fp->tf_tpath != (TerminalPath *) NULL)
{
@ -785,8 +803,11 @@ DBTreeSrCells(scx, xMask, func, cdarg)
if (!DBDescendSubcell(cellUse, xMask))
return 0;
if ((cellUse->cu_def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(cellUse->cu_def, (char *) NULL, TRUE, NULL))
{
bool dereference = (cellUse->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(cellUse->cu_def, (char *) NULL, TRUE, dereference, NULL))
return 0;
}
context.tc_scx = scx;
context.tc_filter = &filter;
@ -831,8 +852,11 @@ dbTreeCellSrFunc(scx, fp)
else
{
if ((use->cu_def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, NULL))
{
bool dereference = (use->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, dereference, NULL))
return 0;
}
result = DBCellSrArea(scx, dbTreeCellSrFunc, (ClientData) fp);
}
return result;
@ -1082,8 +1106,12 @@ DBCellSrArea(scx, func, cdarg)
context.tc_scx = scx;
if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, NULL))
{
bool dereference = (scx->scx_use->cu_def->cd_flags & CDDEREFERENCE) ?
TRUE : FALSE;
if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, dereference, NULL))
return 0;
}
if (DBSrCellPlaneArea(scx->scx_use->cu_def->cd_cellPlane,
&scx->scx_area, dbCellSrFunc, (ClientData) &context))
@ -1205,7 +1233,10 @@ DBCellEnum(cellDef, func, cdarg)
filter.tf_func = func;
filter.tf_arg = cdarg;
if ((cellDef->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(cellDef, (char *) NULL, TRUE, NULL)) return 0;
{
bool dereference = (cellDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(cellDef, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
if (DBSrCellPlaneArea(cellDef->cd_cellPlane,
&TiPlaneRect, dbEnumFunc, (ClientData) &filter))
return 1;

View File

@ -73,8 +73,12 @@ DBDescendSubcell(use, xMask)
case CU_DESCEND_NO_SUBCKT:
if ((use->cu_def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, NULL))
{
bool dereference = (use->cu_def->cd_flags & CDDEREFERENCE) ?
TRUE : FALSE;
if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, dereference, NULL))
return FALSE;
}
return (DBIsSubcircuit(use->cu_def)) ? FALSE : TRUE;
case CU_DESCEND_NO_LOCK:

View File

@ -661,6 +661,9 @@ dbcUnconnectFunc(tile, clientData)
* ----------------------------------------------------------------------------
*/
/* To do: Make the tpath entries dynamically allocated */
#define FLATTERMSIZE 1024
int
dbcConnectLabelFunc(scx, lab, tpath, csa2)
SearchContext *scx;
@ -672,6 +675,8 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
Rect r;
Point offset;
int pos, rotate;
char newlabtext[FLATTERMSIZE];
char *newlabptr;
int dbcConnectFunc(); /* Forward declaration */
GeoTransRect(&scx->scx_trans, &lab->lab_rect, &r);
@ -683,12 +688,29 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
/* the top level (Note: Could alter label to be placed with */
/* tpath). */
if (csa2->csa2_topscx->scx_use == scx->scx_use)
if (scx->scx_use != csa2->csa2_topscx->scx_use)
{
DBEraseLabelsByContent(def, &r, -1, lab->lab_text);
DBPutFontLabel(def, &r, lab->lab_font, lab->lab_size, rotate, &offset,
pos, lab->lab_text, lab->lab_type, lab->lab_flags);
int newllen = tpath->tp_next - tpath->tp_first;
newlabtext[0] = '\0';
if (newllen > 0)
strncpy(newlabtext, tpath->tp_first, newllen);
sprintf(newlabtext + newllen, "%s", lab->lab_text);
newlabptr = newlabtext;
}
else
newlabptr = lab->lab_text;
/* Do not repeat a label copy; check that the label doesn't */
/* already exist in the destination def first. */
if (DBCheckLabelsByContent(def, &r, lab->lab_type, lab->lab_text))
return 0;
if (DBCheckLabelsByContent(def, &r, lab->lab_type, newlabptr))
return 0;
DBEraseLabelsByContent(def, &r, -1, lab->lab_text);
DBPutFontLabel(def, &r, lab->lab_font, lab->lab_size, rotate, &offset,
pos, newlabptr, lab->lab_type, lab->lab_flags);
if (lab->lab_flags & PORT_DIR_MASK)
{
@ -1024,6 +1046,13 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, destUse)
DBTreeSrTiles(scx, mask, xMask, dbcConnectFunc, (ClientData) &csa2);
while (csa2.csa2_top >= 0)
{
char pathstring[FLATTERMSIZE];
TerminalPath tpath;
tpath.tp_first = tpath.tp_next = pathstring;
tpath.tp_last = pathstring + FLATTERMSIZE;
pathstring[0] = '\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;
@ -1064,7 +1093,7 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, destUse)
searchtype |= TF_LABEL_ATTACH_NOT_SE;
}
}
DBTreeSrLabels(scx, newmask, xMask, NULL, searchtype,
DBTreeSrLabels(scx, newmask, xMask, &tpath, searchtype,
dbcConnectLabelFunc, (ClientData) &csa2);
}
freeMagic((char *)csa2.csa2_list);

View File

@ -37,6 +37,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
*/
struct expandArg
{
bool ea_deref; /* TRUE if root def dereference flag is set */
int ea_xmask; /* Expand mask. */
int (*ea_func)(); /* Function to call for each cell whose
* status is changed.
@ -81,7 +82,8 @@ DBExpand(cellUse, expandMask, expandFlag)
def = cellUse->cu_def;
if ((def->cd_flags & CDAVAILABLE) == 0)
{
if (!DBCellRead(def, (char *) NULL, TRUE, NULL))
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL))
return;
/* Note: we don't have to recompute the bbox here, because
* if it changed, then a timestamp violation must have occurred
@ -142,9 +144,13 @@ DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg)
int dbExpandFunc(), dbUnexpandFunc();
SearchContext scontext;
struct expandArg arg;
bool dereference = (rootUse->cu_def->cd_flags & CDDEREFERENCE) ?
TRUE : FALSE;
if ((rootUse->cu_def->cd_flags & CDAVAILABLE) == 0)
(void) DBCellRead(rootUse->cu_def, (char *) NULL, TRUE, NULL);
{
(void) DBCellRead(rootUse->cu_def, (char *) NULL, TRUE, dereference, NULL);
}
/*
* Walk through the area and set the expansion state
@ -154,6 +160,7 @@ DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg)
arg.ea_xmask = expandMask;
arg.ea_func = func;
arg.ea_arg = cdarg;
arg.ea_deref = dereference;
scontext.scx_use = rootUse;
scontext.scx_trans = GeoIdentityTransform;
@ -193,7 +200,7 @@ dbExpandFunc(scx, arg)
/* If the cell is unavailable, then don't expand it.
*/
if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0)
if(!DBCellRead(childUse->cu_def, (char *) NULL, TRUE, NULL))
if(!DBCellRead(childUse->cu_def, (char *) NULL, TRUE, arg->ea_deref, NULL))
{
TxError("Cell %s is unavailable. It could not be expanded.\n",
childUse->cu_def->cd_name);
@ -303,7 +310,8 @@ dbReadAreaFunc(scx)
if ((def->cd_flags & CDAVAILABLE) == 0)
{
(void) DBCellRead(def, (char *) NULL, TRUE, NULL);
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
(void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL);
/* Note: we don't have to invoke DBReComputeBbox here because
* if the bbox changed then there was a timestamp mismatch and
* the timestamp code will take care of the bounding box later.

View File

@ -264,7 +264,7 @@ file_is_not_writeable(name)
*/
bool
dbCellReadDef(f, cellDef, name, ignoreTech)
dbCellReadDef(f, cellDef, name, ignoreTech, dereference)
FILE *f; /* The file, already opened by the caller */
CellDef *cellDef; /* Pointer to definition of cell to be read in */
char *name; /* Name of file from which to read definition.
@ -279,6 +279,7 @@ dbCellReadDef(f, cellDef, name, ignoreTech)
* names do not match, but an attempt will be
* made to read the file anyway.
*/
bool dereference; /* If TRUE, ignore path references in the input */
{
int cellStamp = 0, rectCount = 0, rectReport = 10000;
char line[2048], tech[50], layername[50];
@ -437,7 +438,7 @@ dbCellReadDef(f, cellDef, name, ignoreTech)
*/
if (sscanf(line, "<< %s >>", layername) != 1)
{
if (!dbReadUse(cellDef, line, sizeof line, f, n, d))
if (!dbReadUse(cellDef, line, sizeof line, f, n, d, dereference))
goto badfile;
continue;
}
@ -619,6 +620,9 @@ done:
}
}
}
/* Update timestamp flags */
DBFlagMismatches(cellDef);
cellDef->cd_timestamp = cellStamp;
if (cellStamp == 0)
{
@ -860,7 +864,7 @@ DBReadBackup(name)
cellDef->cd_flags &= ~CDNOTFOUND;
cellDef->cd_flags |= CDAVAILABLE;
if (dbCellReadDef(f, cellDef, filename, TRUE) == FALSE)
if (dbCellReadDef(f, cellDef, filename, TRUE, FALSE) == FALSE)
return FALSE;
if (dbFgets(line, sizeof(line), f) == NULL)
@ -869,6 +873,8 @@ DBReadBackup(name)
name);
return FALSE;
}
/* Update timestamp flags from dbCellReadDef() */
DBFlagMismatches(cellDef);
}
else
{
@ -914,7 +920,7 @@ DBReadBackup(name)
*/
bool
DBCellRead(cellDef, name, ignoreTech, errptr)
DBCellRead(cellDef, name, ignoreTech, dereference, errptr)
CellDef *cellDef; /* Pointer to definition of cell to be read in */
char *name; /* Name of file from which to read definition.
* If NULL, then use cellDef->cd_file; if that
@ -928,6 +934,7 @@ DBCellRead(cellDef, name, ignoreTech, errptr)
* names do not match, but an attempt will be
* made to read the file anyway.
*/
bool dereference; /* If TRUE then ignore path argument to uses */
int *errptr; /* Copy of errno set by file reading routine
* is placed here, unless NULL.
*/
@ -945,7 +952,7 @@ DBCellRead(cellDef, name, ignoreTech, errptr)
else
{
result = (dbCellReadDef(f, cellDef, name, ignoreTech));
result = (dbCellReadDef(f, cellDef, name, ignoreTech, dereference));
#ifdef FILE_LOCKS
/* Close files that were locked by another user */
@ -1188,13 +1195,14 @@ DBTestOpen(name, fullPath)
*/
bool
dbReadUse(cellDef, line, len, f, scalen, scaled)
dbReadUse(cellDef, line, len, f, scalen, scaled, dereference)
CellDef *cellDef; /* Cell whose cells are being read */
char *line; /* Line containing "use ..." */
int len; /* Size of buffer pointed to by line */
FILE *f; /* Input file */
int scalen; /* Multiply values in file by this */
int scaled; /* Divide values in file by this */
bool dereference; /* If TRUE, ignore path references */
{
int xlo, xhi, ylo, yhi, xsep, ysep, childStamp;
int absa, absb, absd, abse, nconv;
@ -1225,7 +1233,7 @@ dbReadUse(cellDef, line, len, f, scalen, scaled)
pathptr = &path[0];
while (*pathptr == ' ' || *pathptr == '\t') pathptr++;
if (*pathptr == '\n') *pathptr = '\0';
if ((dereference == TRUE) || (*pathptr == '\n')) *pathptr = '\0';
locked = (useid[0] == CULOCKCHAR) ? TRUE : FALSE;
@ -1432,9 +1440,22 @@ badTransform:
slashptr = strrchr(subCellDef->cd_file, '/');
if (slashptr != NULL)
{
bool pathOK = FALSE;
*slashptr = '\0';
if (strcmp(subCellDef->cd_file, pathptr))
/* Avoid generating error message if pathptr starts with '~' */
/* and the tilde-expanded name matches the subCellDef name */
if (*pathptr == '~')
{
char *homedir = getenv("HOME");
if (!strncmp(subCellDef->cd_file, homedir, strlen(homedir))
&& (!strcmp(subCellDef->cd_file + strlen(homedir),
pathptr + 1)))
pathOK = TRUE;
}
if ((pathOK == FALSE) && strcmp(subCellDef->cd_file, pathptr))
{
TxError("Duplicate cell in %s: Instance of cell %s is from "
"path %s but cell was previously read from %s.\n",
@ -2345,6 +2366,8 @@ DBCellWriteFile(cellDef, f)
int reducer;
char *estring;
char lstring[256];
char *propvalue;
bool propfound;
#define FPRINTF(f,s)\
{\
@ -2537,12 +2560,43 @@ DBCellWriteFile(cellDef, f)
}
/* And any properties */
/* NOTE: FIXED_BBOX is treated specially; values are database */
/* values and should be divided by reducer. Easiest to do it */
/* here and revert values after. */
propvalue = (char *)DBPropGet(cellDef, "FIXED_BBOX", &propfound);
if (propfound)
{
char *proporig, *propscaled;
Rect scalebox, bbox;
proporig = StrDup((char **)NULL, propvalue);
propscaled = mallocMagic(strlen(propvalue) + 5);
if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot,
&bbox.r_xtop, &bbox.r_ytop) == 4)
{
scalebox.r_xbot = bbox.r_xbot / reducer;
scalebox.r_xtop = bbox.r_xtop / reducer;
scalebox.r_ybot = bbox.r_ybot / reducer;
scalebox.r_ytop = bbox.r_ytop / reducer;
sprintf(propscaled, "%d %d %d %d",
bbox.r_xbot / reducer, bbox.r_ybot / reducer,
bbox.r_xtop / reducer, bbox.r_ytop / reducer);
DBPropPut(cellDef, "FIXED_BBOX", propscaled);
propvalue = proporig;
}
}
if (cellDef->cd_props != (ClientData)NULL)
{
FPRINTF(f, "<< properties >>\n");
DBPropEnum(cellDef, dbWritePropFunc, (ClientData)f);
}
if (propfound) DBPropPut(cellDef, "FIXED_BBOX", propvalue);
FPRINTF(f, "<< end >>\n");
if (fflush(f) == EOF || ferror(f))
@ -2801,8 +2855,11 @@ DBCellWrite(cellDef, fileName)
#ifdef FILE_LOCKS
else
{
bool dereference = (cellDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
/* Re-aquire the lock on the new file by opening it. */
DBCellRead(cellDef, NULL, TRUE, NULL);
DBCellRead(cellDef, NULL, TRUE, dereference, NULL);
}
#endif
}

View File

@ -313,7 +313,55 @@ DBEraseLabel(cellDef, area, mask, areaReturn)
cellDef->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
return (erasedAny);
}
#define RECTEQUAL(r1, r2) ((r1)->r_xbot == (r2)->r_xbot \
&& (r1)->r_ybot == (r2)->r_ybot \
&& (r1)->r_xtop == (r2)->r_xtop \
&& (r1)->r_ytop == (r2)->r_ytop)
/*
* ----------------------------------------------------------------------------
*
* DBCheckLabelsByContent --
*
* Return any label found on the label list for the given
* CellDef that matches the given specification.
*
* Results:
* Returns a label if a match is found, otherwise returns NULL.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
Label *
DBCheckLabelsByContent(def, rect, type, text)
CellDef *def; /* Where to look for label to delete. */
Rect *rect; /* Coordinates of label. If NULL, then
* labels are searched regardless of coords.
*/
TileType type; /* Layer label is attached to. If < 0, then
* labels are searched regardless of type.
*/
char *text; /* Text associated with label. If NULL, then
* labels are searched regardless of text.
*/
{
Label *lab;
for (lab = def->cd_labels; lab; lab = lab->lab_next)
{
if ((rect != NULL) && !(RECTEQUAL(&lab->lab_rect, rect))) continue;
if ((type >= 0) && (type != lab->lab_type)) continue;
if ((text != NULL) && (strcmp(text, lab->lab_text) != 0)) continue;
return lab;
}
return NULL;
}
/*
* ----------------------------------------------------------------------------
*
@ -348,11 +396,6 @@ DBEraseLabelsByContent(def, rect, type, text)
{
Label *lab, *labPrev;
#define RECTEQUAL(r1, r2) ((r1)->r_xbot == (r2)->r_xbot \
&& (r1)->r_ybot == (r2)->r_ybot \
&& (r1)->r_xtop == (r2)->r_xtop \
&& (r1)->r_ytop == (r2)->r_ytop)
for (labPrev = NULL, lab = def->cd_labels;
lab != NULL;
labPrev = lab, lab = lab->lab_next)

View File

@ -294,20 +294,31 @@ DBTreeFindUse(name, use, scx)
* is read in from disk.
*/
if ((def->cd_flags & CDAVAILABLE) == 0)
(void) DBCellRead(def, (char *) NULL, TRUE, NULL);
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
(void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL);
}
/*
* Pull off the next component of path up to but not including
* any array subscripts.
*/
for (cp = name; *cp && *cp != '[' && *cp != '/'; cp++)
/* Nothing */;
csave = *cp;
*cp = '\0';
cp = name;
he = HashLookOnly(&def->cd_idHash, name);
*cp = csave;
if (he == NULL || HashGetValue(he) == NULL)
return;
{
/*
* Pull off the next component of path up to but not including
* any array subscripts.
* NOTE: This should check the array bounds and only remove
* array components that are expected, not array components
* embedded in the name.
*/
for (; *cp && *cp != '[' && *cp != '/'; cp++)
/* Nothing */;
csave = *cp;
*cp = '\0';
he = HashLookOnly(&def->cd_idHash, name);
*cp = csave;
if (he == NULL || HashGetValue(he) == NULL)
return;
}
use = (CellUse *) HashGetValue(he);
def = use->cu_def;
@ -335,7 +346,10 @@ DBTreeFindUse(name, use, scx)
/* Ensure that the leaf cell is read in */
def = use->cu_def;
if ((def->cd_flags & CDAVAILABLE) == 0)
(void) DBCellRead(def, (char *) NULL, TRUE, NULL);
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
(void) DBCellRead(def, (char *) NULL, dereference, NULL);
}
scx->scx_use = use;
}

View File

@ -66,11 +66,23 @@ DBPropPut(cellDef, name, value)
HashInit( (HashTable *) cellDef->cd_props, 8, 0);
}
htab = (HashTable *) cellDef->cd_props;
/* Special handling of FIXED_BBOX, which uses CDFIXEDBBOX as a quick lookup */
if (!strcmp(name, "FIXED_BBOX"))
{
if (value == (ClientData)NULL)
cellDef->cd_flags &= ~CDFIXEDBBOX;
else
cellDef->cd_flags |= CDFIXEDBBOX;
}
entry = HashFind(htab, name);
oldvalue = (char *)HashGetValue(entry);
if (oldvalue != NULL) freeMagic(oldvalue);
HashSetValue(entry, value);
if (value == (ClientData)NULL)
HashRemove(htab, name);
else
HashSetValue(entry, value);
}
/* ----------------------------------------------------------------------------
@ -202,4 +214,8 @@ DBPropClearAll(cellDef)
HashKill(htab);
freeMagic((char *) htab);
cellDef->cd_props = (ClientData) NULL;
/* Since CDFIXEDBBOX requires a FIXED_BBOX property, clearing all */
/* properties necessarily means this flag must be clear. */
cellDef->cd_flags &= ~CDFIXEDBBOX;
}

View File

@ -141,7 +141,7 @@ DBTechInitPlane()
for (dpp = dbTechDefaultPlanes; dpp->dp_names; dpp++)
{
cp = dbTechNameAdd(dpp->dp_names, (ClientData) dpp->dp_plane,
&dbPlaneNameLists);
&dbPlaneNameLists, FALSE);
if (cp == NULL)
{
TxError("DBTechInit: can't add plane names %s\n", dpp->dp_names);
@ -224,7 +224,7 @@ DBTechInitType()
for (dtp = dbTechDefaultTypes; dtp->dt_names; dtp++)
{
cp = dbTechNameAdd(dtp->dt_names, (ClientData) dtp->dt_type,
&dbTypeNameLists);
&dbTypeNameLists, FALSE);
if (cp == NULL)
{
TxError("DBTechInit: can't add type names %s\n", dtp->dt_names);
@ -283,7 +283,7 @@ DBTechAddPlane(sectionName, argc, argv)
return FALSE;
}
cp = dbTechNameAdd(argv[0], (ClientData) DBNumPlanes, &dbPlaneNameLists);
cp = dbTechNameAdd(argv[0], (ClientData) DBNumPlanes, &dbPlaneNameLists, FALSE);
if (cp == NULL)
return FALSE;
DBPlaneLongNameTbl[DBNumPlanes++] = cp;
@ -315,7 +315,7 @@ DBTechAddNameToType(newname, ttype, canonical)
{
char *cp;
cp = dbTechNameAdd(newname, (ClientData) ttype, &dbTypeNameLists);
cp = dbTechNameAdd(newname, (ClientData) ttype, &dbTypeNameLists, TRUE);
if (canonical)
DBTypeLongNameTbl[ttype] = cp;
}
@ -455,7 +455,7 @@ DBTechAddType(sectionName, argc, argv)
}
else
{
cp = dbTechNameAdd(argv[1], (ClientData) DBNumTypes, &dbTypeNameLists);
cp = dbTechNameAdd(argv[1], (ClientData) DBNumTypes, &dbTypeNameLists, FALSE);
if (cp == NULL)
return FALSE;
@ -513,7 +513,7 @@ dbTechNewStackedType(type1, type2)
}
sprintf(buf, "%s+%s", DBTypeShortName(type1), DBTypeShortName(type2));
cp = dbTechNameAdd(buf, (ClientData) DBNumTypes, &dbTypeNameLists);
cp = dbTechNameAdd(buf, (ClientData) DBNumTypes, &dbTypeNameLists, FALSE);
if (cp == NULL)
{
TechError("Couldn't generate new stacking type %s\n", buf);
@ -730,10 +730,11 @@ dbTechNameLookup(str, table)
*/
char *
dbTechNameAdd(name, cdata, ptable)
dbTechNameAdd(name, cdata, ptable, alias)
char *name; /* Comma-separated list of names to be added */
ClientData cdata; /* Value to be stored with each name above */
NameList *ptable; /* Table to which we will add names */
int alias; /* 1 if this is an alias (never make primary) */
{
char *cp;
char onename[BUFSIZ];
@ -769,7 +770,7 @@ dbTechNameAdd(name, cdata, ptable)
}
}
if (primary)
if (primary && (alias == 0))
primary->sn_primary = TRUE;
return (first);
}

View File

@ -126,6 +126,8 @@ DBFixMismatch()
while (mismatch != NULL)
{
bool dereference;
/* Be careful to remove the front element from the mismatch
* list before processing it, because while processing it we
* may add new elements to the list.
@ -137,7 +139,8 @@ DBFixMismatch()
mismatch = mismatch->mm_next;
if (cellDef->cd_flags & CDPROCESSED) continue;
(void) DBCellRead(cellDef, (char *) NULL, TRUE, NULL);
dereference = (cellDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
(void) DBCellRead(cellDef, (char *) NULL, TRUE, dereference, NULL);
/* Jimmy up the cell's current bounding box, so the following
* procedure call will absolutely and positively know that
@ -267,6 +270,16 @@ dbStampFunc(cellDef)
* processing. When DBFixMismatch is called, it will notify
* the design-rule checker to recheck both wrongArea, and
* the cell's eventual correct area.
*
* This routine has been modified from a poor implementation. Previously
* the parent def of all uses of the cell being checked would be marked
* for a stamp mismatch check. However, when reading a cell with large
* numbers of instances, the list of instances would be parsed for every
* instance added, leading to an O(N^2) computation. Routine DBStampMismatch()
* has been broken into two parts. DBStampMismatch() only records the
* area to be checked. DBFlagMismatches() looks at the parents of each
* celldef only once, after all instances have been read.
*
* ----------------------------------------------------------------------------
*/
@ -278,16 +291,27 @@ DBStampMismatch(cellDef, wrongArea)
*/
{
Mismatch *mm;
CellUse *parentUse;
mm = (Mismatch *) mallocMagic((unsigned) (sizeof (Mismatch)));
mm->mm_cellDef = cellDef;
mm->mm_oldArea = *wrongArea;
mm->mm_next = mismatch;
mismatch = mm;
}
for (parentUse = cellDef->cd_parents; parentUse != NULL;
parentUse = parentUse->cu_nextuse)
/*
* ----------------------------------------------------------------------------
* ----------------------------------------------------------------------------
*/
void
DBFlagMismatches(checkDef)
CellDef *checkDef;
{
CellUse *parentUse;
for (parentUse = checkDef->cd_parents; parentUse != NULL;
parentUse = parentUse->cu_nextuse)
{
if (parentUse->cu_parent == NULL) continue;
parentUse->cu_parent->cd_flags |= CDSTAMPSCHANGED;

View File

@ -396,6 +396,9 @@ typedef struct celldef
* with the option "gds readonly true".
* CDVISITED indicates that at least one instance of the cell was
* already output during a file write.
* CDDEREFERENCE is a flag indicating that when loading or expanding
* children of a cell, the path should be ignored and the cell
* path should be searched for the location.
*/
#define CDAVAILABLE 0x0001
@ -413,6 +416,7 @@ typedef struct celldef
#define CDPROCESSEDGDS 0x1000
#define CDVENDORGDS 0x2000
#define CDVISITED 0x4000
#define CDDEREFERENCE 0x8000
/*
* Description of an array.

View File

@ -199,6 +199,7 @@ extern void DBUndoPutLabel();
extern void DBUndoEraseLabel();
extern void DBUndoCellUse();
extern void DBStampMismatch();
extern void DBFlagMismatches();
extern void DBTechAddNameToType();
extern void dbComputeBbox();

View File

@ -38,7 +38,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
* Standard DBWind command set
*/
extern void CmdAddPath(), CmdArray();
extern void CmdAddPath(), CmdAntennaCheck(), CmdArray();
extern void CmdBox(), CmdCellname(), CmdClockwise();
extern void CmdContact(), CmdCopy(), CmdCorner();
extern void CmdCrash(), CmdCrosshair();
@ -222,6 +222,9 @@ DBWInitCommands()
WindAddCommand(DBWclientID,
"addpath [path] append to current search path",
CmdAddPath, FALSE);
WindAddCommand(DBWclientID,
"antennacheck [path] check for antenna violations",
CmdAntennaCheck, FALSE);
WindAddCommand(DBWclientID,
"array xsize ysize OR\n"
"array xlo xhi ylo yhi\n"

View File

@ -418,7 +418,7 @@ DBWredisplay(w, rootArea, clipArea)
/* Set style information beforehand */
GrSetStuff(STYLE_LABEL);
(void) DBTreeSrLabels(&scontext, &DBAllTypeBits, bitMask,
(TerminalPath *) NULL, TF_LABEL_DISPLAY,
(TerminalPath *) NULL, TF_LABEL_DISPLAY | TF_LABEL_ATTACH,
dbwLabelFunc, (ClientData) NULL);
GrClipTo(&rootClip);
}

View File

@ -127,10 +127,10 @@ DBWcreate(window, argc, argv)
window->w_clientData = (ClientData) crec;
if (argc > 0)
DBWloadWindow(window, argv[0], TRUE, FALSE);
DBWloadWindow(window, argv[0], TRUE, FALSE, FALSE);
else if (ToolGetBox(&boxDef, &box))
{
DBWloadWindow(window, boxDef->cd_name, TRUE, FALSE);
DBWloadWindow(window, boxDef->cd_name, TRUE, FALSE, FALSE);
/* Zoom in on the box, leaving a 10% border or at least 2 units
* on each side.
@ -148,7 +148,7 @@ DBWcreate(window, argc, argv)
}
else
{
DBWloadWindow(window, (char *) NULL, TRUE, FALSE);
DBWloadWindow(window, (char *) NULL, TRUE, FALSE, FALSE);
}
return TRUE;
}
@ -249,7 +249,7 @@ dbwReloadFunc(w, name)
MagWindow *w;
char *name;
{
DBWloadWindow(w, name, TRUE, FALSE);
DBWloadWindow(w, name, TRUE, FALSE, FALSE);
return (0);
}
@ -274,26 +274,29 @@ dbwReloadFunc(w, name)
* cell doesn't change.
*
* If "expand" is true, unexpands all subcells of the root cell.
* If "dereference" is true, ignore path reference in the input file.
*
* ----------------------------------------------------------------------------
*/
void
DBWloadWindow(window, name, ignoreTech, expand)
DBWloadWindow(window, name, ignoreTech, expand, dereference)
MagWindow *window; /* Identifies window to which cell is to be bound */
char *name; /* Name of new cell to be bound to this window */
bool ignoreTech; /* If FALSE, indicates that the technology of
* the layout must match the current technology.
*/
bool expand; /* Indicates whether or not to expand the cell */
bool dereference; /* If TRUE, ignore path references in the input */
{
CellDef *newEditDef;
CellDef *newEditDef, *deleteDef;
CellUse *newEditUse;
void DisplayWindow();
int res, newEdit, error_val;
int xadd, yadd;
Rect loadBox;
char *rootname;
bool isUnnamed;
int UnexpandFunc(); /* forward declaration */
loadBox.r_xbot = loadBox.r_ybot = 0;
@ -303,6 +306,19 @@ DBWloadWindow(window, name, ignoreTech, expand)
newEdit = !WindSearch((WindClient) DBWclientID, (ClientData) NULL,
(Rect *) NULL, dbwLoadFunc, (ClientData) window);
/* The (UNNAMED) cell generally gets in the way, so delete it if */
/* any new cell is loaded and (UNNAMED) has no contents. */
if (window->w_surfaceID == (ClientData)NULL)
deleteDef = NULL;
else
{
deleteDef = ((CellUse *)window->w_surfaceID)->cu_def;
if (strcmp(deleteDef->cd_name, "(UNNAMED)") ||
deleteDef->cd_flags & (CDMODIFIED|CDBOXESCHANGED|CDSTAMPSCHANGED))
deleteDef = NULL;
}
if ((name == (char *) NULL) || (name[0] == '\0'))
{
/*
@ -383,7 +399,9 @@ DBWloadWindow(window, name, ignoreTech, expand)
if (newEditDef == (CellDef *) NULL)
newEditDef = DBCellNewDef(rootname, (char *) NULL);
if (!DBCellRead(newEditDef, name, ignoreTech, &error_val))
if (dereference) newEditDef->cd_flags |= CDDEREFERENCE;
if (!DBCellRead(newEditDef, name, ignoreTech, dereference, &error_val))
{
if (error_val == ENOENT)
{
@ -499,6 +517,12 @@ DBWloadWindow(window, name, ignoreTech, expand)
if (newEdit)
DBWAreaChanged(newEditDef, &newEditDef->cd_bbox, DBW_ALLWINDOWS,
&DBAllButSpaceBits);
/* If the cell before loading was (UNNAMED) and it was */
/* never modified, then delete it now. */
if (deleteDef != NULL)
DBCellDelete(deleteDef->cd_name, TRUE);
}
/* This function is called for each cell whose expansion status changed.

View File

@ -1,98 +0,0 @@
# defs.mak.in --
# source file for autoconf-generated "defs.mak" for magic
# defs.mak. Generated from defs.mak.in by configure.
# Feel free to change the values in here to suit your needs.
# Be aware that running scripts/configure again will overwrite
# any changes!
SHELL = /bin/sh
prefix = /usr/local
exec_prefix = ${prefix}
bindir = ${exec_prefix}/bin
libdir = ${exec_prefix}/lib
mandir = ${prefix}/share/man
SCRIPTS = ${MAGICDIR}/scripts
INSTALL = /bin/install -c
INSTALL_PROGRAM = ${INSTALL}
INSTALL_DATA = ${INSTALL} -m 644
INSTALL_SCRIPT = ${INSTALL}
# Override standard "make" target when compiling under TCL
ALL_TARGET = tcl
INSTALL_TARGET = install-tcl
# Change libdir to install in a different place
BINDIR = ${bindir}
MANDIR = ${mandir}
LIBDIR = ${libdir}
SYSDIR = ${libdir}/magic/sys
SCMDIR = ${libdir}/magic/scm
TCLDIR = ${libdir}/magic/tcl
MAIN_EXTRA_LIBS = ${MAGICDIR}/ext2sim/libext2sim.o ${MAGICDIR}/ext2spice/libext2spice.o ${MAGICDIR}/calma/libcalma.o ${MAGICDIR}/cif/libcif.o ${MAGICDIR}/plot/libplot.o ${MAGICDIR}/lef/liblef.o ${MAGICDIR}/extflat/libextflat.o ${MAGICDIR}/garouter/libgarouter.o ${MAGICDIR}/mzrouter/libmzrouter.o ${MAGICDIR}/router/librouter.o ${MAGICDIR}/irouter/libirouter.o ${MAGICDIR}/grouter/libgrouter.o ${MAGICDIR}/gcr/libgcr.o ${MAGICDIR}/tcltk/libtcltk.o
LD_EXTRA_LIBS =
LD_SHARED =
TOP_EXTRA_LIBS =
SUB_EXTRA_LIBS =
MODULES += ext2sim ext2spice calma cif plot lef garouter grouter irouter mzrouter router gcr tcltk
UNUSED_MODULES += readline lisp
PROGRAMS += net2ir tcltk
INSTALL_CAD_DIRS += graphics tcltk
RM = rm -f
CP = cp
AR = ar
ARFLAGS = crv
LINK = ld -r
LD = /bin/ld
M4 = /bin/m4
MCPP = ${MAGICDIR}/scripts/preproc.py
SCPP = gcc -E -x c
RANLIB = ranlib
SHDLIB_EXT = .so
LDDL_FLAGS = ${LDFLAGS} -shared -Wl,-soname,$@ -Wl,--version-script=${MAGICDIR}/magic/symbol.map
LD_RUN_PATH =
LIB_SPECS = -L/usr/lib64 -ltkstub8.6 -L/usr/lib64 -ltclstub8.6
LIB_SPECS_NOSTUB = -L/usr/lib64 -ltk8.6 -L/usr/lib64 -ltcl8.6
WISH_EXE = /usr/bin/wish
TCL_LIB_DIR = /usr/lib
MAGIC_VERSION = 8.2
MAGIC_REVISION = 101
CC = gcc
CPP = gcc -E
CXX = g++
CPPFLAGS = -I. -I${MAGICDIR}
DFLAGS = -DCAD_DIR=\"${LIBDIR}\" -DBIN_DIR=\"${BINDIR}\" -DTCL_DIR=\"${TCLDIR}\" -DUSE_TCL_STUBS -DUSE_TK_STUBS -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DMAGIC_VERSION=\"8.2\" -DMAGIC_REVISION=\"101\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_SYS_MMAN_H=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_PATHS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DFILE_LOCKS=1 -DCALMA_MODULE=1 -DCIF_MODULE=1 -DPLOT_MODULE=1 -DLEF_MODULE=1 -DROUTE_MODULE=1 -DUSE_NEW_MACROS=1 -DHAVE_LIBGL=1 -DHAVE_LIBGLU=1 -DVECTOR_FONTS=1 -DHAVE_LIBCAIRO=1 -DMAGIC_WRAPPER=1 -DTHREE_D=1 -Dlinux=1 -DSYSV=1 -DISC=1 -DGCORE=\"/bin/gcore\"
DFLAGS += -DSHDLIB_EXT=\".so\" -DNDEBUG
DFLAGS_NOSTUB = -DCAD_DIR=\"${LIBDIR}\" -DBIN_DIR=\"${BINDIR}\" -DTCL_DIR=\"${TCLDIR}\" -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DMAGIC_VERSION=\"8.2\" -DMAGIC_REVISION=\"101\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DSIZEOF_VOID_P=8 -DSIZEOF_UNSIGNED_INT=4 -DSIZEOF_UNSIGNED_LONG=8 -DSIZEOF_UNSIGNED_LONG_LONG=8 -DSTDC_HEADERS=1 -DHAVE_SETENV=1 -DHAVE_PUTENV=1 -DHAVE_SYS_MMAN_H=1 -DHAVE_DIRENT_H=1 -DHAVE_LIMITS_H=1 -DHAVE_PATHS_H=1 -DHAVE_VA_COPY=1 -DHAVE___VA_COPY=1 -DFILE_LOCKS=1 -DCALMA_MODULE=1 -DCIF_MODULE=1 -DPLOT_MODULE=1 -DLEF_MODULE=1 -DROUTE_MODULE=1 -DUSE_NEW_MACROS=1 -DHAVE_LIBGL=1 -DHAVE_LIBGLU=1 -DVECTOR_FONTS=1 -DHAVE_LIBCAIRO=1 -DMAGIC_WRAPPER=1 -DTHREE_D=1 -Dlinux=1 -DSYSV=1 -DISC=1 -DGCORE=\"/bin/gcore\"
DFLAGS_NOSTUB += -DSHDLIB_EXT=\".so\" -DNDEBUG
CFLAGS = -g -m64 -fPIC -Wimplicit-int -fPIC
READLINE_DEFS =
READLINE_LIBS =
DEPEND_FILE = Depend
DEPEND_FLAG = -MM
EXEEXT =
GR_CFLAGS =
GR_DFLAGS = -DX11 -DXLIB -DOGL -DCAIRO -DNDEBUG
GR_LIBS = -lX11 -lGL -lGLU -lXi -lXmu -lXext -lm -lcairo -lfontconfig -lfreetype -lstdc++ ${X11_LDFLAGS}
GR_SRCS = ${TK_SRCS} ${TOGL_SRCS} ${TCAIRO_SRCS} ${TKCOMMON_SRCS}
GR_HELPER_SRCS =
GR_HELPER_PROG =
OA =
OA_LIBS =
DEPSRCS = ${SRCS}
OBJS = ${SRCS:.c=.o} ${CXXSRCS:.cpp=.o}
LIB_OBJS = ${LIB_SRCS:.c=.o}
CLEANS = ${OBJS} ${LIB_OBJS} lib${MODULE}.a lib${MODULE}.o ${MODULE}

View File

@ -2,7 +2,7 @@ MAGICDIR = ../..
include $(MAGICDIR)/defs.mak
HTML_INSTDIR=$(LIBDIR)/magic/doc/html
HTML_INSTDIR=$(INSTALL_LIBDIR)/magic/doc/html
install: $(DESTDIR)${HTML_INSTDIR}
tar cf - . | (cd $(DESTDIR)${HTML_INSTDIR}; tar xf - )

View File

@ -68,7 +68,7 @@ Define or print a macro called char
Buttons are treated just like keys for the purpose of
defining macros. While the official names for buttons
in <TT>keysymdef.h</TT> are "<B>XK_Pointer_Button_1</B>",
in <TT>keysymdef.h</TT> are "<B>XK_Pointer_Button1</B>",
etc., the <B>macro</B> command accepts the abbreviated
forms <B>Button1</B>, and so forth. <P>

View File

@ -3,7 +3,7 @@ MAGICDIR = ../..
include $(MAGICDIR)/defs.mak
PS_SRCDIR=../psfiles
PS_INSTDIR=$(LIBDIR)/magic/doc
PS_INSTDIR=$(INSTALL_LIBDIR)/magic/doc
.SUFFIXES: .dvi .tex .ps

View File

@ -15,36 +15,36 @@ EQN=eqn -Ppsc
include ${MAGICDIR}/defs.mak
MANFILES = \
$(DESTDIR)${MANDIR}/man1/ext2spice.1 \
$(DESTDIR)${MANDIR}/man1/extcheck.1 \
$(DESTDIR)${MANDIR}/man1/ext2sim.1 \
$(DESTDIR)${MANDIR}/man1/magic.1 \
$(DESTDIR)${MANDIR}/man5/cmap.5 \
$(DESTDIR)${MANDIR}/man5/displays.5 \
$(DESTDIR)${MANDIR}/man5/dlys.5 \
$(DESTDIR)${MANDIR}/man5/dstyle.5 \
$(DESTDIR)${MANDIR}/man5/ext.5 \
$(DESTDIR)${MANDIR}/man5/glyphs.5 \
$(DESTDIR)${MANDIR}/man5/mag.5 \
$(DESTDIR)${MANDIR}/man5/net.5 \
$(DESTDIR)${MANDIR}/man5/sim.5
$(DESTDIR)${INSTALL_MANDIR}/man1/ext2spice.1 \
$(DESTDIR)${INSTALL_MANDIR}/man1/extcheck.1 \
$(DESTDIR)${INSTALL_MANDIR}/man1/ext2sim.1 \
$(DESTDIR)${INSTALL_MANDIR}/man1/magic.1 \
$(DESTDIR)${INSTALL_MANDIR}/man5/cmap.5 \
$(DESTDIR)${INSTALL_MANDIR}/man5/displays.5 \
$(DESTDIR)${INSTALL_MANDIR}/man5/dlys.5 \
$(DESTDIR)${INSTALL_MANDIR}/man5/dstyle.5 \
$(DESTDIR)${INSTALL_MANDIR}/man5/ext.5 \
$(DESTDIR)${INSTALL_MANDIR}/man5/glyphs.5 \
$(DESTDIR)${INSTALL_MANDIR}/man5/mag.5 \
$(DESTDIR)${INSTALL_MANDIR}/man5/net.5 \
$(DESTDIR)${INSTALL_MANDIR}/man5/sim.5
install: ${MANFILES}
$(DESTDIR)${MANDIR}:
${SCRIPTS}/mkdirs $(DESTDIR)${MANDIR}
$(DESTDIR)${INSTALL_MANDIR}:
${SCRIPTS}/mkdirs $(DESTDIR)${INSTALL_MANDIR}
$(DESTDIR)${MANDIR}/man1: $(DESTDIR)${MANDIR}
${SCRIPTS}/mkdirs $(DESTDIR)${MANDIR}/man1
$(DESTDIR)${INSTALL_MANDIR}/man1: $(DESTDIR)${INSTALL_MANDIR}
${SCRIPTS}/mkdirs $(DESTDIR)${INSTALL_MANDIR}/man1
$(DESTDIR)${MANDIR}/man1/%: % $(DESTDIR)${MANDIR}/man1
${CP} $* $(DESTDIR)${MANDIR}/man1/$*
$(DESTDIR)${INSTALL_MANDIR}/man1/%: % $(DESTDIR)${INSTALL_MANDIR}/man1
${CP} $* $(DESTDIR)${INSTALL_MANDIR}/man1/$*
$(DESTDIR)${MANDIR}/man5: $(DESTDIR)${MANDIR}
${SCRIPTS}/mkdirs $(DESTDIR)${MANDIR}/man5
$(DESTDIR)${INSTALL_MANDIR}/man5: $(DESTDIR)${INSTALL_MANDIR}
${SCRIPTS}/mkdirs $(DESTDIR)${INSTALL_MANDIR}/man5
$(DESTDIR)${MANDIR}/man5/%: % $(DESTDIR)${MANDIR}/man5
${CP} $* $(DESTDIR)${MANDIR}/man5/$*
$(DESTDIR)${INSTALL_MANDIR}/man5/%: % $(DESTDIR)${INSTALL_MANDIR}/man5
${CP} $* $(DESTDIR)${INSTALL_MANDIR}/man5/$*
mans:
${SCRIPTS}/printmans "${TROFF} ${MANMACS} -" *.1 *.5

View File

@ -6,7 +6,7 @@ MAGICDIR = ../..
include ${MAGICDIR}/defs.mak
TUTDIR = ${LIBDIR}/magic/tutorial
TUTDIR = ${INSTALL_LIBDIR}/magic/tutorial
TUTFILES= m3a.mag maint2a.mag tut1.mag \
tut2a.mag tut2b.mag tut2c.mag tut2d.mag \

View File

@ -46,7 +46,7 @@ static DRCCookie drcArrayCookie = {
0, 0, 0, 0,
{ 0 }, { 0 },
0, 0, 0,
"This layer can't abut or partially overlap between array elements",
DRC_ARRAY_OVERLAP_TAG,
(DRCCookie *) NULL
};

View File

@ -47,7 +47,7 @@ static DRCCookie drcOverlapCookie = {
0, 0, 0, 0,
{ 0 }, { 0 },
0, 0, 0,
"Can't overlap those layers",
DRC_OVERLAP_TAG,
(DRCCookie *) NULL
};
@ -484,6 +484,7 @@ drcTile (tile, arg)
int edgeX = LEFT(tile);
firsttile = TRUE;
mrd = NULL;
for (tpleft = BL(tile); BOTTOM(tpleft) < top; tpleft = RT(tpleft))
{
/* Get the tile types to the left and right of the edge */
@ -554,8 +555,6 @@ drcTile (tile, arg)
mrd = drcCanonicalMaxwidth(tpleft, GEO_WEST, arg, cptr);
else if (firsttile)
mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr);
else
mrd = NULL;
if (!trigpending || (DRCCurStyle->DRCFlags
& DRC_FLAGS_WIDEWIDTH_NONINCLUSIVE))
cptr->drcc_dist--;
@ -610,7 +609,6 @@ drcTile (tile, arg)
drcCheckMaxwidth(tile, arg, cptr);
continue;
}
else if (!triggered) mrd = NULL;
if (cptr->drcc_flags & DRC_RECTSIZE)
{
@ -625,6 +623,7 @@ drcTile (tile, arg)
result = 0;
arg->dCD_radial = 0;
arg->dCD_entries = 0;
do {
if (triggered)
{
@ -870,6 +869,7 @@ checkbottom:
/* Go right across bottom of tile */
firsttile = TRUE;
mrd = NULL;
for (tpbot = LB(tile); LEFT(tpbot) < right; tpbot = TR(tpbot))
{
/* Get the tile types to the top and bottom of the edge */
@ -936,8 +936,6 @@ checkbottom:
mrd = drcCanonicalMaxwidth(tpbot, GEO_SOUTH, arg, cptr);
else if (firsttile)
mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr);
else
mrd = NULL;
if (!trigpending || (DRCCurStyle->DRCFlags
& DRC_FLAGS_WIDEWIDTH_NONINCLUSIVE))
cptr->drcc_dist--;
@ -992,10 +990,10 @@ checkbottom:
if (trigpending) cptr = cptr->drcc_next;
continue;
}
else if (!triggered) mrd = NULL;
result = 0;
arg->dCD_radial = 0;
arg->dCD_entries = 0;
do {
if (triggered)
{

View File

@ -48,7 +48,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "utils/malloc.h"
#include "utils/utils.h"
extern char *drcWhyDup();
extern int drcCifTile();
extern int areaCifCheck();
extern void drcCheckCifMaxwidth();
@ -67,9 +66,10 @@ extern bool DRCForceReload;
TileTypeBitMask drcCifGenLayers;
DRCCookie *drcCifRules[MAXCIFLAYERS][2];
DRCCookie *drcCifCur=NULL;
DRCCookie *drcCifCur = NULL;
int drcCifValid = FALSE;
int beenWarned;
bool beenWarned = FALSE;
char *drcNeedStyle = NULL;
#define DRC_CIF_SPACE 0
#define DRC_CIF_SOLID 1
@ -112,14 +112,12 @@ drcCifSetStyle(argc, argv)
{
if (!strcmp(new->cs_name, argv[1]))
{
drcNeedStyle = new->cs_name;
DRCForceReload = TRUE;
if (!strcmp(new->cs_name, CIFCurStyle->cs_name))
drcCifStyle = CIFCurStyle;
else
{
TechError("DRC cif extensions are not enabled.\n\t"
"Use \"cif ostyle %s\" to enable them.\n",
new->cs_name);
drcCifStyle = NULL;
beenWarned = TRUE; /* post no more error messages */
}
@ -170,7 +168,7 @@ drcCifWidth(argc, argv)
char *layername = argv[1];
int scalefactor;
int centidistance = atoi(argv[2]);
char *why = drcWhyDup(argv[3]);
int why = drcWhyCreate(argv[3]);
TileTypeBitMask set, setC, tmp1;
int thislayer = -1;
DRCCookie *dpnew,*dpnext;
@ -200,7 +198,7 @@ drcCifWidth(argc, argv)
dpnext = drcCifRules[thislayer][DRC_CIF_SPACE];
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
drcAssign(dpnew, centidistance, dpnext, &CIFSolidBits,
drcCifAssign(dpnew, centidistance, dpnext, &CIFSolidBits,
&CIFSolidBits, why, centidistance,
DRC_FORWARD, thislayer, 0);
drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew;
@ -229,7 +227,7 @@ drcCifSpacing(argc, argv)
char *argv[];
{
char *adjacency = argv[4];
char *why = drcWhyDup(argv[5]);
int why = drcWhyCreate(argv[5]);
DRCCookie *dpnext, *dpnew;
int needReverse = FALSE;
TileType i, j;
@ -292,7 +290,7 @@ drcCifSpacing(argc, argv)
centidistance *= drcCifStyle->cs_expander; // BSI
dpnext = drcCifRules[layer[0]][DRC_CIF_SOLID];
dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie));
drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits,
drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits,
&cmask, why, centidistance, DRC_FORWARD, layer[1], 0);
drcCifRules[layer[0]][DRC_CIF_SOLID] = dpnew;
if (needReverse) dpnew->drcc_flags |= DRC_BOTHCORNERS;
@ -300,7 +298,7 @@ drcCifSpacing(argc, argv)
// Add rule in reverse direction
dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE];
dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie));
drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits,
drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits,
&cmask, why, centidistance, DRC_REVERSE, layer[1], 0);
drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew;
@ -312,14 +310,14 @@ drcCifSpacing(argc, argv)
dpnew->drcc_flags |= DRC_BOTHCORNERS;
dpnext = drcCifRules[layer[1]][DRC_CIF_SOLID];
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask,
drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask,
why, centidistance, DRC_FORWARD|DRC_BOTHCORNERS, layer[0], 0);
drcCifRules[layer[1]][DRC_CIF_SOLID] = dpnew;
// Add rule in reverse direction
dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE];
dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie));
drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask,
drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask,
why, centidistance, DRC_REVERSE|DRC_BOTHCORNERS, layer[0], 0);
drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew;
@ -327,14 +325,14 @@ drcCifSpacing(argc, argv)
{
dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE];
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits,
drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits,
&cmask, why, centidistance, DRC_REVERSE | DRC_BOTHCORNERS,
layer[0], 0);
drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew;
dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE];
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask,
drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask,
why, centidistance, DRC_REVERSE | DRC_BOTHCORNERS,
layer[1], 0);
drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew;
@ -345,13 +343,13 @@ drcCifSpacing(argc, argv)
{
dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE];
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
drcAssign(dpnew, scalefactor, dpnext, &DBSpaceBits, &DBZeroTypeBits,
drcCifAssign(dpnew, scalefactor, dpnext, &DBSpaceBits, &DBZeroTypeBits,
why, scalefactor, DRC_FORWARD, layer[0], 0);
drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew;
dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE];
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
drcAssign(dpnew, scalefactor, dpnext, &DBSpaceBits, &DBZeroTypeBits,
drcCifAssign(dpnew, scalefactor, dpnext, &DBSpaceBits, &DBZeroTypeBits,
why, scalefactor, DRC_FORWARD, layer[1], 0);
drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew;
}
@ -501,9 +499,37 @@ drcCifCheck(arg)
int scale;
int i,j;
int oldTiles;
CIFStyle *CIFSaveStyle = NULL;
if (drcCifValid == FALSE) return;
else if (CIFCurStyle != drcCifStyle) return;
if (CIFCurStyle != drcCifStyle)
{
if (drcNeedStyle == NULL) return;
CIFSaveStyle = CIFCurStyle;
if (drcCifStyle == NULL)
{
TxPrintf("Loading DRC CIF style.\n");
CIFCurStyle = NULL;
CIFLoadStyle(drcNeedStyle);
if (drcCifValid != FALSE)
CIFCurStyle = CIFSaveStyle;
else
drcCifStyle = CIFCurStyle;
}
if (drcCifStyle == NULL)
{
TxError("Error: Failed to load CIF DRC style.\n");
return;
}
CIFCurStyle = drcCifStyle;
}
if (drcCifValid == FALSE)
{
if (CIFSaveStyle != NULL)
CIFCurStyle = CIFSaveStyle;
return;
}
scale = drcCifStyle->cs_scaleFactor;
cifrect = *checkRect;
@ -534,6 +560,9 @@ drcCifCheck(arg)
}
arg->dCD_rect = checkRect;
DRCstatCifTiles += DRCstatTiles - oldTiles;
/* Put it back the way you found it */
if (CIFSaveStyle != NULL) CIFCurStyle = CIFSaveStyle;
}
/*
@ -1035,7 +1064,7 @@ drcCifArea(argc, argv)
char *layers = argv[1];
int centiarea = atoi(argv[2]);
int centihorizon = atoi(argv[3]);
char *why = drcWhyDup(argv[4]);
int why = drcWhyCreate(argv[4]);
TileTypeBitMask set, setC, tmp1;
DRCCookie *dpnext, *dpnew;
TileType i, j;
@ -1066,7 +1095,7 @@ drcCifArea(argc, argv)
centiarea *= (drcCifStyle->cs_expander * drcCifStyle->cs_expander);
dpnext = drcCifRules[thislayer][DRC_CIF_SPACE];
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
drcAssign(dpnew, centihorizon, dpnext, &CIFSolidBits, &CIFSolidBits,
drcCifAssign(dpnew, centihorizon, dpnext, &CIFSolidBits, &CIFSolidBits,
why, centiarea, DRC_AREA | DRC_FORWARD, thislayer, 0);
drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew;
@ -1096,7 +1125,7 @@ drcCifMaxwidth(argc, argv)
char *layers = argv[1];
int centidistance = atoi(argv[2]);
char *bends = argv[3];
char *why = drcWhyDup(argv[4]);
int why = drcWhyCreate(argv[4]);
TileTypeBitMask set, setC, tmp1;
DRCCookie *dpnext, *dpnew;
TileType i, j;
@ -1136,11 +1165,10 @@ drcCifMaxwidth(argc, argv)
centidistance *= drcCifStyle->cs_expander; // BSI
dpnext = drcCifRules[thislayer][DRC_CIF_SPACE];
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
drcAssign(dpnew, centidistance, dpnext, &CIFSolidBits, &CIFSolidBits,
drcCifAssign(dpnew, centidistance, dpnext, &CIFSolidBits, &CIFSolidBits,
why, centidistance, DRC_MAXWIDTH | bend, thislayer, 0);
drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew;
return ((centidistance+scalefactor-1)/scalefactor);
}

View File

@ -69,9 +69,8 @@ TileType DRCErrorType; /* Type of error tile to paint. */
/* Used by drcPrintError: */
HashTable DRCErrorTable; /* Hash table used to eliminate duplicate
* error strings.
*/
int *DRCErrorList; /* List of DRC error type counts */
HashTable DRCErrorTable; /* Table of DRC errors and geometry */
/* Global variables used by all DRC modules to record statistics.
* For each statistic we keep two values, the count since stats
@ -183,11 +182,12 @@ drcSubstitute (cptr)
DRCCookie * cptr; /* Design rule violated */
{
static char *why_out = NULL;
char *whyptr = cptr->drcc_why, *sptr, *wptr;
char *whyptr, *sptr, *wptr;
int subscnt = 0, whylen;
float oscale, value;
extern float CIFGetOutputScale();
whyptr = DRCCurStyle->DRCWhyList[cptr->drcc_tag];
while ((sptr = strchr(whyptr, '%')) != NULL)
{
subscnt++;
@ -195,7 +195,7 @@ drcSubstitute (cptr)
}
if (subscnt == 0) return whyptr; /* No substitutions */
whyptr = cptr->drcc_why;
whyptr = DRCCurStyle->DRCWhyList[cptr->drcc_tag];
whylen = strlen(whyptr) + 20 * subscnt;
if (why_out != NULL) freeMagic(why_out);
why_out = (char *)mallocMagic(whylen * sizeof(char));
@ -256,7 +256,7 @@ drcSubstitute (cptr)
*
* Side effects:
* DRCErrorCount is incremented. The text associated with
* the error is entered into DRCErrorTable, and, if this is
* the error is entered into DRCErrorList, and, if this is
* the first time that entry has been seen, then the error
* text is printed. If the area parameter is non-NULL, then
* only errors intersecting that area are considered.
@ -279,12 +279,11 @@ drcPrintError (celldef, rect, cptr, scx)
area = &scx->scx_area;
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
DRCErrorCount += 1;
h = HashFind(&DRCErrorTable, cptr->drcc_why);
i = (spointertype) HashGetValue(h);
i = DRCErrorList[cptr->drcc_tag];
if (i == 0)
TxPrintf("%s\n", drcSubstitute(cptr));
i++;
HashSetValue(h, (spointertype)i);
DRCErrorList[cptr->drcc_tag] = i + 1;
}
/* Same routine as above, but output goes to a Tcl list and is appended */
@ -308,8 +307,7 @@ drcListError (celldef, rect, cptr, scx)
area = &scx->scx_area;
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
DRCErrorCount += 1;
h = HashFind(&DRCErrorTable, cptr->drcc_why);
i = (spointertype) HashGetValue(h);
i = DRCErrorList[cptr->drcc_tag];
if (i == 0)
{
Tcl_Obj *lobj;
@ -318,8 +316,7 @@ drcListError (celldef, rect, cptr, scx)
Tcl_NewStringObj(drcSubstitute(cptr), -1));
Tcl_SetObjResult(magicinterp, lobj);
}
i += 1;
HashSetValue(h, (spointertype)i);
DRCErrorList[cptr->drcc_tag] = i + 1;
}
/* Same routine as above, but output for every single error is recorded */
@ -343,7 +340,7 @@ drcListallError (celldef, rect, cptr, scx)
area = &scx->scx_area;
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
DRCErrorCount += 1;
h = HashFind(&DRCErrorTable, cptr->drcc_why);
h = HashFind(&DRCErrorTable, drcSubstitute(cptr));
lobj = (Tcl_Obj *) HashGetValue(h);
if (lobj == NULL)
lobj = Tcl_NewListObj(0, NULL);
@ -475,11 +472,15 @@ DRCWhy(dolist, use, area)
{
SearchContext scx;
Rect box;
int i;
extern int drcWhyFunc(); /* Forward reference. */
/* Create a hash table to used for eliminating duplicate messages. */
/* Create a hash table to eliminate duplicate messages. */
DRCErrorList = (int *)mallocMagic((DRCCurStyle->DRCWhySize + 1) * sizeof(int));
for (i = 0; i <= DRCCurStyle->DRCWhySize; i++)
DRCErrorList[i] = 0;
HashInit(&DRCErrorTable, 16, HT_STRINGKEYS);
DRCErrorCount = 0;
box = DRCdef->cd_bbox;
@ -494,12 +495,9 @@ DRCWhy(dolist, use, area)
drcWhyFunc(&scx, (pointertype)dolist);
UndoEnable();
/* Delete the hash table now that we're finished (otherwise there
* will be a core leak.
*/
HashKill(&DRCErrorTable);
/* Delete the error list */
freeMagic(DRCErrorList);
/* Redisplay the DRC yank definition in case anyone is looking
* at it.
*/
@ -532,7 +530,7 @@ DRCWhyAll(use, area, fout)
HashEntry *he;
Tcl_Obj *lobj, *robj;
/* Create a hash table to used for eliminating duplicate messages. */
/* Create a hash table for storing all of the results */
HashInit(&DRCErrorTable, 16, HT_STRINGKEYS);
DRCErrorCount = 0;
@ -566,10 +564,7 @@ DRCWhyAll(use, area, fout)
}
Tcl_SetObjResult(magicinterp, robj);
/* Delete the hash table now that we're finished (otherwise there
* will be a core leak.
*/
/* Delete the error table now that we're finished */
HashKill(&DRCErrorTable);
/* Redisplay the DRC yank definition in case anyone is looking
@ -748,9 +743,10 @@ drcCheckFunc(scx, cdarg)
*/
DRCCountList *
DRCCount(use, area)
DRCCount(use, area, recurse)
CellUse *use; /* Top-level use of hierarchy. */
Rect *area; /* Area in which violations are counted. */
bool recurse; /* If TRUE, count errors in all subcells */
{
DRCCountList *dcl, *newdcl;
HashTable dupTable;
@ -758,7 +754,11 @@ DRCCount(use, area)
HashSearch hs;
int count;
SearchContext scx;
extern int drcCountFunc(); /* Forward reference. */
CellDef *def;
extern int drcCountFunc();
/* Shouldn't happen? */
if (!(use->cu_def->cd_flags & CDAVAILABLE)) return NULL;
/* Use a hash table to make sure that we don't output information
* for any cell more than once.
@ -766,6 +766,10 @@ DRCCount(use, area)
HashInit(&dupTable, 16, HT_WORDKEYS);
/* Clearing CDAVAILABLE from cd_flags keeps the count from recursing */
if (recurse == FALSE)
use->cu_def->cd_flags &= ~CDAVAILABLE;
scx.scx_use = use;
scx.scx_x = use->cu_xlo;
scx.scx_y = use->cu_ylo;
@ -781,7 +785,7 @@ DRCCount(use, area)
HashStartSearch(&hs);
while ((he = HashNext(&dupTable, &hs)) != (HashEntry *)NULL)
{
count = (spointertype)HashGetValue(he);
count = (spointertype)HashGetValue(he);
if (count > 1)
{
newdcl = (DRCCountList *)mallocMagic(sizeof(DRCCountList));
@ -793,15 +797,20 @@ DRCCount(use, area)
}
}
HashKill(&dupTable);
/* Restore the CDAVAILABLE flag */
if (recurse == FALSE)
use->cu_def->cd_flags |= CDAVAILABLE;
return dcl;
}
int
drcCountFunc(scx, dupTable)
SearchContext *scx;
HashTable *dupTable; /* Passed as client data, used to
* avoid searching any cell twice.
*/
HashTable *dupTable; /* Passed as client data, used to
* avoid searching any cell twice.
*/
{
int count;
HashEntry *h;
@ -821,7 +830,7 @@ drcCountFunc(scx, dupTable)
count = 0;
(void) DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR],
&def->cd_bbox, &DBAllButSpaceBits, drcCountFunc2, (ClientData) &count);
&def->cd_bbox, &DBAllButSpaceBits, drcCountFunc2, (ClientData)(&count));
HashSetValue(h, (spointertype)count + 1);
/* Ignore children that have not been loaded---we will only report */
@ -832,26 +841,26 @@ drcCountFunc(scx, dupTable)
if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) return 0;
/* New behavior: Don't search children, instead propagate errors up. */
/* (void) DBCellSrArea(scx, drcCountFunc, (ClientData) dupTable); */
/* Scan children recursively. */
DBCellSrArea(scx, drcCountFunc, (ClientData)dupTable);
/* As a special performance hack, if the complete cell area is
* handled here, don't bother to look at any more array elements.
*/
done: if (GEO_SURROUND(&scx->scx_area, &def->cd_bbox)) return 2;
else return 0;
}
int
drcCountFunc2(tile, pCount)
Tile *tile; /* Tile found in error plane. */
int *pCount; /* Address of count word. */
drcCountFunc2(tile, countptr)
Tile *tile; /* Tile found in error plane. */
int *countptr; /* Address of count word. */
{
if (TiGetType(tile) != (TileType) TT_SPACE) *pCount += 1;
if (TiGetType(tile) != (TileType) TT_SPACE) (*countptr)++;
return 0;
}
/*
* ----------------------------------------------------------------------------
*
@ -963,13 +972,15 @@ drcFindFunc(scx, finddata)
CellDef *def;
HashEntry *h;
int drcFindFunc2();
bool dereference;
def = scx->scx_use->cu_def;
h = HashFind(finddata->deft, (char *)def);
if (HashGetValue(h) != 0) return 0;
HashSetValue(h, 1);
(void) DBCellRead(def, (char *) NULL, TRUE, NULL);
dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
(void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL);
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR],
&def->cd_bbox, &DBAllButSpaceBits, drcFindFunc2,

View File

@ -56,7 +56,7 @@ static DRCCookie drcSubcellCookie = {
0, 0, 0, 0,
{ 0 }, { 0 },
0, 0, 0,
"This layer can't abut or partially overlap between subcells",
DRC_SUBCELL_OVERLAP_TAG,
(DRCCookie *) NULL
};

View File

@ -40,6 +40,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
CIFStyle *drcCifStyle = NULL;
bool DRCForceReload = FALSE;
HashTable DRCWhyErrorTable; /* Table of DRC errors */
/*
* DRC interaction radius being used (not necessarily the same as
@ -61,6 +62,11 @@ global int DRCRuleOptimization = TRUE;
static int drcRulesSpecified = 0;
static int drcRulesOptimized = 0;
/* Rules with unique names are tagged with a reference number */
/* for use in placing errors into the DRC error plane. */
static int DRCtag = 0;
/*
* Forward declarations.
*/
@ -281,21 +287,14 @@ drcTechFreeStyle()
dp = DRCCurStyle->DRCRulesTbl[i][j];
while (dp != NULL)
{
char *old = (char *) dp;
char *old = (char *)dp;
dp = dp->drcc_next;
freeMagic(old);
}
}
/* Clear the DRCWhyList */
while (DRCCurStyle->DRCWhyList != NULL)
{
old = (char *) DRCCurStyle->DRCWhyList;
StrDup(&(DRCCurStyle->DRCWhyList->dwl_string), (char *) NULL);
DRCCurStyle->DRCWhyList = DRCCurStyle->DRCWhyList->dwl_next;
freeMagic(old);
}
/* Clear the Why string list */
freeMagic(DRCCurStyle->DRCWhyList);
freeMagic(DRCCurStyle);
DRCCurStyle = NULL;
@ -329,31 +328,55 @@ drcTechNewStyle()
/*
* ----------------------------------------------------------------------------
* drcWhyDup --
* drcWhyCreate --
*
* Duplicate a shared "why" string using StrDup() and remember it so we can
* free it sometime later, in drcWhyClear().
* Create a hash entry for the DRC "why" string, if it does not already
* exist.
*
* Returns:
* A copy of the given string.
* A pointer to the drcWhy structure containing the string and tag.
*
* Side effects:
* Adds to the DRCWhyList. Calls StrDup().
* Adds to the DRCWhyList if whystring has not been used before.
* Calls StrDup() and increments DRCWhySize. DRCWhyList is allocated
* in blocks of 50 at a time and only expands when filled.
* Temporary hash table DRCWhyErrorTable is used to determine if a
* string entry is unique. It is cleared after the technology file
* has been processed.
* ----------------------------------------------------------------------------
*/
char *
drcWhyDup(why)
char * why;
int
drcWhyCreate(whystring)
char *whystring;
{
struct drcwhylist * new;
HashEntry *he;
new = (struct drcwhylist *) mallocMagic((unsigned) (sizeof *new));
new->dwl_string = StrDup((char **) NULL, why);
new->dwl_next = DRCCurStyle->DRCWhyList;
DRCCurStyle->DRCWhyList = new;
he = HashLookOnly(&DRCWhyErrorTable, whystring);
if (he != NULL)
return (int)((pointertype)HashGetValue(he));
return new->dwl_string;
/* Grow the list in increments of 50 */
if ((DRCCurStyle->DRCWhySize % 50) == 0)
{
int i;
char **newList;
newList = (char **)mallocMagic((DRCCurStyle->DRCWhySize + 51) * sizeof(char *));
newList[0] = (char *)NULL;
for (i = 1; i <= DRCCurStyle->DRCWhySize; i++)
newList[i] = DRCCurStyle->DRCWhyList[i];
if (DRCCurStyle->DRCWhySize > 0)
freeMagic((char *)DRCCurStyle->DRCWhyList);
DRCCurStyle->DRCWhyList = newList;
}
DRCCurStyle->DRCWhySize++;
he = HashFind(&DRCWhyErrorTable, whystring);
HashSetValue(he, (char *)((pointertype)DRCCurStyle->DRCWhySize));
DRCCurStyle->DRCWhyList[DRCCurStyle->DRCWhySize] = StrDup((char **)NULL, whystring);
return DRCCurStyle->DRCWhySize;
}
/*
@ -535,12 +558,29 @@ DRCTechStyleInit()
DRCCurStyle->ds_status = TECH_NOT_LOADED;
TTMaskZero(&DRCCurStyle->DRCExactOverlapTypes);
DRCCurStyle->DRCWhyList = NULL;
DRCCurStyle->DRCTechHalo = 0;
DRCCurStyle->DRCScaleFactorN = 1;
DRCCurStyle->DRCScaleFactorD = 1;
DRCCurStyle->DRCStepSize = 0;
DRCCurStyle->DRCFlags = (char)0;
DRCCurStyle->DRCWhySize = 0;
HashInit(&DRCWhyErrorTable, 16, HT_STRINGKEYS);
/* First DRC entry is associated with the statically-allocated */
/* drcArrayCookie and has a tag of DRC_ARRAY_OVERLAP_TAG = 1 */
/* (see DRCarray.c). */
drcWhyCreate("This layer can't abut or partially overlap between array elements");
/* Second DRC entry is associated with the statically-allocated */
/* drcOverlapCookie and has a tag of DRC_OVERLAP_TAG = 2 */
/* (see DRCbasic.c). */
drcWhyCreate("Can't overlap those layers");
/* Third DRC entry is associated with the statically-allocated */
/* drcSubcellCookie and has a tag of DRC_SUBCELL_OVERLAP_TAG = 3 */
/* (see DRCsubcell.c). */
drcWhyCreate("This layer can't abut or partially overlap between subcells");
DRCTechHalo = 0;
@ -872,22 +912,18 @@ DRCTechLine(sectionName, argc, argv)
}
void
drcAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefrom)
drcCifAssign(cookie, dist, next, mask, corner, tag, cdist, flags, planeto, planefrom)
DRCCookie *cookie, *next;
int dist, cdist;
TileTypeBitMask *mask, *corner;
char *why;
int tag;
int flags, planeto, planefrom;
{
/* Diagnostic */
if (planeto >= DBNumPlanes) {
TxError("Bad plane in DRC assign!\n");
}
(cookie)->drcc_dist = dist;
(cookie)->drcc_next = next;
(cookie)->drcc_mask = *mask;
(cookie)->drcc_corner = *corner;
(cookie)->drcc_why = why;
(cookie)->drcc_tag = tag;
(cookie)->drcc_cdist = cdist;
(cookie)->drcc_flags = flags;
(cookie)->drcc_edgeplane = planefrom;
@ -896,6 +932,27 @@ drcAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefro
(cookie)->drcc_cmod = 0;
}
// This is like drcCifAssign, but checks for bad plane numbers in planeto and
// planefrom
void
drcAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefrom)
DRCCookie *cookie, *next;
int dist, cdist;
TileTypeBitMask *mask, *corner;
int why;
int flags, planeto, planefrom;
{
/* Diagnostic */
if (planeto >= DBNumPlanes)
TechError("Bad plane in DRC assignment.\n");
if (planefrom >= DBNumPlanes)
TechError("Bad edge plane in DRC assignment.\n");
drcCifAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto,
planefrom);
}
/*
* ----------------------------------------------------------------------------
*
@ -1071,7 +1128,7 @@ drcExtend(argc, argv)
char *layers1 = argv[1];
char *layers2 = argv[2];
int distance = atoi(argv[3]);
char *why;
int why;
TileTypeBitMask set1, setC;
DRCCookie *dp, *dpnew, *dptrig;
TileType i, j;
@ -1083,10 +1140,10 @@ drcExtend(argc, argv)
if (!strncmp(argv[4], "exact_", 6))
{
exact = TRUE;
why = drcWhyDup(argv[5]);
why = drcWhyCreate(argv[5]);
}
else
why = drcWhyDup(argv[4]);
why = drcWhyCreate(argv[4]);
ptest = DBTechNoisyNameMask(layers1, &set1);
pMask1 = CoincidentPlanes(&set1, ptest);
@ -1240,7 +1297,7 @@ drcWidth(argc, argv)
{
char *layers = argv[1];
int distance = atoi(argv[2]);
char *why = drcWhyDup(argv[3]);
int why = drcWhyCreate(argv[3]);
TileTypeBitMask set, setC;
PlaneMask pmask, pset, ptest;
DRCCookie *dp, *dpnew;
@ -1325,7 +1382,7 @@ drcArea(argc, argv)
char *layers = argv[1];
int distance = atoi(argv[2]);
int horizon = atoi(argv[3]);
char *why = drcWhyDup(argv[4]);
int why = drcWhyCreate(argv[4]);
TileTypeBitMask set, setC;
DRCCookie *dp, *dpnew;
TileType i, j;
@ -1425,7 +1482,7 @@ drcMaxwidth(argc, argv)
char *layers = argv[1];
int distance = atoi(argv[2]);
char *bends = argv[3];
char *why;
int why;
TileTypeBitMask set, setC;
DRCCookie *dp, *dpnew;
TileType i, j;
@ -1452,7 +1509,7 @@ drcMaxwidth(argc, argv)
bend = 0;
else
bend = DRC_BENDS;
why = drcWhyDup(argv[3]);
why = drcWhyCreate(argv[3]);
}
else
{
@ -1463,7 +1520,7 @@ drcMaxwidth(argc, argv)
TechError("unknown bend option %s\n",bends);
return (0);
}
why = drcWhyDup(argv[4]);
why = drcWhyCreate(argv[4]);
}
for (i = 0; i < DBNumTypes; i++)
@ -1514,7 +1571,7 @@ drcAngles(argc, argv)
{
char *layers = argv[1];
int angles = atoi(argv[2]);
char *why = drcWhyDup(argv[3]);
int why = drcWhyCreate(argv[3]);
TileTypeBitMask set;
DRCCookie *dp, *dpnew;
int plane;
@ -1582,7 +1639,7 @@ drcSpacing3(argc, argv)
char *layers3 = argv[5];
int distance = atoi(argv[3]);
char *adjacency = argv[4];
char *why = drcWhyDup(argv[6]);
int why = drcWhyCreate(argv[6]);
TileTypeBitMask set1, set2, set3;
int plane;
DRCCookie *dp, *dpnew;
@ -2134,7 +2191,7 @@ drcSpacing(argc, argv)
{
char *layers1 = argv[1], *layers2;
char *adjacency;
char *why;
int why;
TileTypeBitMask set1, set2, tmp1, tmp2;
PlaneMask pmask1, pmask2, pmaskA, pmaskB, ptest;
int wwidth, distance, plane, plane2, runlength;
@ -2155,7 +2212,7 @@ drcSpacing(argc, argv)
layers2 = argv[4];
distance = atoi(argv[5]);
adjacency = argv[6];
why = drcWhyDup(argv[7]);
why = drcWhyCreate(argv[7]);
}
else
{
@ -2163,7 +2220,7 @@ drcSpacing(argc, argv)
distance = atoi(argv[4]);
runlength = distance;
adjacency = argv[5];
why = drcWhyDup(argv[6]);
why = drcWhyCreate(argv[6]);
}
/* TxPrintf("Info: DRCtech: widespacing rule for %s width %d:"
" spacing must be %d\n", layers1, wwidth, distance); */
@ -2174,7 +2231,7 @@ drcSpacing(argc, argv)
distance = atoi(argv[3]);
adjacency = argv[4];
wwidth = distance;
why = drcWhyDup(argv[5]);
why = drcWhyCreate(argv[5]);
runlength = distance;
if (argc >= 7)
{
@ -2308,7 +2365,7 @@ drcEdge(argc, argv)
int distance = atoi(argv[3]);
char *okTypes = argv[4], *cornerTypes = argv[5];
int cdist = atoi(argv[6]);
char *why = drcWhyDup(argv[7]);
int why = drcWhyCreate(argv[7]);
bool fourway = (strcmp(argv[0], "edge4way") == 0);
TileTypeBitMask set1, set2, setC, setM;
DRCCookie *dp, *dpnew;
@ -2474,7 +2531,7 @@ drcOverhang(argc, argv)
{
char *layers2 = argv[1], *layers1 = argv[2];
int distance = atoi(argv[3]);
char *why = drcWhyDup(argv[4]);
int why = drcWhyCreate(argv[4]);
TileTypeBitMask set1, set2, setM, setC, setN, set2inv;
DRCCookie *dp, *dpnew, *dptrig;
int plane, plane2;
@ -2610,7 +2667,7 @@ drcRectOnly(argc, argv)
char *argv[];
{
char *layers = argv[1];
char *why = drcWhyDup(argv[2]);
int why = drcWhyCreate(argv[2]);
TileTypeBitMask set1, set2, setC;
PlaneMask pmask, pset, ptest;
DRCCookie *dp, *dpnew;
@ -2710,7 +2767,7 @@ drcSurround(argc, argv)
char *layers1 = argv[1], *layers2 = argv[2];
int distance = atoi(argv[3]);
char *presence = argv[4];
char *why = drcWhyDup(argv[5]);
int why = drcWhyCreate(argv[5]);
TileTypeBitMask set1, set2, setM, invM, setR;
DRCCookie *dp, *dpnew, *dptrig;
int plane1, plane2;
@ -3083,7 +3140,7 @@ drcRectangle(argc, argv)
char *argv[];
{
char *layers = argv[1];
char *why = drcWhyDup(argv[4]);
int why = drcWhyCreate(argv[4]);
TileTypeBitMask types, nottypes;
int maxwidth;
static char *drcRectOpt[4] = {"any", "even", "odd", 0};
@ -3449,6 +3506,9 @@ drcTechFinalStyle(style)
DRCCookie **dpp, **dp2back;
TileType i, j;
/* Done with DRCWhyErrorTable */
HashKill(&DRCWhyErrorTable);
/* If the scale factor is not 1, then divide all distances by */
/* the scale factor, take the ceiling, and save the (negative) */
/* remainder. */
@ -3570,7 +3630,6 @@ drcTechFinalStyle(style)
}
else
{
/* Don't free the shared drcc_why string here! */
freeMagic((char *)dptest);
drcRulesOptimized++;
}
@ -3665,7 +3724,8 @@ drcTechFinalStyle(style)
/* TxPrintf("For edge %s-%s, \"%s\" covers \"%s\"\n",
DBTypeShortName(i), DBTypeShortName(j),
next->drcc_why, dp->drcc_why);
DRCCurStyle->DRCWhyList[next->drcc_tag],
DRCCurStyle->DRCWhyList[dp->drcc_tag]);
*/
dp2back = &(style->DRCRulesTbl[i][j]);
while (*dp2back != dp)
@ -3687,7 +3747,6 @@ drcTechFinalStyle(style)
else
*dp2back = dp->drcc_next;
/* Don't free the shared drcc_why string here! */
freeMagic((char *) dp);
drcRulesOptimized += 1;
}

View File

@ -39,10 +39,15 @@ typedef struct drccookie
int drcc_edgeplane; /* Plane of edge */
int drcc_plane; /* Index of plane on which to check
* legal types. */
char *drcc_why; /* Explanation of error found */
int drcc_tag; /* Tag to explanation of error found */
struct drccookie *drcc_next;
} DRCCookie;
/* These DRC tags in DRCcookie are predefined. */
#define DRC_ARRAY_OVERLAP_TAG 1
#define DRC_OVERLAP_TAG 2
#define DRC_SUBCELL_OVERLAP_TAG 3
/* *This is size "int" because it holds an area for DRC_AREA rules, */
/* and therefore may have twice the bit length of a normal rule distance. */
@ -129,9 +134,9 @@ typedef struct drcpendingcookie
typedef struct drccountlist
{
CellDef *dcl_def;
int dcl_count;
struct drccountlist *dcl_next;
CellDef *dcl_def;
int dcl_count;
struct drccountlist *dcl_next;
} DRCCountList;
/* Structure used to keep information about the current DRC style */
@ -142,22 +147,6 @@ typedef struct drckeep
char *ds_name;
} DRCKeep;
/*
* DRC "why" strings are potentially referred to hundreds of times by
* DRC cookies in the rule table. Rather than creating hundreds of
* copies of each string, we create just one copy and let all the cookies
* point to that one copy.
*
* Since we can't free these shared "why" strings when we delete a cookie,
* we keep a list of these strings and free them all when convenient.
*/
typedef struct drcwhylist
{
char * dwl_string;
struct drcwhylist * dwl_next;
} drcWhyList;
/*
* Structure defining a DRC style
*/
@ -173,7 +162,8 @@ typedef struct drcstyle
int DRCTechHalo; /* largest action distance of design rules */
int DRCStepSize; /* chunk size for decomposing large areas */
char DRCFlags; /* Option flags */
drcWhyList *DRCWhyList;
char **DRCWhyList; /* Indexed list of "why" text strings */
int DRCWhySize; /* Length of DRCWhyList */
PaintResultType DRCPaintTable[NP][NT][NT];
} DRCStyle;
@ -239,6 +229,9 @@ extern void drcPrintError();
extern int drcIncludeArea();
extern int drcExactOverlapTile();
extern void drcInitRulesTbl();
extern void drcAssign();
extern void drcCifAssign();
extern int drcWhyCreate();
/*
* Exported procedures

View File

@ -26,12 +26,12 @@ exttosim${SHDLIB_EXT}: simwrap.o ${MAGICDIR}/extflat/libextflat.o
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} simwrap.o \
${MAGICDIR}/extflat/libextflat.o ${LD_SHARED} -lc ${LIBS}
install: $(DESTDIR)${BINDIR}/${MODULE}${EXEEXT}
install: $(DESTDIR)${INSTALL_BINDIR}/${MODULE}${EXEEXT}
install-tcl: $(DESTDIR)${TCLDIR}/exttosim${SHDLIB_EXT}
install-tcl: $(DESTDIR)${INSTALL_TCLDIR}/exttosim${SHDLIB_EXT}
$(DESTDIR)${TCLDIR}/exttosim${SHDLIB_EXT}: exttosim${SHDLIB_EXT}
${RM} $(DESTDIR)${TCLDIR}/exttosim${SHDLIB_EXT}
${CP} exttosim${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/exttosim${SHDLIB_EXT}
$(DESTDIR)${INSTALL_TCLDIR}/exttosim${SHDLIB_EXT}: exttosim${SHDLIB_EXT}
${RM} $(DESTDIR)${INSTALL_TCLDIR}/exttosim${SHDLIB_EXT}
${CP} exttosim${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/exttosim${SHDLIB_EXT}
include ${MAGICDIR}/rules.mak

View File

@ -1078,7 +1078,7 @@ simdevVisit(dev, hierName, scale, trans)
{
putc(' ', esSimF);
simdevSubstrate(hierName, subnode->efnode_name->efnn_hier,
dev->dev_type, 0, FALSE, esSimF);
dev->dev_type, 0.0, FALSE, esSimF);
}
GeoTransRect(trans, &dev->dev_rect, &r);
@ -1196,7 +1196,8 @@ int
simdevSubstrate( prefix, suffix, type, scale, doAP, outf)
HierName *prefix;
HierName *suffix;
int type, scale;
int type;
float scale;
bool doAP;
FILE *outf;
{
@ -1264,7 +1265,8 @@ FILE *outf;
bool simnAP(node, resClass, scale, outf)
EFNode *node;
int resClass, scale;
int resClass;
float scale;
FILE *outf;
{
int a, p;
@ -1277,8 +1279,8 @@ FILE *outf;
return FALSE;
}
markVisited((nodeClient *)node->efnode_client, resClass);
a = node->efnode_pa[resClass].pa_area*scale*scale;
p = node->efnode_pa[resClass].pa_perim*scale;
a = (int)(node->efnode_pa[resClass].pa_area*scale*scale);
p = (int)(node->efnode_pa[resClass].pa_perim*scale);
if ( a < 0 ) a = 0;
if ( p < 0 ) p = 0;
fprintf(outf,"A_%d,P_%d", a, p);
@ -1288,7 +1290,8 @@ FILE *outf;
bool simnAPHier(dterm, hierName, resClass, scale, outf)
DevTerm *dterm;
HierName *hierName;
int resClass, scale;
int resClass;
float scale;
FILE *outf;
{
EFNode *node = dterm->dterm_node;
@ -1308,8 +1311,8 @@ bool simnAPHier(dterm, hierName, resClass, scale, outf)
return FALSE;
}
markVisited((nodeClientHier *)node->efnode_client, resClass);
a = node->efnode_pa[resClass].pa_area*scale*scale;
p = node->efnode_pa[resClass].pa_perim*scale;
a = (int)(node->efnode_pa[resClass].pa_area*scale*scale);
p = (int)(node->efnode_pa[resClass].pa_perim*scale);
if ( a < 0 ) a = 0;
if ( p < 0 ) p = 0;
fprintf(outf,"A_%d,P_%d", a, p);

View File

@ -29,16 +29,16 @@ exttospice${SHDLIB_EXT}: spicewrap.o spicehier.o ${MAGICDIR}/extflat/libextflat.
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} spicewrap.o spicehier.o \
${MAGICDIR}/extflat/libextflat.o ${LD_SHARED} -lc ${LIBS}
install: $(DESTDIR)${BINDIR}/${MODULE}${EXEEXT} $(DESTDIR)${BINDIR}/spice2sim
install: $(DESTDIR)${INSTALL_BINDIR}/${MODULE}${EXEEXT} $(DESTDIR)${INSTALL_BINDIR}/spice2sim
install-tcl: $(DESTDIR)${TCLDIR}/exttospice${SHDLIB_EXT} $(DESTDIR)${BINDIR}/spice2sim
install-tcl: $(DESTDIR)${INSTALL_TCLDIR}/exttospice${SHDLIB_EXT} $(DESTDIR)${INSTALL_BINDIR}/spice2sim
$(DESTDIR)${TCLDIR}/exttospice${SHDLIB_EXT}: exttospice${SHDLIB_EXT}
${RM} $(DESTDIR)${TCLDIR}/exttospice${SHDLIB_EXT}
${CP} exttospice${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/exttospice${SHDLIB_EXT}
$(DESTDIR)${INSTALL_TCLDIR}/exttospice${SHDLIB_EXT}: exttospice${SHDLIB_EXT}
${RM} $(DESTDIR)${INSTALL_TCLDIR}/exttospice${SHDLIB_EXT}
${CP} exttospice${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/exttospice${SHDLIB_EXT}
$(DESTDIR)${BINDIR}/spice2sim: spice2sim
${RM} $(DESTDIR)${BINDIR}/spice2sim
${CP} spice2sim $(DESTDIR)${BINDIR}/spice2sim
$(DESTDIR)${INSTALL_BINDIR}/spice2sim: spice2sim
${RM} $(DESTDIR)${INSTALL_BINDIR}/spice2sim
${CP} spice2sim $(DESTDIR)${INSTALL_BINDIR}/spice2sim
include ${MAGICDIR}/rules.mak

View File

@ -1159,13 +1159,11 @@ spcresistHierVisit(hc, hierName1, hierName2, res)
HierContext *hc;
HierName *hierName1;
HierName *hierName2;
int res;
float res;
{
res = (res + 500) / 1000;
fprintf(esSpiceF, "R%d %s %s %d\n", esResNum++,
fprintf(esSpiceF, "R%d %s %s %g\n", esResNum++,
nodeSpiceHierName(hc, hierName1),
nodeSpiceHierName(hc, hierName2), res);
nodeSpiceHierName(hc, hierName2), res / 1000.);
return 0;
}
@ -1572,27 +1570,39 @@ esMakePorts(hc, cdata)
while (tptr != NULL)
{
/* Ignore array information for the purpose of tracing */
/* the cell definition hierarchy. */
int idum[6];
bool is_array;
aptr = strchr(portname, '[');
if ((aptr == NULL) || (aptr > tptr))
*tptr = '\0';
else
*aptr = '\0';
/* Ignore array information for the purpose of tracing */
/* the cell definition hierarchy. If a cell use name */
/* contains a bracket, check first if the complete name */
/* matches a use. If not, then check if the part */
/* the last opening bracket matches a known use. */
aptr = strrchr(portname, '[');
*tptr = '\0';
is_array = FALSE;
if (aptr != NULL)
{
he = HashLookOnly(&updef->def_uses, portname);
if (he == NULL)
{
*aptr = '\0';
is_array = TRUE;
}
}
// Find the cell for the instance
portdef = NULL;
he = HashFind(&updef->def_uses, portname);
he = HashLookOnly(&updef->def_uses, portname);
if (he != NULL)
{
use = (Use *)HashGetValue(he);
portdef = use->use_def;
}
if ((aptr == NULL) || (aptr > tptr))
*tptr = '/';
else
if (is_array)
*aptr = '[';
*tptr = '/';
portname = tptr + 1;
// Find the net of portname in the subcell and
@ -1613,6 +1623,10 @@ esMakePorts(hc, cdata)
{
nn->efnn_node->efnode_flags |= EF_PORT;
nn->efnn_port = -1; // Will be sorted later
// Diagnostic
// TxPrintf("Port connection in %s from net %s to net %s (%s)\n",
// def->def_name, locname, name, portname);
}
}
@ -1622,9 +1636,6 @@ esMakePorts(hc, cdata)
updef = portdef;
}
// Diagnostic
// TxPrintf("Connection in %s to net %s (%s)\n", def->def_name,
// name, portname);
}
}
@ -1644,34 +1655,46 @@ esMakePorts(hc, cdata)
// In particular, this keeps parasitics out of the netlist for
// LVS purposes if "cthresh" is set to "infinite".
if (fabs((double)conn->conn_cap) < EFCapThreshold) continue;
if (fabs((double)conn->conn_cap / 1000) < EFCapThreshold) continue;
portname = name;
updef = def;
while (tptr != NULL)
{
int idum[6];
bool is_array;
/* Ignore array information for the purpose of tracing */
/* the cell definition hierarchy. */
aptr = strchr(portname, '[');
if ((aptr == NULL) || (aptr > tptr))
*tptr = '\0';
else
if (aptr && (aptr < tptr) &&
(sscanf(aptr, "[%d:%d:%d][%d:%d:%d]",
&idum[0], &idum[1], &idum[2],
&idum[3], &idum[4], &idum[5]) == 6))
{
*aptr = '\0';
is_array = TRUE;
}
else
{
*tptr = '\0';
is_array = FALSE;
}
// Find the cell for the instance
portdef = NULL;
he = HashFind(&updef->def_uses, portname);
he = HashLookOnly(&updef->def_uses, portname);
if (he != NULL)
{
use = (Use *)HashGetValue(he);
portdef = use->use_def;
}
if ((aptr == NULL) || (aptr > tptr))
*tptr = '/';
else
if (is_array)
*aptr = '[';
else
*tptr = '/';
portname = tptr + 1;
// Find the net of portname in the subcell and
@ -1747,7 +1770,8 @@ esHierVisit(hc, cdata)
if (def != topdef)
{
if ((def->def_devs == NULL) && (HashGetNumEntries(&def->def_uses) == 0))
if ((HashGetNumEntries(&def->def_devs) == 0) &&
(HashGetNumEntries(&def->def_uses) == 0))
{
if (locDoSubckt == AUTO)
{
@ -1859,6 +1883,9 @@ esHierVisit(hc, cdata)
EFHierVisitNodes(hcf, spcnodeHierVisit, (ClientData) NULL);
freeMagic(resstr);
}
/* Reset device merge index for next cell */
if (esMergeDevsA || esMergeDevsC) esFMIndex = 0;
}
if ((def != topdef) || (def->def_flags & DEF_SUBCIRCUIT) || (locDoSubckt == TRUE))

View File

@ -140,9 +140,16 @@ esFormatSubs(outf, suf)
if ((EFTrimFlags & EF_TRIMGLOB ) && suf[l] == '!' ||
(EFTrimFlags & EF_TRIMLOCAL) && suf[l] == '#')
suf[l] = '\0' ;
if (EFTrimFlags & EF_CONVERTCOMMAS)
if (EFTrimFlags & EF_CONVERTCOMMA)
while ((specchar = strchr(suf, ',')) != NULL)
*specchar = ';';
*specchar = '|';
if (EFTrimFlags & EF_CONVERTBRACKETS)
{
while ((specchar = strchr(suf, '[')) != NULL)
*specchar = '_';
while ((specchar = strchr(suf, ']')) != NULL)
*specchar = '_';
}
if (EFTrimFlags & EF_CONVERTEQUAL)
while ((specchar = strchr(suf, '=')) != NULL)
*specchar = ':';
@ -257,7 +264,8 @@ CmdExtToSpice(w, cmd)
"extresist [on|off] incorporate information from extresist",
"resistor tee [on|off] model resistor capacitance as a T-network",
"scale [on|off] use .option card for scaling",
"subcircuits [on|off] standard cells become subcircuit calls",
"subcircuits [top|descend] [on|off|auto]\n"
" standard cells become subcircuit calls",
"hierarchy [on|off] output hierarchical spice for LVS",
"blackbox [on|off] output abstract views as black-box entries",
"renumber [on|off] on = number instances X1, X2, etc.\n"
@ -607,7 +615,7 @@ CmdExtToSpice(w, cmd)
case EXTTOSPC_DEFAULT:
LocCapThreshold = 2;
LocResistThreshold = INFINITE_THRESHOLD;
EFTrimFlags = EF_CONVERTCOMMAS | EF_CONVERTEQUAL;
EFTrimFlags = EF_CONVERTCOMMA | EF_CONVERTEQUAL;
EFScale = 0.0;
if (EFArgTech)
{
@ -821,7 +829,7 @@ runexttospice:
// This forces options TRIMGLOB and CONVERTEQUAL, not sure that's such a
// good idea. . .
EFTrimFlags |= EF_TRIMGLOB | EF_CONVERTEQUAL;
EFTrimFlags |= EF_TRIMGLOB | EF_CONVERTEQUAL | EF_CONVERTCOMMA;
if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS;
if (esFormat == HSPICE)
EFTrimFlags |= EF_TRIMLOCAL;
@ -1140,6 +1148,17 @@ spcmainArgs(pargc, pargv)
char **argv = *pargv, *cp;
int argc = *pargc;
char usage_text[] = "Usage: ext2spice "
"[-B] [-o spicefile] [-M|-m] [-y cap_digits] "
"[-J flat|hier]\n"
"[-f spice2|spice3|hspice|ngspice] [-M] [-m] "
#ifdef MAGIC_WRAPPER
"[file]\n";
#else
"[-j device:sdRclass[/subRclass]/defaultSubstrate]\n"
"file\n\n or else see options to extcheck(1)\n";
#endif
switch (argv[0][1])
{
case 'd':
@ -1236,6 +1255,9 @@ spcmainArgs(pargc, pargv)
break;
}
#endif /* MAGIC_WRAPPER */
case 'h': /* -h or -help, as suggested by "ext2spice help" */
TxPrintf(usage_text);
break;
default:
TxError("Unrecognized flag: %s\n", argv[0]);
goto usage;
@ -1246,16 +1268,7 @@ spcmainArgs(pargc, pargv)
return 0;
usage:
TxError("Usage: ext2spice [-B] [-o spicefile] [-M|-m] [-y cap_digits] "
"[-J flat|hier]\n"
"[-f spice2|spice3|hspice] [-M] [-m] "
#ifdef MAGIC_WRAPPER
"[file]\n"
#else
"[-j device:sdRclass[/subRclass]/defaultSubstrate]\n"
"file\n\n or else see options to extcheck(1)\n"
#endif
);
TxError(usage_text);
#ifdef MAGIC_WRAPPER
return 1;
@ -1359,10 +1372,11 @@ subcktVisit(use, hierName, is_top)
EFNode *snode;
Def *def = use->use_def;
EFNodeName *nodeName;
int portorder, portmax, imp_max, tchars;
int portorder, portmax, portidx, imp_max, tchars;
char stmp[MAX_STR_SIZE];
char *instname, *subcktname;
DevParam *plist, *pptr;
EFNodeName **nodeList;
if (is_top == TRUE) return 0; /* Ignore the top-level cell */
@ -1379,7 +1393,7 @@ subcktVisit(use, hierName, is_top)
else
{
int savflags = EFTrimFlags;
EFTrimFlags = 0; // Do no substitutions on subcircuit names
EFTrimFlags = EF_CONVERTCOMMA; // Only substitute commas on subcircuit names
/* Use full hierarchical decomposition for name */
/* (not just use->use_id. hierName already has use->use_id at end) */
@ -1454,35 +1468,58 @@ subcktVisit(use, hierName, is_top)
/* Port numbers need not start at zero or be contiguous. */
/* They will be printed in numerical order. */
portorder = 0;
while (portorder <= portmax)
{
for (snode = (EFNode *) def->def_firstn.efnode_next;
nodeList = (EFNodeName **)mallocMagic((portmax + 1) * sizeof(EFNodeName *));
for (portidx = 0; portidx <= portmax; portidx++)
nodeList[portidx] = (EFNodeName *)NULL;
for (snode = (EFNode *) def->def_firstn.efnode_next;
snode != &def->def_firstn;
snode = (EFNode *) snode->efnode_next)
{
if (!(snode->efnode_flags & EF_PORT)) continue;
for (nodeName = snode->efnode_name; nodeName != NULL;
{
if (!(snode->efnode_flags & EF_PORT)) continue;
for (nodeName = snode->efnode_name; nodeName != NULL;
nodeName = nodeName->efnn_next)
{
EFNodeName *nn;
HashEntry *he;
char *pname;
portidx = nodeName->efnn_port;
if (portidx < 0) continue;
if (nodeList[portidx] == NULL)
{
int portidx = nodeName->efnn_port;
if (portidx == portorder)
{
if (tchars > 80)
{
fprintf(esSpiceF, "\n+");
tchars = 1;
}
tchars += spcdevOutNode(hierName, nodeName->efnn_hier,
"subcircuit", esSpiceF);
break;
}
nodeList[portidx] = nodeName;
}
else if (EFHNBest(nodeName->efnn_hier, nodeList[portidx]->efnn_hier))
{
nodeList[portidx] = nodeName;
}
if (nodeName != NULL) break;
}
portorder++;
}
for (portidx = 0; portidx <= portmax; portidx++)
{
nodeName = nodeList[portidx];
if (nodeName != NULL)
{
if (tchars > 80)
{
fprintf(esSpiceF, "\n+");
tchars = 1;
}
tchars += spcdevOutNode(hierName, nodeName->efnn_hier,
"subcircuit", esSpiceF);
}
else
{
// As port indexes do not have to be contiguous, this does not
// necessarily indicate an error condition. No need to report?
// TxError("No port connection on port %d; need to resolve.\n", portidx);
}
}
freeMagic(nodeList);
/* Look for all implicit substrate connections that are */
/* declared as local node names, and put them last. */
@ -1602,7 +1639,7 @@ topVisit(def, doStub)
Def *def;
bool doStub;
{
EFNode *snode;
EFNode *snode, *basenode;
EFNodeName *sname, *nodeName;
HashSearch hs;
HashEntry *he;
@ -1655,7 +1692,9 @@ topVisit(def, doStub)
snode = sname->efnn_node;
if (snode->efnode_flags & EF_PORT)
if (snode->efnode_name->efnn_port < 0)
{
pname = nodeSpiceName(snode->efnode_name->efnn_hier, &basenode);
if (basenode->efnode_name->efnn_port < 0)
{
if (tchars > 80)
{
@ -1663,11 +1702,12 @@ topVisit(def, doStub)
fprintf(esSpiceF, "\n+");
tchars = 1;
}
pname = nodeSpiceName(snode->efnode_name->efnn_hier);
fprintf(esSpiceF, " %s", pname);
tchars += strlen(pname) + 1;
snode->efnode_name->efnn_port = portorder++;
basenode->efnode_name->efnn_port = portorder++;
}
snode->efnode_name->efnn_port = basenode->efnode_name->efnn_port;
}
}
}
else
@ -1681,6 +1721,7 @@ topVisit(def, doStub)
HashStartSearch(&hs);
while (he = HashNext(&def->def_nodes, &hs))
{
char stmp[MAX_STR_SIZE];
int portidx;
EFNodeName *unnumbered;
@ -1701,7 +1742,17 @@ topVisit(def, doStub)
fprintf(esSpiceF, "\n+");
tchars = 1;
}
pname = nodeSpiceName(snode->efnode_name->efnn_hier);
// If view is abstract, rely on the given port name, not
// the node. Otherwise, artifacts of the abstract view
// may cause nodes to be merged and the names lost.
if (def->def_flags & DEF_ABSTRACT)
{
EFHNSprintf(stmp, nodeName->efnn_hier);
pname = stmp;
}
else
pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL);
fprintf(esSpiceF, " %s", pname);
tchars += strlen(pname) + 1;
break;
@ -2083,6 +2134,56 @@ esOutputResistor(dev, hierName, scale, term1, term2, has_model, l, w, dscale)
}
}
/* Report if device at index n has been deleted due to merging */
bool
devIsKilled(n)
int n;
{
return (esFMult[(n)] <= (float)0.0) ? TRUE : FALSE;
}
/* Add a dev's multiplier to the table and grow it if necessary */
void
addDevMult(f)
float f;
{
int i;
float *op;
if (esFMult == NULL) {
esFMult = (float *) mallocMagic((unsigned) (esFMSize*sizeof(float)));
}
else if (esFMIndex >= esFMSize)
{
op = esFMult;
esFMSize *= 2;
esFMult = (float *)mallocMagic((unsigned)(esFMSize * sizeof(float)));
for (i = 0; i < esFMSize / 2; i++) esFMult[i] = op[i];
if (op) freeMagic(op);
}
esFMult[esFMIndex++] = f;
}
/* Set the multiplier value f of device at index i */
void
setDevMult(i, f)
int i;
float f;
{
esFMult[i] = f;
}
/* Get the multiplier value of the device at the current index esFMIndex */
float
getCurDevMult()
{
return (esFMult && (esFMIndex > 0)) ? esFMult[esFMIndex-1] : (float)1.0;
}
/*
* ----------------------------------------------------------------------------
*
@ -2708,13 +2809,16 @@ FILE *outf;
/* Canonical name */
nn = (EFNodeName *) HashGetValue(he);
if (outf)
fprintf(outf, "%s", nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier));
fprintf(outf, "%s", nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier,
NULL));
/* Mark node as visited */
if ((nodeClient *)nn->efnn_node->efnode_client == (ClientData)NULL)
initNodeClientHier(nn->efnn_node);
((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= DEV_CONNECT_MASK;
if (!esDistrJunct)
((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |=
DEV_CONNECT_MASK;
return nn->efnn_node;
}
}
@ -2769,7 +2873,14 @@ int spcnAP(node, resClass, scale, asterm, psterm, m, outf, w)
if (!esDistrJunct || w == -1) goto oldFmt;
dsc = w / ((nodeClient*)node->efnode_client)->m_w.widths[resClass];
if (((nodeClient*)node->efnode_client)->m_w.widths != NULL)
dsc = w / ((nodeClient*)node->efnode_client)->m_w.widths[resClass];
else
{
TxError("Device missing records for source/drain area/perim.\n");
dsc = w;
}
if (esScale < 0)
{
if (asterm)
@ -2917,10 +3028,13 @@ spcdevOutNode(prefix, suffix, name, outf)
return 0;
}
nn = (EFNodeName *) HashGetValue(he);
nname = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier);
nname = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier, NULL);
fprintf(outf, " %s", nname);
/* Mark node as visited */
((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= DEV_CONNECT_MASK;
if (!esDistrJunct)
((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= DEV_CONNECT_MASK;
return (1 + strlen(nname));
}
@ -2960,8 +3074,8 @@ spccapVisit(hierName1, hierName2, cap)
if (cap <= EFCapThreshold)
return 0;
fprintf(esSpiceF, esSpiceCapFormat ,esCapNum++,nodeSpiceName(hierName1),
nodeSpiceName(hierName2), cap);
fprintf(esSpiceF, esSpiceCapFormat ,esCapNum++,nodeSpiceName(hierName1, NULL),
nodeSpiceName(hierName2, NULL), cap);
return 0;
}
@ -2996,8 +3110,8 @@ spcresistVisit(hierName1, hierName2, res)
HierName *hierName2;
float res;
{
fprintf(esSpiceF, "R%d %s %s %g\n", esResNum++, nodeSpiceName(hierName1),
nodeSpiceName(hierName2), res / 1000.);
fprintf(esSpiceF, "R%d %s %s %g\n", esResNum++, nodeSpiceName(hierName1, NULL),
nodeSpiceName(hierName2, NULL), res / 1000.);
return 0;
}
@ -3032,7 +3146,7 @@ spcsubVisit(node, res, cap, resstr)
if (node->efnode_flags & EF_SUBS_NODE)
{
hierName = (HierName *) node->efnode_name->efnn_hier;
nsn = nodeSpiceName(hierName);
nsn = nodeSpiceName(hierName, NULL);
*resstr = StrDup((char **)NULL, nsn);
return 1;
}
@ -3082,7 +3196,7 @@ spcnodeVisit(node, res, cap)
if (!isConnected && node->efnode_flags & EF_PORT) isConnected = TRUE;
hierName = (HierName *) node->efnode_name->efnn_hier;
nsn = nodeSpiceName(hierName);
nsn = nodeSpiceName(hierName, NULL);
if (esFormat == SPICE2 || esFormat == HSPICE && strncmp(nsn, "z@", 2)==0 ) {
static char ntmp[MAX_STR_SIZE];
@ -3127,7 +3241,7 @@ nodeVisitDebug(node, res, cap)
EFAttr *ap;
hierName = (HierName *) node->efnode_name->efnn_hier;
nsn = nodeSpiceName(hierName);
nsn = nodeSpiceName(hierName, NULL);
TxError("** %s (%x)\n", nsn, node);
printf("\t client.name=%s, client.m_w=%p\n",
@ -3150,23 +3264,27 @@ nodeVisitDebug(node, res, cap)
*
* Side effects:
* Allocates nodeClients for the node.
* Returns the node in the "rnode" pointer, if non-NULL.
*
* ----------------------------------------------------------------------------
*/
static char esTempName[MAX_STR_SIZE];
char *nodeSpiceName(hname)
char *nodeSpiceName(hname, rnode)
HierName *hname;
EFNode **rnode;
{
EFNodeName *nn;
HashEntry *he;
EFNode *node;
if (rnode) *rnode = (EFNode *)NULL;
he = EFHNLook(hname, (char *) NULL, "nodeName");
if ( he == NULL )
return "errGnd!";
nn = (EFNodeName *) HashGetValue(he);
node = nn->efnn_node;
if (rnode) *rnode = node;
if ( (nodeClient *) (node->efnode_client) == NULL ) {
initNodeClient(node);
@ -3215,7 +3333,7 @@ EFHNSprintf(str, hierName)
char *str;
HierName *hierName;
{
bool trimGlob, trimLocal, convertComma, convertEqual;
bool trimGlob, trimLocal, convertComma, convertEqual, convertBrackets;
char *s, *cp, c;
char *efHNSprintfPrefix(HierName *, char *);
@ -3226,8 +3344,9 @@ EFHNSprintf(str, hierName)
cp = hierName->hn_name;
trimGlob = (EFTrimFlags & EF_TRIMGLOB);
trimLocal = (EFTrimFlags & EF_TRIMLOCAL);
convertComma = (EFTrimFlags & EF_CONVERTCOMMAS);
convertComma = (EFTrimFlags & EF_CONVERTCOMMA);
convertEqual = (EFTrimFlags & EF_CONVERTEQUAL);
convertBrackets = (EFTrimFlags & EF_CONVERTBRACKETS);
while (c = *cp++)
{
switch (c)
@ -3235,7 +3354,9 @@ EFHNSprintf(str, hierName)
case '!': if (!trimGlob) *str++ = c; break;
case '.': *str++ = (esFormat == HSPICE)?'@':'.'; break;
case '=': if (convertEqual) *str++ = ':'; break;
case ',': if (convertComma) *str++ = ';'; break;
case ',': if (convertComma) *str++ = '|'; break;
case '[': *str++ = (convertBrackets) ? '_' : '['; break;
case ']': *str++ = (convertBrackets) ? '_' : ']'; break;
case '#': if (trimLocal) break; // else fall through
default: *str++ = c; break;
}
@ -3252,6 +3373,8 @@ char *efHNSprintfPrefix(hierName, str)
{
char *cp, c;
bool convertEqual = (EFTrimFlags & EF_CONVERTEQUAL) ? TRUE : FALSE;
bool convertComma = (EFTrimFlags & EF_CONVERTCOMMA) ? TRUE : FALSE;
bool convertBrackets = (EFTrimFlags & EF_CONVERTBRACKETS) ? TRUE : FALSE;
if (hierName->hn_parent)
str = efHNSprintfPrefix(hierName->hn_parent, str);
@ -3260,6 +3383,13 @@ char *efHNSprintfPrefix(hierName, str)
while (1) {
if (convertEqual && (*cp == '='))
*str = ':';
else if (convertBrackets && ((*cp == '[') || (*cp == ']')))
*str = '_';
else if (*cp == ',')
{
if (convertComma) *str = '|';
else str--;
}
else
*str = *cp;
if (!(*str)) break;

View File

@ -36,6 +36,11 @@ extern char *nodeSpiceHierName();
extern devMerge *mkDevMerge();
extern bool extHierSDAttr();
extern bool devIsKilled();
extern float getCurDevMult();
extern void addDevMult();
extern void setDevMult();
/* Options specific to ext2spice */
extern bool esDoExtResis;
extern bool esDoPorts;
@ -166,7 +171,7 @@ typedef struct {
/*
*---------------------------------------------------------
* Variables & macros used for merging parallel devs
* Variables used for merging parallel devs
* The merging of devs is based on the fact that spcdevVisit
* visits the devs in the same order all the time so the
* value of esFMult[i] keeps the multiplier for the ith dev
@ -174,31 +179,8 @@ typedef struct {
*/
#define DEV_KILLED ((float) -1.0)
#define FMULT_SIZE (1<<10)
#define devIsKilled(n) ( esFMult[(n)] <=(float)0.0 )
#define DEV_KILLED ((float) -1.0)
/* macro to add a dev's multiplier to the table and grow it if necessary */
#define addDevMult(f) \
{ \
if ( esFMult == NULL ) { \
esFMult = (float *) mallocMagic((unsigned) (esFMSize*sizeof(float))); \
} else if ( esFMIndex >= esFMSize ) { \
int i; \
float *op = esFMult ; \
esFMult = (float *) mallocMagic((unsigned) ((esFMSize = esFMSize*2)*sizeof(float))); \
for ( i = 0 ; i < esFMSize/2 ; i++ ) esFMult[i] = op[i]; \
if (op) freeMagic(op); \
} \
esFMult[esFMIndex++] = (float)(f); \
}
#define setDevMult(i,f) { esFMult[(i)] = (float)(f); }
#define getCurDevMult() ((esFMult && (esFMIndex > 0)) ? esFMult[esFMIndex-1] : (float)1.0)
#ifdef MAGIC_WRAPPER
#define atoCap(s) ((EFCapValue)atof(s))
#endif

View File

@ -23,10 +23,16 @@ EFread.o: EFread.c ../tcltk/tclmagic.h ../utils/magic.h ../utils/malloc.h \
../bplane/bplane.h ../bplane/bpOpaque.h ../utils/ihash.h \
../bplane/bpEnum.h ../utils/geofast.h ../bplane/bplaneInt.h \
../extflat/extflat.h ../extflat/EFint.h ../extract/extract.h \
../utils/paths.h
../extract/extractInt.h ../extract/extDebugInt.h ../utils/paths.h
EFsym.o: EFsym.c ../utils/magic.h ../utils/geometry.h ../utils/geofast.h \
../utils/hash.h ../utils/malloc.h ../utils/utils.h ../extflat/extflat.h \
../extflat/EFint.h
EFvisit.o: EFvisit.c ../utils/magic.h ../utils/geometry.h \
../utils/geofast.h ../utils/hash.h ../utils/malloc.h ../utils/utils.h \
../extflat/extflat.h ../extflat/EFint.h ../extract/extract.h
EFantenna.o: EFantenna.c ../tcltk/tclmagic.h ../utils/magic.h \
../utils/geometry.h ../utils/hash.h ../utils/utils.h ../utils/styles.h \
../tiles/tile.h ../database/database.h ../windows/windows.h \
../textio/textio.h ../dbwind/dbwind.h ../textio/txcommands.h \
../extflat/extflat.h ../extract/extract.h ../extract/extractInt.h \
../extract/extDebugInt.h ../utils/malloc.h

844
extflat/EFantenna.c Normal file
View File

@ -0,0 +1,844 @@
/*
* EFantenna.c --
*
* Program to flatten hierarchical .ext files and then execute an
* antenna violation check for every MOSFET device in the flattened
* design.
*
* Flattens the tree rooted at file.ext, reading in additional .ext
* files as specified by "use" lines in file.ext.
*
*/
#include <stdio.h>
#include <stdlib.h> /* for atof() */
#include <string.h>
#include <ctype.h>
#include <math.h> /* for INFINITY */
#ifdef MAGIC_WRAPPER
#include "tcltk/tclmagic.h"
#endif
#include "utils/magic.h"
#include "utils/geometry.h"
#include "utils/hash.h"
#include "utils/utils.h"
#include "utils/styles.h"
#include "tiles/tile.h"
#include "database/database.h"
#include "windows/windows.h"
#include "textio/textio.h"
#include "dbwind/dbwind.h"
#include "textio/txcommands.h"
#include "extflat/extflat.h"
#include "extract/extract.h"
#include "extract/extractInt.h"
#include "utils/malloc.h"
/* Forward declarations */
int antennacheckArgs();
int antennacheckVisit();
typedef struct {
long visitMask:MAXDEVTYPES;
} nodeClient;
typedef struct {
HierName *lastPrefix;
long visitMask:MAXDEVTYPES;
} nodeClientHier;
#define NO_RESCLASS -1
#define markVisited(client, rclass) \
{ (client)->visitMask |= (1<<rclass); }
#define clearVisited(client) \
{ (client)->visitMask = (long)0; }
#define beenVisited(client, rclass) \
( (client)->visitMask & (1<<rclass))
#define initNodeClient(node) \
{ \
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClient))); \
(( nodeClient *)(node)->efnode_client)->visitMask = (long) 0; \
}
#define initNodeClientHier(node) \
{ \
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClientHier))); \
((nodeClientHier *) (node)->efnode_client)->visitMask = (long) 0; \
}
/* Diagnostic */
int efGates;
static int efAntennaDebug = FALSE;
/* The extract file is designed to be independent of the magic database, */
/* but that means that the device types do not match magic database types. */
/* A lookup table is needed to cross-reference the device types. */
TileType *EFDeviceTypes;
typedef struct _aas {
int *accum; /* Pointer to array of accumulated areas per type */
int pNum; /* Plane of check */
Rect r; /* Holds any one visited rectangle */
CellDef *def; /* CellDef for adding feedback */
} AntennaAccumStruct;
typedef struct _gdas {
int accum; /* Accumulated area of all gates/diff */
Rect r; /* Holds any one visited rectangle */
CellDef *def; /* CellDef for adding feedback */
} GateDiffAccumStruct;
typedef struct _ams {
int pNum; /* Plane of check */
CellDef *def; /* CellDef for adding feedback */
} AntennaMarkStruct;
/*
* ----------------------------------------------------------------------------
*
* Main Tcl callback for command "magic::antennacheck"
*
* ----------------------------------------------------------------------------
*/
#define ANTENNACHECK_RUN 0
#define ANTENNACHECK_DEBUG 1
#define ANTENNACHECK_HELP 2
void
CmdAntennaCheck(w, cmd)
MagWindow *w;
TxCommand *cmd;
{
int i, flatFlags;
char *inName;
FILE *f;
TileType t;
int option = ANTENNACHECK_RUN;
int value;
int argc = cmd->tx_argc;
char **argv = cmd->tx_argv;
char **msg;
bool err_result;
short sd_rclass;
short sub_rclass;
char *devname;
char *subname;
int idx;
CellUse *editUse;
static char *cmdAntennaCheckOption[] = {
"[run] [options] run antennacheck on current cell\n"
" use \"run -help\" to get standard options",
"debug print detailed information about each error",
"help print help information",
NULL
};
if (cmd->tx_argc > 1)
{
option = Lookup(cmd->tx_argv[1], cmdAntennaCheckOption);
if (option < 0) option = ANTENNACHECK_RUN;
else argv++;
}
switch (option)
{
case ANTENNACHECK_RUN:
goto runantennacheck;
break;
case ANTENNACHECK_DEBUG:
efAntennaDebug = TRUE;
break;
case ANTENNACHECK_HELP:
usage:
for (msg = &(cmdAntennaCheckOption[0]); *msg != NULL; msg++)
{
TxPrintf(" %s\n", *msg);
}
break;
}
return;
runantennacheck:
if (ExtCurStyle->exts_planeOrderStatus == noPlaneOrder)
{
TxError("No planeorder specified for this process: "
"Cannot run antenna checks!\n");
return;
}
EFInit();
EFCapThreshold = INFINITY;
EFResistThreshold = INFINITY;
/* Process command line arguments */
inName = EFArgs(argc, argv, &err_result, antennacheckArgs, (ClientData) NULL);
if (err_result == TRUE)
{
EFDone();
return /* TCL_ERROR */;
}
if (inName == NULL)
{
/* Assume that we want to do exttospice on the currently loaded cell */
if (w == (MagWindow *) NULL)
windCheckOnlyWindow(&w, DBWclientID);
if (w == (MagWindow *) NULL)
{
TxError("Point to a window or specify a cell name.\n");
EFDone();
return /* TCL_ERROR */;
}
inName = ((CellUse *) w->w_surfaceID)->cu_def->cd_name;
}
editUse = (CellUse *)w->w_surfaceID;
/*
* Initializations specific to this program.
*/
/* Read the hierarchical description of the input circuit */
TxPrintf("Reading extract file.\n");
if (EFReadFile(inName, FALSE, FALSE, FALSE) == FALSE)
{
EFDone();
return /* TCL_ERROR */;
}
/* Convert the hierarchical description to a flat one */
flatFlags = EF_FLATNODES;
TxPrintf("Building flattened netlist.\n");
EFFlatBuild(inName, flatFlags);
/* Build device lookup table */
EFDeviceTypes = (TileType *)mallocMagic(MAXDEVTYPES * sizeof(TileType));
for (i = 0; i < MAXDEVTYPES; i++)
if (EFDevTypes[i])
EFDeviceTypes[i] = extGetDevType(EFDevTypes[i]);
efGates = 0;
TxPrintf("Running antenna checks.\n");
EFVisitDevs(antennacheckVisit, (ClientData)editUse);
EFFlatDone();
EFDone();
TxPrintf("antennacheck finished.\n");
freeMagic(EFDeviceTypes);
efAntennaDebug = FALSE;
}
/*
* ----------------------------------------------------------------------------
*
* antennacheckArgs --
*
* Process those arguments that are specific to antennacheck.
* Assumes that *pargv[0][0] is '-', indicating a flag
* argument.
*
* Results:
* None. TCL version returns False if an error is encountered
* while parsing arguments, True otherwise.
*
* Side effects:
* After processing an argument, updates *pargc and *pargv
* to point to after the argument.
*
* May initialize various global variables based on the
* arguments given to us.
*
* Exits in the event of an improper argument.
*
* ----------------------------------------------------------------------------
*/
int
antennacheckArgs(pargc, pargv)
int *pargc;
char ***pargv;
{
char **argv = *pargv, *cp;
int argc = *pargc;
switch (argv[0][1])
{
default:
TxError("Unrecognized flag: %s\n", argv[0]);
goto usage;
}
*pargv = argv;
*pargc = argc;
return 0;
usage:
TxError("Usage: antennacheck\n");
return 1;
}
/*
* ----------------------------------------------------------------------------
*
* AntennaGetNode --
*
* function to find a node given its hierarchical prefix and suffix
*
* Results:
* a pointer to the node struct or NULL
*
* ----------------------------------------------------------------------------
*/
EFNode *
AntennaGetNode(prefix, suffix)
HierName *prefix;
HierName *suffix;
{
HashEntry *he;
he = EFHNConcatLook(prefix, suffix, "output");
return(((EFNodeName *) HashGetValue(he))->efnn_node);
}
/*
* ----------------------------------------------------------------------------
*
* antennacheckVisit --
*
* Procedure to check for antenna violations from a single device.
* Called by EFVisitDevs().
*
* Results:
* Returns 0 always.
*
* Side effects:
* May tag other device records to avoid double-counting devices.
* Generates feedback entries if an antenna violation is found.
*
* ----------------------------------------------------------------------------
*/
int
antennacheckVisit(dev, hierName, scale, trans, editUse)
Dev *dev; /* Device being output */
HierName *hierName; /* Hierarchical path down to this device */
float scale; /* Scale transform for output */
Transform *trans; /* Coordinate transform */
CellUse *editUse; /* ClientData is edit cell use */
{
DevTerm *gate;
TileType t, conType;
int pos, pNum, pNum2, pmax, p, i, j, gatearea, diffarea, total;
double anttotal;
float saveRatio, ratioTotal;
int *antennaarea;
Rect r, gaterect;
EFNode *gnode;
SearchContext scx;
TileTypeBitMask gatemask, saveConMask;
bool antennaError;
extern CellDef *extPathDef; /* see extract/ExtLength.c */
extern CellUse *extPathUse; /* see extract/ExtLength.c */
extern int areaAccumFunc(), antennaAccumFunc(), areaMarkFunc();
antennaarea = (int *)mallocMagic(DBNumTypes * sizeof(int));
switch(dev->dev_class)
{
case DEV_FET:
case DEV_MOSFET:
case DEV_MSUBCKT:
case DEV_ASYMMETRIC:
/* Procedure:
*
* 1. If device gate node is marked visited, return.
* 2. Mark device gate node visited
* 3. For each plane from metal1 up (determined by planeorder):
* a. Run DBTreeCopyConnect()
* b. Accumulate gate area of connected devices
* c. Accumulate diffusion area of connected devices
* d. Accumulate metal area of connected devices
* e. Check against antenna ratio(s)
* f. Generate feedback if in violation of antenna rule
*
* NOTE: DBTreeCopyConnect() is used cumulatively, so that
* additional searching only needs to be done for the additional
* layer being searched.
*/
GeoTransRect(trans, &dev->dev_rect, &r);
gate = &dev->dev_terms[0];
gnode = AntennaGetNode(hierName, gate->dterm_node->efnode_name->efnn_hier);
if (gnode->efnode_client == (ClientData) NULL)
initNodeClient(gnode);
if (beenVisited((nodeClient *)gnode->efnode_client, 0))
return 0;
else
markVisited((nodeClient *)gnode->efnode_client, 0);
/* Diagnostic stuff */
efGates++;
if (efGates % 100 == 0) TxPrintf(" %d gates analyzed.\n", efGates);
/* Find the plane of the gate type */
t = EFDeviceTypes[dev->dev_type];
pNum = DBPlane(t);
pos = ExtCurStyle->exts_planeOrder[pNum];
pmax = ++pos;
/* Find the highest plane in the technology */
for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++)
if (ExtCurStyle->exts_planeOrder[p] > pmax)
pmax = ExtCurStyle->exts_planeOrder[p];
/* Create the yank cell if it doesn't already exist */
if (extPathDef == (CellDef *) NULL)
DBNewYank("__PATHYANK__", &extPathUse, &extPathDef);
/* Use the cellDef reserved for extraction */
/* DBCellClearDef(extPathDef); */ /* See below */
scx.scx_use = editUse;
scx.scx_trans = GeoIdentityTransform;
scx.scx_area = r;
/* gatemask is a mask of all gate types for MOSFET devices */
TTMaskZero(&gatemask);
for (i = 0; i < DBNumTypes; i++)
{
ExtDevice *ed;
char devclass;
if (ExtCurStyle->exts_device[i] != NULL)
{
for (ed = ExtCurStyle->exts_device[i]; ed; ed = ed->exts_next)
{
devclass = ed->exts_deviceClass;
switch (devclass)
{
case DEV_MOSFET:
case DEV_FET:
case DEV_ASYMMETRIC:
case DEV_MSUBCKT:
TTMaskSetType(&gatemask, i);
break;
}
}
}
}
for (; pos <= pmax; pos++)
{
GateDiffAccumStruct gdas;
AntennaAccumStruct aas;
AntennaMarkStruct ams;
/* Find the plane of pos */
for (p = 0; p < DBNumPlanes; p++)
if (ExtCurStyle->exts_planeOrder[p] == pos)
pNum2 = p;
/* Find the tiletype which is a contact and whose base is pNum2 */
/* (NOTE: Need to extend to all such contacts, as there may be */
/* more than one.) (Also should find these types up top, not */
/* within the loop.) */
/* Modify DBConnectTbl to limit connectivity to the plane */
/* of the antenna check and below */
conType = -1;
for (i = 0; i < DBNumTypes; i++)
if (DBIsContact(i) && DBPlane(i) == pNum2)
{
conType = i;
TTMaskZero(&saveConMask);
TTMaskSetMask(&saveConMask, &DBConnectTbl[i]);
TTMaskZero(&DBConnectTbl[i]);
for (j = 0; j < DBNumTypes; j++)
if (TTMaskHasType(&saveConMask, j) &&
(DBPlane(j) <= pNum2))
TTMaskSetType(&DBConnectTbl[i], j);
break;
}
for (i = 0; i < DBNumTypes; i++) antennaarea[i] = 0;
gatearea = 0;
diffarea = 0;
/* Note: Ideally, the addition of material in the next */
/* metal plane is additive. But that requires enumerating */
/* all the vias and using those as starting points for the */
/* next connectivity search, which needs to be coded. */
DBCellClearDef(extPathDef);
/* To do: Mark tiles so area count can be progressive */
DBTreeCopyConnect(&scx, &DBConnectTbl[t], 0,
DBConnectTbl, &TiPlaneRect, extPathUse);
/* Search planes of tie types and accumulate all tiedown areas */
gdas.accum = 0;
for (p = 0; p < DBNumPlanes; p++)
DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[p],
&TiPlaneRect, &ExtCurStyle->exts_antennaTieTypes,
areaAccumFunc, (ClientData)&gdas);
diffarea = gdas.accum;
/* Search plane of gate type and accumulate all gate area */
gdas.accum = 0;
DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[pNum],
&TiPlaneRect, &gatemask, areaAccumFunc, (ClientData)&gdas);
gatearea = gdas.accum;
/* Search metal planes and accumulate all antenna areas */
for (p = 0; p < DBNumPlanes; p++)
{
if (ExtCurStyle->exts_antennaModel & ANTENNAMODEL_PARTIAL)
if (p != pNum2) continue;
aas.pNum = p;
aas.accum = &antennaarea[0];
if (ExtCurStyle->exts_planeOrder[p] <= pos)
DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[p],
&TiPlaneRect, &DBAllButSpaceAndDRCBits,
antennaAccumFunc, (ClientData)&aas);
}
antennaError = FALSE;
if (diffarea == 0)
{
anttotal = 0.0;
saveRatio = 0.0;
for (i = 0; i < DBNumTypes; i++)
{
if (ExtCurStyle->exts_antennaRatio[i].ratioGate > 0)
{
anttotal += (double)antennaarea[i] /
(double)ExtCurStyle->exts_antennaRatio[i].ratioGate;
}
if (ExtCurStyle->exts_antennaRatio[i].ratioGate > saveRatio)
saveRatio = ExtCurStyle->exts_antennaRatio[i].ratioGate;
}
if (anttotal > (double)gatearea)
{
antennaError = TRUE;
if (efAntennaDebug == TRUE)
{
TxError("Antenna violation detected at plane %s\n",
DBPlaneLongNameTbl[pNum2]);
TxError("Effective antenna ratio %g > limit %g\n",
saveRatio * (float)anttotal / (float)gatearea,
saveRatio);
TxError("Gate rect (%d %d) to (%d %d)\n",
gdas.r.r_xbot, gdas.r.r_ybot,
gdas.r.r_xtop, gdas.r.r_ytop);
TxError("Antenna rect (%d %d) to (%d %d)\n",
aas.r.r_xbot, aas.r.r_ybot,
aas.r.r_xtop, aas.r.r_ytop);
}
}
}
else
{
anttotal = 0.0;
saveRatio = 0.0;
for (i = 0; i < DBNumTypes; i++)
if (ExtCurStyle->exts_antennaRatio[i].ratioDiffB != INFINITY)
{
ratioTotal = ExtCurStyle->exts_antennaRatio[i].ratioDiffB +
diffarea * ExtCurStyle->exts_antennaRatio[i].ratioDiffA;
if (ratioTotal > 0)
anttotal += (double)antennaarea[i] / (double)ratioTotal;
if (ratioTotal > saveRatio)
saveRatio = ratioTotal;
}
if (anttotal > (double)gatearea)
{
antennaError = TRUE;
if (efAntennaDebug == TRUE)
{
TxError("Antenna violation detected at plane %s\n",
DBPlaneLongNameTbl[pNum2]);
TxError("Effective antenna ratio %g > limit %g\n",
saveRatio * (float)anttotal / (float)gatearea,
saveRatio);
TxError("Gate rect (%d %d) to (%d %d)\n",
gdas.r.r_xbot, gdas.r.r_ybot,
gdas.r.r_xtop, gdas.r.r_ytop);
TxError("Antenna rect (%d %d) to (%d %d)\n",
aas.r.r_xbot, aas.r.r_ybot,
aas.r.r_xtop, aas.r.r_ytop);
}
}
}
if (antennaError)
{
/* Search plane of gate type and mark all gate areas */
ams.def = editUse->cu_def;
ams.pNum = pNum2;
DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[pNum],
&TiPlaneRect, &gatemask, areaMarkFunc, (ClientData)&ams);
/* Search metal planes and accumulate all antenna areas */
for (p = 0; p < DBNumPlanes; p++)
{
if (ExtCurStyle->exts_antennaModel & ANTENNAMODEL_PARTIAL)
if (p != pNum2) continue;
if (ExtCurStyle->exts_planeOrder[p] <= pos)
DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[p],
&TiPlaneRect, &DBAllButSpaceAndDRCBits,
areaMarkFunc, (ClientData)&ams);
}
}
/* Put the connect table back the way it was */
if (conType >= 0)
TTMaskSetMask(&DBConnectTbl[conType], &saveConMask);
}
}
freeMagic(antennaarea);
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* areaMarkFunc --
*
* Mark the tile areas searched with feedback entries
*
* ----------------------------------------------------------------------------
*/
int
areaMarkFunc(tile, ams)
Tile *tile;
AntennaMarkStruct *ams;
{
Rect rect;
char msg[200];
TiToRect(tile, &rect);
sprintf(msg, "Antenna error at plane %s\n", DBPlaneLongNameTbl[ams->pNum]);
DBWFeedbackAdd(&rect, msg, ams->def, 1, STYLE_PALEHIGHLIGHTS);
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* areaAccumFunc --
*
* Accumulate the total tile area searched
*
* ----------------------------------------------------------------------------
*/
int
areaAccumFunc(tile, gdas)
Tile *tile;
GateDiffAccumStruct *gdas;
{
Rect *rect = &(gdas->r);
int area, type;
TiToRect(tile, rect);
area = (rect->r_xtop - rect->r_xbot) * (rect->r_ytop - rect->r_ybot);
gdas->accum += area;
return 0;
}
/*
* ----------------------------------------------------------------------------
*
* antennaAccumFunc --
*
* Accumulate the total tile area searched, keeping an individual
* count for each tile type. If the antenna model is SIDEWALL, then
* calculate the area of the tile sidewall (tile perimeter * layer
* thickness), rather than the drawn tile area.
*
* ----------------------------------------------------------------------------
*/
int
antennaAccumFunc(tile, aaptr)
Tile *tile;
AntennaAccumStruct *aaptr;
{
Rect *rect = &(aaptr->r);
int area;
int type;
int *typeareas = aaptr->accum;
int plane = aaptr->pNum;
float thick;
type = TiGetType(tile);
TiToRect(tile, rect);
if (ExtCurStyle->exts_antennaRatio[type].areaType & ANTENNAMODEL_SIDEWALL)
{
/* Accumulate perimeter of tile where tile abuts space */
Tile *tp;
int perimeter = 0, pmax, pmin;
/* Top */
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp))
{
if (TiGetBottomType(tp) == TT_SPACE)
{
pmin = MAX(LEFT(tile), LEFT(tp));
pmax = MIN(RIGHT(tile), RIGHT(tp));
perimeter += (pmax - pmin);
}
}
/* Bottom */
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
{
if (TiGetTopType(tp) == TT_SPACE)
{
pmin = MAX(LEFT(tile), LEFT(tp));
pmax = MIN(RIGHT(tile), RIGHT(tp));
perimeter += (pmax - pmin);
}
}
/* Left */
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp))
{
if (TiGetRightType(tp) == TT_SPACE)
{
pmin = MAX(BOTTOM(tile), BOTTOM(tp));
pmax = MIN(TOP(tile), TOP(tp));
perimeter += (pmax - pmin);
}
}
/* Right */
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp))
{
if (TiGetLeftType(tp) == TT_SPACE)
{
pmin = MAX(BOTTOM(tile), BOTTOM(tp));
pmax = MIN(TOP(tile), TOP(tp));
perimeter += (pmax - pmin);
}
}
if (DBIsContact(type))
{
int cperim;
TileType ttype;
TileTypeBitMask sMask;
float thick;
cperim = ((rect->r_xtop - rect->r_xbot) + (rect->r_ytop - rect->r_ybot)) << 1;
/* For contacts, add the area of the perimeter to the */
/* residue (metal) type on the plane being searched. */
/* Then, if the plane is the same as the base type of */
/* the contact, add the entire perimeter area of the */
/* tile to the total for the contact type itself. */
DBFullResidueMask(type, &sMask);
for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++)
if (TTMaskHasType(&sMask, ttype))
if (DBTypeOnPlane(ttype, plane))
{
thick = ExtCurStyle->exts_thick[ttype];
typeareas[ttype] += (int)((float)perimeter * thick);
}
if (type >= DBNumUserLayers)
{
DBResidueMask(type, &sMask);
for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++)
if (TTMaskHasType(&sMask, ttype))
if (DBTypeOnPlane(ttype, plane))
{
thick = ExtCurStyle->exts_thick[ttype];
typeareas[ttype] += (int)((float)perimeter * thick);
break;
}
}
else
{
thick = ExtCurStyle->exts_thick[type];
typeareas[type] += (int)((float)perimeter * thick);
}
}
else
{
/* Area is perimeter times layer thickness */
thick = ExtCurStyle->exts_thick[type];
typeareas[type] += (int)((float)perimeter * thick);
}
}
else if (ExtCurStyle->exts_antennaRatio[type].areaType & ANTENNAMODEL_SURFACE)
{
/* Simple tile area calculation */
area = (rect->r_xtop - rect->r_xbot) * (rect->r_ytop - rect->r_ybot);
/* If type is a contact, then add area to both residues as well */
/* as the contact type. */
/* NOTE: Restrict area counts per plane so areas of contacts */
/* are not double-counted. */
if (DBIsContact(type))
{
TileType ttype;
TileTypeBitMask sMask;
DBFullResidueMask(type, &sMask);
for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++)
if (TTMaskHasType(&sMask, ttype))
if (DBTypeOnPlane(ttype, plane))
typeareas[ttype] += area;
if (type >= DBNumUserLayers)
{
DBResidueMask(type, &sMask);
for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++)
if (TTMaskHasType(&sMask, ttype))
if (DBTypeOnPlane(ttype, plane))
{
typeareas[ttype] += area;
break;
}
}
else
typeareas[type] += area;
}
else
typeareas[type] += area;
}
return 0;
}

View File

@ -160,6 +160,15 @@ EFArgs(argc, argv, err_result, argsProc, cdata)
HierName *hierName;
FILE *f;
char usage_text[] =
"Standard arguments: [-R] [-C] [-r rthresh] [-c cthresh] [-v]\n"
"[-p searchpath] [-s sym=value] [-S symfile] [-t trimchars]\n"
#ifdef MAGIC_WRAPPER
"[rootfile]\n";
#else
"[-T techname] rootfile\n";
#endif
if (err_result != NULL) *err_result = FALSE;
/* Hash table of nodes we're going to watch if -N given */
@ -209,8 +218,10 @@ EFArgs(argc, argv, err_result, argsProc, cdata)
goto usage;
if (strchr(cp, '!')) EFTrimFlags |= EF_TRIMGLOB;
if (strchr(cp, '#')) EFTrimFlags |= EF_TRIMLOCAL;
if (strchr(cp, ',')) EFTrimFlags |= EF_CONVERTCOMMAS;
if (strchr(cp, ',')) EFTrimFlags |= EF_CONVERTCOMMA;
if (strchr(cp, '=')) EFTrimFlags |= EF_CONVERTEQUAL;
if (strchr(cp, '[')) EFTrimFlags |= EF_CONVERTBRACKETS;
if (strchr(cp, ']')) EFTrimFlags |= EF_CONVERTBRACKETS;
break;
case 'C':
EFCapThreshold = (EFCapValue)INFINITE_THRESHOLD_F;
@ -268,6 +279,11 @@ EFArgs(argc, argv, err_result, argsProc, cdata)
case 'z':
efHNStats = TRUE;
break;
case 'h':
if (argsProc != NULL) (*argsProc)(&argc, &argv, cdata);
TxPrintf(usage_text);
if (err_result != NULL) *err_result = TRUE;
return NULL;
/*** Try a caller-supplied argument processing function ***/
default:
@ -310,19 +326,15 @@ EFArgs(argc, argv, err_result, argsProc, cdata)
realIn[cp - inname] = '\0';
inname = realIn;
}
return inname;
usage:
TxError("Standard arguments: [-R] [-C] [-r rthresh] [-c cthresh] [-v]\n"
"[-p searchpath] [-s sym=value] [-S symfile] [-t trimchars]\n"
TxError(usage_text);
#ifdef MAGIC_WRAPPER
"[rootfile]\n");
if (err_result != NULL) *err_result = TRUE;
return NULL;
#else
"[-T techname] rootfile\n");
exit (1);
/*NOTREACHED*/
#endif

View File

@ -63,6 +63,8 @@ void efNodeMerge();
bool efConnBuildName();
bool efConnInitSubs();
extern float locScale;
/*
* ----------------------------------------------------------------------------
@ -172,15 +174,15 @@ efBuildNode(def, isSubsnode, nodeName, nodeCap, x, y, layerName, av, ac)
HashSetValue(he, (char *) newname);
/* New node itself */
size = sizeof (EFNode) + (efNumResistClasses - 1) * sizeof (PerimArea);
size = sizeof (EFNode) + (efNumResistClasses - 1) * sizeof (EFPerimArea);
newnode = (EFNode *) mallocMagic((unsigned)(size));
newnode->efnode_flags = (isSubsnode == TRUE) ? EF_SUBS_NODE : 0;
newnode->efnode_cap = nodeCap;
newnode->efnode_attrs = (EFAttr *) NULL;
newnode->efnode_loc.r_xbot = x;
newnode->efnode_loc.r_ybot = y;
newnode->efnode_loc.r_xtop = x + 1;
newnode->efnode_loc.r_ytop = y + 1;
newnode->efnode_loc.r_xbot = (int)(0.5 + (float)x * locScale);
newnode->efnode_loc.r_ybot = (int)(0.5 + (float)y * locScale);
newnode->efnode_loc.r_xtop = newnode->efnode_loc.r_xbot + 1;
newnode->efnode_loc.r_ytop = newnode->efnode_loc.r_ybot + 1;
newnode->efnode_client = (ClientData) NULL;
if (layerName) newnode->efnode_type =
efBuildAddStr(EFLayerNames, &EFLayerNumNames, MAXTYPES, layerName);
@ -553,8 +555,8 @@ efBuildDeviceParams(name, argc, argv)
if (name[0] == ':')
{
newparm->parm_name = StrDup((char **)NULL, argv[n]);
newparm->parm_type[1] = '0' + n / 10;
newparm->parm_type[0] = '0' + n % 10;
newparm->parm_type[0] = '0' + n / 10;
newparm->parm_type[1] = '0' + n % 10;
}
else
newparm->parm_name = StrDup((char **)NULL, pptr + 1);
@ -591,23 +593,28 @@ efBuildDevice(def, class, type, r, argc, argv)
Rect *r; /* Coordinates of 1x1 rectangle entirely inside device */
int argc; /* Size of argv */
char *argv[]; /* Tokens for the rest of the dev line.
* The first depend on the type of device. The rest
* are taken in groups of 3, one for each terminal.
* Each group of 3 consists of the node name to which
* the terminal connects, the length of the terminal,
* and an attribute list (or the token 0).
* Starts with the last two position values, used to
* hash the device record. The next arguments depend
* on the type of device. The rest are taken in groups
* of 3, one for each terminal. Each group of 3 consists
* of the node name to which the terminal connects, the
* length of the terminal, and an attribute list (or the
* token 0).
*/
{
int n, nterminals, pn;
HashEntry *he;
DevTerm *term;
Dev *newdev, devtmp;
DevParam *newparm, *devp, *sparm;
char ptype, *pptr, **av;
char devhash[64];
int argstart = 1; /* start of terminal list in argv[] */
bool hasModel = strcmp(type, "None") ? TRUE : FALSE;
int area, perim; /* Total area, perimeter of primary type (i.e., channel) */
newdev = (Dev *)NULL;
devtmp.dev_subsnode = NULL;
devtmp.dev_cap = 0.0;
devtmp.dev_res = 0.0;
@ -681,7 +688,8 @@ efBuildDevice(def, class, type, r, argc, argv)
{
pn = *(argv[argstart] + 1) - '0';
if (pn == 0)
devtmp.dev_area = atoi(pptr);
devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
* locScale * locScale);
/* Otherwise, punt */
}
break;
@ -692,15 +700,15 @@ efBuildDevice(def, class, type, r, argc, argv)
{
pn = *(argv[argstart] + 1) - '0';
if (pn == 0)
devtmp.dev_perim = atoi(pptr);
devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale);
/* Otherwise, use verbatim */
}
break;
case 'l':
devtmp.dev_length = atoi(pptr);
devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
break;
case 'w':
devtmp.dev_width = atoi(pptr);
devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale);
break;
case 'c':
devtmp.dev_cap = (float)atof(pptr);
@ -713,7 +721,6 @@ efBuildDevice(def, class, type, r, argc, argv)
}
/* Check for optional substrate node */
switch (class)
{
case DEV_RES:
@ -743,93 +750,149 @@ efBuildDevice(def, class, type, r, argc, argv)
nterminals = (argc - argstart) / 3;
newdev = (Dev *) mallocMagic((unsigned) DevSize(nterminals));
newdev->dev_subsnode = devtmp.dev_subsnode;
newdev->dev_cap = devtmp.dev_cap;
newdev->dev_res = devtmp.dev_res;
newdev->dev_area = devtmp.dev_area;
newdev->dev_perim = devtmp.dev_perim;
newdev->dev_length = devtmp.dev_length;
newdev->dev_width = devtmp.dev_width;
newdev->dev_params = devtmp.dev_params;
/* Determine if this device has been seen before */
newdev->dev_nterm = nterminals;
newdev->dev_rect = *r;
newdev->dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, type);
newdev->dev_class = class;
sprintf(devhash, "%dx%d%s", r->r_xbot, r->r_ybot, type);
he = HashFind(&def->def_devs, devhash);
newdev = (Dev *)HashGetValue(he);
if (newdev)
{
/* Duplicate device. Duplicates will only appear in res.ext files
* where a device has nodes changed. Merge all properties of the
* original device with nodes from the new device. Keep the
* original device and discard the new one.
*
* Check that the device is actually the same device type and number
* of terminals. If not, throw an error and abandon the new device.
*/
if ((newdev->dev_class != class) ||
(strcmp(EFDevTypes[newdev->dev_type], type)))
{
TxError("Device %s %s at (%d, %d) overlaps incompatible device %s %s!\n",
extDevTable[class], type, r->r_xbot, r->r_ybot,
extDevTable[newdev->dev_class], EFDevTypes[newdev->dev_type]);
return 0;
}
else if (newdev->dev_nterm != nterminals)
{
TxError("Device %s %s at (%d, %d) overlaps device with incompatible"
" number of terminals (%d vs. %d)!\n",
extDevTable[class], type, r->r_xbot, r->r_ybot, nterminals,
newdev->dev_nterm);
return 0;
}
}
else
{
newdev = (Dev *) mallocMagic((unsigned) DevSize(nterminals));
/* Add this dev to the hash table for def */
HashSetValue(he, (ClientData)newdev);
newdev->dev_cap = devtmp.dev_cap;
newdev->dev_res = devtmp.dev_res;
newdev->dev_area = devtmp.dev_area;
newdev->dev_perim = devtmp.dev_perim;
newdev->dev_length = devtmp.dev_length;
newdev->dev_width = devtmp.dev_width;
newdev->dev_params = devtmp.dev_params;
newdev->dev_nterm = nterminals;
newdev->dev_rect = *r;
newdev->dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, type);
newdev->dev_class = class;
switch (class)
{
case DEV_FET: /* old-style "fet" record */
newdev->dev_area = atoi(argv[0]);
newdev->dev_perim = atoi(argv[1]);
break;
case DEV_MOSFET: /* new-style "device mosfet" record */
case DEV_ASYMMETRIC:
case DEV_BJT:
newdev->dev_length = atoi(argv[0]);
newdev->dev_width = atoi(argv[1]);
break;
case DEV_RES:
if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1]))
{
newdev->dev_length = atoi(argv[0]);
newdev->dev_width = atoi(argv[1]);
}
else if (StrIsNumeric(argv[0]))
{
newdev->dev_res = (float)atof(argv[0]);
}
else
{
if (hasModel)
{
efReadError("Error: expected L and W, got %s %s\n", argv[0],
argv[1]);
newdev->dev_length = 0;
newdev->dev_width = 0;
}
else
{
efReadError("Error: expected resistance value, got %s\n",
argv[0]);
newdev->dev_res = 0.0;
}
}
break;
case DEV_CAP:
case DEV_CAPREV:
if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1]))
{
newdev->dev_length = atoi(argv[0]);
newdev->dev_width = atoi(argv[1]);
}
else if (StrIsNumeric(argv[0]))
{
newdev->dev_cap = (float)atof(argv[0]);
}
else
{
if (hasModel)
{
efReadError("Error: expected L and W, got %s %s\n", argv[0],
argv[1]);
newdev->dev_length = 0;
newdev->dev_width = 0;
}
else
{
efReadError("Error: expected capacitance value, got %s\n",
argv[0]);
newdev->dev_cap = 0.0;
}
}
break;
}
}
newdev->dev_subsnode = devtmp.dev_subsnode;
switch (class)
{
case DEV_FET: /* old-style "fet" record */
newdev->dev_area = atoi(argv[0]);
newdev->dev_perim = atoi(argv[1]);
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
break;
case DEV_MOSFET: /* new-style "device mosfet" record */
case DEV_ASYMMETRIC:
case DEV_BJT:
newdev->dev_length = atoi(argv[0]);
newdev->dev_width = atoi(argv[1]);
/* "None" in the place of the substrate name means substrate is ignored */
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
break;
case DEV_RES:
if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1]))
{
newdev->dev_length = atoi(argv[0]);
newdev->dev_width = atoi(argv[1]);
}
else if (StrIsNumeric(argv[0]))
{
newdev->dev_res = (float)atof(argv[0]);
}
else
{
if (hasModel)
{
efReadError("Error: expected L and W, got %s %s\n", argv[0],
argv[1]);
newdev->dev_length = 0;
newdev->dev_width = 0;
}
else
{
efReadError("Error: expected resistance value, got %s\n", argv[0]);
newdev->dev_res = 0.0;
}
}
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
break;
case DEV_CAP:
case DEV_CAPREV:
if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1]))
{
newdev->dev_length = atoi(argv[0]);
newdev->dev_width = atoi(argv[1]);
}
else if (StrIsNumeric(argv[0]))
{
newdev->dev_cap = (float)atof(argv[0]);
}
else
{
if (hasModel)
{
efReadError("Error: expected L and W, got %s %s\n", argv[0],
argv[1]);
newdev->dev_length = 0;
newdev->dev_width = 0;
}
else
{
efReadError("Error: expected capacitance value, got %s\n", argv[0]);
newdev->dev_cap = 0.0;
}
}
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
@ -859,10 +922,6 @@ efBuildDevice(def, class, type, r, argc, argv)
#undef TERM_PERIM
#undef TERM_ATTRS
/* Add this dev to the list for def */
newdev->dev_next = def->def_devs;
def->def_devs = newdev;
return 0;
}
@ -1123,12 +1182,26 @@ efBuildUse(def, subDefName, subUseId, ta, tb, tc, td, te, tf)
}
else
{
*cp = '\0';
newuse->use_id = StrDup((char **) NULL, subUseId);
*cp = '[';
(void) sscanf(cp, "[%d:%d:%d][%d:%d:%d]",
/* Note: Preserve any use of brackets as-is other than the */
/* standard magic array notation below. This allows, for */
/* example, verilog instance arrays read from DEF files to */
/* be passed through correctly. */
if ((sscanf(cp, "[%d:%d:%d][%d:%d:%d]",
&newuse->use_xlo, &newuse->use_xhi, &newuse->use_xsep,
&newuse->use_ylo, &newuse->use_yhi, &newuse->use_ysep);
&newuse->use_ylo, &newuse->use_yhi, &newuse->use_ysep)) == 6)
{
*cp = '\0';
newuse->use_id = StrDup((char **) NULL, subUseId);
*cp = '[';
}
else
{
newuse->use_id = StrDup((char **) NULL, subUseId);
newuse->use_xlo = newuse->use_xhi = 0;
newuse->use_ylo = newuse->use_yhi = 0;
newuse->use_xsep = newuse->use_ysep = 0;
}
}
he = HashFind(&def->def_uses, newuse->use_id);
@ -1168,7 +1241,7 @@ efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac)
int n;
Connection *conn;
unsigned size = sizeof (Connection)
+ (efNumResistClasses - 1) * sizeof (PerimArea);
+ (efNumResistClasses - 1) * sizeof (EFPerimArea);
conn = (Connection *) mallocMagic((unsigned)(size));
@ -1178,8 +1251,9 @@ efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac)
conn->conn_next = def->def_conns;
for (n = 0; n < efNumResistClasses && ac > 1; n++, ac -= 2)
{
conn->conn_pa[n].pa_area = atoi(*av++);
conn->conn_pa[n].pa_perim = atoi(*av++);
conn->conn_pa[n].pa_area = (int)(0.5 + (float)atoi(*av++)
* locScale * locScale);
conn->conn_pa[n].pa_perim = (int)(0.5 + (float)atoi(*av++) * locScale);
}
for ( ; n < efNumResistClasses; n++)
conn->conn_pa[n].pa_area = conn->conn_pa[n].pa_perim = 0;
@ -1211,14 +1285,14 @@ efBuildResistor(def, nodeName1, nodeName2, resistance)
Def *def; /* Def to which this connection is to be added */
char *nodeName1; /* Name of first node in resistor */
char *nodeName2; /* Name of second node in resistor */
float resistance; /* Resistor value */
int resistance; /* Resistor value */
{
Connection *conn;
conn = (Connection *) mallocMagic((unsigned)(sizeof (Connection)));
if (efConnInitSubs(conn, nodeName1, nodeName2))
{
conn->conn_res = resistance;
conn->conn_res = (float)resistance;
conn->conn_next = def->def_resistors;
def->def_resistors = conn;
}
@ -1682,6 +1756,36 @@ efFreeUseTable(table)
}
}
/*
* ----------------------------------------------------------------------------
*
* efFreeDevTable --
*
* Free the device records allocated for each entry in the device hash table,
* the memory allocated by the device, leaving the hash entry null.
*
* ----------------------------------------------------------------------------
*/
void
efFreeDevTable(table)
HashTable *table;
{
Dev *dev;
HashSearch hs;
HashEntry *he;
int n;
HashStartSearch(&hs);
while (he = HashNext(table, &hs))
{
dev = (Dev *)HashGetValue(he);
for (n = 0; n < (int)dev->dev_nterm; n++)
if (dev->dev_terms[n].dterm_attrs)
freeMagic((char *) dev->dev_terms[n].dterm_attrs);
freeMagic((char *) dev);
}
}
/*
* ----------------------------------------------------------------------------

View File

@ -103,7 +103,6 @@ EFDone()
Kill *kill;
Def *def;
Use *use;
Dev *dev;
int n;
HashStartSearch(&hs);
@ -114,22 +113,18 @@ EFDone()
efFreeNodeTable(&def->def_nodes);
efFreeNodeList(&def->def_firstn);
efFreeUseTable(&def->def_uses);
efFreeDevTable(&def->def_devs);
HashKill(&def->def_nodes);
HashKill(&def->def_dists);
HashKill(&def->def_uses);
HashKill(&def->def_devs);
for (conn = def->def_conns; conn; conn = conn->conn_next)
efFreeConn(conn);
for (conn = def->def_caps; conn; conn = conn->conn_next)
efFreeConn(conn);
for (conn = def->def_resistors; conn; conn = conn->conn_next)
efFreeConn(conn);
for (dev = def->def_devs; dev; dev = dev->dev_next)
{
for (n = 0; n < (int)dev->dev_nterm; n++)
if (dev->dev_terms[n].dterm_attrs)
freeMagic((char *) dev->dev_terms[n].dterm_attrs);
freeMagic((char *) dev);
}
for (kill = def->def_kills; kill; kill = kill->kill_next)
{
freeMagic(kill->kill_name);
@ -151,13 +146,6 @@ EFDone()
EFTech = (char *)NULL;
}
/* Free up all HierNames that were stored in efFreeHashTable */
/*
HashStartSearch(&hs);
while (he = HashNext(&efFreeHashTable, &hs))
freeMagic(he->h_key.h_ptr);
*/
/* Free up the parameter name tables for each device */
HashStartSearch(&hs);
@ -244,7 +232,6 @@ efDefNew(name)
newdef->def_conns = (Connection *) NULL;
newdef->def_caps = (Connection *) NULL;
newdef->def_resistors = (Connection *) NULL;
newdef->def_devs = (Dev *) NULL;
newdef->def_kills = (Kill *) NULL;
/* Initialize circular list of nodes */
@ -257,6 +244,9 @@ efDefNew(name)
/* Initialize hash table of node names */
HashInit(&newdef->def_nodes, INITNODESIZE, HT_STRINGKEYS);
/* Initialize hash table of devices */
HashInit(&newdef->def_devs, INITNODESIZE, HT_STRINGKEYS);
/* Initialize hash table of distances */
HashInitClient(&newdef->def_dists, INITNODESIZE, HT_CLIENTKEYS,
efHNDistCompare, efHNDistCopy, efHNDistHash, efHNDistKill);

View File

@ -59,7 +59,8 @@ bool efFlatGlobCmp(HierName *, HierName *);
char *efFlatGlobCopy(HierName *);
void efFlatGlobError(EFNodeName *, EFNodeName *);
int efAddNodes(HierContext *, bool);
int efAddOneConn(HierContext *, char *, char *, Connection *);
int efAddConns(HierContext *, bool);
int efAddOneConn(HierContext *, char *, char *, Connection *, bool);
/*
@ -126,7 +127,7 @@ EFFlatBuild(name, flags)
if (flags & EF_NOFLATSUBCKT)
efFlatNodesStdCell(&efFlatContext);
else
efFlatNodes(&efFlatContext);
efFlatNodes(&efFlatContext, FALSE, TRUE);
efFlatKills(&efFlatContext);
if (!(flags & EF_NONAMEMERGE))
efFlatGlob();
@ -193,8 +194,8 @@ EFFlatBuildOneLevel(def, flags)
efFlatContext.hc_x = efFlatContext.hc_y = 0;
efFlatRootUse.use_def = efFlatRootDef;
/* Record all nodes of the next level in the hierarchy */
efHierSrUses(&efFlatContext, efAddNodes, (ClientData)TRUE);
/* Record all nodes down the hierarchy from here */
efFlatNodes(&efFlatContext, (ClientData)TRUE, (ClientData)FALSE);
/* Expand all subcells that contain connectivity information but */
/* no active devices (including those in subcells). */
@ -205,12 +206,12 @@ EFFlatBuildOneLevel(def, flags)
if (usecount > 0)
efHierSrUses(&efFlatContext, efFlatNodesDeviceless, (ClientData)&usecount);
if ((usecount == 0) && (efFlatRootUse.use_def->def_devs == NULL))
if ((usecount == 0) && (HashGetNumEntries(&efFlatRootUse.use_def->def_devs) == 0))
efFlatRootUse.use_def->def_flags |= DEF_NODEVICES;
/* Record all local nodes */
efAddNodes(&efFlatContext, FALSE);
efAddConns(&efFlatContext);
efAddConns(&efFlatContext, TRUE);
efFlatKills(&efFlatContext);
if (!(flags & EF_NONAMEMERGE))
@ -291,16 +292,16 @@ EFFlatDone()
*/
int
efFlatNodes(hc)
efFlatNodes(hc, stdcell, doWarn)
HierContext *hc;
{
(void) efHierSrUses(hc, efFlatNodes);
/* Add all our own nodes to the table */
efAddNodes(hc, FALSE);
efAddNodes(hc, stdcell);
/* Process our own connections and adjustments */
(void) efAddConns(hc);
(void) efAddConns(hc, doWarn);
return (0);
}
@ -352,7 +353,7 @@ efFlatNodesStdCell(hc)
/* Process our own connections and adjustments */
if (!(hc->hc_use->use_def->def_flags & DEF_SUBCIRCUIT))
(void) efAddConns(hc);
(void) efAddConns(hc, TRUE);
return (0);
}
@ -372,13 +373,13 @@ efFlatNodesDeviceless(hc, cdata)
if (newcount > 0)
efHierSrUses(hc, efFlatNodesDeviceless, (ClientData)&newcount);
if ((hc->hc_use->use_def->def_devs == NULL) && (newcount == 0))
if ((HashGetNumEntries(&hc->hc_use->use_def->def_devs) == 0) && (newcount == 0))
{
/* Add all our own nodes to the table */
efAddNodes(hc, TRUE);
/* Process our own connections and adjustments */
efAddConns(hc);
efAddConns(hc, TRUE);
/* Mark this definition as having no devices, so it will not be visited */
hc->hc_use->use_def->def_flags |= DEF_NODEVICES;
@ -430,7 +431,7 @@ efAddNodes(hc, stdcell)
bool is_subcircuit = (def->def_flags & DEF_SUBCIRCUIT) ? TRUE : FALSE;
scale = def->def_scale;
size = sizeof (EFNode) + (efNumResistClasses-1) * sizeof (PerimArea);
size = sizeof (EFNode) + (efNumResistClasses-1) * sizeof (EFPerimArea);
for (node = (EFNode *) def->def_firstn.efnode_next;
node != &def->def_firstn;
@ -467,10 +468,10 @@ efAddNodes(hc, stdcell)
newnode->efnode_type = node->efnode_type;
if (!stdcell)
bcopy((char *) node->efnode_pa, (char *) newnode->efnode_pa,
efNumResistClasses * sizeof (PerimArea));
efNumResistClasses * sizeof (EFPerimArea));
else
bzero((char *) newnode->efnode_pa,
efNumResistClasses * sizeof (PerimArea));
efNumResistClasses * sizeof (EFPerimArea));
GeoTransRect(&hc->hc_trans, &node->efnode_loc, &newnode->efnode_loc);
/* Scale the result by "scale" --- hopefully we end up with an integer */
@ -527,6 +528,7 @@ efAddNodes(hc, stdcell)
HashSetValue(he, (char *) newname);
newname->efnn_node = newnode;
newname->efnn_hier = hierName;
newname->efnn_port = -1;
if (newnode->efnode_name)
{
newname->efnn_next = newnode->efnode_name->efnn_next;
@ -561,8 +563,9 @@ efAddNodes(hc, stdcell)
*/
int
efAddConns(hc)
efAddConns(hc, doWarn)
HierContext *hc;
bool doWarn;
{
Connection *conn;
@ -575,9 +578,9 @@ efAddConns(hc)
{
/* Special case for speed when no array info is present */
if (conn->conn_1.cn_nsubs == 0)
efAddOneConn(hc, conn->conn_name1, conn->conn_name2, conn);
efAddOneConn(hc, conn->conn_name1, conn->conn_name2, conn, doWarn);
else
efHierSrArray(hc, conn, efAddOneConn, (ClientData) NULL);
efHierSrArray(hc, conn, efAddOneConn, (ClientData)doWarn);
}
return (0);
@ -604,16 +607,17 @@ efAddConns(hc)
*/
int
efAddOneConn(hc, name1, name2, conn)
efAddOneConn(hc, name1, name2, conn, doWarn)
HierContext *hc;
char *name1, *name2; /* These are strings, not HierNames */
Connection *conn;
bool doWarn;
{
HashEntry *he1, *he2;
EFNode *node, *newnode;
int n;
he1 = EFHNLook(hc->hc_hierName, name1, "connect(1)");
he1 = EFHNLook(hc->hc_hierName, name1, (doWarn) ? "connect(1)" : NULL);
if (he1 == NULL)
return 0;
@ -629,7 +633,7 @@ efAddOneConn(hc, name1, name2, conn)
/* Merge this node with conn_name2 if one was specified */
if (name2)
{
he2 = EFHNLook(hc->hc_hierName, name2, "connect(2)");
he2 = EFHNLook(hc->hc_hierName, name2, (doWarn) ? "connect(2)" : NULL);
if (he2 == NULL)
return 0;
newnode = ((EFNodeName *) HashGetValue(he2))->efnn_node;
@ -1018,14 +1022,23 @@ efFlatSingleCap(hc, name1, name2, conn)
EFNode *n1, *n2;
HashEntry *he;
EFCoupleKey ck;
static char msg0[] = "cap(1)";
static char msg1[] = "cap(2)";
char *msg;
/* Connections that are below threshold (ext2spice hierarchy only) */
/* will be missing. Do not generate errors for these. */
if ((he = EFHNLook(hc->hc_hierName, name1, "cap(1)")) == NULL)
msg = (fabs((double)conn->conn_cap / 1000) < EFCapThreshold) ? NULL : msg0;
if ((he = EFHNLook(hc->hc_hierName, name1, msg)) == NULL)
return 0;
n1 = ((EFNodeName *) HashGetValue(he))->efnn_node;
if (n1->efnode_flags & EF_KILLED)
return 0;
if ((he = EFHNLook(hc->hc_hierName, name2, "cap(2)")) == NULL)
if (msg) msg = msg1;
if ((he = EFHNLook(hc->hc_hierName, name2, msg)) == NULL)
return 0;
n2 = ((EFNodeName *) HashGetValue(he))->efnn_node;
if (n2->efnode_flags & EF_KILLED)

View File

@ -471,6 +471,8 @@ efHierVisitDevs(hc, ca)
{
Def *def = hc->hc_use->use_def;
Dev *dev;
HashSearch hs;
HashEntry *he;
float scale;
/*
@ -482,8 +484,10 @@ efHierVisitDevs(hc, ca)
scale = (efScaleChanged && def->def_scale != 1.0) ? def->def_scale : 1.0;
/* Visit all devices */
for (dev = def->def_devs; dev; dev = dev->dev_next)
HashStartSearch(&hs);
while (he = HashNext(&def->def_devs, &hs))
{
dev = (Dev *)HashGetValue(he);
if (efHierDevKilled(hc, dev, hc->hc_hierName))
continue;

View File

@ -133,7 +133,7 @@ typedef struct conn
} conn_value;
struct conn *conn_next; /* Next connection in list */
PerimArea conn_pa[1]; /* Dummy; each connection actually has
EFPerimArea conn_pa[1]; /* Dummy; each connection actually has
* efNumResistClasses array elements
* allocated to it.
*/
@ -156,6 +156,7 @@ typedef struct def
HashTable def_nodes; /* Map names into EFNodeNames */
HashTable def_dists; /* Map pairs of names into Distances */
HashTable def_uses; /* Hash children of this def by name */
HashTable def_devs; /* Devices (hash by position) */
EFNode def_firstn; /* Head of circular list of nodes */
/* The following are all NULL-terminated lists */
@ -163,7 +164,6 @@ typedef struct def
Connection *def_conns; /* Hierarchical connections/adjustments */
Connection *def_caps; /* Two-terminal capacitors */
Connection *def_resistors; /* Two-terminal resistors */
Dev *def_devs; /* Devices */
Kill *def_kills; /* Used to modify hierarchical structure
* using information present only in the
* parent, e.g, to kill an old node and

View File

@ -38,6 +38,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "extflat/extflat.h"
#include "extflat/EFint.h"
#include "extract/extract.h"
#include "extract/extractInt.h"
#include "utils/paths.h"
#ifndef MAGIC_WRAPPER
@ -96,6 +97,7 @@ keyTable[] =
/* Data shared with EFerror.c */
char *efReadFileName; /* Name of file currently being read */
int efReadLineNum; /* Current line number in above file */
float locScale; /* Multiply values in the file by this on read-in */
/* Data local to this file */
static bool efReadDef();
@ -139,6 +141,7 @@ EFReadFile(name, dosubckt, resist, noscale)
if (def == NULL)
def = efDefNew(name);
locScale = 1.0;
rc = efReadDef(def, dosubckt, resist, noscale, TRUE);
if (EFArgTech) EFTech = StrDup((char **) NULL, EFArgTech);
if (EFScale == 0.0) EFScale = 1.0;
@ -265,6 +268,11 @@ readfile:
cscale = 1;
}
lscale = (float)atof(argv[3]);
if (lscale != ExtCurStyle->exts_unitsPerLambda)
{
locScale = lscale / ExtCurStyle->exts_unitsPerLambda;
lscale = ExtCurStyle->exts_unitsPerLambda;
}
if (lscale == 0.0)
{
efReadError("Bad linear scaling = 0; reset to 1.\n");
@ -283,10 +291,10 @@ readfile:
/* attr node xlo ylo xhi yhi type text */
case ATTR:
r.r_xbot = atoi(argv[2]);
r.r_ybot = atoi(argv[3]);
r.r_xtop = atoi(argv[4]);
r.r_ytop = atoi(argv[5]),
r.r_xbot = (int)(0.5 + (float)atoi(argv[2]) * locScale);
r.r_ybot = (int)(0.5 + (float)atoi(argv[3]) * locScale);
r.r_xtop = (int)(0.5 + (float)atoi(argv[4]) * locScale);
r.r_ytop = (int)(0.5 + (float)atoi(argv[5]) * locScale),
efBuildAttr(def, argv[1], &r, argv[6], argv[7]);
break;
@ -351,13 +359,12 @@ readfile:
break; /* we will deal with in efBuildDevice(). */
}
r.r_xbot = atoi(argv[3]);
r.r_ybot = atoi(argv[4]);
r.r_xtop = atoi(argv[5]);
r.r_ytop = atoi(argv[6]);
r.r_xbot = (int)(0.5 + (float)atoi(argv[3]) * locScale);
r.r_ybot = (int)(0.5 + (float)atoi(argv[4]) * locScale);
r.r_xtop = (int)(0.5 + (float)atoi(argv[5]) * locScale);
r.r_ytop = (int)(0.5 + (float)atoi(argv[6]) * locScale);
if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7,
&argv[7]) != 0)
if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7, &argv[7]) != 0)
{
efReadError("Incomplete terminal description for device\n");
continue;
@ -367,10 +374,10 @@ readfile:
/* for backwards compatibility */
/* fet type xlo ylo xhi yhi area perim substrate GATE T1 T2 ... */
case FET:
r.r_xbot = atoi(argv[2]);
r.r_ybot = atoi(argv[3]);
r.r_xtop = atoi(argv[4]);
r.r_ytop = atoi(argv[5]);
r.r_xbot = (int)(0.5 + (float)atoi(argv[2]) * locScale);
r.r_ybot = (int)(0.5 + (float)atoi(argv[3]) * locScale);
r.r_xtop = (int)(0.5 + (float)atoi(argv[4]) * locScale);
r.r_ytop = (int)(0.5 + (float)atoi(argv[5]) * locScale);
if (efBuildDevice(def, DEV_FET, argv[1], &r, argc - 6, &argv[6]) != 0)
{
efReadError("Incomplete terminal description for fet\n");
@ -426,10 +433,8 @@ readfile:
/* port name num xl yl xh yh type */
case PORT:
if (DoSubCircuit)
{
DoResist = FALSE;
def->def_flags |= DEF_SUBCIRCUIT;
}
efBuildPortNode(def, argv[1], atoi(argv[2]), atoi(argv[3]),
atoi(argv[4]), argv[7], toplevel);
break;
@ -566,8 +571,8 @@ resistChanged:
/* distance driver receiver min max */
case DIST:
efBuildDist(def, argv[1], argv[2],
(int)(lscale*atoi(argv[3])),
(int)(lscale*atoi(argv[4])));
(int)(lscale*atoi(argv[3])*locScale),
(int)(lscale*atoi(argv[4])*locScale));
break;
/* killnode nodename */
@ -576,8 +581,12 @@ resistChanged:
break;
/* resistor node1 node2 resistance */
/* NOTE: Value changed to floating-point 12/16/2019; */
/* (value * rscale) is in milliohms which is integer as */
/* resolution finer than milliohms is deemed unnecessary. */
case RESISTOR:
efBuildResistor(def, argv[1], argv[2], rscale*atoi(argv[3]));
efBuildResistor(def, argv[1], argv[2],
(int)(0.5 + (double)rscale * atof(argv[3])));
break;
/* abstract (no options/arguments) */
@ -719,11 +728,15 @@ start:
}
}
if (*get == '\\') /* Process quoted characters literally */
{
get++;
if (*get == '\0') break;
}
/* Process backslash characters literally unless they */
/* are followed by the end-of-line. */
if (*get == '\\')
if (*(get + 1) == '\0')
{
get++;
break;
}
/* Copy into token receiving area */
*put++ = *get++;

View File

@ -300,6 +300,8 @@ efVisitDevs(hc, ca)
Dev *dev;
float scale;
Transform t;
HashSearch hs;
HashEntry *he;
if (def->def_flags & DEF_SUBCIRCUIT) return 0;
@ -311,15 +313,17 @@ efVisitDevs(hc, ca)
t = hc->hc_trans;
/* Visit our own devices */
for (dev = def->def_devs; dev; dev = dev->dev_next)
HashStartSearch(&hs);
while (he = HashNext(&def->def_devs, &hs))
{
dev = (Dev *)HashGetValue(he);
if (efDevKilled(dev, hc->hc_hierName))
continue;
if ((*ca->ca_proc)(dev, hc->hc_hierName, scale, &t, ca->ca_cdata))
return 1;
}
return 0;
}
@ -859,7 +863,7 @@ EFHNOut(hierName, outf)
HierName *hierName;
FILE *outf;
{
bool trimGlob, trimLocal, trimComma;
bool trimGlob, trimLocal, convComma, convBrackets;
char *cp, c;
if (hierName->hn_parent) efHNOutPrefix(hierName->hn_parent, outf);
@ -868,13 +872,19 @@ EFHNOut(hierName, outf)
cp = hierName->hn_name;
trimGlob = (EFTrimFlags & EF_TRIMGLOB);
trimLocal = (EFTrimFlags & EF_TRIMLOCAL);
trimComma = (EFTrimFlags & EF_CONVERTCOMMAS);
convComma = (EFTrimFlags & EF_CONVERTCOMMA);
convBrackets = (EFTrimFlags & EF_CONVERTBRACKETS);
while (c = *cp++)
{
if (*cp)
{
if (trimComma && (c == ','))
putc(';', outf);
if (c == ',')
{
if (convComma)
putc('|', outf);
}
else if (convBrackets && ((c == '[') || (c == ']')))
putc('_', outf);
else
putc(c, outf);
}

View File

@ -5,7 +5,7 @@
MODULE = extflat
MAGICDIR = ..
SRCS = EFargs.c EFbuild.c EFdef.c EFerr.c EFflat.c EFhier.c EFname.c \
EFread.c EFsym.c EFvisit.c
EFread.c EFsym.c EFvisit.c EFantenna.c
include ${MAGICDIR}/defs.mak
include ${MAGICDIR}/rules.mak

View File

@ -40,8 +40,9 @@ typedef unsigned char U_char;
/* Flags to control output of node names. Stored in EFTrimFlags */
#define EF_TRIMGLOB 0x01 /* Delete trailing '!' from names */
#define EF_TRIMLOCAL 0x02 /* Delete trailing '#' from names */
#define EF_CONVERTCOMMAS 0x04 /* Change ',' to ';' in names */
#define EF_CONVERTEQUAL 0x08 /* Change '=' to ':' in names */
#define EF_CONVERTCOMMA 0x04 /* Change ',' to '|' in names, else remove */
#define EF_CONVERTEQUAL 0x08 /* Change '=' to ':' in names, else remove */
#define EF_CONVERTBRACKETS 0x10 /* Change '[' and ']' to '_' in names */
/*
* capacitance type now set to float
@ -141,7 +142,7 @@ typedef struct
{
int pa_area;
int pa_perim;
} PerimArea;
} EFPerimArea;
typedef struct efnhdr
{
@ -218,7 +219,7 @@ typedef struct efnode
*/
EFAttr *efnode_attrs; /* Node attribute list */
ClientData efnode_client; /* For hire */
PerimArea efnode_pa[1]; /* Dummy; each node actually has
EFPerimArea efnode_pa[1]; /* Dummy; each node actually has
* efNumResistClasses array elements
* allocated to it.
*/

File diff suppressed because it is too large Load Diff

View File

@ -424,7 +424,10 @@ extTreeSrPaintArea(scx, func, cdarg)
int pNum;
if ((def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0;
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0;
}
filter.tf_func = func;
filter.tf_arg = cdarg;
@ -461,7 +464,10 @@ extTreeSrFunc(scx, fp)
int pNum;
if ((def->cd_flags & CDAVAILABLE) == 0)
if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return (0);
{
bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return (0);
}
context.tc_scx = scx;
context.tc_filter = fp;
@ -480,3 +486,176 @@ extTreeSrFunc(scx, fp)
return (DBCellSrArea(scx, extTreeSrFunc, (ClientData) fp));
}
int
extCellSrArea(scx, func, cdarg)
SearchContext *scx;
/* Pointer to search context specifying a cell use to
* search, an area in the coordinates of the cell's
* def, and a transform back to "root" coordinates.
* The area may have zero size.
*/
int (*func)(); /* Function to apply at every tile found */
ClientData cdarg; /* Argument to pass to function */
{
int xlo, xhi, ylo, yhi, xbase, ybase, xsep, ysep, clientResult;
int srchBot, srchRight;
Plane *plane = scx->scx_use->cu_def->cd_planes[PL_CELL];
Tile *tp, *tpnew;
Rect *rect, *bbox;
CellUse *use;
SearchContext newScx;
CellTileBody *body;
Transform t, tinv;
TreeFilter filter;
Rect expanded;
Point start;
filter.tf_func = func;
filter.tf_arg = cdarg;
if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0)
{
bool dereference = (scx->scx_use->cu_def->cd_flags & CDDEREFERENCE) ?
TRUE : FALSE;
if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, dereference, NULL))
return 0;
}
/*
* In order to make this work with zero-size areas, we first expand
* the area by before searching the tile plane. extCellSrFunc will
* check carefully to throw out things that don't overlap the original
* area. The expansion is tricky because we mustn't expand infinities.
*/
expanded = scx->scx_area;
if (expanded.r_xbot > TiPlaneRect.r_xbot) expanded.r_xbot -= 1;
if (expanded.r_ybot > TiPlaneRect.r_ybot) expanded.r_ybot -= 1;
if (expanded.r_xtop < TiPlaneRect.r_xtop) expanded.r_xtop += 1;
if (expanded.r_ytop < TiPlaneRect.r_ytop) expanded.r_ytop += 1;
rect = &expanded;
/* Start along the top of the LHS of the search area */
start.p_x = rect->r_xbot;
start.p_y = rect->r_ytop - 1;
tp = plane->pl_hint;
GOTOPOINT(tp, &start);
/* Each iteration visits another tile on the LHS of the search area */
while (TOP(tp) > rect->r_ybot)
{
/* Each iteration enumerates another tile */
enumerate:
plane->pl_hint = tp;
if (SigInterruptPending)
return (1);
/*
* Since subcells are allowed to overlap, a single tile body may
* refer to many subcells and a single subcell may be referred to
* by many tile bodies. To insure that each CellUse is enumerated
* exactly once, the procedure given to DBCellSrArea is only applied
* to a CellUse when its lower right corner is contained in the
* tile to dbCellSrFunc (or otherwise at the last tile encountered
* in the event the lower right corner of the CellUse is outside the
* search rectangle).
*/
srchBot = scx->scx_area.r_ybot;
srchRight = scx->scx_area.r_xtop;
for (body = (CellTileBody *) TiGetBody(tp);
body != NULL;
body = body->ctb_next)
{
use = newScx.scx_use = body->ctb_use;
ASSERT(use != (CellUse *) NULL, "dbCellSrFunc");
/*
* The check below is to ensure that we only enumerate each
* cell once, even though it appears in many different tiles
* in the subcell plane.
*/
bbox = &use->cu_bbox;
if ( (BOTTOM(tp) <= bbox->r_ybot ||
(BOTTOM(tp) <= srchBot && bbox->r_ybot < srchBot))
&& (RIGHT(tp) >= bbox->r_xtop ||
(RIGHT(tp) >= srchRight && bbox->r_xtop >= srchRight)))
{
/*
* Make sure that this cell really does overlap the
* search area (it could be just touching because of
* the expand-by-one in DBCellSrArea).
*/
if (!GEO_OVERLAP(&scx->scx_area, bbox)) continue;
/* If not an array element, it's much simpler */
if (use->cu_xlo == use->cu_xhi && use->cu_ylo == use->cu_yhi)
{
newScx.scx_x = use->cu_xlo, newScx.scx_y = use->cu_yhi;
if (SigInterruptPending) return 1;
GEOINVERTTRANS(&use->cu_transform, &tinv);
GEOTRANSTRANS(&use->cu_transform, &scx->scx_trans,
&newScx.scx_trans);
GEOTRANSRECT(&tinv, &scx->scx_area, &newScx.scx_area);
if ((*func)(&newScx, filter.tf_arg) == 1)
return 1;
continue;
}
/*
* More than a single array element;
* check to see which ones overlap our search area.
*/
DBArrayOverlap(use, &scx->scx_area, &xlo, &xhi, &ylo, &yhi);
xsep = (use->cu_xlo > use->cu_xhi)
? -use->cu_xsep : use->cu_xsep;
ysep = (use->cu_ylo > use->cu_yhi)
? -use->cu_ysep : use->cu_ysep;
for (newScx.scx_y = ylo; newScx.scx_y<=yhi; newScx.scx_y++)
for (newScx.scx_x = xlo; newScx.scx_x<=xhi; newScx.scx_x++)
{
if (SigInterruptPending) return 1;
xbase = xsep * (newScx.scx_x - use->cu_xlo);
ybase = ysep * (newScx.scx_y - use->cu_ylo);
GEOTRANSTRANSLATE(xbase, ybase, &use->cu_transform, &t);
GEOINVERTTRANS(&t, &tinv);
GEOTRANSTRANS(&t, &scx->scx_trans, &newScx.scx_trans);
GEOTRANSRECT(&tinv, &scx->scx_area, &newScx.scx_area);
clientResult = (*func)(&newScx, filter.tf_arg);
if (clientResult == 2) goto skipArray;
else if (clientResult == 1) return 1;
}
}
skipArray: continue;
}
tpnew = TR(tp);
if (LEFT(tpnew) < rect->r_xtop)
{
while (BOTTOM(tpnew) >= rect->r_ytop) tpnew = LB(tpnew);
if (BOTTOM(tpnew) >= BOTTOM(tp) || BOTTOM(tp) <= rect->r_ybot)
{
tp = tpnew;
goto enumerate;
}
}
/* Each iteration returns one tile further to the left */
while (LEFT(tp) > rect->r_xbot)
{
if (BOTTOM(tp) <= rect->r_ybot)
return (0);
tpnew = LB(tp);
tp = BL(tp);
if (BOTTOM(tpnew) >= BOTTOM(tp) || BOTTOM(tp) <= rect->r_ybot)
{
tp = tpnew;
goto enumerate;
}
}
/* At left edge -- walk down to next tile along the left edge */
for (tp = LB(tp); RIGHT(tp) <= rect->r_xbot; tp = TR(tp))
/* Nothing */;
}
return (0);
}

View File

@ -71,7 +71,7 @@ typedef enum
AREAC, CONTACT, CSCALE,
DEFAULTAREACAP, DEFAULTOVERLAP, DEFAULTPERIMETER, DEFAULTSIDEOVERLAP,
DEFAULTSIDEWALL,
DEVICE, FET, FETRESIST, HEIGHT, LAMBDA, OVERC,
DEVICE, FET, FETRESIST, HEIGHT, ANTENNA, MODEL, TIEDOWN, LAMBDA, OVERC,
PERIMC, PLANEORDER, NOPLANEORDER, RESIST, RSCALE, SIDEHALO, SIDEOVERLAP,
SIDEWALL, STEP, STYLE, SUBSTRATE, UNITS, VARIANT
} Key;
@ -122,6 +122,15 @@ static keydesc keyTable[] = {
"height", HEIGHT, 4, 4,
"type height-above-subtrate thickness",
"antenna", ANTENNA, 4, 6,
"type [calc-type] [antenna-ratio-proportional] antenna-ratio-const",
"model", MODEL, 2, 3,
"partial-cumulative [area-sidewall]",
"tiedown", TIEDOWN, 2, 2,
"types",
"lambda", LAMBDA, 2, 2,
"units-per-lambda",
@ -157,7 +166,7 @@ static keydesc keyTable[] = {
"style", STYLE, 2, 4,
"stylename",
"substrate", SUBSTRATE, 3, 3,
"substrate", SUBSTRATE, 3, 4,
"types plane",
"units", UNITS, 2, 2,
@ -298,37 +307,47 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr)
TileType t;
TileTypeBitMask *rmask, *tmask;
int n, i = 0, j;
bool repeat;
bool repeat, found;
ExtDevice *devptr;
char *locdname;
char **uniquenamelist = (char **)mallocMagic(DBNumTypes * sizeof(char *));
found = FALSE;
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
{
locdname = ExtCurStyle->exts_transName[t];
if (locdname != NULL)
for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next)
{
repeat = FALSE;
for (j = 0; j < i; j++)
if (!strcmp(uniquenamelist[j], locdname))
{
repeat = TRUE;
break;
}
if (repeat == FALSE)
locdname = devptr->exts_deviceName;
if (locdname != NULL)
{
if (i == idx) break;
uniquenamelist[i] = locdname;
i++;
repeat = FALSE;
for (j = 0; j < i; j++)
if (!strcmp(uniquenamelist[j], locdname))
{
repeat = TRUE;
break;
}
if (repeat == FALSE)
{
if (i == idx)
{
found = TRUE;
break;
}
uniquenamelist[i] = locdname;
i++;
}
}
}
if (found == TRUE) break;
}
if (t == DBNumTypes) return FALSE;
if (devptr == NULL) return FALSE;
*devnameptr = locdname;
*subnameptr = ExtCurStyle->exts_transSubstrateName[t];
*subnameptr = devptr->exts_deviceSubstrateName;
tmask = &ExtCurStyle->exts_transSDTypes[t][0];
tmask = &devptr->exts_deviceSDTypes[0];
*sd_rclassptr = (short)(-1); /* NO_RESCLASS */
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
@ -341,7 +360,7 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr)
}
}
tmask = &ExtCurStyle->exts_transSubstrateTypes[t];
tmask = &devptr->exts_deviceSubstrateTypes;
*sub_rclassptr = (short)(-1); /* NO_RESCLASS */
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
@ -360,6 +379,35 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr)
#endif /* MAGIC_WRAPPER */
/*
* ----------------------------------------------------------------------------
*
* extGetDevType --
*
* Given an extraction model device name (devname), return the associated
* magic tiletype for the device.
*
* Results:
* Tile type that represents the device "devname" in the magic database.
*
* ----------------------------------------------------------------------------
*/
TileType
extGetDevType(devname)
char *devname;
{
TileType t;
ExtDevice *devptr;
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next)
if (!strcmp(devptr->exts_deviceName, devname))
return t;
return -1;
}
#ifdef THREE_D
/*
@ -538,23 +586,10 @@ extTechStyleAlloc()
TileType r;
style = (ExtStyle *) mallocMagic(sizeof (ExtStyle));
/* Make sure that the memory for character strings is NULL, */
/* because we want the Init section to free memory if it */
/* has been previously allocated. */
for (r = 0; r < NT; r++)
{
style->exts_transSubstrateName[r] = (char *) NULL;
style->exts_transName[r] = (char *) NULL;
style->exts_transSDTypes[r] = (TileTypeBitMask *) NULL;
style->exts_deviceParams[r] = (ParamList *) NULL;
style->exts_deviceClass[r] = (char) 0;
style->exts_transResist[r].ht_table = (HashEntry **) NULL;
}
return style;
}
/*
* ----------------------------------------------------------------------------
*
@ -575,7 +610,7 @@ extTechStyleInit(style)
style->exts_status = TECH_NOT_LOADED;
style->exts_sidePlanes = style->exts_overlapPlanes = 0;
TTMaskZero(&style->exts_transMask);
TTMaskZero(&style->exts_deviceMask);
style->exts_activeTypes = DBAllButSpaceAndDRCBits;
for (r = 0; r < NP; r++)
@ -589,7 +624,7 @@ extTechStyleInit(style)
{
TTMaskZero(&style->exts_nodeConn[r]);
TTMaskZero(&style->exts_resistConn[r]);
TTMaskZero(&style->exts_transConn[r]);
TTMaskZero(&style->exts_deviceConn[r]);
style->exts_allConn[r] = DBAllTypeBits;
style->exts_sheetResist[r] = 0;
@ -620,43 +655,41 @@ extTechStyleInit(style)
#ifdef ARIEL
TTMaskZero(&style->exts_subsTransistorTypes[r]);
#endif
if (style->exts_transSDTypes[r] != NULL)
freeMagic(style->exts_transSDTypes[r]);
style->exts_transSDTypes[r] = NULL;
style->exts_transSDCount[r] = 0;
style->exts_transGateCap[r] = (CapValue) 0;
style->exts_transSDCap[r] = (CapValue) 0;
if (style->exts_transSubstrateName[r] != (char *) NULL)
if (style->exts_device[r] != NULL)
{
freeMagic(style->exts_transSubstrateName[r]);
style->exts_transSubstrateName[r] = (char *) NULL;
}
if (style->exts_transName[r] != (char *) NULL)
{
freeMagic(style->exts_transName[r]);
style->exts_transName[r] = (char *) NULL;
}
while (style->exts_deviceParams[r] != (ParamList *) NULL)
{
/* Parameter lists are shared. Only free the last one! */
ExtDevice *devptr;
for (devptr = style->exts_device[r]; devptr; devptr = devptr->exts_next)
{
if (style->exts_deviceParams[r]->pl_count > 1)
{
style->exts_deviceParams[r]->pl_count--;
style->exts_deviceParams[r] = (ParamList *)NULL;
}
else
{
freeMagic(style->exts_deviceParams[r]->pl_name);
freeMagic(style->exts_deviceParams[r]);
style->exts_deviceParams[r] = style->exts_deviceParams[r]->pl_next;
if (devptr->exts_deviceSDTypes != NULL)
freeMagic(devptr->exts_deviceSDTypes);
if (devptr->exts_deviceSubstrateName != (char *) NULL)
freeMagic(devptr->exts_deviceSubstrateName);
if (devptr->exts_deviceName != (char *) NULL)
freeMagic(devptr->exts_deviceName);
while (devptr->exts_deviceParams != (ParamList *) NULL)
{
/* Parameter lists are shared. Only free the last one! */
if (devptr->exts_deviceParams->pl_count > 1)
{
devptr->exts_deviceParams->pl_count--;
devptr->exts_deviceParams = (ParamList *)NULL;
}
else
{
freeMagic(devptr->exts_deviceParams->pl_name);
freeMagic(devptr->exts_deviceParams);
devptr->exts_deviceParams = devptr->exts_deviceParams->pl_next;
}
}
if (devptr->exts_deviceResist.ht_table != (HashEntry **) NULL)
HashKill(&devptr->exts_deviceResist);
freeMagic(devptr);
}
style->exts_device[r] = (ExtDevice *)NULL;
}
style->exts_deviceClass[r] = (char)0;
if (style->exts_transResist[r].ht_table != (HashEntry **) NULL)
HashKill(&style->exts_transResist[r]);
HashInit(&style->exts_transResist[r], 8, HT_STRINGKEYS);
style->exts_linearResist[r] = 0;
}
style->exts_sideCoupleHalo = 0;
@ -667,14 +700,20 @@ extTechStyleInit(style)
style->exts_numResistClasses = 0;
style->exts_planeOrderStatus = needPlaneOrder ;
TTMaskZero(&style->exts_antennaTieTypes);
for (r = 0; r < DBNumTypes; r++)
{
style->exts_antennaRatio[r].areaType = (char)0;
style->exts_antennaRatio[r].ratioGate = 0.0;
style->exts_antennaRatio[r].ratioDiffA = 0.0;
style->exts_antennaRatio[r].ratioDiffB = 0.0;
style->exts_resistByResistClass[r] = 0;
TTMaskZero(&style->exts_typesByResistClass[r]);
style->exts_typesResistChanged[r] = DBAllButSpaceAndDRCBits;
TTMaskSetType(&style->exts_typesResistChanged[r], TT_SPACE);
style->exts_typeToResistClass[r] = -1;
}
doConvert = FALSE;
@ -685,6 +724,7 @@ extTechStyleInit(style)
style->exts_globSubstratePlane = -1;
TTMaskZero(&style->exts_globSubstrateTypes);
TTMaskZero(&style->exts_globSubstrateShieldTypes);
}
@ -798,14 +838,6 @@ ExtTechInit()
if (ExtCurStyle != NULL)
{
extTechStyleInit(ExtCurStyle);
/* Everything has been freed except the hash tables, which */
/* were just reinitialized by extTechStyleInit(). */
for (r = 0; r < NT; r++)
{
if (ExtCurStyle->exts_transResist[r].ht_table != (HashEntry **) NULL)
HashKill(&ExtCurStyle->exts_transResist[r]);
}
ExtCurStyle = NULL;
}
@ -1569,7 +1601,7 @@ ExtTechLine(sectionName, argc, argv)
PlaneMask pshield, pov;
CapValue capVal, gscap, gccap;
TileTypeBitMask types1, types2, termtypes[MAXSD];
TileTypeBitMask near, far, ov, shield, subsTypes;
TileTypeBitMask near, far, ov, shield, subsTypes, idTypes;
char *subsName, *transName, *cp, *endptr, *paramName;
TileType s, t, r, o;
keydesc *kp, *dv;
@ -1578,6 +1610,7 @@ ExtTechLine(sectionName, argc, argv)
EdgeCap *cnew;
ExtKeep *es, *newStyle;
ParamList *subcktParams, *newParam;
ExtDevice *devptr;
int refcnt;
double dhalo;
bool bad;
@ -1796,6 +1829,8 @@ ExtTechLine(sectionName, argc, argv)
case FET:
case FETRESIST:
case HEIGHT:
case ANTENNA:
case TIEDOWN:
case OVERC:
case PERIMC:
case RESIST:
@ -1888,24 +1923,32 @@ ExtTechLine(sectionName, argc, argv)
gccap = (argc > 7) ? aToCap(argv[7]) : (CapValue) 0;
}
TTMaskSetMask(&ExtCurStyle->exts_transMask, &types1);
TTMaskSetMask(&ExtCurStyle->exts_deviceMask, &types1);
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
if (TTMaskHasType(&types1, t))
{
TTMaskSetMask(ExtCurStyle->exts_transConn+t,&types1);
ExtCurStyle->exts_transSDTypes[t] = (TileTypeBitMask *)
devptr = (ExtDevice *)mallocMagic(sizeof(ExtDevice));
devptr->exts_deviceSDTypes = (TileTypeBitMask *)
mallocMagic(2 * sizeof(TileTypeBitMask));
ExtCurStyle->exts_transSDTypes[t][0] = termtypes[0];
ExtCurStyle->exts_transSDTypes[t][1] = DBZeroTypeBits;
ExtCurStyle->exts_transSDCount[t] = nterm;
ExtCurStyle->exts_transSDCap[t] = gscap;
ExtCurStyle->exts_transGateCap[t] = gccap;
ExtCurStyle->exts_deviceClass[t] = DEV_FET;
ExtCurStyle->exts_transName[t] =
StrDup((char **) NULL, transName);
ExtCurStyle->exts_transSubstrateName[t] =
devptr->exts_deviceSDTypes[0] = termtypes[0];
devptr->exts_deviceSDTypes[1] = DBZeroTypeBits;
devptr->exts_deviceSDCount = nterm;
devptr->exts_deviceSDCap = gscap;
devptr->exts_deviceGateCap = gccap;
devptr->exts_deviceClass = DEV_FET;
devptr->exts_deviceName = StrDup((char **) NULL, transName);
devptr->exts_deviceSubstrateName =
StrDup((char **) NULL, subsName);
ExtCurStyle->exts_transSubstrateTypes[t] = subsTypes;
devptr->exts_deviceSubstrateTypes = subsTypes;
devptr->exts_deviceIdentifierTypes = DBZeroTypeBits;
devptr->exts_deviceParams = (ParamList *) NULL;
devptr->exts_deviceResist.ht_table = (HashEntry **) NULL;
HashInit(&devptr->exts_deviceResist, 8, HT_STRINGKEYS);
TTMaskSetMask(ExtCurStyle->exts_deviceConn + t, &types1);
devptr->exts_next = ExtCurStyle->exts_device[t];
ExtCurStyle->exts_device[t] = devptr;
#ifdef ARIEL
{
int z;
@ -1936,12 +1979,11 @@ ExtTechLine(sectionName, argc, argv)
case DEFAULTSIDEWALL:
ExtTechSimpleSidewallCap(argv);
break;
case DEVICE:
/* Parse second argument for device type */
n = LookupStruct(argv[1], (LookupTable *) devTable, sizeof devTable[0]);
n = LookupStruct(argv[1], (LookupTable *)devTable, sizeof devTable[0]);
if (n < 0)
{
TechError("Illegal device. Legal devices are:\n\t");
@ -1999,6 +2041,18 @@ ExtTechLine(sectionName, argc, argv)
argc--;
}
/* If the last entry before any parameters starts with '+', */
/* then use it to set the identity marker. Otherwise, the */
/* identity marker is NULL. */
idTypes = DBZeroTypeBits;
if (*argv[argc - 1] == '+')
{
if ((DBTechNameMask(argv[argc - 1] + 1, &idTypes)) == 0)
idTypes = DBZeroTypeBits;
argc--;
}
/* Check the number of arguments after splitting out */
/* parameter entries. There is no limit on arguments in */
/* DEV_SUBCKT and DEV_MSUBCKT. */
@ -2194,31 +2248,47 @@ ExtTechLine(sectionName, argc, argv)
break;
}
TTMaskSetMask(&ExtCurStyle->exts_transMask, &types1);
TTMaskSetMask(&ExtCurStyle->exts_deviceMask, &types1);
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
{
if (TTMaskHasType(&types1, t))
{
TTMaskSetMask(ExtCurStyle->exts_transConn + t, &types1);
devptr = (ExtDevice *)mallocMagic(sizeof(ExtDevice));
for (i = 0; !TTMaskIsZero(&termtypes[i]); i++);
ExtCurStyle->exts_transSDTypes[t] = (TileTypeBitMask *)
devptr->exts_deviceSDTypes = (TileTypeBitMask *)
mallocMagic((i + 1) * sizeof(TileTypeBitMask));
for (i = 0; !TTMaskIsZero(&termtypes[i]); i++)
ExtCurStyle->exts_transSDTypes[t][i] = termtypes[i];
ExtCurStyle->exts_transSDTypes[t][i] = DBZeroTypeBits;
devptr->exts_deviceSDTypes[i] = termtypes[i];
devptr->exts_deviceSDTypes[i] = DBZeroTypeBits;
ExtCurStyle->exts_transSDCount[t] = nterm;
ExtCurStyle->exts_transSDCap[t] = gscap;
ExtCurStyle->exts_transGateCap[t] = gccap;
ExtCurStyle->exts_deviceClass[t] = class;
ExtCurStyle->exts_transName[t] =
StrDup((char **) NULL, transName);
devptr->exts_deviceSDCount = nterm;
devptr->exts_deviceSDCap = gscap;
devptr->exts_deviceGateCap = gccap;
devptr->exts_deviceClass = class;
devptr->exts_deviceName = StrDup((char **) NULL, transName);
if (subsName != NULL)
ExtCurStyle->exts_transSubstrateName[t] =
devptr->exts_deviceSubstrateName =
StrDup((char **) NULL, subsName);
ExtCurStyle->exts_transSubstrateTypes[t] = subsTypes;
else
devptr->exts_deviceSubstrateName = (char *)NULL;
devptr->exts_deviceSubstrateTypes = subsTypes;
devptr->exts_deviceIdentifierTypes = idTypes;
devptr->exts_deviceParams = (ParamList *) NULL;
if (subcktParams != NULL)
{
devptr->exts_deviceParams = subcktParams;
subcktParams->pl_count++;
}
devptr->exts_deviceResist.ht_table = (HashEntry **) NULL;
HashInit(&devptr->exts_deviceResist, 8, HT_STRINGKEYS);
devptr->exts_next = ExtCurStyle->exts_device[t];
ExtCurStyle->exts_device[t] = devptr;
TTMaskSetMask(ExtCurStyle->exts_deviceConn + t, &types1);
#ifdef ARIEL
{
int z;
@ -2231,11 +2301,6 @@ ExtTechLine(sectionName, argc, argv)
}
}
#endif
if (subcktParams != NULL)
{
ExtCurStyle->exts_deviceParams[t] = subcktParams;
subcktParams->pl_count++;
}
}
}
break;
@ -2249,13 +2314,19 @@ ExtTechLine(sectionName, argc, argv)
val = atoi(argv[3]);
isLinear = (strcmp(argv[2], "linear") == 0);
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
{
ExtDevice *devptr;
if (TTMaskHasType(&types1, t))
{
he = HashFind(&ExtCurStyle->exts_transResist[t], argv[2]);
HashSetValue(he, (spointertype)val);
if (isLinear)
ExtCurStyle->exts_linearResist[t] = val;
for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next)
{
he = HashFind(&devptr->exts_deviceResist, argv[2]);
HashSetValue(he, (spointertype)val);
if (isLinear)
devptr->exts_linearResist = val;
}
}
}
break;
case HEIGHT: {
float height, thick;
@ -2280,6 +2351,122 @@ ExtTechLine(sectionName, argc, argv)
}
}
break;
case ANTENNA: {
float antennaratio;
char areaType;
bool hasModel = FALSE;
int argidx = 2;
if (!StrIsNumeric(argv[2]))
{
if (!strcmp(argv[2], "surface") || !strcmp(argv[2], "area"))
{
areaType = ANTENNAMODEL_SURFACE;
hasModel = TRUE;
}
else if (!strcmp(argv[2], "sidewall") || !strcmp(argv[2], "perimeter"))
{
areaType = ANTENNAMODEL_SIDEWALL;
hasModel = TRUE;
}
else
{
TechError("Error in layer antenna calculation type \"%s\"; "
" must be \"surface\" or \"sidewall\"\n", argv[2]);
break;
}
}
if (hasModel == FALSE)
{
if (ExtCurStyle->exts_antennaModel & ANTENNAMODEL_SURFACE)
areaType = ANTENNAMODEL_SURFACE;
else if (ExtCurStyle->exts_antennaModel & ANTENNAMODEL_SIDEWALL)
areaType = ANTENNAMODEL_SIDEWALL;
else
TechError("No antenna calculation type given for layer(s) %s "
" and no default calculation type found.\n", argv[1]);
}
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
if (TTMaskHasType(&types1, t))
ExtCurStyle->exts_antennaRatio[t].areaType = areaType;
if (hasModel == TRUE) argidx = 3;
if (!StrIsNumeric(argv[argidx]))
{
TechError("Gate layer antenna ratio %s must be numeric\n", argv[argidx]);
break;
}
antennaratio = (float)strtod(argv[argidx], NULL);
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
if (TTMaskHasType(&types1, t))
ExtCurStyle->exts_antennaRatio[t].ratioGate = antennaratio;
argidx++;
if (!StrIsNumeric(argv[argidx]))
{
if (!strcasecmp(argv[argidx], "none"))
antennaratio = INFINITY;
else
{
TechError("Diff layer antenna ratio %s must be numeric\n",
argv[argidx]);
break;
}
}
else
antennaratio = (float)strtod(argv[argidx], NULL);
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
if (TTMaskHasType(&types1, t))
ExtCurStyle->exts_antennaRatio[t].ratioDiffB = antennaratio;
argidx++;
if (argidx < argc)
{
if (!StrIsNumeric(argv[argidx]))
{
TechError("Diff layer antenna ratio %s must be numeric\n",
argv[argidx]);
break;
}
antennaratio = (float)strtod(argv[argidx], NULL);
}
else
antennaratio = 0;
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
if (TTMaskHasType(&types1, t))
ExtCurStyle->exts_antennaRatio[t].ratioDiffA = antennaratio;
break;
}
case MODEL:
if (!strcmp(argv[1], "partial"))
ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_PARTIAL;
else if (!strcmp(argv[1], "cumulative"))
ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_CUMULATIVE;
else
TxError("Unknown antenna model \"%s\": Use \"partial\" or "
"\"cumulative\"");
if (argc > 2)
{
if (!strcmp(argv[2], "surface") || !strcmp(argv[2], "area"))
ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_SURFACE;
else if (!strcmp(argv[2], "sidewall") || !strcmp(argv[2], "perimeter"))
ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_SIDEWALL;
else
TxError("Unknown antenna model \"%s\": Use \"surface\" or "
"\"sidewall\"");
}
break;
case TIEDOWN:
TTMaskSetMask(&ExtCurStyle->exts_antennaTieTypes, &types1);
break;
case UNITS:
if (!strcmp(argv[1], "microns"))
doConvert = TRUE;
@ -2569,8 +2756,22 @@ ExtTechLine(sectionName, argc, argv)
ExtCurStyle->exts_stepSize = val;
break;
case SUBSTRATE:
/* If the last entry starts with '-', then use it to set */
/* the shield types. Otherwise, the shield types mask is */
/* NULL. */
idTypes = DBZeroTypeBits;
if (*argv[argc - 1] == '-')
{
if ((DBTechNameMask(argv[argc - 1] + 1, &idTypes)) == 0)
idTypes = DBZeroTypeBits;
argc--;
}
TTMaskZero(&ExtCurStyle->exts_globSubstrateTypes);
TTMaskZero(&ExtCurStyle->exts_globSubstrateShieldTypes);
TTMaskSetMask(&ExtCurStyle->exts_globSubstrateTypes, &types1);
ExtCurStyle->exts_globSubstrateShieldTypes = idTypes;
ExtCurStyle->exts_globSubstratePlane = DBTechNoisyNamePlane(argv[2]);
break;
case NOPLANEORDER: {
@ -2619,7 +2820,7 @@ diffplane:
*
* Postprocess the technology specific information for extraction.
* Builds the connectivity tables exts_nodeConn[], exts_resistConn[],
* and exts_transConn[].
* and exts_deviceConn[].
*
* Results:
* None.
@ -2664,9 +2865,9 @@ extTechFinalStyle(style)
for (r = TT_TECHDEPBASE; r < DBNumTypes; r++)
{
maskBits = style->exts_nodeConn[r] = DBConnectTbl[r];
if (!TTMaskHasType(&style->exts_transMask, r))
if (!TTMaskHasType(&style->exts_deviceMask, r))
{
TTMaskZero(&style->exts_transConn[r]);
TTMaskZero(&style->exts_deviceConn[r]);
}
for (s = TT_TECHDEPBASE; s < DBNumTypes; s++)
{
@ -2870,10 +3071,15 @@ zinit:
for (r = 0; r < DBNumTypes; r++)
{
style->exts_areaCap[r] *= sqfac;
style->exts_transSDCap[r] *= sqfac;
style->exts_transGateCap[r] *= sqfac;
ExtDevice *devptr;
for (devptr = style->exts_device[r]; devptr; devptr = devptr->exts_next)
{
devptr->exts_deviceSDCap *= sqfac;
devptr->exts_deviceGateCap *= sqfac;
}
style->exts_areaCap[r] *= sqfac;
for (s = 0; s < DBNumTypes; s++)
{
EdgeCap *ec;
@ -2899,6 +3105,10 @@ zinit:
ec = ec->ec_next)
ec->ec_cap *= 0.5;
}
/* Layer thickness and height are in microns, but are floating-point */
style->exts_thick[r] /= dscale;
style->exts_height[r] /= dscale;
}
/* side halo and step size are also in microns */
@ -2953,13 +3163,18 @@ ExtTechScale(scalen, scaled)
for (i = 0; i < DBNumTypes; i++)
{
ExtDevice *devptr;
style->exts_areaCap[i] *= sqn;
style->exts_areaCap[i] /= sqd;
style->exts_transSDCap[i] *= sqn;
style->exts_transSDCap[i] /= sqd;
style->exts_transGateCap[i] *= sqn;
style->exts_transGateCap[i] /= sqd;
for (devptr = style->exts_device[i]; devptr; devptr = devptr->exts_next)
{
devptr->exts_deviceSDCap *= sqn;
devptr->exts_deviceSDCap /= sqd;
devptr->exts_deviceGateCap *= sqn;
devptr->exts_deviceGateCap /= sqd;
}
style->exts_height[i] *= scaled;
style->exts_height[i] /= scalen;

View File

@ -361,7 +361,7 @@ extShowTech(name)
}
}
extShowTrans("Transistor", &ExtCurStyle->exts_transMask, out);
extShowTrans("Transistor", &ExtCurStyle->exts_deviceMask, out);
fprintf(out, "\nNode resistance and capacitance:\n");
fprintf(out, "type R-ohm/sq AreaC-ff/l**2\n");
@ -472,7 +472,7 @@ extShowTech(name)
extShowConnect("\nNode connectivity", ExtCurStyle->exts_nodeConn, out);
extShowConnect("\nResistive region connectivity", ExtCurStyle->exts_resistConn, out);
extShowConnect("\nTransistor connectivity", ExtCurStyle->exts_transConn, out);
extShowConnect("\nTransistor connectivity", ExtCurStyle->exts_deviceConn, out);
if (out != stdout)
(void) fclose(out);
@ -493,12 +493,17 @@ extShowTrans(name, mask, out)
for (t = 0; t < DBNumTypes; t++)
if (TTMaskHasType(mask, t))
{
fprintf(out, " %-8.8s %d terminals: ",
DBTypeShortName(t), ExtCurStyle->exts_transSDCount[t]);
extShowMask(&ExtCurStyle->exts_transSDTypes[t][0], out);
fprintf(out, "\n\tcap (gate-sd/gate-ch) = %lf/%lf\n",
ExtCurStyle->exts_transSDCap[t],
ExtCurStyle->exts_transGateCap[t]);
ExtDevice *devptr;
for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next)
{
fprintf(out, " %-8.8s %d terminals: ",
DBTypeShortName(t), devptr->exts_deviceSDCount);
extShowMask(&devptr->exts_deviceSDTypes[0], out);
fprintf(out, "\n\tcap (gate-sd/gate-ch) = %lf/%lf\n",
devptr->exts_deviceSDCap,
devptr->exts_deviceGateCap);
}
}
}

View File

@ -348,7 +348,7 @@ extTimesCellFunc(cs)
/* Count the number of transistors */
transList = (TransRegion *) ExtFindRegions(def, &TiPlaneRect,
&ExtCurStyle->exts_transMask, ExtCurStyle->exts_transConn,
&ExtCurStyle->exts_deviceMask, ExtCurStyle->exts_deviceConn,
extUnInit, extTransFirst, extTransEach);
ExtResetTiles(def, extUnInit);
for (tl = transList; tl; tl = tl->treg_next)

View File

@ -76,6 +76,7 @@ extern void ExtSetStyle();
extern void ExtPrintStyle();
extern void ExtCell();
#ifdef MAGIC_WRAPPER
extern bool ExtGetDevInfo();
extern bool ExtCompareStyle();

View File

@ -48,6 +48,19 @@ typedef int ResValue; /* Warning: in some places resistances are stored
* as ints. This is here for documentation only.
*/
typedef struct {
char areaType; /* ANTENNAMODEL_SURFACE or ANTENNAMODEL_SIDEWALL */
float ratioGate;
float ratioDiffA; /* Proportional */
float ratioDiffB; /* Constant */
} RatioValues;
/* Antenna models */
#define ANTENNAMODEL_PARTIAL 0x01
#define ANTENNAMODEL_CUMULATIVE 0x02
#define ANTENNAMODEL_SURFACE 0x04
#define ANTENNAMODEL_SIDEWALL 0x08
/* ------------------------ Parameter lists --------------------------- */
/* These lists keep track of what parameter names subcircuit definitions
@ -483,6 +496,82 @@ typedef struct extkeep
char *exts_name;
} ExtKeep;
/*
* Structure used to define transistors and other extracted devices
* One of these records is kept per tile type. However, the record
* can link to additional records through the "exts_next" record,
* so that multiple extraction devices can be defined for the same
* tile type, provided that each definition has a unique combination
* of exts_deviceSDTypes and exts_deviceSubstrateTypes.
*/
typedef struct extDevice
{
/* Name of each transistor type as output in .ext file */
char *exts_deviceName;
/* List of parameter names for each subcircuit type */
ParamList *exts_deviceParams;
/* Device class for each layer type */
char exts_deviceClass;
/*
* Per-square resistances for each possible transistor type,
* in the various regions that such a type might operate.
* The only operating region currently used is "linear",
* which the resistance extractor uses in its thresholding
* operation. NOTE: resistances in this table are in OHMS
* per square, not MILLIOHMS!
*/
HashTable exts_deviceResist;
ResValue exts_linearResist;
/*
* Mask of the types of tiles that connect to the channel terminals
* of a transistor type. The intent is that these will be the
* diffusion terminals of a transistor, ie, its source and drain.
* UPDATED May, 2008: Record is a list of type masks, allowing
* multiple terminal types in the case of, e.g., high-voltage
* or other asymmetric devices. The last entry in the list should
* be equal to DBSpaceBits.
*/
TileTypeBitMask *exts_deviceSDTypes;
/*
* Maximum number of terminals (source/drains) per transistor type.
* This table exists to allow the possibility of transistors with
* more than two diffusion terminals at some point in the future.
*/
int exts_deviceSDCount;
/* Currently unused: gate-source capacitance per unit perimeter */
CapValue exts_deviceSDCap;
/* Currently unused: gate-channel capacitance per unit area */
CapValue exts_deviceGateCap;
/*
* Each type of transistor has a substrate node. By default,
* it is the one given by exts_deviceSubstrateName[t]. However,
* if the mask exts_deviceSubstrateTypes is non-zero, and if
* the transistor overlaps material of one of the types in the
* mask, then the transistor substrate node is the node of the
* material it overlaps.
*/
char *exts_deviceSubstrateName;
TileTypeBitMask exts_deviceSubstrateTypes;
/*
* Each device type can have any number of extract models based
* on identifier layers (such as thickox, esd, etc.)
*/
TileTypeBitMask exts_deviceIdentifierTypes;
struct extDevice *exts_next;
} ExtDevice;
/*
* Parameters for the process being extracted.
* We try to use use integers here, rather than floats, to be nice to
@ -524,11 +613,11 @@ typedef struct extstyle
TileTypeBitMask exts_resistConn[NT];
/*
* Connectivity for determining transistors.
* Each transistor type should connect only to itself.
* Connectivity for determining devices.
* Each devices type should connect only to itself.
* Nothing else should connect to anything else.
*/
TileTypeBitMask exts_transConn[NT];
TileTypeBitMask exts_deviceConn[NT];
/*
* Set of types to be considered for extraction. Types not in
@ -580,6 +669,14 @@ typedef struct extstyle
float exts_height[NT];
float exts_thick[NT];
char exts_antennaModel;
/* Antenna area ratio for each layer */
RatioValues exts_antennaRatio[NT];
/* Mask of types that tie down antennas */
TileTypeBitMask exts_antennaTieTypes;
/*
* Capacitance to substrate for each tile type, in units of
* attofarads per square lambda.
@ -779,65 +876,14 @@ typedef struct extstyle
*/
TileTypeBitMask exts_sideEdges[NT];
/* Transistors */
/* Devices */
/* Name of each transistor type as output in .ext file */
char *exts_transName[NT];
/* Contains one for each type of device, zero for all other tile types */
TileTypeBitMask exts_deviceMask;
/* List of parameter names for each subcircuit type */
ParamList *exts_deviceParams[NT];
/* All information about a device goes in this record (see above) */
ExtDevice *exts_device[NT];
/* Device class for each layer type */
char exts_deviceClass[NT];
/* Contains one for each type of fet, zero for all other types */
TileTypeBitMask exts_transMask;
/*
* Per-square resistances for each possible transistor type,
* in the various regions that such a type might operate.
* The only operating region currently used is "linear",
* which the resistance extractor uses in its thresholding
* operation. NOTE: resistances in this table are in OHMS
* per square, not MILLIOHMS!
*/
HashTable exts_transResist[NT];
ResValue exts_linearResist[NT];
/*
* Mask of the types of tiles that connect to the channel terminals
* of a transistor type. The intent is that these will be the
* diffusion terminals of a transistor, ie, its source and drain.
* UPDATED May, 2008: Record is a list of type masks, allowing
* multiple terminal types in the case of, e.g., high-voltage
* or other asymmetric devices. The last entry in the list should
* be equal to DBSpaceBits.
*/
TileTypeBitMask *exts_transSDTypes[NT];
/*
* Maximum number of terminals (source/drains) per transistor type.
* This table exists to allow the possibility of transistors with
* more than two diffusion terminals at some point in the future.
*/
int exts_transSDCount[NT];
/* Currently unused: gate-source capacitance per unit perimeter */
CapValue exts_transSDCap[NT];
/* Currently unused: gate-channel capacitance per unit area */
CapValue exts_transGateCap[NT];
/*
* Each type of transistor has a substrate node. By default,
* it is the one given by exts_transSubstrateName[t]. However,
* if the mask exts_transSubstrateTypes[t] is non-zero, and if
* the transistor overlaps material of one of the types in the
* mask, then the transistor substrate node is the node of the
* material it overlaps. If exts_transSub
*/
char *exts_transSubstrateName[NT];
TileTypeBitMask exts_transSubstrateTypes[NT];
#ifdef ARIEL
TileTypeBitMask exts_subsTransistorTypes[NT];
#endif /* ARIEL */
@ -847,11 +893,16 @@ typedef struct extstyle
* types that connect to the substrate. Since for non-SOI
* processes, this generally is used to specify that space on
* the well plane is the substrate, the plane number for the
* well plane is given, too.
* well plane is given, too. The "shield types" mask is a
* mask of types that prevent any types in exts_globSubstrateTypes
* from contacting the substrate (e.g., deep nwell might be a
* shielding type, or it could be a special marker layer like
* "not_substrate").
*/
char *exts_globSubstrateName;
TileTypeBitMask exts_globSubstrateTypes;
int exts_globSubstratePlane;
TileTypeBitMask exts_globSubstrateShieldTypes;
/* Scaling */
/*
@ -1024,6 +1075,7 @@ extern NodeRegion *extBasic();
extern NodeRegion *extFindNodes();
extern ExtTree *extHierNewOne();
extern int extNbrPushFunc();
extern TileType extGetDevType();
/* --------------------- Miscellaneous globals ------------------------ */

View File

@ -40,22 +40,22 @@ ${GR_HELPER_PROG}: ${GR_HELPER_SRCS}
${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ${GR_HELPER_SRCS} \
-o ${GR_HELPER_PROG} ${LIBS}
install: $(DESTDIR)${BINDIR}/${GR_HELPER_PROG} glyphs fonts
install: $(DESTDIR)${INSTALL_BINDIR}/${GR_HELPER_PROG} glyphs fonts
install-tcl: glyphs fonts
$(DESTDIR)${BINDIR}/${GR_HELPER_PROG}: ${GR_HELPER_PROG}
${RM} $(DESTDIR)${BINDIR}/${GR_HELPER_PROG}
${CP} ${GR_HELPER_PROG} $(DESTDIR)${BINDIR}
$(DESTDIR)${INSTALL_BINDIR}/${GR_HELPER_PROG}: ${GR_HELPER_PROG}
${RM} $(DESTDIR)${INSTALL_BINDIR}/${GR_HELPER_PROG}
${CP} ${GR_HELPER_PROG} $(DESTDIR)${INSTALL_BINDIR}
glyphs: ${GLYPHS}
for i in ${GLYPHS}; do \
${RM} $(DESTDIR)${SYSDIR}/$$i; \
${CP} $$i $(DESTDIR)${SYSDIR}; done
${RM} $(DESTDIR)${INSTALL_SYSDIR}/$$i; \
${CP} $$i $(DESTDIR)${INSTALL_SYSDIR}; done
fonts: ${OUTLINE_FONTS}
for i in ${OUTLINE_FONTS}; do \
${RM} $(DESTDIR)${SYSDIR}/$$i; \
${CP} $$i $(DESTDIR)${SYSDIR}; done
${RM} $(DESTDIR)${INSTALL_SYSDIR}/$$i; \
${CP} $$i $(DESTDIR)${INSTALL_SYSDIR}; done
include ${MAGICDIR}/rules.mak

View File

@ -1389,12 +1389,14 @@ W3DloadWindow(window, name)
CellDef *newEditDef;
CellUse *newEditUse;
Rect loadBox;
bool dereference;
newEditDef = DBCellLookDef(name);
if (newEditDef == (CellDef *)NULL)
return FALSE;
if (!DBCellRead(newEditDef, (char *)NULL, TRUE, NULL))
dereference = (newEditDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(newEditDef, (char *)NULL, TRUE, dereference, NULL))
return FALSE;
DBReComputeBbox(newEditDef);

View File

@ -370,6 +370,9 @@ GrTCairoPlotSVG (char *filename, MagWindow *mw)
wind_context = tcairodata->context;
tcairodata->surface = (cairo_surface_t *)cairo_svg_surface_create(filename,
(double)screenw, (double)screenh);
cairo_svg_surface_restrict_to_version(tcairodata->surface,
CAIRO_SVG_VERSION_1_2);
tcairodata->context = cairo_create(tcairodata->surface);
WindRedisplay(mw);
WindUpdate();

View File

@ -22,10 +22,10 @@ magiclef${SHDLIB_EXT}: tcllef.o ${OBJS}
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} tcllef.o ${OBJS} \
${EXTRA_LIBS} -lc ${LIBS}
install-tcl: $(DESTDIR)${TCLDIR}/magiclef${SHDLIB_EXT}
install-tcl: $(DESTDIR)${INSTALL_TCLDIR}/magiclef${SHDLIB_EXT}
$(DESTDIR)${TCLDIR}/magiclef${SHDLIB_EXT}: magiclef${SHDLIB_EXT}
${RM} $(DESTDIR)${TCLDIR}/magiclef${SHDLIB_EXT}
${CP} magiclef${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/magiclef${SHDLIB_EXT}
$(DESTDIR)${INSTALL_TCLDIR}/magiclef${SHDLIB_EXT}: magiclef${SHDLIB_EXT}
${RM} $(DESTDIR)${INSTALL_TCLDIR}/magiclef${SHDLIB_EXT}
${CP} magiclef${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/magiclef${SHDLIB_EXT}
include ${MAGICDIR}/rules.mak

View File

@ -26,6 +26,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "tiles/tile.h"
#include "utils/hash.h"
#include "utils/undo.h"
#include "utils/utils.h"
#include "database/database.h"
#include "windows/windows.h"
#include "dbwind/dbwind.h"
@ -73,11 +74,12 @@ enum def_netspecial_shape_keys {
DEF_SPECNET_SHAPE_DRCFILL};
char *
DefAddRoutes(rootDef, f, oscale, special, defLayerMap)
DefAddRoutes(rootDef, f, oscale, special, netname, defLayerMap)
CellDef *rootDef; /* Cell to paint */
FILE *f; /* Input file */
float oscale; /* Scale factor between LEF and magic units */
bool special; /* True if this section is SPECIALNETS */
char *netname; /* Name of the net, if net is to be labeled */
LefMapping *defLayerMap; /* magic-to-lef layer mapping array */
{
char *token;
@ -85,6 +87,7 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap)
Point refp; /* reference point */
bool valid = FALSE; /* is there a valid reference point? */
bool initial = TRUE;
bool labeled = TRUE;
Rect locarea;
int extend, lextend, hextend;
float x, y, z, w;
@ -124,6 +127,8 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap)
NULL
};
if (netname != NULL) labeled = FALSE;
while (initial || (token = LefNextToken(f, TRUE)) != NULL)
{
/* Get next point, token "NEW", or via name */
@ -605,6 +610,16 @@ endCoord:
/* paint */
DBPaint(rootDef, &routeTop->r_r, routeTop->r_type);
/* label */
if (labeled == FALSE)
{
Rect r;
r.r_xbot = r.r_xtop = (routeTop->r_r.r_xbot + routeTop->r_r.r_xtop) / 2;
r.r_ybot = r.r_ytop = (routeTop->r_r.r_ybot + routeTop->r_r.r_ytop) / 2;
DBPutLabel(rootDef, &r, GEO_CENTER, netname, routeTop->r_type, 0);
labeled = TRUE;
}
/* advance to next point and free record (1-delayed) */
freeMagic((char *)routeTop);
routeTop = routeTop->r_next;
@ -636,15 +651,17 @@ enum def_netprop_keys {
DEF_NETPROP_PROPERTY};
void
DefReadNets(f, rootDef, sname, oscale, special, total)
DefReadNets(f, rootDef, sname, oscale, special, dolabels, total)
FILE *f;
CellDef *rootDef;
char *sname;
float oscale;
bool special; /* True if this section is SPECIALNETS */
bool dolabels; /* If true, create a label for each net */
int total;
{
char *token;
char *netname = NULL;
int keyword, subkey;
int processed = 0;
LefMapping *defLayerMap;
@ -684,8 +701,8 @@ DefReadNets(f, rootDef, sname, oscale, special, total)
case DEF_NET_START:
/* Get net name */
/* Presently, we ignore net names completely. */
token = LefNextToken(f, TRUE);
if (dolabels) netname = StrDup((char **)NULL, token);
/* Update the record of the number of nets processed */
/* and spit out a message for every 5% finished. */
@ -725,10 +742,11 @@ DefReadNets(f, rootDef, sname, oscale, special, total)
case DEF_NETPROP_FIXED:
case DEF_NETPROP_COVER:
token = DefAddRoutes(rootDef, f, oscale, special,
defLayerMap);
netname, defLayerMap);
break;
}
}
if (dolabels) freeMagic(netname);
break;
case DEF_NET_END:
@ -775,11 +793,12 @@ enum def_orient {DEF_NORTH, DEF_SOUTH, DEF_EAST, DEF_WEST,
DEF_FLIPPED_WEST};
int
DefReadLocation(use, f, oscale, tptr)
DefReadLocation(use, f, oscale, tptr, noplace)
CellUse *use;
FILE *f;
float oscale;
Transform *tptr;
bool noplace;
{
Rect *r, tr, rect;
int keyword;
@ -791,21 +810,32 @@ DefReadLocation(use, f, oscale, tptr)
"N", "S", "E", "W", "FN", "FS", "FE", "FW"
};
token = LefNextToken(f, TRUE);
if (*token != '(') goto parse_error;
token = LefNextToken(f, TRUE);
if (sscanf(token, "%f", &x) != 1) goto parse_error;
token = LefNextToken(f, TRUE);
if (sscanf(token, "%f", &y) != 1) goto parse_error;
token = LefNextToken(f, TRUE);
if (*token != ')') goto parse_error;
token = LefNextToken(f, TRUE);
keyword = Lookup(token, orientations);
if (keyword < 0)
if (noplace)
{
LefError(DEF_ERROR, "Unknown macro orientation \"%s\".\n", token);
return -1;
LefError(DEF_WARNING, "Unplaced component \"%s\" will be put at origin.\n",
use->cu_id);
x = 0;
y = 0;
keyword = DEF_NORTH;
}
else
{
token = LefNextToken(f, TRUE);
if (*token != '(') goto parse_error;
token = LefNextToken(f, TRUE);
if (sscanf(token, "%f", &x) != 1) goto parse_error;
token = LefNextToken(f, TRUE);
if (sscanf(token, "%f", &y) != 1) goto parse_error;
token = LefNextToken(f, TRUE);
if (*token != ')') goto parse_error;
token = LefNextToken(f, TRUE);
keyword = Lookup(token, orientations);
if (keyword < 0)
{
LefError(DEF_ERROR, "Unknown macro orientation \"%s\".\n", token);
return -1;
}
}
/* The standard transformations are all defined to rotate */
@ -1062,7 +1092,7 @@ DefReadPins(f, rootDef, sname, oscale, total)
break;
case DEF_PINS_PROP_FIXED:
case DEF_PINS_PROP_PLACED:
DefReadLocation(NULL, f, oscale, &t);
DefReadLocation(NULL, f, oscale, &t, FALSE);
if (curlayer == -1)
pending = TRUE;
else
@ -1275,6 +1305,35 @@ DefReadVias(f, sname, oscale, total)
blayer = LefReadLayer(f, FALSE);
clayer = LefReadLayer(f, FALSE);
tlayer = LefReadLayer(f, FALSE);
/* Provisional behavior: A known tool generating */
/* DEF uses the order (bottom, top, cut). This may */
/* be a bug in the tool and an issue is being */
/* raised. However, there is no harm in detecting */
/* which layer is the cut and swapping as needed. */
if (!DBIsContact(clayer))
{
TileType swaplayer;
LefError(DEF_WARNING, "Improper layer order for"
" VIARULE.\n");
if (DBIsContact(tlayer))
{
swaplayer = clayer;
clayer = tlayer;
tlayer = swaplayer;
}
else if (DBIsContact(blayer))
{
swaplayer = clayer;
clayer = blayer;
blayer = swaplayer;
}
else
LefError(DEF_ERROR, "No cut layer specified in"
" VIARULE.\n");
}
generated = TRUE;
break;
case DEF_VIAS_PROP_CUTSPACING:
@ -1450,18 +1509,22 @@ DefReadComponents(f, rootDef, sname, oscale, total)
/* Does use name contain brackets? If so, this can */
/* interfere with magic's use of arrays. */
/* NOTE: This has been commented out. I think */
/* the only confusion is in ext2spice and can be */
/* avoided by allowing any bracket notation in an */
/* instance name other than that used by the .ext */
/* file for dealing with arrays, which uses the */
/* specific syntax [xlo:xsep:xhi][ylo:ysep:yhi] and */
/* is easy enough to distinguish. */
/* NOTE: It is not clear that this needs to be */
/* done during DEF read. The only confusion comes */
/* from the arrays being parsed by ExtFlat when */
/* doing ext2spice. */
dptr = strchr(usename, '[');
if (dptr != NULL) {
*dptr = '_';
dptr = strchr(dptr + 1, ']');
if (dptr != NULL) *dptr = '_';
}
/*
dptr = strchr(usename, '[');
if (dptr != NULL) {
*dptr = '_';
dptr = strchr(dptr + 1, ']');
if (dptr != NULL) *dptr = '_';
}
*/
token = LefNextToken(f, TRUE);
@ -1471,11 +1534,14 @@ DefReadComponents(f, rootDef, sname, oscale, total)
if (defMacro == (CellDef *)NULL)
{
bool dereference;
/* Before giving up, assume that this cell has a */
/* magic .mag layout file. */
defMacro = DBCellNewDef(token, (char *)NULL);
defMacro->cd_flags &= ~CDNOTFOUND;
if (!DBCellRead(defMacro, (char *)NULL, TRUE, NULL))
dereference = (defMacro->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
if (!DBCellRead(defMacro, (char *)NULL, TRUE, dereference, NULL))
{
LefError(DEF_ERROR, "Cell %s is not defined. Maybe you "
"have not read the corresponding LEF file?\n",
@ -1518,10 +1584,12 @@ DefReadComponents(f, rootDef, sname, oscale, total)
switch (subkey)
{
case DEF_PROP_PLACED:
case DEF_PROP_UNPLACED:
case DEF_PROP_FIXED:
case DEF_PROP_COVER:
DefReadLocation(defUse, f, oscale, &t);
DefReadLocation(defUse, f, oscale, &t, FALSE);
break;
case DEF_PROP_UNPLACED:
DefReadLocation(defUse, f, oscale, &t, TRUE);
break;
case DEF_PROP_SOURCE:
case DEF_PROP_WEIGHT:
@ -1598,8 +1666,9 @@ enum def_sections {DEF_VERSION = 0, DEF_NAMESCASESENSITIVE,
DEF_END};
void
DefRead(inName)
DefRead(inName, dolabels)
char *inName;
bool dolabels;
{
CellDef *rootDef;
FILE *f;
@ -1775,13 +1844,15 @@ DefRead(inName)
token = LefNextToken(f, TRUE);
if (sscanf(token, "%d", &total) != 1) total = 0;
LefEndStatement(f);
DefReadNets(f, rootDef, sections[DEF_SPECIALNETS], oscale, TRUE, total);
DefReadNets(f, rootDef, sections[DEF_SPECIALNETS], oscale, TRUE,
dolabels, total);
break;
case DEF_NETS:
token = LefNextToken(f, TRUE);
if (sscanf(token, "%d", &total) != 1) total = 0;
LefEndStatement(f);
DefReadNets(f, rootDef, sections[DEF_NETS], oscale, FALSE, total);
DefReadNets(f, rootDef, sections[DEF_NETS], oscale, FALSE,
dolabels, total);
break;
case DEF_IOTIMINGS:
LefSkipSection(f, sections[DEF_IOTIMINGS]);

View File

@ -87,6 +87,15 @@ CmdLef(w, cmd)
* the macro other than pin area
* immediately surrounding labels.
*/
bool recurse = FALSE; /* If TRUE, recurse on all subcells
* during "writeall". By default,
* only the immediate children of the
* top level cell are output.
*/
bool defLabelNets = FALSE; /* If TRUE, attach a label to the
* center of the first rectangle
* found on that net.
*/
static char *cmdLefOption[] =
{
@ -95,7 +104,9 @@ CmdLef(w, cmd)
"write [filename] [-tech] write LEF for current cell\n"
" write [filename] -hide hide all details other than ports",
"writeall write all cells including the top-level cell\n"
" writeall -notop write all subcells of the top-level cell",
" writeall -notop write all children of the top-level cell\n"
" writeall -all recurse on all subcells of the top-level cell\n",
" writeall -hide hide all details other than ports",
"help print this help information",
NULL
};
@ -103,7 +114,8 @@ CmdLef(w, cmd)
static char *cmdDefOption[] =
{
"read [filename] read a DEF file filename[.def]",
"write [cell] [-allspecial] write DEF for current or indicated cell",
"write [cell] [-allspecial] write DEF for current or indicated cell\n",
"write -labels label every net in NETS with the net name",
"writeall (use \"flatten -nosubckt\" + \"def"
" write\" instead)",
"help print this help information",
@ -151,22 +163,32 @@ CmdLef(w, cmd)
switch (option)
{
case LEF_READ:
if (cmd->tx_argc != 3)
if (cmd->tx_argc > 3)
{
if (cmd->tx_argc == 4)
for (i = 3; i < cmd->tx_argc; i++)
{
if (*(cmd->tx_argv[3]) == '-')
if (!strncmp(cmd->tx_argv[3], "-import", 7))
if (*(cmd->tx_argv[i]) == '-')
{
if (!strncmp(cmd->tx_argv[i], "-import", 7))
lefImport = TRUE;
else if (!strncmp(cmd->tx_argv[i], "-label", 6))
{
if (is_lef)
TxPrintf("The \"-labels\" option is only for def read\n");
else
defLabelNets = TRUE;
}
}
}
else
goto wrongNumArgs;
}
else if (cmd->tx_argc < 3)
goto wrongNumArgs;
namep = cmd->tx_argv[2];
if (is_lef)
LefRead(namep, lefImport);
else
DefRead(namep);
DefRead(namep, defLabelNets);
break;
case LEF_WRITEALL:
if (!is_lef)
@ -184,11 +206,15 @@ CmdLef(w, cmd)
lefTopCell = FALSE;
else if (!strncmp(cmd->tx_argv[i], "-tech", 5))
lefTech = TRUE;
else if (!strncmp(cmd->tx_argv[i], "-hide", 5))
lefHide = TRUE;
else if (!strncmp(cmd->tx_argv[i], "-all", 4))
recurse = TRUE;
else goto wrongNumArgs;
}
else goto wrongNumArgs;
}
LefWriteAll(selectedUse, lefTopCell, lefTech);
LefWriteAll(selectedUse, lefTopCell, lefTech, lefHide, recurse);
}
break;
case LEF_WRITE:

View File

@ -1212,18 +1212,21 @@ LefReadGeometry(lefMacro, f, oscale, do_list)
*
* Side Effects:
* Reads input from file f;
* Paints into the CellDef lefMacro.
* Generates a new label entry in the CellDef lefMacro.
* If "lanno" is not NULL, then the label pointed to by
* lanno is modified.
*
*------------------------------------------------------------
*/
void
LefReadPort(lefMacro, f, pinName, pinNum, pinDir, pinUse, oscale)
LefReadPort(lefMacro, f, pinName, pinNum, pinDir, pinUse, oscale, lanno)
CellDef *lefMacro;
FILE *f;
char *pinName;
int pinNum, pinDir, pinUse;
float oscale;
Label *lanno;
{
Label *newlab;
LinkedRect *rectList;
@ -1235,7 +1238,15 @@ LefReadPort(lefMacro, f, pinName, pinNum, pinDir, pinUse, oscale)
if (pinNum >= 0)
{
/* Label this area */
DBPutLabel(lefMacro, &rectList->r_r, -1, pinName, rectList->r_type, 0);
if (lanno != NULL)
{
/* Modify an existing label */
lanno->lab_rect = rectList->r_r;
lanno->lab_type = rectList->r_type;
}
else
/* Create a new label (non-rendered) */
DBPutLabel(lefMacro, &rectList->r_r, -1, pinName, rectList->r_type, 0);
/* Set this label to be a port */
@ -1243,13 +1254,16 @@ LefReadPort(lefMacro, f, pinName, pinNum, pinDir, pinUse, oscale)
LefError(LEF_ERROR, "Internal error: No labels in cell!\n");
else
{
newlab = lefMacro->cd_lastLabel;
newlab = (lanno != NULL) ? lanno : lefMacro->cd_lastLabel;
if (strcmp(newlab->lab_text, pinName))
LefError(LEF_ERROR, "Internal error: Can't find the label!\n");
else /* Make this a port */
newlab->lab_flags = pinNum | pinUse | pinDir | PORT_DIR_MASK;
}
/* DBAdjustLabels(lefMacro, &rectList->area); */
/* If lanno is non-NULL then the first rectangle in the LEF */
/* port list is used to modify it. All other LEF port geometry */
/* generates new labels in the CellDef. */
if (lanno != NULL) lanno = NULL;
}
freeMagic((char *)rectList);
@ -1383,24 +1397,43 @@ LefReadPin(lefMacro, f, pinname, pinNum, oscale, is_imported)
case LEF_PORT:
if (is_imported)
{
bool needRect = TRUE;
Label *lab;
LefSkipSection(f, NULL);
/* Skip the port geometry but find the pin name and */
/* annotate with the use and direction. Note that */
/* there may be multiple instances of the label. */
/* However, if the label is a point label, then */
/* replace it with the geometry from the LEF file. */
for (lab = lefMacro->cd_labels; lab; lab = lab->lab_next)
{
if (!strcmp(lab->lab_text, pinname))
{
lab->lab_flags &= ~(PORT_USE_MASK | PORT_DIR_MASK |
if (GEO_RECTNULL(&lab->lab_rect))
break;
else
{
needRect = FALSE;
lab->lab_flags &= ~(PORT_USE_MASK | PORT_DIR_MASK |
PORT_CLASS_MASK);
lab->lab_flags = pinNum | pinUse | pinDir | PORT_DIR_MASK;
lab->lab_flags = pinNum | pinUse | pinDir |
PORT_DIR_MASK;
}
}
}
if (needRect)
{
if (lab == NULL)
DBEraseLabelsByContent(lefMacro, NULL, -1, pinname);
LefReadPort(lefMacro, f, pinname, pinNum, pinDir, pinUse,
oscale, lab);
}
else
LefSkipSection(f, NULL);
}
else
LefReadPort(lefMacro, f, pinname, pinNum, pinDir, pinUse, oscale);
LefReadPort(lefMacro, f, pinname, pinNum, pinDir, pinUse, oscale,
NULL);
break;
case LEF_CAPACITANCE:
case LEF_ANTENNADIFF:
@ -1737,10 +1770,18 @@ origin_error:
*
* For LEF contact types matching magic contact types, size the
* LEF contact cut to cover the minimum rectangle in the other
* layers that satisfies the CIF/GDS contact generation. Use
* the "cifinput" style to determine how much the via layer
* needs to grow to make a contact area. If the "cifinput"
* style is not defined, then determine rules from "cifoutput".
* layers that satisfies the CIF/GDS contact generation.
*
* NOTE: If a "cifinput" style is defined, then the via
* remains the size declared in LEF or DEF file, and the
* magic view of the via is generated by applying "cifinput"
* rules when painting into the magic database. If no input
* style is defined, then the output style rules are used to
* modify the cut size to match the way the via is defined in
* magic, and the result is painted directly.
*
* If a "cifinput" style exists, then this routine does
* nothing and has no side effects.
*
*------------------------------------------------------------
*/
@ -1750,36 +1791,10 @@ void LefGrowVia(curlayer, currect, lefl)
Rect *currect;
lefLayer *lefl;
{
if (DBIsContact(curlayer) && cifCurReadStyle != NULL)
{
int growSize;
/* To be completed: This should be deprecated by moving the entire */
/* LEF and DEF read routines to use the cifinput style. */
/* Get the amount (in magic units) that the layer needs to */
/* expand according to the "cifinput" style rules to convert */
/* a contact cut to a magic contact layer. */
growSize = CIFReadGetGrowSize(curlayer);
/* All internal LEF via geometry values are doubled */
growSize <<= 1;
if (growSize % cifCurReadStyle->crs_scaleFactor == 0)
growSize /= cifCurReadStyle->crs_scaleFactor;
else
growSize = growSize / cifCurReadStyle->crs_scaleFactor + 1;
if (growSize > 0)
{
/* cifinput styles expect the cut size to be correct, so */
/* there is no check for correctness of the layer. */
currect->r_xbot = currect->r_xbot - growSize;
currect->r_ybot = currect->r_ybot - growSize;
currect->r_xtop = currect->r_xtop + growSize;
currect->r_ytop = currect->r_ytop + growSize;
}
}
else if (DBIsContact(curlayer) && CIFCurStyle != NULL)
if (DBIsContact(curlayer) && CIFCurStyle != NULL)
{
int edgeSize = 0, contSize, halfSize;

View File

@ -270,7 +270,7 @@ LefTechLine(sectionName, argc, argv)
isContact = DBIsContact(mtype);
if (option == LEFTECH_LAYER)
option = (isContact) ? LEFTECH_CUT : LEFTECH_ROUTE;
else if (isContact && (option != LEFTECH_CUT && option != LEFTECH_CONTACT))
else if (isContact && (option != LEFTECH_CUT && option != LEFTECH_CONTACT && option != LEFTECH_OBS))
TechError("Attempt to define cut type %s as %s.\n",
DBTypeLongNameTbl[mtype], keywords[option]);
else if (!isContact && (option == LEFTECH_CUT || option == LEFTECH_CONTACT))

View File

@ -83,6 +83,8 @@ lefFileOpen(def, file, suffix, mode, prealfile)
*/
{
char namebuf[512], *name, *endp, *ends;
char *locsuffix;
char *pptr;
int len;
FILE *rfile;
@ -108,21 +110,26 @@ lefFileOpen(def, file, suffix, mode, prealfile)
if (endp = strrchr(ends, '.'))
{
if (!strcmp(endp, suffix))
if (strcmp(endp, suffix))
{
len = endp - name;
if (len > sizeof namebuf - 1) len = sizeof namebuf - 1;
(void) strncpy(namebuf, name, len);
namebuf[len] = '\0';
name = namebuf;
locsuffix = suffix;
}
else
locsuffix = NULL;
}
else
locsuffix = suffix;
/* Try once as-is, and if this fails, try stripping any leading */
/* path information in case cell is in a read-only directory (mode */
/* "read" only, and if def is non-NULL). */
if ((rfile = PaOpen(name, mode, suffix, Path, CellLibPath, prealfile)) != NULL)
if ((rfile = PaOpen(name, mode, locsuffix, Path, CellLibPath, prealfile)) != NULL)
return rfile;
if (def)
@ -634,7 +641,7 @@ lefWriteMacro(def, f, scale, hide)
{
bool propfound;
char *propvalue, *class = NULL;
Label *lab;
Label *lab, *tlab;
Rect boundary, labr;
SearchContext scx;
CellDef *lefFlatDef;
@ -772,6 +779,20 @@ lefWriteMacro(def, f, scale, hide)
else
boundary = def->cd_bbox;
/* If a bounding box has been declared with the FIXED_BBOX property */
/* then it takes precedence over def->cd_bbox. */
if (def->cd_flags & CDFIXEDBBOX)
{
char *propvalue;
bool found;
propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &found);
if (found)
sscanf(propvalue, "%d %d %d %d", &boundary.r_xbot,
&boundary.r_ybot, &boundary.r_xtop, &boundary.r_ytop);
}
/* Write position and size information */
fprintf(f, " ORIGIN %.4f %.4f ;\n",
@ -927,7 +948,18 @@ lefWriteMacro(def, f, scale, hide)
SelectClear();
if (hide)
{
SelectChunk(&scx, lab->lab_type, 0, NULL, FALSE);
/* Note that a sticky label could be placed over multiple */
/* tile types, which would cause SelectChunk to fail. So */
/* always paint the label type into the label area in */
/* SelectDef. */
pNum = DBPlane(lab->lab_type);
DBPaintPlane(SelectDef->cd_planes[pNum], &lab->lab_rect,
DBStdPaintTbl(lab->lab_type, pNum), (PaintUndoInfo *) NULL);
}
else
SelectNet(&scx, lab->lab_type, 0, NULL, FALSE);
@ -964,15 +996,21 @@ lefWriteMacro(def, f, scale, hide)
if (maxport >= 0)
{
/* Sanity check to see if port number is a duplicate */
for (lab = lab->lab_next; lab != NULL; lab = lab->lab_next)
/* Sanity check to see if port number is a duplicate. ONLY */
/* flag this if the other index has a different text, as it */
/* is perfectly legal to have multiple ports with the same */
/* name and index. */
for (tlab = lab->lab_next; tlab != NULL; tlab = tlab->lab_next)
{
if (lab->lab_flags & PORT_DIR_MASK)
if ((lab->lab_flags & PORT_NUM_MASK) == idx)
{
TxError("Port index %d is used more than once\n", idx);
idx--;
}
if (tlab->lab_flags & PORT_DIR_MASK)
if ((tlab->lab_flags & PORT_NUM_MASK) == idx)
if (strcmp(lab->lab_text, lab->lab_text))
{
TxError("Index %d is used for ports \"%s\" and \"%s\"\n",
idx, lab->lab_text, tlab->lab_text);
idx--;
}
}
}
else
@ -1030,6 +1068,7 @@ lefWriteMacro(def, f, scale, hide)
scx.scx_area = labr;
SelectClear();
SelectChunk(&scx, lab->lab_type, 0, &carea, FALSE);
if (GEO_RECTNULL(&carea)) carea = lab->lab_rect;
lspace = DRCGetDefaultLayerSpacing(lab->lab_type, lab->lab_type);
carea.r_xbot -= lspace;
carea.r_ybot -= lspace;
@ -1094,10 +1133,12 @@ lefWriteMacro(def, f, scale, hide)
*/
void
LefWriteAll(rootUse, writeTopCell, lefTech)
LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, recurse)
CellUse *rootUse;
bool writeTopCell;
bool lefTech;
bool lefHide;
bool recurse;
{
CellDef *def, *rootdef;
FILE *f;
@ -1116,8 +1157,12 @@ LefWriteAll(rootUse, writeTopCell, lefTech)
(void) DBCellSrDefs(0, lefDefInitFunc, (ClientData) 0);
/* Recursively visit all defs in the tree and push on stack */
/* If "recurse" is false, then only the children of the root use */
/* are pushed (this is the default behavior). */
lefDefStack = StackNew(100);
(void) lefDefPushFunc(rootUse);
if (writeTopCell)
lefDefPushFunc(rootUse, (bool *)NULL);
DBCellEnum(rootUse->cu_def, lefDefPushFunc, (ClientData)&recurse);
/* Open the file for output */
@ -1146,8 +1191,7 @@ LefWriteAll(rootUse, writeTopCell, lefTech)
{
def->cd_client = (ClientData) 0;
if (!SigInterruptPending)
if ((writeTopCell == TRUE) || (def != rootdef))
lefWriteMacro(def, f, scale);
lefWriteMacro(def, f, scale, lefHide);
}
/* End the LEF file */
@ -1178,8 +1222,9 @@ lefDefInitFunc(def)
*/
int
lefDefPushFunc(use)
lefDefPushFunc(use, recurse)
CellUse *use;
bool *recurse;
{
CellDef *def = use->cu_def;
@ -1188,7 +1233,8 @@ lefDefPushFunc(use)
def->cd_client = (ClientData) 1;
StackPush((ClientData) def, lefDefStack);
(void) DBCellEnum(def, lefDefPushFunc, (ClientData) 0);
if (recurse && (*recurse))
(void) DBCellEnum(def, lefDefPushFunc, (ClientData)recurse);
return (0);
}

View File

@ -13,11 +13,11 @@ SCMSRC = default.scm box.scm label.scm draw.scm drc.scm \
include ${MAGICDIR}/defs.mak
INST_SCMSRC = ${SCMSRC:%=$(DESTDIR)${SCMDIR}/%}
INST_SCMSRC = ${SCMSRC:%=$(DESTDIR)${INSTALL_SCMDIR}/%}
install: ${INST_SCMSRC}
$(DESTDIR)${SCMDIR}/%: scm/%
${CP} scm/$* $(DESTDIR)$(SCMDIR)/$*
${CP} scm/$* $(DESTDIR)$(INSTALL_SCMDIR)/$*
include ${MAGICDIR}/rules.mak

View File

@ -29,8 +29,8 @@ EXTRA_LIBS = ${MAGICDIR}/bplane/libbplane.o \
${MAGICDIR}/utils/libutils.o \
${MAIN_EXTRA_LIBS}
BITMAPS = up.xbm down.xbm left.xbm right.xbm zoom.xbm lock.xbm
DEST_XBM = $(BITMAPS:%=$(DESTDIR)${TCLDIR}/bitmaps/%)
BITMAPS = up.gif down.gif left.gif right.gif zoom.gif lock.xbm
DEST_XBM = $(BITMAPS:%=$(DESTDIR)${INSTALL_TCLDIR}/bitmaps/%)
DFLAGS += -DMAGIC_DATE="\"`date`\"" -DCAD_DIR="${LIBDIR}"
LIBS += ${GR_LIBS} ${READLINE_LIBS} -lm ${LD_EXTRA_LIBS} \
@ -49,32 +49,32 @@ tclmagic${SHDLIB_EXT}: ${EXTRA_LIBS}
-lc ${LIBS} ${LIB_SPECS} ${LDFLAGS}
proto.magicrc: proto.magicrc.in
${SCPP} ${GR_DFLAGS} ${DFLAGS} proto.magicrc.in > proto.magicrc
${MCPP} ${GR_DFLAGS} ${DFLAGS} proto.magicrc.in > proto.magicrc
install: $(DESTDIR)${BINDIR}/${MODULE}${EXEEXT} $(DESTDIR)${SYSDIR}/.magicrc \
$(DESTDIR)${SYSDIR}/magicps.pro
install: $(DESTDIR)${INSTALL_BINDIR}/${MODULE}${EXEEXT} $(DESTDIR)${INSTALL_SYSDIR}/.magicrc \
$(DESTDIR)${INSTALL_SYSDIR}/magicps.pro
install-tcl: $(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT} $(DESTDIR)${SYSDIR}/.magicrc \
$(DESTDIR)${SYSDIR}/.initrc $(DESTDIR)${SYSDIR}/magicps.pro ${DEST_XBM}
install-tcl: $(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT} $(DESTDIR)${INSTALL_SYSDIR}/.magicrc \
$(DESTDIR)${INSTALL_SYSDIR}/.initrc $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro ${DEST_XBM}
$(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT}: tclmagic${SHDLIB_EXT}
${RM} $(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT}
${CP} tclmagic${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT}
$(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT}: tclmagic${SHDLIB_EXT}
${RM} $(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT}
${CP} tclmagic${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT}
$(DESTDIR)${TCLDIR}/bitmaps/%: bitmaps/%
${RM} $(DESTDIR)${TCLDIR}/bitmaps/$*
${CP} bitmaps/$* $(DESTDIR)${TCLDIR}/bitmaps/$*
$(DESTDIR)${INSTALL_TCLDIR}/bitmaps/%: bitmaps/%
${RM} $(DESTDIR)${INSTALL_TCLDIR}/bitmaps/$*
${CP} bitmaps/$* $(DESTDIR)${INSTALL_TCLDIR}/bitmaps/$*
$(DESTDIR)${SYSDIR}/.magicrc: proto.magicrc
${RM} $(DESTDIR)${SYSDIR}/.magicrc
${CP} proto.magicrc $(DESTDIR)${SYSDIR}/.magicrc
$(DESTDIR)${INSTALL_SYSDIR}/.magicrc: proto.magicrc
${RM} $(DESTDIR)${INSTALL_SYSDIR}/.magicrc
${CP} proto.magicrc $(DESTDIR)${INSTALL_SYSDIR}/.magicrc
$(DESTDIR)${SYSDIR}/.initrc: proto.initrc
${RM} $(DESTDIR)${SYSDIR}/.initrc
${CP} proto.initrc $(DESTDIR)${SYSDIR}/.initrc
$(DESTDIR)${INSTALL_SYSDIR}/.initrc: proto.initrc
${RM} $(DESTDIR)${INSTALL_SYSDIR}/.initrc
${CP} proto.initrc $(DESTDIR)${INSTALL_SYSDIR}/.initrc
$(DESTDIR)${SYSDIR}/magicps.pro: magicps.pro
${RM} $(DESTDIR)${SYSDIR}/magicps.pro
${CP} magicps.pro $(DESTDIR)${SYSDIR}/magicps.pro
$(DESTDIR)${INSTALL_SYSDIR}/magicps.pro: magicps.pro
${RM} $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro
${CP} magicps.pro $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro
include ${MAGICDIR}/rules.mak

BIN
magic/bitmaps/down.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

BIN
magic/bitmaps/left.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

BIN
magic/bitmaps/right.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

BIN
magic/bitmaps/up.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

BIN
magic/bitmaps/zoom.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

View File

@ -15,7 +15,7 @@ tcl-main:
main: net2ir
install: $(DESTDIR)${BINDIR}/${MODULE}${EXEEXT}
install: $(DESTDIR)${INSTALL_BINDIR}/${MODULE}${EXEEXT}
install-tcl:
echo "Nothing to do here"

View File

@ -28,10 +28,10 @@ tclplot${SHDLIB_EXT}: tclplot.o ${OBJS}
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} tclplot.o ${OBJS} \
${EXTRA_LIBS} -lc ${LIBS}
install-tcl: $(DESTDIR)${TCLDIR}/tclplot${SHDLIB_EXT}
install-tcl: $(DESTDIR)${INSTALL_TCLDIR}/tclplot${SHDLIB_EXT}
$(DESTDIR)${TCLDIR}/tclplot${SHDLIB_EXT}: tclplot${SHDLIB_EXT}
${RM} $(DESTDIR)${TCLDIR}/tclplot${SHDLIB_EXT}
${CP} tclplot${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/tclplot${SHDLIB_EXT}
$(DESTDIR)${INSTALL_TCLDIR}/tclplot${SHDLIB_EXT}: tclplot${SHDLIB_EXT}
${RM} $(DESTDIR)${INSTALL_TCLDIR}/tclplot${SHDLIB_EXT}
${CP} tclplot${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/tclplot${SHDLIB_EXT}
include ${MAGICDIR}/rules.mak

View File

@ -21,7 +21,7 @@ ResMakeRes.o: ResMakeRes.c ../utils/magic.h ../utils/geometry.h \
../bplane/bplaneInt.h ../utils/malloc.h ../textio/textio.h \
../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \
../windows/windows.h ../dbwind/dbwind.h ../utils/tech.h \
../textio/txcommands.h ../resis/resis.h
../textio/txcommands.h ../resis/resis.h ../cif/CIFint.h
ResSimple.o: ResSimple.c ../utils/magic.h ../utils/geometry.h \
../utils/geofast.h ../tiles/tile.h ../utils/hash.h ../utils/heap.h \
../database/database.h ../bplane/bplane.h ../bplane/bpOpaque.h \

View File

@ -24,7 +24,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "textio/txcommands.h"
#include "resis/resis.h"
int resSubTranFunc();
int resSubDevFunc();
/*
*--------------------------------------------------------------------------
@ -113,13 +113,13 @@ resAllPortNodes(tile, list)
*--------------------------------------------------------------------------
*
* ResEachTile--for each tile, make a list of all possible current sources/
* sinks including contacts, transistors, and junctions. Once this
* sinks including contacts, devices, and junctions. Once this
* list is made, calculate the resistor nextwork for the tile.
*
* Results: returns TRUE or FALSE depending on whether a node was
* involved in a merge.
*
* Side Effects: creates Nodes, transistors, junctions, and breakpoints.
* Side Effects: creates Nodes, devices, junctions, and breakpoints.
*
*
*--------------------------------------------------------------------------
@ -139,6 +139,7 @@ ResEachTile(tile, startpoint)
bool merged;
tElement *tcell;
tileJunk *tstructs= (tileJunk *)(tile->ti_client);
ExtDevice *devptr;
ResTileCount++;
@ -165,24 +166,24 @@ ResEachTile(tile, startpoint)
resNodeIsPort(resptr, x, y, tile);
}
if TTMaskHasType(&(ExtCurStyle->exts_transMask), t1)
if TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t1)
{
/*
* The transistor is put in the center of the tile. This is fine
* for single tile transistors, but not as good for multiple ones.
* The device is put in the center of the tile. This is fine
* for single tile device, but not as good for multiple ones.
*/
if (tstructs->tj_status & RES_TILE_TRAN)
if (tstructs->tj_status & RES_TILE_DEV)
{
if (tstructs->transistorList->rt_gate == NULL)
if (tstructs->deviceList->rd_fet_gate == NULL)
{
int x = (LEFT(tile) + RIGHT(tile)) >> 1;
int y = (TOP(tile) + BOTTOM(tile)) >> 1;
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
tstructs->transistorList->rt_gate = resptr;
tstructs->deviceList->rd_fet_gate = resptr;
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
tcell->te_thist = tstructs->transistorList;
tcell->te_thist = tstructs->deviceList;
tcell->te_nextt = NULL;
InitializeNode(resptr, x, y, RES_NODE_JUNCTION);
@ -219,7 +220,7 @@ ResEachTile(tile, startpoint)
{
(void)DBSrPaintArea((Tile *) NULL,
ResUse->cu_def->cd_planes[pNum],
&tileArea, mask, resSubTranFunc, (ClientData) tile);
&tileArea, mask, resSubDevFunc, (ClientData) tile);
}
}
}
@ -250,13 +251,14 @@ ResEachTile(tile, startpoint)
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp))
{
t2 = TiGetRightType(tp);
if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) &&
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1))
/* found transistor */
devptr = ExtCurStyle->exts_device[t2];
if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) &&
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1))
/* found device */
{
xj = LEFT(tile);
yj = (TOP(tp) + BOTTOM(tp)) >> 1;
ResNewSDTransistor(tile, tp, xj, yj, RIGHTEDGE, &ResNodeQueue);
ResNewSDDevice(tile, tp, xj, yj, RIGHTEDGE, &ResNodeQueue);
}
if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2)
/* tile is junction */
@ -272,13 +274,14 @@ ResEachTile(tile, startpoint)
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp))
{
t2 = TiGetLeftType(tp);
if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) &&
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1))
/* found transistor */
devptr = ExtCurStyle->exts_device[t2];
if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) &&
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1))
/* found device */
{
xj = RIGHT(tile);
yj = (TOP(tp)+BOTTOM(tp))>>1;
ResNewSDTransistor(tile, tp, xj, yj, LEFTEDGE, &ResNodeQueue);
ResNewSDDevice(tile, tp, xj, yj, LEFTEDGE, &ResNodeQueue);
}
if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1], t2)
/* tile is junction */
@ -294,13 +297,14 @@ ResEachTile(tile, startpoint)
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp))
{
t2 = TiGetBottomType(tp);
if(TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) &&
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1))
/* found transistor */
devptr = ExtCurStyle->exts_device[t2];
if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) &&
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1))
/* found device */
{
yj = TOP(tile);
xj = (LEFT(tp)+RIGHT(tp))>>1;
ResNewSDTransistor(tile,tp,xj,yj,BOTTOMEDGE, &ResNodeQueue);
ResNewSDDevice(tile,tp,xj,yj,BOTTOMEDGE, &ResNodeQueue);
}
if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1],t2)
/* tile is junction */
@ -315,13 +319,14 @@ ResEachTile(tile, startpoint)
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp))
{
t2 = TiGetTopType(tp);
if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) &&
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1))
/* found transistor */
devptr = ExtCurStyle->exts_device[t2];
if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) &&
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1))
/* found device */
{
yj = BOTTOM(tile);
xj = (LEFT(tp) + RIGHT(tp)) >> 1;
ResNewSDTransistor(tile, tp, xj, yj, TOPEDGE, &ResNodeQueue);
ResNewSDDevice(tile, tp, xj, yj, TOPEDGE, &ResNodeQueue);
}
if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2)
/* tile is junction */
@ -344,7 +349,7 @@ ResEachTile(tile, startpoint)
/*
*-------------------------------------------------------------------------
*
* resSubTranFunc -- called when DBSrPaintArea finds a transistor within
* resSubDevFunc -- called when DBSrPaintArea finds a device within
* a substrate area.
*
* Results: always returns 0 to keep search going.
@ -355,7 +360,7 @@ ResEachTile(tile, startpoint)
*/
int
resSubTranFunc(tile,tp)
resSubDevFunc(tile,tp)
Tile *tile,*tp;
@ -365,13 +370,13 @@ resSubTranFunc(tile,tp)
tElement *tcell;
int x,y;
if (junk->transistorList->rt_subs== NULL)
if (junk->deviceList->rd_fet_subs == NULL)
{
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
junk->transistorList->rt_subs = resptr;
junk->tj_status |= RES_TILE_TRAN;
junk->deviceList->rd_fet_subs = resptr;
junk->tj_status |= RES_TILE_DEV;
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
tcell->te_thist = junk->transistorList;
tcell->te_thist = junk->deviceList;
tcell->te_nextt = NULL;
x = (LEFT(tile)+RIGHT(tile))>>1;
y = (TOP(tile)+BOTTOM(tile))>>1;

View File

@ -43,16 +43,16 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
*/
void
ResSanityChecks(nodename,resistorList,nodeList,tranlist)
ResSanityChecks(nodename,resistorList,nodeList,devlist)
char *nodename;
resResistor *resistorList;
resNode *nodeList;
resTransistor *tranlist;
resDevice *devlist;
{
resResistor *resistor;
resNode *node;
resTransistor *tran;
resDevice *dev;
resElement *rcell;
static Stack *resSanityStack = NULL;
int reached,foundorigin;
@ -107,29 +107,29 @@ ResSanityChecks(nodename,resistorList,nodeList,tranlist)
}
resistor->rr_status &= ~RES_REACHED_RESISTOR;
}
for (tran = tranlist; tran != NULL; tran = tran->rt_nextTran)
for (dev = devlist; dev != NULL; dev = dev->rd_nextDev)
{
int i;
if (tran->rt_status & RES_TRAN_PLUG) continue;
if (dev->rd_status & RES_DEV_PLUG) continue;
reached = FALSE;
for (i=0;i != RT_TERMCOUNT;i++)
for (i=0;i != dev->rd_nterms;i++)
{
if (tran->rt_terminals[i] != NULL)
if (dev->rd_terminals[i] != NULL)
{
reached = TRUE;
if ((tran->rt_terminals[i]->rn_status & RES_REACHED_NODE) == 0)
if ((dev->rd_terminals[i]->rn_status & RES_REACHED_NODE) == 0)
{
TxError("Transistor node %d unreached in %s\n",i,nodename);
TxError("Device node %d unreached in %s\n",i,nodename);
}
}
}
if (reached == 0)
{
TxError("Unreached transistor in %s at %d %d\n",
TxError("Unreached device in %s at %d %d\n",
nodename,
tran->rt_inside.r_xbot,
tran->rt_inside.r_ybot);
dev->rd_inside.r_xbot,
dev->rd_inside.r_ybot);
}
}
foundorigin = 0;

View File

@ -60,7 +60,7 @@ extern int dbcConnectFuncDCS();
extern int resSubSearchFunc();
#endif
static ResTranTile *TransList = NULL;
static ResDevTile *DevList = NULL;
static TileTypeBitMask DiffTypeBitMask;
TileTypeBitMask ResSubsTypeBitMask;
@ -73,14 +73,14 @@ extern void ResCalcPerimOverlap();
*
* dbcConnectFuncDCS -- the same as dbcConnectFunc, except that it does
* some extra searching around diffusion tiles looking for
* transistors.
* 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
* ResTranTile structures.
* ResDevTile structures.
*
* ----------------------------------------------------------------------------
*/
@ -92,8 +92,8 @@ dbcConnectFuncDCS(tile, cx)
{
struct conSrArg2 *csa2;
Rect tileArea, *srArea, tranArea, newarea;
ResTranTile *thisTran;
Rect tileArea, *srArea, devArea, newarea;
ResDevTile *thisDev;
TileTypeBitMask notConnectMask, *connectMask;
Tile *tp;
TileType t2, t1, loctype, ctype;
@ -102,6 +102,7 @@ dbcConnectFuncDCS(tile, cx)
SearchContext scx2;
int pNum;
CellDef *def;
ExtDevice *devptr;
TiToRect(tile, &tileArea);
srArea = &scx->scx_area;
@ -121,79 +122,83 @@ dbcConnectFuncDCS(tile, cx)
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp))
{
t2 = TiGetType(tp);
if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) &&
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1))
devptr = ExtCurStyle->exts_device[t2];
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) &&
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1))
{
TiToRect(tp, &tranArea);
thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile)));
ResCalcPerimOverlap(thisTran,tp);
GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area);
thisTran->type = TiGetType(tp);
thisTran->nextTran = TransList;
TransList = thisTran;
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);
if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) &&
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1))
devptr = ExtCurStyle->exts_device[t2];
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) &&
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1))
{
TiToRect(tp, &tranArea);
thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile)));
GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area);
thisTran->type = TiGetType(tp);
thisTran->nextTran = TransList;
TransList = thisTran;
ResCalcPerimOverlap(thisTran,tp);
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);
if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) &&
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1))
devptr = ExtCurStyle->exts_device[t2];
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) &&
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1))
{
TiToRect(tp, &tranArea);
thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile)));
GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area);
thisTran->type = TiGetType(tp);
thisTran->nextTran = TransList;
TransList = thisTran;
ResCalcPerimOverlap(thisTran,tp);
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);
if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) &&
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1))
devptr = ExtCurStyle->exts_device[t2];
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) &&
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1))
{
TiToRect(tp, &tranArea);
thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile)));
GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area);
thisTran->type = TiGetType(tp);
thisTran->nextTran = TransList;
TransList = thisTran;
ResCalcPerimOverlap(thisTran,tp);
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_transMask),t1)
else if TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t1)
{
TiToRect(tile, &tranArea);
thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile)));
ResCalcPerimOverlap(thisTran,tile);
GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area);
thisTran->type = TiGetType(tile);
thisTran->nextTran = TransList;
TransList = thisTran;
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
transistors whose substrate terminals are part of the given region.
devices whose substrate terminals are part of the given region.
The following does that check. (10-11-88)
*/
#ifdef ARIEL
@ -333,8 +338,8 @@ dbcConnectFuncDCS(tile, cx)
*/
void
ResCalcPerimOverlap(trans, tile)
ResTranTile *trans;
ResCalcPerimOverlap(dev, tile)
ResDevTile *dev;
Tile *tile;
{
@ -342,7 +347,7 @@ ResCalcPerimOverlap(trans, tile)
int t1;
int overlap;
trans->perim = (TOP(tile)-BOTTOM(tile)-LEFT(tile)+RIGHT(tile))<<1;
dev->perim = (TOP(tile)-BOTTOM(tile)-LEFT(tile)+RIGHT(tile))<<1;
overlap =0;
t1 = TiGetType(tile);
@ -386,7 +391,7 @@ ResCalcPerimOverlap(trans, tile)
}
}
trans->overlap = overlap;
dev->overlap = overlap;
}
@ -399,7 +404,7 @@ ResCalcPerimOverlap(trans, tile)
* dbcConnectFuncDCS.
*
* Results:
* Linked list of transistors.
* Linked list of devices.
*
* Side effects:
* The contents of the result cell are modified.
@ -407,7 +412,7 @@ ResCalcPerimOverlap(trans, tile)
* ----------------------------------------------------------------------------
*/
ResTranTile *
ResDevTile *
DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse)
SearchContext *scx;
TileTypeBitMask *mask;
@ -419,12 +424,13 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse)
{
static int first = 1;
struct conSrArg2 csa2;
int tran, pNum;
char *tran_name;
int dev, pNum;
char *dev_name;
TileTypeBitMask *newmask;
ResTranTile *CurrentT;
ResDevTile *CurrentT;
CellDef *def = destUse->cu_def;
TileType newtype;
ExtDevice *devptr;
csa2.csa2_use = destUse;
csa2.csa2_xMask = xMask;
@ -441,21 +447,22 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse)
{
TTMaskZero(&DiffTypeBitMask);
TTMaskZero(&ResSubsTypeBitMask);
for (tran = TT_TECHDEPBASE; tran < TT_MAXTYPES; tran++)
for (dev = TT_TECHDEPBASE; dev < TT_MAXTYPES; dev++)
{
tran_name = (ExtCurStyle->exts_transName)[tran];
if ((tran_name != NULL) && (strcmp(tran_name, "None")))
devptr = ExtCurStyle->exts_device[dev];
if ((devptr != NULL) && ((dev_name = devptr->exts_deviceName) != NULL)
&& (strcmp(dev_name, "None")))
{
TTMaskSetMask(&DiffTypeBitMask,
&(ExtCurStyle->exts_transSDTypes[tran][0]));
&(devptr->exts_deviceSDTypes[0]));
TTMaskSetMask(&ResSubsTypeBitMask,
&(ExtCurStyle->exts_transSubstrateTypes[tran]));
&(devptr->exts_deviceSubstrateTypes));
}
}
first = 0;
}
TransList = NULL;
DevList = NULL;
DBTreeSrTiles(scx, mask, xMask, dbcConnectFuncDCS, (ClientData) &csa2);
while (csa2.csa2_top >= 0)
{
@ -471,7 +478,7 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse)
}
freeMagic((char *)csa2.csa2_list);
for (CurrentT = TransList; CurrentT != NULL; CurrentT=CurrentT->nextTran)
for (CurrentT = DevList; CurrentT != NULL; CurrentT=CurrentT->nextDev)
{
TileType t = CurrentT->type;
TileType nt;
@ -489,7 +496,7 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse)
}
DBReComputeBbox(def);
return(TransList);
return(DevList);
}
@ -499,7 +506,7 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse)
*
* resSubSearchFunc --
*
* called when DBSrPaintArea finds a transistor within
* called when DBSrPaintArea finds a device within
* a substrate area.
*
* Results:
@ -517,22 +524,24 @@ resSubSearchFunc(tile,cx)
{
ResTranTile *thisTran;
Rect tranArea;
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.
*/
if (ExtCurStyle->exts_transSDCount[t] >1) return 0;
TiToRect(tile, &tranArea);
thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile)));
GeoTransRect(&cx->tc_scx->scx_trans, &tranArea, &thisTran->area);
thisTran->type = t;
thisTran->nextTran = TransList;
TransList = thisTran;
ResCalcPerimOverlap(thisTran,tile);
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;
}

View File

@ -101,42 +101,42 @@ ResPrintResistorList(fp,list)
/*
*-------------------------------------------------------------------------
*
* ResPrintTransistorList--
* ResPrintDeviceList--
*
*
* Results: none
*
* Side effects: prints out transistors in list to file fp.
* Side effects: prints out devices in list to file fp.
*
*-------------------------------------------------------------------------
*/
void
ResPrintTransistorList(fp,list)
ResPrintDeviceList(fp,list)
FILE *fp;
resTransistor *list;
resDevice *list;
{
static char termtype[] = {'g','s','d','c'};
int i;
for (; list != NULL; list = list->rt_nextTran)
for (; list != NULL; list = list->rd_nextDev)
{
if (list->rt_status & RES_TRAN_PLUG) continue;
if (list->rd_status & RES_DEV_PLUG) continue;
if (fp == stdout)
TxPrintf("t w %d l %d ", list->rt_width, list->rt_length);
TxPrintf("t w %d l %d ", list->rd_width, list->rd_length);
else
fprintf(fp, "t w %d l %d ", list->rt_width, list->rt_length);
for (i=0; i!= RT_TERMCOUNT;i++)
fprintf(fp, "t w %d l %d ", list->rd_width, list->rd_length);
for (i = 0; i != list->rd_nterms; i++)
{
if (list->rt_terminals[i] == NULL) continue;
if (list->rd_terminals[i] == NULL) continue;
if (fp == stdout)
TxPrintf("%c (%d,%d) ",termtype[i],
list->rt_terminals[i]->rn_loc.p_x,
list->rt_terminals[i]->rn_loc.p_y);
list->rd_terminals[i]->rn_loc.p_x,
list->rd_terminals[i]->rn_loc.p_y);
else
fprintf(fp, "%c (%d,%d) ",termtype[i],
list->rt_terminals[i]->rn_loc.p_x,
list->rt_terminals[i]->rn_loc.p_y);
list->rd_terminals[i]->rn_loc.p_x,
list->rd_terminals[i]->rn_loc.p_y);
}
if (fp == stdout)

Some files were not shown because too many files have changed in this diff Show More