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:
commit
cd87b08b21
|
|
@ -10,5 +10,18 @@ scripts/defs.mak
|
||||||
*.so
|
*.so
|
||||||
*~
|
*~
|
||||||
scmos/cif_template/objs/*
|
scmos/cif_template/objs/*
|
||||||
UPDATE_ME
|
database/database.h
|
||||||
VERSION
|
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
|
||||||
|
|
|
||||||
2
INSTALL
2
INSTALL
|
|
@ -7,6 +7,8 @@ Autoconf Capsule Summary:
|
||||||
make
|
make
|
||||||
make install
|
make install
|
||||||
|
|
||||||
|
Note: Remember to use 'gmake' on FreeBSD.
|
||||||
|
|
||||||
Autoconf options (use "./configure --help" for a complete list):
|
Autoconf options (use "./configure --help" for a complete list):
|
||||||
|
|
||||||
--prefix=DIR Indicates the install directory. Determines the
|
--prefix=DIR Indicates the install directory. Determines the
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
20
Makefile
20
Makefile
|
|
@ -13,7 +13,7 @@ MODULES = bplane cmwind commands database dbwind debug drc extflat \
|
||||||
MAKEFLAGS =
|
MAKEFLAGS =
|
||||||
INSTALL_CAD_DIRS = windows doc ${TECH}
|
INSTALL_CAD_DIRS = windows doc ${TECH}
|
||||||
|
|
||||||
include defs.mak
|
-include defs.mak
|
||||||
|
|
||||||
all: $(ALL_TARGET)
|
all: $(ALL_TARGET)
|
||||||
|
|
||||||
|
|
@ -66,8 +66,8 @@ depend: database/database.h
|
||||||
install: $(INSTALL_TARGET)
|
install: $(INSTALL_TARGET)
|
||||||
|
|
||||||
install-magic:
|
install-magic:
|
||||||
@echo --- installing executable to $(DESTDIR)${BINDIR}
|
@echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR}
|
||||||
@echo --- installing runtime files to $(DESTDIR)${LIBDIR}
|
@echo --- installing runtime files to $(DESTDIR)${INSTALL_LIBDIR}
|
||||||
@${MAKE} install-real 2>&1 >> install.log
|
@${MAKE} install-real 2>&1 >> install.log
|
||||||
|
|
||||||
install-real: install-dirs
|
install-real: install-dirs
|
||||||
|
|
@ -77,16 +77,18 @@ install-real: install-dirs
|
||||||
(cd $$dir && ${MAKE} install); done
|
(cd $$dir && ${MAKE} install); done
|
||||||
|
|
||||||
install-tcl-dirs:
|
install-tcl-dirs:
|
||||||
${MAGICDIR}/scripts/mkdirs $(DESTDIR)${BINDIR} $(DESTDIR)${MANDIR} \
|
${MAGICDIR}/scripts/mkdirs $(DESTDIR)${INSTALL_BINDIR} \
|
||||||
$(DESTDIR)${SYSDIR} $(DESTDIR)${TCLDIR} $(DESTDIR)${TCLDIR}/bitmaps
|
$(DESTDIR)${INSTALL_MANDIR} $(DESTDIR)${INSTALL_SYSDIR} \
|
||||||
|
$(DESTDIR)${INSTALL_TCLDIR} $(DESTDIR)${INSTALL_TCLDIR}/bitmaps
|
||||||
|
|
||||||
install-dirs:
|
install-dirs:
|
||||||
${MAGICDIR}/scripts/mkdirs $(DESTDIR)${BINDIR} $(DESTDIR)${MANDIR} \
|
${MAGICDIR}/scripts/mkdirs $(DESTDIR)${INSTALL_BINDIR} \
|
||||||
$(DESTDIR)${SYSDIR} $(DESTDIR)${SCMDIR}
|
$(DESTDIR)${INSTALL_MANDIR} $(DESTDIR)${INSTALL_SYSDIR} \
|
||||||
|
$(DESTDIR)${INSTALL_SCMDIR}
|
||||||
|
|
||||||
install-tcl:
|
install-tcl:
|
||||||
@echo --- installing executable to $(DESTDIR)${BINDIR}
|
@echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR}
|
||||||
@echo --- installing runtime files to $(DESTDIR)${LIBDIR}
|
@echo --- installing runtime files to $(DESTDIR)${INSTALL_LIBDIR}
|
||||||
@${MAKE} install-tcl-real 2>&1 >> install.log
|
@${MAKE} install-tcl-real 2>&1 >> install.log
|
||||||
|
|
||||||
install-tcl-real: install-tcl-dirs
|
install-tcl-real: install-tcl-dirs
|
||||||
|
|
|
||||||
20
TODO
20
TODO
|
|
@ -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
|
1. The "extresist" code needs to extract substrate networks. Moreover,
|
||||||
the new "device" types in the extract file.
|
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
|
2. "plow" should derive its rules from the DRC decks (using the new
|
||||||
from the DRC decks (using the new routines that are meant for just
|
routines that are meant for just that sort of thing).
|
||||||
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.
|
||||||
|
|
|
||||||
|
|
@ -282,7 +282,7 @@ calmaParseStructure(filename)
|
||||||
{
|
{
|
||||||
static int structs[] = { CALMA_STRCLASS, CALMA_STRTYPE, -1 };
|
static int structs[] = { CALMA_STRCLASS, CALMA_STRTYPE, -1 };
|
||||||
int nbytes, rtype, nsrefs, osrefs, npaths;
|
int nbytes, rtype, nsrefs, osrefs, npaths;
|
||||||
char *strname = NULL, newname[CALMANAMELENGTH*2];
|
char *strname = NULL;
|
||||||
HashEntry *he;
|
HashEntry *he;
|
||||||
int suffix;
|
int suffix;
|
||||||
int mfactor;
|
int mfactor;
|
||||||
|
|
@ -327,15 +327,21 @@ calmaParseStructure(filename)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
char *newname;
|
||||||
|
|
||||||
CalmaReadError("Cell \"%s\" was already defined in this file.\n",
|
CalmaReadError("Cell \"%s\" was already defined in this file.\n",
|
||||||
strname);
|
strname);
|
||||||
|
newname = (char *)mallocMagic(strlen(strname) + 20);
|
||||||
for (suffix = 1; HashGetValue(he) != NULL; suffix++)
|
for (suffix = 1; HashGetValue(he) != NULL; suffix++)
|
||||||
{
|
{
|
||||||
(void) sprintf(newname, "%s_%d", strname, suffix);
|
(void) sprintf(newname, "%s_%d", strname, suffix);
|
||||||
he = HashFind(&calmaDefInitHash, newname);
|
he = HashFind(&calmaDefInitHash, newname);
|
||||||
}
|
}
|
||||||
CalmaReadError("Giving this cell a new name: %s\n", 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);
|
cifReadCellDef = calmaFindCell(strname, &was_called);
|
||||||
|
|
@ -405,17 +411,18 @@ calmaParseStructure(filename)
|
||||||
*/
|
*/
|
||||||
if (CalmaFlattenUses && (!was_called) && (npaths < 10) && (nsrefs == 0))
|
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. */
|
/* 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;
|
Plane **cifplanes = (Plane **)cifReadCellDef->cd_client;
|
||||||
int pNum;
|
int pNum;
|
||||||
|
|
||||||
for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++)
|
for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++)
|
||||||
{
|
{
|
||||||
if (cifplanes[pNum] != NULL)
|
if (cifplanes[pNum] != NULL)
|
||||||
{
|
{
|
||||||
DBFreePaintPlane(cifplanes[pNum]);
|
DBFreePaintPlane(cifplanes[pNum]);
|
||||||
TiFreePlane(cifplanes[pNum]);
|
TiFreePlane(cifplanes[pNum]);
|
||||||
|
|
@ -903,7 +910,8 @@ calmaElementSref(filename)
|
||||||
|
|
||||||
for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++)
|
for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++)
|
||||||
{
|
{
|
||||||
if (gdsplanes[pNum] != NULL)
|
if ((def->cd_client != (ClientData)CLIENTDEFAULT) &&
|
||||||
|
(gdsplanes[pNum] != NULL))
|
||||||
{
|
{
|
||||||
gdsCopyRec.plane = cifCurReadPlanes[pNum];
|
gdsCopyRec.plane = cifCurReadPlanes[pNum];
|
||||||
if (isArray)
|
if (isArray)
|
||||||
|
|
|
||||||
|
|
@ -291,10 +291,10 @@ calmaElementBoundary()
|
||||||
|
|
||||||
/* Convert rp to magic database units to compare to label rects */
|
/* Convert rp to magic database units to compare to label rects */
|
||||||
rpc = rp->r_r;
|
rpc = rp->r_r;
|
||||||
rpc.r_xbot /= calmaReadScale1;
|
rpc.r_xbot /= cifCurReadStyle->crs_scaleFactor;
|
||||||
rpc.r_xtop /= calmaReadScale1;
|
rpc.r_xtop /= cifCurReadStyle->crs_scaleFactor;
|
||||||
rpc.r_ybot /= calmaReadScale1;
|
rpc.r_ybot /= cifCurReadStyle->crs_scaleFactor;
|
||||||
rpc.r_ytop /= calmaReadScale1;
|
rpc.r_ytop /= cifCurReadStyle->crs_scaleFactor;
|
||||||
|
|
||||||
if ((ciftype >= 0) &&
|
if ((ciftype >= 0) &&
|
||||||
(cifCurReadStyle->crs_labelSticky[ciftype] != LABEL_TYPE_NONE))
|
(cifCurReadStyle->crs_labelSticky[ciftype] != LABEL_TYPE_NONE))
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,7 @@ done:
|
||||||
if (mw != NULL)
|
if (mw != NULL)
|
||||||
{
|
{
|
||||||
if (calmaLookCell(libname, NULL) != (CellDef *)NULL)
|
if (calmaLookCell(libname, NULL) != (CellDef *)NULL)
|
||||||
DBWloadWindow(mw, libname, FALSE);
|
DBWloadWindow(mw, libname, FALSE, FALSE);
|
||||||
}
|
}
|
||||||
freeMagic(libname);
|
freeMagic(libname);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -372,10 +372,10 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
|
||||||
char *filename;
|
char *filename;
|
||||||
{
|
{
|
||||||
int nbytes, rtype;
|
int nbytes, rtype;
|
||||||
char *strname = NULL, *newnameptr, newname[CALMANAMELENGTH*2];
|
char *strname = NULL, *newnameptr;
|
||||||
HashEntry *he, *he2;
|
HashEntry *he, *he2;
|
||||||
CellDef *edef;
|
CellDef *edef;
|
||||||
char *prefix;
|
char *prefix = NULL;
|
||||||
|
|
||||||
/* Make sure this is a structure; if not, let the caller know we're done */
|
/* Make sure this is a structure; if not, let the caller know we're done */
|
||||||
PEEKRH(nbytes, rtype);
|
PEEKRH(nbytes, rtype);
|
||||||
|
|
@ -397,23 +397,35 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
|
||||||
calmaOutDate(def->cd_timestamp, outf);
|
calmaOutDate(def->cd_timestamp, outf);
|
||||||
calmaOutDate(time((time_t *) 0), outf);
|
calmaOutDate(time((time_t *) 0), outf);
|
||||||
|
|
||||||
|
/* Find the structure's unique prefix, in case structure calls subcells */
|
||||||
|
/* that are not yet defined. */
|
||||||
|
|
||||||
|
he2 = HashFind(&calmaLibHash, filename);
|
||||||
|
if (he2 == NULL)
|
||||||
|
TxError("Fatal error: Library %s not recorded!\n", filename);
|
||||||
|
else
|
||||||
|
prefix = (char *)HashGetValue(he2);
|
||||||
|
|
||||||
/* Prefix structure name with def name, and output new structure name */
|
/* Prefix structure name with def name, and output new structure name */
|
||||||
he = HashFind(calmaDefHash, strname);
|
he = HashFind(calmaDefHash, strname);
|
||||||
if ((newnameptr = (char *)HashGetValue(he)) != NULL)
|
if ((newnameptr = (char *)HashGetValue(he)) != NULL)
|
||||||
{
|
{
|
||||||
/* Structure is defined more than once */
|
/* 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? */
|
/* 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))
|
else if (!strcmp(strname, def->cd_name))
|
||||||
{
|
{
|
||||||
/* This is the top level cell being defined. Its name */
|
/* This is the top level cell being defined. Its name */
|
||||||
/* does not get modified. */
|
/* does not get modified. */
|
||||||
|
|
||||||
newnameptr = mallocMagic(strlen(strname) + 1);
|
newnameptr = mallocMagic(strlen(strname) + 2);
|
||||||
sprintf(newnameptr, "%s", strname);
|
sprintf(newnameptr, "1%s", strname);
|
||||||
calmaOutStringRecord(CALMA_STRNAME, newnameptr, outf);
|
calmaOutStringRecord(CALMA_STRNAME, newnameptr + 1, outf);
|
||||||
HashSetValue(he, (char *)newnameptr);
|
HashSetValue(he, (char *)newnameptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -444,26 +456,20 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
|
||||||
/* Same library, so keep the cellname and mark the cell */
|
/* Same library, so keep the cellname and mark the cell */
|
||||||
/* as having been written to GDS. */
|
/* as having been written to GDS. */
|
||||||
|
|
||||||
newnameptr = mallocMagic(strlen(strname) + 1);
|
newnameptr = mallocMagic(strlen(strname) + 2);
|
||||||
sprintf(newnameptr, "%s", strname);
|
sprintf(newnameptr, "1%s", strname);
|
||||||
HashSetValue(he, (char *)newnameptr);
|
HashSetValue(he, (char *)newnameptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Find the unique library prefix and prepend it to the cell name */
|
/* Find the unique library prefix and prepend it to the cell name */
|
||||||
|
|
||||||
he2 = HashFind(&calmaLibHash, filename);
|
if (prefix == NULL)
|
||||||
if (he2 == NULL)
|
newnameptr = strname; /* Should never happen */
|
||||||
{
|
|
||||||
/* Should never happen */
|
|
||||||
TxError("Fatal error: Library %s not recorded!\n", filename);
|
|
||||||
newnameptr = strname;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
prefix = (char *)HashGetValue(he2);
|
newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 9);
|
||||||
newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 8);
|
sprintf(newnameptr, "1%s_%s", prefix, strname);
|
||||||
sprintf(newnameptr, "%s_%s", prefix, strname);
|
|
||||||
HashSetValue(he, (char *)newnameptr);
|
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 */
|
/* Find the unique library prefix and prepend it to the cell name */
|
||||||
|
|
||||||
he2 = HashFind(&calmaLibHash, filename);
|
if (prefix == NULL)
|
||||||
if (he2 == NULL)
|
newnameptr = strname; /* Should never happen */
|
||||||
{
|
|
||||||
/* Should never happen */
|
|
||||||
TxError("Fatal error: Library %s not recorded!\n", filename);
|
|
||||||
newnameptr = strname;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
prefix = (char *)HashGetValue(he2);
|
newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 9);
|
||||||
newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 8);
|
sprintf(newnameptr, "1%s_%s", prefix, strname);
|
||||||
sprintf(newnameptr, "%s_%s", prefix, strname);
|
|
||||||
HashSetValue(he, (char *)newnameptr);
|
HashSetValue(he, (char *)newnameptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
calmaOutStringRecord(CALMA_STRNAME, newnameptr, outf);
|
calmaOutStringRecord(CALMA_STRNAME, newnameptr + 1, outf);
|
||||||
}
|
}
|
||||||
freeMagic(strname);
|
freeMagic(strname);
|
||||||
|
|
||||||
|
|
@ -525,7 +525,7 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
|
||||||
newnameptr = (char *)HashGetValue(he);
|
newnameptr = (char *)HashGetValue(he);
|
||||||
if (newnameptr != NULL)
|
if (newnameptr != NULL)
|
||||||
{
|
{
|
||||||
calmaOutStringRecord(CALMA_SNAME, newnameptr, outf);
|
calmaOutStringRecord(CALMA_SNAME, newnameptr + 1, outf);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -535,14 +535,14 @@ calmaDumpStructure(def, outf, calmaDefHash, filename)
|
||||||
/* the same way used for structure definitions. */
|
/* the same way used for structure definitions. */
|
||||||
|
|
||||||
newnameptr = (char *)mallocMagic(strlen(strname) +
|
newnameptr = (char *)mallocMagic(strlen(strname) +
|
||||||
strlen(prefix) + 8);
|
strlen(prefix) + 9);
|
||||||
sprintf(newnameptr, "%s_%s", prefix, strname);
|
sprintf(newnameptr, "0%s_%s", prefix, strname);
|
||||||
|
|
||||||
edef = DBCellLookDef(newnameptr);
|
edef = DBCellLookDef(newnameptr + 1);
|
||||||
if (edef != NULL)
|
if (edef != NULL)
|
||||||
sprintf(newnameptr, "%s_%s[[0]]", prefix, strname);
|
sprintf(newnameptr, "0%s_%s[[0]]", prefix, strname);
|
||||||
HashSetValue(he, (char *)newnameptr);
|
HashSetValue(he, (char *)newnameptr);
|
||||||
calmaOutStringRecord(CALMA_SNAME, newnameptr, outf);
|
calmaOutStringRecord(CALMA_SNAME, newnameptr + 1, outf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -746,8 +746,11 @@ calmaProcessDef(def, outf)
|
||||||
|
|
||||||
/* Read the cell in if it is not already available. */
|
/* Read the cell in if it is not already available. */
|
||||||
if ((def->cd_flags & CDAVAILABLE) == 0)
|
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);
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Output the definitions for any of our descendants that have
|
* 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))
|
((lab->lab_flags & PORT_NUM_MASK) == i))
|
||||||
{
|
{
|
||||||
calmaWriteLabelFunc(lab, type, f);
|
calmaWriteLabelFunc(lab, type, f);
|
||||||
break;
|
/* break; */ /* Do not limit to unique labels! */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1316,7 +1319,7 @@ calmaOutStructName(type, def, f)
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
{
|
{
|
||||||
char defname[CALMANAMELENGTH+1];
|
char *defname;
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
char *cp;
|
char *cp;
|
||||||
int calmanum;
|
int calmanum;
|
||||||
|
|
@ -1341,10 +1344,11 @@ calmaOutStructName(type, def, f)
|
||||||
}
|
}
|
||||||
/* We really should ensure that the new name is unique. . . */
|
/* 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 */
|
/* Yes, it's legal: use it */
|
||||||
(void) strcpy(defname, def->cd_name);
|
defname = StrDup(NULL, def->cd_name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1352,12 +1356,14 @@ calmaOutStructName(type, def, f)
|
||||||
bad:
|
bad:
|
||||||
calmanum = (int) def->cd_client;
|
calmanum = (int) def->cd_client;
|
||||||
if (calmanum < 0) calmanum = -calmanum;
|
if (calmanum < 0) calmanum = -calmanum;
|
||||||
|
defname = (char *)mallocMagic(32);
|
||||||
(void) sprintf(defname, "XXXXX%d", calmanum);
|
(void) sprintf(defname, "XXXXX%d", calmanum);
|
||||||
TxError("Warning: string in output unprintable; changed to \'%s\'\n",
|
TxError("Warning: string in output unprintable; changed to \'%s\'\n",
|
||||||
defname);
|
defname);
|
||||||
}
|
}
|
||||||
|
|
||||||
calmaOutStringRecord(type, defname, f);
|
calmaOutStringRecord(type, defname, f);
|
||||||
|
freeMagic(defname);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Added by NP 8/21/2004 */
|
/* Added by NP 8/21/2004 */
|
||||||
|
|
@ -2734,7 +2740,7 @@ calmaOutDate(t, f)
|
||||||
void
|
void
|
||||||
calmaOutStringRecord(type, str, f)
|
calmaOutStringRecord(type, str, f)
|
||||||
int type; /* Type of this record (data type is ASCII string) */
|
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 */
|
FILE *f; /* Stream file */
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
@ -2759,9 +2765,16 @@ calmaOutStringRecord(type, str, f)
|
||||||
* last CALMANAMELENGTH characters (since cell names are more
|
* last CALMANAMELENGTH characters (since cell names are more
|
||||||
* likely to be unique in the last characters than in the first
|
* likely to be unique in the last characters than in the first
|
||||||
* characters).
|
* 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 & 01) len++;
|
||||||
if (len > CALMANAMELENGTH)
|
if ((CIFCurStyle->cs_flags & CWF_STRING_LIMIT) && (len > CALMANAMELENGTH))
|
||||||
{
|
{
|
||||||
TxError("Warning: Cellname %s truncated ", str);
|
TxError("Warning: Cellname %s truncated ", str);
|
||||||
TxError("to %s (GDS format limit)\n", str + len - CALMANAMELENGTH);
|
TxError("to %s (GDS format limit)\n", str + len - CALMANAMELENGTH);
|
||||||
|
|
|
||||||
461
cif/CIFgen.c
461
cif/CIFgen.c
|
|
@ -111,6 +111,177 @@ cifPaintFunc(tile, table)
|
||||||
return 0;
|
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;
|
CIFTileOps += 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -842,6 +1013,46 @@ endbloat:
|
||||||
return 0;
|
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
|
int
|
||||||
cifBloatAllFunc(tile, op)
|
cifBloatAllFunc(tile, bls)
|
||||||
Tile *tile; /* The tile to be processed. */
|
Tile *tile; /* The tile to be processed. */
|
||||||
CIFOp *op; /* Describes the operation to be performed */
|
BloatStruct *bls;
|
||||||
{
|
{
|
||||||
Rect area;
|
Rect area;
|
||||||
TileTypeBitMask connect;
|
TileTypeBitMask connect;
|
||||||
Tile *t, *tp;
|
Tile *t, *tp;
|
||||||
TileType type;
|
TileType type;
|
||||||
BloatData *bloats = (BloatData *)op->co_client;
|
BloatData *bloats;
|
||||||
int i;
|
int i, locScale;
|
||||||
|
PlaneMask pmask;
|
||||||
|
CIFOp *op;
|
||||||
|
CellDef *def;
|
||||||
static Stack *BloatStack = (Stack *)NULL;
|
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
|
/* Create a mask of all connecting types (these must be in a single
|
||||||
* plane), then call a search function to find all connecting material
|
* plane), then call a search function to find all connecting material
|
||||||
* of these types.
|
* of these types.
|
||||||
|
|
@ -900,7 +1107,38 @@ cifBloatAllFunc(tile, op)
|
||||||
if (BloatStack == (Stack *)NULL)
|
if (BloatStack == (Stack *)NULL)
|
||||||
BloatStack = StackNew(64);
|
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))
|
while (!StackEmpty(BloatStack))
|
||||||
{
|
{
|
||||||
t = (Tile *) STACKPOP(BloatStack);
|
t = (Tile *) STACKPOP(BloatStack);
|
||||||
|
|
@ -910,10 +1148,10 @@ cifBloatAllFunc(tile, op)
|
||||||
/* Get the tile into CIF coordinates. */
|
/* Get the tile into CIF coordinates. */
|
||||||
|
|
||||||
TiToRect(t, &area);
|
TiToRect(t, &area);
|
||||||
area.r_xbot *= cifScale;
|
area.r_xbot *= locScale;
|
||||||
area.r_ybot *= cifScale;
|
area.r_ybot *= locScale;
|
||||||
area.r_xtop *= cifScale;
|
area.r_xtop *= locScale;
|
||||||
area.r_ytop *= cifScale;
|
area.r_ytop *= locScale;
|
||||||
|
|
||||||
DBNMPaintPlane(cifPlane, TiGetTypeExact(t), &area,
|
DBNMPaintPlane(cifPlane, TiGetTypeExact(t), &area,
|
||||||
CIFPaintTable, (PaintUndoInfo *) NULL);
|
CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||||
|
|
@ -982,6 +1220,134 @@ cifBloatAllFunc(tile, op)
|
||||||
return 0; /* Keep the search alive. . . */
|
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 */
|
/* Support routines and definitions for cifSquaresFillArea */
|
||||||
/*--------------------------------------------------------------*/
|
/*--------------------------------------------------------------*/
|
||||||
|
|
@ -1310,7 +1676,7 @@ cifRectBoundingBox(op, cellDef, plane)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
maxr = FindMaxRectangle2(&bbox, tile, plane);
|
maxr = FindMaxRectangle2(&bbox, tile, plane, NULL);
|
||||||
DBPaintPlane(cifPlane, maxr, CIFPaintTable, (PaintUndoInfo *)NULL);
|
DBPaintPlane(cifPlane, maxr, CIFPaintTable, (PaintUndoInfo *)NULL);
|
||||||
CIFTileOps++;
|
CIFTileOps++;
|
||||||
}
|
}
|
||||||
|
|
@ -1723,7 +2089,7 @@ cifSlotsFillArea(op, cellDef, plane)
|
||||||
{
|
{
|
||||||
Tile *tile, *t, *tp;
|
Tile *tile, *t, *tp;
|
||||||
Rect bbox, area, square, cut, llcut;
|
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 diff, right;
|
||||||
int xpitch, ypitch, xborder, yborder, xdiff, ydiff;
|
int xpitch, ypitch, xborder, yborder, xdiff, ydiff;
|
||||||
int i, j, k, savecount;
|
int i, j, k, savecount;
|
||||||
|
|
@ -1944,16 +2310,17 @@ cifSlotsFillArea(op, cellDef, plane)
|
||||||
|
|
||||||
cifSlotFunc(&bbox, op, &nUp, &nAcross, &llcut, vertical);
|
cifSlotFunc(&bbox, op, &nUp, &nAcross, &llcut, vertical);
|
||||||
|
|
||||||
cut.r_ybot = llcut.r_ybot;
|
cut.r_ybot = llcut.r_ybot + slots->sl_start;
|
||||||
cut.r_ytop = llcut.r_ytop;
|
cut.r_ytop = llcut.r_ytop + slots->sl_start;
|
||||||
|
|
||||||
/* For each contact cut area, check that there is */
|
/* For each contact cut area, check that there is */
|
||||||
/* no whitespace */
|
/* no whitespace */
|
||||||
|
|
||||||
|
offset = slots->sl_start;
|
||||||
for (i = 0; i < nUp; i++)
|
for (i = 0; i < nUp; i++)
|
||||||
{
|
{
|
||||||
cut.r_xbot = llcut.r_xbot;
|
cut.r_xbot = llcut.r_xbot + offset;
|
||||||
cut.r_xtop = llcut.r_xtop;
|
cut.r_xtop = llcut.r_xtop + offset;
|
||||||
|
|
||||||
square.r_ybot = cut.r_ybot - yborder;
|
square.r_ybot = cut.r_ybot - yborder;
|
||||||
square.r_ytop = cut.r_ytop + yborder;
|
square.r_ytop = cut.r_ytop + yborder;
|
||||||
|
|
@ -1980,6 +2347,8 @@ cifSlotsFillArea(op, cellDef, plane)
|
||||||
}
|
}
|
||||||
cut.r_ybot += ypitch;
|
cut.r_ybot += ypitch;
|
||||||
cut.r_ytop += ypitch;
|
cut.r_ytop += ypitch;
|
||||||
|
offset += slots->sl_offset;
|
||||||
|
if (offset >= xpitch) offset -= xpitch;
|
||||||
}
|
}
|
||||||
if (savecount != CIFTileOps) break;
|
if (savecount != CIFTileOps) break;
|
||||||
|
|
||||||
|
|
@ -2688,6 +3057,7 @@ cifSrTiles(cifOp, area, cellDef, temps, func, cdArg)
|
||||||
{
|
{
|
||||||
TileTypeBitMask maskBits;
|
TileTypeBitMask maskBits;
|
||||||
TileType t;
|
TileType t;
|
||||||
|
Tile *tp;
|
||||||
int i;
|
int i;
|
||||||
BloatData *bloats;
|
BloatData *bloats;
|
||||||
|
|
||||||
|
|
@ -2699,7 +3069,7 @@ cifSrTiles(cifOp, area, cellDef, temps, func, cdArg)
|
||||||
|
|
||||||
cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1;
|
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) {
|
switch (cifOp->co_opcode) {
|
||||||
case CIFOP_BLOAT:
|
case CIFOP_BLOAT:
|
||||||
|
|
@ -2783,6 +3153,7 @@ CIFGenLayer(op, area, cellDef, temps, clientdata)
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
TileType ttype;
|
TileType ttype;
|
||||||
char *netname;
|
char *netname;
|
||||||
|
BloatStruct bls;
|
||||||
int (*cifGrowFuncPtr)() = (CIFCurStyle->cs_flags & CWF_GROW_EUCLIDEAN) ?
|
int (*cifGrowFuncPtr)() = (CIFCurStyle->cs_flags & CWF_GROW_EUCLIDEAN) ?
|
||||||
cifGrowEuclideanFunc : cifGrowFunc;
|
cifGrowEuclideanFunc : cifGrowFunc;
|
||||||
|
|
||||||
|
|
@ -2926,6 +3297,20 @@ CIFGenLayer(op, area, cellDef, temps, clientdata)
|
||||||
nextPlane = temp;
|
nextPlane = temp;
|
||||||
break;
|
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. */
|
/* GROW_G grows non-uniformly to the indicated grid. */
|
||||||
|
|
||||||
case CIFOP_GROW_G:
|
case CIFOP_GROW_G:
|
||||||
|
|
@ -2956,6 +3341,22 @@ CIFGenLayer(op, area, cellDef, temps, clientdata)
|
||||||
nextPlane = temp;
|
nextPlane = temp;
|
||||||
break;
|
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:
|
case CIFOP_BLOAT:
|
||||||
cifPlane = curPlane;
|
cifPlane = curPlane;
|
||||||
cifSrTiles(op, area, cellDef, temps,
|
cifSrTiles(op, area, cellDef, temps,
|
||||||
|
|
@ -2971,8 +3372,10 @@ CIFGenLayer(op, area, cellDef, temps, clientdata)
|
||||||
|
|
||||||
case CIFOP_BLOATALL:
|
case CIFOP_BLOATALL:
|
||||||
cifPlane = curPlane;
|
cifPlane = curPlane;
|
||||||
|
bls.op = op;
|
||||||
|
bls.def = cellDef;
|
||||||
cifSrTiles(op, area, cellDef, temps,
|
cifSrTiles(op, area, cellDef, temps,
|
||||||
cifBloatAllFunc, (ClientData) op);
|
cifBloatAllFunc, (ClientData)&bls);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CIFOP_SQUARES:
|
case CIFOP_SQUARES:
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
37
cif/CIFint.h
37
cif/CIFint.h
|
|
@ -69,6 +69,7 @@ typedef struct slots_data
|
||||||
int sl_lsize;
|
int sl_lsize;
|
||||||
int sl_lsep;
|
int sl_lsep;
|
||||||
int sl_offset;
|
int sl_offset;
|
||||||
|
int sl_start;
|
||||||
} SlotsData;
|
} SlotsData;
|
||||||
|
|
||||||
typedef struct cifop
|
typedef struct cifop
|
||||||
|
|
@ -95,6 +96,7 @@ typedef struct cifop
|
||||||
* the masks.
|
* the masks.
|
||||||
* CIFOP_GROW - Grow the current results uniformly by co_distance.
|
* CIFOP_GROW - Grow the current results uniformly by co_distance.
|
||||||
* CIFOP_GROW_G - Grow the current results to snap to the indicated grid.
|
* 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_SHRINK - Shrink the current results uniformly by co_distance.
|
||||||
* CIFOP_BLOAT - Find layers in paintMask, then bloat selectively
|
* CIFOP_BLOAT - Find layers in paintMask, then bloat selectively
|
||||||
* according to bl_distance, and OR the results into
|
* 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,
|
* CIFOP_COPYUP - Added 5/5/16---make and keep a copy the resulting layer,
|
||||||
* which will be painted into parent cells instead of the
|
* which will be painted into parent cells instead of the
|
||||||
* current cell. This replaces the "fault" method.
|
* 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_AND 1
|
||||||
#define CIFOP_OR 2
|
#define CIFOP_OR 2
|
||||||
#define CIFOP_GROW 3
|
#define CIFOP_GROW 3
|
||||||
#define CIFOP_GROW_G 4
|
#define CIFOP_GROWMIN 4
|
||||||
#define CIFOP_SHRINK 5
|
#define CIFOP_GROW_G 5
|
||||||
#define CIFOP_BLOAT 6
|
#define CIFOP_SHRINK 6
|
||||||
#define CIFOP_SQUARES 7
|
#define CIFOP_BLOAT 7
|
||||||
#define CIFOP_SLOTS 8
|
#define CIFOP_SQUARES 8
|
||||||
#define CIFOP_BLOATMAX 9
|
#define CIFOP_SLOTS 9
|
||||||
#define CIFOP_BLOATMIN 10
|
#define CIFOP_BLOATMAX 10
|
||||||
#define CIFOP_BLOATALL 11
|
#define CIFOP_BLOATMIN 11
|
||||||
#define CIFOP_ANDNOT 12
|
#define CIFOP_BLOATALL 12
|
||||||
#define CIFOP_SQUARES_G 13
|
#define CIFOP_ANDNOT 13
|
||||||
#define CIFOP_BBOX 14
|
#define CIFOP_SQUARES_G 14
|
||||||
#define CIFOP_BOUNDARY 15
|
#define CIFOP_BBOX 15
|
||||||
#define CIFOP_NET 16
|
#define CIFOP_BOUNDARY 16
|
||||||
#define CIFOP_MAXRECT 17
|
#define CIFOP_NET 17
|
||||||
#define CIFOP_COPYUP 18
|
#define CIFOP_MAXRECT 18
|
||||||
|
#define CIFOP_COPYUP 19
|
||||||
|
#define CIFOP_CLOSE 20
|
||||||
|
|
||||||
/* Added by Tim 10/21/2004 */
|
/* Added by Tim 10/21/2004 */
|
||||||
/* The following structure is used to pass information on how to draw
|
/* 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_GROW_EUCLIDEAN 0x08
|
||||||
#define CWF_SEE_VENDOR 0x10 /* Override vendor GDS flag in cells */
|
#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_NO_ERRORS 0x20 /* Do not generate error msgs and fdbk */
|
||||||
|
#define CWF_STRING_LIMIT 0x40 /* Use older Calma format character limit */
|
||||||
|
|
||||||
/* procedures */
|
/* procedures */
|
||||||
|
|
||||||
|
|
@ -310,6 +316,7 @@ extern void CIFLoadStyle();
|
||||||
extern Plane *CIFPlanes[]; /* Normal place to store CIF. */
|
extern Plane *CIFPlanes[]; /* Normal place to store CIF. */
|
||||||
extern CIFKeep *CIFStyleList; /* List of all CIF styles. */
|
extern CIFKeep *CIFStyleList; /* List of all CIF styles. */
|
||||||
extern CIFStyle *CIFCurStyle; /* Current style being used. */
|
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 CellUse *CIFComponentUse; /* Flatten stuff in here if needed. */
|
||||||
extern CellDef *CIFComponentDef; /* Corresponds to CIFComponentUse. */
|
extern CellDef *CIFComponentDef; /* Corresponds to CIFComponentUse. */
|
||||||
extern CellUse *CIFDummyUse; /* Used to dummy up a CellUse for a
|
extern CellUse *CIFDummyUse; /* Used to dummy up a CellUse for a
|
||||||
|
|
|
||||||
|
|
@ -752,7 +752,7 @@ cifMakeBoundaryFunc(tile, clientdata)
|
||||||
CIFReadError("Warning: Cell %s boundary was redefined.\n",
|
CIFReadError("Warning: Cell %s boundary was redefined.\n",
|
||||||
cifReadCellDef->cd_name);
|
cifReadCellDef->cd_name);
|
||||||
else
|
else
|
||||||
CalmaError("Warning: Cell %s boundary was redefined.\n",
|
CalmaReadError("Warning: Cell %s boundary was redefined.\n",
|
||||||
cifReadCellDef->cd_name);
|
cifReadCellDef->cd_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1508,13 +1508,18 @@ CIFReadCellCleanup(filetype)
|
||||||
freeMagic((char *)def->cd_client);
|
freeMagic((char *)def->cd_client);
|
||||||
def->cd_client = (ClientData)CLIENTDEFAULT;
|
def->cd_client = (ClientData)CLIENTDEFAULT;
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* If the CDFLATTENED flag was not set, then this geometry */
|
/* 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))
|
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",
|
" %s maps to no magic layers\n",
|
||||||
(filetype == FILE_CIF) ? "CIF" : "GDS", def->cd_name);
|
(filetype == FILE_CIF) ? "CIF" : "GDS", def->cd_name);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* Remove the cell if it has no parents, no children, and no geometry */
|
/* Remove the cell if it has no parents, no children, and no geometry */
|
||||||
|
|
|
||||||
|
|
@ -621,8 +621,10 @@ CIFReadTechLine(sectionName, argc, argv)
|
||||||
|
|
||||||
if (argc >= 3)
|
if (argc >= 3)
|
||||||
{
|
{
|
||||||
if(!strncmp(argv[argc - 1], "nanom", 5))
|
if (!strncmp(argv[argc - 1], "nanom", 5))
|
||||||
cifCurReadStyle->crs_multiplier = 10;
|
cifCurReadStyle->crs_multiplier = 10;
|
||||||
|
else if (!strncmp(argv[argc - 1], "angstr", 6))
|
||||||
|
cifCurReadStyle->crs_multiplier = 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cifCurReadStyle->crs_scaleFactor <= 0)
|
if (cifCurReadStyle->crs_scaleFactor <= 0)
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,10 @@ CIFReadError(char *format, ...)
|
||||||
if (CIFWarningLevel == CIF_WARN_NONE) return;
|
if (CIFWarningLevel == CIF_WARN_NONE) return;
|
||||||
if ((cifTotalErrors < 100) || (CIFWarningLevel != CIF_WARN_LIMIT))
|
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);
|
va_start(args, format);
|
||||||
Vfprintf(stderr, format, args);
|
Vfprintf(stderr, format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
@ -141,7 +144,10 @@ CIFReadWarning(char *format, ...)
|
||||||
if (CIFWarningLevel == CIF_WARN_NONE) return;
|
if (CIFWarningLevel == CIF_WARN_NONE) return;
|
||||||
if ((cifTotalWarnings < 100) || (CIFWarningLevel != CIF_WARN_LIMIT))
|
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);
|
va_start(args, format);
|
||||||
Vfprintf(stderr, format, args);
|
Vfprintf(stderr, format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
|
||||||
|
|
@ -994,6 +994,8 @@ CIFTechLine(sectionName, argc, argv)
|
||||||
CIFCurStyle->cs_flags |= CWF_SEE_VENDOR;
|
CIFCurStyle->cs_flags |= CWF_SEE_VENDOR;
|
||||||
else if (strcmp(argv[i], "no-errors") == 0)
|
else if (strcmp(argv[i], "no-errors") == 0)
|
||||||
CIFCurStyle->cs_flags |= CWF_NO_ERRORS;
|
CIFCurStyle->cs_flags |= CWF_NO_ERRORS;
|
||||||
|
else if (strcmp(argv[i], "string-limit") == 0)
|
||||||
|
CIFCurStyle->cs_flags |= CWF_STRING_LIMIT;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
@ -1023,6 +1025,8 @@ CIFTechLine(sectionName, argc, argv)
|
||||||
newOp->co_opcode = CIFOP_OR;
|
newOp->co_opcode = CIFOP_OR;
|
||||||
else if (strcmp(argv[0], "grow") == 0)
|
else if (strcmp(argv[0], "grow") == 0)
|
||||||
newOp->co_opcode = CIFOP_GROW;
|
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)
|
else if (strcmp(argv[0], "grow-grid") == 0)
|
||||||
newOp->co_opcode = CIFOP_GROW_G;
|
newOp->co_opcode = CIFOP_GROW_G;
|
||||||
else if (strcmp(argv[0], "shrink") == 0)
|
else if (strcmp(argv[0], "shrink") == 0)
|
||||||
|
|
@ -1049,6 +1053,8 @@ CIFTechLine(sectionName, argc, argv)
|
||||||
newOp->co_opcode = CIFOP_MAXRECT;
|
newOp->co_opcode = CIFOP_MAXRECT;
|
||||||
else if (strcmp(argv[0], "boundary") == 0)
|
else if (strcmp(argv[0], "boundary") == 0)
|
||||||
newOp->co_opcode = CIFOP_BOUNDARY;
|
newOp->co_opcode = CIFOP_BOUNDARY;
|
||||||
|
else if (strcmp(argv[0], "close") == 0)
|
||||||
|
newOp->co_opcode = CIFOP_CLOSE;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TechError("Unknown statement \"%s\".\n", argv[0]);
|
TechError("Unknown statement \"%s\".\n", argv[0]);
|
||||||
|
|
@ -1066,8 +1072,10 @@ CIFTechLine(sectionName, argc, argv)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CIFOP_GROW:
|
case CIFOP_GROW:
|
||||||
|
case CIFOP_GROWMIN:
|
||||||
case CIFOP_GROW_G:
|
case CIFOP_GROW_G:
|
||||||
case CIFOP_SHRINK:
|
case CIFOP_SHRINK:
|
||||||
|
case CIFOP_CLOSE:
|
||||||
if (argc != 2) goto wrongNumArgs;
|
if (argc != 2) goto wrongNumArgs;
|
||||||
newOp->co_distance = atoi(argv[1]);
|
newOp->co_distance = atoi(argv[1]);
|
||||||
if (newOp->co_distance <= 0)
|
if (newOp->co_distance <= 0)
|
||||||
|
|
@ -1080,14 +1088,18 @@ CIFTechLine(sectionName, argc, argv)
|
||||||
case CIFOP_BLOATALL:
|
case CIFOP_BLOATALL:
|
||||||
if (argc != 3) goto wrongNumArgs;
|
if (argc != 3) goto wrongNumArgs;
|
||||||
cifParseLayers(argv[1], CIFCurStyle, &newOp->co_paintMask,
|
cifParseLayers(argv[1], CIFCurStyle, &newOp->co_paintMask,
|
||||||
(TileTypeBitMask *)NULL, FALSE);
|
&newOp->co_cifMask, FALSE);
|
||||||
bloatLayers = newOp->co_paintMask;
|
|
||||||
bloats = (BloatData *)mallocMagic(sizeof(BloatData));
|
bloats = (BloatData *)mallocMagic(sizeof(BloatData));
|
||||||
for (i = 0; i < TT_MAXTYPES; i++)
|
for (i = 0; i < TT_MAXTYPES; i++)
|
||||||
bloats->bl_distance[i] = 0;
|
bloats->bl_distance[i] = 0;
|
||||||
newOp->co_client = (ClientData)bloats;
|
newOp->co_client = (ClientData)bloats;
|
||||||
|
|
||||||
cifParseLayers(argv[2], CIFCurStyle, &mask, &tempMask, TRUE);
|
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);
|
TTMaskSetMask(&bloatLayers, &mask);
|
||||||
if (!TTMaskEqual(&tempMask, &DBZeroTypeBits))
|
if (!TTMaskEqual(&tempMask, &DBZeroTypeBits))
|
||||||
TechError("Can't use templayers in bloat statement.\n");
|
TechError("Can't use templayers in bloat statement.\n");
|
||||||
|
|
@ -1323,6 +1335,7 @@ bloatCheck:
|
||||||
slots->sl_lsize = 0;
|
slots->sl_lsize = 0;
|
||||||
slots->sl_lsep = 0;
|
slots->sl_lsep = 0;
|
||||||
slots->sl_offset = 0;
|
slots->sl_offset = 0;
|
||||||
|
slots->sl_start = 0;
|
||||||
}
|
}
|
||||||
if (argc >= 5)
|
if (argc >= 5)
|
||||||
{
|
{
|
||||||
|
|
@ -1357,7 +1370,7 @@ bloatCheck:
|
||||||
goto errorReturn;
|
goto errorReturn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (argc == 8)
|
if (argc >= 8)
|
||||||
{
|
{
|
||||||
i = atoi(argv[7]);
|
i = atoi(argv[7]);
|
||||||
slots->sl_offset = i;
|
slots->sl_offset = i;
|
||||||
|
|
@ -1367,7 +1380,17 @@ bloatCheck:
|
||||||
goto errorReturn;
|
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;
|
goto wrongNumArgs;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1481,6 +1504,7 @@ cifComputeRadii(layer, des)
|
||||||
case CIFOP_OR: break;
|
case CIFOP_OR: break;
|
||||||
|
|
||||||
case CIFOP_GROW:
|
case CIFOP_GROW:
|
||||||
|
case CIFOP_GROWMIN:
|
||||||
case CIFOP_GROW_G:
|
case CIFOP_GROW_G:
|
||||||
grow += op->co_distance;
|
grow += op->co_distance;
|
||||||
break;
|
break;
|
||||||
|
|
@ -1681,7 +1705,7 @@ CIFTechFinal()
|
||||||
{
|
{
|
||||||
slots = (SlotsData *)op->co_client;
|
slots = (SlotsData *)op->co_client;
|
||||||
|
|
||||||
for (j = 0; j < 7; j++)
|
for (j = 0; j < 8; j++)
|
||||||
{
|
{
|
||||||
switch (j) {
|
switch (j) {
|
||||||
case 0: bvalue = slots->sl_sborder; break;
|
case 0: bvalue = slots->sl_sborder; break;
|
||||||
|
|
@ -1691,6 +1715,7 @@ CIFTechFinal()
|
||||||
case 4: bvalue = slots->sl_lsize; break;
|
case 4: bvalue = slots->sl_lsize; break;
|
||||||
case 5: bvalue = slots->sl_lsep; break;
|
case 5: bvalue = slots->sl_lsep; break;
|
||||||
case 6: bvalue = slots->sl_offset; break;
|
case 6: bvalue = slots->sl_offset; break;
|
||||||
|
case 7: bvalue = slots->sl_start; break;
|
||||||
}
|
}
|
||||||
if (bvalue != 0)
|
if (bvalue != 0)
|
||||||
{
|
{
|
||||||
|
|
@ -1945,7 +1970,7 @@ CIFLoadStyle(stylename)
|
||||||
{
|
{
|
||||||
SectionID invcif;
|
SectionID invcif;
|
||||||
|
|
||||||
if (CIFCurStyle->cs_name == stylename) return;
|
if (CIFCurStyle && (CIFCurStyle->cs_name == stylename)) return;
|
||||||
|
|
||||||
cifTechNewStyle();
|
cifTechNewStyle();
|
||||||
CIFCurStyle->cs_name = stylename;
|
CIFCurStyle->cs_name = stylename;
|
||||||
|
|
@ -2092,7 +2117,7 @@ CIFTechOutputScale(n, d)
|
||||||
SquaresData *squares;
|
SquaresData *squares;
|
||||||
SlotsData *slots;
|
SlotsData *slots;
|
||||||
BloatData *bloats;
|
BloatData *bloats;
|
||||||
bool has_odd_space;
|
bool has_odd_space = FALSE;
|
||||||
|
|
||||||
if (ostyle == NULL) return;
|
if (ostyle == NULL) return;
|
||||||
|
|
||||||
|
|
@ -2189,7 +2214,7 @@ CIFTechOutputScale(n, d)
|
||||||
else if (op->co_opcode == CIFOP_SLOTS)
|
else if (op->co_opcode == CIFOP_SLOTS)
|
||||||
{
|
{
|
||||||
slots = (SlotsData *)op->co_client;
|
slots = (SlotsData *)op->co_client;
|
||||||
for (j = 0; j < 7; j++)
|
for (j = 0; j < 8; j++)
|
||||||
{
|
{
|
||||||
switch (j) {
|
switch (j) {
|
||||||
case 0: bptr = &slots->sl_sborder; break;
|
case 0: bptr = &slots->sl_sborder; break;
|
||||||
|
|
@ -2199,6 +2224,7 @@ CIFTechOutputScale(n, d)
|
||||||
case 4: bptr = &slots->sl_lsize; break;
|
case 4: bptr = &slots->sl_lsize; break;
|
||||||
case 5: bptr = &slots->sl_lsep; break;
|
case 5: bptr = &slots->sl_lsep; break;
|
||||||
case 6: bptr = &slots->sl_offset; break;
|
case 6: bptr = &slots->sl_offset; break;
|
||||||
|
case 7: bptr = &slots->sl_start; break;
|
||||||
}
|
}
|
||||||
if (*bptr != 0)
|
if (*bptr != 0)
|
||||||
{
|
{
|
||||||
|
|
@ -2315,6 +2341,8 @@ CIFTechOutputScale(n, d)
|
||||||
slots->sl_lsep /= lexpand;
|
slots->sl_lsep /= lexpand;
|
||||||
if (slots->sl_offset != 0)
|
if (slots->sl_offset != 0)
|
||||||
slots->sl_offset /= lexpand;
|
slots->sl_offset /= lexpand;
|
||||||
|
if (slots->sl_start != 0)
|
||||||
|
slots->sl_start /= lexpand;
|
||||||
break;
|
break;
|
||||||
case CIFOP_SQUARES_G:
|
case CIFOP_SQUARES_G:
|
||||||
squares = (SquaresData *)op->co_client;
|
squares = (SquaresData *)op->co_client;
|
||||||
|
|
|
||||||
|
|
@ -312,7 +312,8 @@ cifOut(outf)
|
||||||
/* Read the cell in if it is not already available. */
|
/* Read the cell in if it is not already available. */
|
||||||
if ((def->cd_flags & CDAVAILABLE) == 0)
|
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
|
/* Add any subcells to the stack. This must be done before
|
||||||
|
|
|
||||||
|
|
@ -1434,7 +1434,7 @@ CmdCif(w, cmd)
|
||||||
if (!ToolGetBox(&rootDef, &box))
|
if (!ToolGetBox(&rootDef, &box))
|
||||||
{
|
{
|
||||||
TxError("Use the box to select the area in");
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if (argc == 5)
|
if (argc == 5)
|
||||||
|
|
@ -3079,7 +3079,7 @@ CmdDown(w, cmd)
|
||||||
GeoTransRect(&EditToRootTransform, &(EditCellUse->cu_def->cd_bbox), &area);
|
GeoTransRect(&EditToRootTransform, &(EditCellUse->cu_def->cd_bbox), &area);
|
||||||
(void) WindSearch(DBWclientID, (ClientData) NULL,
|
(void) WindSearch(DBWclientID, (ClientData) NULL,
|
||||||
(Rect *) NULL, cmdEditRedisplayFunc, (ClientData) &area);
|
(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
|
/* Search function to find the new edit cell: look for a cell use
|
||||||
|
|
@ -3182,7 +3182,7 @@ CmdDrc(w, cmd)
|
||||||
bool doforall = FALSE;
|
bool doforall = FALSE;
|
||||||
bool dolist = FALSE;
|
bool dolist = FALSE;
|
||||||
int count_total;
|
int count_total;
|
||||||
DRCCountList *dcl, *dclsrch;
|
DRCCountList *dcl;
|
||||||
int argc = cmd->tx_argc;
|
int argc = cmd->tx_argc;
|
||||||
char **argv = cmd->tx_argv;
|
char **argv = cmd->tx_argv;
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
|
|
@ -3197,9 +3197,9 @@ CmdDrc(w, cmd)
|
||||||
"*stepsize [d] change DRC step size to d units",
|
"*stepsize [d] change DRC step size to d units",
|
||||||
"catchup run checker and wait for it to complete",
|
"catchup run checker and wait for it to complete",
|
||||||
"check recheck area under box in all cells",
|
"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",
|
"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",
|
"help print this help information",
|
||||||
"off turn off background checker",
|
"off turn off background checker",
|
||||||
"on reenable background checker",
|
"on reenable background checker",
|
||||||
|
|
@ -3313,7 +3313,6 @@ CmdDrc(w, cmd)
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
if (count_total == -1) lobj = Tcl_NewListObj(0, NULL);
|
if (count_total == -1) lobj = Tcl_NewListObj(0, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((window = w) == NULL)
|
if ((window = w) == NULL)
|
||||||
{
|
{
|
||||||
window = ToolGetBoxWindow(&rootArea, (int *) NULL);
|
window = ToolGetBoxWindow(&rootArea, (int *) NULL);
|
||||||
|
|
@ -3323,7 +3322,7 @@ CmdDrc(w, cmd)
|
||||||
rootArea = w->w_surfaceArea;
|
rootArea = w->w_surfaceArea;
|
||||||
|
|
||||||
rootUse = (CellUse *) window->w_surfaceID;
|
rootUse = (CellUse *) window->w_surfaceID;
|
||||||
dcl = DRCCount(rootUse, &rootArea);
|
dcl = DRCCount(rootUse, &rootArea, doforall);
|
||||||
while (dcl != NULL)
|
while (dcl != NULL)
|
||||||
{
|
{
|
||||||
if (count_total >= 0)
|
if (count_total >= 0)
|
||||||
|
|
@ -3343,7 +3342,6 @@ CmdDrc(w, cmd)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (dcl->dcl_count > 1)
|
if (dcl->dcl_count > 1)
|
||||||
TxPrintf("Cell %s has %d error tiles.\n",
|
TxPrintf("Cell %s has %d error tiles.\n",
|
||||||
dcl->dcl_def->cd_name, dcl->dcl_count);
|
dcl->dcl_def->cd_name, dcl->dcl_count);
|
||||||
|
|
@ -3372,11 +3370,12 @@ CmdDrc(w, cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (dolist)
|
else if (dolist)
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
if ((DRCBackGround != DRC_SET_OFF) && (count_total == -1))
|
if ((DRCBackGround != DRC_SET_OFF) && (count_total == -1))
|
||||||
count_total = 0;
|
count_total = 0;
|
||||||
if (count_total >= 0)
|
if (count_gotal >= 0)
|
||||||
TxPrintf("Total DRC errors found: %d\n", count_total);
|
TxPrintf("Total DRC errors found: %d\n", count_total);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
@ -3677,7 +3676,7 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
|
||||||
{
|
{
|
||||||
Point childPoint, editPoint, rootPoint;
|
Point childPoint, editPoint, rootPoint;
|
||||||
CellDef *def, *rootDef, *editDef;
|
CellDef *def, *rootDef, *editDef;
|
||||||
bool hasChild, hasRoot, hasTrans;
|
bool hasChild, hasRoot, hasTrans, dereference;
|
||||||
Rect rootBox, bbox;
|
Rect rootBox, bbox;
|
||||||
Transform *tx_cell, trans_cell;
|
Transform *tx_cell, trans_cell;
|
||||||
char **av;
|
char **av;
|
||||||
|
|
@ -3777,7 +3776,8 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx)
|
||||||
* looked for then no new error message will be printed.
|
* looked for then no new error message will be printed.
|
||||||
*/
|
*/
|
||||||
def->cd_flags &= ~CDNOTFOUND;
|
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);
|
return (FALSE);
|
||||||
DBReComputeBbox(def);
|
DBReComputeBbox(def);
|
||||||
dummy->cu_def = def;
|
dummy->cu_def = def;
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,11 @@ CmdEdit(w, cmd)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!(EditCellUse->cu_def->cd_flags & CDAVAILABLE))
|
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)
|
if (EditCellUse->cu_def->cd_flags & CDNOEDIT)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1452,7 +1452,11 @@ CmdIdentify(w, cmd)
|
||||||
return;
|
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;
|
return;
|
||||||
|
|
||||||
if (SelEnumCells(FALSE, (int *) NULL, (SearchContext *) NULL,
|
if (SelEnumCells(FALSE, (int *) NULL, (SearchContext *) NULL,
|
||||||
|
|
@ -1789,6 +1793,7 @@ FlatCopyAllLabels(scx, mask, xMask, targetUse)
|
||||||
char pathstring[FLATTERMSIZE];
|
char pathstring[FLATTERMSIZE];
|
||||||
TerminalPath tpath;
|
TerminalPath tpath;
|
||||||
|
|
||||||
|
pathstring[0] = '\0';
|
||||||
tpath.tp_first = tpath.tp_next = pathstring;
|
tpath.tp_first = tpath.tp_next = pathstring;
|
||||||
tpath.tp_last = pathstring + FLATTERMSIZE;
|
tpath.tp_last = pathstring + FLATTERMSIZE;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -318,7 +318,7 @@ CmdLabel(w, cmd)
|
||||||
* Implement the "load" command.
|
* Implement the "load" command.
|
||||||
*
|
*
|
||||||
* Usage:
|
* 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
|
* If name is supplied, then the window containing the point tool is
|
||||||
* remapped so as to edit the cell with the given name.
|
* 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
|
* An input file can be scaled by specifying the "scaled" option, for
|
||||||
* which the geometry of the input file is multiplied by n/d.
|
* 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:
|
* Results:
|
||||||
* None.
|
* None.
|
||||||
*
|
*
|
||||||
|
|
@ -350,6 +357,7 @@ CmdLoad(w, cmd)
|
||||||
int locargc = cmd->tx_argc;
|
int locargc = cmd->tx_argc;
|
||||||
bool ignoreTech = FALSE;
|
bool ignoreTech = FALSE;
|
||||||
bool noWindow = FALSE;
|
bool noWindow = FALSE;
|
||||||
|
bool dereference = FALSE;
|
||||||
int keepGoing(); /* forward declaration */
|
int keepGoing(); /* forward declaration */
|
||||||
|
|
||||||
if (locargc > 2)
|
if (locargc > 2)
|
||||||
|
|
@ -359,29 +367,38 @@ CmdLoad(w, cmd)
|
||||||
locargc--;
|
locargc--;
|
||||||
noWindow = TRUE;
|
noWindow = TRUE;
|
||||||
}
|
}
|
||||||
|
if (!strncmp(cmd->tx_argv[locargc - 1], "-deref", 5))
|
||||||
|
{
|
||||||
|
locargc--;
|
||||||
|
dereference = TRUE;
|
||||||
|
}
|
||||||
if (!strncmp(cmd->tx_argv[locargc - 1], "-force", 6))
|
if (!strncmp(cmd->tx_argv[locargc - 1], "-force", 6))
|
||||||
{
|
{
|
||||||
locargc--;
|
locargc--;
|
||||||
ignoreTech = TRUE;
|
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]))
|
StrIsInt(cmd->tx_argv[3]))
|
||||||
{
|
{
|
||||||
n = atoi(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]);
|
d = atoi(cmd->tx_argv[4]);
|
||||||
else if (locargc != 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;
|
return;
|
||||||
}
|
}
|
||||||
DBLambda[0] *= d;
|
DBLambda[0] *= d;
|
||||||
DBLambda[1] *= n;
|
DBLambda[1] *= n;
|
||||||
ReduceFraction(&DBLambda[0], &DBLambda[1]);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -406,7 +423,7 @@ CmdLoad(w, cmd)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
DBWloadWindow((noWindow == TRUE) ? NULL : w, cmd->tx_argv[1],
|
DBWloadWindow((noWindow == TRUE) ? NULL : w, cmd->tx_argv[1],
|
||||||
ignoreTech, FALSE);
|
ignoreTech, FALSE, dereference);
|
||||||
|
|
||||||
if ((n > 1) || (d > 1))
|
if ((n > 1) || (d > 1))
|
||||||
{
|
{
|
||||||
|
|
@ -439,7 +456,7 @@ CmdLoad(w, cmd)
|
||||||
ReduceFraction(&DBLambda[0], &DBLambda[1]);
|
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
|
#ifdef MAGIC_WRAPPER
|
||||||
char *keyvalue;
|
char *keyvalue;
|
||||||
|
|
||||||
keyvalue = (char *)mallocMagic(strlen(name) + strlen((char *)value) + 2);
|
if (value == NULL)
|
||||||
sprintf(keyvalue, "%s %s", name, (char *)value);
|
{
|
||||||
|
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);
|
Tcl_AppendElement(magicinterp, keyvalue);
|
||||||
freeMagic(keyvalue);
|
freeMagic(keyvalue);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -288,6 +288,7 @@ cmdFlushCell(def)
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
{
|
{
|
||||||
CellUse *parentUse;
|
CellUse *parentUse;
|
||||||
|
bool dereference;
|
||||||
|
|
||||||
/* Disallow flushing a cell that contains the edit cell as a child */
|
/* Disallow flushing a cell that contains the edit cell as a child */
|
||||||
if (EditCellUse && (EditCellUse->cu_parent == def))
|
if (EditCellUse && (EditCellUse->cu_parent == def))
|
||||||
|
|
@ -309,7 +310,8 @@ cmdFlushCell(def)
|
||||||
}
|
}
|
||||||
DBCellClearDef(def);
|
DBCellClearDef(def);
|
||||||
DBCellClearAvail(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);
|
DBCellSetAvail(def);
|
||||||
DBReComputeBbox(def);
|
DBReComputeBbox(def);
|
||||||
DBCellSetModified(def, FALSE);
|
DBCellSetModified(def, FALSE);
|
||||||
|
|
|
||||||
|
|
@ -1885,9 +1885,9 @@ CmdXload(w, cmd)
|
||||||
{
|
{
|
||||||
if (CmdIllegalChars(cmd->tx_argv[1], "[],", "Cell name"))
|
if (CmdIllegalChars(cmd->tx_argv[1], "[],", "Cell name"))
|
||||||
return;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -234,7 +234,10 @@ dbCellPlaneSrFunc(scx, fp)
|
||||||
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask))
|
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask))
|
||||||
return 0;
|
return 0;
|
||||||
if ((def->cd_flags & CDAVAILABLE) == 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_scx = scx;
|
||||||
context.tc_filter = fp;
|
context.tc_filter = fp;
|
||||||
|
|
@ -353,7 +356,10 @@ dbCellUniqueTileSrFunc(scx, fp)
|
||||||
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask))
|
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask))
|
||||||
return 0;
|
return 0;
|
||||||
if ((def->cd_flags & CDAVAILABLE) == 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_scx = scx;
|
||||||
context.tc_filter = fp;
|
context.tc_filter = fp;
|
||||||
|
|
@ -462,7 +468,10 @@ DBNoTreeSrTiles(scx, mask, xMask, func, cdarg)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ((def->cd_flags & CDAVAILABLE) == 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_func = func;
|
||||||
filter.tf_arg = cdarg;
|
filter.tf_arg = cdarg;
|
||||||
|
|
@ -570,7 +579,10 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
|
||||||
ASSERT(def != (CellDef *) NULL, "DBTreeSrLabels");
|
ASSERT(def != (CellDef *) NULL, "DBTreeSrLabels");
|
||||||
if (!DBDescendSubcell(cellUse, xMask)) return 0;
|
if (!DBDescendSubcell(cellUse, xMask)) return 0;
|
||||||
if ((def->cd_flags & CDAVAILABLE) == 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)
|
for (lab = def->cd_labels; lab; lab = lab->lab_next)
|
||||||
{
|
{
|
||||||
|
|
@ -613,8 +625,11 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg)
|
||||||
else
|
else
|
||||||
is_touching = GEO_TOUCH(&lab->lab_rect, r);
|
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);
|
is_touching = GEO_TOUCH(&lab->lab_bbox, r);
|
||||||
|
}
|
||||||
|
|
||||||
if (is_touching && TTMaskHasType(mask, lab->lab_type))
|
if (is_touching && TTMaskHasType(mask, lab->lab_type))
|
||||||
if ((*func)(scx, lab, tpath, cdarg))
|
if ((*func)(scx, lab, tpath, cdarg))
|
||||||
|
|
@ -671,7 +686,10 @@ dbCellLabelSrFunc(scx, fp)
|
||||||
ASSERT(def != (CellDef *) NULL, "dbCellLabelSrFunc");
|
ASSERT(def != (CellDef *) NULL, "dbCellLabelSrFunc");
|
||||||
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0;
|
if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0;
|
||||||
if ((def->cd_flags & CDAVAILABLE) == 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)
|
if (fp->tf_tpath != (TerminalPath *) NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -785,8 +803,11 @@ DBTreeSrCells(scx, xMask, func, cdarg)
|
||||||
if (!DBDescendSubcell(cellUse, xMask))
|
if (!DBDescendSubcell(cellUse, xMask))
|
||||||
return 0;
|
return 0;
|
||||||
if ((cellUse->cu_def->cd_flags & CDAVAILABLE) == 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;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
context.tc_scx = scx;
|
context.tc_scx = scx;
|
||||||
context.tc_filter = &filter;
|
context.tc_filter = &filter;
|
||||||
|
|
@ -831,8 +852,11 @@ dbTreeCellSrFunc(scx, fp)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((use->cu_def->cd_flags & CDAVAILABLE) == 0)
|
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;
|
return 0;
|
||||||
|
}
|
||||||
result = DBCellSrArea(scx, dbTreeCellSrFunc, (ClientData) fp);
|
result = DBCellSrArea(scx, dbTreeCellSrFunc, (ClientData) fp);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -1082,8 +1106,12 @@ DBCellSrArea(scx, func, cdarg)
|
||||||
context.tc_scx = scx;
|
context.tc_scx = scx;
|
||||||
|
|
||||||
if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0)
|
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;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (DBSrCellPlaneArea(scx->scx_use->cu_def->cd_cellPlane,
|
if (DBSrCellPlaneArea(scx->scx_use->cu_def->cd_cellPlane,
|
||||||
&scx->scx_area, dbCellSrFunc, (ClientData) &context))
|
&scx->scx_area, dbCellSrFunc, (ClientData) &context))
|
||||||
|
|
@ -1205,7 +1233,10 @@ DBCellEnum(cellDef, func, cdarg)
|
||||||
filter.tf_func = func;
|
filter.tf_func = func;
|
||||||
filter.tf_arg = cdarg;
|
filter.tf_arg = cdarg;
|
||||||
if ((cellDef->cd_flags & CDAVAILABLE) == 0)
|
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,
|
if (DBSrCellPlaneArea(cellDef->cd_cellPlane,
|
||||||
&TiPlaneRect, dbEnumFunc, (ClientData) &filter))
|
&TiPlaneRect, dbEnumFunc, (ClientData) &filter))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
||||||
|
|
@ -73,8 +73,12 @@ DBDescendSubcell(use, xMask)
|
||||||
|
|
||||||
case CU_DESCEND_NO_SUBCKT:
|
case CU_DESCEND_NO_SUBCKT:
|
||||||
if ((use->cu_def->cd_flags & CDAVAILABLE) == 0)
|
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 FALSE;
|
||||||
|
}
|
||||||
return (DBIsSubcircuit(use->cu_def)) ? FALSE : TRUE;
|
return (DBIsSubcircuit(use->cu_def)) ? FALSE : TRUE;
|
||||||
|
|
||||||
case CU_DESCEND_NO_LOCK:
|
case CU_DESCEND_NO_LOCK:
|
||||||
|
|
|
||||||
|
|
@ -661,6 +661,9 @@ dbcUnconnectFunc(tile, clientData)
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* To do: Make the tpath entries dynamically allocated */
|
||||||
|
#define FLATTERMSIZE 1024
|
||||||
|
|
||||||
int
|
int
|
||||||
dbcConnectLabelFunc(scx, lab, tpath, csa2)
|
dbcConnectLabelFunc(scx, lab, tpath, csa2)
|
||||||
SearchContext *scx;
|
SearchContext *scx;
|
||||||
|
|
@ -672,6 +675,8 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2)
|
||||||
Rect r;
|
Rect r;
|
||||||
Point offset;
|
Point offset;
|
||||||
int pos, rotate;
|
int pos, rotate;
|
||||||
|
char newlabtext[FLATTERMSIZE];
|
||||||
|
char *newlabptr;
|
||||||
int dbcConnectFunc(); /* Forward declaration */
|
int dbcConnectFunc(); /* Forward declaration */
|
||||||
|
|
||||||
GeoTransRect(&scx->scx_trans, &lab->lab_rect, &r);
|
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 */
|
/* the top level (Note: Could alter label to be placed with */
|
||||||
/* tpath). */
|
/* 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);
|
int newllen = tpath->tp_next - tpath->tp_first;
|
||||||
DBPutFontLabel(def, &r, lab->lab_font, lab->lab_size, rotate, &offset,
|
newlabtext[0] = '\0';
|
||||||
pos, lab->lab_text, lab->lab_type, lab->lab_flags);
|
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)
|
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);
|
DBTreeSrTiles(scx, mask, xMask, dbcConnectFunc, (ClientData) &csa2);
|
||||||
while (csa2.csa2_top >= 0)
|
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;
|
newmask = csa2.csa2_list[csa2.csa2_top].connectMask;
|
||||||
scx->scx_area = csa2.csa2_list[csa2.csa2_top].area;
|
scx->scx_area = csa2.csa2_list[csa2.csa2_top].area;
|
||||||
newtype = csa2.csa2_list[csa2.csa2_top].dinfo;
|
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;
|
searchtype |= TF_LABEL_ATTACH_NOT_SE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DBTreeSrLabels(scx, newmask, xMask, NULL, searchtype,
|
DBTreeSrLabels(scx, newmask, xMask, &tpath, searchtype,
|
||||||
dbcConnectLabelFunc, (ClientData) &csa2);
|
dbcConnectLabelFunc, (ClientData) &csa2);
|
||||||
}
|
}
|
||||||
freeMagic((char *)csa2.csa2_list);
|
freeMagic((char *)csa2.csa2_list);
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
*/
|
*/
|
||||||
struct expandArg
|
struct expandArg
|
||||||
{
|
{
|
||||||
|
bool ea_deref; /* TRUE if root def dereference flag is set */
|
||||||
int ea_xmask; /* Expand mask. */
|
int ea_xmask; /* Expand mask. */
|
||||||
int (*ea_func)(); /* Function to call for each cell whose
|
int (*ea_func)(); /* Function to call for each cell whose
|
||||||
* status is changed.
|
* status is changed.
|
||||||
|
|
@ -81,7 +82,8 @@ DBExpand(cellUse, expandMask, expandFlag)
|
||||||
def = cellUse->cu_def;
|
def = cellUse->cu_def;
|
||||||
if ((def->cd_flags & CDAVAILABLE) == 0)
|
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;
|
return;
|
||||||
/* Note: we don't have to recompute the bbox here, because
|
/* Note: we don't have to recompute the bbox here, because
|
||||||
* if it changed, then a timestamp violation must have occurred
|
* if it changed, then a timestamp violation must have occurred
|
||||||
|
|
@ -142,9 +144,13 @@ DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg)
|
||||||
int dbExpandFunc(), dbUnexpandFunc();
|
int dbExpandFunc(), dbUnexpandFunc();
|
||||||
SearchContext scontext;
|
SearchContext scontext;
|
||||||
struct expandArg arg;
|
struct expandArg arg;
|
||||||
|
bool dereference = (rootUse->cu_def->cd_flags & CDDEREFERENCE) ?
|
||||||
|
TRUE : FALSE;
|
||||||
|
|
||||||
if ((rootUse->cu_def->cd_flags & CDAVAILABLE) == 0)
|
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
|
* 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_xmask = expandMask;
|
||||||
arg.ea_func = func;
|
arg.ea_func = func;
|
||||||
arg.ea_arg = cdarg;
|
arg.ea_arg = cdarg;
|
||||||
|
arg.ea_deref = dereference;
|
||||||
|
|
||||||
scontext.scx_use = rootUse;
|
scontext.scx_use = rootUse;
|
||||||
scontext.scx_trans = GeoIdentityTransform;
|
scontext.scx_trans = GeoIdentityTransform;
|
||||||
|
|
@ -193,7 +200,7 @@ dbExpandFunc(scx, arg)
|
||||||
/* If the cell is unavailable, then don't expand it.
|
/* If the cell is unavailable, then don't expand it.
|
||||||
*/
|
*/
|
||||||
if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0)
|
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",
|
TxError("Cell %s is unavailable. It could not be expanded.\n",
|
||||||
childUse->cu_def->cd_name);
|
childUse->cu_def->cd_name);
|
||||||
|
|
@ -303,7 +310,8 @@ dbReadAreaFunc(scx)
|
||||||
|
|
||||||
if ((def->cd_flags & CDAVAILABLE) == 0)
|
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
|
/* Note: we don't have to invoke DBReComputeBbox here because
|
||||||
* if the bbox changed then there was a timestamp mismatch and
|
* if the bbox changed then there was a timestamp mismatch and
|
||||||
* the timestamp code will take care of the bounding box later.
|
* the timestamp code will take care of the bounding box later.
|
||||||
|
|
|
||||||
|
|
@ -264,7 +264,7 @@ file_is_not_writeable(name)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
dbCellReadDef(f, cellDef, name, ignoreTech)
|
dbCellReadDef(f, cellDef, name, ignoreTech, dereference)
|
||||||
FILE *f; /* The file, already opened by the caller */
|
FILE *f; /* The file, already opened by the caller */
|
||||||
CellDef *cellDef; /* Pointer to definition of cell to be read in */
|
CellDef *cellDef; /* Pointer to definition of cell to be read in */
|
||||||
char *name; /* Name of file from which to read definition.
|
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
|
* names do not match, but an attempt will be
|
||||||
* made to read the file anyway.
|
* made to read the file anyway.
|
||||||
*/
|
*/
|
||||||
|
bool dereference; /* If TRUE, ignore path references in the input */
|
||||||
{
|
{
|
||||||
int cellStamp = 0, rectCount = 0, rectReport = 10000;
|
int cellStamp = 0, rectCount = 0, rectReport = 10000;
|
||||||
char line[2048], tech[50], layername[50];
|
char line[2048], tech[50], layername[50];
|
||||||
|
|
@ -437,7 +438,7 @@ dbCellReadDef(f, cellDef, name, ignoreTech)
|
||||||
*/
|
*/
|
||||||
if (sscanf(line, "<< %s >>", layername) != 1)
|
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;
|
goto badfile;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -619,6 +620,9 @@ done:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Update timestamp flags */
|
||||||
|
DBFlagMismatches(cellDef);
|
||||||
|
|
||||||
cellDef->cd_timestamp = cellStamp;
|
cellDef->cd_timestamp = cellStamp;
|
||||||
if (cellStamp == 0)
|
if (cellStamp == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -860,7 +864,7 @@ DBReadBackup(name)
|
||||||
cellDef->cd_flags &= ~CDNOTFOUND;
|
cellDef->cd_flags &= ~CDNOTFOUND;
|
||||||
cellDef->cd_flags |= CDAVAILABLE;
|
cellDef->cd_flags |= CDAVAILABLE;
|
||||||
|
|
||||||
if (dbCellReadDef(f, cellDef, filename, TRUE) == FALSE)
|
if (dbCellReadDef(f, cellDef, filename, TRUE, FALSE) == FALSE)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (dbFgets(line, sizeof(line), f) == NULL)
|
if (dbFgets(line, sizeof(line), f) == NULL)
|
||||||
|
|
@ -869,6 +873,8 @@ DBReadBackup(name)
|
||||||
name);
|
name);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
/* Update timestamp flags from dbCellReadDef() */
|
||||||
|
DBFlagMismatches(cellDef);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -914,7 +920,7 @@ DBReadBackup(name)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DBCellRead(cellDef, name, ignoreTech, errptr)
|
DBCellRead(cellDef, name, ignoreTech, dereference, errptr)
|
||||||
CellDef *cellDef; /* Pointer to definition of cell to be read in */
|
CellDef *cellDef; /* Pointer to definition of cell to be read in */
|
||||||
char *name; /* Name of file from which to read definition.
|
char *name; /* Name of file from which to read definition.
|
||||||
* If NULL, then use cellDef->cd_file; if that
|
* 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
|
* names do not match, but an attempt will be
|
||||||
* made to read the file anyway.
|
* 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
|
int *errptr; /* Copy of errno set by file reading routine
|
||||||
* is placed here, unless NULL.
|
* is placed here, unless NULL.
|
||||||
*/
|
*/
|
||||||
|
|
@ -945,7 +952,7 @@ DBCellRead(cellDef, name, ignoreTech, errptr)
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = (dbCellReadDef(f, cellDef, name, ignoreTech));
|
result = (dbCellReadDef(f, cellDef, name, ignoreTech, dereference));
|
||||||
|
|
||||||
#ifdef FILE_LOCKS
|
#ifdef FILE_LOCKS
|
||||||
/* Close files that were locked by another user */
|
/* Close files that were locked by another user */
|
||||||
|
|
@ -1188,13 +1195,14 @@ DBTestOpen(name, fullPath)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
dbReadUse(cellDef, line, len, f, scalen, scaled)
|
dbReadUse(cellDef, line, len, f, scalen, scaled, dereference)
|
||||||
CellDef *cellDef; /* Cell whose cells are being read */
|
CellDef *cellDef; /* Cell whose cells are being read */
|
||||||
char *line; /* Line containing "use ..." */
|
char *line; /* Line containing "use ..." */
|
||||||
int len; /* Size of buffer pointed to by line */
|
int len; /* Size of buffer pointed to by line */
|
||||||
FILE *f; /* Input file */
|
FILE *f; /* Input file */
|
||||||
int scalen; /* Multiply values in file by this */
|
int scalen; /* Multiply values in file by this */
|
||||||
int scaled; /* Divide 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 xlo, xhi, ylo, yhi, xsep, ysep, childStamp;
|
||||||
int absa, absb, absd, abse, nconv;
|
int absa, absb, absd, abse, nconv;
|
||||||
|
|
@ -1225,7 +1233,7 @@ dbReadUse(cellDef, line, len, f, scalen, scaled)
|
||||||
|
|
||||||
pathptr = &path[0];
|
pathptr = &path[0];
|
||||||
while (*pathptr == ' ' || *pathptr == '\t') pathptr++;
|
while (*pathptr == ' ' || *pathptr == '\t') pathptr++;
|
||||||
if (*pathptr == '\n') *pathptr = '\0';
|
if ((dereference == TRUE) || (*pathptr == '\n')) *pathptr = '\0';
|
||||||
|
|
||||||
locked = (useid[0] == CULOCKCHAR) ? TRUE : FALSE;
|
locked = (useid[0] == CULOCKCHAR) ? TRUE : FALSE;
|
||||||
|
|
||||||
|
|
@ -1432,9 +1440,22 @@ badTransform:
|
||||||
slashptr = strrchr(subCellDef->cd_file, '/');
|
slashptr = strrchr(subCellDef->cd_file, '/');
|
||||||
if (slashptr != NULL)
|
if (slashptr != NULL)
|
||||||
{
|
{
|
||||||
|
bool pathOK = FALSE;
|
||||||
*slashptr = '\0';
|
*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 "
|
TxError("Duplicate cell in %s: Instance of cell %s is from "
|
||||||
"path %s but cell was previously read from %s.\n",
|
"path %s but cell was previously read from %s.\n",
|
||||||
|
|
@ -2345,6 +2366,8 @@ DBCellWriteFile(cellDef, f)
|
||||||
int reducer;
|
int reducer;
|
||||||
char *estring;
|
char *estring;
|
||||||
char lstring[256];
|
char lstring[256];
|
||||||
|
char *propvalue;
|
||||||
|
bool propfound;
|
||||||
|
|
||||||
#define FPRINTF(f,s)\
|
#define FPRINTF(f,s)\
|
||||||
{\
|
{\
|
||||||
|
|
@ -2537,12 +2560,43 @@ DBCellWriteFile(cellDef, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* And any properties */
|
/* 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)
|
if (cellDef->cd_props != (ClientData)NULL)
|
||||||
{
|
{
|
||||||
FPRINTF(f, "<< properties >>\n");
|
FPRINTF(f, "<< properties >>\n");
|
||||||
DBPropEnum(cellDef, dbWritePropFunc, (ClientData)f);
|
DBPropEnum(cellDef, dbWritePropFunc, (ClientData)f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (propfound) DBPropPut(cellDef, "FIXED_BBOX", propvalue);
|
||||||
|
|
||||||
FPRINTF(f, "<< end >>\n");
|
FPRINTF(f, "<< end >>\n");
|
||||||
|
|
||||||
if (fflush(f) == EOF || ferror(f))
|
if (fflush(f) == EOF || ferror(f))
|
||||||
|
|
@ -2801,8 +2855,11 @@ DBCellWrite(cellDef, fileName)
|
||||||
|
|
||||||
#ifdef FILE_LOCKS
|
#ifdef FILE_LOCKS
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
bool dereference = (cellDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE;
|
||||||
/* Re-aquire the lock on the new file by opening it. */
|
/* Re-aquire the lock on the new file by opening it. */
|
||||||
DBCellRead(cellDef, NULL, TRUE, NULL);
|
DBCellRead(cellDef, NULL, TRUE, dereference, NULL);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -313,7 +313,55 @@ DBEraseLabel(cellDef, area, mask, areaReturn)
|
||||||
cellDef->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
|
cellDef->cd_flags |= CDMODIFIED|CDGETNEWSTAMP;
|
||||||
return (erasedAny);
|
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;
|
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;
|
for (labPrev = NULL, lab = def->cd_labels;
|
||||||
lab != NULL;
|
lab != NULL;
|
||||||
labPrev = lab, lab = lab->lab_next)
|
labPrev = lab, lab = lab->lab_next)
|
||||||
|
|
|
||||||
|
|
@ -294,20 +294,31 @@ DBTreeFindUse(name, use, scx)
|
||||||
* is read in from disk.
|
* is read in from disk.
|
||||||
*/
|
*/
|
||||||
if ((def->cd_flags & CDAVAILABLE) == 0)
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
cp = name;
|
||||||
* 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';
|
|
||||||
he = HashLookOnly(&def->cd_idHash, name);
|
he = HashLookOnly(&def->cd_idHash, name);
|
||||||
*cp = csave;
|
|
||||||
if (he == NULL || HashGetValue(he) == NULL)
|
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);
|
use = (CellUse *) HashGetValue(he);
|
||||||
def = use->cu_def;
|
def = use->cu_def;
|
||||||
|
|
||||||
|
|
@ -335,7 +346,10 @@ DBTreeFindUse(name, use, scx)
|
||||||
/* Ensure that the leaf cell is read in */
|
/* Ensure that the leaf cell is read in */
|
||||||
def = use->cu_def;
|
def = use->cu_def;
|
||||||
if ((def->cd_flags & CDAVAILABLE) == 0)
|
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;
|
scx->scx_use = use;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,11 +66,23 @@ DBPropPut(cellDef, name, value)
|
||||||
HashInit( (HashTable *) cellDef->cd_props, 8, 0);
|
HashInit( (HashTable *) cellDef->cd_props, 8, 0);
|
||||||
}
|
}
|
||||||
htab = (HashTable *) cellDef->cd_props;
|
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);
|
entry = HashFind(htab, name);
|
||||||
oldvalue = (char *)HashGetValue(entry);
|
oldvalue = (char *)HashGetValue(entry);
|
||||||
if (oldvalue != NULL) freeMagic(oldvalue);
|
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);
|
HashKill(htab);
|
||||||
freeMagic((char *) htab);
|
freeMagic((char *) htab);
|
||||||
cellDef->cd_props = (ClientData) NULL;
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ DBTechInitPlane()
|
||||||
for (dpp = dbTechDefaultPlanes; dpp->dp_names; dpp++)
|
for (dpp = dbTechDefaultPlanes; dpp->dp_names; dpp++)
|
||||||
{
|
{
|
||||||
cp = dbTechNameAdd(dpp->dp_names, (ClientData) dpp->dp_plane,
|
cp = dbTechNameAdd(dpp->dp_names, (ClientData) dpp->dp_plane,
|
||||||
&dbPlaneNameLists);
|
&dbPlaneNameLists, FALSE);
|
||||||
if (cp == NULL)
|
if (cp == NULL)
|
||||||
{
|
{
|
||||||
TxError("DBTechInit: can't add plane names %s\n", dpp->dp_names);
|
TxError("DBTechInit: can't add plane names %s\n", dpp->dp_names);
|
||||||
|
|
@ -224,7 +224,7 @@ DBTechInitType()
|
||||||
for (dtp = dbTechDefaultTypes; dtp->dt_names; dtp++)
|
for (dtp = dbTechDefaultTypes; dtp->dt_names; dtp++)
|
||||||
{
|
{
|
||||||
cp = dbTechNameAdd(dtp->dt_names, (ClientData) dtp->dt_type,
|
cp = dbTechNameAdd(dtp->dt_names, (ClientData) dtp->dt_type,
|
||||||
&dbTypeNameLists);
|
&dbTypeNameLists, FALSE);
|
||||||
if (cp == NULL)
|
if (cp == NULL)
|
||||||
{
|
{
|
||||||
TxError("DBTechInit: can't add type names %s\n", dtp->dt_names);
|
TxError("DBTechInit: can't add type names %s\n", dtp->dt_names);
|
||||||
|
|
@ -283,7 +283,7 @@ DBTechAddPlane(sectionName, argc, argv)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
cp = dbTechNameAdd(argv[0], (ClientData) DBNumPlanes, &dbPlaneNameLists);
|
cp = dbTechNameAdd(argv[0], (ClientData) DBNumPlanes, &dbPlaneNameLists, FALSE);
|
||||||
if (cp == NULL)
|
if (cp == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
DBPlaneLongNameTbl[DBNumPlanes++] = cp;
|
DBPlaneLongNameTbl[DBNumPlanes++] = cp;
|
||||||
|
|
@ -315,7 +315,7 @@ DBTechAddNameToType(newname, ttype, canonical)
|
||||||
{
|
{
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
cp = dbTechNameAdd(newname, (ClientData) ttype, &dbTypeNameLists);
|
cp = dbTechNameAdd(newname, (ClientData) ttype, &dbTypeNameLists, TRUE);
|
||||||
if (canonical)
|
if (canonical)
|
||||||
DBTypeLongNameTbl[ttype] = cp;
|
DBTypeLongNameTbl[ttype] = cp;
|
||||||
}
|
}
|
||||||
|
|
@ -455,7 +455,7 @@ DBTechAddType(sectionName, argc, argv)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cp = dbTechNameAdd(argv[1], (ClientData) DBNumTypes, &dbTypeNameLists);
|
cp = dbTechNameAdd(argv[1], (ClientData) DBNumTypes, &dbTypeNameLists, FALSE);
|
||||||
if (cp == NULL)
|
if (cp == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
|
@ -513,7 +513,7 @@ dbTechNewStackedType(type1, type2)
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(buf, "%s+%s", DBTypeShortName(type1), DBTypeShortName(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)
|
if (cp == NULL)
|
||||||
{
|
{
|
||||||
TechError("Couldn't generate new stacking type %s\n", buf);
|
TechError("Couldn't generate new stacking type %s\n", buf);
|
||||||
|
|
@ -730,10 +730,11 @@ dbTechNameLookup(str, table)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
dbTechNameAdd(name, cdata, ptable)
|
dbTechNameAdd(name, cdata, ptable, alias)
|
||||||
char *name; /* Comma-separated list of names to be added */
|
char *name; /* Comma-separated list of names to be added */
|
||||||
ClientData cdata; /* Value to be stored with each name above */
|
ClientData cdata; /* Value to be stored with each name above */
|
||||||
NameList *ptable; /* Table to which we will add names */
|
NameList *ptable; /* Table to which we will add names */
|
||||||
|
int alias; /* 1 if this is an alias (never make primary) */
|
||||||
{
|
{
|
||||||
char *cp;
|
char *cp;
|
||||||
char onename[BUFSIZ];
|
char onename[BUFSIZ];
|
||||||
|
|
@ -769,7 +770,7 @@ dbTechNameAdd(name, cdata, ptable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (primary)
|
if (primary && (alias == 0))
|
||||||
primary->sn_primary = TRUE;
|
primary->sn_primary = TRUE;
|
||||||
return (first);
|
return (first);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,8 @@ DBFixMismatch()
|
||||||
|
|
||||||
while (mismatch != NULL)
|
while (mismatch != NULL)
|
||||||
{
|
{
|
||||||
|
bool dereference;
|
||||||
|
|
||||||
/* Be careful to remove the front element from the mismatch
|
/* Be careful to remove the front element from the mismatch
|
||||||
* list before processing it, because while processing it we
|
* list before processing it, because while processing it we
|
||||||
* may add new elements to the list.
|
* may add new elements to the list.
|
||||||
|
|
@ -137,7 +139,8 @@ DBFixMismatch()
|
||||||
mismatch = mismatch->mm_next;
|
mismatch = mismatch->mm_next;
|
||||||
if (cellDef->cd_flags & CDPROCESSED) continue;
|
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
|
/* Jimmy up the cell's current bounding box, so the following
|
||||||
* procedure call will absolutely and positively know that
|
* procedure call will absolutely and positively know that
|
||||||
|
|
@ -267,6 +270,16 @@ dbStampFunc(cellDef)
|
||||||
* processing. When DBFixMismatch is called, it will notify
|
* processing. When DBFixMismatch is called, it will notify
|
||||||
* the design-rule checker to recheck both wrongArea, and
|
* the design-rule checker to recheck both wrongArea, and
|
||||||
* the cell's eventual correct area.
|
* 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;
|
Mismatch *mm;
|
||||||
CellUse *parentUse;
|
|
||||||
|
|
||||||
mm = (Mismatch *) mallocMagic((unsigned) (sizeof (Mismatch)));
|
mm = (Mismatch *) mallocMagic((unsigned) (sizeof (Mismatch)));
|
||||||
mm->mm_cellDef = cellDef;
|
mm->mm_cellDef = cellDef;
|
||||||
mm->mm_oldArea = *wrongArea;
|
mm->mm_oldArea = *wrongArea;
|
||||||
mm->mm_next = mismatch;
|
mm->mm_next = mismatch;
|
||||||
mismatch = mm;
|
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;
|
if (parentUse->cu_parent == NULL) continue;
|
||||||
parentUse->cu_parent->cd_flags |= CDSTAMPSCHANGED;
|
parentUse->cu_parent->cd_flags |= CDSTAMPSCHANGED;
|
||||||
|
|
|
||||||
|
|
@ -396,6 +396,9 @@ typedef struct celldef
|
||||||
* with the option "gds readonly true".
|
* with the option "gds readonly true".
|
||||||
* CDVISITED indicates that at least one instance of the cell was
|
* CDVISITED indicates that at least one instance of the cell was
|
||||||
* already output during a file write.
|
* 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
|
#define CDAVAILABLE 0x0001
|
||||||
|
|
@ -413,6 +416,7 @@ typedef struct celldef
|
||||||
#define CDPROCESSEDGDS 0x1000
|
#define CDPROCESSEDGDS 0x1000
|
||||||
#define CDVENDORGDS 0x2000
|
#define CDVENDORGDS 0x2000
|
||||||
#define CDVISITED 0x4000
|
#define CDVISITED 0x4000
|
||||||
|
#define CDDEREFERENCE 0x8000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Description of an array.
|
* Description of an array.
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,7 @@ extern void DBUndoPutLabel();
|
||||||
extern void DBUndoEraseLabel();
|
extern void DBUndoEraseLabel();
|
||||||
extern void DBUndoCellUse();
|
extern void DBUndoCellUse();
|
||||||
extern void DBStampMismatch();
|
extern void DBStampMismatch();
|
||||||
|
extern void DBFlagMismatches();
|
||||||
extern void DBTechAddNameToType();
|
extern void DBTechAddNameToType();
|
||||||
|
|
||||||
extern void dbComputeBbox();
|
extern void dbComputeBbox();
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
* Standard DBWind command set
|
* Standard DBWind command set
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern void CmdAddPath(), CmdArray();
|
extern void CmdAddPath(), CmdAntennaCheck(), CmdArray();
|
||||||
extern void CmdBox(), CmdCellname(), CmdClockwise();
|
extern void CmdBox(), CmdCellname(), CmdClockwise();
|
||||||
extern void CmdContact(), CmdCopy(), CmdCorner();
|
extern void CmdContact(), CmdCopy(), CmdCorner();
|
||||||
extern void CmdCrash(), CmdCrosshair();
|
extern void CmdCrash(), CmdCrosshair();
|
||||||
|
|
@ -222,6 +222,9 @@ DBWInitCommands()
|
||||||
WindAddCommand(DBWclientID,
|
WindAddCommand(DBWclientID,
|
||||||
"addpath [path] append to current search path",
|
"addpath [path] append to current search path",
|
||||||
CmdAddPath, FALSE);
|
CmdAddPath, FALSE);
|
||||||
|
WindAddCommand(DBWclientID,
|
||||||
|
"antennacheck [path] check for antenna violations",
|
||||||
|
CmdAntennaCheck, FALSE);
|
||||||
WindAddCommand(DBWclientID,
|
WindAddCommand(DBWclientID,
|
||||||
"array xsize ysize OR\n"
|
"array xsize ysize OR\n"
|
||||||
"array xlo xhi ylo yhi\n"
|
"array xlo xhi ylo yhi\n"
|
||||||
|
|
|
||||||
|
|
@ -418,7 +418,7 @@ DBWredisplay(w, rootArea, clipArea)
|
||||||
/* Set style information beforehand */
|
/* Set style information beforehand */
|
||||||
GrSetStuff(STYLE_LABEL);
|
GrSetStuff(STYLE_LABEL);
|
||||||
(void) DBTreeSrLabels(&scontext, &DBAllTypeBits, bitMask,
|
(void) DBTreeSrLabels(&scontext, &DBAllTypeBits, bitMask,
|
||||||
(TerminalPath *) NULL, TF_LABEL_DISPLAY,
|
(TerminalPath *) NULL, TF_LABEL_DISPLAY | TF_LABEL_ATTACH,
|
||||||
dbwLabelFunc, (ClientData) NULL);
|
dbwLabelFunc, (ClientData) NULL);
|
||||||
GrClipTo(&rootClip);
|
GrClipTo(&rootClip);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -127,10 +127,10 @@ DBWcreate(window, argc, argv)
|
||||||
|
|
||||||
window->w_clientData = (ClientData) crec;
|
window->w_clientData = (ClientData) crec;
|
||||||
if (argc > 0)
|
if (argc > 0)
|
||||||
DBWloadWindow(window, argv[0], TRUE, FALSE);
|
DBWloadWindow(window, argv[0], TRUE, FALSE, FALSE);
|
||||||
else if (ToolGetBox(&boxDef, &box))
|
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
|
/* Zoom in on the box, leaving a 10% border or at least 2 units
|
||||||
* on each side.
|
* on each side.
|
||||||
|
|
@ -148,7 +148,7 @@ DBWcreate(window, argc, argv)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DBWloadWindow(window, (char *) NULL, TRUE, FALSE);
|
DBWloadWindow(window, (char *) NULL, TRUE, FALSE, FALSE);
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
@ -249,7 +249,7 @@ dbwReloadFunc(w, name)
|
||||||
MagWindow *w;
|
MagWindow *w;
|
||||||
char *name;
|
char *name;
|
||||||
{
|
{
|
||||||
DBWloadWindow(w, name, TRUE, FALSE);
|
DBWloadWindow(w, name, TRUE, FALSE, FALSE);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -274,26 +274,29 @@ dbwReloadFunc(w, name)
|
||||||
* cell doesn't change.
|
* cell doesn't change.
|
||||||
*
|
*
|
||||||
* If "expand" is true, unexpands all subcells of the root cell.
|
* If "expand" is true, unexpands all subcells of the root cell.
|
||||||
|
* If "dereference" is true, ignore path reference in the input file.
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
DBWloadWindow(window, name, ignoreTech, expand)
|
DBWloadWindow(window, name, ignoreTech, expand, dereference)
|
||||||
MagWindow *window; /* Identifies window to which cell is to be bound */
|
MagWindow *window; /* Identifies window to which cell is to be bound */
|
||||||
char *name; /* Name of new cell to be bound to this window */
|
char *name; /* Name of new cell to be bound to this window */
|
||||||
bool ignoreTech; /* If FALSE, indicates that the technology of
|
bool ignoreTech; /* If FALSE, indicates that the technology of
|
||||||
* the layout must match the current technology.
|
* the layout must match the current technology.
|
||||||
*/
|
*/
|
||||||
bool expand; /* Indicates whether or not to expand the cell */
|
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;
|
CellUse *newEditUse;
|
||||||
void DisplayWindow();
|
void DisplayWindow();
|
||||||
int res, newEdit, error_val;
|
int res, newEdit, error_val;
|
||||||
int xadd, yadd;
|
int xadd, yadd;
|
||||||
Rect loadBox;
|
Rect loadBox;
|
||||||
char *rootname;
|
char *rootname;
|
||||||
|
bool isUnnamed;
|
||||||
int UnexpandFunc(); /* forward declaration */
|
int UnexpandFunc(); /* forward declaration */
|
||||||
|
|
||||||
loadBox.r_xbot = loadBox.r_ybot = 0;
|
loadBox.r_xbot = loadBox.r_ybot = 0;
|
||||||
|
|
@ -303,6 +306,19 @@ DBWloadWindow(window, name, ignoreTech, expand)
|
||||||
newEdit = !WindSearch((WindClient) DBWclientID, (ClientData) NULL,
|
newEdit = !WindSearch((WindClient) DBWclientID, (ClientData) NULL,
|
||||||
(Rect *) NULL, dbwLoadFunc, (ClientData) window);
|
(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'))
|
if ((name == (char *) NULL) || (name[0] == '\0'))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
@ -383,7 +399,9 @@ DBWloadWindow(window, name, ignoreTech, expand)
|
||||||
if (newEditDef == (CellDef *) NULL)
|
if (newEditDef == (CellDef *) NULL)
|
||||||
newEditDef = DBCellNewDef(rootname, (char *) 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)
|
if (error_val == ENOENT)
|
||||||
{
|
{
|
||||||
|
|
@ -499,6 +517,12 @@ DBWloadWindow(window, name, ignoreTech, expand)
|
||||||
if (newEdit)
|
if (newEdit)
|
||||||
DBWAreaChanged(newEditDef, &newEditDef->cd_bbox, DBW_ALLWINDOWS,
|
DBWAreaChanged(newEditDef, &newEditDef->cd_bbox, DBW_ALLWINDOWS,
|
||||||
&DBAllButSpaceBits);
|
&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.
|
/* This function is called for each cell whose expansion status changed.
|
||||||
|
|
|
||||||
98
defs.mak
98
defs.mak
|
|
@ -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}
|
|
||||||
|
|
@ -2,7 +2,7 @@ MAGICDIR = ../..
|
||||||
|
|
||||||
include $(MAGICDIR)/defs.mak
|
include $(MAGICDIR)/defs.mak
|
||||||
|
|
||||||
HTML_INSTDIR=$(LIBDIR)/magic/doc/html
|
HTML_INSTDIR=$(INSTALL_LIBDIR)/magic/doc/html
|
||||||
|
|
||||||
install: $(DESTDIR)${HTML_INSTDIR}
|
install: $(DESTDIR)${HTML_INSTDIR}
|
||||||
tar cf - . | (cd $(DESTDIR)${HTML_INSTDIR}; tar xf - )
|
tar cf - . | (cd $(DESTDIR)${HTML_INSTDIR}; tar xf - )
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ Define or print a macro called char
|
||||||
|
|
||||||
Buttons are treated just like keys for the purpose of
|
Buttons are treated just like keys for the purpose of
|
||||||
defining macros. While the official names for buttons
|
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
|
etc., the <B>macro</B> command accepts the abbreviated
|
||||||
forms <B>Button1</B>, and so forth. <P>
|
forms <B>Button1</B>, and so forth. <P>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ MAGICDIR = ../..
|
||||||
include $(MAGICDIR)/defs.mak
|
include $(MAGICDIR)/defs.mak
|
||||||
|
|
||||||
PS_SRCDIR=../psfiles
|
PS_SRCDIR=../psfiles
|
||||||
PS_INSTDIR=$(LIBDIR)/magic/doc
|
PS_INSTDIR=$(INSTALL_LIBDIR)/magic/doc
|
||||||
|
|
||||||
.SUFFIXES: .dvi .tex .ps
|
.SUFFIXES: .dvi .tex .ps
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,36 +15,36 @@ EQN=eqn -Ppsc
|
||||||
include ${MAGICDIR}/defs.mak
|
include ${MAGICDIR}/defs.mak
|
||||||
|
|
||||||
MANFILES = \
|
MANFILES = \
|
||||||
$(DESTDIR)${MANDIR}/man1/ext2spice.1 \
|
$(DESTDIR)${INSTALL_MANDIR}/man1/ext2spice.1 \
|
||||||
$(DESTDIR)${MANDIR}/man1/extcheck.1 \
|
$(DESTDIR)${INSTALL_MANDIR}/man1/extcheck.1 \
|
||||||
$(DESTDIR)${MANDIR}/man1/ext2sim.1 \
|
$(DESTDIR)${INSTALL_MANDIR}/man1/ext2sim.1 \
|
||||||
$(DESTDIR)${MANDIR}/man1/magic.1 \
|
$(DESTDIR)${INSTALL_MANDIR}/man1/magic.1 \
|
||||||
$(DESTDIR)${MANDIR}/man5/cmap.5 \
|
$(DESTDIR)${INSTALL_MANDIR}/man5/cmap.5 \
|
||||||
$(DESTDIR)${MANDIR}/man5/displays.5 \
|
$(DESTDIR)${INSTALL_MANDIR}/man5/displays.5 \
|
||||||
$(DESTDIR)${MANDIR}/man5/dlys.5 \
|
$(DESTDIR)${INSTALL_MANDIR}/man5/dlys.5 \
|
||||||
$(DESTDIR)${MANDIR}/man5/dstyle.5 \
|
$(DESTDIR)${INSTALL_MANDIR}/man5/dstyle.5 \
|
||||||
$(DESTDIR)${MANDIR}/man5/ext.5 \
|
$(DESTDIR)${INSTALL_MANDIR}/man5/ext.5 \
|
||||||
$(DESTDIR)${MANDIR}/man5/glyphs.5 \
|
$(DESTDIR)${INSTALL_MANDIR}/man5/glyphs.5 \
|
||||||
$(DESTDIR)${MANDIR}/man5/mag.5 \
|
$(DESTDIR)${INSTALL_MANDIR}/man5/mag.5 \
|
||||||
$(DESTDIR)${MANDIR}/man5/net.5 \
|
$(DESTDIR)${INSTALL_MANDIR}/man5/net.5 \
|
||||||
$(DESTDIR)${MANDIR}/man5/sim.5
|
$(DESTDIR)${INSTALL_MANDIR}/man5/sim.5
|
||||||
|
|
||||||
install: ${MANFILES}
|
install: ${MANFILES}
|
||||||
|
|
||||||
$(DESTDIR)${MANDIR}:
|
$(DESTDIR)${INSTALL_MANDIR}:
|
||||||
${SCRIPTS}/mkdirs $(DESTDIR)${MANDIR}
|
${SCRIPTS}/mkdirs $(DESTDIR)${INSTALL_MANDIR}
|
||||||
|
|
||||||
$(DESTDIR)${MANDIR}/man1: $(DESTDIR)${MANDIR}
|
$(DESTDIR)${INSTALL_MANDIR}/man1: $(DESTDIR)${INSTALL_MANDIR}
|
||||||
${SCRIPTS}/mkdirs $(DESTDIR)${MANDIR}/man1
|
${SCRIPTS}/mkdirs $(DESTDIR)${INSTALL_MANDIR}/man1
|
||||||
|
|
||||||
$(DESTDIR)${MANDIR}/man1/%: % $(DESTDIR)${MANDIR}/man1
|
$(DESTDIR)${INSTALL_MANDIR}/man1/%: % $(DESTDIR)${INSTALL_MANDIR}/man1
|
||||||
${CP} $* $(DESTDIR)${MANDIR}/man1/$*
|
${CP} $* $(DESTDIR)${INSTALL_MANDIR}/man1/$*
|
||||||
|
|
||||||
$(DESTDIR)${MANDIR}/man5: $(DESTDIR)${MANDIR}
|
$(DESTDIR)${INSTALL_MANDIR}/man5: $(DESTDIR)${INSTALL_MANDIR}
|
||||||
${SCRIPTS}/mkdirs $(DESTDIR)${MANDIR}/man5
|
${SCRIPTS}/mkdirs $(DESTDIR)${INSTALL_MANDIR}/man5
|
||||||
|
|
||||||
$(DESTDIR)${MANDIR}/man5/%: % $(DESTDIR)${MANDIR}/man5
|
$(DESTDIR)${INSTALL_MANDIR}/man5/%: % $(DESTDIR)${INSTALL_MANDIR}/man5
|
||||||
${CP} $* $(DESTDIR)${MANDIR}/man5/$*
|
${CP} $* $(DESTDIR)${INSTALL_MANDIR}/man5/$*
|
||||||
|
|
||||||
mans:
|
mans:
|
||||||
${SCRIPTS}/printmans "${TROFF} ${MANMACS} -" *.1 *.5
|
${SCRIPTS}/printmans "${TROFF} ${MANMACS} -" *.1 *.5
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ MAGICDIR = ../..
|
||||||
|
|
||||||
include ${MAGICDIR}/defs.mak
|
include ${MAGICDIR}/defs.mak
|
||||||
|
|
||||||
TUTDIR = ${LIBDIR}/magic/tutorial
|
TUTDIR = ${INSTALL_LIBDIR}/magic/tutorial
|
||||||
|
|
||||||
TUTFILES= m3a.mag maint2a.mag tut1.mag \
|
TUTFILES= m3a.mag maint2a.mag tut1.mag \
|
||||||
tut2a.mag tut2b.mag tut2c.mag tut2d.mag \
|
tut2a.mag tut2b.mag tut2c.mag tut2d.mag \
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ static DRCCookie drcArrayCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ 0 }, { 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
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ static DRCCookie drcOverlapCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ 0 }, { 0 },
|
{ 0 }, { 0 },
|
||||||
0, 0, 0,
|
0, 0, 0,
|
||||||
"Can't overlap those layers",
|
DRC_OVERLAP_TAG,
|
||||||
(DRCCookie *) NULL
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -484,6 +484,7 @@ drcTile (tile, arg)
|
||||||
int edgeX = LEFT(tile);
|
int edgeX = LEFT(tile);
|
||||||
|
|
||||||
firsttile = TRUE;
|
firsttile = TRUE;
|
||||||
|
mrd = NULL;
|
||||||
for (tpleft = BL(tile); BOTTOM(tpleft) < top; tpleft = RT(tpleft))
|
for (tpleft = BL(tile); BOTTOM(tpleft) < top; tpleft = RT(tpleft))
|
||||||
{
|
{
|
||||||
/* Get the tile types to the left and right of the edge */
|
/* 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);
|
mrd = drcCanonicalMaxwidth(tpleft, GEO_WEST, arg, cptr);
|
||||||
else if (firsttile)
|
else if (firsttile)
|
||||||
mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr);
|
mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr);
|
||||||
else
|
|
||||||
mrd = NULL;
|
|
||||||
if (!trigpending || (DRCCurStyle->DRCFlags
|
if (!trigpending || (DRCCurStyle->DRCFlags
|
||||||
& DRC_FLAGS_WIDEWIDTH_NONINCLUSIVE))
|
& DRC_FLAGS_WIDEWIDTH_NONINCLUSIVE))
|
||||||
cptr->drcc_dist--;
|
cptr->drcc_dist--;
|
||||||
|
|
@ -610,7 +609,6 @@ drcTile (tile, arg)
|
||||||
drcCheckMaxwidth(tile, arg, cptr);
|
drcCheckMaxwidth(tile, arg, cptr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (!triggered) mrd = NULL;
|
|
||||||
|
|
||||||
if (cptr->drcc_flags & DRC_RECTSIZE)
|
if (cptr->drcc_flags & DRC_RECTSIZE)
|
||||||
{
|
{
|
||||||
|
|
@ -625,6 +623,7 @@ drcTile (tile, arg)
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
arg->dCD_radial = 0;
|
arg->dCD_radial = 0;
|
||||||
|
arg->dCD_entries = 0;
|
||||||
do {
|
do {
|
||||||
if (triggered)
|
if (triggered)
|
||||||
{
|
{
|
||||||
|
|
@ -870,6 +869,7 @@ checkbottom:
|
||||||
|
|
||||||
/* Go right across bottom of tile */
|
/* Go right across bottom of tile */
|
||||||
firsttile = TRUE;
|
firsttile = TRUE;
|
||||||
|
mrd = NULL;
|
||||||
for (tpbot = LB(tile); LEFT(tpbot) < right; tpbot = TR(tpbot))
|
for (tpbot = LB(tile); LEFT(tpbot) < right; tpbot = TR(tpbot))
|
||||||
{
|
{
|
||||||
/* Get the tile types to the top and bottom of the edge */
|
/* Get the tile types to the top and bottom of the edge */
|
||||||
|
|
@ -936,8 +936,6 @@ checkbottom:
|
||||||
mrd = drcCanonicalMaxwidth(tpbot, GEO_SOUTH, arg, cptr);
|
mrd = drcCanonicalMaxwidth(tpbot, GEO_SOUTH, arg, cptr);
|
||||||
else if (firsttile)
|
else if (firsttile)
|
||||||
mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr);
|
mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr);
|
||||||
else
|
|
||||||
mrd = NULL;
|
|
||||||
if (!trigpending || (DRCCurStyle->DRCFlags
|
if (!trigpending || (DRCCurStyle->DRCFlags
|
||||||
& DRC_FLAGS_WIDEWIDTH_NONINCLUSIVE))
|
& DRC_FLAGS_WIDEWIDTH_NONINCLUSIVE))
|
||||||
cptr->drcc_dist--;
|
cptr->drcc_dist--;
|
||||||
|
|
@ -992,10 +990,10 @@ checkbottom:
|
||||||
if (trigpending) cptr = cptr->drcc_next;
|
if (trigpending) cptr = cptr->drcc_next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (!triggered) mrd = NULL;
|
|
||||||
|
|
||||||
result = 0;
|
result = 0;
|
||||||
arg->dCD_radial = 0;
|
arg->dCD_radial = 0;
|
||||||
|
arg->dCD_entries = 0;
|
||||||
do {
|
do {
|
||||||
if (triggered)
|
if (triggered)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
76
drc/DRCcif.c
76
drc/DRCcif.c
|
|
@ -48,7 +48,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "utils/malloc.h"
|
#include "utils/malloc.h"
|
||||||
#include "utils/utils.h"
|
#include "utils/utils.h"
|
||||||
|
|
||||||
extern char *drcWhyDup();
|
|
||||||
extern int drcCifTile();
|
extern int drcCifTile();
|
||||||
extern int areaCifCheck();
|
extern int areaCifCheck();
|
||||||
extern void drcCheckCifMaxwidth();
|
extern void drcCheckCifMaxwidth();
|
||||||
|
|
@ -67,9 +66,10 @@ extern bool DRCForceReload;
|
||||||
TileTypeBitMask drcCifGenLayers;
|
TileTypeBitMask drcCifGenLayers;
|
||||||
|
|
||||||
DRCCookie *drcCifRules[MAXCIFLAYERS][2];
|
DRCCookie *drcCifRules[MAXCIFLAYERS][2];
|
||||||
DRCCookie *drcCifCur=NULL;
|
DRCCookie *drcCifCur = NULL;
|
||||||
int drcCifValid = FALSE;
|
int drcCifValid = FALSE;
|
||||||
int beenWarned;
|
bool beenWarned = FALSE;
|
||||||
|
char *drcNeedStyle = NULL;
|
||||||
|
|
||||||
#define DRC_CIF_SPACE 0
|
#define DRC_CIF_SPACE 0
|
||||||
#define DRC_CIF_SOLID 1
|
#define DRC_CIF_SOLID 1
|
||||||
|
|
@ -112,14 +112,12 @@ drcCifSetStyle(argc, argv)
|
||||||
{
|
{
|
||||||
if (!strcmp(new->cs_name, argv[1]))
|
if (!strcmp(new->cs_name, argv[1]))
|
||||||
{
|
{
|
||||||
|
drcNeedStyle = new->cs_name;
|
||||||
DRCForceReload = TRUE;
|
DRCForceReload = TRUE;
|
||||||
if (!strcmp(new->cs_name, CIFCurStyle->cs_name))
|
if (!strcmp(new->cs_name, CIFCurStyle->cs_name))
|
||||||
drcCifStyle = CIFCurStyle;
|
drcCifStyle = CIFCurStyle;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TechError("DRC cif extensions are not enabled.\n\t"
|
|
||||||
"Use \"cif ostyle %s\" to enable them.\n",
|
|
||||||
new->cs_name);
|
|
||||||
drcCifStyle = NULL;
|
drcCifStyle = NULL;
|
||||||
beenWarned = TRUE; /* post no more error messages */
|
beenWarned = TRUE; /* post no more error messages */
|
||||||
}
|
}
|
||||||
|
|
@ -170,7 +168,7 @@ drcCifWidth(argc, argv)
|
||||||
char *layername = argv[1];
|
char *layername = argv[1];
|
||||||
int scalefactor;
|
int scalefactor;
|
||||||
int centidistance = atoi(argv[2]);
|
int centidistance = atoi(argv[2]);
|
||||||
char *why = drcWhyDup(argv[3]);
|
int why = drcWhyCreate(argv[3]);
|
||||||
TileTypeBitMask set, setC, tmp1;
|
TileTypeBitMask set, setC, tmp1;
|
||||||
int thislayer = -1;
|
int thislayer = -1;
|
||||||
DRCCookie *dpnew,*dpnext;
|
DRCCookie *dpnew,*dpnext;
|
||||||
|
|
@ -200,7 +198,7 @@ drcCifWidth(argc, argv)
|
||||||
|
|
||||||
dpnext = drcCifRules[thislayer][DRC_CIF_SPACE];
|
dpnext = drcCifRules[thislayer][DRC_CIF_SPACE];
|
||||||
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
|
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
|
||||||
drcAssign(dpnew, centidistance, dpnext, &CIFSolidBits,
|
drcCifAssign(dpnew, centidistance, dpnext, &CIFSolidBits,
|
||||||
&CIFSolidBits, why, centidistance,
|
&CIFSolidBits, why, centidistance,
|
||||||
DRC_FORWARD, thislayer, 0);
|
DRC_FORWARD, thislayer, 0);
|
||||||
drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew;
|
drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew;
|
||||||
|
|
@ -229,7 +227,7 @@ drcCifSpacing(argc, argv)
|
||||||
char *argv[];
|
char *argv[];
|
||||||
{
|
{
|
||||||
char *adjacency = argv[4];
|
char *adjacency = argv[4];
|
||||||
char *why = drcWhyDup(argv[5]);
|
int why = drcWhyCreate(argv[5]);
|
||||||
DRCCookie *dpnext, *dpnew;
|
DRCCookie *dpnext, *dpnew;
|
||||||
int needReverse = FALSE;
|
int needReverse = FALSE;
|
||||||
TileType i, j;
|
TileType i, j;
|
||||||
|
|
@ -292,7 +290,7 @@ drcCifSpacing(argc, argv)
|
||||||
centidistance *= drcCifStyle->cs_expander; // BSI
|
centidistance *= drcCifStyle->cs_expander; // BSI
|
||||||
dpnext = drcCifRules[layer[0]][DRC_CIF_SOLID];
|
dpnext = drcCifRules[layer[0]][DRC_CIF_SOLID];
|
||||||
dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie));
|
dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie));
|
||||||
drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits,
|
drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits,
|
||||||
&cmask, why, centidistance, DRC_FORWARD, layer[1], 0);
|
&cmask, why, centidistance, DRC_FORWARD, layer[1], 0);
|
||||||
drcCifRules[layer[0]][DRC_CIF_SOLID] = dpnew;
|
drcCifRules[layer[0]][DRC_CIF_SOLID] = dpnew;
|
||||||
if (needReverse) dpnew->drcc_flags |= DRC_BOTHCORNERS;
|
if (needReverse) dpnew->drcc_flags |= DRC_BOTHCORNERS;
|
||||||
|
|
@ -300,7 +298,7 @@ drcCifSpacing(argc, argv)
|
||||||
// Add rule in reverse direction
|
// Add rule in reverse direction
|
||||||
dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE];
|
dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE];
|
||||||
dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie));
|
dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie));
|
||||||
drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits,
|
drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits,
|
||||||
&cmask, why, centidistance, DRC_REVERSE, layer[1], 0);
|
&cmask, why, centidistance, DRC_REVERSE, layer[1], 0);
|
||||||
drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew;
|
drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew;
|
||||||
|
|
||||||
|
|
@ -312,14 +310,14 @@ drcCifSpacing(argc, argv)
|
||||||
dpnew->drcc_flags |= DRC_BOTHCORNERS;
|
dpnew->drcc_flags |= DRC_BOTHCORNERS;
|
||||||
dpnext = drcCifRules[layer[1]][DRC_CIF_SOLID];
|
dpnext = drcCifRules[layer[1]][DRC_CIF_SOLID];
|
||||||
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
|
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);
|
why, centidistance, DRC_FORWARD|DRC_BOTHCORNERS, layer[0], 0);
|
||||||
drcCifRules[layer[1]][DRC_CIF_SOLID] = dpnew;
|
drcCifRules[layer[1]][DRC_CIF_SOLID] = dpnew;
|
||||||
|
|
||||||
// Add rule in reverse direction
|
// Add rule in reverse direction
|
||||||
dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE];
|
dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE];
|
||||||
dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie));
|
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);
|
why, centidistance, DRC_REVERSE|DRC_BOTHCORNERS, layer[0], 0);
|
||||||
drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew;
|
drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew;
|
||||||
|
|
||||||
|
|
@ -327,14 +325,14 @@ drcCifSpacing(argc, argv)
|
||||||
{
|
{
|
||||||
dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE];
|
dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE];
|
||||||
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
|
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
|
||||||
drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits,
|
drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits,
|
||||||
&cmask, why, centidistance, DRC_REVERSE | DRC_BOTHCORNERS,
|
&cmask, why, centidistance, DRC_REVERSE | DRC_BOTHCORNERS,
|
||||||
layer[0], 0);
|
layer[0], 0);
|
||||||
drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew;
|
drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew;
|
||||||
|
|
||||||
dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE];
|
dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE];
|
||||||
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
|
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
|
||||||
drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask,
|
drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask,
|
||||||
why, centidistance, DRC_REVERSE | DRC_BOTHCORNERS,
|
why, centidistance, DRC_REVERSE | DRC_BOTHCORNERS,
|
||||||
layer[1], 0);
|
layer[1], 0);
|
||||||
drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew;
|
drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew;
|
||||||
|
|
@ -345,13 +343,13 @@ drcCifSpacing(argc, argv)
|
||||||
{
|
{
|
||||||
dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE];
|
dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE];
|
||||||
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
|
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);
|
why, scalefactor, DRC_FORWARD, layer[0], 0);
|
||||||
drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew;
|
drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew;
|
||||||
|
|
||||||
dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE];
|
dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE];
|
||||||
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
|
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);
|
why, scalefactor, DRC_FORWARD, layer[1], 0);
|
||||||
drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew;
|
drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew;
|
||||||
}
|
}
|
||||||
|
|
@ -501,9 +499,37 @@ drcCifCheck(arg)
|
||||||
int scale;
|
int scale;
|
||||||
int i,j;
|
int i,j;
|
||||||
int oldTiles;
|
int oldTiles;
|
||||||
|
CIFStyle *CIFSaveStyle = NULL;
|
||||||
|
|
||||||
if (drcCifValid == FALSE) return;
|
if (CIFCurStyle != drcCifStyle)
|
||||||
else if (CIFCurStyle != drcCifStyle) return;
|
{
|
||||||
|
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;
|
scale = drcCifStyle->cs_scaleFactor;
|
||||||
cifrect = *checkRect;
|
cifrect = *checkRect;
|
||||||
|
|
@ -534,6 +560,9 @@ drcCifCheck(arg)
|
||||||
}
|
}
|
||||||
arg->dCD_rect = checkRect;
|
arg->dCD_rect = checkRect;
|
||||||
DRCstatCifTiles += DRCstatTiles - oldTiles;
|
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];
|
char *layers = argv[1];
|
||||||
int centiarea = atoi(argv[2]);
|
int centiarea = atoi(argv[2]);
|
||||||
int centihorizon = atoi(argv[3]);
|
int centihorizon = atoi(argv[3]);
|
||||||
char *why = drcWhyDup(argv[4]);
|
int why = drcWhyCreate(argv[4]);
|
||||||
TileTypeBitMask set, setC, tmp1;
|
TileTypeBitMask set, setC, tmp1;
|
||||||
DRCCookie *dpnext, *dpnew;
|
DRCCookie *dpnext, *dpnew;
|
||||||
TileType i, j;
|
TileType i, j;
|
||||||
|
|
@ -1066,7 +1095,7 @@ drcCifArea(argc, argv)
|
||||||
centiarea *= (drcCifStyle->cs_expander * drcCifStyle->cs_expander);
|
centiarea *= (drcCifStyle->cs_expander * drcCifStyle->cs_expander);
|
||||||
dpnext = drcCifRules[thislayer][DRC_CIF_SPACE];
|
dpnext = drcCifRules[thislayer][DRC_CIF_SPACE];
|
||||||
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
|
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);
|
why, centiarea, DRC_AREA | DRC_FORWARD, thislayer, 0);
|
||||||
drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew;
|
drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew;
|
||||||
|
|
||||||
|
|
@ -1096,7 +1125,7 @@ drcCifMaxwidth(argc, argv)
|
||||||
char *layers = argv[1];
|
char *layers = argv[1];
|
||||||
int centidistance = atoi(argv[2]);
|
int centidistance = atoi(argv[2]);
|
||||||
char *bends = argv[3];
|
char *bends = argv[3];
|
||||||
char *why = drcWhyDup(argv[4]);
|
int why = drcWhyCreate(argv[4]);
|
||||||
TileTypeBitMask set, setC, tmp1;
|
TileTypeBitMask set, setC, tmp1;
|
||||||
DRCCookie *dpnext, *dpnew;
|
DRCCookie *dpnext, *dpnew;
|
||||||
TileType i, j;
|
TileType i, j;
|
||||||
|
|
@ -1136,11 +1165,10 @@ drcCifMaxwidth(argc, argv)
|
||||||
centidistance *= drcCifStyle->cs_expander; // BSI
|
centidistance *= drcCifStyle->cs_expander; // BSI
|
||||||
dpnext = drcCifRules[thislayer][DRC_CIF_SPACE];
|
dpnext = drcCifRules[thislayer][DRC_CIF_SPACE];
|
||||||
dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie)));
|
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);
|
why, centidistance, DRC_MAXWIDTH | bend, thislayer, 0);
|
||||||
drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew;
|
drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew;
|
||||||
|
|
||||||
|
|
||||||
return ((centidistance+scalefactor-1)/scalefactor);
|
return ((centidistance+scalefactor-1)/scalefactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,9 +69,8 @@ TileType DRCErrorType; /* Type of error tile to paint. */
|
||||||
|
|
||||||
/* Used by drcPrintError: */
|
/* Used by drcPrintError: */
|
||||||
|
|
||||||
HashTable DRCErrorTable; /* Hash table used to eliminate duplicate
|
int *DRCErrorList; /* List of DRC error type counts */
|
||||||
* error strings.
|
HashTable DRCErrorTable; /* Table of DRC errors and geometry */
|
||||||
*/
|
|
||||||
|
|
||||||
/* Global variables used by all DRC modules to record statistics.
|
/* Global variables used by all DRC modules to record statistics.
|
||||||
* For each statistic we keep two values, the count since stats
|
* For each statistic we keep two values, the count since stats
|
||||||
|
|
@ -183,11 +182,12 @@ drcSubstitute (cptr)
|
||||||
DRCCookie * cptr; /* Design rule violated */
|
DRCCookie * cptr; /* Design rule violated */
|
||||||
{
|
{
|
||||||
static char *why_out = NULL;
|
static char *why_out = NULL;
|
||||||
char *whyptr = cptr->drcc_why, *sptr, *wptr;
|
char *whyptr, *sptr, *wptr;
|
||||||
int subscnt = 0, whylen;
|
int subscnt = 0, whylen;
|
||||||
float oscale, value;
|
float oscale, value;
|
||||||
extern float CIFGetOutputScale();
|
extern float CIFGetOutputScale();
|
||||||
|
|
||||||
|
whyptr = DRCCurStyle->DRCWhyList[cptr->drcc_tag];
|
||||||
while ((sptr = strchr(whyptr, '%')) != NULL)
|
while ((sptr = strchr(whyptr, '%')) != NULL)
|
||||||
{
|
{
|
||||||
subscnt++;
|
subscnt++;
|
||||||
|
|
@ -195,7 +195,7 @@ drcSubstitute (cptr)
|
||||||
}
|
}
|
||||||
if (subscnt == 0) return whyptr; /* No substitutions */
|
if (subscnt == 0) return whyptr; /* No substitutions */
|
||||||
|
|
||||||
whyptr = cptr->drcc_why;
|
whyptr = DRCCurStyle->DRCWhyList[cptr->drcc_tag];
|
||||||
whylen = strlen(whyptr) + 20 * subscnt;
|
whylen = strlen(whyptr) + 20 * subscnt;
|
||||||
if (why_out != NULL) freeMagic(why_out);
|
if (why_out != NULL) freeMagic(why_out);
|
||||||
why_out = (char *)mallocMagic(whylen * sizeof(char));
|
why_out = (char *)mallocMagic(whylen * sizeof(char));
|
||||||
|
|
@ -256,7 +256,7 @@ drcSubstitute (cptr)
|
||||||
*
|
*
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* DRCErrorCount is incremented. The text associated with
|
* 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
|
* the first time that entry has been seen, then the error
|
||||||
* text is printed. If the area parameter is non-NULL, then
|
* text is printed. If the area parameter is non-NULL, then
|
||||||
* only errors intersecting that area are considered.
|
* only errors intersecting that area are considered.
|
||||||
|
|
@ -279,12 +279,11 @@ drcPrintError (celldef, rect, cptr, scx)
|
||||||
area = &scx->scx_area;
|
area = &scx->scx_area;
|
||||||
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
||||||
DRCErrorCount += 1;
|
DRCErrorCount += 1;
|
||||||
h = HashFind(&DRCErrorTable, cptr->drcc_why);
|
|
||||||
i = (spointertype) HashGetValue(h);
|
i = DRCErrorList[cptr->drcc_tag];
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
TxPrintf("%s\n", drcSubstitute(cptr));
|
TxPrintf("%s\n", drcSubstitute(cptr));
|
||||||
i++;
|
DRCErrorList[cptr->drcc_tag] = i + 1;
|
||||||
HashSetValue(h, (spointertype)i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Same routine as above, but output goes to a Tcl list and is appended */
|
/* 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;
|
area = &scx->scx_area;
|
||||||
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
||||||
DRCErrorCount += 1;
|
DRCErrorCount += 1;
|
||||||
h = HashFind(&DRCErrorTable, cptr->drcc_why);
|
i = DRCErrorList[cptr->drcc_tag];
|
||||||
i = (spointertype) HashGetValue(h);
|
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
{
|
{
|
||||||
Tcl_Obj *lobj;
|
Tcl_Obj *lobj;
|
||||||
|
|
@ -318,8 +316,7 @@ drcListError (celldef, rect, cptr, scx)
|
||||||
Tcl_NewStringObj(drcSubstitute(cptr), -1));
|
Tcl_NewStringObj(drcSubstitute(cptr), -1));
|
||||||
Tcl_SetObjResult(magicinterp, lobj);
|
Tcl_SetObjResult(magicinterp, lobj);
|
||||||
}
|
}
|
||||||
i += 1;
|
DRCErrorList[cptr->drcc_tag] = i + 1;
|
||||||
HashSetValue(h, (spointertype)i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Same routine as above, but output for every single error is recorded */
|
/* 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;
|
area = &scx->scx_area;
|
||||||
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return;
|
||||||
DRCErrorCount += 1;
|
DRCErrorCount += 1;
|
||||||
h = HashFind(&DRCErrorTable, cptr->drcc_why);
|
h = HashFind(&DRCErrorTable, drcSubstitute(cptr));
|
||||||
lobj = (Tcl_Obj *) HashGetValue(h);
|
lobj = (Tcl_Obj *) HashGetValue(h);
|
||||||
if (lobj == NULL)
|
if (lobj == NULL)
|
||||||
lobj = Tcl_NewListObj(0, NULL);
|
lobj = Tcl_NewListObj(0, NULL);
|
||||||
|
|
@ -475,11 +472,15 @@ DRCWhy(dolist, use, area)
|
||||||
{
|
{
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
Rect box;
|
Rect box;
|
||||||
|
int i;
|
||||||
extern int drcWhyFunc(); /* Forward reference. */
|
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;
|
DRCErrorCount = 0;
|
||||||
box = DRCdef->cd_bbox;
|
box = DRCdef->cd_bbox;
|
||||||
|
|
||||||
|
|
@ -494,12 +495,9 @@ DRCWhy(dolist, use, area)
|
||||||
drcWhyFunc(&scx, (pointertype)dolist);
|
drcWhyFunc(&scx, (pointertype)dolist);
|
||||||
UndoEnable();
|
UndoEnable();
|
||||||
|
|
||||||
/* Delete the hash table now that we're finished (otherwise there
|
/* Delete the error list */
|
||||||
* will be a core leak.
|
freeMagic(DRCErrorList);
|
||||||
*/
|
|
||||||
|
|
||||||
HashKill(&DRCErrorTable);
|
|
||||||
|
|
||||||
/* Redisplay the DRC yank definition in case anyone is looking
|
/* Redisplay the DRC yank definition in case anyone is looking
|
||||||
* at it.
|
* at it.
|
||||||
*/
|
*/
|
||||||
|
|
@ -532,7 +530,7 @@ DRCWhyAll(use, area, fout)
|
||||||
HashEntry *he;
|
HashEntry *he;
|
||||||
Tcl_Obj *lobj, *robj;
|
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);
|
HashInit(&DRCErrorTable, 16, HT_STRINGKEYS);
|
||||||
DRCErrorCount = 0;
|
DRCErrorCount = 0;
|
||||||
|
|
@ -566,10 +564,7 @@ DRCWhyAll(use, area, fout)
|
||||||
}
|
}
|
||||||
Tcl_SetObjResult(magicinterp, robj);
|
Tcl_SetObjResult(magicinterp, robj);
|
||||||
|
|
||||||
/* Delete the hash table now that we're finished (otherwise there
|
/* Delete the error table now that we're finished */
|
||||||
* will be a core leak.
|
|
||||||
*/
|
|
||||||
|
|
||||||
HashKill(&DRCErrorTable);
|
HashKill(&DRCErrorTable);
|
||||||
|
|
||||||
/* Redisplay the DRC yank definition in case anyone is looking
|
/* Redisplay the DRC yank definition in case anyone is looking
|
||||||
|
|
@ -748,9 +743,10 @@ drcCheckFunc(scx, cdarg)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DRCCountList *
|
DRCCountList *
|
||||||
DRCCount(use, area)
|
DRCCount(use, area, recurse)
|
||||||
CellUse *use; /* Top-level use of hierarchy. */
|
CellUse *use; /* Top-level use of hierarchy. */
|
||||||
Rect *area; /* Area in which violations are counted. */
|
Rect *area; /* Area in which violations are counted. */
|
||||||
|
bool recurse; /* If TRUE, count errors in all subcells */
|
||||||
{
|
{
|
||||||
DRCCountList *dcl, *newdcl;
|
DRCCountList *dcl, *newdcl;
|
||||||
HashTable dupTable;
|
HashTable dupTable;
|
||||||
|
|
@ -758,7 +754,11 @@ DRCCount(use, area)
|
||||||
HashSearch hs;
|
HashSearch hs;
|
||||||
int count;
|
int count;
|
||||||
SearchContext scx;
|
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
|
/* Use a hash table to make sure that we don't output information
|
||||||
* for any cell more than once.
|
* for any cell more than once.
|
||||||
|
|
@ -766,6 +766,10 @@ DRCCount(use, area)
|
||||||
|
|
||||||
HashInit(&dupTable, 16, HT_WORDKEYS);
|
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_use = use;
|
||||||
scx.scx_x = use->cu_xlo;
|
scx.scx_x = use->cu_xlo;
|
||||||
scx.scx_y = use->cu_ylo;
|
scx.scx_y = use->cu_ylo;
|
||||||
|
|
@ -781,7 +785,7 @@ DRCCount(use, area)
|
||||||
HashStartSearch(&hs);
|
HashStartSearch(&hs);
|
||||||
while ((he = HashNext(&dupTable, &hs)) != (HashEntry *)NULL)
|
while ((he = HashNext(&dupTable, &hs)) != (HashEntry *)NULL)
|
||||||
{
|
{
|
||||||
count = (spointertype)HashGetValue(he);
|
count = (spointertype)HashGetValue(he);
|
||||||
if (count > 1)
|
if (count > 1)
|
||||||
{
|
{
|
||||||
newdcl = (DRCCountList *)mallocMagic(sizeof(DRCCountList));
|
newdcl = (DRCCountList *)mallocMagic(sizeof(DRCCountList));
|
||||||
|
|
@ -793,15 +797,20 @@ DRCCount(use, area)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HashKill(&dupTable);
|
HashKill(&dupTable);
|
||||||
|
|
||||||
|
/* Restore the CDAVAILABLE flag */
|
||||||
|
if (recurse == FALSE)
|
||||||
|
use->cu_def->cd_flags |= CDAVAILABLE;
|
||||||
|
|
||||||
return dcl;
|
return dcl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drcCountFunc(scx, dupTable)
|
drcCountFunc(scx, dupTable)
|
||||||
SearchContext *scx;
|
SearchContext *scx;
|
||||||
HashTable *dupTable; /* Passed as client data, used to
|
HashTable *dupTable; /* Passed as client data, used to
|
||||||
* avoid searching any cell twice.
|
* avoid searching any cell twice.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
int count;
|
int count;
|
||||||
HashEntry *h;
|
HashEntry *h;
|
||||||
|
|
@ -821,7 +830,7 @@ drcCountFunc(scx, dupTable)
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
(void) DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR],
|
(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);
|
HashSetValue(h, (spointertype)count + 1);
|
||||||
|
|
||||||
/* Ignore children that have not been loaded---we will only report */
|
/* 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;
|
if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) return 0;
|
||||||
|
|
||||||
/* New behavior: Don't search children, instead propagate errors up. */
|
/* Scan children recursively. */
|
||||||
/* (void) DBCellSrArea(scx, drcCountFunc, (ClientData) dupTable); */
|
|
||||||
|
DBCellSrArea(scx, drcCountFunc, (ClientData)dupTable);
|
||||||
|
|
||||||
/* As a special performance hack, if the complete cell area is
|
/* As a special performance hack, if the complete cell area is
|
||||||
* handled here, don't bother to look at any more array elements.
|
* handled here, don't bother to look at any more array elements.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
done: if (GEO_SURROUND(&scx->scx_area, &def->cd_bbox)) return 2;
|
done: if (GEO_SURROUND(&scx->scx_area, &def->cd_bbox)) return 2;
|
||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
drcCountFunc2(tile, pCount)
|
drcCountFunc2(tile, countptr)
|
||||||
Tile *tile; /* Tile found in error plane. */
|
Tile *tile; /* Tile found in error plane. */
|
||||||
int *pCount; /* Address of count word. */
|
int *countptr; /* Address of count word. */
|
||||||
{
|
{
|
||||||
if (TiGetType(tile) != (TileType) TT_SPACE) *pCount += 1;
|
if (TiGetType(tile) != (TileType) TT_SPACE) (*countptr)++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -963,13 +972,15 @@ drcFindFunc(scx, finddata)
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
HashEntry *h;
|
HashEntry *h;
|
||||||
int drcFindFunc2();
|
int drcFindFunc2();
|
||||||
|
bool dereference;
|
||||||
|
|
||||||
def = scx->scx_use->cu_def;
|
def = scx->scx_use->cu_def;
|
||||||
h = HashFind(finddata->deft, (char *)def);
|
h = HashFind(finddata->deft, (char *)def);
|
||||||
if (HashGetValue(h) != 0) return 0;
|
if (HashGetValue(h) != 0) return 0;
|
||||||
HashSetValue(h, 1);
|
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],
|
if (DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR],
|
||||||
&def->cd_bbox, &DBAllButSpaceBits, drcFindFunc2,
|
&def->cd_bbox, &DBAllButSpaceBits, drcFindFunc2,
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ static DRCCookie drcSubcellCookie = {
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
{ 0 }, { 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
|
(DRCCookie *) NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
167
drc/DRCtech.c
167
drc/DRCtech.c
|
|
@ -40,6 +40,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
|
|
||||||
CIFStyle *drcCifStyle = NULL;
|
CIFStyle *drcCifStyle = NULL;
|
||||||
bool DRCForceReload = FALSE;
|
bool DRCForceReload = FALSE;
|
||||||
|
HashTable DRCWhyErrorTable; /* Table of DRC errors */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DRC interaction radius being used (not necessarily the same as
|
* DRC interaction radius being used (not necessarily the same as
|
||||||
|
|
@ -61,6 +62,11 @@ global int DRCRuleOptimization = TRUE;
|
||||||
static int drcRulesSpecified = 0;
|
static int drcRulesSpecified = 0;
|
||||||
static int drcRulesOptimized = 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.
|
* Forward declarations.
|
||||||
*/
|
*/
|
||||||
|
|
@ -281,21 +287,14 @@ drcTechFreeStyle()
|
||||||
dp = DRCCurStyle->DRCRulesTbl[i][j];
|
dp = DRCCurStyle->DRCRulesTbl[i][j];
|
||||||
while (dp != NULL)
|
while (dp != NULL)
|
||||||
{
|
{
|
||||||
char *old = (char *) dp;
|
char *old = (char *)dp;
|
||||||
dp = dp->drcc_next;
|
dp = dp->drcc_next;
|
||||||
freeMagic(old);
|
freeMagic(old);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear the DRCWhyList */
|
/* Clear the Why string list */
|
||||||
|
freeMagic(DRCCurStyle->DRCWhyList);
|
||||||
while (DRCCurStyle->DRCWhyList != NULL)
|
|
||||||
{
|
|
||||||
old = (char *) DRCCurStyle->DRCWhyList;
|
|
||||||
StrDup(&(DRCCurStyle->DRCWhyList->dwl_string), (char *) NULL);
|
|
||||||
DRCCurStyle->DRCWhyList = DRCCurStyle->DRCWhyList->dwl_next;
|
|
||||||
freeMagic(old);
|
|
||||||
}
|
|
||||||
|
|
||||||
freeMagic(DRCCurStyle);
|
freeMagic(DRCCurStyle);
|
||||||
DRCCurStyle = NULL;
|
DRCCurStyle = NULL;
|
||||||
|
|
@ -329,31 +328,55 @@ drcTechNewStyle()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
* drcWhyDup --
|
* drcWhyCreate --
|
||||||
*
|
*
|
||||||
* Duplicate a shared "why" string using StrDup() and remember it so we can
|
* Create a hash entry for the DRC "why" string, if it does not already
|
||||||
* free it sometime later, in drcWhyClear().
|
* exist.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* A copy of the given string.
|
* A pointer to the drcWhy structure containing the string and tag.
|
||||||
*
|
*
|
||||||
* Side effects:
|
* 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 *
|
int
|
||||||
drcWhyDup(why)
|
drcWhyCreate(whystring)
|
||||||
char * why;
|
char *whystring;
|
||||||
{
|
{
|
||||||
struct drcwhylist * new;
|
HashEntry *he;
|
||||||
|
|
||||||
new = (struct drcwhylist *) mallocMagic((unsigned) (sizeof *new));
|
he = HashLookOnly(&DRCWhyErrorTable, whystring);
|
||||||
new->dwl_string = StrDup((char **) NULL, why);
|
if (he != NULL)
|
||||||
new->dwl_next = DRCCurStyle->DRCWhyList;
|
return (int)((pointertype)HashGetValue(he));
|
||||||
DRCCurStyle->DRCWhyList = new;
|
|
||||||
|
|
||||||
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;
|
DRCCurStyle->ds_status = TECH_NOT_LOADED;
|
||||||
|
|
||||||
TTMaskZero(&DRCCurStyle->DRCExactOverlapTypes);
|
TTMaskZero(&DRCCurStyle->DRCExactOverlapTypes);
|
||||||
DRCCurStyle->DRCWhyList = NULL;
|
|
||||||
DRCCurStyle->DRCTechHalo = 0;
|
DRCCurStyle->DRCTechHalo = 0;
|
||||||
DRCCurStyle->DRCScaleFactorN = 1;
|
DRCCurStyle->DRCScaleFactorN = 1;
|
||||||
DRCCurStyle->DRCScaleFactorD = 1;
|
DRCCurStyle->DRCScaleFactorD = 1;
|
||||||
DRCCurStyle->DRCStepSize = 0;
|
DRCCurStyle->DRCStepSize = 0;
|
||||||
DRCCurStyle->DRCFlags = (char)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;
|
DRCTechHalo = 0;
|
||||||
|
|
||||||
|
|
@ -872,22 +912,18 @@ DRCTechLine(sectionName, argc, argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
DRCCookie *cookie, *next;
|
||||||
int dist, cdist;
|
int dist, cdist;
|
||||||
TileTypeBitMask *mask, *corner;
|
TileTypeBitMask *mask, *corner;
|
||||||
char *why;
|
int tag;
|
||||||
int flags, planeto, planefrom;
|
int flags, planeto, planefrom;
|
||||||
{
|
{
|
||||||
/* Diagnostic */
|
|
||||||
if (planeto >= DBNumPlanes) {
|
|
||||||
TxError("Bad plane in DRC assign!\n");
|
|
||||||
}
|
|
||||||
(cookie)->drcc_dist = dist;
|
(cookie)->drcc_dist = dist;
|
||||||
(cookie)->drcc_next = next;
|
(cookie)->drcc_next = next;
|
||||||
(cookie)->drcc_mask = *mask;
|
(cookie)->drcc_mask = *mask;
|
||||||
(cookie)->drcc_corner = *corner;
|
(cookie)->drcc_corner = *corner;
|
||||||
(cookie)->drcc_why = why;
|
(cookie)->drcc_tag = tag;
|
||||||
(cookie)->drcc_cdist = cdist;
|
(cookie)->drcc_cdist = cdist;
|
||||||
(cookie)->drcc_flags = flags;
|
(cookie)->drcc_flags = flags;
|
||||||
(cookie)->drcc_edgeplane = planefrom;
|
(cookie)->drcc_edgeplane = planefrom;
|
||||||
|
|
@ -896,6 +932,27 @@ drcAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefro
|
||||||
(cookie)->drcc_cmod = 0;
|
(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 *layers1 = argv[1];
|
||||||
char *layers2 = argv[2];
|
char *layers2 = argv[2];
|
||||||
int distance = atoi(argv[3]);
|
int distance = atoi(argv[3]);
|
||||||
char *why;
|
int why;
|
||||||
TileTypeBitMask set1, setC;
|
TileTypeBitMask set1, setC;
|
||||||
DRCCookie *dp, *dpnew, *dptrig;
|
DRCCookie *dp, *dpnew, *dptrig;
|
||||||
TileType i, j;
|
TileType i, j;
|
||||||
|
|
@ -1083,10 +1140,10 @@ drcExtend(argc, argv)
|
||||||
if (!strncmp(argv[4], "exact_", 6))
|
if (!strncmp(argv[4], "exact_", 6))
|
||||||
{
|
{
|
||||||
exact = TRUE;
|
exact = TRUE;
|
||||||
why = drcWhyDup(argv[5]);
|
why = drcWhyCreate(argv[5]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
why = drcWhyDup(argv[4]);
|
why = drcWhyCreate(argv[4]);
|
||||||
|
|
||||||
ptest = DBTechNoisyNameMask(layers1, &set1);
|
ptest = DBTechNoisyNameMask(layers1, &set1);
|
||||||
pMask1 = CoincidentPlanes(&set1, ptest);
|
pMask1 = CoincidentPlanes(&set1, ptest);
|
||||||
|
|
@ -1240,7 +1297,7 @@ drcWidth(argc, argv)
|
||||||
{
|
{
|
||||||
char *layers = argv[1];
|
char *layers = argv[1];
|
||||||
int distance = atoi(argv[2]);
|
int distance = atoi(argv[2]);
|
||||||
char *why = drcWhyDup(argv[3]);
|
int why = drcWhyCreate(argv[3]);
|
||||||
TileTypeBitMask set, setC;
|
TileTypeBitMask set, setC;
|
||||||
PlaneMask pmask, pset, ptest;
|
PlaneMask pmask, pset, ptest;
|
||||||
DRCCookie *dp, *dpnew;
|
DRCCookie *dp, *dpnew;
|
||||||
|
|
@ -1325,7 +1382,7 @@ drcArea(argc, argv)
|
||||||
char *layers = argv[1];
|
char *layers = argv[1];
|
||||||
int distance = atoi(argv[2]);
|
int distance = atoi(argv[2]);
|
||||||
int horizon = atoi(argv[3]);
|
int horizon = atoi(argv[3]);
|
||||||
char *why = drcWhyDup(argv[4]);
|
int why = drcWhyCreate(argv[4]);
|
||||||
TileTypeBitMask set, setC;
|
TileTypeBitMask set, setC;
|
||||||
DRCCookie *dp, *dpnew;
|
DRCCookie *dp, *dpnew;
|
||||||
TileType i, j;
|
TileType i, j;
|
||||||
|
|
@ -1425,7 +1482,7 @@ drcMaxwidth(argc, argv)
|
||||||
char *layers = argv[1];
|
char *layers = argv[1];
|
||||||
int distance = atoi(argv[2]);
|
int distance = atoi(argv[2]);
|
||||||
char *bends = argv[3];
|
char *bends = argv[3];
|
||||||
char *why;
|
int why;
|
||||||
TileTypeBitMask set, setC;
|
TileTypeBitMask set, setC;
|
||||||
DRCCookie *dp, *dpnew;
|
DRCCookie *dp, *dpnew;
|
||||||
TileType i, j;
|
TileType i, j;
|
||||||
|
|
@ -1452,7 +1509,7 @@ drcMaxwidth(argc, argv)
|
||||||
bend = 0;
|
bend = 0;
|
||||||
else
|
else
|
||||||
bend = DRC_BENDS;
|
bend = DRC_BENDS;
|
||||||
why = drcWhyDup(argv[3]);
|
why = drcWhyCreate(argv[3]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1463,7 +1520,7 @@ drcMaxwidth(argc, argv)
|
||||||
TechError("unknown bend option %s\n",bends);
|
TechError("unknown bend option %s\n",bends);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
why = drcWhyDup(argv[4]);
|
why = drcWhyCreate(argv[4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < DBNumTypes; i++)
|
for (i = 0; i < DBNumTypes; i++)
|
||||||
|
|
@ -1514,7 +1571,7 @@ drcAngles(argc, argv)
|
||||||
{
|
{
|
||||||
char *layers = argv[1];
|
char *layers = argv[1];
|
||||||
int angles = atoi(argv[2]);
|
int angles = atoi(argv[2]);
|
||||||
char *why = drcWhyDup(argv[3]);
|
int why = drcWhyCreate(argv[3]);
|
||||||
TileTypeBitMask set;
|
TileTypeBitMask set;
|
||||||
DRCCookie *dp, *dpnew;
|
DRCCookie *dp, *dpnew;
|
||||||
int plane;
|
int plane;
|
||||||
|
|
@ -1582,7 +1639,7 @@ drcSpacing3(argc, argv)
|
||||||
char *layers3 = argv[5];
|
char *layers3 = argv[5];
|
||||||
int distance = atoi(argv[3]);
|
int distance = atoi(argv[3]);
|
||||||
char *adjacency = argv[4];
|
char *adjacency = argv[4];
|
||||||
char *why = drcWhyDup(argv[6]);
|
int why = drcWhyCreate(argv[6]);
|
||||||
TileTypeBitMask set1, set2, set3;
|
TileTypeBitMask set1, set2, set3;
|
||||||
int plane;
|
int plane;
|
||||||
DRCCookie *dp, *dpnew;
|
DRCCookie *dp, *dpnew;
|
||||||
|
|
@ -2134,7 +2191,7 @@ drcSpacing(argc, argv)
|
||||||
{
|
{
|
||||||
char *layers1 = argv[1], *layers2;
|
char *layers1 = argv[1], *layers2;
|
||||||
char *adjacency;
|
char *adjacency;
|
||||||
char *why;
|
int why;
|
||||||
TileTypeBitMask set1, set2, tmp1, tmp2;
|
TileTypeBitMask set1, set2, tmp1, tmp2;
|
||||||
PlaneMask pmask1, pmask2, pmaskA, pmaskB, ptest;
|
PlaneMask pmask1, pmask2, pmaskA, pmaskB, ptest;
|
||||||
int wwidth, distance, plane, plane2, runlength;
|
int wwidth, distance, plane, plane2, runlength;
|
||||||
|
|
@ -2155,7 +2212,7 @@ drcSpacing(argc, argv)
|
||||||
layers2 = argv[4];
|
layers2 = argv[4];
|
||||||
distance = atoi(argv[5]);
|
distance = atoi(argv[5]);
|
||||||
adjacency = argv[6];
|
adjacency = argv[6];
|
||||||
why = drcWhyDup(argv[7]);
|
why = drcWhyCreate(argv[7]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -2163,7 +2220,7 @@ drcSpacing(argc, argv)
|
||||||
distance = atoi(argv[4]);
|
distance = atoi(argv[4]);
|
||||||
runlength = distance;
|
runlength = distance;
|
||||||
adjacency = argv[5];
|
adjacency = argv[5];
|
||||||
why = drcWhyDup(argv[6]);
|
why = drcWhyCreate(argv[6]);
|
||||||
}
|
}
|
||||||
/* TxPrintf("Info: DRCtech: widespacing rule for %s width %d:"
|
/* TxPrintf("Info: DRCtech: widespacing rule for %s width %d:"
|
||||||
" spacing must be %d\n", layers1, wwidth, distance); */
|
" spacing must be %d\n", layers1, wwidth, distance); */
|
||||||
|
|
@ -2174,7 +2231,7 @@ drcSpacing(argc, argv)
|
||||||
distance = atoi(argv[3]);
|
distance = atoi(argv[3]);
|
||||||
adjacency = argv[4];
|
adjacency = argv[4];
|
||||||
wwidth = distance;
|
wwidth = distance;
|
||||||
why = drcWhyDup(argv[5]);
|
why = drcWhyCreate(argv[5]);
|
||||||
runlength = distance;
|
runlength = distance;
|
||||||
if (argc >= 7)
|
if (argc >= 7)
|
||||||
{
|
{
|
||||||
|
|
@ -2308,7 +2365,7 @@ drcEdge(argc, argv)
|
||||||
int distance = atoi(argv[3]);
|
int distance = atoi(argv[3]);
|
||||||
char *okTypes = argv[4], *cornerTypes = argv[5];
|
char *okTypes = argv[4], *cornerTypes = argv[5];
|
||||||
int cdist = atoi(argv[6]);
|
int cdist = atoi(argv[6]);
|
||||||
char *why = drcWhyDup(argv[7]);
|
int why = drcWhyCreate(argv[7]);
|
||||||
bool fourway = (strcmp(argv[0], "edge4way") == 0);
|
bool fourway = (strcmp(argv[0], "edge4way") == 0);
|
||||||
TileTypeBitMask set1, set2, setC, setM;
|
TileTypeBitMask set1, set2, setC, setM;
|
||||||
DRCCookie *dp, *dpnew;
|
DRCCookie *dp, *dpnew;
|
||||||
|
|
@ -2474,7 +2531,7 @@ drcOverhang(argc, argv)
|
||||||
{
|
{
|
||||||
char *layers2 = argv[1], *layers1 = argv[2];
|
char *layers2 = argv[1], *layers1 = argv[2];
|
||||||
int distance = atoi(argv[3]);
|
int distance = atoi(argv[3]);
|
||||||
char *why = drcWhyDup(argv[4]);
|
int why = drcWhyCreate(argv[4]);
|
||||||
TileTypeBitMask set1, set2, setM, setC, setN, set2inv;
|
TileTypeBitMask set1, set2, setM, setC, setN, set2inv;
|
||||||
DRCCookie *dp, *dpnew, *dptrig;
|
DRCCookie *dp, *dpnew, *dptrig;
|
||||||
int plane, plane2;
|
int plane, plane2;
|
||||||
|
|
@ -2610,7 +2667,7 @@ drcRectOnly(argc, argv)
|
||||||
char *argv[];
|
char *argv[];
|
||||||
{
|
{
|
||||||
char *layers = argv[1];
|
char *layers = argv[1];
|
||||||
char *why = drcWhyDup(argv[2]);
|
int why = drcWhyCreate(argv[2]);
|
||||||
TileTypeBitMask set1, set2, setC;
|
TileTypeBitMask set1, set2, setC;
|
||||||
PlaneMask pmask, pset, ptest;
|
PlaneMask pmask, pset, ptest;
|
||||||
DRCCookie *dp, *dpnew;
|
DRCCookie *dp, *dpnew;
|
||||||
|
|
@ -2710,7 +2767,7 @@ drcSurround(argc, argv)
|
||||||
char *layers1 = argv[1], *layers2 = argv[2];
|
char *layers1 = argv[1], *layers2 = argv[2];
|
||||||
int distance = atoi(argv[3]);
|
int distance = atoi(argv[3]);
|
||||||
char *presence = argv[4];
|
char *presence = argv[4];
|
||||||
char *why = drcWhyDup(argv[5]);
|
int why = drcWhyCreate(argv[5]);
|
||||||
TileTypeBitMask set1, set2, setM, invM, setR;
|
TileTypeBitMask set1, set2, setM, invM, setR;
|
||||||
DRCCookie *dp, *dpnew, *dptrig;
|
DRCCookie *dp, *dpnew, *dptrig;
|
||||||
int plane1, plane2;
|
int plane1, plane2;
|
||||||
|
|
@ -3083,7 +3140,7 @@ drcRectangle(argc, argv)
|
||||||
char *argv[];
|
char *argv[];
|
||||||
{
|
{
|
||||||
char *layers = argv[1];
|
char *layers = argv[1];
|
||||||
char *why = drcWhyDup(argv[4]);
|
int why = drcWhyCreate(argv[4]);
|
||||||
TileTypeBitMask types, nottypes;
|
TileTypeBitMask types, nottypes;
|
||||||
int maxwidth;
|
int maxwidth;
|
||||||
static char *drcRectOpt[4] = {"any", "even", "odd", 0};
|
static char *drcRectOpt[4] = {"any", "even", "odd", 0};
|
||||||
|
|
@ -3449,6 +3506,9 @@ drcTechFinalStyle(style)
|
||||||
DRCCookie **dpp, **dp2back;
|
DRCCookie **dpp, **dp2back;
|
||||||
TileType i, j;
|
TileType i, j;
|
||||||
|
|
||||||
|
/* Done with DRCWhyErrorTable */
|
||||||
|
HashKill(&DRCWhyErrorTable);
|
||||||
|
|
||||||
/* If the scale factor is not 1, then divide all distances by */
|
/* If the scale factor is not 1, then divide all distances by */
|
||||||
/* the scale factor, take the ceiling, and save the (negative) */
|
/* the scale factor, take the ceiling, and save the (negative) */
|
||||||
/* remainder. */
|
/* remainder. */
|
||||||
|
|
@ -3570,7 +3630,6 @@ drcTechFinalStyle(style)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Don't free the shared drcc_why string here! */
|
|
||||||
freeMagic((char *)dptest);
|
freeMagic((char *)dptest);
|
||||||
drcRulesOptimized++;
|
drcRulesOptimized++;
|
||||||
}
|
}
|
||||||
|
|
@ -3665,7 +3724,8 @@ drcTechFinalStyle(style)
|
||||||
|
|
||||||
/* TxPrintf("For edge %s-%s, \"%s\" covers \"%s\"\n",
|
/* TxPrintf("For edge %s-%s, \"%s\" covers \"%s\"\n",
|
||||||
DBTypeShortName(i), DBTypeShortName(j),
|
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]);
|
dp2back = &(style->DRCRulesTbl[i][j]);
|
||||||
while (*dp2back != dp)
|
while (*dp2back != dp)
|
||||||
|
|
@ -3687,7 +3747,6 @@ drcTechFinalStyle(style)
|
||||||
else
|
else
|
||||||
*dp2back = dp->drcc_next;
|
*dp2back = dp->drcc_next;
|
||||||
|
|
||||||
/* Don't free the shared drcc_why string here! */
|
|
||||||
freeMagic((char *) dp);
|
freeMagic((char *) dp);
|
||||||
drcRulesOptimized += 1;
|
drcRulesOptimized += 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
35
drc/drc.h
35
drc/drc.h
|
|
@ -39,10 +39,15 @@ typedef struct drccookie
|
||||||
int drcc_edgeplane; /* Plane of edge */
|
int drcc_edgeplane; /* Plane of edge */
|
||||||
int drcc_plane; /* Index of plane on which to check
|
int drcc_plane; /* Index of plane on which to check
|
||||||
* legal types. */
|
* legal types. */
|
||||||
char *drcc_why; /* Explanation of error found */
|
int drcc_tag; /* Tag to explanation of error found */
|
||||||
struct drccookie *drcc_next;
|
struct drccookie *drcc_next;
|
||||||
} DRCCookie;
|
} 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, */
|
/* *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. */
|
/* and therefore may have twice the bit length of a normal rule distance. */
|
||||||
|
|
||||||
|
|
@ -129,9 +134,9 @@ typedef struct drcpendingcookie
|
||||||
|
|
||||||
typedef struct drccountlist
|
typedef struct drccountlist
|
||||||
{
|
{
|
||||||
CellDef *dcl_def;
|
CellDef *dcl_def;
|
||||||
int dcl_count;
|
int dcl_count;
|
||||||
struct drccountlist *dcl_next;
|
struct drccountlist *dcl_next;
|
||||||
} DRCCountList;
|
} DRCCountList;
|
||||||
|
|
||||||
/* Structure used to keep information about the current DRC style */
|
/* Structure used to keep information about the current DRC style */
|
||||||
|
|
@ -142,22 +147,6 @@ typedef struct drckeep
|
||||||
char *ds_name;
|
char *ds_name;
|
||||||
} DRCKeep;
|
} 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
|
* Structure defining a DRC style
|
||||||
*/
|
*/
|
||||||
|
|
@ -173,7 +162,8 @@ typedef struct drcstyle
|
||||||
int DRCTechHalo; /* largest action distance of design rules */
|
int DRCTechHalo; /* largest action distance of design rules */
|
||||||
int DRCStepSize; /* chunk size for decomposing large areas */
|
int DRCStepSize; /* chunk size for decomposing large areas */
|
||||||
char DRCFlags; /* Option flags */
|
char DRCFlags; /* Option flags */
|
||||||
drcWhyList *DRCWhyList;
|
char **DRCWhyList; /* Indexed list of "why" text strings */
|
||||||
|
int DRCWhySize; /* Length of DRCWhyList */
|
||||||
PaintResultType DRCPaintTable[NP][NT][NT];
|
PaintResultType DRCPaintTable[NP][NT][NT];
|
||||||
} DRCStyle;
|
} DRCStyle;
|
||||||
|
|
||||||
|
|
@ -239,6 +229,9 @@ extern void drcPrintError();
|
||||||
extern int drcIncludeArea();
|
extern int drcIncludeArea();
|
||||||
extern int drcExactOverlapTile();
|
extern int drcExactOverlapTile();
|
||||||
extern void drcInitRulesTbl();
|
extern void drcInitRulesTbl();
|
||||||
|
extern void drcAssign();
|
||||||
|
extern void drcCifAssign();
|
||||||
|
extern int drcWhyCreate();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exported procedures
|
* Exported procedures
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,12 @@ exttosim${SHDLIB_EXT}: simwrap.o ${MAGICDIR}/extflat/libextflat.o
|
||||||
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} simwrap.o \
|
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} simwrap.o \
|
||||||
${MAGICDIR}/extflat/libextflat.o ${LD_SHARED} -lc ${LIBS}
|
${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}
|
$(DESTDIR)${INSTALL_TCLDIR}/exttosim${SHDLIB_EXT}: exttosim${SHDLIB_EXT}
|
||||||
${RM} $(DESTDIR)${TCLDIR}/exttosim${SHDLIB_EXT}
|
${RM} $(DESTDIR)${INSTALL_TCLDIR}/exttosim${SHDLIB_EXT}
|
||||||
${CP} exttosim${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/exttosim${SHDLIB_EXT}
|
${CP} exttosim${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/exttosim${SHDLIB_EXT}
|
||||||
|
|
||||||
include ${MAGICDIR}/rules.mak
|
include ${MAGICDIR}/rules.mak
|
||||||
|
|
|
||||||
|
|
@ -1078,7 +1078,7 @@ simdevVisit(dev, hierName, scale, trans)
|
||||||
{
|
{
|
||||||
putc(' ', esSimF);
|
putc(' ', esSimF);
|
||||||
simdevSubstrate(hierName, subnode->efnode_name->efnn_hier,
|
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);
|
GeoTransRect(trans, &dev->dev_rect, &r);
|
||||||
|
|
@ -1196,7 +1196,8 @@ int
|
||||||
simdevSubstrate( prefix, suffix, type, scale, doAP, outf)
|
simdevSubstrate( prefix, suffix, type, scale, doAP, outf)
|
||||||
HierName *prefix;
|
HierName *prefix;
|
||||||
HierName *suffix;
|
HierName *suffix;
|
||||||
int type, scale;
|
int type;
|
||||||
|
float scale;
|
||||||
bool doAP;
|
bool doAP;
|
||||||
FILE *outf;
|
FILE *outf;
|
||||||
{
|
{
|
||||||
|
|
@ -1264,7 +1265,8 @@ FILE *outf;
|
||||||
|
|
||||||
bool simnAP(node, resClass, scale, outf)
|
bool simnAP(node, resClass, scale, outf)
|
||||||
EFNode *node;
|
EFNode *node;
|
||||||
int resClass, scale;
|
int resClass;
|
||||||
|
float scale;
|
||||||
FILE *outf;
|
FILE *outf;
|
||||||
{
|
{
|
||||||
int a, p;
|
int a, p;
|
||||||
|
|
@ -1277,8 +1279,8 @@ FILE *outf;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
markVisited((nodeClient *)node->efnode_client, resClass);
|
markVisited((nodeClient *)node->efnode_client, resClass);
|
||||||
a = node->efnode_pa[resClass].pa_area*scale*scale;
|
a = (int)(node->efnode_pa[resClass].pa_area*scale*scale);
|
||||||
p = node->efnode_pa[resClass].pa_perim*scale;
|
p = (int)(node->efnode_pa[resClass].pa_perim*scale);
|
||||||
if ( a < 0 ) a = 0;
|
if ( a < 0 ) a = 0;
|
||||||
if ( p < 0 ) p = 0;
|
if ( p < 0 ) p = 0;
|
||||||
fprintf(outf,"A_%d,P_%d", a, p);
|
fprintf(outf,"A_%d,P_%d", a, p);
|
||||||
|
|
@ -1288,7 +1290,8 @@ FILE *outf;
|
||||||
bool simnAPHier(dterm, hierName, resClass, scale, outf)
|
bool simnAPHier(dterm, hierName, resClass, scale, outf)
|
||||||
DevTerm *dterm;
|
DevTerm *dterm;
|
||||||
HierName *hierName;
|
HierName *hierName;
|
||||||
int resClass, scale;
|
int resClass;
|
||||||
|
float scale;
|
||||||
FILE *outf;
|
FILE *outf;
|
||||||
{
|
{
|
||||||
EFNode *node = dterm->dterm_node;
|
EFNode *node = dterm->dterm_node;
|
||||||
|
|
@ -1308,8 +1311,8 @@ bool simnAPHier(dterm, hierName, resClass, scale, outf)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
markVisited((nodeClientHier *)node->efnode_client, resClass);
|
markVisited((nodeClientHier *)node->efnode_client, resClass);
|
||||||
a = node->efnode_pa[resClass].pa_area*scale*scale;
|
a = (int)(node->efnode_pa[resClass].pa_area*scale*scale);
|
||||||
p = node->efnode_pa[resClass].pa_perim*scale;
|
p = (int)(node->efnode_pa[resClass].pa_perim*scale);
|
||||||
if ( a < 0 ) a = 0;
|
if ( a < 0 ) a = 0;
|
||||||
if ( p < 0 ) p = 0;
|
if ( p < 0 ) p = 0;
|
||||||
fprintf(outf,"A_%d,P_%d", a, p);
|
fprintf(outf,"A_%d,P_%d", a, p);
|
||||||
|
|
|
||||||
|
|
@ -29,16 +29,16 @@ exttospice${SHDLIB_EXT}: spicewrap.o spicehier.o ${MAGICDIR}/extflat/libextflat.
|
||||||
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} spicewrap.o spicehier.o \
|
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} spicewrap.o spicehier.o \
|
||||||
${MAGICDIR}/extflat/libextflat.o ${LD_SHARED} -lc ${LIBS}
|
${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}
|
$(DESTDIR)${INSTALL_TCLDIR}/exttospice${SHDLIB_EXT}: exttospice${SHDLIB_EXT}
|
||||||
${RM} $(DESTDIR)${TCLDIR}/exttospice${SHDLIB_EXT}
|
${RM} $(DESTDIR)${INSTALL_TCLDIR}/exttospice${SHDLIB_EXT}
|
||||||
${CP} exttospice${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/exttospice${SHDLIB_EXT}
|
${CP} exttospice${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/exttospice${SHDLIB_EXT}
|
||||||
|
|
||||||
$(DESTDIR)${BINDIR}/spice2sim: spice2sim
|
$(DESTDIR)${INSTALL_BINDIR}/spice2sim: spice2sim
|
||||||
${RM} $(DESTDIR)${BINDIR}/spice2sim
|
${RM} $(DESTDIR)${INSTALL_BINDIR}/spice2sim
|
||||||
${CP} spice2sim $(DESTDIR)${BINDIR}/spice2sim
|
${CP} spice2sim $(DESTDIR)${INSTALL_BINDIR}/spice2sim
|
||||||
|
|
||||||
include ${MAGICDIR}/rules.mak
|
include ${MAGICDIR}/rules.mak
|
||||||
|
|
|
||||||
|
|
@ -1159,13 +1159,11 @@ spcresistHierVisit(hc, hierName1, hierName2, res)
|
||||||
HierContext *hc;
|
HierContext *hc;
|
||||||
HierName *hierName1;
|
HierName *hierName1;
|
||||||
HierName *hierName2;
|
HierName *hierName2;
|
||||||
int res;
|
float res;
|
||||||
{
|
{
|
||||||
res = (res + 500) / 1000;
|
fprintf(esSpiceF, "R%d %s %s %g\n", esResNum++,
|
||||||
|
|
||||||
fprintf(esSpiceF, "R%d %s %s %d\n", esResNum++,
|
|
||||||
nodeSpiceHierName(hc, hierName1),
|
nodeSpiceHierName(hc, hierName1),
|
||||||
nodeSpiceHierName(hc, hierName2), res);
|
nodeSpiceHierName(hc, hierName2), res / 1000.);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1572,27 +1570,39 @@ esMakePorts(hc, cdata)
|
||||||
|
|
||||||
while (tptr != NULL)
|
while (tptr != NULL)
|
||||||
{
|
{
|
||||||
/* Ignore array information for the purpose of tracing */
|
int idum[6];
|
||||||
/* the cell definition hierarchy. */
|
bool is_array;
|
||||||
|
|
||||||
aptr = strchr(portname, '[');
|
/* Ignore array information for the purpose of tracing */
|
||||||
if ((aptr == NULL) || (aptr > tptr))
|
/* the cell definition hierarchy. If a cell use name */
|
||||||
*tptr = '\0';
|
/* contains a bracket, check first if the complete name */
|
||||||
else
|
/* matches a use. If not, then check if the part */
|
||||||
*aptr = '\0';
|
/* 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
|
// Find the cell for the instance
|
||||||
portdef = NULL;
|
portdef = NULL;
|
||||||
he = HashFind(&updef->def_uses, portname);
|
he = HashLookOnly(&updef->def_uses, portname);
|
||||||
if (he != NULL)
|
if (he != NULL)
|
||||||
{
|
{
|
||||||
use = (Use *)HashGetValue(he);
|
use = (Use *)HashGetValue(he);
|
||||||
portdef = use->use_def;
|
portdef = use->use_def;
|
||||||
}
|
}
|
||||||
if ((aptr == NULL) || (aptr > tptr))
|
if (is_array)
|
||||||
*tptr = '/';
|
|
||||||
else
|
|
||||||
*aptr = '[';
|
*aptr = '[';
|
||||||
|
*tptr = '/';
|
||||||
portname = tptr + 1;
|
portname = tptr + 1;
|
||||||
|
|
||||||
// Find the net of portname in the subcell and
|
// 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_node->efnode_flags |= EF_PORT;
|
||||||
nn->efnn_port = -1; // Will be sorted later
|
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;
|
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
|
// In particular, this keeps parasitics out of the netlist for
|
||||||
// LVS purposes if "cthresh" is set to "infinite".
|
// 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;
|
portname = name;
|
||||||
updef = def;
|
updef = def;
|
||||||
|
|
||||||
while (tptr != NULL)
|
while (tptr != NULL)
|
||||||
{
|
{
|
||||||
|
int idum[6];
|
||||||
|
bool is_array;
|
||||||
|
|
||||||
/* Ignore array information for the purpose of tracing */
|
/* Ignore array information for the purpose of tracing */
|
||||||
/* the cell definition hierarchy. */
|
/* the cell definition hierarchy. */
|
||||||
|
|
||||||
aptr = strchr(portname, '[');
|
aptr = strchr(portname, '[');
|
||||||
if ((aptr == NULL) || (aptr > tptr))
|
if (aptr && (aptr < tptr) &&
|
||||||
*tptr = '\0';
|
(sscanf(aptr, "[%d:%d:%d][%d:%d:%d]",
|
||||||
else
|
&idum[0], &idum[1], &idum[2],
|
||||||
|
&idum[3], &idum[4], &idum[5]) == 6))
|
||||||
|
{
|
||||||
*aptr = '\0';
|
*aptr = '\0';
|
||||||
|
is_array = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*tptr = '\0';
|
||||||
|
is_array = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
// Find the cell for the instance
|
// Find the cell for the instance
|
||||||
portdef = NULL;
|
portdef = NULL;
|
||||||
he = HashFind(&updef->def_uses, portname);
|
he = HashLookOnly(&updef->def_uses, portname);
|
||||||
if (he != NULL)
|
if (he != NULL)
|
||||||
{
|
{
|
||||||
use = (Use *)HashGetValue(he);
|
use = (Use *)HashGetValue(he);
|
||||||
portdef = use->use_def;
|
portdef = use->use_def;
|
||||||
}
|
}
|
||||||
if ((aptr == NULL) || (aptr > tptr))
|
if (is_array)
|
||||||
*tptr = '/';
|
|
||||||
else
|
|
||||||
*aptr = '[';
|
*aptr = '[';
|
||||||
|
else
|
||||||
|
*tptr = '/';
|
||||||
portname = tptr + 1;
|
portname = tptr + 1;
|
||||||
|
|
||||||
// Find the net of portname in the subcell and
|
// Find the net of portname in the subcell and
|
||||||
|
|
@ -1747,7 +1770,8 @@ esHierVisit(hc, cdata)
|
||||||
|
|
||||||
if (def != topdef)
|
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)
|
if (locDoSubckt == AUTO)
|
||||||
{
|
{
|
||||||
|
|
@ -1859,6 +1883,9 @@ esHierVisit(hc, cdata)
|
||||||
EFHierVisitNodes(hcf, spcnodeHierVisit, (ClientData) NULL);
|
EFHierVisitNodes(hcf, spcnodeHierVisit, (ClientData) NULL);
|
||||||
freeMagic(resstr);
|
freeMagic(resstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reset device merge index for next cell */
|
||||||
|
if (esMergeDevsA || esMergeDevsC) esFMIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((def != topdef) || (def->def_flags & DEF_SUBCIRCUIT) || (locDoSubckt == TRUE))
|
if ((def != topdef) || (def->def_flags & DEF_SUBCIRCUIT) || (locDoSubckt == TRUE))
|
||||||
|
|
|
||||||
|
|
@ -140,9 +140,16 @@ esFormatSubs(outf, suf)
|
||||||
if ((EFTrimFlags & EF_TRIMGLOB ) && suf[l] == '!' ||
|
if ((EFTrimFlags & EF_TRIMGLOB ) && suf[l] == '!' ||
|
||||||
(EFTrimFlags & EF_TRIMLOCAL) && suf[l] == '#')
|
(EFTrimFlags & EF_TRIMLOCAL) && suf[l] == '#')
|
||||||
suf[l] = '\0' ;
|
suf[l] = '\0' ;
|
||||||
if (EFTrimFlags & EF_CONVERTCOMMAS)
|
if (EFTrimFlags & EF_CONVERTCOMMA)
|
||||||
while ((specchar = strchr(suf, ',')) != NULL)
|
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)
|
if (EFTrimFlags & EF_CONVERTEQUAL)
|
||||||
while ((specchar = strchr(suf, '=')) != NULL)
|
while ((specchar = strchr(suf, '=')) != NULL)
|
||||||
*specchar = ':';
|
*specchar = ':';
|
||||||
|
|
@ -257,7 +264,8 @@ CmdExtToSpice(w, cmd)
|
||||||
"extresist [on|off] incorporate information from extresist",
|
"extresist [on|off] incorporate information from extresist",
|
||||||
"resistor tee [on|off] model resistor capacitance as a T-network",
|
"resistor tee [on|off] model resistor capacitance as a T-network",
|
||||||
"scale [on|off] use .option card for scaling",
|
"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",
|
"hierarchy [on|off] output hierarchical spice for LVS",
|
||||||
"blackbox [on|off] output abstract views as black-box entries",
|
"blackbox [on|off] output abstract views as black-box entries",
|
||||||
"renumber [on|off] on = number instances X1, X2, etc.\n"
|
"renumber [on|off] on = number instances X1, X2, etc.\n"
|
||||||
|
|
@ -607,7 +615,7 @@ CmdExtToSpice(w, cmd)
|
||||||
case EXTTOSPC_DEFAULT:
|
case EXTTOSPC_DEFAULT:
|
||||||
LocCapThreshold = 2;
|
LocCapThreshold = 2;
|
||||||
LocResistThreshold = INFINITE_THRESHOLD;
|
LocResistThreshold = INFINITE_THRESHOLD;
|
||||||
EFTrimFlags = EF_CONVERTCOMMAS | EF_CONVERTEQUAL;
|
EFTrimFlags = EF_CONVERTCOMMA | EF_CONVERTEQUAL;
|
||||||
EFScale = 0.0;
|
EFScale = 0.0;
|
||||||
if (EFArgTech)
|
if (EFArgTech)
|
||||||
{
|
{
|
||||||
|
|
@ -821,7 +829,7 @@ runexttospice:
|
||||||
|
|
||||||
// This forces options TRIMGLOB and CONVERTEQUAL, not sure that's such a
|
// This forces options TRIMGLOB and CONVERTEQUAL, not sure that's such a
|
||||||
// good idea. . .
|
// good idea. . .
|
||||||
EFTrimFlags |= EF_TRIMGLOB | EF_CONVERTEQUAL;
|
EFTrimFlags |= EF_TRIMGLOB | EF_CONVERTEQUAL | EF_CONVERTCOMMA;
|
||||||
if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS;
|
if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS;
|
||||||
if (esFormat == HSPICE)
|
if (esFormat == HSPICE)
|
||||||
EFTrimFlags |= EF_TRIMLOCAL;
|
EFTrimFlags |= EF_TRIMLOCAL;
|
||||||
|
|
@ -1140,6 +1148,17 @@ spcmainArgs(pargc, pargv)
|
||||||
char **argv = *pargv, *cp;
|
char **argv = *pargv, *cp;
|
||||||
int argc = *pargc;
|
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])
|
switch (argv[0][1])
|
||||||
{
|
{
|
||||||
case 'd':
|
case 'd':
|
||||||
|
|
@ -1236,6 +1255,9 @@ spcmainArgs(pargc, pargv)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif /* MAGIC_WRAPPER */
|
#endif /* MAGIC_WRAPPER */
|
||||||
|
case 'h': /* -h or -help, as suggested by "ext2spice help" */
|
||||||
|
TxPrintf(usage_text);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
TxError("Unrecognized flag: %s\n", argv[0]);
|
TxError("Unrecognized flag: %s\n", argv[0]);
|
||||||
goto usage;
|
goto usage;
|
||||||
|
|
@ -1246,16 +1268,7 @@ spcmainArgs(pargc, pargv)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
usage:
|
usage:
|
||||||
TxError("Usage: ext2spice [-B] [-o spicefile] [-M|-m] [-y cap_digits] "
|
TxError(usage_text);
|
||||||
"[-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
|
|
||||||
);
|
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -1359,10 +1372,11 @@ subcktVisit(use, hierName, is_top)
|
||||||
EFNode *snode;
|
EFNode *snode;
|
||||||
Def *def = use->use_def;
|
Def *def = use->use_def;
|
||||||
EFNodeName *nodeName;
|
EFNodeName *nodeName;
|
||||||
int portorder, portmax, imp_max, tchars;
|
int portorder, portmax, portidx, imp_max, tchars;
|
||||||
char stmp[MAX_STR_SIZE];
|
char stmp[MAX_STR_SIZE];
|
||||||
char *instname, *subcktname;
|
char *instname, *subcktname;
|
||||||
DevParam *plist, *pptr;
|
DevParam *plist, *pptr;
|
||||||
|
EFNodeName **nodeList;
|
||||||
|
|
||||||
if (is_top == TRUE) return 0; /* Ignore the top-level cell */
|
if (is_top == TRUE) return 0; /* Ignore the top-level cell */
|
||||||
|
|
||||||
|
|
@ -1379,7 +1393,7 @@ subcktVisit(use, hierName, is_top)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int savflags = EFTrimFlags;
|
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 */
|
/* Use full hierarchical decomposition for name */
|
||||||
/* (not just use->use_id. hierName already has use->use_id at end) */
|
/* (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. */
|
/* Port numbers need not start at zero or be contiguous. */
|
||||||
/* They will be printed in numerical order. */
|
/* They will be printed in numerical order. */
|
||||||
|
|
||||||
portorder = 0;
|
nodeList = (EFNodeName **)mallocMagic((portmax + 1) * sizeof(EFNodeName *));
|
||||||
while (portorder <= portmax)
|
for (portidx = 0; portidx <= portmax; portidx++)
|
||||||
{
|
nodeList[portidx] = (EFNodeName *)NULL;
|
||||||
for (snode = (EFNode *) def->def_firstn.efnode_next;
|
|
||||||
|
for (snode = (EFNode *) def->def_firstn.efnode_next;
|
||||||
snode != &def->def_firstn;
|
snode != &def->def_firstn;
|
||||||
snode = (EFNode *) snode->efnode_next)
|
snode = (EFNode *) snode->efnode_next)
|
||||||
{
|
{
|
||||||
if (!(snode->efnode_flags & EF_PORT)) continue;
|
if (!(snode->efnode_flags & EF_PORT)) continue;
|
||||||
for (nodeName = snode->efnode_name; nodeName != NULL;
|
for (nodeName = snode->efnode_name; nodeName != NULL;
|
||||||
nodeName = nodeName->efnn_next)
|
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;
|
nodeList[portidx] = nodeName;
|
||||||
if (portidx == portorder)
|
}
|
||||||
{
|
else if (EFHNBest(nodeName->efnn_hier, nodeList[portidx]->efnn_hier))
|
||||||
if (tchars > 80)
|
{
|
||||||
{
|
nodeList[portidx] = nodeName;
|
||||||
fprintf(esSpiceF, "\n+");
|
|
||||||
tchars = 1;
|
|
||||||
}
|
|
||||||
tchars += spcdevOutNode(hierName, nodeName->efnn_hier,
|
|
||||||
"subcircuit", esSpiceF);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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 */
|
/* Look for all implicit substrate connections that are */
|
||||||
/* declared as local node names, and put them last. */
|
/* declared as local node names, and put them last. */
|
||||||
|
|
||||||
|
|
@ -1602,7 +1639,7 @@ topVisit(def, doStub)
|
||||||
Def *def;
|
Def *def;
|
||||||
bool doStub;
|
bool doStub;
|
||||||
{
|
{
|
||||||
EFNode *snode;
|
EFNode *snode, *basenode;
|
||||||
EFNodeName *sname, *nodeName;
|
EFNodeName *sname, *nodeName;
|
||||||
HashSearch hs;
|
HashSearch hs;
|
||||||
HashEntry *he;
|
HashEntry *he;
|
||||||
|
|
@ -1655,7 +1692,9 @@ topVisit(def, doStub)
|
||||||
snode = sname->efnn_node;
|
snode = sname->efnn_node;
|
||||||
|
|
||||||
if (snode->efnode_flags & EF_PORT)
|
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)
|
if (tchars > 80)
|
||||||
{
|
{
|
||||||
|
|
@ -1663,11 +1702,12 @@ topVisit(def, doStub)
|
||||||
fprintf(esSpiceF, "\n+");
|
fprintf(esSpiceF, "\n+");
|
||||||
tchars = 1;
|
tchars = 1;
|
||||||
}
|
}
|
||||||
pname = nodeSpiceName(snode->efnode_name->efnn_hier);
|
|
||||||
fprintf(esSpiceF, " %s", pname);
|
fprintf(esSpiceF, " %s", pname);
|
||||||
tchars += strlen(pname) + 1;
|
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
|
else
|
||||||
|
|
@ -1681,6 +1721,7 @@ topVisit(def, doStub)
|
||||||
HashStartSearch(&hs);
|
HashStartSearch(&hs);
|
||||||
while (he = HashNext(&def->def_nodes, &hs))
|
while (he = HashNext(&def->def_nodes, &hs))
|
||||||
{
|
{
|
||||||
|
char stmp[MAX_STR_SIZE];
|
||||||
int portidx;
|
int portidx;
|
||||||
EFNodeName *unnumbered;
|
EFNodeName *unnumbered;
|
||||||
|
|
||||||
|
|
@ -1701,7 +1742,17 @@ topVisit(def, doStub)
|
||||||
fprintf(esSpiceF, "\n+");
|
fprintf(esSpiceF, "\n+");
|
||||||
tchars = 1;
|
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);
|
fprintf(esSpiceF, " %s", pname);
|
||||||
tchars += strlen(pname) + 1;
|
tchars += strlen(pname) + 1;
|
||||||
break;
|
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 */
|
/* Canonical name */
|
||||||
nn = (EFNodeName *) HashGetValue(he);
|
nn = (EFNodeName *) HashGetValue(he);
|
||||||
if (outf)
|
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 */
|
/* Mark node as visited */
|
||||||
if ((nodeClient *)nn->efnn_node->efnode_client == (ClientData)NULL)
|
if ((nodeClient *)nn->efnn_node->efnode_client == (ClientData)NULL)
|
||||||
initNodeClientHier(nn->efnn_node);
|
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;
|
return nn->efnn_node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2769,7 +2873,14 @@ int spcnAP(node, resClass, scale, asterm, psterm, m, outf, w)
|
||||||
|
|
||||||
if (!esDistrJunct || w == -1) goto oldFmt;
|
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 (esScale < 0)
|
||||||
{
|
{
|
||||||
if (asterm)
|
if (asterm)
|
||||||
|
|
@ -2917,10 +3028,13 @@ spcdevOutNode(prefix, suffix, name, outf)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
nn = (EFNodeName *) HashGetValue(he);
|
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);
|
fprintf(outf, " %s", nname);
|
||||||
|
|
||||||
/* Mark node as visited */
|
/* 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));
|
return (1 + strlen(nname));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2960,8 +3074,8 @@ spccapVisit(hierName1, hierName2, cap)
|
||||||
if (cap <= EFCapThreshold)
|
if (cap <= EFCapThreshold)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fprintf(esSpiceF, esSpiceCapFormat ,esCapNum++,nodeSpiceName(hierName1),
|
fprintf(esSpiceF, esSpiceCapFormat ,esCapNum++,nodeSpiceName(hierName1, NULL),
|
||||||
nodeSpiceName(hierName2), cap);
|
nodeSpiceName(hierName2, NULL), cap);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2996,8 +3110,8 @@ spcresistVisit(hierName1, hierName2, res)
|
||||||
HierName *hierName2;
|
HierName *hierName2;
|
||||||
float res;
|
float res;
|
||||||
{
|
{
|
||||||
fprintf(esSpiceF, "R%d %s %s %g\n", esResNum++, nodeSpiceName(hierName1),
|
fprintf(esSpiceF, "R%d %s %s %g\n", esResNum++, nodeSpiceName(hierName1, NULL),
|
||||||
nodeSpiceName(hierName2), res / 1000.);
|
nodeSpiceName(hierName2, NULL), res / 1000.);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -3032,7 +3146,7 @@ spcsubVisit(node, res, cap, resstr)
|
||||||
if (node->efnode_flags & EF_SUBS_NODE)
|
if (node->efnode_flags & EF_SUBS_NODE)
|
||||||
{
|
{
|
||||||
hierName = (HierName *) node->efnode_name->efnn_hier;
|
hierName = (HierName *) node->efnode_name->efnn_hier;
|
||||||
nsn = nodeSpiceName(hierName);
|
nsn = nodeSpiceName(hierName, NULL);
|
||||||
*resstr = StrDup((char **)NULL, nsn);
|
*resstr = StrDup((char **)NULL, nsn);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
@ -3082,7 +3196,7 @@ spcnodeVisit(node, res, cap)
|
||||||
if (!isConnected && node->efnode_flags & EF_PORT) isConnected = TRUE;
|
if (!isConnected && node->efnode_flags & EF_PORT) isConnected = TRUE;
|
||||||
|
|
||||||
hierName = (HierName *) node->efnode_name->efnn_hier;
|
hierName = (HierName *) node->efnode_name->efnn_hier;
|
||||||
nsn = nodeSpiceName(hierName);
|
nsn = nodeSpiceName(hierName, NULL);
|
||||||
|
|
||||||
if (esFormat == SPICE2 || esFormat == HSPICE && strncmp(nsn, "z@", 2)==0 ) {
|
if (esFormat == SPICE2 || esFormat == HSPICE && strncmp(nsn, "z@", 2)==0 ) {
|
||||||
static char ntmp[MAX_STR_SIZE];
|
static char ntmp[MAX_STR_SIZE];
|
||||||
|
|
@ -3127,7 +3241,7 @@ nodeVisitDebug(node, res, cap)
|
||||||
EFAttr *ap;
|
EFAttr *ap;
|
||||||
|
|
||||||
hierName = (HierName *) node->efnode_name->efnn_hier;
|
hierName = (HierName *) node->efnode_name->efnn_hier;
|
||||||
nsn = nodeSpiceName(hierName);
|
nsn = nodeSpiceName(hierName, NULL);
|
||||||
TxError("** %s (%x)\n", nsn, node);
|
TxError("** %s (%x)\n", nsn, node);
|
||||||
|
|
||||||
printf("\t client.name=%s, client.m_w=%p\n",
|
printf("\t client.name=%s, client.m_w=%p\n",
|
||||||
|
|
@ -3150,23 +3264,27 @@ nodeVisitDebug(node, res, cap)
|
||||||
*
|
*
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* Allocates nodeClients for the node.
|
* Allocates nodeClients for the node.
|
||||||
|
* Returns the node in the "rnode" pointer, if non-NULL.
|
||||||
*
|
*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
static char esTempName[MAX_STR_SIZE];
|
static char esTempName[MAX_STR_SIZE];
|
||||||
|
|
||||||
char *nodeSpiceName(hname)
|
char *nodeSpiceName(hname, rnode)
|
||||||
HierName *hname;
|
HierName *hname;
|
||||||
|
EFNode **rnode;
|
||||||
{
|
{
|
||||||
EFNodeName *nn;
|
EFNodeName *nn;
|
||||||
HashEntry *he;
|
HashEntry *he;
|
||||||
EFNode *node;
|
EFNode *node;
|
||||||
|
|
||||||
|
if (rnode) *rnode = (EFNode *)NULL;
|
||||||
he = EFHNLook(hname, (char *) NULL, "nodeName");
|
he = EFHNLook(hname, (char *) NULL, "nodeName");
|
||||||
if ( he == NULL )
|
if ( he == NULL )
|
||||||
return "errGnd!";
|
return "errGnd!";
|
||||||
nn = (EFNodeName *) HashGetValue(he);
|
nn = (EFNodeName *) HashGetValue(he);
|
||||||
node = nn->efnn_node;
|
node = nn->efnn_node;
|
||||||
|
if (rnode) *rnode = node;
|
||||||
|
|
||||||
if ( (nodeClient *) (node->efnode_client) == NULL ) {
|
if ( (nodeClient *) (node->efnode_client) == NULL ) {
|
||||||
initNodeClient(node);
|
initNodeClient(node);
|
||||||
|
|
@ -3215,7 +3333,7 @@ EFHNSprintf(str, hierName)
|
||||||
char *str;
|
char *str;
|
||||||
HierName *hierName;
|
HierName *hierName;
|
||||||
{
|
{
|
||||||
bool trimGlob, trimLocal, convertComma, convertEqual;
|
bool trimGlob, trimLocal, convertComma, convertEqual, convertBrackets;
|
||||||
char *s, *cp, c;
|
char *s, *cp, c;
|
||||||
char *efHNSprintfPrefix(HierName *, char *);
|
char *efHNSprintfPrefix(HierName *, char *);
|
||||||
|
|
||||||
|
|
@ -3226,8 +3344,9 @@ EFHNSprintf(str, hierName)
|
||||||
cp = hierName->hn_name;
|
cp = hierName->hn_name;
|
||||||
trimGlob = (EFTrimFlags & EF_TRIMGLOB);
|
trimGlob = (EFTrimFlags & EF_TRIMGLOB);
|
||||||
trimLocal = (EFTrimFlags & EF_TRIMLOCAL);
|
trimLocal = (EFTrimFlags & EF_TRIMLOCAL);
|
||||||
convertComma = (EFTrimFlags & EF_CONVERTCOMMAS);
|
convertComma = (EFTrimFlags & EF_CONVERTCOMMA);
|
||||||
convertEqual = (EFTrimFlags & EF_CONVERTEQUAL);
|
convertEqual = (EFTrimFlags & EF_CONVERTEQUAL);
|
||||||
|
convertBrackets = (EFTrimFlags & EF_CONVERTBRACKETS);
|
||||||
while (c = *cp++)
|
while (c = *cp++)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
|
|
@ -3235,7 +3354,9 @@ EFHNSprintf(str, hierName)
|
||||||
case '!': if (!trimGlob) *str++ = c; break;
|
case '!': if (!trimGlob) *str++ = c; break;
|
||||||
case '.': *str++ = (esFormat == HSPICE)?'@':'.'; break;
|
case '.': *str++ = (esFormat == HSPICE)?'@':'.'; break;
|
||||||
case '=': if (convertEqual) *str++ = ':'; 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
|
case '#': if (trimLocal) break; // else fall through
|
||||||
default: *str++ = c; break;
|
default: *str++ = c; break;
|
||||||
}
|
}
|
||||||
|
|
@ -3252,6 +3373,8 @@ char *efHNSprintfPrefix(hierName, str)
|
||||||
{
|
{
|
||||||
char *cp, c;
|
char *cp, c;
|
||||||
bool convertEqual = (EFTrimFlags & EF_CONVERTEQUAL) ? TRUE : FALSE;
|
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)
|
if (hierName->hn_parent)
|
||||||
str = efHNSprintfPrefix(hierName->hn_parent, str);
|
str = efHNSprintfPrefix(hierName->hn_parent, str);
|
||||||
|
|
@ -3260,6 +3383,13 @@ char *efHNSprintfPrefix(hierName, str)
|
||||||
while (1) {
|
while (1) {
|
||||||
if (convertEqual && (*cp == '='))
|
if (convertEqual && (*cp == '='))
|
||||||
*str = ':';
|
*str = ':';
|
||||||
|
else if (convertBrackets && ((*cp == '[') || (*cp == ']')))
|
||||||
|
*str = '_';
|
||||||
|
else if (*cp == ',')
|
||||||
|
{
|
||||||
|
if (convertComma) *str = '|';
|
||||||
|
else str--;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
*str = *cp;
|
*str = *cp;
|
||||||
if (!(*str)) break;
|
if (!(*str)) break;
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,11 @@ extern char *nodeSpiceHierName();
|
||||||
extern devMerge *mkDevMerge();
|
extern devMerge *mkDevMerge();
|
||||||
extern bool extHierSDAttr();
|
extern bool extHierSDAttr();
|
||||||
|
|
||||||
|
extern bool devIsKilled();
|
||||||
|
extern float getCurDevMult();
|
||||||
|
extern void addDevMult();
|
||||||
|
extern void setDevMult();
|
||||||
|
|
||||||
/* Options specific to ext2spice */
|
/* Options specific to ext2spice */
|
||||||
extern bool esDoExtResis;
|
extern bool esDoExtResis;
|
||||||
extern bool esDoPorts;
|
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
|
* The merging of devs is based on the fact that spcdevVisit
|
||||||
* visits the devs in the same order all the time so the
|
* visits the devs in the same order all the time so the
|
||||||
* value of esFMult[i] keeps the multiplier for the ith dev
|
* value of esFMult[i] keeps the multiplier for the ith dev
|
||||||
|
|
@ -174,31 +179,8 @@ typedef struct {
|
||||||
*/
|
*/
|
||||||
#define DEV_KILLED ((float) -1.0)
|
#define DEV_KILLED ((float) -1.0)
|
||||||
#define FMULT_SIZE (1<<10)
|
#define FMULT_SIZE (1<<10)
|
||||||
|
|
||||||
#define devIsKilled(n) ( esFMult[(n)] <=(float)0.0 )
|
|
||||||
|
|
||||||
#define DEV_KILLED ((float) -1.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
|
#ifdef MAGIC_WRAPPER
|
||||||
#define atoCap(s) ((EFCapValue)atof(s))
|
#define atoCap(s) ((EFCapValue)atof(s))
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -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/bplane.h ../bplane/bpOpaque.h ../utils/ihash.h \
|
||||||
../bplane/bpEnum.h ../utils/geofast.h ../bplane/bplaneInt.h \
|
../bplane/bpEnum.h ../utils/geofast.h ../bplane/bplaneInt.h \
|
||||||
../extflat/extflat.h ../extflat/EFint.h ../extract/extract.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 \
|
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 \
|
../utils/hash.h ../utils/malloc.h ../utils/utils.h ../extflat/extflat.h \
|
||||||
../extflat/EFint.h
|
../extflat/EFint.h
|
||||||
EFvisit.o: EFvisit.c ../utils/magic.h ../utils/geometry.h \
|
EFvisit.o: EFvisit.c ../utils/magic.h ../utils/geometry.h \
|
||||||
../utils/geofast.h ../utils/hash.h ../utils/malloc.h ../utils/utils.h \
|
../utils/geofast.h ../utils/hash.h ../utils/malloc.h ../utils/utils.h \
|
||||||
../extflat/extflat.h ../extflat/EFint.h ../extract/extract.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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -160,6 +160,15 @@ EFArgs(argc, argv, err_result, argsProc, cdata)
|
||||||
HierName *hierName;
|
HierName *hierName;
|
||||||
FILE *f;
|
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;
|
if (err_result != NULL) *err_result = FALSE;
|
||||||
|
|
||||||
/* Hash table of nodes we're going to watch if -N given */
|
/* 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;
|
goto usage;
|
||||||
if (strchr(cp, '!')) EFTrimFlags |= EF_TRIMGLOB;
|
if (strchr(cp, '!')) EFTrimFlags |= EF_TRIMGLOB;
|
||||||
if (strchr(cp, '#')) EFTrimFlags |= EF_TRIMLOCAL;
|
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_CONVERTEQUAL;
|
||||||
|
if (strchr(cp, '[')) EFTrimFlags |= EF_CONVERTBRACKETS;
|
||||||
|
if (strchr(cp, ']')) EFTrimFlags |= EF_CONVERTBRACKETS;
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
EFCapThreshold = (EFCapValue)INFINITE_THRESHOLD_F;
|
EFCapThreshold = (EFCapValue)INFINITE_THRESHOLD_F;
|
||||||
|
|
@ -268,6 +279,11 @@ EFArgs(argc, argv, err_result, argsProc, cdata)
|
||||||
case 'z':
|
case 'z':
|
||||||
efHNStats = TRUE;
|
efHNStats = TRUE;
|
||||||
break;
|
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 ***/
|
/*** Try a caller-supplied argument processing function ***/
|
||||||
default:
|
default:
|
||||||
|
|
@ -310,19 +326,15 @@ EFArgs(argc, argv, err_result, argsProc, cdata)
|
||||||
realIn[cp - inname] = '\0';
|
realIn[cp - inname] = '\0';
|
||||||
inname = realIn;
|
inname = realIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
return inname;
|
return inname;
|
||||||
|
|
||||||
usage:
|
usage:
|
||||||
TxError("Standard arguments: [-R] [-C] [-r rthresh] [-c cthresh] [-v]\n"
|
TxError(usage_text);
|
||||||
"[-p searchpath] [-s sym=value] [-S symfile] [-t trimchars]\n"
|
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
"[rootfile]\n");
|
|
||||||
if (err_result != NULL) *err_result = TRUE;
|
if (err_result != NULL) *err_result = TRUE;
|
||||||
return NULL;
|
return NULL;
|
||||||
#else
|
#else
|
||||||
"[-T techname] rootfile\n");
|
|
||||||
exit (1);
|
exit (1);
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,8 @@ void efNodeMerge();
|
||||||
bool efConnBuildName();
|
bool efConnBuildName();
|
||||||
bool efConnInitSubs();
|
bool efConnInitSubs();
|
||||||
|
|
||||||
|
extern float locScale;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
|
|
@ -172,15 +174,15 @@ efBuildNode(def, isSubsnode, nodeName, nodeCap, x, y, layerName, av, ac)
|
||||||
HashSetValue(he, (char *) newname);
|
HashSetValue(he, (char *) newname);
|
||||||
|
|
||||||
/* New node itself */
|
/* New node itself */
|
||||||
size = sizeof (EFNode) + (efNumResistClasses - 1) * sizeof (PerimArea);
|
size = sizeof (EFNode) + (efNumResistClasses - 1) * sizeof (EFPerimArea);
|
||||||
newnode = (EFNode *) mallocMagic((unsigned)(size));
|
newnode = (EFNode *) mallocMagic((unsigned)(size));
|
||||||
newnode->efnode_flags = (isSubsnode == TRUE) ? EF_SUBS_NODE : 0;
|
newnode->efnode_flags = (isSubsnode == TRUE) ? EF_SUBS_NODE : 0;
|
||||||
newnode->efnode_cap = nodeCap;
|
newnode->efnode_cap = nodeCap;
|
||||||
newnode->efnode_attrs = (EFAttr *) NULL;
|
newnode->efnode_attrs = (EFAttr *) NULL;
|
||||||
newnode->efnode_loc.r_xbot = x;
|
newnode->efnode_loc.r_xbot = (int)(0.5 + (float)x * locScale);
|
||||||
newnode->efnode_loc.r_ybot = y;
|
newnode->efnode_loc.r_ybot = (int)(0.5 + (float)y * locScale);
|
||||||
newnode->efnode_loc.r_xtop = x + 1;
|
newnode->efnode_loc.r_xtop = newnode->efnode_loc.r_xbot + 1;
|
||||||
newnode->efnode_loc.r_ytop = y + 1;
|
newnode->efnode_loc.r_ytop = newnode->efnode_loc.r_ybot + 1;
|
||||||
newnode->efnode_client = (ClientData) NULL;
|
newnode->efnode_client = (ClientData) NULL;
|
||||||
if (layerName) newnode->efnode_type =
|
if (layerName) newnode->efnode_type =
|
||||||
efBuildAddStr(EFLayerNames, &EFLayerNumNames, MAXTYPES, layerName);
|
efBuildAddStr(EFLayerNames, &EFLayerNumNames, MAXTYPES, layerName);
|
||||||
|
|
@ -553,8 +555,8 @@ efBuildDeviceParams(name, argc, argv)
|
||||||
if (name[0] == ':')
|
if (name[0] == ':')
|
||||||
{
|
{
|
||||||
newparm->parm_name = StrDup((char **)NULL, argv[n]);
|
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
|
else
|
||||||
newparm->parm_name = StrDup((char **)NULL, pptr + 1);
|
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 */
|
Rect *r; /* Coordinates of 1x1 rectangle entirely inside device */
|
||||||
int argc; /* Size of argv */
|
int argc; /* Size of argv */
|
||||||
char *argv[]; /* Tokens for the rest of the dev line.
|
char *argv[]; /* Tokens for the rest of the dev line.
|
||||||
* The first depend on the type of device. The rest
|
* Starts with the last two position values, used to
|
||||||
* are taken in groups of 3, one for each terminal.
|
* hash the device record. The next arguments depend
|
||||||
* Each group of 3 consists of the node name to which
|
* on the type of device. The rest are taken in groups
|
||||||
* the terminal connects, the length of the terminal,
|
* of 3, one for each terminal. Each group of 3 consists
|
||||||
* and an attribute list (or the token 0).
|
* 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;
|
int n, nterminals, pn;
|
||||||
|
HashEntry *he;
|
||||||
DevTerm *term;
|
DevTerm *term;
|
||||||
Dev *newdev, devtmp;
|
Dev *newdev, devtmp;
|
||||||
DevParam *newparm, *devp, *sparm;
|
DevParam *newparm, *devp, *sparm;
|
||||||
char ptype, *pptr, **av;
|
char ptype, *pptr, **av;
|
||||||
|
char devhash[64];
|
||||||
int argstart = 1; /* start of terminal list in argv[] */
|
int argstart = 1; /* start of terminal list in argv[] */
|
||||||
bool hasModel = strcmp(type, "None") ? TRUE : FALSE;
|
bool hasModel = strcmp(type, "None") ? TRUE : FALSE;
|
||||||
|
|
||||||
int area, perim; /* Total area, perimeter of primary type (i.e., channel) */
|
int area, perim; /* Total area, perimeter of primary type (i.e., channel) */
|
||||||
|
|
||||||
|
newdev = (Dev *)NULL;
|
||||||
devtmp.dev_subsnode = NULL;
|
devtmp.dev_subsnode = NULL;
|
||||||
devtmp.dev_cap = 0.0;
|
devtmp.dev_cap = 0.0;
|
||||||
devtmp.dev_res = 0.0;
|
devtmp.dev_res = 0.0;
|
||||||
|
|
@ -681,7 +688,8 @@ efBuildDevice(def, class, type, r, argc, argv)
|
||||||
{
|
{
|
||||||
pn = *(argv[argstart] + 1) - '0';
|
pn = *(argv[argstart] + 1) - '0';
|
||||||
if (pn == 0)
|
if (pn == 0)
|
||||||
devtmp.dev_area = atoi(pptr);
|
devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
|
||||||
|
* locScale * locScale);
|
||||||
/* Otherwise, punt */
|
/* Otherwise, punt */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -692,15 +700,15 @@ efBuildDevice(def, class, type, r, argc, argv)
|
||||||
{
|
{
|
||||||
pn = *(argv[argstart] + 1) - '0';
|
pn = *(argv[argstart] + 1) - '0';
|
||||||
if (pn == 0)
|
if (pn == 0)
|
||||||
devtmp.dev_perim = atoi(pptr);
|
devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale);
|
||||||
/* Otherwise, use verbatim */
|
/* Otherwise, use verbatim */
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
devtmp.dev_length = atoi(pptr);
|
devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
|
||||||
break;
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
devtmp.dev_width = atoi(pptr);
|
devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale);
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
devtmp.dev_cap = (float)atof(pptr);
|
devtmp.dev_cap = (float)atof(pptr);
|
||||||
|
|
@ -713,7 +721,6 @@ efBuildDevice(def, class, type, r, argc, argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for optional substrate node */
|
/* Check for optional substrate node */
|
||||||
|
|
||||||
switch (class)
|
switch (class)
|
||||||
{
|
{
|
||||||
case DEV_RES:
|
case DEV_RES:
|
||||||
|
|
@ -743,93 +750,149 @@ efBuildDevice(def, class, type, r, argc, argv)
|
||||||
|
|
||||||
nterminals = (argc - argstart) / 3;
|
nterminals = (argc - argstart) / 3;
|
||||||
|
|
||||||
newdev = (Dev *) mallocMagic((unsigned) DevSize(nterminals));
|
/* Determine if this device has been seen before */
|
||||||
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;
|
|
||||||
|
|
||||||
newdev->dev_nterm = nterminals;
|
sprintf(devhash, "%dx%d%s", r->r_xbot, r->r_ybot, type);
|
||||||
newdev->dev_rect = *r;
|
he = HashFind(&def->def_devs, devhash);
|
||||||
newdev->dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, type);
|
newdev = (Dev *)HashGetValue(he);
|
||||||
newdev->dev_class = class;
|
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)
|
switch (class)
|
||||||
{
|
{
|
||||||
case DEV_FET: /* old-style "fet" record */
|
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);
|
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
||||||
break;
|
break;
|
||||||
case DEV_MOSFET: /* new-style "device mosfet" record */
|
case DEV_MOSFET: /* new-style "device mosfet" record */
|
||||||
case DEV_ASYMMETRIC:
|
case DEV_ASYMMETRIC:
|
||||||
case DEV_BJT:
|
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 */
|
/* "None" in the place of the substrate name means substrate is ignored */
|
||||||
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
||||||
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
||||||
break;
|
break;
|
||||||
case DEV_RES:
|
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))
|
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
||||||
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case DEV_CAP:
|
case DEV_CAP:
|
||||||
case DEV_CAPREV:
|
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))
|
if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0))
|
||||||
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE);
|
||||||
|
|
||||||
|
|
@ -859,10 +922,6 @@ efBuildDevice(def, class, type, r, argc, argv)
|
||||||
#undef TERM_PERIM
|
#undef TERM_PERIM
|
||||||
#undef TERM_ATTRS
|
#undef TERM_ATTRS
|
||||||
|
|
||||||
/* Add this dev to the list for def */
|
|
||||||
newdev->dev_next = def->def_devs;
|
|
||||||
def->def_devs = newdev;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1123,12 +1182,26 @@ efBuildUse(def, subDefName, subUseId, ta, tb, tc, td, te, tf)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*cp = '\0';
|
/* Note: Preserve any use of brackets as-is other than the */
|
||||||
newuse->use_id = StrDup((char **) NULL, subUseId);
|
/* standard magic array notation below. This allows, for */
|
||||||
*cp = '[';
|
/* example, verilog instance arrays read from DEF files to */
|
||||||
(void) sscanf(cp, "[%d:%d:%d][%d:%d:%d]",
|
/* be passed through correctly. */
|
||||||
|
|
||||||
|
if ((sscanf(cp, "[%d:%d:%d][%d:%d:%d]",
|
||||||
&newuse->use_xlo, &newuse->use_xhi, &newuse->use_xsep,
|
&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);
|
he = HashFind(&def->def_uses, newuse->use_id);
|
||||||
|
|
@ -1168,7 +1241,7 @@ efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac)
|
||||||
int n;
|
int n;
|
||||||
Connection *conn;
|
Connection *conn;
|
||||||
unsigned size = sizeof (Connection)
|
unsigned size = sizeof (Connection)
|
||||||
+ (efNumResistClasses - 1) * sizeof (PerimArea);
|
+ (efNumResistClasses - 1) * sizeof (EFPerimArea);
|
||||||
|
|
||||||
conn = (Connection *) mallocMagic((unsigned)(size));
|
conn = (Connection *) mallocMagic((unsigned)(size));
|
||||||
|
|
||||||
|
|
@ -1178,8 +1251,9 @@ efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac)
|
||||||
conn->conn_next = def->def_conns;
|
conn->conn_next = def->def_conns;
|
||||||
for (n = 0; n < efNumResistClasses && ac > 1; n++, ac -= 2)
|
for (n = 0; n < efNumResistClasses && ac > 1; n++, ac -= 2)
|
||||||
{
|
{
|
||||||
conn->conn_pa[n].pa_area = atoi(*av++);
|
conn->conn_pa[n].pa_area = (int)(0.5 + (float)atoi(*av++)
|
||||||
conn->conn_pa[n].pa_perim = atoi(*av++);
|
* locScale * locScale);
|
||||||
|
conn->conn_pa[n].pa_perim = (int)(0.5 + (float)atoi(*av++) * locScale);
|
||||||
}
|
}
|
||||||
for ( ; n < efNumResistClasses; n++)
|
for ( ; n < efNumResistClasses; n++)
|
||||||
conn->conn_pa[n].pa_area = conn->conn_pa[n].pa_perim = 0;
|
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 */
|
Def *def; /* Def to which this connection is to be added */
|
||||||
char *nodeName1; /* Name of first node in resistor */
|
char *nodeName1; /* Name of first node in resistor */
|
||||||
char *nodeName2; /* Name of second node in resistor */
|
char *nodeName2; /* Name of second node in resistor */
|
||||||
float resistance; /* Resistor value */
|
int resistance; /* Resistor value */
|
||||||
{
|
{
|
||||||
Connection *conn;
|
Connection *conn;
|
||||||
|
|
||||||
conn = (Connection *) mallocMagic((unsigned)(sizeof (Connection)));
|
conn = (Connection *) mallocMagic((unsigned)(sizeof (Connection)));
|
||||||
if (efConnInitSubs(conn, nodeName1, nodeName2))
|
if (efConnInitSubs(conn, nodeName1, nodeName2))
|
||||||
{
|
{
|
||||||
conn->conn_res = resistance;
|
conn->conn_res = (float)resistance;
|
||||||
conn->conn_next = def->def_resistors;
|
conn->conn_next = def->def_resistors;
|
||||||
def->def_resistors = conn;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,6 @@ EFDone()
|
||||||
Kill *kill;
|
Kill *kill;
|
||||||
Def *def;
|
Def *def;
|
||||||
Use *use;
|
Use *use;
|
||||||
Dev *dev;
|
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
HashStartSearch(&hs);
|
HashStartSearch(&hs);
|
||||||
|
|
@ -114,22 +113,18 @@ EFDone()
|
||||||
efFreeNodeTable(&def->def_nodes);
|
efFreeNodeTable(&def->def_nodes);
|
||||||
efFreeNodeList(&def->def_firstn);
|
efFreeNodeList(&def->def_firstn);
|
||||||
efFreeUseTable(&def->def_uses);
|
efFreeUseTable(&def->def_uses);
|
||||||
|
efFreeDevTable(&def->def_devs);
|
||||||
HashKill(&def->def_nodes);
|
HashKill(&def->def_nodes);
|
||||||
HashKill(&def->def_dists);
|
HashKill(&def->def_dists);
|
||||||
HashKill(&def->def_uses);
|
HashKill(&def->def_uses);
|
||||||
|
HashKill(&def->def_devs);
|
||||||
for (conn = def->def_conns; conn; conn = conn->conn_next)
|
for (conn = def->def_conns; conn; conn = conn->conn_next)
|
||||||
efFreeConn(conn);
|
efFreeConn(conn);
|
||||||
for (conn = def->def_caps; conn; conn = conn->conn_next)
|
for (conn = def->def_caps; conn; conn = conn->conn_next)
|
||||||
efFreeConn(conn);
|
efFreeConn(conn);
|
||||||
for (conn = def->def_resistors; conn; conn = conn->conn_next)
|
for (conn = def->def_resistors; conn; conn = conn->conn_next)
|
||||||
efFreeConn(conn);
|
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)
|
for (kill = def->def_kills; kill; kill = kill->kill_next)
|
||||||
{
|
{
|
||||||
freeMagic(kill->kill_name);
|
freeMagic(kill->kill_name);
|
||||||
|
|
@ -151,13 +146,6 @@ EFDone()
|
||||||
EFTech = (char *)NULL;
|
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 */
|
/* Free up the parameter name tables for each device */
|
||||||
|
|
||||||
HashStartSearch(&hs);
|
HashStartSearch(&hs);
|
||||||
|
|
@ -244,7 +232,6 @@ efDefNew(name)
|
||||||
newdef->def_conns = (Connection *) NULL;
|
newdef->def_conns = (Connection *) NULL;
|
||||||
newdef->def_caps = (Connection *) NULL;
|
newdef->def_caps = (Connection *) NULL;
|
||||||
newdef->def_resistors = (Connection *) NULL;
|
newdef->def_resistors = (Connection *) NULL;
|
||||||
newdef->def_devs = (Dev *) NULL;
|
|
||||||
newdef->def_kills = (Kill *) NULL;
|
newdef->def_kills = (Kill *) NULL;
|
||||||
|
|
||||||
/* Initialize circular list of nodes */
|
/* Initialize circular list of nodes */
|
||||||
|
|
@ -257,6 +244,9 @@ efDefNew(name)
|
||||||
/* Initialize hash table of node names */
|
/* Initialize hash table of node names */
|
||||||
HashInit(&newdef->def_nodes, INITNODESIZE, HT_STRINGKEYS);
|
HashInit(&newdef->def_nodes, INITNODESIZE, HT_STRINGKEYS);
|
||||||
|
|
||||||
|
/* Initialize hash table of devices */
|
||||||
|
HashInit(&newdef->def_devs, INITNODESIZE, HT_STRINGKEYS);
|
||||||
|
|
||||||
/* Initialize hash table of distances */
|
/* Initialize hash table of distances */
|
||||||
HashInitClient(&newdef->def_dists, INITNODESIZE, HT_CLIENTKEYS,
|
HashInitClient(&newdef->def_dists, INITNODESIZE, HT_CLIENTKEYS,
|
||||||
efHNDistCompare, efHNDistCopy, efHNDistHash, efHNDistKill);
|
efHNDistCompare, efHNDistCopy, efHNDistHash, efHNDistKill);
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,8 @@ bool efFlatGlobCmp(HierName *, HierName *);
|
||||||
char *efFlatGlobCopy(HierName *);
|
char *efFlatGlobCopy(HierName *);
|
||||||
void efFlatGlobError(EFNodeName *, EFNodeName *);
|
void efFlatGlobError(EFNodeName *, EFNodeName *);
|
||||||
int efAddNodes(HierContext *, bool);
|
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)
|
if (flags & EF_NOFLATSUBCKT)
|
||||||
efFlatNodesStdCell(&efFlatContext);
|
efFlatNodesStdCell(&efFlatContext);
|
||||||
else
|
else
|
||||||
efFlatNodes(&efFlatContext);
|
efFlatNodes(&efFlatContext, FALSE, TRUE);
|
||||||
efFlatKills(&efFlatContext);
|
efFlatKills(&efFlatContext);
|
||||||
if (!(flags & EF_NONAMEMERGE))
|
if (!(flags & EF_NONAMEMERGE))
|
||||||
efFlatGlob();
|
efFlatGlob();
|
||||||
|
|
@ -193,8 +194,8 @@ EFFlatBuildOneLevel(def, flags)
|
||||||
efFlatContext.hc_x = efFlatContext.hc_y = 0;
|
efFlatContext.hc_x = efFlatContext.hc_y = 0;
|
||||||
efFlatRootUse.use_def = efFlatRootDef;
|
efFlatRootUse.use_def = efFlatRootDef;
|
||||||
|
|
||||||
/* Record all nodes of the next level in the hierarchy */
|
/* Record all nodes down the hierarchy from here */
|
||||||
efHierSrUses(&efFlatContext, efAddNodes, (ClientData)TRUE);
|
efFlatNodes(&efFlatContext, (ClientData)TRUE, (ClientData)FALSE);
|
||||||
|
|
||||||
/* Expand all subcells that contain connectivity information but */
|
/* Expand all subcells that contain connectivity information but */
|
||||||
/* no active devices (including those in subcells). */
|
/* no active devices (including those in subcells). */
|
||||||
|
|
@ -205,12 +206,12 @@ EFFlatBuildOneLevel(def, flags)
|
||||||
if (usecount > 0)
|
if (usecount > 0)
|
||||||
efHierSrUses(&efFlatContext, efFlatNodesDeviceless, (ClientData)&usecount);
|
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;
|
efFlatRootUse.use_def->def_flags |= DEF_NODEVICES;
|
||||||
|
|
||||||
/* Record all local nodes */
|
/* Record all local nodes */
|
||||||
efAddNodes(&efFlatContext, FALSE);
|
efAddNodes(&efFlatContext, FALSE);
|
||||||
efAddConns(&efFlatContext);
|
efAddConns(&efFlatContext, TRUE);
|
||||||
|
|
||||||
efFlatKills(&efFlatContext);
|
efFlatKills(&efFlatContext);
|
||||||
if (!(flags & EF_NONAMEMERGE))
|
if (!(flags & EF_NONAMEMERGE))
|
||||||
|
|
@ -291,16 +292,16 @@ EFFlatDone()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
efFlatNodes(hc)
|
efFlatNodes(hc, stdcell, doWarn)
|
||||||
HierContext *hc;
|
HierContext *hc;
|
||||||
{
|
{
|
||||||
(void) efHierSrUses(hc, efFlatNodes);
|
(void) efHierSrUses(hc, efFlatNodes);
|
||||||
|
|
||||||
/* Add all our own nodes to the table */
|
/* Add all our own nodes to the table */
|
||||||
efAddNodes(hc, FALSE);
|
efAddNodes(hc, stdcell);
|
||||||
|
|
||||||
/* Process our own connections and adjustments */
|
/* Process our own connections and adjustments */
|
||||||
(void) efAddConns(hc);
|
(void) efAddConns(hc, doWarn);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
@ -352,7 +353,7 @@ efFlatNodesStdCell(hc)
|
||||||
|
|
||||||
/* Process our own connections and adjustments */
|
/* Process our own connections and adjustments */
|
||||||
if (!(hc->hc_use->use_def->def_flags & DEF_SUBCIRCUIT))
|
if (!(hc->hc_use->use_def->def_flags & DEF_SUBCIRCUIT))
|
||||||
(void) efAddConns(hc);
|
(void) efAddConns(hc, TRUE);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
@ -372,13 +373,13 @@ efFlatNodesDeviceless(hc, cdata)
|
||||||
if (newcount > 0)
|
if (newcount > 0)
|
||||||
efHierSrUses(hc, efFlatNodesDeviceless, (ClientData)&newcount);
|
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 */
|
/* Add all our own nodes to the table */
|
||||||
efAddNodes(hc, TRUE);
|
efAddNodes(hc, TRUE);
|
||||||
|
|
||||||
/* Process our own connections and adjustments */
|
/* Process our own connections and adjustments */
|
||||||
efAddConns(hc);
|
efAddConns(hc, TRUE);
|
||||||
|
|
||||||
/* Mark this definition as having no devices, so it will not be visited */
|
/* Mark this definition as having no devices, so it will not be visited */
|
||||||
hc->hc_use->use_def->def_flags |= DEF_NODEVICES;
|
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;
|
bool is_subcircuit = (def->def_flags & DEF_SUBCIRCUIT) ? TRUE : FALSE;
|
||||||
|
|
||||||
scale = def->def_scale;
|
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;
|
for (node = (EFNode *) def->def_firstn.efnode_next;
|
||||||
node != &def->def_firstn;
|
node != &def->def_firstn;
|
||||||
|
|
@ -467,10 +468,10 @@ efAddNodes(hc, stdcell)
|
||||||
newnode->efnode_type = node->efnode_type;
|
newnode->efnode_type = node->efnode_type;
|
||||||
if (!stdcell)
|
if (!stdcell)
|
||||||
bcopy((char *) node->efnode_pa, (char *) newnode->efnode_pa,
|
bcopy((char *) node->efnode_pa, (char *) newnode->efnode_pa,
|
||||||
efNumResistClasses * sizeof (PerimArea));
|
efNumResistClasses * sizeof (EFPerimArea));
|
||||||
else
|
else
|
||||||
bzero((char *) newnode->efnode_pa,
|
bzero((char *) newnode->efnode_pa,
|
||||||
efNumResistClasses * sizeof (PerimArea));
|
efNumResistClasses * sizeof (EFPerimArea));
|
||||||
GeoTransRect(&hc->hc_trans, &node->efnode_loc, &newnode->efnode_loc);
|
GeoTransRect(&hc->hc_trans, &node->efnode_loc, &newnode->efnode_loc);
|
||||||
|
|
||||||
/* Scale the result by "scale" --- hopefully we end up with an integer */
|
/* Scale the result by "scale" --- hopefully we end up with an integer */
|
||||||
|
|
@ -527,6 +528,7 @@ efAddNodes(hc, stdcell)
|
||||||
HashSetValue(he, (char *) newname);
|
HashSetValue(he, (char *) newname);
|
||||||
newname->efnn_node = newnode;
|
newname->efnn_node = newnode;
|
||||||
newname->efnn_hier = hierName;
|
newname->efnn_hier = hierName;
|
||||||
|
newname->efnn_port = -1;
|
||||||
if (newnode->efnode_name)
|
if (newnode->efnode_name)
|
||||||
{
|
{
|
||||||
newname->efnn_next = newnode->efnode_name->efnn_next;
|
newname->efnn_next = newnode->efnode_name->efnn_next;
|
||||||
|
|
@ -561,8 +563,9 @@ efAddNodes(hc, stdcell)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
efAddConns(hc)
|
efAddConns(hc, doWarn)
|
||||||
HierContext *hc;
|
HierContext *hc;
|
||||||
|
bool doWarn;
|
||||||
{
|
{
|
||||||
Connection *conn;
|
Connection *conn;
|
||||||
|
|
||||||
|
|
@ -575,9 +578,9 @@ efAddConns(hc)
|
||||||
{
|
{
|
||||||
/* Special case for speed when no array info is present */
|
/* Special case for speed when no array info is present */
|
||||||
if (conn->conn_1.cn_nsubs == 0)
|
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
|
else
|
||||||
efHierSrArray(hc, conn, efAddOneConn, (ClientData) NULL);
|
efHierSrArray(hc, conn, efAddOneConn, (ClientData)doWarn);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
@ -604,16 +607,17 @@ efAddConns(hc)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
efAddOneConn(hc, name1, name2, conn)
|
efAddOneConn(hc, name1, name2, conn, doWarn)
|
||||||
HierContext *hc;
|
HierContext *hc;
|
||||||
char *name1, *name2; /* These are strings, not HierNames */
|
char *name1, *name2; /* These are strings, not HierNames */
|
||||||
Connection *conn;
|
Connection *conn;
|
||||||
|
bool doWarn;
|
||||||
{
|
{
|
||||||
HashEntry *he1, *he2;
|
HashEntry *he1, *he2;
|
||||||
EFNode *node, *newnode;
|
EFNode *node, *newnode;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
he1 = EFHNLook(hc->hc_hierName, name1, "connect(1)");
|
he1 = EFHNLook(hc->hc_hierName, name1, (doWarn) ? "connect(1)" : NULL);
|
||||||
if (he1 == NULL)
|
if (he1 == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -629,7 +633,7 @@ efAddOneConn(hc, name1, name2, conn)
|
||||||
/* Merge this node with conn_name2 if one was specified */
|
/* Merge this node with conn_name2 if one was specified */
|
||||||
if (name2)
|
if (name2)
|
||||||
{
|
{
|
||||||
he2 = EFHNLook(hc->hc_hierName, name2, "connect(2)");
|
he2 = EFHNLook(hc->hc_hierName, name2, (doWarn) ? "connect(2)" : NULL);
|
||||||
if (he2 == NULL)
|
if (he2 == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
newnode = ((EFNodeName *) HashGetValue(he2))->efnn_node;
|
newnode = ((EFNodeName *) HashGetValue(he2))->efnn_node;
|
||||||
|
|
@ -1018,14 +1022,23 @@ efFlatSingleCap(hc, name1, name2, conn)
|
||||||
EFNode *n1, *n2;
|
EFNode *n1, *n2;
|
||||||
HashEntry *he;
|
HashEntry *he;
|
||||||
EFCoupleKey ck;
|
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;
|
return 0;
|
||||||
n1 = ((EFNodeName *) HashGetValue(he))->efnn_node;
|
n1 = ((EFNodeName *) HashGetValue(he))->efnn_node;
|
||||||
if (n1->efnode_flags & EF_KILLED)
|
if (n1->efnode_flags & EF_KILLED)
|
||||||
return 0;
|
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;
|
return 0;
|
||||||
n2 = ((EFNodeName *) HashGetValue(he))->efnn_node;
|
n2 = ((EFNodeName *) HashGetValue(he))->efnn_node;
|
||||||
if (n2->efnode_flags & EF_KILLED)
|
if (n2->efnode_flags & EF_KILLED)
|
||||||
|
|
|
||||||
|
|
@ -471,6 +471,8 @@ efHierVisitDevs(hc, ca)
|
||||||
{
|
{
|
||||||
Def *def = hc->hc_use->use_def;
|
Def *def = hc->hc_use->use_def;
|
||||||
Dev *dev;
|
Dev *dev;
|
||||||
|
HashSearch hs;
|
||||||
|
HashEntry *he;
|
||||||
float scale;
|
float scale;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -482,8 +484,10 @@ efHierVisitDevs(hc, ca)
|
||||||
scale = (efScaleChanged && def->def_scale != 1.0) ? def->def_scale : 1.0;
|
scale = (efScaleChanged && def->def_scale != 1.0) ? def->def_scale : 1.0;
|
||||||
|
|
||||||
/* Visit all devices */
|
/* 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))
|
if (efHierDevKilled(hc, dev, hc->hc_hierName))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,7 @@ typedef struct conn
|
||||||
} conn_value;
|
} conn_value;
|
||||||
|
|
||||||
struct conn *conn_next; /* Next connection in list */
|
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
|
* efNumResistClasses array elements
|
||||||
* allocated to it.
|
* allocated to it.
|
||||||
*/
|
*/
|
||||||
|
|
@ -156,6 +156,7 @@ typedef struct def
|
||||||
HashTable def_nodes; /* Map names into EFNodeNames */
|
HashTable def_nodes; /* Map names into EFNodeNames */
|
||||||
HashTable def_dists; /* Map pairs of names into Distances */
|
HashTable def_dists; /* Map pairs of names into Distances */
|
||||||
HashTable def_uses; /* Hash children of this def by name */
|
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 */
|
EFNode def_firstn; /* Head of circular list of nodes */
|
||||||
|
|
||||||
/* The following are all NULL-terminated lists */
|
/* The following are all NULL-terminated lists */
|
||||||
|
|
@ -163,7 +164,6 @@ typedef struct def
|
||||||
Connection *def_conns; /* Hierarchical connections/adjustments */
|
Connection *def_conns; /* Hierarchical connections/adjustments */
|
||||||
Connection *def_caps; /* Two-terminal capacitors */
|
Connection *def_caps; /* Two-terminal capacitors */
|
||||||
Connection *def_resistors; /* Two-terminal resistors */
|
Connection *def_resistors; /* Two-terminal resistors */
|
||||||
Dev *def_devs; /* Devices */
|
|
||||||
Kill *def_kills; /* Used to modify hierarchical structure
|
Kill *def_kills; /* Used to modify hierarchical structure
|
||||||
* using information present only in the
|
* using information present only in the
|
||||||
* parent, e.g, to kill an old node and
|
* parent, e.g, to kill an old node and
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "extflat/extflat.h"
|
#include "extflat/extflat.h"
|
||||||
#include "extflat/EFint.h"
|
#include "extflat/EFint.h"
|
||||||
#include "extract/extract.h"
|
#include "extract/extract.h"
|
||||||
|
#include "extract/extractInt.h"
|
||||||
#include "utils/paths.h"
|
#include "utils/paths.h"
|
||||||
|
|
||||||
#ifndef MAGIC_WRAPPER
|
#ifndef MAGIC_WRAPPER
|
||||||
|
|
@ -96,6 +97,7 @@ keyTable[] =
|
||||||
/* Data shared with EFerror.c */
|
/* Data shared with EFerror.c */
|
||||||
char *efReadFileName; /* Name of file currently being read */
|
char *efReadFileName; /* Name of file currently being read */
|
||||||
int efReadLineNum; /* Current line number in above file */
|
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 */
|
/* Data local to this file */
|
||||||
static bool efReadDef();
|
static bool efReadDef();
|
||||||
|
|
@ -139,6 +141,7 @@ EFReadFile(name, dosubckt, resist, noscale)
|
||||||
if (def == NULL)
|
if (def == NULL)
|
||||||
def = efDefNew(name);
|
def = efDefNew(name);
|
||||||
|
|
||||||
|
locScale = 1.0;
|
||||||
rc = efReadDef(def, dosubckt, resist, noscale, TRUE);
|
rc = efReadDef(def, dosubckt, resist, noscale, TRUE);
|
||||||
if (EFArgTech) EFTech = StrDup((char **) NULL, EFArgTech);
|
if (EFArgTech) EFTech = StrDup((char **) NULL, EFArgTech);
|
||||||
if (EFScale == 0.0) EFScale = 1.0;
|
if (EFScale == 0.0) EFScale = 1.0;
|
||||||
|
|
@ -265,6 +268,11 @@ readfile:
|
||||||
cscale = 1;
|
cscale = 1;
|
||||||
}
|
}
|
||||||
lscale = (float)atof(argv[3]);
|
lscale = (float)atof(argv[3]);
|
||||||
|
if (lscale != ExtCurStyle->exts_unitsPerLambda)
|
||||||
|
{
|
||||||
|
locScale = lscale / ExtCurStyle->exts_unitsPerLambda;
|
||||||
|
lscale = ExtCurStyle->exts_unitsPerLambda;
|
||||||
|
}
|
||||||
if (lscale == 0.0)
|
if (lscale == 0.0)
|
||||||
{
|
{
|
||||||
efReadError("Bad linear scaling = 0; reset to 1.\n");
|
efReadError("Bad linear scaling = 0; reset to 1.\n");
|
||||||
|
|
@ -283,10 +291,10 @@ readfile:
|
||||||
|
|
||||||
/* attr node xlo ylo xhi yhi type text */
|
/* attr node xlo ylo xhi yhi type text */
|
||||||
case ATTR:
|
case ATTR:
|
||||||
r.r_xbot = atoi(argv[2]);
|
r.r_xbot = (int)(0.5 + (float)atoi(argv[2]) * locScale);
|
||||||
r.r_ybot = atoi(argv[3]);
|
r.r_ybot = (int)(0.5 + (float)atoi(argv[3]) * locScale);
|
||||||
r.r_xtop = atoi(argv[4]);
|
r.r_xtop = (int)(0.5 + (float)atoi(argv[4]) * locScale);
|
||||||
r.r_ytop = atoi(argv[5]),
|
r.r_ytop = (int)(0.5 + (float)atoi(argv[5]) * locScale),
|
||||||
efBuildAttr(def, argv[1], &r, argv[6], argv[7]);
|
efBuildAttr(def, argv[1], &r, argv[6], argv[7]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -351,13 +359,12 @@ readfile:
|
||||||
break; /* we will deal with in efBuildDevice(). */
|
break; /* we will deal with in efBuildDevice(). */
|
||||||
}
|
}
|
||||||
|
|
||||||
r.r_xbot = atoi(argv[3]);
|
r.r_xbot = (int)(0.5 + (float)atoi(argv[3]) * locScale);
|
||||||
r.r_ybot = atoi(argv[4]);
|
r.r_ybot = (int)(0.5 + (float)atoi(argv[4]) * locScale);
|
||||||
r.r_xtop = atoi(argv[5]);
|
r.r_xtop = (int)(0.5 + (float)atoi(argv[5]) * locScale);
|
||||||
r.r_ytop = atoi(argv[6]);
|
r.r_ytop = (int)(0.5 + (float)atoi(argv[6]) * locScale);
|
||||||
|
|
||||||
if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7,
|
if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7, &argv[7]) != 0)
|
||||||
&argv[7]) != 0)
|
|
||||||
{
|
{
|
||||||
efReadError("Incomplete terminal description for device\n");
|
efReadError("Incomplete terminal description for device\n");
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -367,10 +374,10 @@ readfile:
|
||||||
/* for backwards compatibility */
|
/* for backwards compatibility */
|
||||||
/* fet type xlo ylo xhi yhi area perim substrate GATE T1 T2 ... */
|
/* fet type xlo ylo xhi yhi area perim substrate GATE T1 T2 ... */
|
||||||
case FET:
|
case FET:
|
||||||
r.r_xbot = atoi(argv[2]);
|
r.r_xbot = (int)(0.5 + (float)atoi(argv[2]) * locScale);
|
||||||
r.r_ybot = atoi(argv[3]);
|
r.r_ybot = (int)(0.5 + (float)atoi(argv[3]) * locScale);
|
||||||
r.r_xtop = atoi(argv[4]);
|
r.r_xtop = (int)(0.5 + (float)atoi(argv[4]) * locScale);
|
||||||
r.r_ytop = atoi(argv[5]);
|
r.r_ytop = (int)(0.5 + (float)atoi(argv[5]) * locScale);
|
||||||
if (efBuildDevice(def, DEV_FET, argv[1], &r, argc - 6, &argv[6]) != 0)
|
if (efBuildDevice(def, DEV_FET, argv[1], &r, argc - 6, &argv[6]) != 0)
|
||||||
{
|
{
|
||||||
efReadError("Incomplete terminal description for fet\n");
|
efReadError("Incomplete terminal description for fet\n");
|
||||||
|
|
@ -426,10 +433,8 @@ readfile:
|
||||||
/* port name num xl yl xh yh type */
|
/* port name num xl yl xh yh type */
|
||||||
case PORT:
|
case PORT:
|
||||||
if (DoSubCircuit)
|
if (DoSubCircuit)
|
||||||
{
|
|
||||||
DoResist = FALSE;
|
|
||||||
def->def_flags |= DEF_SUBCIRCUIT;
|
def->def_flags |= DEF_SUBCIRCUIT;
|
||||||
}
|
|
||||||
efBuildPortNode(def, argv[1], atoi(argv[2]), atoi(argv[3]),
|
efBuildPortNode(def, argv[1], atoi(argv[2]), atoi(argv[3]),
|
||||||
atoi(argv[4]), argv[7], toplevel);
|
atoi(argv[4]), argv[7], toplevel);
|
||||||
break;
|
break;
|
||||||
|
|
@ -566,8 +571,8 @@ resistChanged:
|
||||||
/* distance driver receiver min max */
|
/* distance driver receiver min max */
|
||||||
case DIST:
|
case DIST:
|
||||||
efBuildDist(def, argv[1], argv[2],
|
efBuildDist(def, argv[1], argv[2],
|
||||||
(int)(lscale*atoi(argv[3])),
|
(int)(lscale*atoi(argv[3])*locScale),
|
||||||
(int)(lscale*atoi(argv[4])));
|
(int)(lscale*atoi(argv[4])*locScale));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* killnode nodename */
|
/* killnode nodename */
|
||||||
|
|
@ -576,8 +581,12 @@ resistChanged:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* resistor node1 node2 resistance */
|
/* 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:
|
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;
|
break;
|
||||||
|
|
||||||
/* abstract (no options/arguments) */
|
/* abstract (no options/arguments) */
|
||||||
|
|
@ -719,11 +728,15 @@ start:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*get == '\\') /* Process quoted characters literally */
|
/* Process backslash characters literally unless they */
|
||||||
{
|
/* are followed by the end-of-line. */
|
||||||
get++;
|
|
||||||
if (*get == '\0') break;
|
if (*get == '\\')
|
||||||
}
|
if (*(get + 1) == '\0')
|
||||||
|
{
|
||||||
|
get++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Copy into token receiving area */
|
/* Copy into token receiving area */
|
||||||
*put++ = *get++;
|
*put++ = *get++;
|
||||||
|
|
|
||||||
|
|
@ -300,6 +300,8 @@ efVisitDevs(hc, ca)
|
||||||
Dev *dev;
|
Dev *dev;
|
||||||
float scale;
|
float scale;
|
||||||
Transform t;
|
Transform t;
|
||||||
|
HashSearch hs;
|
||||||
|
HashEntry *he;
|
||||||
|
|
||||||
if (def->def_flags & DEF_SUBCIRCUIT) return 0;
|
if (def->def_flags & DEF_SUBCIRCUIT) return 0;
|
||||||
|
|
||||||
|
|
@ -311,15 +313,17 @@ efVisitDevs(hc, ca)
|
||||||
t = hc->hc_trans;
|
t = hc->hc_trans;
|
||||||
|
|
||||||
/* Visit our own devices */
|
/* 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))
|
if (efDevKilled(dev, hc->hc_hierName))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((*ca->ca_proc)(dev, hc->hc_hierName, scale, &t, ca->ca_cdata))
|
if ((*ca->ca_proc)(dev, hc->hc_hierName, scale, &t, ca->ca_cdata))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -859,7 +863,7 @@ EFHNOut(hierName, outf)
|
||||||
HierName *hierName;
|
HierName *hierName;
|
||||||
FILE *outf;
|
FILE *outf;
|
||||||
{
|
{
|
||||||
bool trimGlob, trimLocal, trimComma;
|
bool trimGlob, trimLocal, convComma, convBrackets;
|
||||||
char *cp, c;
|
char *cp, c;
|
||||||
|
|
||||||
if (hierName->hn_parent) efHNOutPrefix(hierName->hn_parent, outf);
|
if (hierName->hn_parent) efHNOutPrefix(hierName->hn_parent, outf);
|
||||||
|
|
@ -868,13 +872,19 @@ EFHNOut(hierName, outf)
|
||||||
cp = hierName->hn_name;
|
cp = hierName->hn_name;
|
||||||
trimGlob = (EFTrimFlags & EF_TRIMGLOB);
|
trimGlob = (EFTrimFlags & EF_TRIMGLOB);
|
||||||
trimLocal = (EFTrimFlags & EF_TRIMLOCAL);
|
trimLocal = (EFTrimFlags & EF_TRIMLOCAL);
|
||||||
trimComma = (EFTrimFlags & EF_CONVERTCOMMAS);
|
convComma = (EFTrimFlags & EF_CONVERTCOMMA);
|
||||||
|
convBrackets = (EFTrimFlags & EF_CONVERTBRACKETS);
|
||||||
while (c = *cp++)
|
while (c = *cp++)
|
||||||
{
|
{
|
||||||
if (*cp)
|
if (*cp)
|
||||||
{
|
{
|
||||||
if (trimComma && (c == ','))
|
if (c == ',')
|
||||||
putc(';', outf);
|
{
|
||||||
|
if (convComma)
|
||||||
|
putc('|', outf);
|
||||||
|
}
|
||||||
|
else if (convBrackets && ((c == '[') || (c == ']')))
|
||||||
|
putc('_', outf);
|
||||||
else
|
else
|
||||||
putc(c, outf);
|
putc(c, outf);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
MODULE = extflat
|
MODULE = extflat
|
||||||
MAGICDIR = ..
|
MAGICDIR = ..
|
||||||
SRCS = EFargs.c EFbuild.c EFdef.c EFerr.c EFflat.c EFhier.c EFname.c \
|
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}/defs.mak
|
||||||
include ${MAGICDIR}/rules.mak
|
include ${MAGICDIR}/rules.mak
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,9 @@ typedef unsigned char U_char;
|
||||||
/* Flags to control output of node names. Stored in EFTrimFlags */
|
/* Flags to control output of node names. Stored in EFTrimFlags */
|
||||||
#define EF_TRIMGLOB 0x01 /* Delete trailing '!' from names */
|
#define EF_TRIMGLOB 0x01 /* Delete trailing '!' from names */
|
||||||
#define EF_TRIMLOCAL 0x02 /* Delete trailing '#' from names */
|
#define EF_TRIMLOCAL 0x02 /* Delete trailing '#' from names */
|
||||||
#define EF_CONVERTCOMMAS 0x04 /* Change ',' to ';' in names */
|
#define EF_CONVERTCOMMA 0x04 /* Change ',' to '|' in names, else remove */
|
||||||
#define EF_CONVERTEQUAL 0x08 /* Change '=' to ':' in names */
|
#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
|
* capacitance type now set to float
|
||||||
|
|
@ -141,7 +142,7 @@ typedef struct
|
||||||
{
|
{
|
||||||
int pa_area;
|
int pa_area;
|
||||||
int pa_perim;
|
int pa_perim;
|
||||||
} PerimArea;
|
} EFPerimArea;
|
||||||
|
|
||||||
typedef struct efnhdr
|
typedef struct efnhdr
|
||||||
{
|
{
|
||||||
|
|
@ -218,7 +219,7 @@ typedef struct efnode
|
||||||
*/
|
*/
|
||||||
EFAttr *efnode_attrs; /* Node attribute list */
|
EFAttr *efnode_attrs; /* Node attribute list */
|
||||||
ClientData efnode_client; /* For hire */
|
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
|
* efNumResistClasses array elements
|
||||||
* allocated to it.
|
* allocated to it.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -424,7 +424,10 @@ extTreeSrPaintArea(scx, func, cdarg)
|
||||||
int pNum;
|
int pNum;
|
||||||
|
|
||||||
if ((def->cd_flags & CDAVAILABLE) == 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_func = func;
|
||||||
filter.tf_arg = cdarg;
|
filter.tf_arg = cdarg;
|
||||||
|
|
@ -461,7 +464,10 @@ extTreeSrFunc(scx, fp)
|
||||||
int pNum;
|
int pNum;
|
||||||
|
|
||||||
if ((def->cd_flags & CDAVAILABLE) == 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_scx = scx;
|
||||||
context.tc_filter = fp;
|
context.tc_filter = fp;
|
||||||
|
|
@ -480,3 +486,176 @@ extTreeSrFunc(scx, fp)
|
||||||
return (DBCellSrArea(scx, extTreeSrFunc, (ClientData) 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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ typedef enum
|
||||||
AREAC, CONTACT, CSCALE,
|
AREAC, CONTACT, CSCALE,
|
||||||
DEFAULTAREACAP, DEFAULTOVERLAP, DEFAULTPERIMETER, DEFAULTSIDEOVERLAP,
|
DEFAULTAREACAP, DEFAULTOVERLAP, DEFAULTPERIMETER, DEFAULTSIDEOVERLAP,
|
||||||
DEFAULTSIDEWALL,
|
DEFAULTSIDEWALL,
|
||||||
DEVICE, FET, FETRESIST, HEIGHT, LAMBDA, OVERC,
|
DEVICE, FET, FETRESIST, HEIGHT, ANTENNA, MODEL, TIEDOWN, LAMBDA, OVERC,
|
||||||
PERIMC, PLANEORDER, NOPLANEORDER, RESIST, RSCALE, SIDEHALO, SIDEOVERLAP,
|
PERIMC, PLANEORDER, NOPLANEORDER, RESIST, RSCALE, SIDEHALO, SIDEOVERLAP,
|
||||||
SIDEWALL, STEP, STYLE, SUBSTRATE, UNITS, VARIANT
|
SIDEWALL, STEP, STYLE, SUBSTRATE, UNITS, VARIANT
|
||||||
} Key;
|
} Key;
|
||||||
|
|
@ -122,6 +122,15 @@ static keydesc keyTable[] = {
|
||||||
"height", HEIGHT, 4, 4,
|
"height", HEIGHT, 4, 4,
|
||||||
"type height-above-subtrate thickness",
|
"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,
|
"lambda", LAMBDA, 2, 2,
|
||||||
"units-per-lambda",
|
"units-per-lambda",
|
||||||
|
|
||||||
|
|
@ -157,7 +166,7 @@ static keydesc keyTable[] = {
|
||||||
"style", STYLE, 2, 4,
|
"style", STYLE, 2, 4,
|
||||||
"stylename",
|
"stylename",
|
||||||
|
|
||||||
"substrate", SUBSTRATE, 3, 3,
|
"substrate", SUBSTRATE, 3, 4,
|
||||||
"types plane",
|
"types plane",
|
||||||
|
|
||||||
"units", UNITS, 2, 2,
|
"units", UNITS, 2, 2,
|
||||||
|
|
@ -298,37 +307,47 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr)
|
||||||
TileType t;
|
TileType t;
|
||||||
TileTypeBitMask *rmask, *tmask;
|
TileTypeBitMask *rmask, *tmask;
|
||||||
int n, i = 0, j;
|
int n, i = 0, j;
|
||||||
bool repeat;
|
bool repeat, found;
|
||||||
|
ExtDevice *devptr;
|
||||||
char *locdname;
|
char *locdname;
|
||||||
char **uniquenamelist = (char **)mallocMagic(DBNumTypes * sizeof(char *));
|
char **uniquenamelist = (char **)mallocMagic(DBNumTypes * sizeof(char *));
|
||||||
|
|
||||||
|
found = FALSE;
|
||||||
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
|
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
|
||||||
{
|
{
|
||||||
locdname = ExtCurStyle->exts_transName[t];
|
for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next)
|
||||||
if (locdname != NULL)
|
|
||||||
{
|
{
|
||||||
repeat = FALSE;
|
locdname = devptr->exts_deviceName;
|
||||||
for (j = 0; j < i; j++)
|
if (locdname != NULL)
|
||||||
if (!strcmp(uniquenamelist[j], locdname))
|
|
||||||
{
|
|
||||||
repeat = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (repeat == FALSE)
|
|
||||||
{
|
{
|
||||||
if (i == idx) break;
|
repeat = FALSE;
|
||||||
uniquenamelist[i] = locdname;
|
for (j = 0; j < i; j++)
|
||||||
i++;
|
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 (t == DBNumTypes) return FALSE;
|
||||||
|
if (devptr == NULL) return FALSE;
|
||||||
|
|
||||||
*devnameptr = locdname;
|
*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 */
|
*sd_rclassptr = (short)(-1); /* NO_RESCLASS */
|
||||||
|
|
||||||
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
|
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 */
|
*sub_rclassptr = (short)(-1); /* NO_RESCLASS */
|
||||||
|
|
||||||
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
|
for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++)
|
||||||
|
|
@ -360,6 +379,35 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr)
|
||||||
|
|
||||||
#endif /* MAGIC_WRAPPER */
|
#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
|
#ifdef THREE_D
|
||||||
/*
|
/*
|
||||||
|
|
@ -538,23 +586,10 @@ extTechStyleAlloc()
|
||||||
TileType r;
|
TileType r;
|
||||||
|
|
||||||
style = (ExtStyle *) mallocMagic(sizeof (ExtStyle));
|
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;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
@ -575,7 +610,7 @@ extTechStyleInit(style)
|
||||||
style->exts_status = TECH_NOT_LOADED;
|
style->exts_status = TECH_NOT_LOADED;
|
||||||
|
|
||||||
style->exts_sidePlanes = style->exts_overlapPlanes = 0;
|
style->exts_sidePlanes = style->exts_overlapPlanes = 0;
|
||||||
TTMaskZero(&style->exts_transMask);
|
TTMaskZero(&style->exts_deviceMask);
|
||||||
style->exts_activeTypes = DBAllButSpaceAndDRCBits;
|
style->exts_activeTypes = DBAllButSpaceAndDRCBits;
|
||||||
|
|
||||||
for (r = 0; r < NP; r++)
|
for (r = 0; r < NP; r++)
|
||||||
|
|
@ -589,7 +624,7 @@ extTechStyleInit(style)
|
||||||
{
|
{
|
||||||
TTMaskZero(&style->exts_nodeConn[r]);
|
TTMaskZero(&style->exts_nodeConn[r]);
|
||||||
TTMaskZero(&style->exts_resistConn[r]);
|
TTMaskZero(&style->exts_resistConn[r]);
|
||||||
TTMaskZero(&style->exts_transConn[r]);
|
TTMaskZero(&style->exts_deviceConn[r]);
|
||||||
style->exts_allConn[r] = DBAllTypeBits;
|
style->exts_allConn[r] = DBAllTypeBits;
|
||||||
|
|
||||||
style->exts_sheetResist[r] = 0;
|
style->exts_sheetResist[r] = 0;
|
||||||
|
|
@ -620,43 +655,41 @@ extTechStyleInit(style)
|
||||||
#ifdef ARIEL
|
#ifdef ARIEL
|
||||||
TTMaskZero(&style->exts_subsTransistorTypes[r]);
|
TTMaskZero(&style->exts_subsTransistorTypes[r]);
|
||||||
#endif
|
#endif
|
||||||
if (style->exts_transSDTypes[r] != NULL)
|
if (style->exts_device[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)
|
|
||||||
{
|
{
|
||||||
freeMagic(style->exts_transSubstrateName[r]);
|
ExtDevice *devptr;
|
||||||
style->exts_transSubstrateName[r] = (char *) NULL;
|
for (devptr = style->exts_device[r]; devptr; devptr = devptr->exts_next)
|
||||||
}
|
{
|
||||||
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! */
|
|
||||||
|
|
||||||
if (style->exts_deviceParams[r]->pl_count > 1)
|
if (devptr->exts_deviceSDTypes != NULL)
|
||||||
{
|
freeMagic(devptr->exts_deviceSDTypes);
|
||||||
style->exts_deviceParams[r]->pl_count--;
|
if (devptr->exts_deviceSubstrateName != (char *) NULL)
|
||||||
style->exts_deviceParams[r] = (ParamList *)NULL;
|
freeMagic(devptr->exts_deviceSubstrateName);
|
||||||
}
|
if (devptr->exts_deviceName != (char *) NULL)
|
||||||
else
|
freeMagic(devptr->exts_deviceName);
|
||||||
{
|
while (devptr->exts_deviceParams != (ParamList *) NULL)
|
||||||
freeMagic(style->exts_deviceParams[r]->pl_name);
|
{
|
||||||
freeMagic(style->exts_deviceParams[r]);
|
/* Parameter lists are shared. Only free the last one! */
|
||||||
style->exts_deviceParams[r] = style->exts_deviceParams[r]->pl_next;
|
|
||||||
|
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;
|
style->exts_sideCoupleHalo = 0;
|
||||||
|
|
@ -667,14 +700,20 @@ extTechStyleInit(style)
|
||||||
style->exts_numResistClasses = 0;
|
style->exts_numResistClasses = 0;
|
||||||
|
|
||||||
style->exts_planeOrderStatus = needPlaneOrder ;
|
style->exts_planeOrderStatus = needPlaneOrder ;
|
||||||
|
TTMaskZero(&style->exts_antennaTieTypes);
|
||||||
|
|
||||||
for (r = 0; r < DBNumTypes; r++)
|
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;
|
style->exts_resistByResistClass[r] = 0;
|
||||||
TTMaskZero(&style->exts_typesByResistClass[r]);
|
TTMaskZero(&style->exts_typesByResistClass[r]);
|
||||||
style->exts_typesResistChanged[r] = DBAllButSpaceAndDRCBits;
|
style->exts_typesResistChanged[r] = DBAllButSpaceAndDRCBits;
|
||||||
TTMaskSetType(&style->exts_typesResistChanged[r], TT_SPACE);
|
TTMaskSetType(&style->exts_typesResistChanged[r], TT_SPACE);
|
||||||
style->exts_typeToResistClass[r] = -1;
|
style->exts_typeToResistClass[r] = -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
doConvert = FALSE;
|
doConvert = FALSE;
|
||||||
|
|
||||||
|
|
@ -685,6 +724,7 @@ extTechStyleInit(style)
|
||||||
|
|
||||||
style->exts_globSubstratePlane = -1;
|
style->exts_globSubstratePlane = -1;
|
||||||
TTMaskZero(&style->exts_globSubstrateTypes);
|
TTMaskZero(&style->exts_globSubstrateTypes);
|
||||||
|
TTMaskZero(&style->exts_globSubstrateShieldTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -798,14 +838,6 @@ ExtTechInit()
|
||||||
if (ExtCurStyle != NULL)
|
if (ExtCurStyle != NULL)
|
||||||
{
|
{
|
||||||
extTechStyleInit(ExtCurStyle);
|
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;
|
ExtCurStyle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1569,7 +1601,7 @@ ExtTechLine(sectionName, argc, argv)
|
||||||
PlaneMask pshield, pov;
|
PlaneMask pshield, pov;
|
||||||
CapValue capVal, gscap, gccap;
|
CapValue capVal, gscap, gccap;
|
||||||
TileTypeBitMask types1, types2, termtypes[MAXSD];
|
TileTypeBitMask types1, types2, termtypes[MAXSD];
|
||||||
TileTypeBitMask near, far, ov, shield, subsTypes;
|
TileTypeBitMask near, far, ov, shield, subsTypes, idTypes;
|
||||||
char *subsName, *transName, *cp, *endptr, *paramName;
|
char *subsName, *transName, *cp, *endptr, *paramName;
|
||||||
TileType s, t, r, o;
|
TileType s, t, r, o;
|
||||||
keydesc *kp, *dv;
|
keydesc *kp, *dv;
|
||||||
|
|
@ -1578,6 +1610,7 @@ ExtTechLine(sectionName, argc, argv)
|
||||||
EdgeCap *cnew;
|
EdgeCap *cnew;
|
||||||
ExtKeep *es, *newStyle;
|
ExtKeep *es, *newStyle;
|
||||||
ParamList *subcktParams, *newParam;
|
ParamList *subcktParams, *newParam;
|
||||||
|
ExtDevice *devptr;
|
||||||
int refcnt;
|
int refcnt;
|
||||||
double dhalo;
|
double dhalo;
|
||||||
bool bad;
|
bool bad;
|
||||||
|
|
@ -1796,6 +1829,8 @@ ExtTechLine(sectionName, argc, argv)
|
||||||
case FET:
|
case FET:
|
||||||
case FETRESIST:
|
case FETRESIST:
|
||||||
case HEIGHT:
|
case HEIGHT:
|
||||||
|
case ANTENNA:
|
||||||
|
case TIEDOWN:
|
||||||
case OVERC:
|
case OVERC:
|
||||||
case PERIMC:
|
case PERIMC:
|
||||||
case RESIST:
|
case RESIST:
|
||||||
|
|
@ -1888,24 +1923,32 @@ ExtTechLine(sectionName, argc, argv)
|
||||||
gccap = (argc > 7) ? aToCap(argv[7]) : (CapValue) 0;
|
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++)
|
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
|
||||||
if (TTMaskHasType(&types1, t))
|
if (TTMaskHasType(&types1, t))
|
||||||
{
|
{
|
||||||
TTMaskSetMask(ExtCurStyle->exts_transConn+t,&types1);
|
devptr = (ExtDevice *)mallocMagic(sizeof(ExtDevice));
|
||||||
ExtCurStyle->exts_transSDTypes[t] = (TileTypeBitMask *)
|
devptr->exts_deviceSDTypes = (TileTypeBitMask *)
|
||||||
mallocMagic(2 * sizeof(TileTypeBitMask));
|
mallocMagic(2 * sizeof(TileTypeBitMask));
|
||||||
ExtCurStyle->exts_transSDTypes[t][0] = termtypes[0];
|
devptr->exts_deviceSDTypes[0] = termtypes[0];
|
||||||
ExtCurStyle->exts_transSDTypes[t][1] = DBZeroTypeBits;
|
devptr->exts_deviceSDTypes[1] = DBZeroTypeBits;
|
||||||
ExtCurStyle->exts_transSDCount[t] = nterm;
|
devptr->exts_deviceSDCount = nterm;
|
||||||
ExtCurStyle->exts_transSDCap[t] = gscap;
|
devptr->exts_deviceSDCap = gscap;
|
||||||
ExtCurStyle->exts_transGateCap[t] = gccap;
|
devptr->exts_deviceGateCap = gccap;
|
||||||
ExtCurStyle->exts_deviceClass[t] = DEV_FET;
|
devptr->exts_deviceClass = DEV_FET;
|
||||||
ExtCurStyle->exts_transName[t] =
|
devptr->exts_deviceName = StrDup((char **) NULL, transName);
|
||||||
StrDup((char **) NULL, transName);
|
devptr->exts_deviceSubstrateName =
|
||||||
ExtCurStyle->exts_transSubstrateName[t] =
|
|
||||||
StrDup((char **) NULL, subsName);
|
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
|
#ifdef ARIEL
|
||||||
{
|
{
|
||||||
int z;
|
int z;
|
||||||
|
|
@ -1936,12 +1979,11 @@ ExtTechLine(sectionName, argc, argv)
|
||||||
case DEFAULTSIDEWALL:
|
case DEFAULTSIDEWALL:
|
||||||
ExtTechSimpleSidewallCap(argv);
|
ExtTechSimpleSidewallCap(argv);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEVICE:
|
case DEVICE:
|
||||||
|
|
||||||
/* Parse second argument for device type */
|
/* 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)
|
if (n < 0)
|
||||||
{
|
{
|
||||||
TechError("Illegal device. Legal devices are:\n\t");
|
TechError("Illegal device. Legal devices are:\n\t");
|
||||||
|
|
@ -1999,6 +2041,18 @@ ExtTechLine(sectionName, argc, argv)
|
||||||
argc--;
|
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 */
|
/* Check the number of arguments after splitting out */
|
||||||
/* parameter entries. There is no limit on arguments in */
|
/* parameter entries. There is no limit on arguments in */
|
||||||
/* DEV_SUBCKT and DEV_MSUBCKT. */
|
/* DEV_SUBCKT and DEV_MSUBCKT. */
|
||||||
|
|
@ -2194,31 +2248,47 @@ ExtTechLine(sectionName, argc, argv)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
TTMaskSetMask(&ExtCurStyle->exts_transMask, &types1);
|
TTMaskSetMask(&ExtCurStyle->exts_deviceMask, &types1);
|
||||||
|
|
||||||
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
|
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
|
||||||
{
|
{
|
||||||
if (TTMaskHasType(&types1, t))
|
if (TTMaskHasType(&types1, t))
|
||||||
{
|
{
|
||||||
TTMaskSetMask(ExtCurStyle->exts_transConn + t, &types1);
|
devptr = (ExtDevice *)mallocMagic(sizeof(ExtDevice));
|
||||||
|
|
||||||
for (i = 0; !TTMaskIsZero(&termtypes[i]); i++);
|
for (i = 0; !TTMaskIsZero(&termtypes[i]); i++);
|
||||||
ExtCurStyle->exts_transSDTypes[t] = (TileTypeBitMask *)
|
devptr->exts_deviceSDTypes = (TileTypeBitMask *)
|
||||||
mallocMagic((i + 1) * sizeof(TileTypeBitMask));
|
mallocMagic((i + 1) * sizeof(TileTypeBitMask));
|
||||||
|
|
||||||
for (i = 0; !TTMaskIsZero(&termtypes[i]); i++)
|
for (i = 0; !TTMaskIsZero(&termtypes[i]); i++)
|
||||||
ExtCurStyle->exts_transSDTypes[t][i] = termtypes[i];
|
devptr->exts_deviceSDTypes[i] = termtypes[i];
|
||||||
ExtCurStyle->exts_transSDTypes[t][i] = DBZeroTypeBits;
|
devptr->exts_deviceSDTypes[i] = DBZeroTypeBits;
|
||||||
|
|
||||||
ExtCurStyle->exts_transSDCount[t] = nterm;
|
devptr->exts_deviceSDCount = nterm;
|
||||||
ExtCurStyle->exts_transSDCap[t] = gscap;
|
devptr->exts_deviceSDCap = gscap;
|
||||||
ExtCurStyle->exts_transGateCap[t] = gccap;
|
devptr->exts_deviceGateCap = gccap;
|
||||||
ExtCurStyle->exts_deviceClass[t] = class;
|
devptr->exts_deviceClass = class;
|
||||||
ExtCurStyle->exts_transName[t] =
|
devptr->exts_deviceName = StrDup((char **) NULL, transName);
|
||||||
StrDup((char **) NULL, transName);
|
|
||||||
if (subsName != NULL)
|
if (subsName != NULL)
|
||||||
ExtCurStyle->exts_transSubstrateName[t] =
|
devptr->exts_deviceSubstrateName =
|
||||||
StrDup((char **) NULL, subsName);
|
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
|
#ifdef ARIEL
|
||||||
{
|
{
|
||||||
int z;
|
int z;
|
||||||
|
|
@ -2231,11 +2301,6 @@ ExtTechLine(sectionName, argc, argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (subcktParams != NULL)
|
|
||||||
{
|
|
||||||
ExtCurStyle->exts_deviceParams[t] = subcktParams;
|
|
||||||
subcktParams->pl_count++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -2249,13 +2314,19 @@ ExtTechLine(sectionName, argc, argv)
|
||||||
val = atoi(argv[3]);
|
val = atoi(argv[3]);
|
||||||
isLinear = (strcmp(argv[2], "linear") == 0);
|
isLinear = (strcmp(argv[2], "linear") == 0);
|
||||||
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
|
for (t = TT_TECHDEPBASE; t < DBNumTypes; t++)
|
||||||
|
{
|
||||||
|
ExtDevice *devptr;
|
||||||
if (TTMaskHasType(&types1, t))
|
if (TTMaskHasType(&types1, t))
|
||||||
{
|
{
|
||||||
he = HashFind(&ExtCurStyle->exts_transResist[t], argv[2]);
|
for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next)
|
||||||
HashSetValue(he, (spointertype)val);
|
{
|
||||||
if (isLinear)
|
he = HashFind(&devptr->exts_deviceResist, argv[2]);
|
||||||
ExtCurStyle->exts_linearResist[t] = val;
|
HashSetValue(he, (spointertype)val);
|
||||||
|
if (isLinear)
|
||||||
|
devptr->exts_linearResist = val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case HEIGHT: {
|
case HEIGHT: {
|
||||||
float height, thick;
|
float height, thick;
|
||||||
|
|
@ -2280,6 +2351,122 @@ ExtTechLine(sectionName, argc, argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case UNITS:
|
||||||
if (!strcmp(argv[1], "microns"))
|
if (!strcmp(argv[1], "microns"))
|
||||||
doConvert = TRUE;
|
doConvert = TRUE;
|
||||||
|
|
@ -2569,8 +2756,22 @@ ExtTechLine(sectionName, argc, argv)
|
||||||
ExtCurStyle->exts_stepSize = val;
|
ExtCurStyle->exts_stepSize = val;
|
||||||
break;
|
break;
|
||||||
case SUBSTRATE:
|
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_globSubstrateTypes);
|
||||||
|
TTMaskZero(&ExtCurStyle->exts_globSubstrateShieldTypes);
|
||||||
TTMaskSetMask(&ExtCurStyle->exts_globSubstrateTypes, &types1);
|
TTMaskSetMask(&ExtCurStyle->exts_globSubstrateTypes, &types1);
|
||||||
|
ExtCurStyle->exts_globSubstrateShieldTypes = idTypes;
|
||||||
ExtCurStyle->exts_globSubstratePlane = DBTechNoisyNamePlane(argv[2]);
|
ExtCurStyle->exts_globSubstratePlane = DBTechNoisyNamePlane(argv[2]);
|
||||||
break;
|
break;
|
||||||
case NOPLANEORDER: {
|
case NOPLANEORDER: {
|
||||||
|
|
@ -2619,7 +2820,7 @@ diffplane:
|
||||||
*
|
*
|
||||||
* Postprocess the technology specific information for extraction.
|
* Postprocess the technology specific information for extraction.
|
||||||
* Builds the connectivity tables exts_nodeConn[], exts_resistConn[],
|
* Builds the connectivity tables exts_nodeConn[], exts_resistConn[],
|
||||||
* and exts_transConn[].
|
* and exts_deviceConn[].
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* None.
|
* None.
|
||||||
|
|
@ -2664,9 +2865,9 @@ extTechFinalStyle(style)
|
||||||
for (r = TT_TECHDEPBASE; r < DBNumTypes; r++)
|
for (r = TT_TECHDEPBASE; r < DBNumTypes; r++)
|
||||||
{
|
{
|
||||||
maskBits = style->exts_nodeConn[r] = DBConnectTbl[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++)
|
for (s = TT_TECHDEPBASE; s < DBNumTypes; s++)
|
||||||
{
|
{
|
||||||
|
|
@ -2870,10 +3071,15 @@ zinit:
|
||||||
|
|
||||||
for (r = 0; r < DBNumTypes; r++)
|
for (r = 0; r < DBNumTypes; r++)
|
||||||
{
|
{
|
||||||
style->exts_areaCap[r] *= sqfac;
|
ExtDevice *devptr;
|
||||||
style->exts_transSDCap[r] *= sqfac;
|
|
||||||
style->exts_transGateCap[r] *= sqfac;
|
|
||||||
|
|
||||||
|
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++)
|
for (s = 0; s < DBNumTypes; s++)
|
||||||
{
|
{
|
||||||
EdgeCap *ec;
|
EdgeCap *ec;
|
||||||
|
|
@ -2899,6 +3105,10 @@ zinit:
|
||||||
ec = ec->ec_next)
|
ec = ec->ec_next)
|
||||||
ec->ec_cap *= 0.5;
|
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 */
|
/* side halo and step size are also in microns */
|
||||||
|
|
@ -2953,13 +3163,18 @@ ExtTechScale(scalen, scaled)
|
||||||
|
|
||||||
for (i = 0; i < DBNumTypes; i++)
|
for (i = 0; i < DBNumTypes; i++)
|
||||||
{
|
{
|
||||||
|
ExtDevice *devptr;
|
||||||
|
|
||||||
style->exts_areaCap[i] *= sqn;
|
style->exts_areaCap[i] *= sqn;
|
||||||
style->exts_areaCap[i] /= sqd;
|
style->exts_areaCap[i] /= sqd;
|
||||||
|
|
||||||
style->exts_transSDCap[i] *= sqn;
|
for (devptr = style->exts_device[i]; devptr; devptr = devptr->exts_next)
|
||||||
style->exts_transSDCap[i] /= sqd;
|
{
|
||||||
style->exts_transGateCap[i] *= sqn;
|
devptr->exts_deviceSDCap *= sqn;
|
||||||
style->exts_transGateCap[i] /= sqd;
|
devptr->exts_deviceSDCap /= sqd;
|
||||||
|
devptr->exts_deviceGateCap *= sqn;
|
||||||
|
devptr->exts_deviceGateCap /= sqd;
|
||||||
|
}
|
||||||
|
|
||||||
style->exts_height[i] *= scaled;
|
style->exts_height[i] *= scaled;
|
||||||
style->exts_height[i] /= scalen;
|
style->exts_height[i] /= scalen;
|
||||||
|
|
|
||||||
|
|
@ -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, "\nNode resistance and capacitance:\n");
|
||||||
fprintf(out, "type R-ohm/sq AreaC-ff/l**2\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("\nNode connectivity", ExtCurStyle->exts_nodeConn, out);
|
||||||
extShowConnect("\nResistive region connectivity", ExtCurStyle->exts_resistConn, 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)
|
if (out != stdout)
|
||||||
(void) fclose(out);
|
(void) fclose(out);
|
||||||
|
|
@ -493,12 +493,17 @@ extShowTrans(name, mask, out)
|
||||||
for (t = 0; t < DBNumTypes; t++)
|
for (t = 0; t < DBNumTypes; t++)
|
||||||
if (TTMaskHasType(mask, t))
|
if (TTMaskHasType(mask, t))
|
||||||
{
|
{
|
||||||
fprintf(out, " %-8.8s %d terminals: ",
|
ExtDevice *devptr;
|
||||||
DBTypeShortName(t), ExtCurStyle->exts_transSDCount[t]);
|
|
||||||
extShowMask(&ExtCurStyle->exts_transSDTypes[t][0], out);
|
for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next)
|
||||||
fprintf(out, "\n\tcap (gate-sd/gate-ch) = %lf/%lf\n",
|
{
|
||||||
ExtCurStyle->exts_transSDCap[t],
|
fprintf(out, " %-8.8s %d terminals: ",
|
||||||
ExtCurStyle->exts_transGateCap[t]);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -348,7 +348,7 @@ extTimesCellFunc(cs)
|
||||||
|
|
||||||
/* Count the number of transistors */
|
/* Count the number of transistors */
|
||||||
transList = (TransRegion *) ExtFindRegions(def, &TiPlaneRect,
|
transList = (TransRegion *) ExtFindRegions(def, &TiPlaneRect,
|
||||||
&ExtCurStyle->exts_transMask, ExtCurStyle->exts_transConn,
|
&ExtCurStyle->exts_deviceMask, ExtCurStyle->exts_deviceConn,
|
||||||
extUnInit, extTransFirst, extTransEach);
|
extUnInit, extTransFirst, extTransEach);
|
||||||
ExtResetTiles(def, extUnInit);
|
ExtResetTiles(def, extUnInit);
|
||||||
for (tl = transList; tl; tl = tl->treg_next)
|
for (tl = transList; tl; tl = tl->treg_next)
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ extern void ExtSetStyle();
|
||||||
extern void ExtPrintStyle();
|
extern void ExtPrintStyle();
|
||||||
extern void ExtCell();
|
extern void ExtCell();
|
||||||
|
|
||||||
|
|
||||||
#ifdef MAGIC_WRAPPER
|
#ifdef MAGIC_WRAPPER
|
||||||
extern bool ExtGetDevInfo();
|
extern bool ExtGetDevInfo();
|
||||||
extern bool ExtCompareStyle();
|
extern bool ExtCompareStyle();
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,19 @@ typedef int ResValue; /* Warning: in some places resistances are stored
|
||||||
* as ints. This is here for documentation only.
|
* 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 --------------------------- */
|
/* ------------------------ Parameter lists --------------------------- */
|
||||||
|
|
||||||
/* These lists keep track of what parameter names subcircuit definitions
|
/* These lists keep track of what parameter names subcircuit definitions
|
||||||
|
|
@ -483,6 +496,82 @@ typedef struct extkeep
|
||||||
char *exts_name;
|
char *exts_name;
|
||||||
} ExtKeep;
|
} 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.
|
* Parameters for the process being extracted.
|
||||||
* We try to use use integers here, rather than floats, to be nice to
|
* 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];
|
TileTypeBitMask exts_resistConn[NT];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Connectivity for determining transistors.
|
* Connectivity for determining devices.
|
||||||
* Each transistor type should connect only to itself.
|
* Each devices type should connect only to itself.
|
||||||
* Nothing else should connect to anything else.
|
* 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
|
* Set of types to be considered for extraction. Types not in
|
||||||
|
|
@ -580,6 +669,14 @@ typedef struct extstyle
|
||||||
float exts_height[NT];
|
float exts_height[NT];
|
||||||
float exts_thick[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
|
* Capacitance to substrate for each tile type, in units of
|
||||||
* attofarads per square lambda.
|
* attofarads per square lambda.
|
||||||
|
|
@ -779,65 +876,14 @@ typedef struct extstyle
|
||||||
*/
|
*/
|
||||||
TileTypeBitMask exts_sideEdges[NT];
|
TileTypeBitMask exts_sideEdges[NT];
|
||||||
|
|
||||||
/* Transistors */
|
/* Devices */
|
||||||
|
|
||||||
/* Name of each transistor type as output in .ext file */
|
/* Contains one for each type of device, zero for all other tile types */
|
||||||
char *exts_transName[NT];
|
TileTypeBitMask exts_deviceMask;
|
||||||
|
|
||||||
/* List of parameter names for each subcircuit type */
|
/* All information about a device goes in this record (see above) */
|
||||||
ParamList *exts_deviceParams[NT];
|
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
|
#ifdef ARIEL
|
||||||
TileTypeBitMask exts_subsTransistorTypes[NT];
|
TileTypeBitMask exts_subsTransistorTypes[NT];
|
||||||
#endif /* ARIEL */
|
#endif /* ARIEL */
|
||||||
|
|
@ -847,11 +893,16 @@ typedef struct extstyle
|
||||||
* types that connect to the substrate. Since for non-SOI
|
* types that connect to the substrate. Since for non-SOI
|
||||||
* processes, this generally is used to specify that space on
|
* processes, this generally is used to specify that space on
|
||||||
* the well plane is the substrate, the plane number for the
|
* 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;
|
char *exts_globSubstrateName;
|
||||||
TileTypeBitMask exts_globSubstrateTypes;
|
TileTypeBitMask exts_globSubstrateTypes;
|
||||||
int exts_globSubstratePlane;
|
int exts_globSubstratePlane;
|
||||||
|
TileTypeBitMask exts_globSubstrateShieldTypes;
|
||||||
|
|
||||||
/* Scaling */
|
/* Scaling */
|
||||||
/*
|
/*
|
||||||
|
|
@ -1024,6 +1075,7 @@ extern NodeRegion *extBasic();
|
||||||
extern NodeRegion *extFindNodes();
|
extern NodeRegion *extFindNodes();
|
||||||
extern ExtTree *extHierNewOne();
|
extern ExtTree *extHierNewOne();
|
||||||
extern int extNbrPushFunc();
|
extern int extNbrPushFunc();
|
||||||
|
extern TileType extGetDevType();
|
||||||
|
|
||||||
/* --------------------- Miscellaneous globals ------------------------ */
|
/* --------------------- Miscellaneous globals ------------------------ */
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,22 +40,22 @@ ${GR_HELPER_PROG}: ${GR_HELPER_SRCS}
|
||||||
${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ${GR_HELPER_SRCS} \
|
${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ${GR_HELPER_SRCS} \
|
||||||
-o ${GR_HELPER_PROG} ${LIBS}
|
-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
|
install-tcl: glyphs fonts
|
||||||
|
|
||||||
$(DESTDIR)${BINDIR}/${GR_HELPER_PROG}: ${GR_HELPER_PROG}
|
$(DESTDIR)${INSTALL_BINDIR}/${GR_HELPER_PROG}: ${GR_HELPER_PROG}
|
||||||
${RM} $(DESTDIR)${BINDIR}/${GR_HELPER_PROG}
|
${RM} $(DESTDIR)${INSTALL_BINDIR}/${GR_HELPER_PROG}
|
||||||
${CP} ${GR_HELPER_PROG} $(DESTDIR)${BINDIR}
|
${CP} ${GR_HELPER_PROG} $(DESTDIR)${INSTALL_BINDIR}
|
||||||
|
|
||||||
glyphs: ${GLYPHS}
|
glyphs: ${GLYPHS}
|
||||||
for i in ${GLYPHS}; do \
|
for i in ${GLYPHS}; do \
|
||||||
${RM} $(DESTDIR)${SYSDIR}/$$i; \
|
${RM} $(DESTDIR)${INSTALL_SYSDIR}/$$i; \
|
||||||
${CP} $$i $(DESTDIR)${SYSDIR}; done
|
${CP} $$i $(DESTDIR)${INSTALL_SYSDIR}; done
|
||||||
|
|
||||||
fonts: ${OUTLINE_FONTS}
|
fonts: ${OUTLINE_FONTS}
|
||||||
for i in ${OUTLINE_FONTS}; do \
|
for i in ${OUTLINE_FONTS}; do \
|
||||||
${RM} $(DESTDIR)${SYSDIR}/$$i; \
|
${RM} $(DESTDIR)${INSTALL_SYSDIR}/$$i; \
|
||||||
${CP} $$i $(DESTDIR)${SYSDIR}; done
|
${CP} $$i $(DESTDIR)${INSTALL_SYSDIR}; done
|
||||||
|
|
||||||
include ${MAGICDIR}/rules.mak
|
include ${MAGICDIR}/rules.mak
|
||||||
|
|
|
||||||
|
|
@ -1389,12 +1389,14 @@ W3DloadWindow(window, name)
|
||||||
CellDef *newEditDef;
|
CellDef *newEditDef;
|
||||||
CellUse *newEditUse;
|
CellUse *newEditUse;
|
||||||
Rect loadBox;
|
Rect loadBox;
|
||||||
|
bool dereference;
|
||||||
|
|
||||||
newEditDef = DBCellLookDef(name);
|
newEditDef = DBCellLookDef(name);
|
||||||
if (newEditDef == (CellDef *)NULL)
|
if (newEditDef == (CellDef *)NULL)
|
||||||
return FALSE;
|
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;
|
return FALSE;
|
||||||
|
|
||||||
DBReComputeBbox(newEditDef);
|
DBReComputeBbox(newEditDef);
|
||||||
|
|
|
||||||
|
|
@ -370,6 +370,9 @@ GrTCairoPlotSVG (char *filename, MagWindow *mw)
|
||||||
wind_context = tcairodata->context;
|
wind_context = tcairodata->context;
|
||||||
tcairodata->surface = (cairo_surface_t *)cairo_svg_surface_create(filename,
|
tcairodata->surface = (cairo_surface_t *)cairo_svg_surface_create(filename,
|
||||||
(double)screenw, (double)screenh);
|
(double)screenw, (double)screenh);
|
||||||
|
cairo_svg_surface_restrict_to_version(tcairodata->surface,
|
||||||
|
CAIRO_SVG_VERSION_1_2);
|
||||||
|
|
||||||
tcairodata->context = cairo_create(tcairodata->surface);
|
tcairodata->context = cairo_create(tcairodata->surface);
|
||||||
WindRedisplay(mw);
|
WindRedisplay(mw);
|
||||||
WindUpdate();
|
WindUpdate();
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,10 @@ magiclef${SHDLIB_EXT}: tcllef.o ${OBJS}
|
||||||
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} tcllef.o ${OBJS} \
|
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} tcllef.o ${OBJS} \
|
||||||
${EXTRA_LIBS} -lc ${LIBS}
|
${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}
|
$(DESTDIR)${INSTALL_TCLDIR}/magiclef${SHDLIB_EXT}: magiclef${SHDLIB_EXT}
|
||||||
${RM} $(DESTDIR)${TCLDIR}/magiclef${SHDLIB_EXT}
|
${RM} $(DESTDIR)${INSTALL_TCLDIR}/magiclef${SHDLIB_EXT}
|
||||||
${CP} magiclef${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/magiclef${SHDLIB_EXT}
|
${CP} magiclef${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/magiclef${SHDLIB_EXT}
|
||||||
|
|
||||||
include ${MAGICDIR}/rules.mak
|
include ${MAGICDIR}/rules.mak
|
||||||
|
|
|
||||||
145
lef/defRead.c
145
lef/defRead.c
|
|
@ -26,6 +26,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "tiles/tile.h"
|
#include "tiles/tile.h"
|
||||||
#include "utils/hash.h"
|
#include "utils/hash.h"
|
||||||
#include "utils/undo.h"
|
#include "utils/undo.h"
|
||||||
|
#include "utils/utils.h"
|
||||||
#include "database/database.h"
|
#include "database/database.h"
|
||||||
#include "windows/windows.h"
|
#include "windows/windows.h"
|
||||||
#include "dbwind/dbwind.h"
|
#include "dbwind/dbwind.h"
|
||||||
|
|
@ -73,11 +74,12 @@ enum def_netspecial_shape_keys {
|
||||||
DEF_SPECNET_SHAPE_DRCFILL};
|
DEF_SPECNET_SHAPE_DRCFILL};
|
||||||
|
|
||||||
char *
|
char *
|
||||||
DefAddRoutes(rootDef, f, oscale, special, defLayerMap)
|
DefAddRoutes(rootDef, f, oscale, special, netname, defLayerMap)
|
||||||
CellDef *rootDef; /* Cell to paint */
|
CellDef *rootDef; /* Cell to paint */
|
||||||
FILE *f; /* Input file */
|
FILE *f; /* Input file */
|
||||||
float oscale; /* Scale factor between LEF and magic units */
|
float oscale; /* Scale factor between LEF and magic units */
|
||||||
bool special; /* True if this section is SPECIALNETS */
|
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 */
|
LefMapping *defLayerMap; /* magic-to-lef layer mapping array */
|
||||||
{
|
{
|
||||||
char *token;
|
char *token;
|
||||||
|
|
@ -85,6 +87,7 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap)
|
||||||
Point refp; /* reference point */
|
Point refp; /* reference point */
|
||||||
bool valid = FALSE; /* is there a valid reference point? */
|
bool valid = FALSE; /* is there a valid reference point? */
|
||||||
bool initial = TRUE;
|
bool initial = TRUE;
|
||||||
|
bool labeled = TRUE;
|
||||||
Rect locarea;
|
Rect locarea;
|
||||||
int extend, lextend, hextend;
|
int extend, lextend, hextend;
|
||||||
float x, y, z, w;
|
float x, y, z, w;
|
||||||
|
|
@ -124,6 +127,8 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap)
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (netname != NULL) labeled = FALSE;
|
||||||
|
|
||||||
while (initial || (token = LefNextToken(f, TRUE)) != NULL)
|
while (initial || (token = LefNextToken(f, TRUE)) != NULL)
|
||||||
{
|
{
|
||||||
/* Get next point, token "NEW", or via name */
|
/* Get next point, token "NEW", or via name */
|
||||||
|
|
@ -605,6 +610,16 @@ endCoord:
|
||||||
/* paint */
|
/* paint */
|
||||||
DBPaint(rootDef, &routeTop->r_r, routeTop->r_type);
|
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) */
|
/* advance to next point and free record (1-delayed) */
|
||||||
freeMagic((char *)routeTop);
|
freeMagic((char *)routeTop);
|
||||||
routeTop = routeTop->r_next;
|
routeTop = routeTop->r_next;
|
||||||
|
|
@ -636,15 +651,17 @@ enum def_netprop_keys {
|
||||||
DEF_NETPROP_PROPERTY};
|
DEF_NETPROP_PROPERTY};
|
||||||
|
|
||||||
void
|
void
|
||||||
DefReadNets(f, rootDef, sname, oscale, special, total)
|
DefReadNets(f, rootDef, sname, oscale, special, dolabels, total)
|
||||||
FILE *f;
|
FILE *f;
|
||||||
CellDef *rootDef;
|
CellDef *rootDef;
|
||||||
char *sname;
|
char *sname;
|
||||||
float oscale;
|
float oscale;
|
||||||
bool special; /* True if this section is SPECIALNETS */
|
bool special; /* True if this section is SPECIALNETS */
|
||||||
|
bool dolabels; /* If true, create a label for each net */
|
||||||
int total;
|
int total;
|
||||||
{
|
{
|
||||||
char *token;
|
char *token;
|
||||||
|
char *netname = NULL;
|
||||||
int keyword, subkey;
|
int keyword, subkey;
|
||||||
int processed = 0;
|
int processed = 0;
|
||||||
LefMapping *defLayerMap;
|
LefMapping *defLayerMap;
|
||||||
|
|
@ -684,8 +701,8 @@ DefReadNets(f, rootDef, sname, oscale, special, total)
|
||||||
case DEF_NET_START:
|
case DEF_NET_START:
|
||||||
|
|
||||||
/* Get net name */
|
/* Get net name */
|
||||||
/* Presently, we ignore net names completely. */
|
|
||||||
token = LefNextToken(f, TRUE);
|
token = LefNextToken(f, TRUE);
|
||||||
|
if (dolabels) netname = StrDup((char **)NULL, token);
|
||||||
|
|
||||||
/* Update the record of the number of nets processed */
|
/* Update the record of the number of nets processed */
|
||||||
/* and spit out a message for every 5% finished. */
|
/* 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_FIXED:
|
||||||
case DEF_NETPROP_COVER:
|
case DEF_NETPROP_COVER:
|
||||||
token = DefAddRoutes(rootDef, f, oscale, special,
|
token = DefAddRoutes(rootDef, f, oscale, special,
|
||||||
defLayerMap);
|
netname, defLayerMap);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (dolabels) freeMagic(netname);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DEF_NET_END:
|
case DEF_NET_END:
|
||||||
|
|
@ -775,11 +793,12 @@ enum def_orient {DEF_NORTH, DEF_SOUTH, DEF_EAST, DEF_WEST,
|
||||||
DEF_FLIPPED_WEST};
|
DEF_FLIPPED_WEST};
|
||||||
|
|
||||||
int
|
int
|
||||||
DefReadLocation(use, f, oscale, tptr)
|
DefReadLocation(use, f, oscale, tptr, noplace)
|
||||||
CellUse *use;
|
CellUse *use;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
float oscale;
|
float oscale;
|
||||||
Transform *tptr;
|
Transform *tptr;
|
||||||
|
bool noplace;
|
||||||
{
|
{
|
||||||
Rect *r, tr, rect;
|
Rect *r, tr, rect;
|
||||||
int keyword;
|
int keyword;
|
||||||
|
|
@ -791,21 +810,32 @@ DefReadLocation(use, f, oscale, tptr)
|
||||||
"N", "S", "E", "W", "FN", "FS", "FE", "FW"
|
"N", "S", "E", "W", "FN", "FS", "FE", "FW"
|
||||||
};
|
};
|
||||||
|
|
||||||
token = LefNextToken(f, TRUE);
|
if (noplace)
|
||||||
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);
|
LefError(DEF_WARNING, "Unplaced component \"%s\" will be put at origin.\n",
|
||||||
return -1;
|
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 */
|
/* The standard transformations are all defined to rotate */
|
||||||
|
|
@ -1062,7 +1092,7 @@ DefReadPins(f, rootDef, sname, oscale, total)
|
||||||
break;
|
break;
|
||||||
case DEF_PINS_PROP_FIXED:
|
case DEF_PINS_PROP_FIXED:
|
||||||
case DEF_PINS_PROP_PLACED:
|
case DEF_PINS_PROP_PLACED:
|
||||||
DefReadLocation(NULL, f, oscale, &t);
|
DefReadLocation(NULL, f, oscale, &t, FALSE);
|
||||||
if (curlayer == -1)
|
if (curlayer == -1)
|
||||||
pending = TRUE;
|
pending = TRUE;
|
||||||
else
|
else
|
||||||
|
|
@ -1275,6 +1305,35 @@ DefReadVias(f, sname, oscale, total)
|
||||||
blayer = LefReadLayer(f, FALSE);
|
blayer = LefReadLayer(f, FALSE);
|
||||||
clayer = LefReadLayer(f, FALSE);
|
clayer = LefReadLayer(f, FALSE);
|
||||||
tlayer = 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;
|
generated = TRUE;
|
||||||
break;
|
break;
|
||||||
case DEF_VIAS_PROP_CUTSPACING:
|
case DEF_VIAS_PROP_CUTSPACING:
|
||||||
|
|
@ -1450,18 +1509,22 @@ DefReadComponents(f, rootDef, sname, oscale, total)
|
||||||
|
|
||||||
/* Does use name contain brackets? If so, this can */
|
/* Does use name contain brackets? If so, this can */
|
||||||
/* interfere with magic's use of arrays. */
|
/* 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 */
|
dptr = strchr(usename, '[');
|
||||||
/* from the arrays being parsed by ExtFlat when */
|
if (dptr != NULL) {
|
||||||
/* doing ext2spice. */
|
*dptr = '_';
|
||||||
|
dptr = strchr(dptr + 1, ']');
|
||||||
dptr = strchr(usename, '[');
|
if (dptr != NULL) *dptr = '_';
|
||||||
if (dptr != NULL) {
|
}
|
||||||
*dptr = '_';
|
*/
|
||||||
dptr = strchr(dptr + 1, ']');
|
|
||||||
if (dptr != NULL) *dptr = '_';
|
|
||||||
}
|
|
||||||
|
|
||||||
token = LefNextToken(f, TRUE);
|
token = LefNextToken(f, TRUE);
|
||||||
|
|
||||||
|
|
@ -1471,11 +1534,14 @@ DefReadComponents(f, rootDef, sname, oscale, total)
|
||||||
|
|
||||||
if (defMacro == (CellDef *)NULL)
|
if (defMacro == (CellDef *)NULL)
|
||||||
{
|
{
|
||||||
|
bool dereference;
|
||||||
|
|
||||||
/* Before giving up, assume that this cell has a */
|
/* Before giving up, assume that this cell has a */
|
||||||
/* magic .mag layout file. */
|
/* magic .mag layout file. */
|
||||||
defMacro = DBCellNewDef(token, (char *)NULL);
|
defMacro = DBCellNewDef(token, (char *)NULL);
|
||||||
defMacro->cd_flags &= ~CDNOTFOUND;
|
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 "
|
LefError(DEF_ERROR, "Cell %s is not defined. Maybe you "
|
||||||
"have not read the corresponding LEF file?\n",
|
"have not read the corresponding LEF file?\n",
|
||||||
|
|
@ -1518,10 +1584,12 @@ DefReadComponents(f, rootDef, sname, oscale, total)
|
||||||
switch (subkey)
|
switch (subkey)
|
||||||
{
|
{
|
||||||
case DEF_PROP_PLACED:
|
case DEF_PROP_PLACED:
|
||||||
case DEF_PROP_UNPLACED:
|
|
||||||
case DEF_PROP_FIXED:
|
case DEF_PROP_FIXED:
|
||||||
case DEF_PROP_COVER:
|
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;
|
break;
|
||||||
case DEF_PROP_SOURCE:
|
case DEF_PROP_SOURCE:
|
||||||
case DEF_PROP_WEIGHT:
|
case DEF_PROP_WEIGHT:
|
||||||
|
|
@ -1598,8 +1666,9 @@ enum def_sections {DEF_VERSION = 0, DEF_NAMESCASESENSITIVE,
|
||||||
DEF_END};
|
DEF_END};
|
||||||
|
|
||||||
void
|
void
|
||||||
DefRead(inName)
|
DefRead(inName, dolabels)
|
||||||
char *inName;
|
char *inName;
|
||||||
|
bool dolabels;
|
||||||
{
|
{
|
||||||
CellDef *rootDef;
|
CellDef *rootDef;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
@ -1775,13 +1844,15 @@ DefRead(inName)
|
||||||
token = LefNextToken(f, TRUE);
|
token = LefNextToken(f, TRUE);
|
||||||
if (sscanf(token, "%d", &total) != 1) total = 0;
|
if (sscanf(token, "%d", &total) != 1) total = 0;
|
||||||
LefEndStatement(f);
|
LefEndStatement(f);
|
||||||
DefReadNets(f, rootDef, sections[DEF_SPECIALNETS], oscale, TRUE, total);
|
DefReadNets(f, rootDef, sections[DEF_SPECIALNETS], oscale, TRUE,
|
||||||
|
dolabels, total);
|
||||||
break;
|
break;
|
||||||
case DEF_NETS:
|
case DEF_NETS:
|
||||||
token = LefNextToken(f, TRUE);
|
token = LefNextToken(f, TRUE);
|
||||||
if (sscanf(token, "%d", &total) != 1) total = 0;
|
if (sscanf(token, "%d", &total) != 1) total = 0;
|
||||||
LefEndStatement(f);
|
LefEndStatement(f);
|
||||||
DefReadNets(f, rootDef, sections[DEF_NETS], oscale, FALSE, total);
|
DefReadNets(f, rootDef, sections[DEF_NETS], oscale, FALSE,
|
||||||
|
dolabels, total);
|
||||||
break;
|
break;
|
||||||
case DEF_IOTIMINGS:
|
case DEF_IOTIMINGS:
|
||||||
LefSkipSection(f, sections[DEF_IOTIMINGS]);
|
LefSkipSection(f, sections[DEF_IOTIMINGS]);
|
||||||
|
|
|
||||||
46
lef/lefCmd.c
46
lef/lefCmd.c
|
|
@ -87,6 +87,15 @@ CmdLef(w, cmd)
|
||||||
* the macro other than pin area
|
* the macro other than pin area
|
||||||
* immediately surrounding labels.
|
* 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[] =
|
static char *cmdLefOption[] =
|
||||||
{
|
{
|
||||||
|
|
@ -95,7 +104,9 @@ CmdLef(w, cmd)
|
||||||
"write [filename] [-tech] write LEF for current cell\n"
|
"write [filename] [-tech] write LEF for current cell\n"
|
||||||
" write [filename] -hide hide all details other than ports",
|
" write [filename] -hide hide all details other than ports",
|
||||||
"writeall write all cells including the top-level cell\n"
|
"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",
|
"help print this help information",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
@ -103,7 +114,8 @@ CmdLef(w, cmd)
|
||||||
static char *cmdDefOption[] =
|
static char *cmdDefOption[] =
|
||||||
{
|
{
|
||||||
"read [filename] read a DEF file filename[.def]",
|
"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"
|
"writeall (use \"flatten -nosubckt\" + \"def"
|
||||||
" write\" instead)",
|
" write\" instead)",
|
||||||
"help print this help information",
|
"help print this help information",
|
||||||
|
|
@ -151,22 +163,32 @@ CmdLef(w, cmd)
|
||||||
switch (option)
|
switch (option)
|
||||||
{
|
{
|
||||||
case LEF_READ:
|
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 (*(cmd->tx_argv[i]) == '-')
|
||||||
if (!strncmp(cmd->tx_argv[3], "-import", 7))
|
{
|
||||||
|
if (!strncmp(cmd->tx_argv[i], "-import", 7))
|
||||||
lefImport = TRUE;
|
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];
|
namep = cmd->tx_argv[2];
|
||||||
if (is_lef)
|
if (is_lef)
|
||||||
LefRead(namep, lefImport);
|
LefRead(namep, lefImport);
|
||||||
else
|
else
|
||||||
DefRead(namep);
|
DefRead(namep, defLabelNets);
|
||||||
break;
|
break;
|
||||||
case LEF_WRITEALL:
|
case LEF_WRITEALL:
|
||||||
if (!is_lef)
|
if (!is_lef)
|
||||||
|
|
@ -184,11 +206,15 @@ CmdLef(w, cmd)
|
||||||
lefTopCell = FALSE;
|
lefTopCell = FALSE;
|
||||||
else if (!strncmp(cmd->tx_argv[i], "-tech", 5))
|
else if (!strncmp(cmd->tx_argv[i], "-tech", 5))
|
||||||
lefTech = TRUE;
|
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;
|
||||||
}
|
}
|
||||||
else goto wrongNumArgs;
|
else goto wrongNumArgs;
|
||||||
}
|
}
|
||||||
LefWriteAll(selectedUse, lefTopCell, lefTech);
|
LefWriteAll(selectedUse, lefTopCell, lefTech, lefHide, recurse);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LEF_WRITE:
|
case LEF_WRITE:
|
||||||
|
|
|
||||||
|
|
@ -1212,18 +1212,21 @@ LefReadGeometry(lefMacro, f, oscale, do_list)
|
||||||
*
|
*
|
||||||
* Side Effects:
|
* Side Effects:
|
||||||
* Reads input from file f;
|
* 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
|
void
|
||||||
LefReadPort(lefMacro, f, pinName, pinNum, pinDir, pinUse, oscale)
|
LefReadPort(lefMacro, f, pinName, pinNum, pinDir, pinUse, oscale, lanno)
|
||||||
CellDef *lefMacro;
|
CellDef *lefMacro;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char *pinName;
|
char *pinName;
|
||||||
int pinNum, pinDir, pinUse;
|
int pinNum, pinDir, pinUse;
|
||||||
float oscale;
|
float oscale;
|
||||||
|
Label *lanno;
|
||||||
{
|
{
|
||||||
Label *newlab;
|
Label *newlab;
|
||||||
LinkedRect *rectList;
|
LinkedRect *rectList;
|
||||||
|
|
@ -1235,7 +1238,15 @@ LefReadPort(lefMacro, f, pinName, pinNum, pinDir, pinUse, oscale)
|
||||||
if (pinNum >= 0)
|
if (pinNum >= 0)
|
||||||
{
|
{
|
||||||
/* Label this area */
|
/* 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 */
|
/* 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");
|
LefError(LEF_ERROR, "Internal error: No labels in cell!\n");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newlab = lefMacro->cd_lastLabel;
|
newlab = (lanno != NULL) ? lanno : lefMacro->cd_lastLabel;
|
||||||
if (strcmp(newlab->lab_text, pinName))
|
if (strcmp(newlab->lab_text, pinName))
|
||||||
LefError(LEF_ERROR, "Internal error: Can't find the label!\n");
|
LefError(LEF_ERROR, "Internal error: Can't find the label!\n");
|
||||||
else /* Make this a port */
|
else /* Make this a port */
|
||||||
newlab->lab_flags = pinNum | pinUse | pinDir | PORT_DIR_MASK;
|
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);
|
freeMagic((char *)rectList);
|
||||||
|
|
@ -1383,24 +1397,43 @@ LefReadPin(lefMacro, f, pinname, pinNum, oscale, is_imported)
|
||||||
case LEF_PORT:
|
case LEF_PORT:
|
||||||
if (is_imported)
|
if (is_imported)
|
||||||
{
|
{
|
||||||
|
bool needRect = TRUE;
|
||||||
Label *lab;
|
Label *lab;
|
||||||
|
|
||||||
LefSkipSection(f, NULL);
|
|
||||||
/* Skip the port geometry but find the pin name and */
|
/* Skip the port geometry but find the pin name and */
|
||||||
/* annotate with the use and direction. Note that */
|
/* annotate with the use and direction. Note that */
|
||||||
/* there may be multiple instances of the label. */
|
/* 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)
|
for (lab = lefMacro->cd_labels; lab; lab = lab->lab_next)
|
||||||
{
|
{
|
||||||
if (!strcmp(lab->lab_text, pinname))
|
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);
|
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
|
else
|
||||||
LefReadPort(lefMacro, f, pinname, pinNum, pinDir, pinUse, oscale);
|
LefReadPort(lefMacro, f, pinname, pinNum, pinDir, pinUse, oscale,
|
||||||
|
NULL);
|
||||||
break;
|
break;
|
||||||
case LEF_CAPACITANCE:
|
case LEF_CAPACITANCE:
|
||||||
case LEF_ANTENNADIFF:
|
case LEF_ANTENNADIFF:
|
||||||
|
|
@ -1737,10 +1770,18 @@ origin_error:
|
||||||
*
|
*
|
||||||
* For LEF contact types matching magic contact types, size the
|
* For LEF contact types matching magic contact types, size the
|
||||||
* LEF contact cut to cover the minimum rectangle in the other
|
* LEF contact cut to cover the minimum rectangle in the other
|
||||||
* layers that satisfies the CIF/GDS contact generation. Use
|
* layers that satisfies the CIF/GDS contact generation.
|
||||||
* the "cifinput" style to determine how much the via layer
|
*
|
||||||
* needs to grow to make a contact area. If the "cifinput"
|
* NOTE: If a "cifinput" style is defined, then the via
|
||||||
* style is not defined, then determine rules from "cifoutput".
|
* 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;
|
Rect *currect;
|
||||||
lefLayer *lefl;
|
lefLayer *lefl;
|
||||||
{
|
{
|
||||||
if (DBIsContact(curlayer) && cifCurReadStyle != NULL)
|
/* To be completed: This should be deprecated by moving the entire */
|
||||||
{
|
/* LEF and DEF read routines to use the cifinput style. */
|
||||||
int growSize;
|
|
||||||
|
|
||||||
/* Get the amount (in magic units) that the layer needs to */
|
if (DBIsContact(curlayer) && CIFCurStyle != NULL)
|
||||||
/* 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)
|
|
||||||
{
|
{
|
||||||
int edgeSize = 0, contSize, halfSize;
|
int edgeSize = 0, contSize, halfSize;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -270,7 +270,7 @@ LefTechLine(sectionName, argc, argv)
|
||||||
isContact = DBIsContact(mtype);
|
isContact = DBIsContact(mtype);
|
||||||
if (option == LEFTECH_LAYER)
|
if (option == LEFTECH_LAYER)
|
||||||
option = (isContact) ? LEFTECH_CUT : LEFTECH_ROUTE;
|
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",
|
TechError("Attempt to define cut type %s as %s.\n",
|
||||||
DBTypeLongNameTbl[mtype], keywords[option]);
|
DBTypeLongNameTbl[mtype], keywords[option]);
|
||||||
else if (!isContact && (option == LEFTECH_CUT || option == LEFTECH_CONTACT))
|
else if (!isContact && (option == LEFTECH_CUT || option == LEFTECH_CONTACT))
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,8 @@ lefFileOpen(def, file, suffix, mode, prealfile)
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
char namebuf[512], *name, *endp, *ends;
|
char namebuf[512], *name, *endp, *ends;
|
||||||
|
char *locsuffix;
|
||||||
|
char *pptr;
|
||||||
int len;
|
int len;
|
||||||
FILE *rfile;
|
FILE *rfile;
|
||||||
|
|
||||||
|
|
@ -108,21 +110,26 @@ lefFileOpen(def, file, suffix, mode, prealfile)
|
||||||
|
|
||||||
if (endp = strrchr(ends, '.'))
|
if (endp = strrchr(ends, '.'))
|
||||||
{
|
{
|
||||||
if (!strcmp(endp, suffix))
|
if (strcmp(endp, suffix))
|
||||||
{
|
{
|
||||||
len = endp - name;
|
len = endp - name;
|
||||||
if (len > sizeof namebuf - 1) len = sizeof namebuf - 1;
|
if (len > sizeof namebuf - 1) len = sizeof namebuf - 1;
|
||||||
(void) strncpy(namebuf, name, len);
|
(void) strncpy(namebuf, name, len);
|
||||||
namebuf[len] = '\0';
|
namebuf[len] = '\0';
|
||||||
name = namebuf;
|
name = namebuf;
|
||||||
|
locsuffix = suffix;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
locsuffix = NULL;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
locsuffix = suffix;
|
||||||
|
|
||||||
/* Try once as-is, and if this fails, try stripping any leading */
|
/* Try once as-is, and if this fails, try stripping any leading */
|
||||||
/* path information in case cell is in a read-only directory (mode */
|
/* path information in case cell is in a read-only directory (mode */
|
||||||
/* "read" only, and if def is non-NULL). */
|
/* "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;
|
return rfile;
|
||||||
|
|
||||||
if (def)
|
if (def)
|
||||||
|
|
@ -634,7 +641,7 @@ lefWriteMacro(def, f, scale, hide)
|
||||||
{
|
{
|
||||||
bool propfound;
|
bool propfound;
|
||||||
char *propvalue, *class = NULL;
|
char *propvalue, *class = NULL;
|
||||||
Label *lab;
|
Label *lab, *tlab;
|
||||||
Rect boundary, labr;
|
Rect boundary, labr;
|
||||||
SearchContext scx;
|
SearchContext scx;
|
||||||
CellDef *lefFlatDef;
|
CellDef *lefFlatDef;
|
||||||
|
|
@ -772,6 +779,20 @@ lefWriteMacro(def, f, scale, hide)
|
||||||
else
|
else
|
||||||
boundary = def->cd_bbox;
|
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 */
|
/* Write position and size information */
|
||||||
|
|
||||||
fprintf(f, " ORIGIN %.4f %.4f ;\n",
|
fprintf(f, " ORIGIN %.4f %.4f ;\n",
|
||||||
|
|
@ -927,7 +948,18 @@ lefWriteMacro(def, f, scale, hide)
|
||||||
SelectClear();
|
SelectClear();
|
||||||
|
|
||||||
if (hide)
|
if (hide)
|
||||||
|
{
|
||||||
SelectChunk(&scx, lab->lab_type, 0, NULL, FALSE);
|
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
|
else
|
||||||
SelectNet(&scx, lab->lab_type, 0, NULL, FALSE);
|
SelectNet(&scx, lab->lab_type, 0, NULL, FALSE);
|
||||||
|
|
||||||
|
|
@ -964,15 +996,21 @@ lefWriteMacro(def, f, scale, hide)
|
||||||
|
|
||||||
if (maxport >= 0)
|
if (maxport >= 0)
|
||||||
{
|
{
|
||||||
/* Sanity check to see if port number is a duplicate */
|
/* Sanity check to see if port number is a duplicate. ONLY */
|
||||||
for (lab = lab->lab_next; lab != NULL; lab = lab->lab_next)
|
/* 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 (tlab->lab_flags & PORT_DIR_MASK)
|
||||||
if ((lab->lab_flags & PORT_NUM_MASK) == idx)
|
if ((tlab->lab_flags & PORT_NUM_MASK) == idx)
|
||||||
{
|
if (strcmp(lab->lab_text, lab->lab_text))
|
||||||
TxError("Port index %d is used more than once\n", idx);
|
{
|
||||||
idx--;
|
TxError("Index %d is used for ports \"%s\" and \"%s\"\n",
|
||||||
}
|
idx, lab->lab_text, tlab->lab_text);
|
||||||
|
idx--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1030,6 +1068,7 @@ lefWriteMacro(def, f, scale, hide)
|
||||||
scx.scx_area = labr;
|
scx.scx_area = labr;
|
||||||
SelectClear();
|
SelectClear();
|
||||||
SelectChunk(&scx, lab->lab_type, 0, &carea, FALSE);
|
SelectChunk(&scx, lab->lab_type, 0, &carea, FALSE);
|
||||||
|
if (GEO_RECTNULL(&carea)) carea = lab->lab_rect;
|
||||||
lspace = DRCGetDefaultLayerSpacing(lab->lab_type, lab->lab_type);
|
lspace = DRCGetDefaultLayerSpacing(lab->lab_type, lab->lab_type);
|
||||||
carea.r_xbot -= lspace;
|
carea.r_xbot -= lspace;
|
||||||
carea.r_ybot -= lspace;
|
carea.r_ybot -= lspace;
|
||||||
|
|
@ -1094,10 +1133,12 @@ lefWriteMacro(def, f, scale, hide)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
LefWriteAll(rootUse, writeTopCell, lefTech)
|
LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, recurse)
|
||||||
CellUse *rootUse;
|
CellUse *rootUse;
|
||||||
bool writeTopCell;
|
bool writeTopCell;
|
||||||
bool lefTech;
|
bool lefTech;
|
||||||
|
bool lefHide;
|
||||||
|
bool recurse;
|
||||||
{
|
{
|
||||||
CellDef *def, *rootdef;
|
CellDef *def, *rootdef;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
@ -1116,8 +1157,12 @@ LefWriteAll(rootUse, writeTopCell, lefTech)
|
||||||
(void) DBCellSrDefs(0, lefDefInitFunc, (ClientData) 0);
|
(void) DBCellSrDefs(0, lefDefInitFunc, (ClientData) 0);
|
||||||
|
|
||||||
/* Recursively visit all defs in the tree and push on stack */
|
/* 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);
|
lefDefStack = StackNew(100);
|
||||||
(void) lefDefPushFunc(rootUse);
|
if (writeTopCell)
|
||||||
|
lefDefPushFunc(rootUse, (bool *)NULL);
|
||||||
|
DBCellEnum(rootUse->cu_def, lefDefPushFunc, (ClientData)&recurse);
|
||||||
|
|
||||||
/* Open the file for output */
|
/* Open the file for output */
|
||||||
|
|
||||||
|
|
@ -1146,8 +1191,7 @@ LefWriteAll(rootUse, writeTopCell, lefTech)
|
||||||
{
|
{
|
||||||
def->cd_client = (ClientData) 0;
|
def->cd_client = (ClientData) 0;
|
||||||
if (!SigInterruptPending)
|
if (!SigInterruptPending)
|
||||||
if ((writeTopCell == TRUE) || (def != rootdef))
|
lefWriteMacro(def, f, scale, lefHide);
|
||||||
lefWriteMacro(def, f, scale);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End the LEF file */
|
/* End the LEF file */
|
||||||
|
|
@ -1178,8 +1222,9 @@ lefDefInitFunc(def)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
lefDefPushFunc(use)
|
lefDefPushFunc(use, recurse)
|
||||||
CellUse *use;
|
CellUse *use;
|
||||||
|
bool *recurse;
|
||||||
{
|
{
|
||||||
CellDef *def = use->cu_def;
|
CellDef *def = use->cu_def;
|
||||||
|
|
||||||
|
|
@ -1188,7 +1233,8 @@ lefDefPushFunc(use)
|
||||||
|
|
||||||
def->cd_client = (ClientData) 1;
|
def->cd_client = (ClientData) 1;
|
||||||
StackPush((ClientData) def, lefDefStack);
|
StackPush((ClientData) def, lefDefStack);
|
||||||
(void) DBCellEnum(def, lefDefPushFunc, (ClientData) 0);
|
if (recurse && (*recurse))
|
||||||
|
(void) DBCellEnum(def, lefDefPushFunc, (ClientData)recurse);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,11 @@ SCMSRC = default.scm box.scm label.scm draw.scm drc.scm \
|
||||||
|
|
||||||
include ${MAGICDIR}/defs.mak
|
include ${MAGICDIR}/defs.mak
|
||||||
|
|
||||||
INST_SCMSRC = ${SCMSRC:%=$(DESTDIR)${SCMDIR}/%}
|
INST_SCMSRC = ${SCMSRC:%=$(DESTDIR)${INSTALL_SCMDIR}/%}
|
||||||
|
|
||||||
install: ${INST_SCMSRC}
|
install: ${INST_SCMSRC}
|
||||||
|
|
||||||
$(DESTDIR)${SCMDIR}/%: scm/%
|
$(DESTDIR)${SCMDIR}/%: scm/%
|
||||||
${CP} scm/$* $(DESTDIR)$(SCMDIR)/$*
|
${CP} scm/$* $(DESTDIR)$(INSTALL_SCMDIR)/$*
|
||||||
|
|
||||||
include ${MAGICDIR}/rules.mak
|
include ${MAGICDIR}/rules.mak
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ EXTRA_LIBS = ${MAGICDIR}/bplane/libbplane.o \
|
||||||
${MAGICDIR}/utils/libutils.o \
|
${MAGICDIR}/utils/libutils.o \
|
||||||
${MAIN_EXTRA_LIBS}
|
${MAIN_EXTRA_LIBS}
|
||||||
|
|
||||||
BITMAPS = up.xbm down.xbm left.xbm right.xbm zoom.xbm lock.xbm
|
BITMAPS = up.gif down.gif left.gif right.gif zoom.gif lock.xbm
|
||||||
DEST_XBM = $(BITMAPS:%=$(DESTDIR)${TCLDIR}/bitmaps/%)
|
DEST_XBM = $(BITMAPS:%=$(DESTDIR)${INSTALL_TCLDIR}/bitmaps/%)
|
||||||
|
|
||||||
DFLAGS += -DMAGIC_DATE="\"`date`\"" -DCAD_DIR="${LIBDIR}"
|
DFLAGS += -DMAGIC_DATE="\"`date`\"" -DCAD_DIR="${LIBDIR}"
|
||||||
LIBS += ${GR_LIBS} ${READLINE_LIBS} -lm ${LD_EXTRA_LIBS} \
|
LIBS += ${GR_LIBS} ${READLINE_LIBS} -lm ${LD_EXTRA_LIBS} \
|
||||||
|
|
@ -49,32 +49,32 @@ tclmagic${SHDLIB_EXT}: ${EXTRA_LIBS}
|
||||||
-lc ${LIBS} ${LIB_SPECS} ${LDFLAGS}
|
-lc ${LIBS} ${LIB_SPECS} ${LDFLAGS}
|
||||||
|
|
||||||
proto.magicrc: proto.magicrc.in
|
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 \
|
install: $(DESTDIR)${INSTALL_BINDIR}/${MODULE}${EXEEXT} $(DESTDIR)${INSTALL_SYSDIR}/.magicrc \
|
||||||
$(DESTDIR)${SYSDIR}/magicps.pro
|
$(DESTDIR)${INSTALL_SYSDIR}/magicps.pro
|
||||||
|
|
||||||
install-tcl: $(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT} $(DESTDIR)${SYSDIR}/.magicrc \
|
install-tcl: $(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT} $(DESTDIR)${INSTALL_SYSDIR}/.magicrc \
|
||||||
$(DESTDIR)${SYSDIR}/.initrc $(DESTDIR)${SYSDIR}/magicps.pro ${DEST_XBM}
|
$(DESTDIR)${INSTALL_SYSDIR}/.initrc $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro ${DEST_XBM}
|
||||||
|
|
||||||
$(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT}: tclmagic${SHDLIB_EXT}
|
$(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT}: tclmagic${SHDLIB_EXT}
|
||||||
${RM} $(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT}
|
${RM} $(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT}
|
||||||
${CP} tclmagic${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT}
|
${CP} tclmagic${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT}
|
||||||
|
|
||||||
$(DESTDIR)${TCLDIR}/bitmaps/%: bitmaps/%
|
$(DESTDIR)${INSTALL_TCLDIR}/bitmaps/%: bitmaps/%
|
||||||
${RM} $(DESTDIR)${TCLDIR}/bitmaps/$*
|
${RM} $(DESTDIR)${INSTALL_TCLDIR}/bitmaps/$*
|
||||||
${CP} bitmaps/$* $(DESTDIR)${TCLDIR}/bitmaps/$*
|
${CP} bitmaps/$* $(DESTDIR)${INSTALL_TCLDIR}/bitmaps/$*
|
||||||
|
|
||||||
$(DESTDIR)${SYSDIR}/.magicrc: proto.magicrc
|
$(DESTDIR)${INSTALL_SYSDIR}/.magicrc: proto.magicrc
|
||||||
${RM} $(DESTDIR)${SYSDIR}/.magicrc
|
${RM} $(DESTDIR)${INSTALL_SYSDIR}/.magicrc
|
||||||
${CP} proto.magicrc $(DESTDIR)${SYSDIR}/.magicrc
|
${CP} proto.magicrc $(DESTDIR)${INSTALL_SYSDIR}/.magicrc
|
||||||
|
|
||||||
$(DESTDIR)${SYSDIR}/.initrc: proto.initrc
|
$(DESTDIR)${INSTALL_SYSDIR}/.initrc: proto.initrc
|
||||||
${RM} $(DESTDIR)${SYSDIR}/.initrc
|
${RM} $(DESTDIR)${INSTALL_SYSDIR}/.initrc
|
||||||
${CP} proto.initrc $(DESTDIR)${SYSDIR}/.initrc
|
${CP} proto.initrc $(DESTDIR)${INSTALL_SYSDIR}/.initrc
|
||||||
|
|
||||||
$(DESTDIR)${SYSDIR}/magicps.pro: magicps.pro
|
$(DESTDIR)${INSTALL_SYSDIR}/magicps.pro: magicps.pro
|
||||||
${RM} $(DESTDIR)${SYSDIR}/magicps.pro
|
${RM} $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro
|
||||||
${CP} magicps.pro $(DESTDIR)${SYSDIR}/magicps.pro
|
${CP} magicps.pro $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro
|
||||||
|
|
||||||
include ${MAGICDIR}/rules.mak
|
include ${MAGICDIR}/rules.mak
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 103 B |
Binary file not shown.
|
After Width: | Height: | Size: 103 B |
Binary file not shown.
|
After Width: | Height: | Size: 102 B |
Binary file not shown.
|
After Width: | Height: | Size: 102 B |
Binary file not shown.
|
After Width: | Height: | Size: 103 B |
|
|
@ -15,7 +15,7 @@ tcl-main:
|
||||||
|
|
||||||
main: net2ir
|
main: net2ir
|
||||||
|
|
||||||
install: $(DESTDIR)${BINDIR}/${MODULE}${EXEEXT}
|
install: $(DESTDIR)${INSTALL_BINDIR}/${MODULE}${EXEEXT}
|
||||||
|
|
||||||
install-tcl:
|
install-tcl:
|
||||||
echo "Nothing to do here"
|
echo "Nothing to do here"
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,10 @@ tclplot${SHDLIB_EXT}: tclplot.o ${OBJS}
|
||||||
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} tclplot.o ${OBJS} \
|
${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} tclplot.o ${OBJS} \
|
||||||
${EXTRA_LIBS} -lc ${LIBS}
|
${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}
|
$(DESTDIR)${INSTALL_TCLDIR}/tclplot${SHDLIB_EXT}: tclplot${SHDLIB_EXT}
|
||||||
${RM} $(DESTDIR)${TCLDIR}/tclplot${SHDLIB_EXT}
|
${RM} $(DESTDIR)${INSTALL_TCLDIR}/tclplot${SHDLIB_EXT}
|
||||||
${CP} tclplot${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/tclplot${SHDLIB_EXT}
|
${CP} tclplot${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/tclplot${SHDLIB_EXT}
|
||||||
|
|
||||||
include ${MAGICDIR}/rules.mak
|
include ${MAGICDIR}/rules.mak
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ ResMakeRes.o: ResMakeRes.c ../utils/magic.h ../utils/geometry.h \
|
||||||
../bplane/bplaneInt.h ../utils/malloc.h ../textio/textio.h \
|
../bplane/bplaneInt.h ../utils/malloc.h ../textio/textio.h \
|
||||||
../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \
|
../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \
|
||||||
../windows/windows.h ../dbwind/dbwind.h ../utils/tech.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 \
|
ResSimple.o: ResSimple.c ../utils/magic.h ../utils/geometry.h \
|
||||||
../utils/geofast.h ../tiles/tile.h ../utils/hash.h ../utils/heap.h \
|
../utils/geofast.h ../tiles/tile.h ../utils/hash.h ../utils/heap.h \
|
||||||
../database/database.h ../bplane/bplane.h ../bplane/bpOpaque.h \
|
../database/database.h ../bplane/bplane.h ../bplane/bpOpaque.h \
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
#include "textio/txcommands.h"
|
#include "textio/txcommands.h"
|
||||||
#include "resis/resis.h"
|
#include "resis/resis.h"
|
||||||
|
|
||||||
int resSubTranFunc();
|
int resSubDevFunc();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*--------------------------------------------------------------------------
|
*--------------------------------------------------------------------------
|
||||||
|
|
@ -113,13 +113,13 @@ resAllPortNodes(tile, list)
|
||||||
*--------------------------------------------------------------------------
|
*--------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* ResEachTile--for each tile, make a list of all possible current sources/
|
* 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.
|
* list is made, calculate the resistor nextwork for the tile.
|
||||||
*
|
*
|
||||||
* Results: returns TRUE or FALSE depending on whether a node was
|
* Results: returns TRUE or FALSE depending on whether a node was
|
||||||
* involved in a merge.
|
* 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;
|
bool merged;
|
||||||
tElement *tcell;
|
tElement *tcell;
|
||||||
tileJunk *tstructs= (tileJunk *)(tile->ti_client);
|
tileJunk *tstructs= (tileJunk *)(tile->ti_client);
|
||||||
|
ExtDevice *devptr;
|
||||||
|
|
||||||
ResTileCount++;
|
ResTileCount++;
|
||||||
|
|
||||||
|
|
@ -165,24 +166,24 @@ ResEachTile(tile, startpoint)
|
||||||
resNodeIsPort(resptr, x, y, tile);
|
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
|
* The device is put in the center of the tile. This is fine
|
||||||
* for single tile transistors, but not as good for multiple ones.
|
* 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 x = (LEFT(tile) + RIGHT(tile)) >> 1;
|
||||||
int y = (TOP(tile) + BOTTOM(tile)) >> 1;
|
int y = (TOP(tile) + BOTTOM(tile)) >> 1;
|
||||||
|
|
||||||
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
||||||
tstructs->transistorList->rt_gate = resptr;
|
tstructs->deviceList->rd_fet_gate = resptr;
|
||||||
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
|
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
|
||||||
tcell->te_thist = tstructs->transistorList;
|
tcell->te_thist = tstructs->deviceList;
|
||||||
tcell->te_nextt = NULL;
|
tcell->te_nextt = NULL;
|
||||||
|
|
||||||
InitializeNode(resptr, x, y, RES_NODE_JUNCTION);
|
InitializeNode(resptr, x, y, RES_NODE_JUNCTION);
|
||||||
|
|
@ -219,7 +220,7 @@ ResEachTile(tile, startpoint)
|
||||||
{
|
{
|
||||||
(void)DBSrPaintArea((Tile *) NULL,
|
(void)DBSrPaintArea((Tile *) NULL,
|
||||||
ResUse->cu_def->cd_planes[pNum],
|
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))
|
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp))
|
||||||
{
|
{
|
||||||
t2 = TiGetRightType(tp);
|
t2 = TiGetRightType(tp);
|
||||||
if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) &&
|
devptr = ExtCurStyle->exts_device[t2];
|
||||||
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1))
|
if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) &&
|
||||||
/* found transistor */
|
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1))
|
||||||
|
/* found device */
|
||||||
{
|
{
|
||||||
xj = LEFT(tile);
|
xj = LEFT(tile);
|
||||||
yj = (TOP(tp) + BOTTOM(tp)) >> 1;
|
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)
|
if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2)
|
||||||
/* tile is junction */
|
/* tile is junction */
|
||||||
|
|
@ -272,13 +274,14 @@ ResEachTile(tile, startpoint)
|
||||||
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp))
|
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp))
|
||||||
{
|
{
|
||||||
t2 = TiGetLeftType(tp);
|
t2 = TiGetLeftType(tp);
|
||||||
if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) &&
|
devptr = ExtCurStyle->exts_device[t2];
|
||||||
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1))
|
if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) &&
|
||||||
/* found transistor */
|
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1))
|
||||||
|
/* found device */
|
||||||
{
|
{
|
||||||
xj = RIGHT(tile);
|
xj = RIGHT(tile);
|
||||||
yj = (TOP(tp)+BOTTOM(tp))>>1;
|
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)
|
if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1], t2)
|
||||||
/* tile is junction */
|
/* tile is junction */
|
||||||
|
|
@ -294,13 +297,14 @@ ResEachTile(tile, startpoint)
|
||||||
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp))
|
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp))
|
||||||
{
|
{
|
||||||
t2 = TiGetBottomType(tp);
|
t2 = TiGetBottomType(tp);
|
||||||
if(TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) &&
|
devptr = ExtCurStyle->exts_device[t2];
|
||||||
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1))
|
if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) &&
|
||||||
/* found transistor */
|
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1))
|
||||||
|
/* found device */
|
||||||
{
|
{
|
||||||
yj = TOP(tile);
|
yj = TOP(tile);
|
||||||
xj = (LEFT(tp)+RIGHT(tp))>>1;
|
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)
|
if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1],t2)
|
||||||
/* tile is junction */
|
/* tile is junction */
|
||||||
|
|
@ -315,13 +319,14 @@ ResEachTile(tile, startpoint)
|
||||||
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp))
|
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp))
|
||||||
{
|
{
|
||||||
t2 = TiGetTopType(tp);
|
t2 = TiGetTopType(tp);
|
||||||
if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) &&
|
devptr = ExtCurStyle->exts_device[t2];
|
||||||
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1))
|
if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) &&
|
||||||
/* found transistor */
|
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1))
|
||||||
|
/* found device */
|
||||||
{
|
{
|
||||||
yj = BOTTOM(tile);
|
yj = BOTTOM(tile);
|
||||||
xj = (LEFT(tp) + RIGHT(tp)) >> 1;
|
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)
|
if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2)
|
||||||
/* tile is junction */
|
/* 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.
|
* a substrate area.
|
||||||
*
|
*
|
||||||
* Results: always returns 0 to keep search going.
|
* Results: always returns 0 to keep search going.
|
||||||
|
|
@ -355,7 +360,7 @@ ResEachTile(tile, startpoint)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
resSubTranFunc(tile,tp)
|
resSubDevFunc(tile,tp)
|
||||||
Tile *tile,*tp;
|
Tile *tile,*tp;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -365,13 +370,13 @@ resSubTranFunc(tile,tp)
|
||||||
tElement *tcell;
|
tElement *tcell;
|
||||||
int x,y;
|
int x,y;
|
||||||
|
|
||||||
if (junk->transistorList->rt_subs== NULL)
|
if (junk->deviceList->rd_fet_subs == NULL)
|
||||||
{
|
{
|
||||||
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
|
||||||
junk->transistorList->rt_subs = resptr;
|
junk->deviceList->rd_fet_subs = resptr;
|
||||||
junk->tj_status |= RES_TILE_TRAN;
|
junk->tj_status |= RES_TILE_DEV;
|
||||||
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
|
tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement)));
|
||||||
tcell->te_thist = junk->transistorList;
|
tcell->te_thist = junk->deviceList;
|
||||||
tcell->te_nextt = NULL;
|
tcell->te_nextt = NULL;
|
||||||
x = (LEFT(tile)+RIGHT(tile))>>1;
|
x = (LEFT(tile)+RIGHT(tile))>>1;
|
||||||
y = (TOP(tile)+BOTTOM(tile))>>1;
|
y = (TOP(tile)+BOTTOM(tile))>>1;
|
||||||
|
|
|
||||||
|
|
@ -43,16 +43,16 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ResSanityChecks(nodename,resistorList,nodeList,tranlist)
|
ResSanityChecks(nodename,resistorList,nodeList,devlist)
|
||||||
char *nodename;
|
char *nodename;
|
||||||
resResistor *resistorList;
|
resResistor *resistorList;
|
||||||
resNode *nodeList;
|
resNode *nodeList;
|
||||||
resTransistor *tranlist;
|
resDevice *devlist;
|
||||||
|
|
||||||
{
|
{
|
||||||
resResistor *resistor;
|
resResistor *resistor;
|
||||||
resNode *node;
|
resNode *node;
|
||||||
resTransistor *tran;
|
resDevice *dev;
|
||||||
resElement *rcell;
|
resElement *rcell;
|
||||||
static Stack *resSanityStack = NULL;
|
static Stack *resSanityStack = NULL;
|
||||||
int reached,foundorigin;
|
int reached,foundorigin;
|
||||||
|
|
@ -107,29 +107,29 @@ ResSanityChecks(nodename,resistorList,nodeList,tranlist)
|
||||||
}
|
}
|
||||||
resistor->rr_status &= ~RES_REACHED_RESISTOR;
|
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;
|
int i;
|
||||||
|
|
||||||
if (tran->rt_status & RES_TRAN_PLUG) continue;
|
if (dev->rd_status & RES_DEV_PLUG) continue;
|
||||||
reached = FALSE;
|
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;
|
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)
|
if (reached == 0)
|
||||||
{
|
{
|
||||||
TxError("Unreached transistor in %s at %d %d\n",
|
TxError("Unreached device in %s at %d %d\n",
|
||||||
nodename,
|
nodename,
|
||||||
tran->rt_inside.r_xbot,
|
dev->rd_inside.r_xbot,
|
||||||
tran->rt_inside.r_ybot);
|
dev->rd_inside.r_ybot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foundorigin = 0;
|
foundorigin = 0;
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ extern int dbcConnectFuncDCS();
|
||||||
extern int resSubSearchFunc();
|
extern int resSubSearchFunc();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static ResTranTile *TransList = NULL;
|
static ResDevTile *DevList = NULL;
|
||||||
static TileTypeBitMask DiffTypeBitMask;
|
static TileTypeBitMask DiffTypeBitMask;
|
||||||
TileTypeBitMask ResSubsTypeBitMask;
|
TileTypeBitMask ResSubsTypeBitMask;
|
||||||
|
|
||||||
|
|
@ -73,14 +73,14 @@ extern void ResCalcPerimOverlap();
|
||||||
*
|
*
|
||||||
* dbcConnectFuncDCS -- the same as dbcConnectFunc, except that it does
|
* dbcConnectFuncDCS -- the same as dbcConnectFunc, except that it does
|
||||||
* some extra searching around diffusion tiles looking for
|
* some extra searching around diffusion tiles looking for
|
||||||
* transistors.
|
* devices.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* Always returns 0 to keep the search from aborting.
|
* Always returns 0 to keep the search from aborting.
|
||||||
*
|
*
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* Adds a new record to the current check list. May also add new
|
* 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;
|
struct conSrArg2 *csa2;
|
||||||
Rect tileArea, *srArea, tranArea, newarea;
|
Rect tileArea, *srArea, devArea, newarea;
|
||||||
ResTranTile *thisTran;
|
ResDevTile *thisDev;
|
||||||
TileTypeBitMask notConnectMask, *connectMask;
|
TileTypeBitMask notConnectMask, *connectMask;
|
||||||
Tile *tp;
|
Tile *tp;
|
||||||
TileType t2, t1, loctype, ctype;
|
TileType t2, t1, loctype, ctype;
|
||||||
|
|
@ -102,6 +102,7 @@ dbcConnectFuncDCS(tile, cx)
|
||||||
SearchContext scx2;
|
SearchContext scx2;
|
||||||
int pNum;
|
int pNum;
|
||||||
CellDef *def;
|
CellDef *def;
|
||||||
|
ExtDevice *devptr;
|
||||||
|
|
||||||
TiToRect(tile, &tileArea);
|
TiToRect(tile, &tileArea);
|
||||||
srArea = &scx->scx_area;
|
srArea = &scx->scx_area;
|
||||||
|
|
@ -121,79 +122,83 @@ dbcConnectFuncDCS(tile, cx)
|
||||||
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp))
|
for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp))
|
||||||
{
|
{
|
||||||
t2 = TiGetType(tp);
|
t2 = TiGetType(tp);
|
||||||
if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) &&
|
devptr = ExtCurStyle->exts_device[t2];
|
||||||
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1))
|
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) &&
|
||||||
|
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1))
|
||||||
{
|
{
|
||||||
TiToRect(tp, &tranArea);
|
TiToRect(tp, &devArea);
|
||||||
thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile)));
|
thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile)));
|
||||||
ResCalcPerimOverlap(thisTran,tp);
|
ResCalcPerimOverlap(thisDev,tp);
|
||||||
GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area);
|
GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area);
|
||||||
thisTran->type = TiGetType(tp);
|
thisDev->type = TiGetType(tp);
|
||||||
thisTran->nextTran = TransList;
|
thisDev->nextDev = DevList;
|
||||||
TransList = thisTran;
|
DevList = thisDev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*right*/
|
/*right*/
|
||||||
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp))
|
for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp))
|
||||||
{
|
{
|
||||||
t2 = TiGetType(tp);
|
t2 = TiGetType(tp);
|
||||||
if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) &&
|
devptr = ExtCurStyle->exts_device[t2];
|
||||||
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1))
|
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) &&
|
||||||
|
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1))
|
||||||
{
|
{
|
||||||
TiToRect(tp, &tranArea);
|
TiToRect(tp, &devArea);
|
||||||
thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile)));
|
thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile)));
|
||||||
GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area);
|
GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area);
|
||||||
thisTran->type = TiGetType(tp);
|
thisDev->type = TiGetType(tp);
|
||||||
thisTran->nextTran = TransList;
|
thisDev->nextDev = DevList;
|
||||||
TransList = thisTran;
|
DevList = thisDev;
|
||||||
ResCalcPerimOverlap(thisTran,tp);
|
ResCalcPerimOverlap(thisDev,tp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*top*/
|
/*top*/
|
||||||
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp))
|
for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp))
|
||||||
{
|
{
|
||||||
t2 = TiGetType(tp);
|
t2 = TiGetType(tp);
|
||||||
if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) &&
|
devptr = ExtCurStyle->exts_device[t2];
|
||||||
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1))
|
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) &&
|
||||||
|
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1))
|
||||||
{
|
{
|
||||||
TiToRect(tp, &tranArea);
|
TiToRect(tp, &devArea);
|
||||||
thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile)));
|
thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile)));
|
||||||
GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area);
|
GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area);
|
||||||
thisTran->type = TiGetType(tp);
|
thisDev->type = TiGetType(tp);
|
||||||
thisTran->nextTran = TransList;
|
thisDev->nextDev = DevList;
|
||||||
TransList = thisTran;
|
DevList = thisDev;
|
||||||
ResCalcPerimOverlap(thisTran,tp);
|
ResCalcPerimOverlap(thisDev,tp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*bottom */
|
/*bottom */
|
||||||
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp))
|
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp))
|
||||||
{
|
{
|
||||||
t2 = TiGetType(tp);
|
t2 = TiGetType(tp);
|
||||||
if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) &&
|
devptr = ExtCurStyle->exts_device[t2];
|
||||||
TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1))
|
if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) &&
|
||||||
|
TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1))
|
||||||
{
|
{
|
||||||
TiToRect(tp, &tranArea);
|
TiToRect(tp, &devArea);
|
||||||
thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile)));
|
thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile)));
|
||||||
GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area);
|
GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area);
|
||||||
thisTran->type = TiGetType(tp);
|
thisDev->type = TiGetType(tp);
|
||||||
thisTran->nextTran = TransList;
|
thisDev->nextDev = DevList;
|
||||||
TransList = thisTran;
|
DevList = thisDev;
|
||||||
ResCalcPerimOverlap(thisTran,tp);
|
ResCalcPerimOverlap(thisDev,tp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if TTMaskHasType(&(ExtCurStyle->exts_transMask),t1)
|
else if TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t1)
|
||||||
{
|
{
|
||||||
TiToRect(tile, &tranArea);
|
TiToRect(tile, &devArea);
|
||||||
thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile)));
|
thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile)));
|
||||||
ResCalcPerimOverlap(thisTran,tile);
|
ResCalcPerimOverlap(thisDev,tile);
|
||||||
GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area);
|
GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area);
|
||||||
thisTran->type = TiGetType(tile);
|
thisDev->type = TiGetType(tile);
|
||||||
thisTran->nextTran = TransList;
|
thisDev->nextDev = DevList;
|
||||||
TransList = thisTran;
|
DevList = thisDev;
|
||||||
}
|
}
|
||||||
/* in some cases (primarily bipolar technology), we'll want to extract
|
/* 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)
|
The following does that check. (10-11-88)
|
||||||
*/
|
*/
|
||||||
#ifdef ARIEL
|
#ifdef ARIEL
|
||||||
|
|
@ -333,8 +338,8 @@ dbcConnectFuncDCS(tile, cx)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ResCalcPerimOverlap(trans, tile)
|
ResCalcPerimOverlap(dev, tile)
|
||||||
ResTranTile *trans;
|
ResDevTile *dev;
|
||||||
Tile *tile;
|
Tile *tile;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -342,7 +347,7 @@ ResCalcPerimOverlap(trans, tile)
|
||||||
int t1;
|
int t1;
|
||||||
int overlap;
|
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;
|
overlap =0;
|
||||||
|
|
||||||
t1 = TiGetType(tile);
|
t1 = TiGetType(tile);
|
||||||
|
|
@ -386,7 +391,7 @@ ResCalcPerimOverlap(trans, tile)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
trans->overlap = overlap;
|
dev->overlap = overlap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -399,7 +404,7 @@ ResCalcPerimOverlap(trans, tile)
|
||||||
* dbcConnectFuncDCS.
|
* dbcConnectFuncDCS.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* Linked list of transistors.
|
* Linked list of devices.
|
||||||
*
|
*
|
||||||
* Side effects:
|
* Side effects:
|
||||||
* The contents of the result cell are modified.
|
* The contents of the result cell are modified.
|
||||||
|
|
@ -407,7 +412,7 @@ ResCalcPerimOverlap(trans, tile)
|
||||||
* ----------------------------------------------------------------------------
|
* ----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ResTranTile *
|
ResDevTile *
|
||||||
DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse)
|
DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse)
|
||||||
SearchContext *scx;
|
SearchContext *scx;
|
||||||
TileTypeBitMask *mask;
|
TileTypeBitMask *mask;
|
||||||
|
|
@ -419,12 +424,13 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse)
|
||||||
{
|
{
|
||||||
static int first = 1;
|
static int first = 1;
|
||||||
struct conSrArg2 csa2;
|
struct conSrArg2 csa2;
|
||||||
int tran, pNum;
|
int dev, pNum;
|
||||||
char *tran_name;
|
char *dev_name;
|
||||||
TileTypeBitMask *newmask;
|
TileTypeBitMask *newmask;
|
||||||
ResTranTile *CurrentT;
|
ResDevTile *CurrentT;
|
||||||
CellDef *def = destUse->cu_def;
|
CellDef *def = destUse->cu_def;
|
||||||
TileType newtype;
|
TileType newtype;
|
||||||
|
ExtDevice *devptr;
|
||||||
|
|
||||||
csa2.csa2_use = destUse;
|
csa2.csa2_use = destUse;
|
||||||
csa2.csa2_xMask = xMask;
|
csa2.csa2_xMask = xMask;
|
||||||
|
|
@ -441,21 +447,22 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse)
|
||||||
{
|
{
|
||||||
TTMaskZero(&DiffTypeBitMask);
|
TTMaskZero(&DiffTypeBitMask);
|
||||||
TTMaskZero(&ResSubsTypeBitMask);
|
TTMaskZero(&ResSubsTypeBitMask);
|
||||||
for (tran = TT_TECHDEPBASE; tran < TT_MAXTYPES; tran++)
|
for (dev = TT_TECHDEPBASE; dev < TT_MAXTYPES; dev++)
|
||||||
{
|
{
|
||||||
tran_name = (ExtCurStyle->exts_transName)[tran];
|
devptr = ExtCurStyle->exts_device[dev];
|
||||||
if ((tran_name != NULL) && (strcmp(tran_name, "None")))
|
if ((devptr != NULL) && ((dev_name = devptr->exts_deviceName) != NULL)
|
||||||
|
&& (strcmp(dev_name, "None")))
|
||||||
{
|
{
|
||||||
TTMaskSetMask(&DiffTypeBitMask,
|
TTMaskSetMask(&DiffTypeBitMask,
|
||||||
&(ExtCurStyle->exts_transSDTypes[tran][0]));
|
&(devptr->exts_deviceSDTypes[0]));
|
||||||
TTMaskSetMask(&ResSubsTypeBitMask,
|
TTMaskSetMask(&ResSubsTypeBitMask,
|
||||||
&(ExtCurStyle->exts_transSubstrateTypes[tran]));
|
&(devptr->exts_deviceSubstrateTypes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
first = 0;
|
first = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransList = NULL;
|
DevList = NULL;
|
||||||
DBTreeSrTiles(scx, mask, xMask, dbcConnectFuncDCS, (ClientData) &csa2);
|
DBTreeSrTiles(scx, mask, xMask, dbcConnectFuncDCS, (ClientData) &csa2);
|
||||||
while (csa2.csa2_top >= 0)
|
while (csa2.csa2_top >= 0)
|
||||||
{
|
{
|
||||||
|
|
@ -471,7 +478,7 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse)
|
||||||
}
|
}
|
||||||
freeMagic((char *)csa2.csa2_list);
|
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 t = CurrentT->type;
|
||||||
TileType nt;
|
TileType nt;
|
||||||
|
|
@ -489,7 +496,7 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse)
|
||||||
}
|
}
|
||||||
|
|
||||||
DBReComputeBbox(def);
|
DBReComputeBbox(def);
|
||||||
return(TransList);
|
return(DevList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -499,7 +506,7 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse)
|
||||||
*
|
*
|
||||||
* resSubSearchFunc --
|
* resSubSearchFunc --
|
||||||
*
|
*
|
||||||
* called when DBSrPaintArea finds a transistor within
|
* called when DBSrPaintArea finds a device within
|
||||||
* a substrate area.
|
* a substrate area.
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
|
|
@ -517,22 +524,24 @@ resSubSearchFunc(tile,cx)
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
ResTranTile *thisTran;
|
ResDevTile *thisDev;
|
||||||
Rect tranArea;
|
Rect devArea;
|
||||||
TileType t = TiGetType(tile);
|
TileType t = TiGetType(tile);
|
||||||
|
ExtDevice *devptr;
|
||||||
|
|
||||||
/* Right now, we're only going to extract substrate terminals for
|
/* Right now, we're only going to extract substrate terminals for
|
||||||
devices with only one diffusion terminal, principally bipolar
|
devices with only one diffusion terminal, principally bipolar
|
||||||
devices.
|
devices.
|
||||||
*/
|
*/
|
||||||
if (ExtCurStyle->exts_transSDCount[t] >1) return 0;
|
devptr = ExtCurStyle->exts_device[t]
|
||||||
TiToRect(tile, &tranArea);
|
if (devptr->exts_deviceSDCount >1) return 0;
|
||||||
thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile)));
|
TiToRect(tile, &devArea);
|
||||||
GeoTransRect(&cx->tc_scx->scx_trans, &tranArea, &thisTran->area);
|
thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile)));
|
||||||
thisTran->type = t;
|
GeoTransRect(&cx->tc_scx->scx_trans, &devArea, &thisDev->area);
|
||||||
thisTran->nextTran = TransList;
|
thisDev->type = t;
|
||||||
TransList = thisTran;
|
thisDev->nextDev = DevList;
|
||||||
ResCalcPerimOverlap(thisTran,tile);
|
DevList = thisDev;
|
||||||
|
ResCalcPerimOverlap(thisDev,tile);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,42 +101,42 @@ ResPrintResistorList(fp,list)
|
||||||
/*
|
/*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* ResPrintTransistorList--
|
* ResPrintDeviceList--
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Results: none
|
* Results: none
|
||||||
*
|
*
|
||||||
* Side effects: prints out transistors in list to file fp.
|
* Side effects: prints out devices in list to file fp.
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ResPrintTransistorList(fp,list)
|
ResPrintDeviceList(fp,list)
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
resTransistor *list;
|
resDevice *list;
|
||||||
|
|
||||||
{
|
{
|
||||||
static char termtype[] = {'g','s','d','c'};
|
static char termtype[] = {'g','s','d','c'};
|
||||||
int i;
|
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)
|
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
|
else
|
||||||
fprintf(fp, "t w %d l %d ", list->rt_width, list->rt_length);
|
fprintf(fp, "t w %d l %d ", list->rd_width, list->rd_length);
|
||||||
for (i=0; i!= RT_TERMCOUNT;i++)
|
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)
|
if (fp == stdout)
|
||||||
TxPrintf("%c (%d,%d) ",termtype[i],
|
TxPrintf("%c (%d,%d) ",termtype[i],
|
||||||
list->rt_terminals[i]->rn_loc.p_x,
|
list->rd_terminals[i]->rn_loc.p_x,
|
||||||
list->rt_terminals[i]->rn_loc.p_y);
|
list->rd_terminals[i]->rn_loc.p_y);
|
||||||
else
|
else
|
||||||
fprintf(fp, "%c (%d,%d) ",termtype[i],
|
fprintf(fp, "%c (%d,%d) ",termtype[i],
|
||||||
list->rt_terminals[i]->rn_loc.p_x,
|
list->rd_terminals[i]->rn_loc.p_x,
|
||||||
list->rt_terminals[i]->rn_loc.p_y);
|
list->rd_terminals[i]->rn_loc.p_y);
|
||||||
|
|
||||||
}
|
}
|
||||||
if (fp == stdout)
|
if (fp == stdout)
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue