From 982bb8aa63e678f484d45f7a336e31995659754f Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 25 Jul 2019 10:20:24 -0400 Subject: [PATCH 001/121] Changed a recent commit which removed brackets from instance names while reading DEF. To preserve names as much as possible, such names are now kept. To avoid problems, EFbuild.c and ext2hier behavior has been changed to only parse entries in a .ext file as instance arrays if the array notation follows the specific syntax of [ax:bx:cx][ay:by:cy], letting all other uses of brackets pass through unaffected. --- ext2spice/ext2hier.c | 53 +++++++++++++++++++++++++++++++++----------- extflat/EFbuild.c | 24 +++++++++++++++----- lef/defRead.c | 26 +++++++++++++--------- 3 files changed, 74 insertions(+), 29 deletions(-) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index e5686cbf..93236df8 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1572,14 +1572,29 @@ esMakePorts(hc, cdata) while (tptr != NULL) { + int idum[6]; + bool is_array; + /* Ignore array information for the purpose of tracing */ - /* the cell definition hierarchy. */ + /* the cell definition hierarchy. Complementary to the */ + /* method used in EFbuild.c, only consider uses of */ + /* brackets that conform to the [ax:bx:cx][ay:by:cy] */ + /* notation. */ aptr = strchr(portname, '['); - if ((aptr == NULL) || (aptr > tptr)) - *tptr = '\0'; - else + if (aptr && (aptr < tptr) && + (sscanf(aptr, "[%d:%d:%d][%d:%d:%d]", + &idum[0], &idum[1], &idum[2], + &idum[3], &idum[4], &idum[5]) == 6)) + { + is_array = TRUE; *aptr = '\0'; + } + else + { + is_array = FALSE; + *tptr = '\0'; + } // Find the cell for the instance portdef = NULL; @@ -1589,10 +1604,10 @@ esMakePorts(hc, cdata) use = (Use *)HashGetValue(he); portdef = use->use_def; } - if ((aptr == NULL) || (aptr > tptr)) - *tptr = '/'; - else + if (is_array) *aptr = '['; + else + *tptr = '/'; portname = tptr + 1; // Find the net of portname in the subcell and @@ -1651,14 +1666,26 @@ esMakePorts(hc, cdata) while (tptr != NULL) { + int idum[6]; + bool is_array; + /* Ignore array information for the purpose of tracing */ /* the cell definition hierarchy. */ aptr = strchr(portname, '['); - if ((aptr == NULL) || (aptr > tptr)) - *tptr = '\0'; - else + if (aptr && (aptr < tptr) && + (sscanf(aptr, "[%d:%d:%d][%d:%d:%d]", + &idum[0], &idum[1], &idum[2], + &idum[3], &idum[4], &idum[5]) == 6)) + { *aptr = '\0'; + is_array = TRUE; + } + else + { + *tptr = '\0'; + is_array = FALSE; + } // Find the cell for the instance portdef = NULL; @@ -1668,10 +1695,10 @@ esMakePorts(hc, cdata) use = (Use *)HashGetValue(he); portdef = use->use_def; } - if ((aptr == NULL) || (aptr > tptr)) - *tptr = '/'; - else + if (is_array) *aptr = '['; + else + *tptr = '/'; portname = tptr + 1; // Find the net of portname in the subcell and diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c index 684168f1..3d56225f 100644 --- a/extflat/EFbuild.c +++ b/extflat/EFbuild.c @@ -1123,12 +1123,26 @@ efBuildUse(def, subDefName, subUseId, ta, tb, tc, td, te, tf) } else { - *cp = '\0'; - newuse->use_id = StrDup((char **) NULL, subUseId); - *cp = '['; - (void) sscanf(cp, "[%d:%d:%d][%d:%d:%d]", + /* Note: Preserve any use of brackets as-is other than the */ + /* standard magic array notation below. This allows, for */ + /* example, verilog instance arrays read from DEF files to */ + /* be passed through correctly. */ + + if ((sscanf(cp, "[%d:%d:%d][%d:%d:%d]", &newuse->use_xlo, &newuse->use_xhi, &newuse->use_xsep, - &newuse->use_ylo, &newuse->use_yhi, &newuse->use_ysep); + &newuse->use_ylo, &newuse->use_yhi, &newuse->use_ysep)) == 6) + { + *cp = '\0'; + newuse->use_id = StrDup((char **) NULL, subUseId); + *cp = '['; + } + else + { + newuse->use_id = StrDup((char **) NULL, subUseId); + newuse->use_xlo = newuse->use_xhi = 0; + newuse->use_ylo = newuse->use_yhi = 0; + newuse->use_xsep = newuse->use_ysep = 0; + } } he = HashFind(&def->def_uses, newuse->use_id); diff --git a/lef/defRead.c b/lef/defRead.c index afe49a2a..d4a1377f 100644 --- a/lef/defRead.c +++ b/lef/defRead.c @@ -1450,18 +1450,22 @@ DefReadComponents(f, rootDef, sname, oscale, total) /* Does use name contain brackets? If so, this can */ /* interfere with magic's use of arrays. */ + /* NOTE: This has been commented out. I think */ + /* the only confusion is in ext2spice and can be */ + /* avoided by allowing any bracket notation in an */ + /* instance name other than that used by the .ext */ + /* file for dealing with arrays, which uses the */ + /* specific syntax [xlo:xsep:xhi][ylo:ysep:yhi] and */ + /* is easy enough to distinguish. */ - /* NOTE: It is not clear that this needs to be */ - /* done during DEF read. The only confusion comes */ - /* from the arrays being parsed by ExtFlat when */ - /* doing ext2spice. */ - - dptr = strchr(usename, '['); - if (dptr != NULL) { - *dptr = '_'; - dptr = strchr(dptr + 1, ']'); - if (dptr != NULL) *dptr = '_'; - } + /* + dptr = strchr(usename, '['); + if (dptr != NULL) { + *dptr = '_'; + dptr = strchr(dptr + 1, ']'); + if (dptr != NULL) *dptr = '_'; + } + */ token = LefNextToken(f, TRUE); From 8562812fff467a1c50341185b6f56d4162023c29 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 25 Jul 2019 16:29:12 -0400 Subject: [PATCH 002/121] Corrected CalmaError() to CalmaReadError() in cif/CIFrdcl.c. Thanks to Toby Schaffer for the bug report and patch! --- cif/CIFrdcl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cif/CIFrdcl.c b/cif/CIFrdcl.c index 2157b15a..23321977 100644 --- a/cif/CIFrdcl.c +++ b/cif/CIFrdcl.c @@ -752,7 +752,7 @@ cifMakeBoundaryFunc(tile, clientdata) CIFReadError("Warning: Cell %s boundary was redefined.\n", cifReadCellDef->cd_name); else - CalmaError("Warning: Cell %s boundary was redefined.\n", + CalmaReadError("Warning: Cell %s boundary was redefined.\n", cifReadCellDef->cd_name); } } From df77f7853c043cb1b1710148cecc537b147a2545 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 29 Jul 2019 09:51:48 -0400 Subject: [PATCH 003/121] Corrected the handling of UNPLACED components in a DEF file, which was previously (and erroneously) lumped with PLACED and FIXED which take a position argument afterward. Note that this fix allows the DEF file to be read without error but does not have the (presumably desired) behavior of parsing SITE information from the LEF file and ROWS information from the DEF file and giving each unplaced component an arbitrary but legal position. That would require a significant amount of additional coding work. --- lef/defRead.c | 50 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/lef/defRead.c b/lef/defRead.c index d4a1377f..a9026263 100644 --- a/lef/defRead.c +++ b/lef/defRead.c @@ -775,11 +775,12 @@ enum def_orient {DEF_NORTH, DEF_SOUTH, DEF_EAST, DEF_WEST, DEF_FLIPPED_WEST}; int -DefReadLocation(use, f, oscale, tptr) +DefReadLocation(use, f, oscale, tptr, noplace) CellUse *use; FILE *f; float oscale; Transform *tptr; + bool noplace; { Rect *r, tr, rect; int keyword; @@ -791,21 +792,32 @@ DefReadLocation(use, f, oscale, tptr) "N", "S", "E", "W", "FN", "FS", "FE", "FW" }; - token = LefNextToken(f, TRUE); - if (*token != '(') goto parse_error; - token = LefNextToken(f, TRUE); - if (sscanf(token, "%f", &x) != 1) goto parse_error; - token = LefNextToken(f, TRUE); - if (sscanf(token, "%f", &y) != 1) goto parse_error; - token = LefNextToken(f, TRUE); - if (*token != ')') goto parse_error; - token = LefNextToken(f, TRUE); - - keyword = Lookup(token, orientations); - if (keyword < 0) + if (noplace) { - LefError(DEF_ERROR, "Unknown macro orientation \"%s\".\n", token); - return -1; + LefError(DEF_WARNING, "Unplaced component \"%s\" will be put at origin.\n", + use->cu_id); + x = 0; + y = 0; + keyword = DEF_NORTH; + } + else + { + token = LefNextToken(f, TRUE); + if (*token != '(') goto parse_error; + token = LefNextToken(f, TRUE); + if (sscanf(token, "%f", &x) != 1) goto parse_error; + token = LefNextToken(f, TRUE); + if (sscanf(token, "%f", &y) != 1) goto parse_error; + token = LefNextToken(f, TRUE); + if (*token != ')') goto parse_error; + token = LefNextToken(f, TRUE); + + keyword = Lookup(token, orientations); + if (keyword < 0) + { + LefError(DEF_ERROR, "Unknown macro orientation \"%s\".\n", token); + return -1; + } } /* The standard transformations are all defined to rotate */ @@ -1062,7 +1074,7 @@ DefReadPins(f, rootDef, sname, oscale, total) break; case DEF_PINS_PROP_FIXED: case DEF_PINS_PROP_PLACED: - DefReadLocation(NULL, f, oscale, &t); + DefReadLocation(NULL, f, oscale, &t, FALSE); if (curlayer == -1) pending = TRUE; else @@ -1522,10 +1534,12 @@ DefReadComponents(f, rootDef, sname, oscale, total) switch (subkey) { case DEF_PROP_PLACED: - case DEF_PROP_UNPLACED: case DEF_PROP_FIXED: case DEF_PROP_COVER: - DefReadLocation(defUse, f, oscale, &t); + DefReadLocation(defUse, f, oscale, &t, FALSE); + break; + case DEF_PROP_UNPLACED: + DefReadLocation(defUse, f, oscale, &t, TRUE); break; case DEF_PROP_SOURCE: case DEF_PROP_WEIGHT: From 9635f10c5adbb985cf584ec63c92f084a95583c4 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 2 Aug 2019 14:50:32 -0400 Subject: [PATCH 004/121] Removed a badly implemented double-loop from the timestamp mismatch code. --- commands/CmdFI.c | 6 +++++- database/DBio.c | 5 +++++ database/DBtimestmp.c | 30 +++++++++++++++++++++++++++--- database/databaseInt.h | 1 + 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/commands/CmdFI.c b/commands/CmdFI.c index 8669ea3c..178fe9ee 100644 --- a/commands/CmdFI.c +++ b/commands/CmdFI.c @@ -1452,7 +1452,11 @@ CmdIdentify(w, cmd) return; } - if (CmdIllegalChars(cmd->tx_argv[1], "[],/", "Cell use id")) + /* NOTE: Relaxing the definition of illegal characters in cell use IDs */ + /* by allowing brackets. Possibly the list can be reduced further. */ + + /* if (CmdIllegalChars(cmd->tx_argv[1], "[],/", "Cell use id")) */ + if (CmdIllegalChars(cmd->tx_argv[1], ",/", "Cell use id")) return; if (SelEnumCells(FALSE, (int *) NULL, (SearchContext *) NULL, diff --git a/database/DBio.c b/database/DBio.c index 3f6aca45..6389eb23 100644 --- a/database/DBio.c +++ b/database/DBio.c @@ -619,6 +619,9 @@ done: } } } + /* Update timestamp flags */ + DBFlagMismatches(cellDef); + cellDef->cd_timestamp = cellStamp; if (cellStamp == 0) { @@ -869,6 +872,8 @@ DBReadBackup(name) name); return FALSE; } + /* Update timestamp flags from dbCellReadDef() */ + DBFlagMismatches(); } else { diff --git a/database/DBtimestmp.c b/database/DBtimestmp.c index 8143eced..f6900a70 100644 --- a/database/DBtimestmp.c +++ b/database/DBtimestmp.c @@ -270,6 +270,16 @@ dbStampFunc(cellDef) * processing. When DBFixMismatch is called, it will notify * the design-rule checker to recheck both wrongArea, and * the cell's eventual correct area. + * + * This routine has been modified from a poor implementation. Previously + * the parent def of all uses of the cell being checked would be marked + * for a stamp mismatch check. However, when reading a cell with large + * numbers of instances, the list of instances would be parsed for every + * instance added, leading to an O(N^2) computation. Routine DBStampMismatch() + * has been broken into two parts. DBStampMismatch() only records the + * area to be checked. DBFlagMismatches() looks at the parents of each + * celldef only once, after all instances have been read. + * * ---------------------------------------------------------------------------- */ @@ -281,18 +291,32 @@ DBStampMismatch(cellDef, wrongArea) */ { Mismatch *mm; - CellUse *parentUse; mm = (Mismatch *) mallocMagic((unsigned) (sizeof (Mismatch))); mm->mm_cellDef = cellDef; mm->mm_oldArea = *wrongArea; mm->mm_next = mismatch; mismatch = mm; +} - for (parentUse = cellDef->cd_parents; parentUse != NULL; - parentUse = parentUse->cu_nextuse) +/* + * ---------------------------------------------------------------------------- + * ---------------------------------------------------------------------------- + */ + +void +DBFlagMismatches(checkDef) + CellDef *checkDef; +{ + CellUse *parentUse; + long count; + + for (parentUse = checkDef->cd_parents; parentUse != NULL; + parentUse = parentUse->cu_nextuse) { + count++; if (parentUse->cu_parent == NULL) continue; parentUse->cu_parent->cd_flags |= CDSTAMPSCHANGED; } + TxPrintf("Diagnostic: cell %s count = %ld\n", checkDef->cd_name, count); } diff --git a/database/databaseInt.h b/database/databaseInt.h index ae3f0f63..5756c458 100644 --- a/database/databaseInt.h +++ b/database/databaseInt.h @@ -199,6 +199,7 @@ extern void DBUndoPutLabel(); extern void DBUndoEraseLabel(); extern void DBUndoCellUse(); extern void DBStampMismatch(); +extern void DBFlagMismatches(); extern void DBTechAddNameToType(); extern void dbComputeBbox(); From 381fc0cca487e6bfdf31de968c486a83a575099f Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 2 Aug 2019 14:53:22 -0400 Subject: [PATCH 005/121] Removed diagnostic print from last commit. --- database/DBtimestmp.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/database/DBtimestmp.c b/database/DBtimestmp.c index f6900a70..d33b20fa 100644 --- a/database/DBtimestmp.c +++ b/database/DBtimestmp.c @@ -309,14 +309,11 @@ DBFlagMismatches(checkDef) CellDef *checkDef; { CellUse *parentUse; - long count; for (parentUse = checkDef->cd_parents; parentUse != NULL; parentUse = parentUse->cu_nextuse) { - count++; if (parentUse->cu_parent == NULL) continue; parentUse->cu_parent->cd_flags |= CDSTAMPSCHANGED; } - TxPrintf("Diagnostic: cell %s count = %ld\n", checkDef->cd_name, count); } From 05c069783a1102acc054e04e92ea018d8c566635 Mon Sep 17 00:00:00 2001 From: Roman-Parise Date: Sun, 21 Jul 2019 16:31:12 -0700 Subject: [PATCH 006/121] Added FreeBSD detail to INSTALL --- INSTALL | 2 ++ 1 file changed, 2 insertions(+) diff --git a/INSTALL b/INSTALL index 6794b09d..0543faba 100644 --- a/INSTALL +++ b/INSTALL @@ -7,6 +7,8 @@ Autoconf Capsule Summary: make make install + Note: Remember to use 'gmake' on FreeBSD. + Autoconf options (use "./configure --help" for a complete list): --prefix=DIR Indicates the install directory. Determines the From d235e01b2da04a88353043ca19439d4664ff8b5b Mon Sep 17 00:00:00 2001 From: Roman-Parise Date: Sun, 21 Jul 2019 16:32:04 -0700 Subject: [PATCH 007/121] Edited configure scripts for FreeBSD installation --- scripts/configure | 2 +- scripts/configure.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/configure b/scripts/configure index 4cb2d8d7..3b604040 100755 --- a/scripts/configure +++ b/scripts/configure @@ -8072,7 +8072,7 @@ fi # Not available on all versions: check for include file. SHLIB_CFLAGS="-fpic" LDDL_FLAGS="-shared ${LIB_SPECS}" - CFLAGS="${CFLAGS} -l/usr/X11R6/include" + CFLAGS="${CFLAGS} -L/usr/X11R6/include" ;; *-netbsd*|*-openbsd*) diff --git a/scripts/configure.in b/scripts/configure.in index b2070922..3000438e 100644 --- a/scripts/configure.in +++ b/scripts/configure.in @@ -1615,7 +1615,7 @@ if test $usingTcl ; then # Not available on all versions: check for include file. SHLIB_CFLAGS="-fpic" LDDL_FLAGS="-shared ${LIB_SPECS}" - CFLAGS="${CFLAGS} -l/usr/X11R6/include" + CFLAGS="${CFLAGS} -L/usr/X11R6/include" ;; *-netbsd*|*-openbsd*) From 46e0ec7a24e90d499b7450681606c2a6ae1c2a18 Mon Sep 17 00:00:00 2001 From: Roman-Parise Date: Sun, 21 Jul 2019 16:32:45 -0700 Subject: [PATCH 008/121] Updated outdated files in utils/magsgtty.h --- utils/magsgtty.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/utils/magsgtty.h b/utils/magsgtty.h index 839ce532..a0962a0e 100644 --- a/utils/magsgtty.h +++ b/utils/magsgtty.h @@ -22,11 +22,19 @@ #define _MAGSGTTY_H #if !defined(SYSV) && !defined(CYGWIN) + # ifdef ALPHA # undef MAX # undef MIN # endif -#include + +# ifndef COMPAT_43TTY +# define COMPAT_43TTY +# endif + +#include +#include + #else #include #endif From 1edccafb2c078688bc5b352ad2fcac4252fe4751 Mon Sep 17 00:00:00 2001 From: Roman-Parise Date: Sun, 21 Jul 2019 17:08:40 -0700 Subject: [PATCH 009/121] Removed files in .gitignore from repo --- defs.mak | 98 ----- scripts/config.log | 930 ---------------------------------------- scripts/config.status | 958 ------------------------------------------ scripts/defs.mak | 98 ----- 4 files changed, 2084 deletions(-) delete mode 100644 defs.mak delete mode 100644 scripts/config.log delete mode 100755 scripts/config.status delete mode 100644 scripts/defs.mak diff --git a/defs.mak b/defs.mak deleted file mode 100644 index c3bb2089..00000000 --- a/defs.mak +++ /dev/null @@ -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} diff --git a/scripts/config.log b/scripts/config.log deleted file mode 100644 index 1c3c70ad..00000000 --- a/scripts/config.log +++ /dev/null @@ -1,930 +0,0 @@ -This file contains any messages produced by compilers while -running configure, to aid debugging if configure makes a mistake. - -It was created by configure, which was -generated by GNU Autoconf 2.69. Invocation command line was - - $ ./configure - -## --------- ## -## Platform. ## -## --------- ## - -hostname = stravinsky -uname -m = x86_64 -uname -r = 4.1.13-100.fc21.x86_64 -uname -s = Linux -uname -v = #1 SMP Tue Nov 10 13:13:20 UTC 2015 - -/usr/bin/uname -p = x86_64 -/bin/uname -X = unknown - -/bin/arch = x86_64 -/usr/bin/arch -k = unknown -/usr/convex/getsysinfo = unknown -/usr/bin/hostinfo = unknown -/bin/machine = unknown -/usr/bin/oslevel = unknown -/bin/universe = unknown - -PATH: . -PATH: /bin -PATH: /sbin -PATH: /usr/bin -PATH: /usr/sbin -PATH: /usr/local/bin - - -## ----------- ## -## Core tests. ## -## ----------- ## - -configure:2488: checking build system type -configure:2502: result: x86_64-unknown-linux-gnu -configure:2522: checking host system type -configure:2535: result: x86_64-unknown-linux-gnu -configure:2555: checking target system type -configure:2568: result: x86_64-unknown-linux-gnu -configure:2660: checking for gcc -configure:2676: found /bin/gcc -configure:2687: result: gcc -configure:2916: checking for C compiler version -configure:2925: gcc --version >&5 -gcc (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6) -Copyright (C) 2014 Free Software Foundation, Inc. -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -configure:2936: $? = 0 -configure:2925: gcc -v >&5 -Using built-in specs. -COLLECT_GCC=gcc -COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.9.2/lto-wrapper -Target: x86_64-redhat-linux -Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.9.2-20150212/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.9.2-20150212/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux -Thread model: posix -gcc version 4.9.2 20150212 (Red Hat 4.9.2-6) (GCC) -configure:2936: $? = 0 -configure:2925: gcc -V >&5 -gcc: error: unrecognized command line option '-V' -gcc: fatal error: no input files -compilation terminated. -configure:2936: $? = 4 -configure:2925: gcc -qversion >&5 -gcc: error: unrecognized command line option '-qversion' -gcc: fatal error: no input files -compilation terminated. -configure:2936: $? = 4 -configure:2956: checking whether the C compiler works -configure:2978: gcc -g conftest.c >&5 -configure:2982: $? = 0 -configure:3030: result: yes -configure:3033: checking for C compiler default output file name -configure:3035: result: a.out -configure:3041: checking for suffix of executables -configure:3048: gcc -o conftest -g conftest.c >&5 -configure:3052: $? = 0 -configure:3074: result: -configure:3096: checking whether we are cross compiling -configure:3104: gcc -o conftest -g conftest.c >&5 -configure:3108: $? = 0 -configure:3115: ./conftest -configure:3119: $? = 0 -configure:3134: result: no -configure:3139: checking for suffix of object files -configure:3161: gcc -c -g conftest.c >&5 -configure:3165: $? = 0 -configure:3186: result: o -configure:3190: checking whether we are using the GNU C compiler -configure:3209: gcc -c -g conftest.c >&5 -configure:3209: $? = 0 -configure:3218: result: yes -configure:3227: checking whether gcc accepts -g -configure:3247: gcc -c -g conftest.c >&5 -configure:3247: $? = 0 -configure:3288: result: yes -configure:3305: checking for gcc option to accept ISO C89 -configure:3368: gcc -c -g conftest.c >&5 -configure:3368: $? = 0 -configure:3381: result: none needed -configure:3406: checking how to run the C preprocessor -configure:3437: gcc -E conftest.c -configure:3437: $? = 0 -configure:3451: gcc -E conftest.c -conftest.c:11:28: fatal error: ac_nonexistent.h: No such file or directory - #include - ^ -compilation terminated. -configure:3451: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "" -| #define PACKAGE_TARNAME "" -| #define PACKAGE_VERSION "" -| #define PACKAGE_STRING "" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define MAGIC_VERSION "8.2" -| #define MAGIC_REVISION "101" -| /* end confdefs.h. */ -| #include -configure:3476: result: gcc -E -configure:3496: gcc -E conftest.c -configure:3496: $? = 0 -configure:3510: gcc -E conftest.c -conftest.c:11:28: fatal error: ac_nonexistent.h: No such file or directory - #include - ^ -compilation terminated. -configure:3510: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "" -| #define PACKAGE_TARNAME "" -| #define PACKAGE_VERSION "" -| #define PACKAGE_STRING "" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define MAGIC_VERSION "8.2" -| #define MAGIC_REVISION "101" -| /* end confdefs.h. */ -| #include -configure:3596: checking for g++ -configure:3612: found /bin/g++ -configure:3623: result: g++ -configure:3650: checking for C++ compiler version -configure:3659: g++ --version >&5 -g++ (GCC) 4.9.2 20150212 (Red Hat 4.9.2-6) -Copyright (C) 2014 Free Software Foundation, Inc. -This is free software; see the source for copying conditions. There is NO -warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -configure:3670: $? = 0 -configure:3659: g++ -v >&5 -Using built-in specs. -COLLECT_GCC=g++ -COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.9.2/lto-wrapper -Target: x86_64-redhat-linux -Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.9.2-20150212/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.9.2-20150212/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux -Thread model: posix -gcc version 4.9.2 20150212 (Red Hat 4.9.2-6) (GCC) -configure:3670: $? = 0 -configure:3659: g++ -V >&5 -g++: error: unrecognized command line option '-V' -g++: fatal error: no input files -compilation terminated. -configure:3670: $? = 4 -configure:3659: g++ -qversion >&5 -g++: error: unrecognized command line option '-qversion' -g++: fatal error: no input files -compilation terminated. -configure:3670: $? = 4 -configure:3674: checking whether we are using the GNU C++ compiler -configure:3693: g++ -c conftest.cpp >&5 -configure:3693: $? = 0 -configure:3702: result: yes -configure:3711: checking whether g++ accepts -g -configure:3731: g++ -c -g conftest.cpp >&5 -configure:3731: $? = 0 -configure:3772: result: yes -configure:3796: checking for library containing strerror -configure:3827: gcc -o conftest -g conftest.c >&5 -configure:3827: $? = 0 -configure:3844: result: none required -configure:3866: checking for a BSD-compatible install -configure:3934: result: /bin/install -c -configure:3988: checking for ranlib -configure:4004: found /bin/ranlib -configure:4015: result: ranlib -configure:4042: checking for gm4 -configure:4075: result: no -configure:4042: checking for gnum4 -configure:4075: result: no -configure:4042: checking for m4 -configure:4060: found /bin/m4 -configure:4072: result: /bin/m4 -configure:4090: checking for python3 -configure:4108: found /bin/python3 -configure:4121: result: /bin/python3 -configure:4166: checking for ld used by GCC -configure:4229: result: /bin/ld -configure:4236: checking if the linker (/bin/ld) is GNU ld -GNU ld version 2.24 -configure:4248: result: yes -configure:4255: checking for grep that handles long lines and -e -configure:4313: result: /bin/grep -configure:4318: checking for egrep -configure:4380: result: /bin/grep -E -configure:4385: checking for ANSI C header files -configure:4405: gcc -c -g conftest.c >&5 -configure:4405: $? = 0 -configure:4478: gcc -o conftest -g conftest.c >&5 -configure:4478: $? = 0 -configure:4478: ./conftest -configure:4478: $? = 0 -configure:4489: result: yes -configure:4502: checking for sys/types.h -configure:4502: gcc -c -g conftest.c >&5 -configure:4502: $? = 0 -configure:4502: result: yes -configure:4502: checking for sys/stat.h -configure:4502: gcc -c -g conftest.c >&5 -configure:4502: $? = 0 -configure:4502: result: yes -configure:4502: checking for stdlib.h -configure:4502: gcc -c -g conftest.c >&5 -configure:4502: $? = 0 -configure:4502: result: yes -configure:4502: checking for string.h -configure:4502: gcc -c -g conftest.c >&5 -configure:4502: $? = 0 -configure:4502: result: yes -configure:4502: checking for memory.h -configure:4502: gcc -c -g conftest.c >&5 -configure:4502: $? = 0 -configure:4502: result: yes -configure:4502: checking for strings.h -configure:4502: gcc -c -g conftest.c >&5 -configure:4502: $? = 0 -configure:4502: result: yes -configure:4502: checking for inttypes.h -configure:4502: gcc -c -g conftest.c >&5 -configure:4502: $? = 0 -configure:4502: result: yes -configure:4502: checking for stdint.h -configure:4502: gcc -c -g conftest.c >&5 -configure:4502: $? = 0 -configure:4502: result: yes -configure:4502: checking for unistd.h -configure:4502: gcc -c -g conftest.c >&5 -configure:4502: $? = 0 -configure:4502: result: yes -configure:4518: checking size of void * -configure:4523: gcc -o conftest -g conftest.c >&5 -configure:4523: $? = 0 -configure:4523: ./conftest -configure:4523: $? = 0 -configure:4537: result: 8 -configure:4551: checking size of unsigned int -configure:4556: gcc -o conftest -g conftest.c >&5 -configure:4556: $? = 0 -configure:4556: ./conftest -configure:4556: $? = 0 -configure:4570: result: 4 -configure:4584: checking size of unsigned long -configure:4589: gcc -o conftest -g conftest.c >&5 -configure:4589: $? = 0 -configure:4589: ./conftest -configure:4589: $? = 0 -configure:4603: result: 8 -configure:4617: checking size of unsigned long long -configure:4622: gcc -o conftest -g conftest.c >&5 -configure:4622: $? = 0 -configure:4622: ./conftest -configure:4622: $? = 0 -configure:4636: result: 8 -configure:4647: checking whether byte ordering is bigendian -configure:4662: gcc -c -g conftest.c >&5 -conftest.c:26:9: error: unknown type name 'not' - not a universal capable compiler - ^ -conftest.c:26:15: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'universal' - not a universal capable compiler - ^ -conftest.c:26:15: error: unknown type name 'universal' -configure:4662: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "" -| #define PACKAGE_TARNAME "" -| #define PACKAGE_VERSION "" -| #define PACKAGE_STRING "" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define MAGIC_VERSION "8.2" -| #define MAGIC_REVISION "101" -| #define STDC_HEADERS 1 -| #define HAVE_SYS_TYPES_H 1 -| #define HAVE_SYS_STAT_H 1 -| #define HAVE_STDLIB_H 1 -| #define HAVE_STRING_H 1 -| #define HAVE_MEMORY_H 1 -| #define HAVE_STRINGS_H 1 -| #define HAVE_INTTYPES_H 1 -| #define HAVE_STDINT_H 1 -| #define HAVE_UNISTD_H 1 -| #define SIZEOF_VOID_P 8 -| #define SIZEOF_UNSIGNED_INT 4 -| #define SIZEOF_UNSIGNED_LONG 8 -| #define SIZEOF_UNSIGNED_LONG_LONG 8 -| /* end confdefs.h. */ -| #ifndef __APPLE_CC__ -| not a universal capable compiler -| #endif -| typedef int dummy; -| -configure:4707: gcc -c -g conftest.c >&5 -configure:4707: $? = 0 -configure:4725: gcc -c -g conftest.c >&5 -conftest.c: In function 'main': -conftest.c:32:4: error: unknown type name 'not' - not big endian - ^ -conftest.c:32:12: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'endian' - not big endian - ^ -configure:4725: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "" -| #define PACKAGE_TARNAME "" -| #define PACKAGE_VERSION "" -| #define PACKAGE_STRING "" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define MAGIC_VERSION "8.2" -| #define MAGIC_REVISION "101" -| #define STDC_HEADERS 1 -| #define HAVE_SYS_TYPES_H 1 -| #define HAVE_SYS_STAT_H 1 -| #define HAVE_STDLIB_H 1 -| #define HAVE_STRING_H 1 -| #define HAVE_MEMORY_H 1 -| #define HAVE_STRINGS_H 1 -| #define HAVE_INTTYPES_H 1 -| #define HAVE_STDINT_H 1 -| #define HAVE_UNISTD_H 1 -| #define SIZEOF_VOID_P 8 -| #define SIZEOF_UNSIGNED_INT 4 -| #define SIZEOF_UNSIGNED_LONG 8 -| #define SIZEOF_UNSIGNED_LONG_LONG 8 -| /* end confdefs.h. */ -| #include -| #include -| -| int -| main () -| { -| #if BYTE_ORDER != BIG_ENDIAN -| not big endian -| #endif -| -| ; -| return 0; -| } -configure:4853: result: no -configure:4872: checking for ANSI C header files -configure:4976: result: yes -configure:4988: checking for setenv -configure:4988: gcc -o conftest -g conftest.c >&5 -configure:4988: $? = 0 -configure:4988: result: yes -configure:4988: checking for putenv -configure:4988: gcc -o conftest -g conftest.c >&5 -configure:4988: $? = 0 -configure:4988: result: yes -configure:4998: checking for vfork -configure:4998: gcc -o conftest -g conftest.c >&5 -configure:4998: $? = 0 -configure:4998: result: yes -configure:5006: checking sys/mman.h usability -configure:5006: gcc -c -g conftest.c >&5 -configure:5006: $? = 0 -configure:5006: result: yes -configure:5006: checking sys/mman.h presence -configure:5006: gcc -E conftest.c -configure:5006: $? = 0 -configure:5006: result: yes -configure:5006: checking for sys/mman.h -configure:5006: result: yes -configure:5019: checking dirent.h usability -configure:5019: gcc -c -g conftest.c >&5 -configure:5019: $? = 0 -configure:5019: result: yes -configure:5019: checking dirent.h presence -configure:5019: gcc -E conftest.c -configure:5019: $? = 0 -configure:5019: result: yes -configure:5019: checking for dirent.h -configure:5019: result: yes -configure:5032: checking limits.h usability -configure:5032: gcc -c -g conftest.c >&5 -configure:5032: $? = 0 -configure:5032: result: yes -configure:5032: checking limits.h presence -configure:5032: gcc -E conftest.c -configure:5032: $? = 0 -configure:5032: result: yes -configure:5032: checking for limits.h -configure:5032: result: yes -configure:5045: checking param.h usability -configure:5045: gcc -c -g conftest.c >&5 -conftest.c:64:19: fatal error: param.h: No such file or directory - #include - ^ -compilation terminated. -configure:5045: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "" -| #define PACKAGE_TARNAME "" -| #define PACKAGE_VERSION "" -| #define PACKAGE_STRING "" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define MAGIC_VERSION "8.2" -| #define MAGIC_REVISION "101" -| #define STDC_HEADERS 1 -| #define HAVE_SYS_TYPES_H 1 -| #define HAVE_SYS_STAT_H 1 -| #define HAVE_STDLIB_H 1 -| #define HAVE_STRING_H 1 -| #define HAVE_MEMORY_H 1 -| #define HAVE_STRINGS_H 1 -| #define HAVE_INTTYPES_H 1 -| #define HAVE_STDINT_H 1 -| #define HAVE_UNISTD_H 1 -| #define SIZEOF_VOID_P 8 -| #define SIZEOF_UNSIGNED_INT 4 -| #define SIZEOF_UNSIGNED_LONG 8 -| #define SIZEOF_UNSIGNED_LONG_LONG 8 -| #define STDC_HEADERS 1 -| #define HAVE_SETENV 1 -| #define HAVE_PUTENV 1 -| #define HAVE_SYS_MMAN_H 1 -| #define HAVE_DIRENT_H 1 -| #define HAVE_LIMITS_H 1 -| /* end confdefs.h. */ -| #include -| #ifdef HAVE_SYS_TYPES_H -| # include -| #endif -| #ifdef HAVE_SYS_STAT_H -| # include -| #endif -| #ifdef STDC_HEADERS -| # include -| # include -| #else -| # ifdef HAVE_STDLIB_H -| # include -| # endif -| #endif -| #ifdef HAVE_STRING_H -| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H -| # include -| # endif -| # include -| #endif -| #ifdef HAVE_STRINGS_H -| # include -| #endif -| #ifdef HAVE_INTTYPES_H -| # include -| #endif -| #ifdef HAVE_STDINT_H -| # include -| #endif -| #ifdef HAVE_UNISTD_H -| # include -| #endif -| #include -configure:5045: result: no -configure:5045: checking param.h presence -configure:5045: gcc -E conftest.c -conftest.c:31:19: fatal error: param.h: No such file or directory - #include - ^ -compilation terminated. -configure:5045: $? = 1 -configure: failed program was: -| /* confdefs.h */ -| #define PACKAGE_NAME "" -| #define PACKAGE_TARNAME "" -| #define PACKAGE_VERSION "" -| #define PACKAGE_STRING "" -| #define PACKAGE_BUGREPORT "" -| #define PACKAGE_URL "" -| #define MAGIC_VERSION "8.2" -| #define MAGIC_REVISION "101" -| #define STDC_HEADERS 1 -| #define HAVE_SYS_TYPES_H 1 -| #define HAVE_SYS_STAT_H 1 -| #define HAVE_STDLIB_H 1 -| #define HAVE_STRING_H 1 -| #define HAVE_MEMORY_H 1 -| #define HAVE_STRINGS_H 1 -| #define HAVE_INTTYPES_H 1 -| #define HAVE_STDINT_H 1 -| #define HAVE_UNISTD_H 1 -| #define SIZEOF_VOID_P 8 -| #define SIZEOF_UNSIGNED_INT 4 -| #define SIZEOF_UNSIGNED_LONG 8 -| #define SIZEOF_UNSIGNED_LONG_LONG 8 -| #define STDC_HEADERS 1 -| #define HAVE_SETENV 1 -| #define HAVE_PUTENV 1 -| #define HAVE_SYS_MMAN_H 1 -| #define HAVE_DIRENT_H 1 -| #define HAVE_LIMITS_H 1 -| /* end confdefs.h. */ -| #include -configure:5045: result: no -configure:5045: checking for param.h -configure:5045: result: no -configure:5058: checking paths.h usability -configure:5058: gcc -c -g conftest.c >&5 -configure:5058: $? = 0 -configure:5058: result: yes -configure:5058: checking paths.h presence -configure:5058: gcc -E conftest.c -configure:5058: $? = 0 -configure:5058: result: yes -configure:5058: checking for paths.h -configure:5058: result: yes -configure:5069: checking for va_copy -configure:5087: gcc -o conftest -g conftest.c >&5 -configure:5087: $? = 0 -configure:5096: result: yes -configure:5104: checking for __va_copy -configure:5122: gcc -o conftest -g conftest.c >&5 -configure:5122: $? = 0 -configure:5131: result: yes -configure:5347: checking for gcore -configure:5365: found /bin/gcore -configure:5378: result: /bin/gcore -configure:5390: checking for csh -configure:5408: found /bin/csh -configure:5421: result: /bin/csh -configure:5435: checking for X -configure:5574: gcc -o conftest -g conftest.c -lX11 >&5 -configure:5574: $? = 0 -configure:5624: result: libraries , headers -configure:5723: gcc -o conftest -g conftest.c -lX11 >&5 -configure:5723: $? = 0 -configure:5821: checking for gethostbyname -configure:5821: gcc -o conftest -g conftest.c >&5 -configure:5821: $? = 0 -configure:5821: result: yes -configure:5918: checking for connect -configure:5918: gcc -o conftest -g conftest.c >&5 -configure:5918: $? = 0 -configure:5918: result: yes -configure:5967: checking for remove -configure:5967: gcc -o conftest -g conftest.c >&5 -configure:5967: $? = 0 -configure:5967: result: yes -configure:6016: checking for shmat -configure:6016: gcc -o conftest -g conftest.c >&5 -configure:6016: $? = 0 -configure:6016: result: yes -configure:6074: checking for IceConnectionNumber in -lICE -configure:6099: gcc -o conftest -g conftest.c -lICE >&5 -configure:6099: $? = 0 -configure:6108: result: yes -configure:6144: checking for XOpenDevice in -lXi -configure:6169: gcc -o conftest -g conftest.c -lXi >&5 -configure:6169: $? = 0 -configure:6178: result: yes -configure:6184: checking for XmuInternAtom in -lXmu -configure:6209: gcc -o conftest -g conftest.c -lXmu >&5 -configure:6209: $? = 0 -configure:6218: result: yes -configure:6224: checking for XextFindDisplay in -lXext -configure:6249: gcc -o conftest -g conftest.c -lXext >&5 -configure:6249: $? = 0 -configure:6258: result: yes -configure:6338: checking for tclConfig.sh -configure:6412: result: /usr/lib64/tclConfig.sh -configure:6428: checking for tkConfig.sh -configure:6501: result: /usr/lib64/tkConfig.sh -configure:6635: checking for wish executable -configure:6663: result: /usr/bin/wish -configure:6669: checking for tclsh executable -configure:6695: result: /usr/bin/tclsh -configure:7404: checking GL/gl.h usability -configure:7404: gcc -c -g conftest.c >&5 -configure:7404: $? = 0 -configure:7404: result: yes -configure:7404: checking GL/gl.h presence -configure:7404: gcc -E conftest.c -configure:7404: $? = 0 -configure:7404: result: yes -configure:7404: checking for GL/gl.h -configure:7404: result: yes -configure:7422: checking for glXCreateContext in -lGL -configure:7447: gcc -o conftest -g -lm conftest.c -lGL >&5 -configure:7447: $? = 0 -configure:7456: result: yes -configure:7472: checking for gluNewTess in -lGLU -configure:7497: gcc -o conftest -g -lm conftest.c -lGLU -lGL >&5 -configure:7497: $? = 0 -configure:7506: result: yes -configure:7557: checking cairo/cairo.h usability -configure:7557: gcc -c -g conftest.c >&5 -configure:7557: $? = 0 -configure:7557: result: yes -configure:7557: checking cairo/cairo.h presence -configure:7557: gcc -E conftest.c -configure:7557: $? = 0 -configure:7557: result: yes -configure:7557: checking for cairo/cairo.h -configure:7557: result: yes -configure:7575: checking for cairo_user_to_device in -lcairo -configure:7600: gcc -o conftest -g -lm conftest.c -lcairo -lGLU -lGL >&5 -configure:7600: $? = 0 -configure:7609: result: yes -configure:8417: creating ./config.status - -## ---------------------- ## -## Running config.status. ## -## ---------------------- ## - -This file was extended by config.status, which was -generated by GNU Autoconf 2.69. Invocation command line was - - CONFIG_FILES = - CONFIG_HEADERS = - CONFIG_LINKS = - CONFIG_COMMANDS = - $ ./config.status - -on stravinsky - -config.status:801: creating defs.mak -config.status:904: WARNING: 'defs.mak.in' seems to ignore the --datarootdir setting - -## ---------------- ## -## Cache variables. ## -## ---------------- ## - -ac_cv_build=x86_64-unknown-linux-gnu -ac_cv_c___va_copy=yes -ac_cv_c_bigendian=no -ac_cv_c_compiler_gnu=yes -ac_cv_c_va_copy=yes -ac_cv_cxx_compiler_gnu=yes -ac_cv_env_CCC_set= -ac_cv_env_CCC_value= -ac_cv_env_CC_set= -ac_cv_env_CC_value= -ac_cv_env_CFLAGS_set=set -ac_cv_env_CFLAGS_value=-g -ac_cv_env_CPPFLAGS_set= -ac_cv_env_CPPFLAGS_value= -ac_cv_env_CPP_set= -ac_cv_env_CPP_value= -ac_cv_env_CXXFLAGS_set= -ac_cv_env_CXXFLAGS_value= -ac_cv_env_CXX_set= -ac_cv_env_CXX_value= -ac_cv_env_LDFLAGS_set= -ac_cv_env_LDFLAGS_value= -ac_cv_env_LIBS_set= -ac_cv_env_LIBS_value= -ac_cv_env_XMKMF_set= -ac_cv_env_XMKMF_value= -ac_cv_env_build_alias_set= -ac_cv_env_build_alias_value= -ac_cv_env_host_alias_set= -ac_cv_env_host_alias_value= -ac_cv_env_target_alias_set= -ac_cv_env_target_alias_value= -ac_cv_func_connect=yes -ac_cv_func_gethostbyname=yes -ac_cv_func_putenv=yes -ac_cv_func_remove=yes -ac_cv_func_setenv=yes -ac_cv_func_shmat=yes -ac_cv_func_vfork=yes -ac_cv_have_x='have_x=yes ac_x_includes='\'''\'' ac_x_libraries='\'''\''' -ac_cv_header_GL_gl_h=yes -ac_cv_header_cairo_cairo_h=yes -ac_cv_header_dirent_h=yes -ac_cv_header_inttypes_h=yes -ac_cv_header_limits_h=yes -ac_cv_header_memory_h=yes -ac_cv_header_param_h=no -ac_cv_header_paths_h=yes -ac_cv_header_stdc=yes -ac_cv_header_stdint_h=yes -ac_cv_header_stdlib_h=yes -ac_cv_header_string_h=yes -ac_cv_header_strings_h=yes -ac_cv_header_sys_mman_h=yes -ac_cv_header_sys_stat_h=yes -ac_cv_header_sys_types_h=yes -ac_cv_header_unistd_h=yes -ac_cv_host=x86_64-unknown-linux-gnu -ac_cv_lib_GLU_gluNewTess=yes -ac_cv_lib_GL_glXCreateContext=yes -ac_cv_lib_ICE_IceConnectionNumber=yes -ac_cv_lib_Xext_XextFindDisplay=yes -ac_cv_lib_Xi_XOpenDevice=yes -ac_cv_lib_Xmu_XmuInternAtom=yes -ac_cv_lib_cairo_cairo_user_to_device=yes -ac_cv_objext=o -ac_cv_path_CSH=/bin/csh -ac_cv_path_EGREP='/bin/grep -E' -ac_cv_path_GCORE=/bin/gcore -ac_cv_path_GREP=/bin/grep -ac_cv_path_LD=/bin/ld -ac_cv_path_M4=/bin/m4 -ac_cv_path_PYTHON3=/bin/python3 -ac_cv_path_install='/bin/install -c' -ac_cv_prog_CPP='gcc -E' -ac_cv_prog_ac_ct_CC=gcc -ac_cv_prog_ac_ct_CXX=g++ -ac_cv_prog_ac_ct_RANLIB=ranlib -ac_cv_prog_cc_c89= -ac_cv_prog_cc_g=yes -ac_cv_prog_cxx_g=yes -ac_cv_prog_gnu_ld=yes -ac_cv_search_strerror='none required' -ac_cv_sizeof_unsigned_int=4 -ac_cv_sizeof_unsigned_long=8 -ac_cv_sizeof_unsigned_long_long=8 -ac_cv_sizeof_void_p=8 -ac_cv_target=x86_64-unknown-linux-gnu - -## ----------------- ## -## Output variables. ## -## ----------------- ## - -ALL_TARGET='tcl' -CC='gcc' -CFLAGS='-g -m64 -fPIC' -CPP='gcc -E' -CPPFLAGS='' -CSH='/bin/csh' -CXX='g++' -CXXFLAGS='-g -O2' -DEFS='-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' -DEPEND_FLAG='-MM' -ECHO_C='' -ECHO_N='printf' -ECHO_T='' -EGREP='/bin/grep -E' -EXEEXT='' -EXTRA_LIB_SPECS='-ldl' -GCORE='/bin/gcore' -GREP='/bin/grep' -INC_SPECS='' -INSTALL_DATA='${INSTALL} -m 644' -INSTALL_PROGRAM='${INSTALL}' -INSTALL_SCRIPT='${INSTALL}' -INSTALL_TARGET='install-tcl' -LD='/bin/ld' -LDDL_FLAGS='-shared -Wl,-soname,$@ -Wl,--version-script=${MAGICDIR}/magic/symbol.map' -LDFLAGS='' -LD_RUN_PATH='' -LIBOBJS='' -LIBS='-lcairo -lGLU -lGL ' -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' -LTLIBOBJS='' -M4='/bin/m4' -MAGIC_REVISION='101' -MAGIC_VERSION='8.2' -MCPP='${MAGICDIR}/scripts/preproc.py' -OA='' -OA_LIBS='' -OBJEXT='o' -PACKAGE='magic' -PACKAGE_BUGREPORT='' -PACKAGE_NAME='' -PACKAGE_STRING='' -PACKAGE_TARNAME='' -PACKAGE_URL='' -PACKAGE_VERSION='' -PATH_SEPARATOR=':' -PYTHON3='/bin/python3' -RANLIB='ranlib' -SCPP='gcc -E -x c' -SCRIPTS='' -SHDLIB_EXT='.so' -SHELL='/bin/sh' -SHLIB_CFLAGS='-Wimplicit-int -fPIC' -SHLIB_LD='' -SHLIB_LIB_SPECS='' -TCLSH_EXE='/usr/bin/tclsh' -TCL_LIB_DIR='/usr/lib' -WISH_EXE='/usr/bin/wish' -XMKMF='' -X_CFLAGS='' -X_EXTRA_LIBS='' -X_LIBS='' -X_PRE_LIBS=' -lSM -lICE' -ac_ct_CC='gcc' -ac_ct_CXX='g++' -bindir='${exec_prefix}/bin' -build='x86_64-unknown-linux-gnu' -build_alias='' -build_cpu='x86_64' -build_os='linux-gnu' -build_vendor='unknown' -cadinstall=' graphics tcltk' -datadir='${datarootdir}' -datarootdir='${prefix}/share' -docdir='${datarootdir}/doc/${PACKAGE}' -dvidir='${docdir}' -exec_prefix='${prefix}' -extra_defs=' -DCAD_DIR=\"${LIBDIR}\" -DBIN_DIR=\"${BINDIR}\" -DTCL_DIR=\"${TCLDIR}\"' -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' -gr_cflags='' -gr_dflags=' -DX11 -DXLIB -DOGL -DCAIRO' -gr_hprog='' -gr_hsrcs='' -gr_libs=' -lX11 -lGL -lGLU -lXi -lXmu -lXext -lm -lcairo -lfontconfig -lfreetype -lstdc++' -gr_srcs=' ${TK_SRCS} ${TOGL_SRCS} ${TCAIRO_SRCS} ${TKCOMMON_SRCS}' -host='x86_64-unknown-linux-gnu' -host_alias='' -host_cpu='x86_64' -host_os='linux-gnu' -host_vendor='unknown' -htmldir='${docdir}' -includedir='${prefix}/include' -infodir='${datarootdir}/info' -ld_extra_libs='' -ld_extra_objs='' -libdir='${exec_prefix}/lib' -libexecdir='${exec_prefix}/libexec' -localedir='${datarootdir}/locale' -localstatedir='${prefix}/var' -mandir='${datarootdir}/man' -modules=' ext2sim ext2spice calma cif plot lef garouter grouter irouter mzrouter router gcr tcltk' -oldincludedir='/usr/include' -pdfdir='${docdir}' -prefix='/usr/local' -program_transform_name='s,x,x,' -programs=' net2ir tcltk' -psdir='${docdir}' -rl_defs='' -rl_libs='' -sbindir='${exec_prefix}/sbin' -sharedstatedir='${prefix}/com' -stub_defs=' -DUSE_TCL_STUBS -DUSE_TK_STUBS' -sub_extra_libs='' -sysconfdir='${prefix}/etc' -target='x86_64-unknown-linux-gnu' -target_alias='' -target_cpu='x86_64' -target_os='linux-gnu' -target_vendor='unknown' -top_extra_libs='' -unused=' readline lisp' - -## ----------- ## -## confdefs.h. ## -## ----------- ## - -/* confdefs.h */ -#define PACKAGE_NAME "" -#define PACKAGE_TARNAME "" -#define PACKAGE_VERSION "" -#define PACKAGE_STRING "" -#define PACKAGE_BUGREPORT "" -#define PACKAGE_URL "" -#define MAGIC_VERSION "8.2" -#define MAGIC_REVISION "101" -#define STDC_HEADERS 1 -#define HAVE_SYS_TYPES_H 1 -#define HAVE_SYS_STAT_H 1 -#define HAVE_STDLIB_H 1 -#define HAVE_STRING_H 1 -#define HAVE_MEMORY_H 1 -#define HAVE_STRINGS_H 1 -#define HAVE_INTTYPES_H 1 -#define HAVE_STDINT_H 1 -#define HAVE_UNISTD_H 1 -#define SIZEOF_VOID_P 8 -#define SIZEOF_UNSIGNED_INT 4 -#define SIZEOF_UNSIGNED_LONG 8 -#define SIZEOF_UNSIGNED_LONG_LONG 8 -#define STDC_HEADERS 1 -#define HAVE_SETENV 1 -#define HAVE_PUTENV 1 -#define HAVE_SYS_MMAN_H 1 -#define HAVE_DIRENT_H 1 -#define HAVE_LIMITS_H 1 -#define HAVE_PATHS_H 1 -#define HAVE_VA_COPY 1 -#define HAVE___VA_COPY 1 -#define FILE_LOCKS 1 -#define CALMA_MODULE 1 -#define CIF_MODULE 1 -#define PLOT_MODULE 1 -#define LEF_MODULE 1 -#define ROUTE_MODULE 1 -#define USE_NEW_MACROS 1 -#define HAVE_LIBGL 1 -#define HAVE_LIBGLU 1 -#define VECTOR_FONTS 1 -#define HAVE_LIBCAIRO 1 -#define MAGIC_WRAPPER 1 -#define THREE_D 1 -#define linux 1 -#define SYSV 1 -#define ISC 1 - -configure: exit 0 diff --git a/scripts/config.status b/scripts/config.status deleted file mode 100755 index d8bc0035..00000000 --- a/scripts/config.status +++ /dev/null @@ -1,958 +0,0 @@ -#! /bin/sh -# Generated by configure. -# Run this file to recreate the current configuration. -# Compiler output produced by configure, useful for debugging -# configure, is in config.log if it exists. - -debug=false -ac_cs_recheck=false -ac_cs_silent=false - -SHELL=${CONFIG_SHELL-/bin/sh} -export SHELL -## -------------------- ## -## M4sh Initialization. ## -## -------------------- ## - -# Be more Bourne compatible -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# Find who we are. Look in the path if we contain no directory separator. -as_myself= -case $0 in #(( - *[\\/]* ) as_myself=$0 ;; - *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break - done -IFS=$as_save_IFS - - ;; -esac -# We did not find ourselves, most probably we were run as `sh COMMAND' -# in which case we are not to be found in the path. -if test "x$as_myself" = x; then - as_myself=$0 -fi -if test ! -f "$as_myself"; then - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - - -# as_fn_error STATUS ERROR [LINENO LOG_FD] -# ---------------------------------------- -# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are -# provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with STATUS, using 1 if that was 0. -as_fn_error () -{ - as_status=$1; test $as_status -eq 0 && as_status=1 - if test "$4"; then - as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$as_me: error: $2" >&2 - as_fn_exit $as_status -} # as_fn_error - - -# as_fn_set_status STATUS -# ----------------------- -# Set $? to STATUS, without forking. -as_fn_set_status () -{ - return $1 -} # as_fn_set_status - -# as_fn_exit STATUS -# ----------------- -# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. -as_fn_exit () -{ - set +e - as_fn_set_status $1 - exit $1 -} # as_fn_exit - -# as_fn_unset VAR -# --------------- -# Portably unset VAR. -as_fn_unset () -{ - { eval $1=; unset $1;} -} -as_unset=as_fn_unset -# as_fn_append VAR VALUE -# ---------------------- -# Append the text in VALUE to the end of the definition contained in VAR. Take -# advantage of any shell optimizations that allow amortized linear growth over -# repeated appends, instead of the typical quadratic growth present in naive -# implementations. -if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : - eval 'as_fn_append () - { - eval $1+=\$2 - }' -else - as_fn_append () - { - eval $1=\$$1\$2 - } -fi # as_fn_append - -# as_fn_arith ARG... -# ------------------ -# Perform arithmetic evaluation on the ARGs, and store the result in the -# global $as_val. Take advantage of shells that can avoid forks. The arguments -# must be portable across $(()) and expr. -if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : - eval 'as_fn_arith () - { - as_val=$(( $* )) - }' -else - as_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -if expr a : '\(a\)' >/dev/null 2>&1 && - test "X`expr 00001 : '.*\(...\)'`" = X001; then - as_expr=expr -else - as_expr=false -fi - -if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then - as_basename=basename -else - as_basename=false -fi - -if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then - as_dirname=dirname -else - as_dirname=false -fi - -as_me=`$as_basename -- "$0" || -$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ - X"$0" : 'X\(//\)$' \| \ - X"$0" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/"$0" | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - -# Avoid depending upon Character Ranges. -as_cr_letters='abcdefghijklmnopqrstuvwxyz' -as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' -as_cr_Letters=$as_cr_letters$as_cr_LETTERS -as_cr_digits='0123456789' -as_cr_alnum=$as_cr_Letters$as_cr_digits - -ECHO_C= ECHO_N= ECHO_T= -case `echo -n x` in #((((( --n*) - case `echo 'xy\c'` in - *c*) ECHO_T=' ';; # ECHO_T is single tab character. - xy) ECHO_C='\c';; - *) echo `echo ksh88 bug on AIX 6.1` > /dev/null - ECHO_T=' ';; - esac;; -*) - ECHO_N='-n';; -esac - -rm -f conf$$ conf$$.exe conf$$.file -if test -d conf$$.dir; then - rm -f conf$$.dir/conf$$.file -else - rm -f conf$$.dir - mkdir conf$$.dir 2>/dev/null -fi -if (echo >conf$$.file) 2>/dev/null; then - if ln -s conf$$.file conf$$ 2>/dev/null; then - as_ln_s='ln -s' - # ... but there are two gotchas: - # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. - # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -pR'. - ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -pR' - elif ln conf$$.file conf$$ 2>/dev/null; then - as_ln_s=ln - else - as_ln_s='cp -pR' - fi -else - as_ln_s='cp -pR' -fi -rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -rmdir conf$$.dir 2>/dev/null - - -# as_fn_mkdir_p -# ------------- -# Create "$as_dir" as a directory, including parents if necessary. -as_fn_mkdir_p () -{ - - case $as_dir in #( - -*) as_dir=./$as_dir;; - esac - test -d "$as_dir" || eval $as_mkdir_p || { - as_dirs= - while :; do - case $as_dir in #( - *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( - *) as_qdir=$as_dir;; - esac - as_dirs="'$as_qdir' $as_dirs" - as_dir=`$as_dirname -- "$as_dir" || -$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$as_dir" : 'X\(//\)[^/]' \| \ - X"$as_dir" : 'X\(//\)$' \| \ - X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$as_dir" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - test -d "$as_dir" && break - done - test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" - - -} # as_fn_mkdir_p -if mkdir -p . 2>/dev/null; then - as_mkdir_p='mkdir -p "$as_dir"' -else - test -d ./-p && rmdir ./-p - as_mkdir_p=false -fi - - -# as_fn_executable_p FILE -# ----------------------- -# Test if FILE is an executable regular file. -as_fn_executable_p () -{ - test -f "$1" && test -x "$1" -} # as_fn_executable_p -as_test_x='test -x' -as_executable_p=as_fn_executable_p - -# Sed expression to map a string onto a valid CPP name. -as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" - -# Sed expression to map a string onto a valid variable name. -as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -exec 6>&1 -## ----------------------------------- ## -## Main body of $CONFIG_STATUS script. ## -## ----------------------------------- ## -# Save the log message, to keep $0 and so on meaningful, and to -# report actual input values of CONFIG_FILES etc. instead of their -# values after options handling. -ac_log=" -This file was extended by $as_me, which was -generated by GNU Autoconf 2.69. Invocation command line was - - CONFIG_FILES = $CONFIG_FILES - CONFIG_HEADERS = $CONFIG_HEADERS - CONFIG_LINKS = $CONFIG_LINKS - CONFIG_COMMANDS = $CONFIG_COMMANDS - $ $0 $@ - -on `(hostname || uname -n) 2>/dev/null | sed 1q` -" - -# Files that config.status was made for. -config_files=" defs.mak" - -ac_cs_usage="\ -\`$as_me' instantiates files and other configuration actions -from templates according to the current configuration. Unless the files -and actions are specified as TAGs, all are instantiated by default. - -Usage: $0 [OPTION]... [TAG]... - - -h, --help print this help, then exit - -V, --version print version number and configuration settings, then exit - --config print configuration, then exit - -q, --quiet, --silent - do not print progress messages - -d, --debug don't remove temporary files - --recheck update $as_me by reconfiguring in the same conditions - --file=FILE[:TEMPLATE] - instantiate the configuration file FILE - -Configuration files: -$config_files - -Report bugs to the package provider." - -ac_cs_config="'CFLAGS=-g'" -ac_cs_version="\ -config.status -configured by ./configure, generated by GNU Autoconf 2.69, - with options \"$ac_cs_config\" - -Copyright (C) 2012 Free Software Foundation, Inc. -This config.status script is free software; the Free Software Foundation -gives unlimited permission to copy, distribute and modify it." - -ac_pwd='/home/tim/gitsrc/magic/scripts' -srcdir='..' -INSTALL='/bin/install -c' -test -n "$AWK" || AWK=awk -# The default lists apply if the user does not specify any file. -ac_need_defaults=: -while test $# != 0 -do - case $1 in - --*=?*) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` - ac_shift=: - ;; - --*=) - ac_option=`expr "X$1" : 'X\([^=]*\)='` - ac_optarg= - ac_shift=: - ;; - *) - ac_option=$1 - ac_optarg=$2 - ac_shift=shift - ;; - esac - - case $ac_option in - # Handling of the options. - -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) - ac_cs_recheck=: ;; - --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) - $as_echo "$ac_cs_version"; exit ;; - --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; - '') as_fn_error $? "missing file argument" ;; - esac - as_fn_append CONFIG_FILES " '$ac_optarg'" - ac_need_defaults=false;; - --he | --h | --help | --hel | -h ) - $as_echo "$ac_cs_usage"; exit ;; - -q | -quiet | --quiet | --quie | --qui | --qu | --q \ - | -silent | --silent | --silen | --sile | --sil | --si | --s) - ac_cs_silent=: ;; - - # This is an error. - -*) as_fn_error $? "unrecognized option: \`$1' -Try \`$0 --help' for more information." ;; - - *) as_fn_append ac_config_targets " $1" - ac_need_defaults=false ;; - - esac - shift -done - -ac_configure_extra_args= - -if $ac_cs_silent; then - exec 6>/dev/null - ac_configure_extra_args="$ac_configure_extra_args --silent" -fi - -if $ac_cs_recheck; then - set X /bin/sh './configure' 'CFLAGS=-g' $ac_configure_extra_args --no-create --no-recursion - shift - $as_echo "running CONFIG_SHELL=/bin/sh $*" >&6 - CONFIG_SHELL='/bin/sh' - export CONFIG_SHELL - exec "$@" -fi - -exec 5>>config.log -{ - echo - sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX -## Running $as_me. ## -_ASBOX - $as_echo "$ac_log" -} >&5 - - -# Handling of arguments. -for ac_config_target in $ac_config_targets -do - case $ac_config_target in - "defs.mak") CONFIG_FILES="$CONFIG_FILES defs.mak" ;; - - *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; - esac -done - - -# If the user did not use the arguments to specify the items to instantiate, -# then the envvar interface is used. Set only those that are not. -# We use the long form for the default assignment because of an extremely -# bizarre bug on SunOS 4.1.3. -if $ac_need_defaults; then - test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files -fi - -# Have a temporary directory for convenience. Make it in the build tree -# simply because there is no reason against having it here, and in addition, -# creating and moving files from /tmp can sometimes cause problems. -# Hook for its removal unless debugging. -# Note that there is a small window in which the directory will not be cleaned: -# after its creation but before its name has been assigned to `$tmp'. -$debug || -{ - tmp= ac_tmp= - trap 'exit_status=$? - : "${ac_tmp:=$tmp}" - { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status -' 0 - trap 'as_fn_exit 1' 1 2 13 15 -} -# Create a (secure) tmp directory for tmp files. - -{ - tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -d "$tmp" -} || -{ - tmp=./conf$$-$RANDOM - (umask 077 && mkdir "$tmp") -} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 -ac_tmp=$tmp - -# Set up the scripts for CONFIG_FILES section. -# No need to generate them if there are no CONFIG_FILES. -# This happens for instance with `./config.status config.h'. -if test -n "$CONFIG_FILES"; then - - -ac_cr=`echo X | tr X '\015'` -# On cygwin, bash can eat \r inside `` if the user requested igncr. -# But we know of no other shell where ac_cr would be empty at this -# point, so we can use a bashism as a fallback. -if test "x$ac_cr" = x; then - eval ac_cr=\$\'\\r\' -fi -ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` -if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\\r' -else - ac_cs_awk_cr=$ac_cr -fi - -echo 'BEGIN {' >"$ac_tmp/subs1.awk" && -cat >>"$ac_tmp/subs1.awk" <<\_ACAWK && -S["LTLIBOBJS"]="" -S["LIBOBJS"]="" -S["INSTALL_TARGET"]="install-tcl" -S["ALL_TARGET"]="tcl" -S["OA_LIBS"]="" -S["OA"]="" -S["MAGIC_REVISION"]="101" -S["MAGIC_VERSION"]="8.2" -S["SCPP"]="gcc -E -x c" -S["MCPP"]="${MAGICDIR}/scripts/preproc.py" -S["LD_RUN_PATH"]="" -S["SHLIB_CFLAGS"]="-Wimplicit-int -fPIC" -S["DEPEND_FLAG"]="-MM" -S["gr_hprog"]="" -S["gr_hsrcs"]="" -S["gr_srcs"]=" ${TK_SRCS} ${TOGL_SRCS} ${TCAIRO_SRCS} ${TKCOMMON_SRCS}" -S["gr_dflags"]=" -DX11 -DXLIB -DOGL -DCAIRO" -S["gr_cflags"]="" -S["rl_libs"]="" -S["rl_defs"]="" -S["cadinstall"]=" graphics tcltk" -S["programs"]=" net2ir tcltk" -S["unused"]=" readline lisp" -S["modules"]=" ext2sim ext2spice calma cif plot lef garouter grouter irouter mzrouter router gcr tcltk" -S["sub_extra_libs"]="" -S["top_extra_libs"]="" -S["ld_extra_objs"]="" -S["ld_extra_libs"]="" -S["stub_defs"]=" -DUSE_TCL_STUBS -DUSE_TK_STUBS" -S["extra_defs"]=" -DCAD_DIR=\\\"${LIBDIR}\\\" -DBIN_DIR=\\\"${BINDIR}\\\" -DTCL_DIR=\\\"${TCLDIR}\\\"" -S["extra_libs"]=" ${MAGICDIR}/ext2sim/libext2sim.o ${MAGICDIR}/ext2spice/libext2spice.o ${MAGICDIR}/calma/libcalma.o ${MAGICDIR}/cif/libcif.o ${MAGICDIR}/plot/libplo"\ -"t.o ${MAGICDIR}/lef/liblef.o ${MAGICDIR}/extflat/libextflat.o ${MAGICDIR}/garouter/libgarouter.o ${MAGICDIR}/mzrouter/libmzrouter.o ${MAGICDIR}/rou"\ -"ter/librouter.o ${MAGICDIR}/irouter/libirouter.o ${MAGICDIR}/grouter/libgrouter.o ${MAGICDIR}/gcr/libgcr.o ${MAGICDIR}/tcltk/libtcltk.o" -S["SCRIPTS"]="" -S["PACKAGE"]="magic" -S["gr_libs"]=" -lX11 -lGL -lGLU -lXi -lXmu -lXext -lm -lcairo -lfontconfig -lfreetype -lstdc++" -S["TCL_LIB_DIR"]="/usr/lib" -S["TCLSH_EXE"]="/usr/bin/tclsh" -S["WISH_EXE"]="/usr/bin/wish" -S["LIB_SPECS_NOSTUB"]=" -L/usr/lib64 -ltk8.6 -L/usr/lib64 -ltcl8.6" -S["LIB_SPECS"]=" -L/usr/lib64 -ltkstub8.6 -L/usr/lib64 -ltclstub8.6" -S["INC_SPECS"]="" -S["EXTRA_LIB_SPECS"]="-ldl" -S["SHLIB_LIB_SPECS"]="" -S["LDDL_FLAGS"]="-shared -Wl,-soname,$@ -Wl,--version-script=${MAGICDIR}/magic/symbol.map" -S["LD"]="/bin/ld" -S["SHLIB_LD"]="" -S["SHDLIB_EXT"]=".so" -S["X_EXTRA_LIBS"]="" -S["X_LIBS"]="" -S["X_PRE_LIBS"]=" -lSM -lICE" -S["X_CFLAGS"]="" -S["XMKMF"]="" -S["CSH"]="/bin/csh" -S["GCORE"]="/bin/gcore" -S["EGREP"]="/bin/grep -E" -S["GREP"]="/bin/grep" -S["PYTHON3"]="/bin/python3" -S["M4"]="/bin/m4" -S["RANLIB"]="ranlib" -S["INSTALL_DATA"]="${INSTALL} -m 644" -S["INSTALL_SCRIPT"]="${INSTALL}" -S["INSTALL_PROGRAM"]="${INSTALL}" -S["ac_ct_CXX"]="g++" -S["CXXFLAGS"]="-g -O2" -S["CXX"]="g++" -S["CPP"]="gcc -E" -S["OBJEXT"]="o" -S["EXEEXT"]="" -S["ac_ct_CC"]="gcc" -S["CPPFLAGS"]="" -S["LDFLAGS"]="" -S["CFLAGS"]="-g -m64 -fPIC" -S["CC"]="gcc" -S["target_os"]="linux-gnu" -S["target_vendor"]="unknown" -S["target_cpu"]="x86_64" -S["target"]="x86_64-unknown-linux-gnu" -S["host_os"]="linux-gnu" -S["host_vendor"]="unknown" -S["host_cpu"]="x86_64" -S["host"]="x86_64-unknown-linux-gnu" -S["build_os"]="linux-gnu" -S["build_vendor"]="unknown" -S["build_cpu"]="x86_64" -S["build"]="x86_64-unknown-linux-gnu" -S["target_alias"]="" -S["host_alias"]="" -S["build_alias"]="" -S["LIBS"]="-lcairo -lGLU -lGL " -S["ECHO_T"]="" -S["ECHO_N"]="-n" -S["ECHO_C"]="" -S["DEFS"]="-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 -DH"\ -"AVE_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 -DHAV"\ -"E_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 -DH"\ -"AVE_LIBGL=1 -DHAVE_LIBGLU=1 -DVECTOR_FONTS=1 -DHAVE_LIBCAIRO=1 -DMAGIC_WRAPPER=1 -DTHREE_D=1 -Dlinux=1 -DSYSV=1 -DISC=1" -S["mandir"]="${datarootdir}/man" -S["localedir"]="${datarootdir}/locale" -S["libdir"]="${exec_prefix}/lib" -S["psdir"]="${docdir}" -S["pdfdir"]="${docdir}" -S["dvidir"]="${docdir}" -S["htmldir"]="${docdir}" -S["infodir"]="${datarootdir}/info" -S["docdir"]="${datarootdir}/doc/${PACKAGE}" -S["oldincludedir"]="/usr/include" -S["includedir"]="${prefix}/include" -S["localstatedir"]="${prefix}/var" -S["sharedstatedir"]="${prefix}/com" -S["sysconfdir"]="${prefix}/etc" -S["datadir"]="${datarootdir}" -S["datarootdir"]="${prefix}/share" -S["libexecdir"]="${exec_prefix}/libexec" -S["sbindir"]="${exec_prefix}/sbin" -S["bindir"]="${exec_prefix}/bin" -S["program_transform_name"]="s,x,x," -S["prefix"]="/usr/local" -S["exec_prefix"]="${prefix}" -S["PACKAGE_URL"]="" -S["PACKAGE_BUGREPORT"]="" -S["PACKAGE_STRING"]="" -S["PACKAGE_VERSION"]="" -S["PACKAGE_TARNAME"]="" -S["PACKAGE_NAME"]="" -S["PATH_SEPARATOR"]=":" -S["SHELL"]="/bin/sh" -_ACAWK -cat >>"$ac_tmp/subs1.awk" <<_ACAWK && - for (key in S) S_is_set[key] = 1 - FS = "" - -} -{ - line = $ 0 - nfields = split(line, field, "@") - substed = 0 - len = length(field[1]) - for (i = 2; i < nfields; i++) { - key = field[i] - keylen = length(key) - if (S_is_set[key]) { - value = S[key] - line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) - len += length(value) + length(field[++i]) - substed = 1 - } else - len += 1 + keylen - } - - print line -} - -_ACAWK -if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then - sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" -else - cat -fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ - || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 -fi # test -n "$CONFIG_FILES" - - -eval set X " :F $CONFIG_FILES " -shift -for ac_tag -do - case $ac_tag in - :[FHLC]) ac_mode=$ac_tag; continue;; - esac - case $ac_mode$ac_tag in - :[FHL]*:*);; - :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; - :[FH]-) ac_tag=-:-;; - :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; - esac - ac_save_IFS=$IFS - IFS=: - set x $ac_tag - IFS=$ac_save_IFS - shift - ac_file=$1 - shift - - case $ac_mode in - :L) ac_source=$1;; - :[FH]) - ac_file_inputs= - for ac_f - do - case $ac_f in - -) ac_f="$ac_tmp/stdin";; - *) # Look for the file first in the build tree, then in the source tree - # (if the path is not absolute). The absolute path cannot be DOS-style, - # because $ac_f cannot contain `:'. - test -f "$ac_f" || - case $ac_f in - [\\/$]*) false;; - *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; - esac || - as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; - esac - case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac - as_fn_append ac_file_inputs " '$ac_f'" - done - - # Let's still pretend it is `configure' which instantiates (i.e., don't - # use $as_me), people would be surprised to read: - # /* config.h. Generated by config.status. */ - configure_input='Generated from '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' - `' by configure.' - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} - fi - # Neutralize special characters interpreted by sed in replacement strings. - case $configure_input in #( - *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$configure_input" | - sed 's/[\\\\&|]/\\\\&/g'`;; #( - *) ac_sed_conf_input=$configure_input;; - esac - - case $ac_tag in - *:-:* | *:-) cat >"$ac_tmp/stdin" \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; - esac - ;; - esac - - ac_dir=`$as_dirname -- "$ac_file" || -$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$ac_file" : 'X\(//\)[^/]' \| \ - X"$ac_file" : 'X\(//\)$' \| \ - X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$ac_file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ - s//\1/ - q - } - /^X\(\/\/\)[^/].*/{ - s//\1/ - q - } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` - as_dir="$ac_dir"; as_fn_mkdir_p - ac_builddir=. - -case "$ac_dir" in -.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; -*) - ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` - case $ac_top_builddir_sub in - "") ac_top_builddir_sub=. ac_top_build_prefix= ;; - *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; - esac ;; -esac -ac_abs_top_builddir=$ac_pwd -ac_abs_builddir=$ac_pwd$ac_dir_suffix -# for backward compatibility: -ac_top_builddir=$ac_top_build_prefix - -case $srcdir in - .) # We are building in place. - ac_srcdir=. - ac_top_srcdir=$ac_top_builddir_sub - ac_abs_top_srcdir=$ac_pwd ;; - [\\/]* | ?:[\\/]* ) # Absolute name. - ac_srcdir=$srcdir$ac_dir_suffix; - ac_top_srcdir=$srcdir - ac_abs_top_srcdir=$srcdir ;; - *) # Relative name. - ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix - ac_top_srcdir=$ac_top_build_prefix$srcdir - ac_abs_top_srcdir=$ac_pwd/$srcdir ;; -esac -ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix - - - case $ac_mode in - :F) - # - # CONFIG_FILE - # - - case $INSTALL in - [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; - *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; - esac -# If the template does not know about datarootdir, expand it. -# FIXME: This hack should be removed a few years after 2.60. -ac_datarootdir_hack=; ac_datarootdir_seen= -ac_sed_dataroot=' -/datarootdir/ { - p - q -} -/@datadir@/p -/@docdir@/p -/@infodir@/p -/@localedir@/p -/@mandir@/p' -case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in -*datarootdir*) ac_datarootdir_seen=yes;; -*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} - ac_datarootdir_hack=' - s&@datadir@&${datarootdir}&g - s&@docdir@&${datarootdir}/doc/${PACKAGE}&g - s&@infodir@&${datarootdir}/info&g - s&@localedir@&${datarootdir}/locale&g - s&@mandir@&${datarootdir}/man&g - s&\${datarootdir}&${prefix}/share&g' ;; -esac -ac_sed_extra=" - -:t -/@[a-zA-Z_][a-zA-Z_0-9]*@/!b -s|@configure_input@|$ac_sed_conf_input|;t t -s&@top_builddir@&$ac_top_builddir_sub&;t t -s&@top_build_prefix@&$ac_top_build_prefix&;t t -s&@srcdir@&$ac_srcdir&;t t -s&@abs_srcdir@&$ac_abs_srcdir&;t t -s&@top_srcdir@&$ac_top_srcdir&;t t -s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t -s&@builddir@&$ac_builddir&;t t -s&@abs_builddir@&$ac_abs_builddir&;t t -s&@abs_top_builddir@&$ac_abs_top_builddir&;t t -s&@INSTALL@&$ac_INSTALL&;t t -$ac_datarootdir_hack -" -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ - >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - -test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ - "$ac_tmp/out"`; test -z "$ac_out"; } && - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&5 -$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined" >&2;} - - rm -f "$ac_tmp/stdin" - case $ac_file in - -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; - *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; - esac \ - || as_fn_error $? "could not create $ac_file" "$LINENO" 5 - ;; - - - - esac - -done # for ac_tag - - -as_fn_exit 0 diff --git a/scripts/defs.mak b/scripts/defs.mak deleted file mode 100644 index c3bb2089..00000000 --- a/scripts/defs.mak +++ /dev/null @@ -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} From f429e4eca4cdc31ce621930b4f03f6ef7e088392 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 9 Aug 2019 16:52:20 -0400 Subject: [PATCH 010/121] Copied the text of the BSD copyright in the C source code into its own file, to be consistent with most other software these days. --- COPYRIGHT | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 COPYRIGHT diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 00000000..015556c5 --- /dev/null +++ b/COPYRIGHT @@ -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. From 8c75f81cc41d137acd374aab830be99b575f219f Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 19 Aug 2019 14:11:02 -0400 Subject: [PATCH 011/121] Revised the method for multiple extraction models per device type to be more robust and not depend on the ordering of the devices in the techfile. The extraction method now keeps a mask of which properties of the device (source/drain types, substrate type, identifier type) have been found, and will look only for device records that match what is known about the device. Added a device identifier record which is the last record before parameters if the record begins with "+". This allows marker layers to be placed over a device such that it will extract with a different type. This helps reduce the complexity of the techfile and allows certain specialized devices like RF or ESD to be identified without a separate layer type for the device. --- extract/ExtBasic.c | 759 +++++++++++++++++++++++++++++-------------- extract/ExtTech.c | 268 ++++++++------- extract/ExtTest.c | 21 +- extract/ExtTimes.c | 2 +- extract/extractInt.h | 143 ++++---- resis/ResBasic.c | 23 +- resis/ResConDCS.c | 35 +- resis/ResMain.c | 36 +- resis/ResPrint.c | 6 +- resis/ResReadSim.c | 4 +- resis/ResSimple.c | 6 +- resis/ResUtils.c | 25 +- sim/SimExtract.c | 19 +- 13 files changed, 856 insertions(+), 491 deletions(-) diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 381cdcf1..89e32cb7 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -85,8 +85,16 @@ typedef struct /* Position of each terminal (below) tile position */ Point pt; } TermTilePos; +/* Field definitions for tr_devmatch */ +#define MATCH_ID 0x01 /* Device matches identifier in devrec */ +#define MATCH_SUB 0x02 /* Device matches substrate type in devrec */ +#define MATCH_TERM 0x04 /* Device matches terminal in devrec */ +/* (additional fields: bit shifts up by 1 for each defined device terminal) */ + struct transRec { + ExtDevice *tr_devrec; /* Device record in ExtCurStyle */ + int tr_devmatch; /* Fields of tr_devrec that match device */ int tr_nterm; /* Number of terminals */ int tr_gatelen; /* Perimeter of connection to gate */ NodeRegion *tr_gatenode; /* Node region for gate terminal */ @@ -134,6 +142,7 @@ void extOutputNodes(); int extTransTileFunc(); int extTransPerimFunc(); int extTransFindSubs(); +int extTransFindId(); int extAnnularTileFunc(); int extResistorTileFunc(); @@ -214,8 +223,8 @@ extBasic(def, outFile) * the regions. */ transList = (TransRegion *) ExtFindRegions(def, &TiPlaneRect, - &ExtCurStyle->exts_transMask, - ExtCurStyle->exts_transConn, + &ExtCurStyle->exts_deviceMask, + ExtCurStyle->exts_deviceConn, extUnInit, extTransFirst, extTransEach); ExtResetTiles(def, extUnInit); @@ -241,7 +250,7 @@ extBasic(def, outFile) scontext.scx_area.r_ur.p_x++; scontext.scx_area.r_ur.p_y++; - if (DBTreeSrTiles(&scontext, &ExtCurStyle->exts_transMask, 0, + if (DBTreeSrTiles(&scontext, &ExtCurStyle->exts_deviceMask, 0, extFoundFunc, (ClientData)def) != 0) reg->treg_type = TT_SPACE; /* Disables the trans record */ } @@ -1429,6 +1438,7 @@ extOutputParameters(def, transList, outFile) TransRegion *reg; TileType t; TileTypeBitMask tmask; + ExtDevice *devptr; TTMaskZero(&tmask); @@ -1450,86 +1460,47 @@ extOutputParameters(def, transList, outFile) { if (TTMaskHasType(&tmask, t)) { - plist = ExtCurStyle->exts_deviceParams[t]; - if (plist != (ParamList *)NULL) + /* Note: If there are multiple variants of a device type, they */ + /* will all be listed even if they are not all present in the */ + /* design. */ + + for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next) { - fprintf(outFile, "parameters %s", ExtCurStyle->exts_transName[t]); - for (; plist != NULL; plist = plist->pl_next) + plist = devptr->exts_deviceParams; + if (plist != (ParamList *)NULL) { - if (plist->pl_param[1] != '\0') + fprintf(outFile, "parameters %s", devptr->exts_deviceName); + for (; plist != NULL; plist = plist->pl_next) { - if (plist->pl_scale != 1.0) - fprintf(outFile, " %c%c=%s*%g", + if (plist->pl_param[1] != '\0') + { + if (plist->pl_scale != 1.0) + fprintf(outFile, " %c%c=%s*%g", plist->pl_param[0], plist->pl_param[1], plist->pl_name, plist->pl_scale); - else - fprintf(outFile, " %c%c=%s", plist->pl_param[0], + else + fprintf(outFile, " %c%c=%s", plist->pl_param[0], plist->pl_param[1], plist->pl_name); - } - else - { - if (plist->pl_scale != 1.0) - fprintf(outFile, " %c=%s*%g", + } + else + { + if (plist->pl_scale != 1.0) + fprintf(outFile, " %c=%s*%g", plist->pl_param[0], plist->pl_name, plist->pl_scale); - else - fprintf(outFile, " %c=%s", plist->pl_param[0], + else + fprintf(outFile, " %c=%s", plist->pl_param[0], plist->pl_name); + + } } + fprintf(outFile, "\n"); } - fprintf(outFile, "\n"); } } } } -/* - * ---------------------------------------------------------------------------- - * - * extGetNativeResistClass() -- - * - * For the purpose of generating a node area and perimeter value to output - * to a subcircuit call as a passed parameter. The value output is assumed - * to refer only to the part of the whole eletrical node that is the - * actual device node, not to include connected metal, contacts, etc. - * Since area and perimeter information about a node is separated into - * resist classes, we need to figure out which resist class belongs to - * the device terminal type. - * - * "type" is the type identifier for the device (e.g., gate). "term" is - * the index of the terminal for the device. Devices with symmetrical - * terminals (e.g., MOSFETs), may have fewer type masks than terminals. - * - * ---------------------------------------------------------------------------- - */ - -int -extGetNativeResistClass(type, term) - TileType type; - int term; -{ - TileTypeBitMask *tmask, *rmask; - int i, n; - - tmask = NULL; - for (i = 0;; i++) - { - rmask = &ExtCurStyle->exts_transSDTypes[type][i]; - if (TTMaskIsZero(rmask)) break; - tmask = rmask; - if (i == term) break; - } - if (tmask == NULL) return -1; /* Error */ - - for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) - { - rmask = &ExtCurStyle->exts_typesByResistClass[n]; - if (TTMaskIntersect(rmask, tmask)) - return n; - } - return -1; /* Error */ -} - /* * ---------------------------------------------------------------------------- * @@ -1549,16 +1520,16 @@ extGetNativeResistClass(type, term) */ void -extOutputDevParams(reg, t, outFile, length, width) +extOutputDevParams(reg, devptr, outFile, length, width) TransRegion *reg; - TileType t; + ExtDevice *devptr; FILE *outFile; int length; int width; { ParamList *chkParam; - for (chkParam = ExtCurStyle->exts_deviceParams[t]; chkParam + for (chkParam = devptr->exts_deviceParams; chkParam != NULL; chkParam = chkParam->pl_next) { switch(tolower(chkParam->pl_param[0])) @@ -1585,9 +1556,9 @@ extOutputDevParams(reg, t, outFile, length, width) break; case 'c': fprintf(outFile, " %c=%g", chkParam->pl_param[0], - (ExtCurStyle->exts_transGateCap[t] + (extTransRec.tr_devrec->exts_deviceGateCap * reg->treg_area) + - (ExtCurStyle->exts_transSDCap[t] + (extTransRec.tr_devrec->exts_deviceSDCap * extTransRec.tr_perim)); break; case 's': @@ -1625,7 +1596,7 @@ extOutputDevParams(reg, t, outFile, length, width) * None. * * Side effects: - * Writes a number of 'fet' records to the file 'outFile'. + * Writes a number of 'device' records to the file 'outFile'. * * Interruptible. If SigInterruptPending is detected, we stop traversing * the transistor list and return. @@ -1641,6 +1612,7 @@ extOutputDevices(def, transList, outFile) { NodeRegion *node, *subsNode; TransRegion *reg; + ExtDevice *devptr; char *subsName; FindRegion arg; LabelList *ll; @@ -1663,13 +1635,15 @@ extOutputDevices(def, transList, outFile) * them with 'reg', then visit them again re-marking them with * the gate node (extGetRegion(reg->treg_tile)). */ + extTransRec.tr_devrec = (ExtDevice *)NULL; + extTransRec.tr_devmatch = 0; extTransRec.tr_nterm = 0; extTransRec.tr_gatelen = 0; extTransRec.tr_perim = 0; extTransRec.tr_subsnode = (NodeRegion *)NULL; arg.fra_def = def; - arg.fra_connectsTo = ExtCurStyle->exts_transConn; + arg.fra_connectsTo = ExtCurStyle->exts_deviceConn; extTransRec.tr_gatenode = (NodeRegion *) extGetRegion(reg->treg_tile); t = reg->treg_type; @@ -1686,7 +1660,6 @@ extOutputDevices(def, transList, outFile) /* 5/30/09---but, reinitialize the array out to MAXSD, */ /* or devices declaring minterms < maxterms screw up! */ - nsd = ExtCurStyle->exts_transSDCount[t]; for (i = 0; i < MAXSD; i++) extTransRec.tr_termnode[i] = NULL; /* Mark with reg and process each perimeter segment */ @@ -1712,16 +1685,20 @@ extOutputDevices(def, transList, outFile) /* search fails, give up and proceed with the reduced */ /* number of terminals. */ + devptr = extTransRec.tr_devrec; + if (devptr == NULL) continue; /* Bad device; do not output */ + + nsd = devptr->exts_deviceSDCount; while (extTransRec.tr_nterm < nsd) { TileTypeBitMask *tmask; - tmask = &ExtCurStyle->exts_transSDTypes[t][extTransRec.tr_nterm]; + tmask = &devptr->exts_deviceSDTypes[extTransRec.tr_nterm]; if (TTMaskIsZero(tmask)) break; if (!TTMaskIntersect(tmask, &DBPlaneTypes[reg->treg_pnum])) { node = NULL; - extTransFindSubs(reg->treg_tile, t, tmask, def, &node); + extTransFindSubs(reg->treg_tile, t, tmask, def, &node, NULL); if (node == NULL) break; extTransRec.tr_termnode[extTransRec.tr_nterm++] = node; } @@ -1774,18 +1751,18 @@ extOutputDevices(def, transList, outFile) /* * Output the transistor record. - * The type is ExtCurStyle->exts_transName[t], which should have + * The type is devptr->exts_deviceName, which should have * some meaning to the simulator we are producing this file for. * Use the default substrate node unless the transistor overlaps - * material whose type is in exts_transSubstrateTypes, in which + * material whose type is in exts_deviceSubstrateTypes, in which * case we use the node of the overlapped material. * * Technology files using the "substrate" keyword (magic-8.1 or * newer) should have the text "error" in the substrate node * name. */ - subsName = ExtCurStyle->exts_transSubstrateName[t]; - if (!TTMaskIsZero(&ExtCurStyle->exts_transSubstrateTypes[t]) + subsName = devptr->exts_deviceSubstrateName; + if (!TTMaskIsZero(&devptr->exts_deviceSubstrateTypes) && (subsNode = extTransRec.tr_subsnode)) { subsName = extNodeName(subsNode); @@ -1809,12 +1786,12 @@ extOutputDevices(def, transList, outFile) #endif /* Original-style FET record backward compatibility */ - if (ExtCurStyle->exts_deviceClass[t] != DEV_FET) + if (devptr->exts_deviceClass != DEV_FET) fprintf(outFile, "device "); fprintf(outFile, "%s %s", - extDevTable[ExtCurStyle->exts_deviceClass[t]], - ExtCurStyle->exts_transName[t]); + extDevTable[devptr->exts_deviceClass], + devptr->exts_deviceName); fprintf(outFile, " %d %d %d %d", reg->treg_ll.p_x, reg->treg_ll.p_y, @@ -1830,7 +1807,7 @@ extOutputDevices(def, transList, outFile) /* etc., etc. */ /* Tim, 2/20/03 */ - switch (ExtCurStyle->exts_deviceClass[t]) + switch (devptr->exts_deviceClass) { case DEV_FET: /* old style, perimeter & area */ fprintf(outFile, " %d %d \"%s\"", @@ -1887,7 +1864,7 @@ extOutputDevices(def, transList, outFile) /* because the substrate node (i.e., well) is the */ /* other terminal. */ - if (ExtDoWarn && (ExtCurStyle->exts_transSDCount[t] > 0)) + if (ExtDoWarn && (devptr->exts_deviceSDCount > 0)) extTransBad(def, reg->treg_tile, "Could not determine device boundary"); length = width = 0; @@ -1929,14 +1906,14 @@ extOutputDevices(def, transList, outFile) } - if (ExtCurStyle->exts_deviceClass[t] == DEV_MOSFET || - ExtCurStyle->exts_deviceClass[t] == DEV_ASYMMETRIC || - ExtCurStyle->exts_deviceClass[t] == DEV_BJT) + if (devptr->exts_deviceClass == DEV_MOSFET || + devptr->exts_deviceClass == DEV_ASYMMETRIC || + devptr->exts_deviceClass == DEV_BJT) { fprintf(outFile, " %d %d", length, width); } - extOutputDevParams(reg, t, outFile, length, width); + extOutputDevParams(reg, devptr, outFile, length, width); fprintf(outFile, " \"%s\"", (subsName == NULL) ? "None" : subsName); @@ -1945,14 +1922,14 @@ extOutputDevices(def, transList, outFile) case DEV_DIODE: /* Only handle the optional substrate node */ case DEV_NDIODE: case DEV_PDIODE: - extOutputDevParams(reg, t, outFile, length, width); + extOutputDevParams(reg, devptr, outFile, length, width); if (subsName != NULL) fprintf(outFile, " \"%s\"", subsName); break; case DEV_RES: case DEV_RSUBCKT: - hasModel = strcmp(ExtCurStyle->exts_transName[t], "None"); + hasModel = strcmp(devptr->exts_deviceName, "None"); length = extTransRec.tr_perim; isAnnular = FALSE; @@ -2059,7 +2036,7 @@ extOutputDevices(def, transList, outFile) "Resistor has zero width"); } - if (ExtCurStyle->exts_deviceClass[t] == DEV_RSUBCKT) + if (devptr->exts_deviceClass == DEV_RSUBCKT) { /* nothing */ } @@ -2072,9 +2049,9 @@ extOutputDevices(def, transList, outFile) else /* regular resistor */ fprintf(outFile, " %g", dres / 1000.0); /* mOhms -> Ohms */ - extOutputDevParams(reg, t, outFile, length, width); + extOutputDevParams(reg, devptr, outFile, length, width); - if (ExtCurStyle->exts_deviceClass[t] == DEV_RSUBCKT) + if (devptr->exts_deviceClass == DEV_RSUBCKT) { fprintf(outFile, " \"%s\"", (subsName == NULL) ? "None" : subsName); @@ -2085,7 +2062,7 @@ extOutputDevices(def, transList, outFile) case DEV_CAP: case DEV_CAPREV: case DEV_CSUBCKT: - hasModel = strcmp(ExtCurStyle->exts_transName[t], "None"); + hasModel = strcmp(devptr->exts_deviceName, "None"); if (hasModel) { for (n = 0; n < extTransRec.tr_nterm && @@ -2143,7 +2120,7 @@ extOutputDevices(def, transList, outFile) (void) ExtFindNeighbors(reg->treg_tile, arg.fra_pNum, &arg); } - if (ExtCurStyle->exts_deviceClass[t] == DEV_CSUBCKT) + if (devptr->exts_deviceClass == DEV_CSUBCKT) { /* (Nothing) */ } @@ -2163,9 +2140,9 @@ extOutputDevices(def, transList, outFile) fprintf(outFile, " \"%s\"", subsName); } - extOutputDevParams(reg, t, outFile, length, width); + extOutputDevParams(reg, devptr, outFile, length, width); - if (ExtCurStyle->exts_deviceClass[t] == DEV_CSUBCKT) + if (devptr->exts_deviceClass == DEV_CSUBCKT) { fprintf(outFile, " \"%s\"", (subsName == NULL) ? "None" : subsName); @@ -2173,8 +2150,8 @@ extOutputDevices(def, transList, outFile) } else { - dcap = (ExtCurStyle->exts_transGateCap[t] * reg->treg_area) + - (ExtCurStyle->exts_transSDCap[t] * extTransRec.tr_perim); + dcap = (devptr->exts_deviceGateCap * reg->treg_area) + + (devptr->exts_deviceSDCap * extTransRec.tr_perim); fprintf(outFile, " %g", dcap / 1000.0); /* aF -> fF */ } @@ -2191,7 +2168,7 @@ extOutputDevices(def, transList, outFile) /* device is asymmetric, in which case source and drain do not */ /* permute, and the terminal order is fixed. */ - if (TTMaskIsZero(&ExtCurStyle->exts_transSDTypes[t][1])) + if (TTMaskIsZero(&devptr->exts_deviceSDTypes[1])) ExtSortTerminals(&extTransRec, ll); /* each non-gate terminal */ @@ -2203,17 +2180,29 @@ extOutputDevices(def, transList, outFile) } } +/* Structure to hold a node region and a tile type */ + +typedef struct _node_type { + NodeRegion *region; + TileType layer; +} NodeAndType; + int -extTransFindSubs(tile, t, mask, def, sn) +extTransFindSubs(tile, t, mask, def, sn, layerptr) Tile *tile; TileType t; TileTypeBitMask *mask; CellDef *def; NodeRegion **sn; + TileType *layerptr; { Rect tileArea; int pNum; int extTransFindSubsFunc1(); /* Forward declaration */ + NodeAndType noderec; + + noderec.region = (NodeRegion *)NULL; + noderec.layer = TT_SPACE; TiToRect(tile, &tileArea); for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) @@ -2221,7 +2210,65 @@ extTransFindSubs(tile, t, mask, def, sn) if (TTMaskIntersect(&DBPlaneTypes[pNum], mask)) { if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], &tileArea, - mask, extTransFindSubsFunc1, (ClientData)sn)) + mask, extTransFindSubsFunc1, (ClientData)&noderec)) + { + *sn = noderec.region; + if (layerptr) *layerptr = noderec.layer; + return 1; + } + } + } + return 0; +} + +int +extTransFindSubsFunc1(tile, noderecptr) + Tile *tile; + NodeAndType *noderecptr; +{ + TileType type; + + /* Report split substrate region errors (two different substrate + * regions under the same device) + */ + + if (tile->ti_client != (ClientData) extUnInit) + { + if ((noderecptr->region != (NodeRegion *)NULL) && + (noderecptr->region != tile->ti_client)) + TxError("Warning: Split substrate under device at (%d %d)\n", + tile->ti_ll.p_x, tile->ti_ll.p_y); + if (IsSplit(tile)) + type = (SplitSide(tile)) ? SplitRightType(tile): SplitLeftType(tile); + else + type = TiGetTypeExact(tile); + + noderecptr->region = (NodeRegion *)tile->ti_client; + noderecptr->layer = type; + return 1; + } + return 0; +} + +int +extTransFindId(tile, mask, def, idtypeptr) + Tile *tile; + TileTypeBitMask *mask; + CellDef *def; + TileType *idtypeptr; +{ + TileType type; + Rect tileArea; + int pNum; + int extTransFindIdFunc1(); /* Forward declaration */ + + TiToRect(tile, &tileArea); + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + { + if (TTMaskIntersect(&DBPlaneTypes[pNum], mask)) + { + if (DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], &tileArea, + mask, extTransFindIdFunc1, (ClientData)idtypeptr)) return 1; } } @@ -2229,24 +2276,92 @@ extTransFindSubs(tile, t, mask, def, sn) } int -extTransFindSubsFunc1(tile, sn) +extTransFindIdFunc1(tile, idtypeptr) Tile *tile; - NodeRegion **sn; + TileType *idtypeptr; { - /* Report split substrate region errors (two different substrate - * regions under the same device) + /* + * ID Layer found overlapping device area, so return 1 to halt search. */ + if (IsSplit(tile)) + *idtypeptr = (SplitSide(tile)) ? SplitRightType(tile): SplitLeftType(tile); + else + *idtypeptr = TiGetTypeExact(tile); - if (tile->ti_client != (ClientData) extUnInit) + return 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * extDevFindMatch -- + * + * Find and return the next matching device record. extTransRec is queried + * to find how many fields have been matched to the device already. Then + * it finds the next record with the same matching fields. Because records + * are in no specific order, it will loop to the beginning of the records + * after reaching the end. It is the responsibility of the calling routine to + * determine if all matching devices have been tested. + * + * deventry is the record position to start the search. + * t is the tile type of the device. + * ---------------------------------------------------------------------------- + */ + +ExtDevice * +extDevFindMatch(deventry, t) + ExtDevice *deventry; + TileType t; +{ + ExtDevice *devptr; + int i, j, matchflags; + bool match; + + matchflags = extTransRec.tr_devmatch; + + if (deventry->exts_next == NULL) + devptr = ExtCurStyle->exts_device[t]; + else + devptr = deventry->exts_next; + + for (; devptr != deventry; + devptr = (devptr->exts_next) ? devptr->exts_next : + ExtCurStyle->exts_device[t]) { - if ((*sn != (NodeRegion *)NULL) && (*sn != tile->ti_client)) - TxError("Warning: Split substrate under device at (%d %d)\n", - tile->ti_ll.p_x, tile->ti_ll.p_y); + if (matchflags == 0) break; /* Always return next entry */ - *sn = (NodeRegion *) tile->ti_client; - return 1; + if (matchflags & MATCH_ID) /* Must have the same identifier */ + if (!TTMaskEqual(&devptr->exts_deviceIdentifierTypes, + &deventry->exts_deviceIdentifierTypes)) continue; + + if (matchflags & MATCH_SUB) /* Must have the same substrate type */ + if (!TTMaskEqual(&devptr->exts_deviceSubstrateTypes, + &deventry->exts_deviceSubstrateTypes)) continue; + + j = MATCH_TERM; + match = True; + for (i = 0; i < MAXSD; i++) + { + if (extTransRec.tr_termnode[i] == NULL) break; + if (matchflags & j) /* Must have the same terminal type */ + { + if (TTMaskIsZero(&devptr->exts_deviceSDTypes[i])) + { + match = False; + break; + } + if (!TTMaskEqual(&devptr->exts_deviceSDTypes[i], + &deventry->exts_deviceSDTypes[i])) + { + match = False; + break; + } + } + j >>= 1; + } + if (match) break; } - return 0; + return (devptr == deventry) ? NULL : devptr; } /* @@ -2273,10 +2388,12 @@ extTransTileFunc(tile, pNum, arg) int pNum; FindRegion *arg; { - TileTypeBitMask mask; - TileType loctype; - int perim; + TileTypeBitMask mask, cmask, *smask; + TileType loctype, idlayer, sublayer; + int perim, result; bool allow_globsubsnode; + ExtDevice *devptr, *deventry, *devtest; + NodeRegion *region; LabelList *ll; Label *lab; @@ -2306,7 +2423,7 @@ extTransTileFunc(tile, pNum, arg) else loctype = TiGetTypeExact(tile); - mask = ExtCurStyle->exts_transConn[loctype]; + mask = ExtCurStyle->exts_deviceConn[loctype]; TTMaskCom(&mask); /* NOTE: DO NOT USE extTransRec.tr_perim += extEnumTilePerim(...) */ @@ -2317,32 +2434,146 @@ extTransTileFunc(tile, pNum, arg) extTransPerimFunc, (ClientData)NULL); extTransRec.tr_perim += perim; - allow_globsubsnode = FALSE; - if (extTransRec.tr_subsnode == (NodeRegion *)NULL) - { - TileTypeBitMask *smask; + devptr = extTransRec.tr_devrec; + if (devptr == NULL) return 0; /* No matching devices, so forget it. */ - smask = &ExtCurStyle->exts_transSubstrateTypes[loctype]; - if (TTMaskHasType(smask, TT_SPACE)) - { - allow_globsubsnode = TRUE; - TTMaskClearType(smask, TT_SPACE); - } - extTransFindSubs(tile, loctype, smask, arg->fra_def, &extTransRec.tr_subsnode); - if (allow_globsubsnode) - TTMaskSetType(smask, TT_SPACE); + allow_globsubsnode = FALSE; + + /* Create a mask of all substrate types of all device records, and */ + /* search for substrate types on this combined mask. */ + + TTMaskZero(&cmask); + for (devtest = ExtCurStyle->exts_device[loctype]; devtest; + devtest = devtest->exts_next) + TTMaskSetMask(&cmask, &devtest->exts_deviceSubstrateTypes); + + if (TTMaskHasType(&cmask, TT_SPACE)) + { + allow_globsubsnode = TRUE; + TTMaskClearType(&cmask, TT_SPACE); } - /* If the transistor does not connect to a defined node, and - * the substrate types include "space", then it is assumed to - * connect to the global substrate. - */ - if (extTransRec.tr_subsnode == (NodeRegion *)NULL) - if (allow_globsubsnode) - extTransRec.tr_subsnode = glob_subsnode; + { + sublayer = TT_SPACE; + region = NULL; + extTransFindSubs(tile, loctype, &cmask, arg->fra_def, ®ion, &sublayer); - return (0); + /* If the device does not connect to a defined node, and + * the substrate types include "space", then it is assumed to + * connect to the global substrate. + */ + + if (region == (NodeRegion *)NULL) + if (allow_globsubsnode) + region = glob_subsnode; + + extTransRec.tr_subsnode = region; + + if ((region != (NodeRegion *)NULL) && + !(TTMaskHasType(&devptr->exts_deviceSubstrateTypes, sublayer))) + { + /* A substrate layer was found but is not compatible with the */ + /* current device. Find a device record with the substrate */ + /* layer that was found, and set the substrate match flag. */ + + deventry = devptr; + while (devptr != NULL) + { + devptr = extDevFindMatch(devptr, loctype); + if ((devptr == NULL) || (devptr == deventry)) + { + TxError("No matching device for %s with substrate layer %s\n", + DBTypeLongNameTbl[loctype], DBTypeLongNameTbl[sublayer]); + devptr = NULL; + break; + } + if (TTMaskHasType(&devptr->exts_deviceSubstrateTypes, sublayer)) + { + extTransRec.tr_devmatch |= MATCH_SUB; + break; + } + } + } + else if (region == (NodeRegion *)NULL) + { + TxError("Device %s does not have a compatible substrate node!\n", + DBTypeLongNameTbl[loctype]); + devptr = NULL; + } + } + extTransRec.tr_devrec = devptr; + if (devptr == NULL) return 0; /* No matching devices, so forget it. */ + + /* If at least one device type declares an ID layer, then make a */ + /* mask of all device ID types, and search on the area of the */ + /* device to see if any device identifier layers are found. */ + + TTMaskZero(&cmask); + for (devtest = ExtCurStyle->exts_device[loctype]; devtest; + devtest = devtest->exts_next) + TTMaskSetMask(&cmask, &devtest->exts_deviceIdentifierTypes); + + if (!TTMaskIsZero(&cmask)) + { + idlayer = TT_SPACE; + extTransFindId(tile, &cmask, arg->fra_def, &idlayer); + + if ((idlayer == TT_SPACE) && !TTMaskIsZero(&devptr->exts_deviceIdentifierTypes)) + { + /* Device expected an ID layer but none was present. Find a device */ + /* record with no ID layer, and set the ID match flag. */ + + deventry = devptr; + while (devptr != NULL) + { + devptr = extDevFindMatch(devptr, loctype); + if ((devptr == NULL) || (devptr == deventry)) + { + TxError("No matching device for %s with no ID layer\n", + DBTypeLongNameTbl[loctype]); + devptr = NULL; + break; + } + if (TTMaskIsZero(&devptr->exts_deviceIdentifierTypes)) + { + extTransRec.tr_devmatch |= MATCH_ID; + break; + } + } + } + else if ((idlayer != TT_SPACE) && + !TTMaskHasType(&devptr->exts_deviceIdentifierTypes, idlayer)) + { + /* Device expected no ID layer but one was present. Find a device */ + /* record with the ID layer and set the ID match flag. If there is */ + /* a valid device without the ID layer, then ignore the ID layer */ + /* and flag a warning. */ + + deventry = devptr; + while (devptr != NULL) + { + devptr = extDevFindMatch(devptr, loctype); + if ((devptr == NULL) || (devptr == deventry)) + { + TxError("ID layer %s on non-matching device %s was ignored.\n", + DBTypeLongNameTbl[idlayer], DBTypeLongNameTbl[loctype]); + devptr = deventry; + break; + } + if (TTMaskHasType(&devptr->exts_deviceIdentifierTypes, idlayer)) + { + extTransRec.tr_devmatch |= MATCH_ID; + break; + } + } + } + else + extTransRec.tr_devmatch |= MATCH_ID; + } + extTransRec.tr_devrec = devptr; + + return 0; } int @@ -2352,6 +2583,7 @@ extTransPerimFunc(bp) TileType tinside, toutside; Tile *tile; NodeRegion *diffNode = (NodeRegion *) extGetRegion(bp->b_outside); + ExtDevice *devptr, *deventry; int i, len = BoundaryLength(bp); int thisterm; LabelList *ll; @@ -2370,115 +2602,138 @@ extTransPerimFunc(bp) else toutside = TiGetTypeExact(bp->b_outside); - for (i = 0; !TTMaskIsZero(&ExtCurStyle->exts_transSDTypes[tinside][i]); i++) + if (extTransRec.tr_devrec != NULL) + devptr = extTransRec.tr_devrec; + else + devptr = ExtCurStyle->exts_device[tinside]; + + deventry = devptr; + while(devptr) { - /* TT_SPACE is allowed, for declaring that a device terminal is */ - /* the substrate. However, it should not be in the plane of */ - /* the device identifier layer, so space tiles should never be */ - /* flagged during a device perimeter search. */ - - if (toutside == TT_SPACE) break; - - if (TTMaskHasType(&ExtCurStyle->exts_transSDTypes[tinside][i], toutside)) + extTransRec.tr_devrec = devptr; + for (i = 0; !TTMaskIsZero(&devptr->exts_deviceSDTypes[i]); i++) { - /* - * It's a diffusion terminal (source or drain). See if the node is - * already in our table; add it if it wasn't already there. - * Asymmetric devices must have terminals in order. - */ - if (TTMaskIsZero(&ExtCurStyle->exts_transSDTypes[tinside][1])) + /* TT_SPACE is allowed, for declaring that a device terminal is */ + /* the substrate. However, it should not be in the plane of */ + /* the device identifier layer, so space tiles should never be */ + /* flagged during a device perimeter search. */ + + if (toutside == TT_SPACE) break; + + if (TTMaskHasType(&devptr->exts_deviceSDTypes[i], toutside)) { - for (thisterm = 0; thisterm < extTransRec.tr_nterm; thisterm++) - if (extTransRec.tr_termnode[thisterm] == diffNode) - break; - } - else - thisterm = i; - - if (extTransRec.tr_termnode[thisterm] == NULL) - { - extTransRec.tr_nterm++; - extTransRec.tr_termnode[thisterm] = diffNode; - extTransRec.tr_termlen[thisterm] = 0; - extTransRec.tr_termvector[thisterm].p_x = 0; - extTransRec.tr_termvector[thisterm].p_y = 0; - extTransRec.tr_termpos[thisterm].pnum = DBPlane(toutside); - extTransRec.tr_termpos[thisterm].pt = bp->b_outside->ti_ll; - - /* Find the total area of this terminal */ - } - else if (extTransRec.tr_termnode[thisterm] == diffNode) - { - TermTilePos *pos = &(extTransRec.tr_termpos[thisterm]); - Tile *otile = bp->b_outside; - - /* update the region tile position */ - - if( DBPlane(TiGetType(otile)) < pos->pnum ) + /* + * It's a diffusion terminal (source or drain). See if the node is + * already in our table; add it if it wasn't already there. + * Asymmetric devices must have terminals in order. + */ + if (TTMaskIsZero(&devptr->exts_deviceSDTypes[1])) { - pos->pnum = DBPlane(TiGetType(otile)); - pos->pt = otile->ti_ll; + for (thisterm = 0; thisterm < extTransRec.tr_nterm; thisterm++) + if (extTransRec.tr_termnode[thisterm] == diffNode) + break; } - else if( DBPlane(TiGetType(otile)) == pos->pnum ) + else + thisterm = i; + + if (extTransRec.tr_termnode[thisterm] == NULL) { - if( LEFT(otile) < pos->pt.p_x ) + extTransRec.tr_nterm++; + extTransRec.tr_termnode[thisterm] = diffNode; + extTransRec.tr_termlen[thisterm] = 0; + extTransRec.tr_termvector[thisterm].p_x = 0; + extTransRec.tr_termvector[thisterm].p_y = 0; + extTransRec.tr_termpos[thisterm].pnum = DBPlane(toutside); + extTransRec.tr_termpos[thisterm].pt = bp->b_outside->ti_ll; + + /* Find the total area of this terminal */ + } + else if (extTransRec.tr_termnode[thisterm] == diffNode) + { + TermTilePos *pos = &(extTransRec.tr_termpos[thisterm]); + Tile *otile = bp->b_outside; + + /* update the region tile position */ + + if( DBPlane(TiGetType(otile)) < pos->pnum ) + { + pos->pnum = DBPlane(TiGetType(otile)); pos->pt = otile->ti_ll; - else if( LEFT(otile) == pos->pt.p_x && + } + else if( DBPlane(TiGetType(otile)) == pos->pnum ) + { + if( LEFT(otile) < pos->pt.p_x ) + pos->pt = otile->ti_ll; + else if( LEFT(otile) == pos->pt.p_x && BOTTOM(otile) < pos->pt.p_y ) - pos->pt.p_y = BOTTOM(otile); + pos->pt.p_y = BOTTOM(otile); + } } - } - else - { - TxError("Error: Asymmetric device with multiple terminals!\n"); - } - - /* Add the length to this terminal's perimeter */ - extTransRec.tr_termlen[thisterm] += len; - - /* Update the boundary traversal vector */ - switch(bp->b_direction) { - case BD_LEFT: - extTransRec.tr_termvector[thisterm].p_y += len; - break; - case BD_TOP: - extTransRec.tr_termvector[thisterm].p_x += len; - break; - case BD_RIGHT: - extTransRec.tr_termvector[thisterm].p_y -= len; - break; - case BD_BOTTOM: - extTransRec.tr_termvector[thisterm].p_x -= len; - break; - } - - /* - * Mark this attribute as belonging to this transistor - * if it is either: - * (1) a terminal attribute whose LL corner touches bp->b_segment, - * or (2) a gate attribute that lies inside bp->b_inside. - */ - for (ll = extTransRec.tr_gatenode->nreg_labels; ll; ll = ll->ll_next) - { - /* Skip if already marked */ - if (ll->ll_attr != LL_NOATTR) - continue; - lab = ll->ll_label; - if (GEO_ENCLOSE(&lab->lab_rect.r_ll, &bp->b_segment) - && extLabType(lab->lab_text, LABTYPE_TERMATTR)) + else { - ll->ll_attr = thisterm; + TxError("Error: Asymmetric device with multiple terminals!\n"); } + + /* Add the length to this terminal's perimeter */ + extTransRec.tr_termlen[thisterm] += len; + + /* Update the boundary traversal vector */ + switch(bp->b_direction) { + case BD_LEFT: + extTransRec.tr_termvector[thisterm].p_y += len; + break; + case BD_TOP: + extTransRec.tr_termvector[thisterm].p_x += len; + break; + case BD_RIGHT: + extTransRec.tr_termvector[thisterm].p_y -= len; + break; + case BD_BOTTOM: + extTransRec.tr_termvector[thisterm].p_x -= len; + break; + } + + /* + * Mark this attribute as belonging to this transistor + * if it is either: + * (1) a terminal attribute whose LL corner touches bp->b_segment, + * or (2) a gate attribute that lies inside bp->b_inside. + */ + for (ll = extTransRec.tr_gatenode->nreg_labels; ll; ll = ll->ll_next) + { + /* Skip if already marked */ + if (ll->ll_attr != LL_NOATTR) + continue; + lab = ll->ll_label; + if (GEO_ENCLOSE(&lab->lab_rect.r_ll, &bp->b_segment) + && extLabType(lab->lab_text, LABTYPE_TERMATTR)) + { + ll->ll_attr = thisterm; + } + } + SDterm = TRUE; + extTransRec.tr_devmatch |= (MATCH_TERM << thisterm); + break; } - SDterm = TRUE; + } + + if (SDterm) break; + if (extConnectsTo(tinside, toutside, ExtCurStyle->exts_nodeConn)) + { + /* Not in a terminal, but are in something that connects to gate */ + extTransRec.tr_gatelen += len; break; } - } - if (!SDterm && extConnectsTo(tinside, toutside, ExtCurStyle->exts_nodeConn)) + /* Did not find a matching terminal, so see if a different extraction */ + /* record matches the terminal type. */ + devptr = extDevFindMatch(devptr, tinside); + if (devptr == deventry) devptr = NULL; + } + if (devptr == NULL) { - /* Not in a terminal, but are in something that connects to gate */ - extTransRec.tr_gatelen += len; + TxError("Error: Cannot find valid terminals on device %s!\n", + DBTypeLongNameTbl[tinside]); } /* @@ -2532,7 +2787,7 @@ extAnnularTileFunc(tile, pNum) else loctype = TiGetTypeExact(tile); - mask = ExtCurStyle->exts_transConn[loctype]; + mask = ExtCurStyle->exts_deviceConn[loctype]; TTMaskCom(&mask); extEnumTilePerim(tile, mask, pNum, extSpecialPerimFunc, (ClientData) TRUE); return (0); @@ -2569,6 +2824,7 @@ extResistorTileFunc(tile, pNum) { TileTypeBitMask mask; TileType loctype; + ExtDevice *devptr; /* * Visit each segment of the perimeter of this tile that @@ -2581,11 +2837,21 @@ extResistorTileFunc(tile, pNum) else loctype = TiGetTypeExact(tile); - mask = ExtCurStyle->exts_transConn[loctype]; - TTMaskSetMask(&mask, &ExtCurStyle->exts_transSDTypes[loctype][0]); - TTMaskCom(&mask); + mask = ExtCurStyle->exts_deviceConn[loctype]; - extEnumTilePerim(tile, mask, pNum, extSpecialPerimFunc, (ClientData)FALSE); + devptr = extTransRec.tr_devrec; + if (devptr == NULL) devptr = ExtCurStyle->exts_device[loctype]; + + while (devptr) + { + TTMaskSetMask(&mask, &devptr->exts_deviceSDTypes[0]); + TTMaskCom(&mask); + + extEnumTilePerim(tile, mask, pNum, extSpecialPerimFunc, (ClientData)FALSE); + + if (extSpecialBounds[0] == NULL) devptr = devptr->exts_next; + } + if (devptr != NULL) extTransRec.tr_devrec = devptr; return (0); } @@ -2605,6 +2871,7 @@ extSpecialPerimFunc(bp, sense) NodeRegion *diffNode = (NodeRegion *) extGetRegion(bp->b_outside); int thisterm, extended, i; LinkedBoundary *newBound, *lb, *lastlb; + ExtDevice *devptr; bool needSurvey; /* Note that extEnumTilePerim() assumes for the non-Manhattan case */ @@ -2633,19 +2900,27 @@ extSpecialPerimFunc(bp, sense) break; } + devptr = extTransRec.tr_devrec; + if (devptr == NULL) devptr = ExtCurStyle->exts_device[tinside]; + /* Check all terminal classes for a matching type */ needSurvey = FALSE; - for (i = 0; !TTMaskIsZero(&ExtCurStyle->exts_transSDTypes[tinside][i]); i++) + for (; devptr; devptr = devptr->exts_next) { - if (TTMaskHasType(&ExtCurStyle->exts_transSDTypes[tinside][i], toutside)) + for (i = 0; !TTMaskIsZero(&devptr->exts_deviceSDTypes[i]); i++) { - needSurvey = TRUE; - break; + if (TTMaskHasType(&devptr->exts_deviceSDTypes[i], toutside)) + { + needSurvey = TRUE; + break; + } } } if (!sense || needSurvey) { + extTransRec.tr_devrec = devptr; + if (toutside == TT_SPACE) if (glob_subsnode != NULL) diffNode = glob_subsnode; diff --git a/extract/ExtTech.c b/extract/ExtTech.c index c4744879..d778749d 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -299,36 +299,41 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr) TileTypeBitMask *rmask, *tmask; int n, i = 0, j; bool repeat; + ExtDevice *devptr; char *locdname; char **uniquenamelist = (char **)mallocMagic(DBNumTypes * sizeof(char *)); for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) { - locdname = ExtCurStyle->exts_transName[t]; - if (locdname != NULL) + for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next) { - repeat = FALSE; - for (j = 0; j < i; j++) - if (!strcmp(uniquenamelist[j], locdname)) - { - repeat = TRUE; - break; - } - if (repeat == FALSE) + locdname = devptr->exts_deviceName; + if (locdname != NULL) { - if (i == idx) break; - uniquenamelist[i] = locdname; - i++; + repeat = FALSE; + for (j = 0; j < i; j++) + if (!strcmp(uniquenamelist[j], locdname)) + { + repeat = TRUE; + break; + } + if (repeat == FALSE) + { + if (i == idx) break; + uniquenamelist[i] = locdname; + i++; + } } } } if (t == DBNumTypes) return FALSE; + if (devptr == NULL) return FALSE; *devnameptr = locdname; - *subnameptr = ExtCurStyle->exts_transSubstrateName[t]; + *subnameptr = devptr->exts_deviceSubstrateName; - tmask = &ExtCurStyle->exts_transSDTypes[t][0]; + tmask = &devptr->exts_deviceSDTypes[0]; *sd_rclassptr = (short)(-1); /* NO_RESCLASS */ for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) @@ -341,7 +346,7 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr) } } - tmask = &ExtCurStyle->exts_transSubstrateTypes[t]; + tmask = &devptr->exts_deviceSubstrateTypes; *sub_rclassptr = (short)(-1); /* NO_RESCLASS */ for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) @@ -538,23 +543,10 @@ extTechStyleAlloc() TileType r; style = (ExtStyle *) mallocMagic(sizeof (ExtStyle)); - - /* Make sure that the memory for character strings is NULL, */ - /* because we want the Init section to free memory if it */ - /* has been previously allocated. */ - - for (r = 0; r < NT; r++) - { - style->exts_transSubstrateName[r] = (char *) NULL; - style->exts_transName[r] = (char *) NULL; - style->exts_transSDTypes[r] = (TileTypeBitMask *) NULL; - style->exts_deviceParams[r] = (ParamList *) NULL; - style->exts_deviceClass[r] = (char) 0; - style->exts_transResist[r].ht_table = (HashEntry **) NULL; - } return style; } + /* * ---------------------------------------------------------------------------- * @@ -575,7 +567,7 @@ extTechStyleInit(style) style->exts_status = TECH_NOT_LOADED; style->exts_sidePlanes = style->exts_overlapPlanes = 0; - TTMaskZero(&style->exts_transMask); + TTMaskZero(&style->exts_deviceMask); style->exts_activeTypes = DBAllButSpaceAndDRCBits; for (r = 0; r < NP; r++) @@ -589,7 +581,7 @@ extTechStyleInit(style) { TTMaskZero(&style->exts_nodeConn[r]); TTMaskZero(&style->exts_resistConn[r]); - TTMaskZero(&style->exts_transConn[r]); + TTMaskZero(&style->exts_deviceConn[r]); style->exts_allConn[r] = DBAllTypeBits; style->exts_sheetResist[r] = 0; @@ -620,43 +612,41 @@ extTechStyleInit(style) #ifdef ARIEL TTMaskZero(&style->exts_subsTransistorTypes[r]); #endif - if (style->exts_transSDTypes[r] != NULL) - freeMagic(style->exts_transSDTypes[r]); - style->exts_transSDTypes[r] = NULL; - style->exts_transSDCount[r] = 0; - style->exts_transGateCap[r] = (CapValue) 0; - style->exts_transSDCap[r] = (CapValue) 0; - if (style->exts_transSubstrateName[r] != (char *) NULL) + if (style->exts_device[r] != NULL) { - freeMagic(style->exts_transSubstrateName[r]); - style->exts_transSubstrateName[r] = (char *) NULL; - } - if (style->exts_transName[r] != (char *) NULL) - { - freeMagic(style->exts_transName[r]); - style->exts_transName[r] = (char *) NULL; - } - while (style->exts_deviceParams[r] != (ParamList *) NULL) - { - /* Parameter lists are shared. Only free the last one! */ + ExtDevice *devptr; + for (devptr = style->exts_device[r]; devptr; devptr = devptr->exts_next) + { - if (style->exts_deviceParams[r]->pl_count > 1) - { - style->exts_deviceParams[r]->pl_count--; - style->exts_deviceParams[r] = (ParamList *)NULL; - } - else - { - freeMagic(style->exts_deviceParams[r]->pl_name); - freeMagic(style->exts_deviceParams[r]); - style->exts_deviceParams[r] = style->exts_deviceParams[r]->pl_next; + if (devptr->exts_deviceSDTypes != NULL) + freeMagic(devptr->exts_deviceSDTypes); + if (devptr->exts_deviceSubstrateName != (char *) NULL) + freeMagic(devptr->exts_deviceSubstrateName); + if (devptr->exts_deviceName != (char *) NULL) + freeMagic(devptr->exts_deviceName); + while (devptr->exts_deviceParams != (ParamList *) NULL) + { + /* Parameter lists are shared. Only free the last one! */ + + if (devptr->exts_deviceParams->pl_count > 1) + { + devptr->exts_deviceParams->pl_count--; + devptr->exts_deviceParams = (ParamList *)NULL; + } + else + { + freeMagic(devptr->exts_deviceParams->pl_name); + freeMagic(devptr->exts_deviceParams); + devptr->exts_deviceParams = devptr->exts_deviceParams->pl_next; + } + } + if (devptr->exts_deviceResist.ht_table != (HashEntry **) NULL) + HashKill(&devptr->exts_deviceResist); + + freeMagic(devptr); } + style->exts_device[r] = (ExtDevice *)NULL; } - style->exts_deviceClass[r] = (char)0; - if (style->exts_transResist[r].ht_table != (HashEntry **) NULL) - HashKill(&style->exts_transResist[r]); - HashInit(&style->exts_transResist[r], 8, HT_STRINGKEYS); - style->exts_linearResist[r] = 0; } style->exts_sideCoupleHalo = 0; @@ -798,14 +788,6 @@ ExtTechInit() if (ExtCurStyle != NULL) { extTechStyleInit(ExtCurStyle); - - /* Everything has been freed except the hash tables, which */ - /* were just reinitialized by extTechStyleInit(). */ - for (r = 0; r < NT; r++) - { - if (ExtCurStyle->exts_transResist[r].ht_table != (HashEntry **) NULL) - HashKill(&ExtCurStyle->exts_transResist[r]); - } ExtCurStyle = NULL; } @@ -1569,7 +1551,7 @@ ExtTechLine(sectionName, argc, argv) PlaneMask pshield, pov; CapValue capVal, gscap, gccap; TileTypeBitMask types1, types2, termtypes[MAXSD]; - TileTypeBitMask near, far, ov, shield, subsTypes; + TileTypeBitMask near, far, ov, shield, subsTypes, idTypes; char *subsName, *transName, *cp, *endptr, *paramName; TileType s, t, r, o; keydesc *kp, *dv; @@ -1578,6 +1560,7 @@ ExtTechLine(sectionName, argc, argv) EdgeCap *cnew; ExtKeep *es, *newStyle; ParamList *subcktParams, *newParam; + ExtDevice *devptr; int refcnt; double dhalo; bool bad; @@ -1888,24 +1871,32 @@ ExtTechLine(sectionName, argc, argv) gccap = (argc > 7) ? aToCap(argv[7]) : (CapValue) 0; } - TTMaskSetMask(&ExtCurStyle->exts_transMask, &types1); + TTMaskSetMask(&ExtCurStyle->exts_deviceMask, &types1); for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) if (TTMaskHasType(&types1, t)) { - TTMaskSetMask(ExtCurStyle->exts_transConn+t,&types1); - ExtCurStyle->exts_transSDTypes[t] = (TileTypeBitMask *) + devptr = (ExtDevice *)mallocMagic(sizeof(ExtDevice)); + devptr->exts_deviceSDTypes = (TileTypeBitMask *) mallocMagic(2 * sizeof(TileTypeBitMask)); - ExtCurStyle->exts_transSDTypes[t][0] = termtypes[0]; - ExtCurStyle->exts_transSDTypes[t][1] = DBZeroTypeBits; - ExtCurStyle->exts_transSDCount[t] = nterm; - ExtCurStyle->exts_transSDCap[t] = gscap; - ExtCurStyle->exts_transGateCap[t] = gccap; - ExtCurStyle->exts_deviceClass[t] = DEV_FET; - ExtCurStyle->exts_transName[t] = - StrDup((char **) NULL, transName); - ExtCurStyle->exts_transSubstrateName[t] = + devptr->exts_deviceSDTypes[0] = termtypes[0]; + devptr->exts_deviceSDTypes[1] = DBZeroTypeBits; + devptr->exts_deviceSDCount = nterm; + devptr->exts_deviceSDCap = gscap; + devptr->exts_deviceGateCap = gccap; + devptr->exts_deviceClass = DEV_FET; + devptr->exts_deviceName = StrDup((char **) NULL, transName); + devptr->exts_deviceSubstrateName = StrDup((char **) NULL, subsName); - ExtCurStyle->exts_transSubstrateTypes[t] = subsTypes; + devptr->exts_deviceSubstrateTypes = subsTypes; + devptr->exts_deviceIdentifierTypes = DBZeroTypeBits; + devptr->exts_deviceParams = (ParamList *) NULL; + devptr->exts_deviceResist.ht_table = (HashEntry **) NULL; + HashInit(&devptr->exts_deviceResist, 8, HT_STRINGKEYS); + + TTMaskSetMask(ExtCurStyle->exts_deviceConn + t, &types1); + + devptr->exts_next = ExtCurStyle->exts_device[t]; + ExtCurStyle->exts_device[t] = devptr; #ifdef ARIEL { int z; @@ -1941,7 +1932,7 @@ ExtTechLine(sectionName, argc, argv) /* Parse second argument for device type */ - n = LookupStruct(argv[1], (LookupTable *) devTable, sizeof devTable[0]); + n = LookupStruct(argv[1], (LookupTable *)devTable, sizeof devTable[0]); if (n < 0) { TechError("Illegal device. Legal devices are:\n\t"); @@ -1999,6 +1990,18 @@ ExtTechLine(sectionName, argc, argv) argc--; } + /* If the last entry before any parameters starts with '+', */ + /* then use it to set the identity marker. Otherwise, the */ + /* identity marker is NULL. */ + + idTypes = DBZeroTypeBits; + if (*argv[argc - 1] == '+') + { + if ((DBTechNameMask(argv[argc - 1] + 1, &idTypes)) == 0) + idTypes = DBZeroTypeBits; + argc--; + } + /* Check the number of arguments after splitting out */ /* parameter entries. There is no limit on arguments in */ /* DEV_SUBCKT and DEV_MSUBCKT. */ @@ -2194,31 +2197,45 @@ ExtTechLine(sectionName, argc, argv) break; } - TTMaskSetMask(&ExtCurStyle->exts_transMask, &types1); + TTMaskSetMask(&ExtCurStyle->exts_deviceMask, &types1); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) { if (TTMaskHasType(&types1, t)) { - TTMaskSetMask(ExtCurStyle->exts_transConn + t, &types1); + devptr = (ExtDevice *)mallocMagic(sizeof(ExtDevice)); for (i = 0; !TTMaskIsZero(&termtypes[i]); i++); - ExtCurStyle->exts_transSDTypes[t] = (TileTypeBitMask *) + devptr->exts_deviceSDTypes = (TileTypeBitMask *) mallocMagic((i + 1) * sizeof(TileTypeBitMask)); for (i = 0; !TTMaskIsZero(&termtypes[i]); i++) - ExtCurStyle->exts_transSDTypes[t][i] = termtypes[i]; - ExtCurStyle->exts_transSDTypes[t][i] = DBZeroTypeBits; + devptr->exts_deviceSDTypes[i] = termtypes[i]; + devptr->exts_deviceSDTypes[i] = DBZeroTypeBits; - ExtCurStyle->exts_transSDCount[t] = nterm; - ExtCurStyle->exts_transSDCap[t] = gscap; - ExtCurStyle->exts_transGateCap[t] = gccap; - ExtCurStyle->exts_deviceClass[t] = class; - ExtCurStyle->exts_transName[t] = - StrDup((char **) NULL, transName); + devptr->exts_deviceSDCount = nterm; + devptr->exts_deviceSDCap = gscap; + devptr->exts_deviceGateCap = gccap; + devptr->exts_deviceClass = class; + devptr->exts_deviceName = StrDup((char **) NULL, transName); if (subsName != NULL) - ExtCurStyle->exts_transSubstrateName[t] = + devptr->exts_deviceSubstrateName = StrDup((char **) NULL, subsName); - ExtCurStyle->exts_transSubstrateTypes[t] = subsTypes; + devptr->exts_deviceSubstrateTypes = subsTypes; + devptr->exts_deviceIdentifierTypes = idTypes; + devptr->exts_deviceParams = (ParamList *) NULL; + if (subcktParams != NULL) + { + devptr->exts_deviceParams = subcktParams; + subcktParams->pl_count++; + } + devptr->exts_deviceResist.ht_table = (HashEntry **) NULL; + HashInit(&devptr->exts_deviceResist, 8, HT_STRINGKEYS); + + devptr->exts_next = ExtCurStyle->exts_device[t]; + ExtCurStyle->exts_device[t] = devptr; + + TTMaskSetMask(ExtCurStyle->exts_deviceConn + t, &types1); #ifdef ARIEL { int z; @@ -2231,11 +2248,6 @@ ExtTechLine(sectionName, argc, argv) } } #endif - if (subcktParams != NULL) - { - ExtCurStyle->exts_deviceParams[t] = subcktParams; - subcktParams->pl_count++; - } } } break; @@ -2249,13 +2261,19 @@ ExtTechLine(sectionName, argc, argv) val = atoi(argv[3]); isLinear = (strcmp(argv[2], "linear") == 0); for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + ExtDevice *devptr; if (TTMaskHasType(&types1, t)) { - he = HashFind(&ExtCurStyle->exts_transResist[t], argv[2]); - HashSetValue(he, (spointertype)val); - if (isLinear) - ExtCurStyle->exts_linearResist[t] = val; + for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next) + { + he = HashFind(&devptr->exts_deviceResist, argv[2]); + HashSetValue(he, (spointertype)val); + if (isLinear) + devptr->exts_linearResist = val; + } } + } break; case HEIGHT: { float height, thick; @@ -2619,7 +2637,7 @@ diffplane: * * Postprocess the technology specific information for extraction. * Builds the connectivity tables exts_nodeConn[], exts_resistConn[], - * and exts_transConn[]. + * and exts_deviceConn[]. * * Results: * None. @@ -2664,9 +2682,9 @@ extTechFinalStyle(style) for (r = TT_TECHDEPBASE; r < DBNumTypes; r++) { maskBits = style->exts_nodeConn[r] = DBConnectTbl[r]; - if (!TTMaskHasType(&style->exts_transMask, r)) + if (!TTMaskHasType(&style->exts_deviceMask, r)) { - TTMaskZero(&style->exts_transConn[r]); + TTMaskZero(&style->exts_deviceConn[r]); } for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) { @@ -2870,10 +2888,15 @@ zinit: for (r = 0; r < DBNumTypes; r++) { - style->exts_areaCap[r] *= sqfac; - style->exts_transSDCap[r] *= sqfac; - style->exts_transGateCap[r] *= sqfac; + ExtDevice *devptr; + for (devptr = style->exts_device[r]; devptr; devptr = devptr->exts_next) + { + devptr->exts_deviceSDCap *= sqfac; + devptr->exts_deviceGateCap *= sqfac; + } + + style->exts_areaCap[r] *= sqfac; for (s = 0; s < DBNumTypes; s++) { EdgeCap *ec; @@ -2953,13 +2976,18 @@ ExtTechScale(scalen, scaled) for (i = 0; i < DBNumTypes; i++) { + ExtDevice *devptr; + style->exts_areaCap[i] *= sqn; style->exts_areaCap[i] /= sqd; - style->exts_transSDCap[i] *= sqn; - style->exts_transSDCap[i] /= sqd; - style->exts_transGateCap[i] *= sqn; - style->exts_transGateCap[i] /= sqd; + for (devptr = style->exts_device[i]; devptr; devptr = devptr->exts_next) + { + devptr->exts_deviceSDCap *= sqn; + devptr->exts_deviceSDCap /= sqd; + devptr->exts_deviceGateCap *= sqn; + devptr->exts_deviceGateCap /= sqd; + } style->exts_height[i] *= scaled; style->exts_height[i] /= scalen; diff --git a/extract/ExtTest.c b/extract/ExtTest.c index 98f61b06..4428a28c 100644 --- a/extract/ExtTest.c +++ b/extract/ExtTest.c @@ -361,7 +361,7 @@ extShowTech(name) } } - extShowTrans("Transistor", &ExtCurStyle->exts_transMask, out); + extShowTrans("Transistor", &ExtCurStyle->exts_deviceMask, out); fprintf(out, "\nNode resistance and capacitance:\n"); fprintf(out, "type R-ohm/sq AreaC-ff/l**2\n"); @@ -472,7 +472,7 @@ extShowTech(name) extShowConnect("\nNode connectivity", ExtCurStyle->exts_nodeConn, out); extShowConnect("\nResistive region connectivity", ExtCurStyle->exts_resistConn, out); - extShowConnect("\nTransistor connectivity", ExtCurStyle->exts_transConn, out); + extShowConnect("\nTransistor connectivity", ExtCurStyle->exts_deviceConn, out); if (out != stdout) (void) fclose(out); @@ -493,12 +493,17 @@ extShowTrans(name, mask, out) for (t = 0; t < DBNumTypes; t++) if (TTMaskHasType(mask, t)) { - fprintf(out, " %-8.8s %d terminals: ", - DBTypeShortName(t), ExtCurStyle->exts_transSDCount[t]); - extShowMask(&ExtCurStyle->exts_transSDTypes[t][0], out); - fprintf(out, "\n\tcap (gate-sd/gate-ch) = %lf/%lf\n", - ExtCurStyle->exts_transSDCap[t], - ExtCurStyle->exts_transGateCap[t]); + ExtDevice *devptr; + + for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next) + { + fprintf(out, " %-8.8s %d terminals: ", + DBTypeShortName(t), devptr->exts_deviceSDCount); + extShowMask(&devptr->exts_deviceSDTypes[0], out); + fprintf(out, "\n\tcap (gate-sd/gate-ch) = %lf/%lf\n", + devptr->exts_deviceSDCap, + devptr->exts_deviceGateCap); + } } } diff --git a/extract/ExtTimes.c b/extract/ExtTimes.c index 3e2e0cbc..72c0f33b 100644 --- a/extract/ExtTimes.c +++ b/extract/ExtTimes.c @@ -348,7 +348,7 @@ extTimesCellFunc(cs) /* Count the number of transistors */ transList = (TransRegion *) ExtFindRegions(def, &TiPlaneRect, - &ExtCurStyle->exts_transMask, ExtCurStyle->exts_transConn, + &ExtCurStyle->exts_deviceMask, ExtCurStyle->exts_deviceConn, extUnInit, extTransFirst, extTransEach); ExtResetTiles(def, extUnInit); for (tl = transList; tl; tl = tl->treg_next) diff --git a/extract/extractInt.h b/extract/extractInt.h index ee264862..d5779afa 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -483,6 +483,82 @@ typedef struct extkeep char *exts_name; } ExtKeep; +/* + * Structure used to define transistors and other extracted devices + * One of these records is kept per tile type. However, the record + * can link to additional records through the "exts_next" record, + * so that multiple extraction devices can be defined for the same + * tile type, provided that each definition has a unique combination + * of exts_deviceSDTypes and exts_deviceSubstrateTypes. + */ + +typedef struct extDevice +{ + /* Name of each transistor type as output in .ext file */ + char *exts_deviceName; + + /* List of parameter names for each subcircuit type */ + ParamList *exts_deviceParams; + + /* Device class for each layer type */ + char exts_deviceClass; + + /* + * Per-square resistances for each possible transistor type, + * in the various regions that such a type might operate. + * The only operating region currently used is "linear", + * which the resistance extractor uses in its thresholding + * operation. NOTE: resistances in this table are in OHMS + * per square, not MILLIOHMS! + */ + + HashTable exts_deviceResist; + ResValue exts_linearResist; + + /* + * Mask of the types of tiles that connect to the channel terminals + * of a transistor type. The intent is that these will be the + * diffusion terminals of a transistor, ie, its source and drain. + * UPDATED May, 2008: Record is a list of type masks, allowing + * multiple terminal types in the case of, e.g., high-voltage + * or other asymmetric devices. The last entry in the list should + * be equal to DBSpaceBits. + */ + TileTypeBitMask *exts_deviceSDTypes; + + /* + * Maximum number of terminals (source/drains) per transistor type. + * This table exists to allow the possibility of transistors with + * more than two diffusion terminals at some point in the future. + */ + int exts_deviceSDCount; + + /* Currently unused: gate-source capacitance per unit perimeter */ + CapValue exts_deviceSDCap; + + /* Currently unused: gate-channel capacitance per unit area */ + CapValue exts_deviceGateCap; + + /* + * Each type of transistor has a substrate node. By default, + * it is the one given by exts_deviceSubstrateName[t]. However, + * if the mask exts_deviceSubstrateTypes is non-zero, and if + * the transistor overlaps material of one of the types in the + * mask, then the transistor substrate node is the node of the + * material it overlaps. + */ + char *exts_deviceSubstrateName; + TileTypeBitMask exts_deviceSubstrateTypes; + + /* + * Each device type can have any number of extract models based + * on identifier layers (such as thickox, esd, etc.) + */ + TileTypeBitMask exts_deviceIdentifierTypes; + + struct extDevice *exts_next; +} ExtDevice; + /* * Parameters for the process being extracted. * We try to use use integers here, rather than floats, to be nice to @@ -524,11 +600,11 @@ typedef struct extstyle TileTypeBitMask exts_resistConn[NT]; /* - * Connectivity for determining transistors. - * Each transistor type should connect only to itself. + * Connectivity for determining devices. + * Each devices type should connect only to itself. * Nothing else should connect to anything else. */ - TileTypeBitMask exts_transConn[NT]; + TileTypeBitMask exts_deviceConn[NT]; /* * Set of types to be considered for extraction. Types not in @@ -779,65 +855,14 @@ typedef struct extstyle */ TileTypeBitMask exts_sideEdges[NT]; - /* Transistors */ + /* Devices */ - /* Name of each transistor type as output in .ext file */ - char *exts_transName[NT]; + /* Contains one for each type of device, zero for all other tile types */ + TileTypeBitMask exts_deviceMask; - /* List of parameter names for each subcircuit type */ - ParamList *exts_deviceParams[NT]; + /* All information about a device goes in this record (see above) */ + ExtDevice *exts_device[NT]; - /* Device class for each layer type */ - char exts_deviceClass[NT]; - - /* Contains one for each type of fet, zero for all other types */ - TileTypeBitMask exts_transMask; - - /* - * Per-square resistances for each possible transistor type, - * in the various regions that such a type might operate. - * The only operating region currently used is "linear", - * which the resistance extractor uses in its thresholding - * operation. NOTE: resistances in this table are in OHMS - * per square, not MILLIOHMS! - */ - HashTable exts_transResist[NT]; - ResValue exts_linearResist[NT]; - - /* - * Mask of the types of tiles that connect to the channel terminals - * of a transistor type. The intent is that these will be the - * diffusion terminals of a transistor, ie, its source and drain. - * UPDATED May, 2008: Record is a list of type masks, allowing - * multiple terminal types in the case of, e.g., high-voltage - * or other asymmetric devices. The last entry in the list should - * be equal to DBSpaceBits. - */ - TileTypeBitMask *exts_transSDTypes[NT]; - - /* - * Maximum number of terminals (source/drains) per transistor type. - * This table exists to allow the possibility of transistors with - * more than two diffusion terminals at some point in the future. - */ - int exts_transSDCount[NT]; - - /* Currently unused: gate-source capacitance per unit perimeter */ - CapValue exts_transSDCap[NT]; - - /* Currently unused: gate-channel capacitance per unit area */ - CapValue exts_transGateCap[NT]; - - /* - * Each type of transistor has a substrate node. By default, - * it is the one given by exts_transSubstrateName[t]. However, - * if the mask exts_transSubstrateTypes[t] is non-zero, and if - * the transistor overlaps material of one of the types in the - * mask, then the transistor substrate node is the node of the - * material it overlaps. If exts_transSub - */ - char *exts_transSubstrateName[NT]; - TileTypeBitMask exts_transSubstrateTypes[NT]; #ifdef ARIEL TileTypeBitMask exts_subsTransistorTypes[NT]; #endif /* ARIEL */ diff --git a/resis/ResBasic.c b/resis/ResBasic.c index 24721e10..273133ae 100644 --- a/resis/ResBasic.c +++ b/resis/ResBasic.c @@ -139,6 +139,7 @@ ResEachTile(tile, startpoint) bool merged; tElement *tcell; tileJunk *tstructs= (tileJunk *)(tile->ti_client); + ExtDevice *devptr; ResTileCount++; @@ -165,7 +166,7 @@ ResEachTile(tile, startpoint) resNodeIsPort(resptr, x, y, tile); } - if TTMaskHasType(&(ExtCurStyle->exts_transMask), t1) + if TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t1) { /* * The transistor is put in the center of the tile. This is fine @@ -250,8 +251,9 @@ ResEachTile(tile, startpoint) for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp)) { t2 = TiGetRightType(tp); - if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1)) + devptr = ExtCurStyle->exts_device[t2]; + if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) /* found transistor */ { xj = LEFT(tile); @@ -272,8 +274,9 @@ ResEachTile(tile, startpoint) for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp)) { t2 = TiGetLeftType(tp); - if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1)) + devptr = ExtCurStyle->exts_device[t2]; + if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) /* found transistor */ { xj = RIGHT(tile); @@ -294,8 +297,9 @@ ResEachTile(tile, startpoint) for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp)) { t2 = TiGetBottomType(tp); - if(TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + devptr = ExtCurStyle->exts_device[t2]; + if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) /* found transistor */ { yj = TOP(tile); @@ -315,8 +319,9 @@ ResEachTile(tile, startpoint) for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp)) { t2 = TiGetTopType(tp); - if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1)) + devptr = ExtCurStyle->exts_device[t2]; + if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) /* found transistor */ { yj = BOTTOM(tile); diff --git a/resis/ResConDCS.c b/resis/ResConDCS.c index aea2ab4a..69adc06a 100644 --- a/resis/ResConDCS.c +++ b/resis/ResConDCS.c @@ -102,6 +102,7 @@ dbcConnectFuncDCS(tile, cx) SearchContext scx2; int pNum; CellDef *def; + ExtDevice *devptr; TiToRect(tile, &tileArea); srArea = &scx->scx_area; @@ -121,8 +122,9 @@ dbcConnectFuncDCS(tile, cx) for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp)) { t2 = TiGetType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + devptr = ExtCurStyle->exts_device[t2]; + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { TiToRect(tp, &tranArea); thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); @@ -137,8 +139,9 @@ dbcConnectFuncDCS(tile, cx) for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp)) { t2 = TiGetType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + devptr = ExtCurStyle->exts_device[t2]; + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { TiToRect(tp, &tranArea); thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); @@ -153,8 +156,9 @@ dbcConnectFuncDCS(tile, cx) for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp)) { t2 = TiGetType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + devptr = ExtCurStyle->exts_device[t2]; + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { TiToRect(tp, &tranArea); thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); @@ -169,8 +173,9 @@ dbcConnectFuncDCS(tile, cx) for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp)) { t2 = TiGetType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + devptr = ExtCurStyle->exts_device[t2]; + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { TiToRect(tp, &tranArea); thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); @@ -182,7 +187,7 @@ dbcConnectFuncDCS(tile, cx) } } } - else if TTMaskHasType(&(ExtCurStyle->exts_transMask),t1) + else if TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t1) { TiToRect(tile, &tranArea); thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); @@ -425,6 +430,7 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) ResTranTile *CurrentT; CellDef *def = destUse->cu_def; TileType newtype; + ExtDevice *devptr; csa2.csa2_use = destUse; csa2.csa2_xMask = xMask; @@ -443,13 +449,14 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) TTMaskZero(&ResSubsTypeBitMask); for (tran = TT_TECHDEPBASE; tran < TT_MAXTYPES; tran++) { - tran_name = (ExtCurStyle->exts_transName)[tran]; + devptr = ExtCurStyle->exts_device[tran]; + tran_name = devptr->exts_deviceName; if ((tran_name != NULL) && (strcmp(tran_name, "None"))) { TTMaskSetMask(&DiffTypeBitMask, - &(ExtCurStyle->exts_transSDTypes[tran][0])); + &(devptr->exts_deviceSDTypes[0])); TTMaskSetMask(&ResSubsTypeBitMask, - &(ExtCurStyle->exts_transSubstrateTypes[tran])); + &(devptr->exts_deviceSubstrateTypes)); } } first = 0; @@ -520,12 +527,14 @@ resSubSearchFunc(tile,cx) ResTranTile *thisTran; Rect tranArea; TileType t = TiGetType(tile); + ExtDevice *devptr; /* Right now, we're only going to extract substrate terminals for devices with only one diffusion terminal, principally bipolar devices. */ - if (ExtCurStyle->exts_transSDCount[t] >1) return 0; + devptr = ExtCurStyle->exts_device[t] + if (devptr->exts_deviceSDCount >1) return 0; TiToRect(tile, &tranArea); thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); GeoTransRect(&cx->tc_scx->scx_trans, &tranArea, &thisTran->area); diff --git a/resis/ResMain.c b/resis/ResMain.c index 1548be5e..33657767 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -53,7 +53,7 @@ extern HashTable ResNodeTable; * ResInitializeConn-- * * Sets up mask by Source/Drain type of transistors. This is - * exts_transSDtypes turned inside out. + * exts_deviceSDtypes turned inside out. * * Results: none * @@ -67,18 +67,20 @@ ResInitializeConn() { TileType tran, diff; char *tran_name; + ExtDevice *devptr; for (tran = TT_TECHDEPBASE; tran < TT_MAXTYPES; tran++) { - tran_name = (ExtCurStyle->exts_transName)[tran]; + devptr = ExtCurStyle->exts_device[tran]; + tran_name = devptr->exts_deviceName; if ((tran_name != NULL) && (strcmp(tran_name, "None"))) { for (diff = TT_TECHDEPBASE; diff < TT_MAXTYPES; diff++) { - if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[tran][0]), diff) + if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), diff) TTMaskSetType(&ResConnectWithSD[diff],tran); - if TTMaskHasType(&(ExtCurStyle->exts_transSubstrateTypes[tran]),diff) + if TTMaskHasType(&(devptr->exts_deviceSubstrateTypes),diff) TTMaskSetType(&ResConnectWithSD[diff],tran); } } @@ -163,7 +165,7 @@ ResDissolveContacts(contacts) { if (TTMaskHasType(&residues, t)) { - if (TTMaskHasType(&ExtCurStyle->exts_transMask, t)) + if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, t)) continue; DBPaint(ResUse->cu_def, &(contacts->cp_rect), t); } @@ -824,6 +826,7 @@ FindStartTile(goodies, SourcePoint) Point workingPoint; Tile *tile, *tp; int pnum, t1, t2; + ExtDevice *devptr; workingPoint.p_x = goodies->rg_tranloc->p_x; workingPoint.p_y = goodies->rg_tranloc->p_y; @@ -868,12 +871,12 @@ FindStartTile(goodies, SourcePoint) if (IsSplit(tile)) { - if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetLeftType(tile)) != 0) + if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetLeftType(tile)) != 0) { t1 = TiGetLeftType(tile); TiSetBody(tile, t1 & ~TT_SIDE); } - else if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetRightType(tile)) != 0) + else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetRightType(tile)) != 0) { t1 = TiGetRightType(tile); TiSetBody(tile, t1 & TT_SIDE); @@ -885,7 +888,7 @@ FindStartTile(goodies, SourcePoint) return(NULL); } } - else if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetType(tile)) == 0) + else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetType(tile)) == 0) { TxError("Couldn't find transistor at %d %d\n", goodies->rg_tranloc->p_x, goodies->rg_tranloc->p_y); @@ -894,11 +897,12 @@ FindStartTile(goodies, SourcePoint) else t1 = TiGetType(tile); + devptr = ExtCurStyle->exts_device[t1]; /* left */ for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp)) { t2 = TiGetRightType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]),t2)) + if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t2)) { SourcePoint->p_x = LEFT(tile); SourcePoint->p_y = (MIN(TOP(tile),TOP(tp))+ @@ -911,7 +915,7 @@ FindStartTile(goodies, SourcePoint) for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp)) { t2 = TiGetLeftType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]),t2)) + if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t2)) { SourcePoint->p_x = RIGHT(tile); SourcePoint->p_y = (MIN(TOP(tile),TOP(tp))+ @@ -924,7 +928,7 @@ FindStartTile(goodies, SourcePoint) for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp)) { t2 = TiGetBottomType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]),t2)) + if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t2)) { SourcePoint->p_y = TOP(tile); SourcePoint->p_x = (MIN(RIGHT(tile),RIGHT(tp))+ @@ -937,7 +941,7 @@ FindStartTile(goodies, SourcePoint) for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp)) { t2 = TiGetTopType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]),t2)) + if (TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t2)) { SourcePoint->p_y = BOTTOM(tile); SourcePoint->p_x = (MIN(RIGHT(tile),RIGHT(tp))+ @@ -977,7 +981,7 @@ ResGetTransistor(pt) for (pnum= PL_TECHDEPBASE; pnum < DBNumPlanes; pnum++) { - if (TTMaskIntersect(&ExtCurStyle->exts_transMask,&DBPlaneTypes[pnum]) == 0) + if (TTMaskIntersect(&ExtCurStyle->exts_deviceMask,&DBPlaneTypes[pnum]) == 0) { continue; } @@ -987,11 +991,11 @@ ResGetTransistor(pt) if (IsSplit(tile)) { - if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetLeftType(tile)) - || TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetRightType(tile))) + if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetLeftType(tile)) + || TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetRightType(tile))) return(((tileJunk *)tile->ti_client)->transistorList); } - else if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetType(tile))) + else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetType(tile))) { return(((tileJunk *)tile->ti_client)->transistorList); } diff --git a/resis/ResPrint.c b/resis/ResPrint.c index 0c93cfcd..1423bfac 100644 --- a/resis/ResPrint.c +++ b/resis/ResPrint.c @@ -114,6 +114,7 @@ ResPrintExtTran(outextfile, transistors) { TileType t; char *subsName; + ExtDevice *devptr; for (; transistors != NULL; transistors = transistors->nextTran) { @@ -122,7 +123,8 @@ ResPrintExtTran(outextfile, transistors) if (ResOptionsFlags & ResOpt_DoExtFile) { t = transistors->layout->rt_trantype; - subsName = ExtCurStyle->exts_transSubstrateName[t]; + devptr = ExtCurStyle->exts_device[t]; + subsName = devptr->exts_deviceSubstrateName; #ifdef MAGIC_WRAPPER /* Substrate variable name substitution */ @@ -139,7 +141,7 @@ ResPrintExtTran(outextfile, transistors) /* fet type xl yl xh yh area perim sub gate t1 t2 */ fprintf(outextfile,"fet %s %d %d %d %d %d %d " "%s \"%s\" %d %s \"%s\" %d %s \"%s\" %d %s\n", - ExtCurStyle->exts_transName[t], + devptr->exts_deviceName, transistors->layout->rt_inside.r_ll.p_x, transistors->layout->rt_inside.r_ll.p_y, transistors->layout->rt_inside.r_ll.p_x + 1, diff --git a/resis/ResReadSim.c b/resis/ResReadSim.c index fd7ce8bb..6cb38633 100644 --- a/resis/ResReadSim.c +++ b/resis/ResReadSim.c @@ -187,8 +187,10 @@ ResReadSim(simfile,fetproc,capproc,resproc,attrproc,mergeproc) else if (fettype != MINFINITY) { float sheetr; + ExtDevice *devptr; - sheetr=(float)ExtCurStyle->exts_linearResist[fettype]; + devptr = ExtCurStyle->exts_device[fettype]; + sheetr=(float)devptr->exts_linearResist; result = (*fetproc)(line,sheetr,fettype); } if (result != 0) diff --git a/resis/ResSimple.c b/resis/ResSimple.c index b4147523..2e55b033 100644 --- a/resis/ResSimple.c +++ b/resis/ResSimple.c @@ -732,6 +732,7 @@ ResCalculateChildCapacitance(me) float childcap; tElement *tptr; int t; + ExtDevice *devptr; if (me->rn_client != (ClientData) NULL) /* we have a loop */ @@ -752,12 +753,13 @@ ResCalculateChildCapacitance(me) t = TiGetType(tran->rt_tile); if (tran->rt_gate == me) { + devptr = ExtCurStyle->exts_device[t]; myC->rc_Cdownstream += tran->rt_length* tran->rt_width* - ExtCurStyle->exts_transGateCap[t]+ + devptr->exts_deviceGateCap+ (tran->rt_width+tran->rt_width)* - ExtCurStyle->exts_transSDCap[t]; + devptr->exts_deviceSDCap; } } diff --git a/resis/ResUtils.c b/resis/ResUtils.c index 5548f4e1..e292a3fb 100644 --- a/resis/ResUtils.c +++ b/resis/ResUtils.c @@ -144,6 +144,7 @@ ResAddPlumbing(tile, arg) TileType loctype, t1; Tile *tp1,*tp2,*source; resTransistor *resFet; + ExtDevice *devptr; if (resTransStack == NULL) { @@ -159,8 +160,9 @@ ResAddPlumbing(tile, arg) else loctype = TiGetTypeExact(tile); + devptr = ExtCurStyle->exts_device[loctype]; junk2 = resAddField(tile); - if (TTMaskHasType(&(ExtCurStyle->exts_transMask), loctype)) + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), loctype)) { resFet = (resTransistor *) mallocMagic((unsigned)(sizeof(resTransistor))); { @@ -191,7 +193,7 @@ ResAddPlumbing(tile, arg) /* top */ for (tp2= RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2)) { - if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[loctype][0]), + if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetBottomType(tp2)) { junk2->sourceEdge |= TOPEDGE; @@ -206,7 +208,7 @@ ResAddPlumbing(tile, arg) if (source == NULL) for (tp2= LB(tile); LEFT(tp2) < RIGHT(tile); tp2 = TR(tp2)) { - if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[loctype][0]), + if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetTopType(tp2)) { junk2->sourceEdge |= BOTTOMEDGE; @@ -221,7 +223,7 @@ ResAddPlumbing(tile, arg) if (source == NULL) for (tp2= TR(tile); TOP(tp2) > BOTTOM(tile); tp2 = LB(tp2)) { - if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[loctype][0]), + if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetLeftType(tp2)) { junk2->sourceEdge |= RIGHTEDGE; @@ -236,7 +238,7 @@ ResAddPlumbing(tile, arg) if (source == NULL) for (tp2= BL(tile); BOTTOM(tp2) < TOP(tile); tp2 = RT(tp2)) { - if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[loctype][0]), + if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetRightType(tp2)) { source = tp2; @@ -339,6 +341,7 @@ ResAddPlumbing(tile, arg) else t1 = TiGetTypeExact(tp1); + devptr = ExtCurStyle->exts_device[t1]; j0 = (tileJunk *) tp1->ti_client; /* top */ for (tp2= RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2)) @@ -352,7 +355,7 @@ ResAddPlumbing(tile, arg) Junk->tj_status |= RES_TILE_TRAN; } - else if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]), + else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetBottomType(tp2)) { Junk = resAddField(tp2); @@ -373,7 +376,7 @@ ResAddPlumbing(tile, arg) Junk->transistorList = resFet; Junk->tj_status |= RES_TILE_TRAN; } - else if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]), + else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetTopType(tp2)) { Junk = resAddField(tp2); @@ -394,7 +397,7 @@ ResAddPlumbing(tile, arg) Junk->transistorList = resFet; Junk->tj_status |= RES_TILE_TRAN; } - else if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]), + else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetLeftType(tp2)) { Junk = resAddField(tp2); @@ -415,7 +418,7 @@ ResAddPlumbing(tile, arg) Junk->transistorList = resFet; Junk->tj_status |= RES_TILE_TRAN; } - else if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t1][0]), + else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetRightType(tp2)) { Junk = resAddField(tp2); @@ -577,7 +580,7 @@ ResPreProcessTransistors(TileList, TransistorList, Def) { if (TTMaskHasType(&ttresidues, residue)) { - if (TTMaskHasType(&ExtCurStyle->exts_transMask, residue)) + if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, residue)) { pNum = DBPlane(residue); break; @@ -594,7 +597,7 @@ ResPreProcessTransistors(TileList, TransistorList, Def) tt = TiGetType(tile); tstruct = (tileJunk *) tile->ti_client; - if (!TTMaskHasType(&ExtCurStyle->exts_transMask, tt) || + if (!TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt) || tstruct->transistorList == NULL) { TxError("Bad Transistor Location at %d,%d\n", diff --git a/sim/SimExtract.c b/sim/SimExtract.c index 5678f360..dfc1faad 100644 --- a/sim/SimExtract.c +++ b/sim/SimExtract.c @@ -239,16 +239,18 @@ SimFreeNodeRegs() int SimInitConnTables() { int i, t, sd, p; + ExtDevice *devptr; - SimTransMask = ExtCurStyle->exts_transMask; + SimTransMask = ExtCurStyle->exts_deviceMask; TTMaskZero( &SimSDMask ); for( t = TT_TECHDEPBASE; t < DBNumTypes; t++ ) { - for (i = 0; !TTMaskHasType(&ExtCurStyle->exts_transSDTypes[t][i], + devptr = ExtCurStyle->exts_device[t]; + for (i = 0; !TTMaskHasType(&devptr->exts_deviceSDTypes[i], TT_SPACE); i++) { - TTMaskSetMask( &SimSDMask, &ExtCurStyle->exts_transSDTypes[t][i] ); + TTMaskSetMask( &SimSDMask, &devptr->exts_deviceSDTypes[i] ); TTMaskZero( &SimFetMask[t] ); } } @@ -258,12 +260,13 @@ int SimInitConnTables() { if (TTMaskHasType(&SimTransMask, t)) { + devptr = ExtCurStyle->exts_device[t]; for (sd = TT_TECHDEPBASE; sd < DBNumTypes; sd++) { - for (i = 0; !TTMaskHasType(&ExtCurStyle->exts_transSDTypes[t][i], + for (i = 0; !TTMaskHasType(&devptr->exts_deviceSDTypes[i], TT_SPACE); i++) { - if (TTMaskHasType(&ExtCurStyle->exts_transSDTypes[t][i], sd)) + if (TTMaskHasType(&devptr->exts_deviceSDTypes[i], sd)) { TTMaskSetType(&SimFetMask[sd], t); SimFetPlanes |= PlaneNumToMaskBit(DBPlane(t)); @@ -471,14 +474,16 @@ SimTransistorTile(tile, pNum, arg) { int i; TileType t; + ExtDevice *devptr; extSetNodeNum((LabRegion *)&transistor, pNum, tile); if (transistor.t_do_terms) { t = TiGetType(tile); - for (i = 0; !TTMaskHasType(&ExtCurStyle->exts_transSDTypes[t][i], + devptr = ExtCurStyle->exts_device[t]; + for (i = 0; !TTMaskHasType(&devptr->exts_deviceSDTypes[i], TT_SPACE); i++) - extEnumTilePerim(tile, ExtCurStyle->exts_transSDTypes[t][i], + extEnumTilePerim(tile, devptr->exts_deviceSDTypes[i], SimTransTerms, (ClientData) &transistor ); } From 942eaf8113383cd0798830787fcc8b5ff3f42a9e Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 20 Aug 2019 08:42:07 -0400 Subject: [PATCH 012/121] Revised the substrate extraction method: Instead of searching on all types specified in the "substrate" statement, split such types into those on the declared well plane, and everything else. Any types on the well plane are searched as before. Types not on the well plane (e.g., psd on active) are searched and added to the substrate node *only* if overlapping nothing on the well plane. This allows a type such as "psd" to be used on, e.g., both space (substrate) and deep pwell, but only be extracted as part of the substrate when found over space. Note that if there is NO implicit substrate, the substrate connections will always be found through the usual connection rules. --- database/DBprop.c | 13 ++++++++ extract/ExtBasic.c | 82 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 82 insertions(+), 13 deletions(-) diff --git a/database/DBprop.c b/database/DBprop.c index c2ded840..85574435 100644 --- a/database/DBprop.c +++ b/database/DBprop.c @@ -66,6 +66,15 @@ DBPropPut(cellDef, name, value) HashInit( (HashTable *) cellDef->cd_props, 8, 0); } htab = (HashTable *) cellDef->cd_props; + + /* Special handling of FIXED_BBOX, which uses CDFIXEDBBOX as a quick lookup */ + if (!strcmp(name, "FIXED_BBOX")) + { + if (value == (ClientData)NULL) + cellDef->cd_flags &= ~CDFIXEDBBOX; + else + cellDef->cd_flags |= CDFIXEDBBOX; + } entry = HashFind(htab, name); oldvalue = (char *)HashGetValue(entry); @@ -202,4 +211,8 @@ DBPropClearAll(cellDef) HashKill(htab); freeMagic((char *) htab); cellDef->cd_props = (ClientData) NULL; + + /* Since CDFIXEDBBOX requires a FIXED_BBOX property, clearing all */ + /* properties necessarily means this flag must be clear. */ + cellDef->cd_flags &= ~CDFIXEDBBOX; } diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 89e32cb7..57f12df1 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -123,18 +123,6 @@ LinkedBoundary **extSpecialBounds; /* Linked Boundary List */ NodeRegion *glob_subsnode = NULL; /* Global substrate node */ NodeRegion *temp_subsnode = NULL; /* Last subsnode found */ -/* Structure used for finding substrate connections on implicitly-defined - * substrates - */ - -typedef struct TSD1 -{ - bool found; /* Set to 1 if a substrate connection was found */ - Rect rtrans; /* Rectangle of device */ - Rect rhalo; /* Search halo around device */ - NodeRegion *nreg; /* Closest substrate region within halo */ -} TransSubsData; - #define EDGENULL(r) ((r)->r_xbot > (r)->r_xtop || (r)->r_ybot > (r)->r_ytop) /* Forward declarations */ @@ -3396,9 +3384,11 @@ extFindNodes(def, clipArea, subonly) { int extNodeAreaFunc(); int extSubsFunc(); + int extSubsFunc2(); FindRegion arg; int pNum, n; TileTypeBitMask subsTypesNonSpace; + bool space_is_substrate; /* Reset perimeter and area prior to node extraction */ for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) @@ -3418,19 +3408,52 @@ extFindNodes(def, clipArea, subonly) /* call extNodeAreaFunc() on the first of these to generate */ /* a single substrate node. */ + /* Refinement: Split search into two parts, one on the */ + /* globSubstratePlane and one on all other planes. ONLY */ + /* search other planes if TT_SPACE is in the list of */ + /* substrate types, and then only consider those types to */ + /* be part of the substrate node if they have only space */ + /* below them on the globSubstratePlane. This method lets */ + /* a single type like "psd" operate on, for example, both */ + /* the substrate and an isolated pwell, without implicitly */ + /* connecting the isolated pwell to the substrate. */ + temp_subsnode = (NodeRegion *)NULL; // Reset for new search + if (TTMaskHasType(&ExtCurStyle->exts_globSubstrateTypes, TT_SPACE)) + space_is_substrate = True; + else + space_is_substrate = False; + TTMaskZero(&subsTypesNonSpace); TTMaskSetMask(&subsTypesNonSpace, &ExtCurStyle->exts_globSubstrateTypes); TTMaskClearType(&subsTypesNonSpace, TT_SPACE); + pNum = ExtCurStyle->exts_globSubstratePlane; + /* Does the type set of this plane intersect the substrate types? */ + if (TTMaskIntersect(&DBPlaneTypes[pNum], &subsTypesNonSpace)) + { + arg.fra_pNum = pNum; + DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum], + &TiPlaneRect, &subsTypesNonSpace, extUnInit, + extSubsFunc, (ClientData) &arg); + } + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) { + if (pNum == ExtCurStyle->exts_globSubstratePlane) continue; + /* Does the type set of this plane intersect the substrate types? */ + if (TTMaskIntersect(&DBPlaneTypes[pNum], &subsTypesNonSpace)) { arg.fra_pNum = pNum; - DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum], + if (space_is_substrate) + DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum], + &TiPlaneRect, &subsTypesNonSpace, extUnInit, + extSubsFunc2, (ClientData) &arg); + else + DBSrPaintClient((Tile *) NULL, def->cd_planes[pNum], &TiPlaneRect, &subsTypesNonSpace, extUnInit, extSubsFunc, (ClientData) &arg); } @@ -3503,6 +3526,39 @@ extSubsFunc(tile, arg) return (0); } +int +extSubsFunc2(tile, arg) + Tile *tile; + FindRegion *arg; +{ + int pNum; + Rect tileArea; + int extSubsFunc3(); + + TiToRect(tile, &tileArea); + + /* Run second search in the area of the tile on the substrate plane */ + /* to make sure that nothing but space is under these tiles. */ + + pNum = ExtCurStyle->exts_globSubstratePlane; + + if (DBSrPaintArea((Tile *) NULL, arg->fra_def->cd_planes[pNum], + &tileArea, &DBAllButSpaceBits, + extSubsFunc3, (ClientData)NULL) == 0) + { + /* Mark this tile as pending and push it */ + PUSHTILE(tile, arg->fra_pNum); + } + return (0); +} + +int +extSubsFunc3(tile) + Tile *tile; +{ + /* Stops the search because something that was not space was found */ + return 1; +} int extNodeAreaFunc(tile, arg) From aa4bb4b19ca8c00ac76bd24a00b7d5c895b6f796 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 20 Aug 2019 10:37:12 -0400 Subject: [PATCH 013/121] Since allowing brackets to be part of cell names in a previous commit, found that DBTreeFindUse fails to find such uses because it strips the array delimiters off the name. Fixed the routine although the routine really should be checking if the use is a 1- or 2- dimensional array and stripping off only the components expected. The current code will probably fail for cell uses that have brackets in the name AND are arrayed. Fortunately this search routine does not appear to be used frequently or in any critical database functions like netlisting. --- database/DBlabel2.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/database/DBlabel2.c b/database/DBlabel2.c index 91c1908d..c060ac14 100644 --- a/database/DBlabel2.c +++ b/database/DBlabel2.c @@ -296,18 +296,25 @@ DBTreeFindUse(name, use, scx) if ((def->cd_flags & CDAVAILABLE) == 0) (void) DBCellRead(def, (char *) NULL, TRUE, NULL); - /* - * Pull off the next component of path up to but not including - * any array subscripts. - */ - for (cp = name; *cp && *cp != '[' && *cp != '/'; cp++) - /* Nothing */; - csave = *cp; - *cp = '\0'; he = HashLookOnly(&def->cd_idHash, name); - *cp = csave; if (he == NULL || HashGetValue(he) == NULL) - return; + { + /* + * Pull off the next component of path up to but not including + * any array subscripts. + * NOTE: This should check the array bounds and only remove + * array components that are expected, not array components + * embedded in the name. + */ + for (cp = name; *cp && *cp != '[' && *cp != '/'; cp++) + /* Nothing */; + csave = *cp; + *cp = '\0'; + he = HashLookOnly(&def->cd_idHash, name); + *cp = csave; + if (he == NULL || HashGetValue(he) == NULL) + return; + } use = (CellUse *) HashGetValue(he); def = use->cu_def; From c360fb9d5a91d4122aba2515f608c5a74d15bb75 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 20 Aug 2019 14:44:20 -0400 Subject: [PATCH 014/121] Corrected check on cd_client in CalmaRdcl; if not set for holding GDS plane data, it is initialized to CLIENTDEFAULT, not NULL. --- calma/CalmaRdcl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/calma/CalmaRdcl.c b/calma/CalmaRdcl.c index 28acae08..a42c624a 100644 --- a/calma/CalmaRdcl.c +++ b/calma/CalmaRdcl.c @@ -903,7 +903,8 @@ calmaElementSref(filename) for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) { - if (gdsplanes[pNum] != NULL) + if ((def->cd_client != (ClientData)CLIENTDEFAULT) && + (gdsplanes[pNum] != NULL)) { gdsCopyRec.plane = cifCurReadPlanes[pNum]; if (isArray) From d5b695fea07b2417899dc58fa82d9eb8e77f5eb1 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 20 Aug 2019 15:05:30 -0400 Subject: [PATCH 015/121] Corrected one other instance of checking for NULL when it should have checked for CLIENTDEFAULT. --- calma/CalmaRdcl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/calma/CalmaRdcl.c b/calma/CalmaRdcl.c index a42c624a..78de9986 100644 --- a/calma/CalmaRdcl.c +++ b/calma/CalmaRdcl.c @@ -415,7 +415,8 @@ calmaParseStructure(filename) for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) { - if (cifplanes[pNum] != NULL) + if ((cifReadCellDef->cd_client != (ClientData)CLIENTDEFAULT) && + (cifplanes[pNum] != NULL)) { DBFreePaintPlane(cifplanes[pNum]); TiFreePlane(cifplanes[pNum]); From a75aec4d7c20c86e7fb52f28f358ad09e0471608 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 20 Aug 2019 15:10:45 -0400 Subject: [PATCH 016/121] Finally realized the problem came from a quick addition of a TO-DO item that was never properly validated. Corrected the root of the problem, which was an attempt to deallocate memory that had never been allocated in the first place. --- calma/CalmaRdcl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/calma/CalmaRdcl.c b/calma/CalmaRdcl.c index 78de9986..e69bb386 100644 --- a/calma/CalmaRdcl.c +++ b/calma/CalmaRdcl.c @@ -405,18 +405,18 @@ calmaParseStructure(filename) */ if (CalmaFlattenUses && (!was_called) && (npaths < 10) && (nsrefs == 0)) { - /* To-do: If CDFLATGDS is already set, need to remove */ + /* If CDFLATGDS is already set, may need to remove */ /* existing planes and free memory. */ - if (cifReadCellDef->cd_flags & CDFLATGDS) + if ((cifReadCellDef->cd_client != (ClientData)CLIENTDEFAULT) && + (cifReadCellDef->cd_flags & CDFLATGDS)) { Plane **cifplanes = (Plane **)cifReadCellDef->cd_client; int pNum; for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) { - if ((cifReadCellDef->cd_client != (ClientData)CLIENTDEFAULT) && - (cifplanes[pNum] != NULL)) + if (cifplanes[pNum] != NULL) { DBFreePaintPlane(cifplanes[pNum]); TiFreePlane(cifplanes[pNum]); From 9f973fa9fc44aceefb517ddd76a5d124ea642c4b Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 23 Aug 2019 14:01:28 -0400 Subject: [PATCH 017/121] Minor correction to device extraction using the new device structure format with multiple devices per magic tile type. The code was left incompatible with diodes defined with one terminal as substrate (and therefore no source/drain-like types connecting to the device type). This has been fixed. --- extract/ExtBasic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 57f12df1..7787a09c 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -2704,7 +2704,7 @@ extTransPerimFunc(bp) break; } } - + if (toutside == TT_SPACE) break; if (SDterm) break; if (extConnectsTo(tinside, toutside, ExtCurStyle->exts_nodeConn)) { @@ -2715,6 +2715,7 @@ extTransPerimFunc(bp) /* Did not find a matching terminal, so see if a different extraction */ /* record matches the terminal type. */ + devptr = extDevFindMatch(devptr, tinside); if (devptr == deventry) devptr = NULL; } From 63829cbbaa6857133b5ad61a80537ae60e40ef91 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Sat, 24 Aug 2019 14:18:03 -0400 Subject: [PATCH 018/121] Hopefully final correction to new extraction method. Now correctly handles diodes or other devices with source/drain on planes other than the plane of the device type. This no longer requires that the non-connecting type be in any given terminal position. The device type boundary is surveyed for all types, connecting or overlapping, and at least one of each required type must be present. --- extract/ExtBasic.c | 192 ++++++++++++++++++++++++++------------------- 1 file changed, 113 insertions(+), 79 deletions(-) diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 7787a09c..bfd25db0 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -142,6 +142,8 @@ void extOutputParameters(); void extTransOutTerminal(); void extTransBad(); +ExtDevice *extDevFindMatch(); + bool extLabType(); /* Function returns 1 if a tile is found by DBTreeSrTiles() */ @@ -1600,12 +1602,12 @@ extOutputDevices(def, transList, outFile) { NodeRegion *node, *subsNode; TransRegion *reg; - ExtDevice *devptr; + ExtDevice *devptr, *deventry; char *subsName; FindRegion arg; LabelList *ll; TileType t; - int nsd, length, width, n, i, ntiles, corners, tn, rc; + int nsd, length, width, n, i, ntiles, corners, tn, rc, termcount; double dres, dcap; char mesg[256]; bool isAnnular, hasModel; @@ -1675,28 +1677,61 @@ extOutputDevices(def, transList, outFile) devptr = extTransRec.tr_devrec; if (devptr == NULL) continue; /* Bad device; do not output */ + deventry = devptr; - nsd = devptr->exts_deviceSDCount; - while (extTransRec.tr_nterm < nsd) + /* Use devmatch flags to determine if the specific S/D */ + /* terminal was handled by extTransPerimFunc already. */ + /* Only look at required S/D terminals that have not */ + /* yet been found. */ + + while (TRUE) { - TileTypeBitMask *tmask; - - tmask = &devptr->exts_deviceSDTypes[extTransRec.tr_nterm]; - if (TTMaskIsZero(tmask)) break; - if (!TTMaskIntersect(tmask, &DBPlaneTypes[reg->treg_pnum])) + nsd = devptr->exts_deviceSDCount; + for (termcount = 0; termcount < nsd; termcount++) { - node = NULL; - extTransFindSubs(reg->treg_tile, t, tmask, def, &node, NULL); - if (node == NULL) break; - extTransRec.tr_termnode[extTransRec.tr_nterm++] = node; + TileTypeBitMask *tmask; + + if ((extTransRec.tr_devmatch & (MATCH_TERM << termcount)) != 0) + continue; /* This terminal already found by perimeter search */ + + tmask = &devptr->exts_deviceSDTypes[termcount]; + if (TTMaskIsZero(tmask)) break; /* End of SD terminals */ + else if (!TTMaskIntersect(tmask, &DBPlaneTypes[reg->treg_pnum])) + { + node = NULL; + extTransFindSubs(reg->treg_tile, t, tmask, def, &node, NULL); + if (node == NULL) { + /* See if there is another matching device record */ + /* with a different terminal type, and try again. */ + devptr = extDevFindMatch(devptr, t); + break; + } + extTransRec.tr_devmatch |= (MATCH_TERM << termcount); + extTransRec.tr_termnode[termcount++] = node; + } + else if (TTMaskHasType(tmask, TT_SPACE)) { + /* Device node is specified as being the substrate */ + if (glob_subsnode == NULL) { + /* See if there is another matching device record */ + /* with a different terminal type, and try again. */ + devptr = extDevFindMatch(devptr, t); + break; + } + extTransRec.tr_devmatch |= (MATCH_TERM << termcount); + extTransRec.tr_termnode[termcount] = glob_subsnode; + } + else { + /* Determine if there is another matching device record */ + /* that has fewer required terminals. */ + devptr = extDevFindMatch(devptr, t); + break; + } } - else if (TTMaskHasType(tmask, TT_SPACE)) { - /* Device node is specified as being the substrate */ - if (glob_subsnode == NULL) break; - extTransRec.tr_termnode[extTransRec.tr_nterm++] = glob_subsnode; - } - else break; + if (termcount == nsd) break; /* All terminals accounted for */ + if (devptr == deventry) break; /* No other device records available */ + /* Try again with a different device record */ } + extTransRec.tr_nterm = termcount; /* * For types that require a minimum number of terminals, @@ -1849,8 +1884,8 @@ extOutputDevices(def, transList, outFile) { /* Don't issue a warning on devices such as a */ /* vertical diode that may declare zero terminals */ - /* because the substrate node (i.e., well) is the */ - /* other terminal. */ + /* because the default substrate node is the other */ + /* terminal. */ if (ExtDoWarn && (devptr->exts_deviceSDCount > 0)) extTransBad(def, reg->treg_tile, @@ -2435,63 +2470,66 @@ extTransTileFunc(tile, pNum, arg) devtest = devtest->exts_next) TTMaskSetMask(&cmask, &devtest->exts_deviceSubstrateTypes); - if (TTMaskHasType(&cmask, TT_SPACE)) + if (!TTMaskIsZero(&cmask)) { - allow_globsubsnode = TRUE; - TTMaskClearType(&cmask, TT_SPACE); - } - - if (extTransRec.tr_subsnode == (NodeRegion *)NULL) - { - sublayer = TT_SPACE; - region = NULL; - extTransFindSubs(tile, loctype, &cmask, arg->fra_def, ®ion, &sublayer); - - /* If the device does not connect to a defined node, and - * the substrate types include "space", then it is assumed to - * connect to the global substrate. - */ - - if (region == (NodeRegion *)NULL) - if (allow_globsubsnode) - region = glob_subsnode; - - extTransRec.tr_subsnode = region; - - if ((region != (NodeRegion *)NULL) && - !(TTMaskHasType(&devptr->exts_deviceSubstrateTypes, sublayer))) + if (TTMaskHasType(&cmask, TT_SPACE)) { - /* A substrate layer was found but is not compatible with the */ - /* current device. Find a device record with the substrate */ - /* layer that was found, and set the substrate match flag. */ + allow_globsubsnode = TRUE; + TTMaskClearType(&cmask, TT_SPACE); + } - deventry = devptr; - while (devptr != NULL) + if (extTransRec.tr_subsnode == (NodeRegion *)NULL) + { + sublayer = TT_SPACE; + region = NULL; + extTransFindSubs(tile, loctype, &cmask, arg->fra_def, ®ion, &sublayer); + + /* If the device does not connect to a defined node, and + * the substrate types include "space", then it is assumed to + * connect to the global substrate. + */ + + if (region == (NodeRegion *)NULL) + if (allow_globsubsnode) + region = glob_subsnode; + + extTransRec.tr_subsnode = region; + + if ((region != (NodeRegion *)NULL) && + !(TTMaskHasType(&devptr->exts_deviceSubstrateTypes, sublayer))) { - devptr = extDevFindMatch(devptr, loctype); - if ((devptr == NULL) || (devptr == deventry)) + /* A substrate layer was found but is not compatible with the */ + /* current device. Find a device record with the substrate */ + /* layer that was found, and set the substrate match flag. */ + + deventry = devptr; + while (devptr != NULL) { - TxError("No matching device for %s with substrate layer %s\n", + devptr = extDevFindMatch(devptr, loctype); + if ((devptr == NULL) || (devptr == deventry)) + { + TxError("No matching device for %s with substrate layer %s\n", DBTypeLongNameTbl[loctype], DBTypeLongNameTbl[sublayer]); - devptr = NULL; - break; - } - if (TTMaskHasType(&devptr->exts_deviceSubstrateTypes, sublayer)) - { - extTransRec.tr_devmatch |= MATCH_SUB; - break; + devptr = NULL; + break; + } + if (TTMaskHasType(&devptr->exts_deviceSubstrateTypes, sublayer)) + { + extTransRec.tr_devmatch |= MATCH_SUB; + break; + } } } + else if (region == (NodeRegion *)NULL) + { + TxError("Device %s does not have a compatible substrate node!\n", + DBTypeLongNameTbl[loctype]); + devptr = NULL; + } } - else if (region == (NodeRegion *)NULL) - { - TxError("Device %s does not have a compatible substrate node!\n", - DBTypeLongNameTbl[loctype]); - devptr = NULL; - } + extTransRec.tr_devrec = devptr; + if (devptr == NULL) return 0; /* No matching devices, so forget it. */ } - extTransRec.tr_devrec = devptr; - if (devptr == NULL) return 0; /* No matching devices, so forget it. */ /* If at least one device type declares an ID layer, then make a */ /* mask of all device ID types, and search on the area of the */ @@ -2889,27 +2927,23 @@ extSpecialPerimFunc(bp, sense) break; } - devptr = extTransRec.tr_devrec; - if (devptr == NULL) devptr = ExtCurStyle->exts_device[tinside]; + /* Required to use the same device record that was used to find */ + /* the terminals. */ + if ((devptr = extTransRec.tr_devrec) == NULL) return 0; /* Check all terminal classes for a matching type */ needSurvey = FALSE; - for (; devptr; devptr = devptr->exts_next) + for (i = 0; !TTMaskIsZero(&devptr->exts_deviceSDTypes[i]); i++) { - for (i = 0; !TTMaskIsZero(&devptr->exts_deviceSDTypes[i]); i++) + if (TTMaskHasType(&devptr->exts_deviceSDTypes[i], toutside)) { - if (TTMaskHasType(&devptr->exts_deviceSDTypes[i], toutside)) - { - needSurvey = TRUE; - break; - } + needSurvey = TRUE; + break; } } if (!sense || needSurvey) { - extTransRec.tr_devrec = devptr; - if (toutside == TT_SPACE) if (glob_subsnode != NULL) diffNode = glob_subsnode; From 643c39a2d5c6979f40ab336b9107ff45f220d049 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 3 Sep 2019 14:02:27 -0400 Subject: [PATCH 019/121] Corrected error where modification to allow use of brackets inside a cell instance name not related to an array moved a variable that was used later in the routine to the inside of an if block, effectively making that variable undefined in most cases. --- database/DBlabel2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/database/DBlabel2.c b/database/DBlabel2.c index c060ac14..9ddba125 100644 --- a/database/DBlabel2.c +++ b/database/DBlabel2.c @@ -296,6 +296,7 @@ DBTreeFindUse(name, use, scx) if ((def->cd_flags & CDAVAILABLE) == 0) (void) DBCellRead(def, (char *) NULL, TRUE, NULL); + cp = name; he = HashLookOnly(&def->cd_idHash, name); if (he == NULL || HashGetValue(he) == NULL) { @@ -306,7 +307,7 @@ DBTreeFindUse(name, use, scx) * array components that are expected, not array components * embedded in the name. */ - for (cp = name; *cp && *cp != '[' && *cp != '/'; cp++) + for (; *cp && *cp != '[' && *cp != '/'; cp++) /* Nothing */; csave = *cp; *cp = '\0'; From 9b0905ad01249221f06a53c3bb4677ae55ebda76 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 13 Sep 2019 09:52:45 -0400 Subject: [PATCH 020/121] Corrected an error in the GDS compositing that fails to handle GDS files that have forward references (cells that are instanced before they are defined), resulting in those cells being given an undefined string for a prefix, which will result in corrupted GDS output. Also added a method to prevent forward-referenced cells from triggering a "redundantly defined" error message when the structure is output. --- calma/CalmaWrite.c | 68 +++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/calma/CalmaWrite.c b/calma/CalmaWrite.c index 82b1929f..5a01d85b 100644 --- a/calma/CalmaWrite.c +++ b/calma/CalmaWrite.c @@ -375,7 +375,7 @@ calmaDumpStructure(def, outf, calmaDefHash, filename) char *strname = NULL, *newnameptr, newname[CALMANAMELENGTH*2]; HashEntry *he, *he2; CellDef *edef; - char *prefix; + char *prefix = NULL; /* Make sure this is a structure; if not, let the caller know we're done */ PEEKRH(nbytes, rtype); @@ -397,23 +397,35 @@ calmaDumpStructure(def, outf, calmaDefHash, filename) calmaOutDate(def->cd_timestamp, outf); calmaOutDate(time((time_t *) 0), outf); + /* Find the structure's unique prefix, in case structure calls subcells */ + /* that are not yet defined. */ + + he2 = HashFind(&calmaLibHash, filename); + if (he2 == NULL) + TxError("Fatal error: Library %s not recorded!\n", filename); + else + prefix = (char *)HashGetValue(he2); + /* Prefix structure name with def name, and output new structure name */ he = HashFind(calmaDefHash, strname); if ((newnameptr = (char *)HashGetValue(he)) != NULL) { /* Structure is defined more than once */ - TxError("Structure %s defined redundantly in GDS\n", strname); + if (*newnameptr != '0') + TxError("Structure %s defined redundantly in GDS\n", strname); + else + *newnameptr = '1'; /* To be considered: Should the structure be output more than once? */ - calmaOutStringRecord(CALMA_STRNAME, newnameptr, outf); + calmaOutStringRecord(CALMA_STRNAME, newnameptr + 1, outf); } else if (!strcmp(strname, def->cd_name)) { /* This is the top level cell being defined. Its name */ /* does not get modified. */ - newnameptr = mallocMagic(strlen(strname) + 1); - sprintf(newnameptr, "%s", strname); - calmaOutStringRecord(CALMA_STRNAME, newnameptr, outf); + newnameptr = mallocMagic(strlen(strname) + 2); + sprintf(newnameptr, "1%s", strname); + calmaOutStringRecord(CALMA_STRNAME, newnameptr + 1, outf); HashSetValue(he, (char *)newnameptr); } else @@ -444,26 +456,20 @@ calmaDumpStructure(def, outf, calmaDefHash, filename) /* Same library, so keep the cellname and mark the cell */ /* as having been written to GDS. */ - newnameptr = mallocMagic(strlen(strname) + 1); - sprintf(newnameptr, "%s", strname); + newnameptr = mallocMagic(strlen(strname) + 2); + sprintf(newnameptr, "1%s", strname); HashSetValue(he, (char *)newnameptr); } else { /* Find the unique library prefix and prepend it to the cell name */ - he2 = HashFind(&calmaLibHash, filename); - if (he2 == NULL) - { - /* Should never happen */ - TxError("Fatal error: Library %s not recorded!\n", filename); - newnameptr = strname; - } + if (prefix == NULL) + newnameptr = strname; /* Should never happen */ else { - prefix = (char *)HashGetValue(he2); - newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 8); - sprintf(newnameptr, "%s_%s", prefix, strname); + newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 9); + sprintf(newnameptr, "1%s_%s", prefix, strname); HashSetValue(he, (char *)newnameptr); } } @@ -472,18 +478,12 @@ calmaDumpStructure(def, outf, calmaDefHash, filename) { /* Find the unique library prefix and prepend it to the cell name */ - he2 = HashFind(&calmaLibHash, filename); - if (he2 == NULL) - { - /* Should never happen */ - TxError("Fatal error: Library %s not recorded!\n", filename); - newnameptr = strname; - } + if (prefix == NULL) + newnameptr = strname; /* Should never happen */ else { - prefix = (char *)HashGetValue(he2); - newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 8); - sprintf(newnameptr, "%s_%s", prefix, strname); + newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 9); + sprintf(newnameptr, "1%s_%s", prefix, strname); HashSetValue(he, (char *)newnameptr); } } @@ -525,7 +525,7 @@ calmaDumpStructure(def, outf, calmaDefHash, filename) newnameptr = (char *)HashGetValue(he); if (newnameptr != NULL) { - calmaOutStringRecord(CALMA_SNAME, newnameptr, outf); + calmaOutStringRecord(CALMA_SNAME, newnameptr + 1, outf); } else { @@ -535,14 +535,14 @@ calmaDumpStructure(def, outf, calmaDefHash, filename) /* the same way used for structure definitions. */ newnameptr = (char *)mallocMagic(strlen(strname) + - strlen(prefix) + 8); - sprintf(newnameptr, "%s_%s", prefix, strname); + strlen(prefix) + 9); + sprintf(newnameptr, "0%s_%s", prefix, strname); - edef = DBCellLookDef(newnameptr); + edef = DBCellLookDef(newnameptr + 1); if (edef != NULL) - sprintf(newnameptr, "%s_%s[[0]]", prefix, strname); + sprintf(newnameptr, "0%s_%s[[0]]", prefix, strname); HashSetValue(he, (char *)newnameptr); - calmaOutStringRecord(CALMA_SNAME, newnameptr, outf); + calmaOutStringRecord(CALMA_SNAME, newnameptr + 1, outf); } break; From 4b5566af3ea71abc06ceaa6e7e00229d2ca4acda Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 18 Sep 2019 20:48:33 -0400 Subject: [PATCH 021/121] Corrected an error that causes alias names for layers to become the principle layer name, which should not happen (especially in the case of space, where layers may be aliased to "space" to make them ignored on input). Also: Implemented a "-" option to the "substrate" record in the techfile to declare types which shield layers from the substrate. This allows types like pwell to be used in different contexts, e.g., as part of the substrate, or as a P-well in deep N-well, without requiring a different type. This works in conjunction with the recently-implemented "+" ID types for devices. All of this may seem unnecessary but helps to reduce the number of layers needing to be defined, and the subsequent complexity of the DRC rulesets. --- database/DBtechtype.c | 17 +++++++++-------- extract/ExtBasic.c | 26 ++++++++++++++++++++++++++ extract/ExtTech.c | 18 ++++++++++++++++-- extract/extractInt.h | 7 ++++++- 4 files changed, 57 insertions(+), 11 deletions(-) diff --git a/database/DBtechtype.c b/database/DBtechtype.c index 5851b5a5..5233d077 100644 --- a/database/DBtechtype.c +++ b/database/DBtechtype.c @@ -141,7 +141,7 @@ DBTechInitPlane() for (dpp = dbTechDefaultPlanes; dpp->dp_names; dpp++) { cp = dbTechNameAdd(dpp->dp_names, (ClientData) dpp->dp_plane, - &dbPlaneNameLists); + &dbPlaneNameLists, FALSE); if (cp == NULL) { TxError("DBTechInit: can't add plane names %s\n", dpp->dp_names); @@ -224,7 +224,7 @@ DBTechInitType() for (dtp = dbTechDefaultTypes; dtp->dt_names; dtp++) { cp = dbTechNameAdd(dtp->dt_names, (ClientData) dtp->dt_type, - &dbTypeNameLists); + &dbTypeNameLists, FALSE); if (cp == NULL) { TxError("DBTechInit: can't add type names %s\n", dtp->dt_names); @@ -283,7 +283,7 @@ DBTechAddPlane(sectionName, argc, argv) return FALSE; } - cp = dbTechNameAdd(argv[0], (ClientData) DBNumPlanes, &dbPlaneNameLists); + cp = dbTechNameAdd(argv[0], (ClientData) DBNumPlanes, &dbPlaneNameLists, FALSE); if (cp == NULL) return FALSE; DBPlaneLongNameTbl[DBNumPlanes++] = cp; @@ -315,7 +315,7 @@ DBTechAddNameToType(newname, ttype, canonical) { char *cp; - cp = dbTechNameAdd(newname, (ClientData) ttype, &dbTypeNameLists); + cp = dbTechNameAdd(newname, (ClientData) ttype, &dbTypeNameLists, TRUE); if (canonical) DBTypeLongNameTbl[ttype] = cp; } @@ -455,7 +455,7 @@ DBTechAddType(sectionName, argc, argv) } else { - cp = dbTechNameAdd(argv[1], (ClientData) DBNumTypes, &dbTypeNameLists); + cp = dbTechNameAdd(argv[1], (ClientData) DBNumTypes, &dbTypeNameLists, FALSE); if (cp == NULL) return FALSE; @@ -513,7 +513,7 @@ dbTechNewStackedType(type1, type2) } sprintf(buf, "%s+%s", DBTypeShortName(type1), DBTypeShortName(type2)); - cp = dbTechNameAdd(buf, (ClientData) DBNumTypes, &dbTypeNameLists); + cp = dbTechNameAdd(buf, (ClientData) DBNumTypes, &dbTypeNameLists, FALSE); if (cp == NULL) { TechError("Couldn't generate new stacking type %s\n", buf); @@ -730,10 +730,11 @@ dbTechNameLookup(str, table) */ char * -dbTechNameAdd(name, cdata, ptable) +dbTechNameAdd(name, cdata, ptable, alias) char *name; /* Comma-separated list of names to be added */ ClientData cdata; /* Value to be stored with each name above */ NameList *ptable; /* Table to which we will add names */ + int alias; /* 1 if this is an alias (never make primary) */ { char *cp; char onename[BUFSIZ]; @@ -769,7 +770,7 @@ dbTechNameAdd(name, cdata, ptable) } } - if (primary) + if (primary && (alias == 0)) primary->sn_primary = TRUE; return (first); } diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index bfd25db0..38d76441 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -3546,7 +3546,11 @@ extSubsFunc(tile, arg) Tile *tile; FindRegion *arg; { + int pNum; + Rect tileArea; TileType type; + TileTypeBitMask *smask; + int extSubsFunc3(); if (IsSplit(tile)) { @@ -3554,6 +3558,17 @@ extSubsFunc(tile, arg) if (type == TT_SPACE) return 0; /* Should not happen */ } + /* Run second search in the area of the tile on the substrate plane */ + /* to make sure that no shield types are covering this tile. */ + + TiToRect(tile, &tileArea); + smask = &ExtCurStyle->exts_globSubstrateShieldTypes; + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if (TTMaskIntersect(&DBPlaneTypes[pNum], smask)) + if (DBSrPaintArea((Tile *) NULL, arg->fra_def->cd_planes[pNum], + &tileArea, smask, extSubsFunc3, (ClientData)NULL) != 0) + return (1); + /* Mark this tile as pending and push it */ PUSHTILE(tile, arg->fra_pNum); @@ -3568,11 +3583,22 @@ extSubsFunc2(tile, arg) { int pNum; Rect tileArea; + TileTypeBitMask *smask; int extSubsFunc3(); TiToRect(tile, &tileArea); /* Run second search in the area of the tile on the substrate plane */ + /* to make sure that no shield types are covering this tile. */ + + smask = &ExtCurStyle->exts_globSubstrateShieldTypes; + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if (TTMaskIntersect(&DBPlaneTypes[pNum], smask)) + if (DBSrPaintArea((Tile *) NULL, arg->fra_def->cd_planes[pNum], + &tileArea, smask, extSubsFunc3, (ClientData)NULL) != 0) + return (1); + + /* Run third search in the area of the tile on the substrate plane */ /* to make sure that nothing but space is under these tiles. */ pNum = ExtCurStyle->exts_globSubstratePlane; diff --git a/extract/ExtTech.c b/extract/ExtTech.c index d778749d..314bed99 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -157,7 +157,7 @@ static keydesc keyTable[] = { "style", STYLE, 2, 4, "stylename", - "substrate", SUBSTRATE, 3, 3, + "substrate", SUBSTRATE, 3, 4, "types plane", "units", UNITS, 2, 2, @@ -675,6 +675,7 @@ extTechStyleInit(style) style->exts_globSubstratePlane = -1; TTMaskZero(&style->exts_globSubstrateTypes); + TTMaskZero(&style->exts_globSubstrateShieldTypes); } @@ -1927,7 +1928,6 @@ ExtTechLine(sectionName, argc, argv) case DEFAULTSIDEWALL: ExtTechSimpleSidewallCap(argv); break; - case DEVICE: /* Parse second argument for device type */ @@ -2587,8 +2587,22 @@ ExtTechLine(sectionName, argc, argv) ExtCurStyle->exts_stepSize = val; break; case SUBSTRATE: + /* If the last entry starts with '-', then use it to set */ + /* the shield types. Otherwise, the shield types mask is */ + /* NULL. */ + + idTypes = DBZeroTypeBits; + if (*argv[argc - 1] == '-') + { + if ((DBTechNameMask(argv[argc - 1] + 1, &idTypes)) == 0) + idTypes = DBZeroTypeBits; + argc--; + } + TTMaskZero(&ExtCurStyle->exts_globSubstrateTypes); + TTMaskZero(&ExtCurStyle->exts_globSubstrateShieldTypes); TTMaskSetMask(&ExtCurStyle->exts_globSubstrateTypes, &types1); + ExtCurStyle->exts_globSubstrateShieldTypes = idTypes; ExtCurStyle->exts_globSubstratePlane = DBTechNoisyNamePlane(argv[2]); break; case NOPLANEORDER: { diff --git a/extract/extractInt.h b/extract/extractInt.h index d5779afa..5e0064e1 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -872,11 +872,16 @@ typedef struct extstyle * types that connect to the substrate. Since for non-SOI * processes, this generally is used to specify that space on * the well plane is the substrate, the plane number for the - * well plane is given, too. + * well plane is given, too. The "shield types" mask is a + * mask of types that prevent any types in exts_globSubstrateTypes + * from contacting the substrate (e.g., deep nwell might be a + * shielding type, or it could be a special marker layer like + * "not_substrate"). */ char *exts_globSubstrateName; TileTypeBitMask exts_globSubstrateTypes; int exts_globSubstratePlane; + TileTypeBitMask exts_globSubstrateShieldTypes; /* Scaling */ /* From 0c24c3345174079a07101d89d35a9c7ac4d47a8e Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 19 Sep 2019 08:22:11 -0400 Subject: [PATCH 022/121] Corrected a bad error from a previous commit (5 days ago, for fixing the forward-referenced GDS cell problem) in which when writing cells from 3rd-party GDS, the structure names are written to GDS with the indicator flag in front, making the structure names and the referenced names different, so that the GDS file is no longer valid. This has been fixed. --- calma/CalmaWrite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/calma/CalmaWrite.c b/calma/CalmaWrite.c index 5a01d85b..8a8842f3 100644 --- a/calma/CalmaWrite.c +++ b/calma/CalmaWrite.c @@ -487,7 +487,7 @@ calmaDumpStructure(def, outf, calmaDefHash, filename) HashSetValue(he, (char *)newnameptr); } } - calmaOutStringRecord(CALMA_STRNAME, newnameptr, outf); + calmaOutStringRecord(CALMA_STRNAME, newnameptr + 1, outf); } freeMagic(strname); From 091d7ba2ae128b7642cadcf372d85f8180dcdea2 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 19 Sep 2019 14:33:30 -0400 Subject: [PATCH 023/121] Corrected drcAssign for use with CIF drc rules, where the check for plane is not relevant and can generate false-positive error messages (although no actual errors occur). --- drc/DRCcif.c | 23 +++++++++++------------ drc/DRCtech.c | 27 ++++++++++++++++++++++----- drc/drc.h | 2 ++ 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/drc/DRCcif.c b/drc/DRCcif.c index 6fe7321b..b4344620 100644 --- a/drc/DRCcif.c +++ b/drc/DRCcif.c @@ -200,7 +200,7 @@ drcCifWidth(argc, argv) dpnext = drcCifRules[thislayer][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, centidistance, dpnext, &CIFSolidBits, + drcCifAssign(dpnew, centidistance, dpnext, &CIFSolidBits, &CIFSolidBits, why, centidistance, DRC_FORWARD, thislayer, 0); drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew; @@ -292,7 +292,7 @@ drcCifSpacing(argc, argv) centidistance *= drcCifStyle->cs_expander; // BSI dpnext = drcCifRules[layer[0]][DRC_CIF_SOLID]; dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie)); - drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, + drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, why, centidistance, DRC_FORWARD, layer[1], 0); drcCifRules[layer[0]][DRC_CIF_SOLID] = dpnew; if (needReverse) dpnew->drcc_flags |= DRC_BOTHCORNERS; @@ -300,7 +300,7 @@ drcCifSpacing(argc, argv) // Add rule in reverse direction dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie)); - drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, + drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, why, centidistance, DRC_REVERSE, layer[1], 0); drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew; @@ -312,14 +312,14 @@ drcCifSpacing(argc, argv) dpnew->drcc_flags |= DRC_BOTHCORNERS; dpnext = drcCifRules[layer[1]][DRC_CIF_SOLID]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, + drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, why, centidistance, DRC_FORWARD|DRC_BOTHCORNERS, layer[0], 0); drcCifRules[layer[1]][DRC_CIF_SOLID] = dpnew; // Add rule in reverse direction dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie)); - drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, + drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, why, centidistance, DRC_REVERSE|DRC_BOTHCORNERS, layer[0], 0); drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew; @@ -327,14 +327,14 @@ drcCifSpacing(argc, argv) { dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, + drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, why, centidistance, DRC_REVERSE | DRC_BOTHCORNERS, layer[0], 0); drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew; dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, + drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, why, centidistance, DRC_REVERSE | DRC_BOTHCORNERS, layer[1], 0); drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew; @@ -345,13 +345,13 @@ drcCifSpacing(argc, argv) { dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, scalefactor, dpnext, &DBSpaceBits, &DBZeroTypeBits, + drcCifAssign(dpnew, scalefactor, dpnext, &DBSpaceBits, &DBZeroTypeBits, why, scalefactor, DRC_FORWARD, layer[0], 0); drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew; dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, scalefactor, dpnext, &DBSpaceBits, &DBZeroTypeBits, + drcCifAssign(dpnew, scalefactor, dpnext, &DBSpaceBits, &DBZeroTypeBits, why, scalefactor, DRC_FORWARD, layer[1], 0); drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew; } @@ -1066,7 +1066,7 @@ drcCifArea(argc, argv) centiarea *= (drcCifStyle->cs_expander * drcCifStyle->cs_expander); dpnext = drcCifRules[thislayer][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, centihorizon, dpnext, &CIFSolidBits, &CIFSolidBits, + drcCifAssign(dpnew, centihorizon, dpnext, &CIFSolidBits, &CIFSolidBits, why, centiarea, DRC_AREA | DRC_FORWARD, thislayer, 0); drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew; @@ -1136,11 +1136,10 @@ drcCifMaxwidth(argc, argv) centidistance *= drcCifStyle->cs_expander; // BSI dpnext = drcCifRules[thislayer][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, centidistance, dpnext, &CIFSolidBits, &CIFSolidBits, + drcCifAssign(dpnew, centidistance, dpnext, &CIFSolidBits, &CIFSolidBits, why, centidistance, DRC_MAXWIDTH | bend, thislayer, 0); drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew; - return ((centidistance+scalefactor-1)/scalefactor); } diff --git a/drc/DRCtech.c b/drc/DRCtech.c index 62c09066..dd49a0d4 100644 --- a/drc/DRCtech.c +++ b/drc/DRCtech.c @@ -872,17 +872,13 @@ DRCTechLine(sectionName, argc, argv) } void -drcAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefrom) +drcCifAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefrom) DRCCookie *cookie, *next; int dist, cdist; TileTypeBitMask *mask, *corner; char *why; int flags, planeto, planefrom; { - /* Diagnostic */ - if (planeto >= DBNumPlanes) { - TxError("Bad plane in DRC assign!\n"); - } (cookie)->drcc_dist = dist; (cookie)->drcc_next = next; (cookie)->drcc_mask = *mask; @@ -896,6 +892,27 @@ drcAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefro (cookie)->drcc_cmod = 0; } +// This is like drcCifAssign, but checks for bad plane numbers in planeto and +// planefrom + +void +drcAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefrom) + DRCCookie *cookie, *next; + int dist, cdist; + TileTypeBitMask *mask, *corner; + char *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); +} + /* * ---------------------------------------------------------------------------- * diff --git a/drc/drc.h b/drc/drc.h index 0ca8847a..e2dea941 100644 --- a/drc/drc.h +++ b/drc/drc.h @@ -239,6 +239,8 @@ extern void drcPrintError(); extern int drcIncludeArea(); extern int drcExactOverlapTile(); extern void drcInitRulesTbl(); +extern void drcAssign(); +extern void drcCifAssign(); /* * Exported procedures From 798e87deaff43411414af4138b376b5aff02158f Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 1 Oct 2019 19:32:52 -0400 Subject: [PATCH 024/121] Corrected method relating to use of array notation in the base use name (not part of an array in magic). This was failing in ext2spice due to code in extflat dealing incorrectly with the array delimiters. The correction fixes the problem but leaves the possibility that there could be a conflict between a use name that is an array and a use name that has the array index as part of the name. --- ext2spice/ext2hier.c | 33 +++++++++++++++------------------ extflat/EFbuild.c | 4 ++-- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 93236df8..62dbc13b 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1576,24 +1576,22 @@ esMakePorts(hc, cdata) bool is_array; /* Ignore array information for the purpose of tracing */ - /* the cell definition hierarchy. Complementary to the */ - /* method used in EFbuild.c, only consider uses of */ - /* brackets that conform to the [ax:bx:cx][ay:by:cy] */ - /* notation. */ + /* the cell definition hierarchy. If a cell use name */ + /* contains a bracket, check first if the complete name */ + /* matches a use. If not, then check if the part */ + /* the last opening bracket matches a known use. */ - aptr = strchr(portname, '['); - if (aptr && (aptr < tptr) && - (sscanf(aptr, "[%d:%d:%d][%d:%d:%d]", - &idum[0], &idum[1], &idum[2], - &idum[3], &idum[4], &idum[5]) == 6)) + aptr = strrchr(portname, '['); + *tptr = '\0'; + is_array = FALSE; + if (aptr != NULL) { - is_array = TRUE; - *aptr = '\0'; - } - else - { - is_array = FALSE; - *tptr = '\0'; + he = HashFind(&updef->def_uses, portname); + if (he == NULL) + { + *aptr = '\0'; + is_array = TRUE; + } } // Find the cell for the instance @@ -1606,8 +1604,7 @@ esMakePorts(hc, cdata) } if (is_array) *aptr = '['; - else - *tptr = '/'; + *tptr = '/'; portname = tptr + 1; // Find the net of portname in the subcell and diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c index 3d56225f..3c83efe4 100644 --- a/extflat/EFbuild.c +++ b/extflat/EFbuild.c @@ -553,8 +553,8 @@ efBuildDeviceParams(name, argc, argv) if (name[0] == ':') { newparm->parm_name = StrDup((char **)NULL, argv[n]); - newparm->parm_type[1] = '0' + n / 10; - newparm->parm_type[0] = '0' + n % 10; + newparm->parm_type[0] = '0' + n / 10; + newparm->parm_type[1] = '0' + n % 10; } else newparm->parm_name = StrDup((char **)NULL, pptr + 1); From 000dab40e3403a69466af37f3458339f62637078 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 2 Oct 2019 12:59:10 -0400 Subject: [PATCH 025/121] Made a correction to the last commit as the wrong hash search function was used (HashFind, which never returns NULL, vs. HashLookOnly, which does) resulting in a failure to solve the problem which was being patched, which was ext2spice crashing when cell arrays are present, which itself was due to allowing brackets in base cell use names. --- ext2spice/ext2hier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 62dbc13b..fd06a376 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1586,7 +1586,7 @@ esMakePorts(hc, cdata) is_array = FALSE; if (aptr != NULL) { - he = HashFind(&updef->def_uses, portname); + he = HashLookOnly(&updef->def_uses, portname); if (he == NULL) { *aptr = '\0'; From b0719384e48cd76a240c90808d08b4eb753ba9aa Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 14 Oct 2019 11:09:58 -0400 Subject: [PATCH 026/121] Modified the new extraction method with multiple records for each device type so that it is now properly backwards compatible with the old-style "fet" records. Also corrected the record matching such that it properly matches according to the number of terminals while allowing the traditional interpretation that there may be fewer S/D type records than terminals if the S/D types are the same for all terminals. --- ext2spice/ext2spice.c | 2 +- extract/ExtBasic.c | 52 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 6947027a..46853437 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -1248,7 +1248,7 @@ spcmainArgs(pargc, pargv) usage: TxError("Usage: ext2spice [-B] [-o spicefile] [-M|-m] [-y cap_digits] " "[-J flat|hier]\n" - "[-f spice2|spice3|hspice] [-M] [-m] " + "[-f spice2|spice3|hspice|ngspice] [-M] [-m] " #ifdef MAGIC_WRAPPER "[file]\n" #else diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 38d76441..e0503d20 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -2337,7 +2337,7 @@ extDevFindMatch(deventry, t) TileType t; { ExtDevice *devptr; - int i, j, matchflags; + int i, j, k, matchflags; bool match; matchflags = extTransRec.tr_devmatch; @@ -2362,10 +2362,11 @@ extDevFindMatch(deventry, t) &deventry->exts_deviceSubstrateTypes)) continue; j = MATCH_TERM; + i = 0; match = True; - for (i = 0; i < MAXSD; i++) + for (k = 0; k < devptr->exts_deviceSDCount; k++) { - if (extTransRec.tr_termnode[i] == NULL) break; + if (extTransRec.tr_termnode[k] == NULL) break; if (matchflags & j) /* Must have the same terminal type */ { if (TTMaskIsZero(&devptr->exts_deviceSDTypes[i])) @@ -2380,7 +2381,13 @@ extDevFindMatch(deventry, t) break; } } - j >>= 1; + j <<= 1; + + /* NOTE: There are fewer exts_deviceSDTypes records than */ + /* terminals if all S/D terminals are the same type. In */ + /* that case k increments and j bit shifts but i remains */ + /* the same. */ + if (!TTMaskIsZero(&devptr->exts_deviceSDTypes[i + 1])) i++; } if (match) break; } @@ -2522,9 +2529,19 @@ extTransTileFunc(tile, pNum, arg) } else if (region == (NodeRegion *)NULL) { - TxError("Device %s does not have a compatible substrate node!\n", - DBTypeLongNameTbl[loctype]); - devptr = NULL; + /* If ExtCurStyle->exts_globSubstrateTypes contains no types */ + /* then this is an older style techfile without a "substrate" */ + /* definition in the extract section. In that case, it is */ + /* expected that the substrate name in the device line will be */ + /* used. */ + + if (!TTMaskIsZero(&ExtCurStyle->exts_globSubstrateTypes) || + (devptr->exts_deviceSubstrateName == NULL)) + { + TxError("Device %s does not have a compatible substrate node!\n", + DBTypeLongNameTbl[loctype]); + devptr = NULL; + } } } extTransRec.tr_devrec = devptr; @@ -2737,8 +2754,27 @@ extTransPerimFunc(bp) ll->ll_attr = thisterm; } } - SDterm = TRUE; + + /* Check if number of terminals exceeds the number allowed in */ + /* this device record. If so, check if there is another device */ + /* record with a different number of terminals. */ + extTransRec.tr_devmatch |= (MATCH_TERM << thisterm); + if (thisterm >= devptr->exts_deviceSDCount) + { + devptr = extDevFindMatch(devptr, tinside); + + /* Should this be an error instead of a warning? */ + /* Traditionally more terminals than defined was allowed */ + /* but not necessarily handled correctly by ext2spice. */ + + if (devptr == deventry) + TxError("Warning: Device has more terminals than defined " + "for type!\n"); + else + extTransRec.tr_devrec = devptr; + } + SDterm = TRUE; break; } } From 1933c5d4a5a747b79eb20e10982dd03b4e7d2edc Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 14 Oct 2019 11:56:39 -0400 Subject: [PATCH 027/121] Corrected another problem where the device source/drain area and perimeter were not output because of recent code that broke the routine that assigns the resistance classes to devices. This is now fixed. Thanks to Dan Moore for bringing this to my attention, and debugging investigations. --- extract/ExtTech.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/extract/ExtTech.c b/extract/ExtTech.c index 314bed99..d2b3ebbf 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -298,12 +298,12 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr) TileType t; TileTypeBitMask *rmask, *tmask; int n, i = 0, j; - bool repeat; + bool repeat, found; ExtDevice *devptr; char *locdname; char **uniquenamelist = (char **)mallocMagic(DBNumTypes * sizeof(char *)); - + found = FALSE; for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) { for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next) @@ -320,12 +320,17 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr) } if (repeat == FALSE) { - if (i == idx) break; + if (i == idx) + { + found = TRUE; + break; + } uniquenamelist[i] = locdname; i++; } } } + if (found == TRUE) break; } if (t == DBNumTypes) return FALSE; if (devptr == NULL) return FALSE; From 58c4c8a32e8685262617ceb010bb5b184b3b6b6e Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 14 Oct 2019 13:49:41 -0400 Subject: [PATCH 028/121] Corrected problem in which using "ext2spice -d" (distributed junctions) causes magic to crash. --- ext2spice/ext2spice.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 46853437..a5bc4817 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -2714,7 +2714,9 @@ FILE *outf; if ((nodeClient *)nn->efnn_node->efnode_client == (ClientData)NULL) initNodeClientHier(nn->efnn_node); - ((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= DEV_CONNECT_MASK; + if (!esDistrJunct) + ((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= + DEV_CONNECT_MASK; return nn->efnn_node; } } @@ -2919,8 +2921,11 @@ spcdevOutNode(prefix, suffix, name, outf) nn = (EFNodeName *) HashGetValue(he); nname = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier); fprintf(outf, " %s", nname); + /* Mark node as visited */ - ((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= DEV_CONNECT_MASK; + if (!esDistrJunct) + ((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= DEV_CONNECT_MASK; + return (1 + strlen(nname)); } From 57a5ff60944704aa70dca67c0b69d23f662ad61a Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 14 Oct 2019 17:17:08 -0400 Subject: [PATCH 029/121] Corrected errors preventing extresist from working properly with hierarchical cells (namely a scaling issue with .sim file units). More can be done to make the extresist command more user friendly, but at least port connections as drivers appears to work. --- resis/Depend | 2 +- resis/ResConDCS.c | 4 ++-- resis/ResMain.c | 4 ++-- resis/ResMakeRes.c | 11 +++++++---- resis/ResReadSim.c | 8 ++++++-- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/resis/Depend b/resis/Depend index b73eacf7..f22d303f 100644 --- a/resis/Depend +++ b/resis/Depend @@ -15,7 +15,7 @@ ResMakeRes.o: ResMakeRes.c ../utils/magic.h ../utils/geometry.h \ ../database/database.h ../utils/malloc.h ../textio/textio.h \ ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ ../windows/windows.h ../dbwind/dbwind.h ../utils/tech.h \ - ../textio/txcommands.h ../resis/resis.h + ../textio/txcommands.h ../resis/resis.h ../cif/CIFint.h ResSimple.o: ResSimple.c ../utils/magic.h ../utils/geometry.h \ ../utils/geofast.h ../tiles/tile.h ../utils/hash.h ../utils/heap.h \ ../database/database.h ../utils/malloc.h ../textio/textio.h \ diff --git a/resis/ResConDCS.c b/resis/ResConDCS.c index 69adc06a..da5cb7fe 100644 --- a/resis/ResConDCS.c +++ b/resis/ResConDCS.c @@ -450,8 +450,8 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) for (tran = TT_TECHDEPBASE; tran < TT_MAXTYPES; tran++) { devptr = ExtCurStyle->exts_device[tran]; - tran_name = devptr->exts_deviceName; - if ((tran_name != NULL) && (strcmp(tran_name, "None"))) + if ((devptr != NULL) && ((tran_name = devptr->exts_deviceName) != NULL) + && (strcmp(tran_name, "None"))) { TTMaskSetMask(&DiffTypeBitMask, &(devptr->exts_deviceSDTypes[0])); diff --git a/resis/ResMain.c b/resis/ResMain.c index 33657767..767c599e 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -72,8 +72,8 @@ ResInitializeConn() for (tran = TT_TECHDEPBASE; tran < TT_MAXTYPES; tran++) { devptr = ExtCurStyle->exts_device[tran]; - tran_name = devptr->exts_deviceName; - if ((tran_name != NULL) && (strcmp(tran_name, "None"))) + if ((devptr != NULL) && ((tran_name = devptr->exts_deviceName) != NULL) + && (strcmp(tran_name, "None"))) { for (diff = TT_TECHDEPBASE; diff < TT_MAXTYPES; diff++) { diff --git a/resis/ResMakeRes.c b/resis/ResMakeRes.c index 1ff30a22..5d874d1d 100644 --- a/resis/ResMakeRes.c +++ b/resis/ResMakeRes.c @@ -24,6 +24,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "utils/tech.h" #include "textio/txcommands.h" #include "resis/resis.h" +#include "cif/CIFint.h" /* Forward declarations */ bool ResCalcNearTransistor(); @@ -783,13 +784,14 @@ ResDoContacts(contact, nodes, resList) resNode *resptr; cElement *ccell; int tilenum, squaresx, squaresy, viawidth; - int minside, spacing, border; + int minside, spacing, border, cscale; float squaresf; resResistor *resistor; resElement *element; static int too_small = 1; minside = CIFGetContactSize(contact->cp_type, &viawidth, &spacing, &border); + cscale = CIFCurStyle->cs_scaleFactor; if ((ExtCurStyle->exts_viaResist[contact->cp_type] == 0) || (viawidth == 0)) { @@ -818,7 +820,8 @@ ResDoContacts(contact, nodes, resList) } else { - if ((contact->cp_width < minside) || (contact->cp_height < minside)) + if (((contact->cp_width * cscale) < minside) || + ((contact->cp_height * cscale) < minside)) { if (too_small) { @@ -832,13 +835,13 @@ ResDoContacts(contact, nodes, resList) else { viawidth += spacing; - squaresf = (float)(contact->cp_width - minside) / (float)viawidth; + squaresf = (float)((contact->cp_width * cscale) - minside) / (float)viawidth; squaresf *= ExtCurStyle->exts_unitsPerLambda; squaresf /= (float)viawidth; squaresx = (int)squaresf; squaresx++; - squaresf = (float)(contact->cp_height - minside) / (float)viawidth; + squaresf = (float)((contact->cp_height * cscale) - minside) / (float)viawidth; squaresf *= ExtCurStyle->exts_unitsPerLambda; squaresf /= (float)viawidth; squaresy = (int)squaresf; diff --git a/resis/ResReadSim.c b/resis/ResReadSim.c index 6cb38633..cc47fb4b 100644 --- a/resis/ResReadSim.c +++ b/resis/ResReadSim.c @@ -146,8 +146,12 @@ ResReadSim(simfile,fetproc,capproc,resproc,attrproc,mergeproc) case '|': if (strcmp(line[NODEUNITS],"units:") == 0) { - lambda = (float)atof(line[NODELAMBDA]); - if (lambda == 0.0) lambda = 1.0; + lambda = (float)atof(line[NODELAMBDA]); + if (lambda == 0.0) lambda = 1.0; + /* NOTE: units is derived from EFScale */ + /* which needs a factor of 100 conversion */ + /* to database units. */ + lambda *= 100.0; } result=0; break; From e9f3dcadefb2f938b8f45ccd3ef362fb2546afb1 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 14 Oct 2019 21:46:07 -0400 Subject: [PATCH 030/121] Added substitution for commas in SPICE output, because commas in instance names and node names are basically fatal to running ngspice. --- ext2spice/ext2spice.c | 35 +++++++++++++++++++++++++++-------- extflat/EFargs.c | 4 +++- extflat/EFvisit.c | 14 ++++++++++---- extflat/extflat.h | 5 +++-- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index a5bc4817..43ebabbe 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -140,9 +140,16 @@ esFormatSubs(outf, suf) if ((EFTrimFlags & EF_TRIMGLOB ) && suf[l] == '!' || (EFTrimFlags & EF_TRIMLOCAL) && suf[l] == '#') suf[l] = '\0' ; - if (EFTrimFlags & EF_CONVERTCOMMAS) + if (EFTrimFlags & EF_CONVERTCOMMA) while ((specchar = strchr(suf, ',')) != NULL) - *specchar = ';'; + *specchar = '|'; + if (EFTrimFlags & EF_CONVERTBRACKETS) + { + while ((specchar = strchr(suf, '[')) != NULL) + *specchar = '_'; + while ((specchar = strchr(suf, ']')) != NULL) + *specchar = '_'; + } if (EFTrimFlags & EF_CONVERTEQUAL) while ((specchar = strchr(suf, '=')) != NULL) *specchar = ':'; @@ -607,7 +614,7 @@ CmdExtToSpice(w, cmd) case EXTTOSPC_DEFAULT: LocCapThreshold = 2; LocResistThreshold = INFINITE_THRESHOLD; - EFTrimFlags = EF_CONVERTCOMMAS | EF_CONVERTEQUAL; + EFTrimFlags = EF_CONVERTCOMMA | EF_CONVERTEQUAL; EFScale = 0.0; if (EFArgTech) { @@ -821,7 +828,7 @@ runexttospice: // This forces options TRIMGLOB and CONVERTEQUAL, not sure that's such a // good idea. . . - EFTrimFlags |= EF_TRIMGLOB | EF_CONVERTEQUAL; + EFTrimFlags |= EF_TRIMGLOB | EF_CONVERTEQUAL | EF_CONVERTCOMMA; if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS; if (esFormat == HSPICE) EFTrimFlags |= EF_TRIMLOCAL; @@ -1379,7 +1386,7 @@ subcktVisit(use, hierName, is_top) else { int savflags = EFTrimFlags; - EFTrimFlags = 0; // Do no substitutions on subcircuit names + EFTrimFlags = EF_CONVERTCOMMA; // Only substitute commas on subcircuit names /* Use full hierarchical decomposition for name */ /* (not just use->use_id. hierName already has use->use_id at end) */ @@ -3220,7 +3227,7 @@ EFHNSprintf(str, hierName) char *str; HierName *hierName; { - bool trimGlob, trimLocal, convertComma, convertEqual; + bool trimGlob, trimLocal, convertComma, convertEqual, convertBrackets; char *s, *cp, c; char *efHNSprintfPrefix(HierName *, char *); @@ -3231,8 +3238,9 @@ EFHNSprintf(str, hierName) cp = hierName->hn_name; trimGlob = (EFTrimFlags & EF_TRIMGLOB); trimLocal = (EFTrimFlags & EF_TRIMLOCAL); - convertComma = (EFTrimFlags & EF_CONVERTCOMMAS); + convertComma = (EFTrimFlags & EF_CONVERTCOMMA); convertEqual = (EFTrimFlags & EF_CONVERTEQUAL); + convertBrackets = (EFTrimFlags & EF_CONVERTBRACKETS); while (c = *cp++) { switch (c) @@ -3240,7 +3248,9 @@ EFHNSprintf(str, hierName) case '!': if (!trimGlob) *str++ = c; break; case '.': *str++ = (esFormat == HSPICE)?'@':'.'; break; case '=': if (convertEqual) *str++ = ':'; break; - case ',': if (convertComma) *str++ = ';'; break; + case ',': if (convertComma) *str++ = '|'; break; + case '[': *str++ = (convertBrackets) ? '_' : '['; break; + case ']': *str++ = (convertBrackets) ? '_' : ']'; break; case '#': if (trimLocal) break; // else fall through default: *str++ = c; break; } @@ -3257,6 +3267,8 @@ char *efHNSprintfPrefix(hierName, str) { char *cp, c; bool convertEqual = (EFTrimFlags & EF_CONVERTEQUAL) ? TRUE : FALSE; + bool convertComma = (EFTrimFlags & EF_CONVERTCOMMA) ? TRUE : FALSE; + bool convertBrackets = (EFTrimFlags & EF_CONVERTBRACKETS) ? TRUE : FALSE; if (hierName->hn_parent) str = efHNSprintfPrefix(hierName->hn_parent, str); @@ -3265,6 +3277,13 @@ char *efHNSprintfPrefix(hierName, str) while (1) { if (convertEqual && (*cp == '=')) *str = ':'; + else if (convertBrackets && ((*cp == '[') || (*cp == ']'))) + *str = '_'; + else if (*cp == ',') + { + if (convertComma) *str = '|'; + else str--; + } else *str = *cp; if (!(*str)) break; diff --git a/extflat/EFargs.c b/extflat/EFargs.c index 40b57278..dd812dac 100644 --- a/extflat/EFargs.c +++ b/extflat/EFargs.c @@ -209,8 +209,10 @@ EFArgs(argc, argv, err_result, argsProc, cdata) goto usage; if (strchr(cp, '!')) EFTrimFlags |= EF_TRIMGLOB; if (strchr(cp, '#')) EFTrimFlags |= EF_TRIMLOCAL; - if (strchr(cp, ',')) EFTrimFlags |= EF_CONVERTCOMMAS; + if (strchr(cp, ',')) EFTrimFlags |= EF_CONVERTCOMMA; if (strchr(cp, '=')) EFTrimFlags |= EF_CONVERTEQUAL; + if (strchr(cp, '[')) EFTrimFlags |= EF_CONVERTBRACKETS; + if (strchr(cp, ']')) EFTrimFlags |= EF_CONVERTBRACKETS; break; case 'C': EFCapThreshold = (EFCapValue)INFINITE_THRESHOLD_F; diff --git a/extflat/EFvisit.c b/extflat/EFvisit.c index aadb98ff..8d802edd 100644 --- a/extflat/EFvisit.c +++ b/extflat/EFvisit.c @@ -859,7 +859,7 @@ EFHNOut(hierName, outf) HierName *hierName; FILE *outf; { - bool trimGlob, trimLocal, trimComma; + bool trimGlob, trimLocal, convComma, convBrackets; char *cp, c; if (hierName->hn_parent) efHNOutPrefix(hierName->hn_parent, outf); @@ -868,13 +868,19 @@ EFHNOut(hierName, outf) cp = hierName->hn_name; trimGlob = (EFTrimFlags & EF_TRIMGLOB); trimLocal = (EFTrimFlags & EF_TRIMLOCAL); - trimComma = (EFTrimFlags & EF_CONVERTCOMMAS); + convComma = (EFTrimFlags & EF_CONVERTCOMMA); + convBrackets = (EFTrimFlags & EF_CONVERTBRACKETS); while (c = *cp++) { if (*cp) { - if (trimComma && (c == ',')) - putc(';', outf); + if (c == ',') + { + if (convComma) + putc('|', outf); + } + else if (convBrackets && ((c == '[') || (c == ']'))) + putc('_', outf); else putc(c, outf); } diff --git a/extflat/extflat.h b/extflat/extflat.h index 8d8f1dba..f249e37c 100644 --- a/extflat/extflat.h +++ b/extflat/extflat.h @@ -40,8 +40,9 @@ typedef unsigned char U_char; /* Flags to control output of node names. Stored in EFTrimFlags */ #define EF_TRIMGLOB 0x01 /* Delete trailing '!' from names */ #define EF_TRIMLOCAL 0x02 /* Delete trailing '#' from names */ -#define EF_CONVERTCOMMAS 0x04 /* Change ',' to ';' in names */ -#define EF_CONVERTEQUAL 0x08 /* Change '=' to ':' in names */ +#define EF_CONVERTCOMMA 0x04 /* Change ',' to '|' in names, else remove */ +#define EF_CONVERTEQUAL 0x08 /* Change '=' to ':' in names, else remove */ +#define EF_CONVERTBRACKETS 0x10 /* Change '[' and ']' to '_' in names */ /* * capacitance type now set to float From 097f4fb28c74508277afc04bfba1f45a9a887976 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 15 Oct 2019 09:16:07 -0400 Subject: [PATCH 031/121] Corrected node reading from extresist because the ".nodes" file does not have any scaling in the dimensions and so values should not be divided by the factor lambda from the .sim file "units" line. --- resis/ResReadSim.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/resis/ResReadSim.c b/resis/ResReadSim.c index cc47fb4b..19ae304d 100644 --- a/resis/ResReadSim.c +++ b/resis/ResReadSim.c @@ -243,13 +243,17 @@ ResReadNode(nodefile) entry = HashFind(&ResNodeTable,line[NODENODENAME]); node = ResInitializeNode(entry); - node->location.p_x = (int)((float)atof(line[NODENODEX])/lambda); - node->location.p_y = (int)((float)atof(line[NODENODEY])/lambda); + /* NOTE: Fixed 10/15/2019. No scalefactor is passed to EFNodeVisit() + * so there is no scaling by lambda. Values are in centimicrons always, + * and factor of 100 is required to get database units. + */ + node->location.p_x = (int)((float)atof(line[NODENODEX]) / 100.0); + node->location.p_y = (int)((float)atof(line[NODENODEY]) / 100.0); #ifdef ARIEL - node->rs_bbox.r_xbot = (int)((float)atof(line[NODE_BBOX_LL_X])/lambda); - node->rs_bbox.r_ybot = (int)((float)atof(line[NODE_BBOX_LL_Y])/lambda); - node->rs_bbox.r_xtop = (int)((float)atof(line[NODE_BBOX_UR_X])/lambda); - node->rs_bbox.r_ytop = (int)((float)atof(line[NODE_BBOX_UR_Y])/lambda); + node->rs_bbox.r_xbot = (int)((float)atof(line[NODE_BBOX_LL_X]) / 100.0); + node->rs_bbox.r_ybot = (int)((float)atof(line[NODE_BBOX_LL_Y]) / 100.0); + node->rs_bbox.r_xtop = (int)((float)atof(line[NODE_BBOX_UR_X]) / 100.0); + node->rs_bbox.r_ytop = (int)((float)atof(line[NODE_BBOX_UR_Y]) / 100.0); #endif if (cp = strchr(line[NODETYPE], ';')) *cp = '\0'; node->type = DBTechNameType(line[NODETYPE]); From e969097f847e7ae982c5a0f813a8805ec85ecb71 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 15 Oct 2019 09:51:25 -0400 Subject: [PATCH 032/121] Another correction to fix the tile type for port drivers in extresist, as the tile type was being set to a transistor gate type and not the type of the port. --- resis/ResRex.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/resis/ResRex.c b/resis/ResRex.c index a1c98d9e..b31299e8 100644 --- a/resis/ResRex.c +++ b/resis/ResRex.c @@ -988,6 +988,12 @@ ResCheckSimNodes(celldef, resisdata) gparams.rg_tranloc = &node->drivepoint; gparams.rg_status |= DRIVEONLY; } + if (node->status & PORTNODE) + { + /* The node is a port, not a transistor, so make */ + /* sure rg_ttype is set accordingly. */ + gparams.rg_ttype = node->rs_ttype; + } } if (gparams.rg_tranloc == NULL && node->status & FORCE) { From 3d7a56ac3a02042a18b0120f322a21658214659d Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 15 Oct 2019 16:24:49 -0400 Subject: [PATCH 033/121] Finally got around to undoing an annoyance caused by the wholesale reduction of memory and startup time, which was to maintain only one CIF style in memory. The new method is just to read in and keep the DRC CIF style separately from the output CIF style. Because the CIF sections of the techfile are read before the DRC sections, and the CIF DRC style is declared in the DRC section, the CIF DRC style is read in on the fly during the first DRC checking. --- cif/CIFgen.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++----- cif/CIFint.h | 1 + cif/CIFtech.c | 10 +++++--- drc/DRCcif.c | 40 ++++++++++++++++++++++++----- 4 files changed, 106 insertions(+), 15 deletions(-) diff --git a/cif/CIFgen.c b/cif/CIFgen.c index d063a087..7233d12f 100644 --- a/cif/CIFgen.c +++ b/cif/CIFgen.c @@ -842,6 +842,35 @@ endbloat: return 0; } +/* + *------------------------------------------------------- + * + * cifFoundFun -- + * + * 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, treturn) + Tile *tile; + Tile **treturn; +{ + *treturn = tile; + return 1; +} + +/* Data structure for bloat-all function */ +typedef struct _bloatStruct { + CIFOp *op; + CellDef *def; +} BloatStruct; + /* * ---------------------------------------------------------------------------- * @@ -873,18 +902,26 @@ endbloat: } int -cifBloatAllFunc(tile, op) +cifBloatAllFunc(tile, bls) Tile *tile; /* The tile to be processed. */ - CIFOp *op; /* Describes the operation to be performed */ + BloatStruct *bls; { Rect area; TileTypeBitMask connect; Tile *t, *tp; TileType type; - BloatData *bloats = (BloatData *)op->co_client; + BloatData *bloats; int i; + PlaneMask pmask; + int pNum; + CIFOp *op; + CellDef *def; static Stack *BloatStack = (Stack *)NULL; + op = bls->op; + def = bls->def; + bloats = (BloatData *)op->co_client; + /* Create a mask of all connecting types (these must be in a single * plane), then call a search function to find all connecting material * of these types. @@ -900,7 +937,24 @@ cifBloatAllFunc(tile, op) if (BloatStack == (Stack *)NULL) BloatStack = StackNew(64); - PUSHTILE(tile, BloatStack); + /* If the type of the tile to be processed is not in the same plane */ + /* as the bloat type(s), then find any tile under the tile to be */ + /* processed that belongs to the connect mask, and use that as the */ + /* starting tile. */ + + t = tile; + type = TiGetType(tile); + pNum = DBPlane(type); + pmask = CoincidentPlanes(&connect, pNum); + if (pmask == 0) + { + TiToRect(tile, &area); + if (DBSrPaintArea((Tile *)NULL, def->cd_planes[bloats->bl_plane], &area, + &connect, cifFoundFunc, (ClientData)(&t)) == 0) + return 0; /* Nothing found here */ + } + + PUSHTILE(t, BloatStack); while (!StackEmpty(BloatStack)) { t = (Tile *) STACKPOP(BloatStack); @@ -2688,6 +2742,7 @@ cifSrTiles(cifOp, area, cellDef, temps, func, cdArg) { TileTypeBitMask maskBits; TileType t; + Tile *tp; int i; BloatData *bloats; @@ -2699,7 +2754,7 @@ cifSrTiles(cifOp, area, cellDef, temps, func, cdArg) cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1; - /* Bloat operations have to be in a single plane */ + /* Bloat operations (except bloat-all) have to be in a single plane */ switch (cifOp->co_opcode) { case CIFOP_BLOAT: @@ -2783,6 +2838,7 @@ CIFGenLayer(op, area, cellDef, temps, clientdata) SearchContext scx; TileType ttype; char *netname; + BloatStruct bls; int (*cifGrowFuncPtr)() = (CIFCurStyle->cs_flags & CWF_GROW_EUCLIDEAN) ? cifGrowEuclideanFunc : cifGrowFunc; @@ -2971,8 +3027,10 @@ CIFGenLayer(op, area, cellDef, temps, clientdata) case CIFOP_BLOATALL: cifPlane = curPlane; + bls.op = op; + bls.def = cellDef; cifSrTiles(op, area, cellDef, temps, - cifBloatAllFunc, (ClientData) op); + cifBloatAllFunc, (ClientData)&bls); break; case CIFOP_SQUARES: diff --git a/cif/CIFint.h b/cif/CIFint.h index 6d3ef7ba..c9280e12 100644 --- a/cif/CIFint.h +++ b/cif/CIFint.h @@ -310,6 +310,7 @@ extern void CIFLoadStyle(); extern Plane *CIFPlanes[]; /* Normal place to store CIF. */ extern CIFKeep *CIFStyleList; /* List of all CIF styles. */ extern CIFStyle *CIFCurStyle; /* Current style being used. */ +extern CIFStyle *CIFDRCStyle; /* CIF style for DRC checking (optional) */ extern CellUse *CIFComponentUse; /* Flatten stuff in here if needed. */ extern CellDef *CIFComponentDef; /* Corresponds to CIFComponentUse. */ extern CellUse *CIFDummyUse; /* Used to dummy up a CellUse for a diff --git a/cif/CIFtech.c b/cif/CIFtech.c index 54bb05c6..25a920e3 100644 --- a/cif/CIFtech.c +++ b/cif/CIFtech.c @@ -1081,13 +1081,17 @@ CIFTechLine(sectionName, argc, argv) if (argc != 3) goto wrongNumArgs; cifParseLayers(argv[1], CIFCurStyle, &newOp->co_paintMask, (TileTypeBitMask *)NULL, FALSE); - bloatLayers = newOp->co_paintMask; bloats = (BloatData *)mallocMagic(sizeof(BloatData)); for (i = 0; i < TT_MAXTYPES; i++) bloats->bl_distance[i] = 0; newOp->co_client = (ClientData)bloats; - cifParseLayers(argv[2], CIFCurStyle, &mask, &tempMask, TRUE); + + /* 10/15/2019: Lifting restriction that the types that */ + /* trigger the bloating must be in the same plane as the */ + /* types that are bloated into. */ + + TTMaskZero(&bloatLayers); TTMaskSetMask(&bloatLayers, &mask); if (!TTMaskEqual(&tempMask, &DBZeroTypeBits)) TechError("Can't use templayers in bloat statement.\n"); @@ -1945,7 +1949,7 @@ CIFLoadStyle(stylename) { SectionID invcif; - if (CIFCurStyle->cs_name == stylename) return; + if (CIFCurStyle && (CIFCurStyle->cs_name == stylename)) return; cifTechNewStyle(); CIFCurStyle->cs_name = stylename; diff --git a/drc/DRCcif.c b/drc/DRCcif.c index b4344620..fa4f00c7 100644 --- a/drc/DRCcif.c +++ b/drc/DRCcif.c @@ -67,9 +67,10 @@ extern bool DRCForceReload; TileTypeBitMask drcCifGenLayers; DRCCookie *drcCifRules[MAXCIFLAYERS][2]; -DRCCookie *drcCifCur=NULL; +DRCCookie *drcCifCur = NULL; int drcCifValid = FALSE; -int beenWarned; +bool beenWarned = FALSE; +char *drcNeedStyle = NULL; #define DRC_CIF_SPACE 0 #define DRC_CIF_SOLID 1 @@ -112,14 +113,12 @@ drcCifSetStyle(argc, argv) { if (!strcmp(new->cs_name, argv[1])) { + drcNeedStyle = new->cs_name; DRCForceReload = TRUE; if (!strcmp(new->cs_name, CIFCurStyle->cs_name)) drcCifStyle = CIFCurStyle; else { - TechError("DRC cif extensions are not enabled.\n\t" - "Use \"cif ostyle %s\" to enable them.\n", - new->cs_name); drcCifStyle = NULL; beenWarned = TRUE; /* post no more error messages */ } @@ -501,9 +500,35 @@ drcCifCheck(arg) int scale; int i,j; int oldTiles; + CIFStyle *CIFSaveStyle = NULL; + if (CIFCurStyle != drcCifStyle) + { + if (drcNeedStyle == NULL) { + TxError("Error: No DRC CIF style declared!\n"); + 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) return; - else if (CIFCurStyle != drcCifStyle) return; scale = drcCifStyle->cs_scaleFactor; cifrect = *checkRect; @@ -534,6 +559,9 @@ drcCifCheck(arg) } arg->dCD_rect = checkRect; DRCstatCifTiles += DRCstatTiles - oldTiles; + + /* Put it back the way you found it */ + if (CIFSaveStyle != NULL) CIFCurStyle = CIFSaveStyle; } /* From 8b0a9275a88c0906641e86b36062efac6d257463 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 15 Oct 2019 20:40:59 -0400 Subject: [PATCH 034/121] Fixed the value of property FIXED_BBOX when saving a file; it needs to be scaled down by "reducer" like all other values in the cell. Suggests a need to have property types other than string, so that a property type "rect" or "box" can be declared that is saved as a Rect and always scales without special hack handling of the specific string FIXED_BBOX. . . --- database/DBio.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/database/DBio.c b/database/DBio.c index 6389eb23..9afe30f3 100644 --- a/database/DBio.c +++ b/database/DBio.c @@ -2350,6 +2350,8 @@ DBCellWriteFile(cellDef, f) int reducer; char *estring; char lstring[256]; + char *propvalue; + bool propfound; #define FPRINTF(f,s)\ {\ @@ -2542,12 +2544,43 @@ DBCellWriteFile(cellDef, f) } /* And any properties */ + + /* NOTE: FIXED_BBOX is treated specially; values are database */ + /* values and should be divided by reducer. Easiest to do it */ + /* here and revert values after. */ + + propvalue = (char *)DBPropGet(cellDef, "FIXED_BBOX", &propfound); + if (propfound) + { + char *proporig, *propscaled; + Rect scalebox, bbox; + + proporig = StrDup((char **)NULL, propvalue); + propscaled = mallocMagic(strlen(propvalue) + 5); + if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot, + &bbox.r_xtop, &bbox.r_ytop) == 4) + { + scalebox.r_xbot = bbox.r_xbot / reducer; + scalebox.r_xtop = bbox.r_xtop / reducer; + scalebox.r_ybot = bbox.r_ybot / reducer; + scalebox.r_ytop = bbox.r_ytop / reducer; + sprintf(propscaled, "%d %d %d %d", + bbox.r_xbot / reducer, bbox.r_ybot / reducer, + bbox.r_xtop / reducer, bbox.r_ytop / reducer); + + DBPropPut(cellDef, "FIXED_BBOX", propscaled); + propvalue = proporig; + } + } + if (cellDef->cd_props != (ClientData)NULL) { FPRINTF(f, "<< properties >>\n"); DBPropEnum(cellDef, dbWritePropFunc, (ClientData)f); } + if (propfound) DBPropPut(cellDef, "FIXED_BBOX", propvalue); + FPRINTF(f, "<< end >>\n"); if (fflush(f) == EOF || ferror(f)) From 46f3f448495cf02da20ffcf0663eb409e794dada Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 16 Oct 2019 09:17:58 -0400 Subject: [PATCH 035/121] Corrected EFArgs() so that "ext2spice run -help" works as advertised; e.g., "-h" or "-help" is now recognized as a valid option instead of printing a usage message by way of throwing an error. --- ext2spice/ext2spice.c | 25 +++++++++++++++---------- extflat/EFargs.c | 20 +++++++++++++++----- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 43ebabbe..8885bdce 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -1147,6 +1147,17 @@ spcmainArgs(pargc, pargv) char **argv = *pargv, *cp; int argc = *pargc; + char usage_text[] = "Usage: ext2spice " + "[-B] [-o spicefile] [-M|-m] [-y cap_digits] " + "[-J flat|hier]\n" + "[-f spice2|spice3|hspice|ngspice] [-M] [-m] " +#ifdef MAGIC_WRAPPER + "[file]\n"; +#else + "[-j device:sdRclass[/subRclass]/defaultSubstrate]\n" + "file\n\n or else see options to extcheck(1)\n"; +#endif + switch (argv[0][1]) { case 'd': @@ -1243,6 +1254,9 @@ spcmainArgs(pargc, pargv) break; } #endif /* MAGIC_WRAPPER */ + case 'h': /* -h or -help, as suggested by "ext2spice help" */ + TxPrintf(usage_text); + break; default: TxError("Unrecognized flag: %s\n", argv[0]); goto usage; @@ -1253,16 +1267,7 @@ spcmainArgs(pargc, pargv) return 0; usage: - TxError("Usage: ext2spice [-B] [-o spicefile] [-M|-m] [-y cap_digits] " - "[-J flat|hier]\n" - "[-f spice2|spice3|hspice|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 - ); + TxError(usage_text); #ifdef MAGIC_WRAPPER return 1; diff --git a/extflat/EFargs.c b/extflat/EFargs.c index dd812dac..d94ebc16 100644 --- a/extflat/EFargs.c +++ b/extflat/EFargs.c @@ -160,6 +160,15 @@ EFArgs(argc, argv, err_result, argsProc, cdata) HierName *hierName; FILE *f; + char usage_text[] = + "Standard arguments: [-R] [-C] [-r rthresh] [-c cthresh] [-v]\n" + "[-p searchpath] [-s sym=value] [-S symfile] [-t trimchars]\n" +#ifdef MAGIC_WRAPPER + "[rootfile]\n"; +#else + "[-T techname] rootfile\n"; +#endif + if (err_result != NULL) *err_result = FALSE; /* Hash table of nodes we're going to watch if -N given */ @@ -270,6 +279,11 @@ EFArgs(argc, argv, err_result, argsProc, cdata) case 'z': efHNStats = TRUE; break; + case 'h': + if (argsProc != NULL) (*argsProc)(&argc, &argv, cdata); + TxPrintf(usage_text); + if (err_result != NULL) *err_result = TRUE; + return NULL; /*** Try a caller-supplied argument processing function ***/ default: @@ -312,19 +326,15 @@ EFArgs(argc, argv, err_result, argsProc, cdata) realIn[cp - inname] = '\0'; inname = realIn; } - return inname; usage: - TxError("Standard arguments: [-R] [-C] [-r rthresh] [-c cthresh] [-v]\n" - "[-p searchpath] [-s sym=value] [-S symfile] [-t trimchars]\n" + TxError(usage_text); #ifdef MAGIC_WRAPPER - "[rootfile]\n"); if (err_result != NULL) *err_result = TRUE; return NULL; #else - "[-T techname] rootfile\n"); exit (1); /*NOTREACHED*/ #endif From 0386752abb77cc565271c9bb4db7f97bfe5118d7 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 16 Oct 2019 10:14:44 -0400 Subject: [PATCH 036/121] Removed an error message from DRCcif.c; otherwise it raises an error whenever there are no DRC-CIF rules in the techfile. The same error will be raised anyway when reading the techfile if DRC-CIF rules are declared without a style being specified. --- drc/DRCcif.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drc/DRCcif.c b/drc/DRCcif.c index fa4f00c7..9031ea4c 100644 --- a/drc/DRCcif.c +++ b/drc/DRCcif.c @@ -504,10 +504,7 @@ drcCifCheck(arg) if (CIFCurStyle != drcCifStyle) { - if (drcNeedStyle == NULL) { - TxError("Error: No DRC CIF style declared!\n"); - return; - } + if (drcNeedStyle == NULL) return; CIFSaveStyle = CIFCurStyle; From 745afa900d41566352491d91f601921b1e41817c Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 16 Oct 2019 11:38:31 -0400 Subject: [PATCH 037/121] Corrected missing NULL initializer for device substrate name, which can result in a segfault when reloading a techfile. --- extract/ExtTech.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extract/ExtTech.c b/extract/ExtTech.c index d2b3ebbf..37259c54 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -2226,6 +2226,8 @@ ExtTechLine(sectionName, argc, argv) if (subsName != NULL) devptr->exts_deviceSubstrateName = StrDup((char **) NULL, subsName); + else + devptr->exts_deviceSubstrateName = (char *)NULL; devptr->exts_deviceSubstrateTypes = subsTypes; devptr->exts_deviceIdentifierTypes = idTypes; devptr->exts_deviceParams = (ParamList *) NULL; From b41c86980b0b37c756218f7c6832e8205107a076 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 16 Oct 2019 20:53:03 -0400 Subject: [PATCH 038/121] Corrected a mistake with the extension of the bloat-all CIF operator that broke the operator for the usual case of all types in the same plane. --- cif/CIFgen.c | 2 +- dbwind/DBWcommands.c | 5 +- extflat/Depend | 5 + extflat/EFantenna.c | 297 +++++++++++++++++++++++++++++++++++++++++++ extflat/Makefile | 2 +- extract/ExtTech.c | 22 +++- extract/extractInt.h | 3 + 7 files changed, 332 insertions(+), 4 deletions(-) create mode 100644 extflat/EFantenna.c diff --git a/cif/CIFgen.c b/cif/CIFgen.c index 7233d12f..ac85961a 100644 --- a/cif/CIFgen.c +++ b/cif/CIFgen.c @@ -945,7 +945,7 @@ cifBloatAllFunc(tile, bls) t = tile; type = TiGetType(tile); pNum = DBPlane(type); - pmask = CoincidentPlanes(&connect, pNum); + pmask = CoincidentPlanes(&connect, PlaneNumToMaskBit(pNum)); if (pmask == 0) { TiToRect(tile, &area); diff --git a/dbwind/DBWcommands.c b/dbwind/DBWcommands.c index 778e3735..7559b1f6 100644 --- a/dbwind/DBWcommands.c +++ b/dbwind/DBWcommands.c @@ -38,7 +38,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ * Standard DBWind command set */ -extern void CmdAddPath(), CmdArray(); +extern void CmdAddPath(), CmdAntennaCheck(), CmdArray(); extern void CmdBox(), CmdCellname(), CmdClockwise(); extern void CmdContact(), CmdCopy(), CmdCorner(); extern void CmdCrash(), CmdCrosshair(); @@ -222,6 +222,9 @@ DBWInitCommands() WindAddCommand(DBWclientID, "addpath [path] append to current search path", CmdAddPath, FALSE); + WindAddCommand(DBWclientID, + "antennacheck [path] check for antenna violations", + CmdAntennaCheck, FALSE); WindAddCommand(DBWclientID, "array xsize ysize OR\n" "array xlo xhi ylo yhi\n" diff --git a/extflat/Depend b/extflat/Depend index 86844587..a48cf3b8 100644 --- a/extflat/Depend +++ b/extflat/Depend @@ -28,3 +28,8 @@ EFsym.o: EFsym.c ../utils/magic.h ../utils/geometry.h ../utils/geofast.h \ EFvisit.o: EFvisit.c ../utils/magic.h ../utils/geometry.h \ ../utils/geofast.h ../utils/hash.h ../utils/malloc.h ../utils/utils.h \ ../extflat/extflat.h ../extflat/EFint.h ../extract/extract.h +EFantenna.o: EFantenna.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/geometry.h ../utils/hash.h ../utils/utils.h ../tiles/tile.h \ + ../database/database.h ../windows/windows.h ../textio/textio.h \ + ../dbwind/dbwind.h ../textio/txcommands.h ../extflat/extflat.h \ + ../extract/extract.h ../utils/malloc.h diff --git a/extflat/EFantenna.c b/extflat/EFantenna.c new file mode 100644 index 00000000..0048b3f9 --- /dev/null +++ b/extflat/EFantenna.c @@ -0,0 +1,297 @@ +/* + * 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 +#include /* for atof() */ +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/utils.h" +#include "tiles/tile.h" +#ifdef MAGIC_WRAPPER +#include "database/database.h" +#include "windows/windows.h" +#include "textio/textio.h" +#include "dbwind/dbwind.h" /* for DBWclientID */ +#include "textio/txcommands.h" +#endif +#include "extflat/extflat.h" +#include "extract/extract.h" /* for extDevTable */ +#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<visitMask = (long)0; } + +#define beenVisited(client, rclass) \ + ( (client)->visitMask & (1<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; \ +} + + +/* + * ---------------------------------------------------------------------------- + * + * Main Tcl callback for command "magic::antennacheck" + * + * ---------------------------------------------------------------------------- + */ + +#define ANTENNACHECK_RUN 0 +#define ANTENNACHECK_HELP 1 + +void +CmdAntennaCheck(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int i,flatFlags; + char *inName; + FILE *f; + + 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; + + static char *cmdAntennaCheckOption[] = { + "[run] [options] run antennacheck on current cell\n" + " use \"run -help\" to get standard options", + "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_HELP: +usage: + for (msg = &(cmdAntennaCheckOption[0]); *msg != NULL; msg++) + { + TxPrintf(" %s\n", *msg); + } + break; + } + return; + +runantennacheck: + + 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; + } + + /* + * Initializations specific to this program. + */ + + /* Read the hierarchical description of the input circuit */ + if (EFReadFile(inName, FALSE, FALSE, FALSE) == FALSE) + { + EFDone(); + return /* TCL_ERROR */; + } + + /* Convert the hierarchical description to a flat one */ + flatFlags = EF_FLATNODES; + EFFlatBuild(inName, flatFlags); + + EFVisitDevs(antennacheckVisit, (ClientData)NULL); + EFFlatDone(); + EFDone(); + + TxPrintf("antennacheck finished.\n"); +} + + +/* + * ---------------------------------------------------------------------------- + * + * 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; +} + + + +/* + * ---------------------------------------------------------------------------- + * + * 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) + Dev *dev; /* Device being output */ + HierName *hierName; /* Hierarchical path down to this device */ + float scale; /* Scale transform for output */ + Transform *trans; /* Coordinate transform */ +{ + DevTerm *gate, *source, *drain; + int l, w; + Rect r; + + switch(dev->dev_class) + { + case DEV_FET: + case DEV_MOSFET: + GeoTransRect(trans, &dev->dev_rect, &r); + + /* Procedure: + * + * 1. If device is marked visited, return. + * 2. Mark device visited + * 3. Mark all connected devices visited + * 4. For each plane from metal1 up (determined by planeorder): + * a. Run SimTreeCopyConnect() + * b. Accumulate gate area of connected devices + * c. Accumulate metal area of connected devices + * d. Check against antenna ratio + * e. Generate feedback if in violation of antenna rule + * + * NOTE: SimTreeCopyConnect() is used cumulatively, so that + * additional searching only needs to be done for the additional + * layer being searched. This is the reason for using + * SimTreeCopyConnect() instead of DBTreeCopyConnect(). + */ + + /* To be completed */ + } + return 0; +} + diff --git a/extflat/Makefile b/extflat/Makefile index 4ec0e281..2794bb7e 100644 --- a/extflat/Makefile +++ b/extflat/Makefile @@ -5,7 +5,7 @@ MODULE = extflat MAGICDIR = .. SRCS = EFargs.c EFbuild.c EFdef.c EFerr.c EFflat.c EFhier.c EFname.c \ - EFread.c EFsym.c EFvisit.c + EFread.c EFsym.c EFvisit.c EFantenna.c include ${MAGICDIR}/defs.mak include ${MAGICDIR}/rules.mak diff --git a/extract/ExtTech.c b/extract/ExtTech.c index 37259c54..21ff4ce3 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -71,7 +71,7 @@ typedef enum AREAC, CONTACT, CSCALE, DEFAULTAREACAP, DEFAULTOVERLAP, DEFAULTPERIMETER, DEFAULTSIDEOVERLAP, DEFAULTSIDEWALL, - DEVICE, FET, FETRESIST, HEIGHT, LAMBDA, OVERC, + DEVICE, FET, FETRESIST, HEIGHT, ANTENNA, LAMBDA, OVERC, PERIMC, PLANEORDER, NOPLANEORDER, RESIST, RSCALE, SIDEHALO, SIDEOVERLAP, SIDEWALL, STEP, STYLE, SUBSTRATE, UNITS, VARIANT } Key; @@ -122,6 +122,9 @@ static keydesc keyTable[] = { "height", HEIGHT, 4, 4, "type height-above-subtrate thickness", + "antenna", ANTENNA, 3, 3, +"type antenna-ratio", + "lambda", LAMBDA, 2, 2, "units-per-lambda", @@ -1785,6 +1788,7 @@ ExtTechLine(sectionName, argc, argv) case FET: case FETRESIST: case HEIGHT: + case ANTENNA: case OVERC: case PERIMC: case RESIST: @@ -2305,6 +2309,22 @@ ExtTechLine(sectionName, argc, argv) } } break; + case ANTENNA: { + float antennaratio; + + if (!StrIsNumeric(argv[2])) + { + TechError("Layer antenna ratio %s must be numeric\n", argv[2]); + break; + } + antennaratio = (float)strtod(argv[2], NULL); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, t)) + { + ExtCurStyle->exts_antennaRatio[t] = antennaratio; + } + } + break; case UNITS: if (!strcmp(argv[1], "microns")) doConvert = TRUE; diff --git a/extract/extractInt.h b/extract/extractInt.h index 5e0064e1..bb30c425 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -656,6 +656,9 @@ typedef struct extstyle float exts_height[NT]; float exts_thick[NT]; + /* Antenna area ratio for each layer */ + float exts_antennaRatio[NT]; + /* * Capacitance to substrate for each tile type, in units of * attofarads per square lambda. From b493334c7304550020927f85cbbb616f21001b21 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 17 Oct 2019 16:21:56 -0400 Subject: [PATCH 039/121] Preliminary changes to support extraction devices other than the original simple FET device in extresist. Also: Extended the bloat-all CIF operator again, allowing the trigger layer for the bloat operation to include both CIF layers and magic layers (previously only magic layers were supported). This extension is possible due to the previous extension allowing the trigger layer and bloating layers to be on separate planes. This operator extension is useful for tagging geometry that is in the proximity of, but not overlapping, geometry on another plane. --- cif/CIFgen.c | 75 +++-- cif/CIFtech.c | 2 +- commands/CmdLQ.c | 12 +- database/DBprop.c | 5 +- extflat/EFbuild.c | 4 +- extflat/EFread.c | 4 +- resis/ResBasic.c | 48 +-- resis/ResChecks.c | 24 +- resis/ResConDCS.c | 134 ++++---- resis/ResDebug.c | 28 +- resis/ResJunct.c | 28 +- resis/ResMain.c | 99 +++--- resis/ResMakeRes.c | 86 +++--- resis/ResMerge.c | 33 +- resis/ResPrint.c | 54 ++-- resis/ResReadSim.c | 102 +++---- resis/ResRex.c | 266 ++++++++-------- resis/ResSimple.c | 76 ++--- resis/ResUtils.c | 741 +++++++++++++++++++++++---------------------- resis/ResWrite.c | 18 +- resis/resis.h | 158 +++++----- utils/hash.c | 45 +++ utils/hash.h | 1 + 23 files changed, 1060 insertions(+), 983 deletions(-) diff --git a/cif/CIFgen.c b/cif/CIFgen.c index ac85961a..9c95f983 100644 --- a/cif/CIFgen.c +++ b/cif/CIFgen.c @@ -842,10 +842,21 @@ endbloat: return 0; } +#define CIF_PENDING 0 +#define CIF_UNPROCESSED CLIENTDEFAULT +#define CIF_PROCESSED 1 +#define CIF_IGNORE 2 + +#define PUSHTILE(tp, stack) \ + if ((tp)->ti_client == (ClientData) CIF_UNPROCESSED) { \ + (tp)->ti_client = (ClientData) CIF_PENDING; \ + STACKPUSH((ClientData) (tp), stack); \ + } + /* *------------------------------------------------------- * - * cifFoundFun -- + * cifFoundFunc -- * * Find the first tile in the given area. * @@ -857,12 +868,12 @@ endbloat: */ int -cifFoundFunc(tile, treturn) +cifFoundFunc(tile, BloatStackPtr) Tile *tile; - Tile **treturn; + Stack **BloatStackPtr; { - *treturn = tile; - return 1; + PUSHTILE(tile, *BloatStackPtr); + return 0; } /* Data structure for bloat-all function */ @@ -890,17 +901,6 @@ typedef struct _bloatStruct { * ---------------------------------------------------------------------------- */ -#define CIF_PENDING 0 -#define CIF_UNPROCESSED CLIENTDEFAULT -#define CIF_PROCESSED 1 -#define CIF_IGNORE 2 - -#define PUSHTILE(tp, stack) \ - if ((tp)->ti_client == (ClientData) CIF_UNPROCESSED) { \ - (tp)->ti_client = (ClientData) CIF_PENDING; \ - STACKPUSH((ClientData) (tp), stack); \ - } - int cifBloatAllFunc(tile, bls) Tile *tile; /* The tile to be processed. */ @@ -911,9 +911,8 @@ cifBloatAllFunc(tile, bls) Tile *t, *tp; TileType type; BloatData *bloats; - int i; + int i, locScale; PlaneMask pmask; - int pNum; CIFOp *op; CellDef *def; static Stack *BloatStack = (Stack *)NULL; @@ -944,17 +943,31 @@ cifBloatAllFunc(tile, bls) t = tile; type = TiGetType(tile); - pNum = DBPlane(type); - pmask = CoincidentPlanes(&connect, PlaneNumToMaskBit(pNum)); - if (pmask == 0) + if (type == CIF_SOLIDTYPE) { - TiToRect(tile, &area); - if (DBSrPaintArea((Tile *)NULL, def->cd_planes[bloats->bl_plane], &area, - &connect, cifFoundFunc, (ClientData)(&t)) == 0) - return 0; /* Nothing found here */ - } + 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); - PUSHTILE(t, BloatStack); while (!StackEmpty(BloatStack)) { t = (Tile *) STACKPOP(BloatStack); @@ -964,10 +977,10 @@ cifBloatAllFunc(tile, bls) /* Get the tile into CIF coordinates. */ TiToRect(t, &area); - area.r_xbot *= cifScale; - area.r_ybot *= cifScale; - area.r_xtop *= cifScale; - area.r_ytop *= cifScale; + area.r_xbot *= locScale; + area.r_ybot *= locScale; + area.r_xtop *= locScale; + area.r_ytop *= locScale; DBNMPaintPlane(cifPlane, TiGetTypeExact(t), &area, CIFPaintTable, (PaintUndoInfo *) NULL); diff --git a/cif/CIFtech.c b/cif/CIFtech.c index 25a920e3..309b06e0 100644 --- a/cif/CIFtech.c +++ b/cif/CIFtech.c @@ -1080,7 +1080,7 @@ CIFTechLine(sectionName, argc, argv) case CIFOP_BLOATALL: if (argc != 3) goto wrongNumArgs; cifParseLayers(argv[1], CIFCurStyle, &newOp->co_paintMask, - (TileTypeBitMask *)NULL, FALSE); + &newOp->co_cifMask, FALSE); bloats = (BloatData *)mallocMagic(sizeof(BloatData)); for (i = 0; i < TT_MAXTYPES; i++) bloats->bl_distance[i] = 0; diff --git a/commands/CmdLQ.c b/commands/CmdLQ.c index 7f3f2310..12250815 100644 --- a/commands/CmdLQ.c +++ b/commands/CmdLQ.c @@ -1882,8 +1882,16 @@ printPropertiesFunc(name, value) #ifdef MAGIC_WRAPPER char *keyvalue; - keyvalue = (char *)mallocMagic(strlen(name) + strlen((char *)value) + 2); - sprintf(keyvalue, "%s %s", name, (char *)value); + if (value == NULL) + { + keyvalue = (char *)mallocMagic(strlen(name) + 4); + sprintf(keyvalue, "%s {}", name); + } + else + { + keyvalue = (char *)mallocMagic(strlen(name) + strlen((char *)value) + 2); + sprintf(keyvalue, "%s %s", name, (char *)value); + } Tcl_AppendElement(magicinterp, keyvalue); freeMagic(keyvalue); diff --git a/database/DBprop.c b/database/DBprop.c index 85574435..0936ec3d 100644 --- a/database/DBprop.c +++ b/database/DBprop.c @@ -79,7 +79,10 @@ DBPropPut(cellDef, name, value) entry = HashFind(htab, name); oldvalue = (char *)HashGetValue(entry); if (oldvalue != NULL) freeMagic(oldvalue); - HashSetValue(entry, value); + if (value == (ClientData)NULL) + HashRemove(htab, name); + else + HashSetValue(entry, value); } /* ---------------------------------------------------------------------------- diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c index 3c83efe4..a7631a26 100644 --- a/extflat/EFbuild.c +++ b/extflat/EFbuild.c @@ -1225,14 +1225,14 @@ efBuildResistor(def, nodeName1, nodeName2, resistance) Def *def; /* Def to which this connection is to be added */ char *nodeName1; /* Name of first node in resistor */ char *nodeName2; /* Name of second node in resistor */ - float resistance; /* Resistor value */ + int resistance; /* Resistor value */ { Connection *conn; conn = (Connection *) mallocMagic((unsigned)(sizeof (Connection))); if (efConnInitSubs(conn, nodeName1, nodeName2)) { - conn->conn_res = resistance; + conn->conn_res = (float)resistance; conn->conn_next = def->def_resistors; def->def_resistors = conn; } diff --git a/extflat/EFread.c b/extflat/EFread.c index 81384a5c..b57477fb 100644 --- a/extflat/EFread.c +++ b/extflat/EFread.c @@ -426,10 +426,8 @@ readfile: /* port name num xl yl xh yh type */ case PORT: if (DoSubCircuit) - { - DoResist = FALSE; def->def_flags |= DEF_SUBCIRCUIT; - } + efBuildPortNode(def, argv[1], atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), argv[7], toplevel); break; diff --git a/resis/ResBasic.c b/resis/ResBasic.c index 273133ae..4322401d 100644 --- a/resis/ResBasic.c +++ b/resis/ResBasic.c @@ -24,7 +24,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "textio/txcommands.h" #include "resis/resis.h" -int resSubTranFunc(); +int resSubDevFunc(); /* *-------------------------------------------------------------------------- @@ -113,13 +113,13 @@ resAllPortNodes(tile, list) *-------------------------------------------------------------------------- * * ResEachTile--for each tile, make a list of all possible current sources/ - * sinks including contacts, transistors, and junctions. Once this + * sinks including contacts, devices, and junctions. Once this * list is made, calculate the resistor nextwork for the tile. * * Results: returns TRUE or FALSE depending on whether a node was * involved in a merge. * - * Side Effects: creates Nodes, transistors, junctions, and breakpoints. + * Side Effects: creates Nodes, devices, junctions, and breakpoints. * * *-------------------------------------------------------------------------- @@ -169,21 +169,21 @@ ResEachTile(tile, startpoint) if TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t1) { /* - * The transistor is put in the center of the tile. This is fine - * for single tile transistors, but not as good for multiple ones. + * The device is put in the center of the tile. This is fine + * for single tile device, but not as good for multiple ones. */ - if (tstructs->tj_status & RES_TILE_TRAN) + if (tstructs->tj_status & RES_TILE_DEV) { - if (tstructs->transistorList->rt_gate == NULL) + if (tstructs->deviceList->rd_fet_gate == NULL) { int x = (LEFT(tile) + RIGHT(tile)) >> 1; int y = (TOP(tile) + BOTTOM(tile)) >> 1; resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); - tstructs->transistorList->rt_gate = resptr; + tstructs->deviceList->rd_fet_gate = resptr; tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement))); - tcell->te_thist = tstructs->transistorList; + tcell->te_thist = tstructs->deviceList; tcell->te_nextt = NULL; InitializeNode(resptr, x, y, RES_NODE_JUNCTION); @@ -220,7 +220,7 @@ ResEachTile(tile, startpoint) { (void)DBSrPaintArea((Tile *) NULL, ResUse->cu_def->cd_planes[pNum], - &tileArea, mask, resSubTranFunc, (ClientData) tile); + &tileArea, mask, resSubDevFunc, (ClientData) tile); } } } @@ -254,11 +254,11 @@ ResEachTile(tile, startpoint) devptr = ExtCurStyle->exts_device[t2]; if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) - /* found transistor */ + /* found device */ { xj = LEFT(tile); yj = (TOP(tp) + BOTTOM(tp)) >> 1; - ResNewSDTransistor(tile, tp, xj, yj, RIGHTEDGE, &ResNodeQueue); + ResNewSDDevice(tile, tp, xj, yj, RIGHTEDGE, &ResNodeQueue); } if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2) /* tile is junction */ @@ -277,11 +277,11 @@ ResEachTile(tile, startpoint) devptr = ExtCurStyle->exts_device[t2]; if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) - /* found transistor */ + /* found device */ { xj = RIGHT(tile); yj = (TOP(tp)+BOTTOM(tp))>>1; - ResNewSDTransistor(tile, tp, xj, yj, LEFTEDGE, &ResNodeQueue); + ResNewSDDevice(tile, tp, xj, yj, LEFTEDGE, &ResNodeQueue); } if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1], t2) /* tile is junction */ @@ -300,11 +300,11 @@ ResEachTile(tile, startpoint) devptr = ExtCurStyle->exts_device[t2]; if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) - /* found transistor */ + /* found device */ { yj = TOP(tile); xj = (LEFT(tp)+RIGHT(tp))>>1; - ResNewSDTransistor(tile,tp,xj,yj,BOTTOMEDGE, &ResNodeQueue); + ResNewSDDevice(tile,tp,xj,yj,BOTTOMEDGE, &ResNodeQueue); } if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1],t2) /* tile is junction */ @@ -322,11 +322,11 @@ ResEachTile(tile, startpoint) devptr = ExtCurStyle->exts_device[t2]; if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) - /* found transistor */ + /* found device */ { yj = BOTTOM(tile); xj = (LEFT(tp) + RIGHT(tp)) >> 1; - ResNewSDTransistor(tile, tp, xj, yj, TOPEDGE, &ResNodeQueue); + ResNewSDDevice(tile, tp, xj, yj, TOPEDGE, &ResNodeQueue); } if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2) /* tile is junction */ @@ -349,7 +349,7 @@ ResEachTile(tile, startpoint) /* *------------------------------------------------------------------------- * - * resSubTranFunc -- called when DBSrPaintArea finds a transistor within + * resSubDevFunc -- called when DBSrPaintArea finds a device within * a substrate area. * * Results: always returns 0 to keep search going. @@ -360,7 +360,7 @@ ResEachTile(tile, startpoint) */ int -resSubTranFunc(tile,tp) +resSubDevFunc(tile,tp) Tile *tile,*tp; @@ -370,13 +370,13 @@ resSubTranFunc(tile,tp) tElement *tcell; int x,y; - if (junk->transistorList->rt_subs== NULL) + if (junk->deviceList->rd_fet_subs == NULL) { resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); - junk->transistorList->rt_subs = resptr; - junk->tj_status |= RES_TILE_TRAN; + junk->deviceList->rd_fet_subs = resptr; + junk->tj_status |= RES_TILE_DEV; tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement))); - tcell->te_thist = junk->transistorList; + tcell->te_thist = junk->deviceList; tcell->te_nextt = NULL; x = (LEFT(tile)+RIGHT(tile))>>1; y = (TOP(tile)+BOTTOM(tile))>>1; diff --git a/resis/ResChecks.c b/resis/ResChecks.c index 458f32ed..927125a3 100644 --- a/resis/ResChecks.c +++ b/resis/ResChecks.c @@ -43,16 +43,16 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ */ void -ResSanityChecks(nodename,resistorList,nodeList,tranlist) +ResSanityChecks(nodename,resistorList,nodeList,devlist) char *nodename; resResistor *resistorList; resNode *nodeList; - resTransistor *tranlist; + resDevice *devlist; { resResistor *resistor; resNode *node; - resTransistor *tran; + resDevice *dev; resElement *rcell; static Stack *resSanityStack = NULL; int reached,foundorigin; @@ -107,29 +107,29 @@ ResSanityChecks(nodename,resistorList,nodeList,tranlist) } resistor->rr_status &= ~RES_REACHED_RESISTOR; } - for (tran = tranlist; tran != NULL; tran = tran->rt_nextTran) + for (dev = devlist; dev != NULL; dev = dev->rd_nextDev) { int i; - if (tran->rt_status & RES_TRAN_PLUG) continue; + if (dev->rd_status & RES_DEV_PLUG) continue; reached = FALSE; - for (i=0;i != RT_TERMCOUNT;i++) + for (i=0;i != dev->rd_nterms;i++) { - if (tran->rt_terminals[i] != NULL) + if (dev->rd_terminals[i] != NULL) { reached = TRUE; - if ((tran->rt_terminals[i]->rn_status & RES_REACHED_NODE) == 0) + if ((dev->rd_terminals[i]->rn_status & RES_REACHED_NODE) == 0) { - TxError("Transistor node %d unreached in %s\n",i,nodename); + TxError("Device node %d unreached in %s\n",i,nodename); } } } if (reached == 0) { - TxError("Unreached transistor in %s at %d %d\n", + TxError("Unreached device in %s at %d %d\n", nodename, - tran->rt_inside.r_xbot, - tran->rt_inside.r_ybot); + dev->rd_inside.r_xbot, + dev->rd_inside.r_ybot); } } foundorigin = 0; diff --git a/resis/ResConDCS.c b/resis/ResConDCS.c index da5cb7fe..9db0a220 100644 --- a/resis/ResConDCS.c +++ b/resis/ResConDCS.c @@ -60,7 +60,7 @@ extern int dbcConnectFuncDCS(); extern int resSubSearchFunc(); #endif -static ResTranTile *TransList = NULL; +static ResDevTile *DevList = NULL; static TileTypeBitMask DiffTypeBitMask; TileTypeBitMask ResSubsTypeBitMask; @@ -73,14 +73,14 @@ extern void ResCalcPerimOverlap(); * * dbcConnectFuncDCS -- the same as dbcConnectFunc, except that it does * some extra searching around diffusion tiles looking for - * transistors. + * devices. * * Results: * Always returns 0 to keep the search from aborting. * * Side effects: * Adds a new record to the current check list. May also add new - * ResTranTile structures. + * ResDevTile structures. * * ---------------------------------------------------------------------------- */ @@ -92,8 +92,8 @@ dbcConnectFuncDCS(tile, cx) { struct conSrArg2 *csa2; - Rect tileArea, *srArea, tranArea, newarea; - ResTranTile *thisTran; + Rect tileArea, *srArea, devArea, newarea; + ResDevTile *thisDev; TileTypeBitMask notConnectMask, *connectMask; Tile *tp; TileType t2, t1, loctype, ctype; @@ -126,13 +126,13 @@ dbcConnectFuncDCS(tile, cx) if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { - TiToRect(tp, &tranArea); - thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); - ResCalcPerimOverlap(thisTran,tp); - GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area); - thisTran->type = TiGetType(tp); - thisTran->nextTran = TransList; - TransList = thisTran; + TiToRect(tp, &devArea); + thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile))); + ResCalcPerimOverlap(thisDev,tp); + GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area); + thisDev->type = TiGetType(tp); + thisDev->nextDev = DevList; + DevList = thisDev; } } /*right*/ @@ -143,13 +143,13 @@ dbcConnectFuncDCS(tile, cx) if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { - TiToRect(tp, &tranArea); - thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); - GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area); - thisTran->type = TiGetType(tp); - thisTran->nextTran = TransList; - TransList = thisTran; - ResCalcPerimOverlap(thisTran,tp); + TiToRect(tp, &devArea); + thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile))); + GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area); + thisDev->type = TiGetType(tp); + thisDev->nextDev = DevList; + DevList = thisDev; + ResCalcPerimOverlap(thisDev,tp); } } /*top*/ @@ -160,13 +160,13 @@ dbcConnectFuncDCS(tile, cx) if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { - TiToRect(tp, &tranArea); - thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); - GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area); - thisTran->type = TiGetType(tp); - thisTran->nextTran = TransList; - TransList = thisTran; - ResCalcPerimOverlap(thisTran,tp); + TiToRect(tp, &devArea); + thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile))); + GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area); + thisDev->type = TiGetType(tp); + thisDev->nextDev = DevList; + DevList = thisDev; + ResCalcPerimOverlap(thisDev,tp); } } /*bottom */ @@ -177,28 +177,28 @@ dbcConnectFuncDCS(tile, cx) if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { - TiToRect(tp, &tranArea); - thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); - GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area); - thisTran->type = TiGetType(tp); - thisTran->nextTran = TransList; - TransList = thisTran; - ResCalcPerimOverlap(thisTran,tp); + TiToRect(tp, &devArea); + thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile))); + GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area); + thisDev->type = TiGetType(tp); + thisDev->nextDev = DevList; + DevList = thisDev; + ResCalcPerimOverlap(thisDev,tp); } } } else if TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t1) { - TiToRect(tile, &tranArea); - thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); - ResCalcPerimOverlap(thisTran,tile); - GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area); - thisTran->type = TiGetType(tile); - thisTran->nextTran = TransList; - TransList = thisTran; + TiToRect(tile, &devArea); + thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile))); + ResCalcPerimOverlap(thisDev,tile); + GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area); + thisDev->type = TiGetType(tile); + thisDev->nextDev = DevList; + DevList = thisDev; } /* in some cases (primarily bipolar technology), we'll want to extract - transistors whose substrate terminals are part of the given region. + devices whose substrate terminals are part of the given region. The following does that check. (10-11-88) */ #ifdef ARIEL @@ -338,8 +338,8 @@ dbcConnectFuncDCS(tile, cx) */ void -ResCalcPerimOverlap(trans, tile) - ResTranTile *trans; +ResCalcPerimOverlap(dev, tile) + ResDevTile *dev; Tile *tile; { @@ -347,7 +347,7 @@ ResCalcPerimOverlap(trans, tile) int t1; int overlap; - trans->perim = (TOP(tile)-BOTTOM(tile)-LEFT(tile)+RIGHT(tile))<<1; + dev->perim = (TOP(tile)-BOTTOM(tile)-LEFT(tile)+RIGHT(tile))<<1; overlap =0; t1 = TiGetType(tile); @@ -391,7 +391,7 @@ ResCalcPerimOverlap(trans, tile) } } - trans->overlap = overlap; + dev->overlap = overlap; } @@ -404,7 +404,7 @@ ResCalcPerimOverlap(trans, tile) * dbcConnectFuncDCS. * * Results: - * Linked list of transistors. + * Linked list of devices. * * Side effects: * The contents of the result cell are modified. @@ -412,7 +412,7 @@ ResCalcPerimOverlap(trans, tile) * ---------------------------------------------------------------------------- */ -ResTranTile * +ResDevTile * DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) SearchContext *scx; TileTypeBitMask *mask; @@ -424,10 +424,10 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) { static int first = 1; struct conSrArg2 csa2; - int tran, pNum; - char *tran_name; + int dev, pNum; + char *dev_name; TileTypeBitMask *newmask; - ResTranTile *CurrentT; + ResDevTile *CurrentT; CellDef *def = destUse->cu_def; TileType newtype; ExtDevice *devptr; @@ -447,11 +447,11 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) { TTMaskZero(&DiffTypeBitMask); TTMaskZero(&ResSubsTypeBitMask); - for (tran = TT_TECHDEPBASE; tran < TT_MAXTYPES; tran++) + for (dev = TT_TECHDEPBASE; dev < TT_MAXTYPES; dev++) { - devptr = ExtCurStyle->exts_device[tran]; - if ((devptr != NULL) && ((tran_name = devptr->exts_deviceName) != NULL) - && (strcmp(tran_name, "None"))) + devptr = ExtCurStyle->exts_device[dev]; + if ((devptr != NULL) && ((dev_name = devptr->exts_deviceName) != NULL) + && (strcmp(dev_name, "None"))) { TTMaskSetMask(&DiffTypeBitMask, &(devptr->exts_deviceSDTypes[0])); @@ -462,7 +462,7 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) first = 0; } - TransList = NULL; + DevList = NULL; DBTreeSrTiles(scx, mask, xMask, dbcConnectFuncDCS, (ClientData) &csa2); while (csa2.csa2_top >= 0) { @@ -478,7 +478,7 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) } freeMagic((char *)csa2.csa2_list); - for (CurrentT = TransList; CurrentT != NULL; CurrentT=CurrentT->nextTran) + for (CurrentT = DevList; CurrentT != NULL; CurrentT=CurrentT->nextDev) { TileType t = CurrentT->type; TileType nt; @@ -496,7 +496,7 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) } DBReComputeBbox(def); - return(TransList); + return(DevList); } @@ -506,7 +506,7 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) * * resSubSearchFunc -- * - * called when DBSrPaintArea finds a transistor within + * called when DBSrPaintArea finds a device within * a substrate area. * * Results: @@ -524,8 +524,8 @@ resSubSearchFunc(tile,cx) { - ResTranTile *thisTran; - Rect tranArea; + ResDevTile *thisDev; + Rect devArea; TileType t = TiGetType(tile); ExtDevice *devptr; @@ -535,13 +535,13 @@ resSubSearchFunc(tile,cx) */ devptr = ExtCurStyle->exts_device[t] if (devptr->exts_deviceSDCount >1) return 0; - TiToRect(tile, &tranArea); - thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); - GeoTransRect(&cx->tc_scx->scx_trans, &tranArea, &thisTran->area); - thisTran->type = t; - thisTran->nextTran = TransList; - TransList = thisTran; - ResCalcPerimOverlap(thisTran,tile); + TiToRect(tile, &devArea); + thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile))); + GeoTransRect(&cx->tc_scx->scx_trans, &devArea, &thisDev->area); + thisDev->type = t; + thisDev->nextDev = DevList; + DevList = thisDev; + ResCalcPerimOverlap(thisDev,tile); return 0; } diff --git a/resis/ResDebug.c b/resis/ResDebug.c index 4a6a4682..d70777e2 100644 --- a/resis/ResDebug.c +++ b/resis/ResDebug.c @@ -101,42 +101,42 @@ ResPrintResistorList(fp,list) /* *------------------------------------------------------------------------- * - * ResPrintTransistorList-- + * ResPrintDeviceList-- * * * Results: none * - * Side effects: prints out transistors in list to file fp. + * Side effects: prints out devices in list to file fp. * *------------------------------------------------------------------------- */ void -ResPrintTransistorList(fp,list) +ResPrintDeviceList(fp,list) FILE *fp; - resTransistor *list; + resDevice *list; { static char termtype[] = {'g','s','d','c'}; int i; - for (; list != NULL; list = list->rt_nextTran) + for (; list != NULL; list = list->rd_nextDev) { - if (list->rt_status & RES_TRAN_PLUG) continue; + if (list->rd_status & RES_DEV_PLUG) continue; if (fp == stdout) - TxPrintf("t w %d l %d ", list->rt_width, list->rt_length); + TxPrintf("t w %d l %d ", list->rd_width, list->rd_length); else - fprintf(fp, "t w %d l %d ", list->rt_width, list->rt_length); - for (i=0; i!= RT_TERMCOUNT;i++) + fprintf(fp, "t w %d l %d ", list->rd_width, list->rd_length); + for (i = 0; i != list->rd_nterms; i++) { - if (list->rt_terminals[i] == NULL) continue; + if (list->rd_terminals[i] == NULL) continue; if (fp == stdout) TxPrintf("%c (%d,%d) ",termtype[i], - list->rt_terminals[i]->rn_loc.p_x, - list->rt_terminals[i]->rn_loc.p_y); + list->rd_terminals[i]->rn_loc.p_x, + list->rd_terminals[i]->rn_loc.p_y); else fprintf(fp, "%c (%d,%d) ",termtype[i], - list->rt_terminals[i]->rn_loc.p_x, - list->rt_terminals[i]->rn_loc.p_y); + list->rd_terminals[i]->rn_loc.p_x, + list->rd_terminals[i]->rn_loc.p_y); } if (fp == stdout) diff --git a/resis/ResJunct.c b/resis/ResJunct.c index 97034eec..7c8ccc0f 100644 --- a/resis/ResJunct.c +++ b/resis/ResJunct.c @@ -31,66 +31,66 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ /* *------------------------------------------------------------------------- * - * ResNewSDTransistor-- called when a transistor is reached via a piece of - * diffusion. (Transistors reached via poly, i.e. + * ResNewSDDevice -- called when a device is reached via a piece of + * diffusion. (Devices reached via poly, i.e. * gates, are handled by ResEachTile.) * * Results:none * * Side Effects: determines to which terminal (source or drain) node * is connected. Makes new node if node hasn't already been created . - * Allocates breakpoint in current tile for transistor. + * Allocates breakpoint in current tile for device. * *------------------------------------------------------------------------- */ void -ResNewSDTransistor(tile,tp,xj,yj,direction,PendingList) +ResNewSDDevice(tile,tp,xj,yj,direction,PendingList) Tile *tile,*tp; int xj,yj,direction; resNode **PendingList; { resNode *resptr; - resTransistor *resFet; + resDevice *resDev; tElement *tcell; int newnode; tileJunk *j; newnode = FALSE; j = (tileJunk *) tp->ti_client; - resFet = j->transistorList; + resDev = j->deviceList; if ((j->sourceEdge & direction) != 0) { - if (resFet->rt_source == (resNode *) NULL) + if (resDev->rd_fet_source == (resNode *) NULL) { resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); newnode = TRUE; - resFet->rt_source = resptr; + resDev->rd_fet_source = resptr; } else { - resptr = resFet->rt_source; + resptr = resDev->rd_fet_source; } } else { - if (resFet->rt_drain == (resNode *) NULL) + if (resDev->rd_fet_drain == (resNode *) NULL) { resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); newnode = TRUE; - resFet->rt_drain = resptr; + resDev->rd_fet_drain = resptr; } else { - resptr = resFet->rt_drain; + resptr = resDev->rd_fet_drain; } } if (newnode) { tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement))); tcell->te_nextt = NULL; - tcell->te_thist = j->transistorList; - InitializeNode(resptr,xj,yj,RES_NODE_TRANSISTOR); + tcell->te_thist = j->deviceList; + InitializeNode(resptr,xj,yj,RES_NODE_DEVICE); resptr->rn_te = tcell; ResAddToQueue(resptr,PendingList); } diff --git a/resis/ResMain.c b/resis/ResMain.c index 767c599e..e25a8e88 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -26,12 +26,12 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ CellUse *ResUse=NULL; /* Our use and def */ CellDef *ResDef=NULL; TileTypeBitMask ResConnectWithSD[NT]; /* A mask that goes from */ - /* SD's to transistors. */ -TileTypeBitMask ResCopyMask[NT]; /* Indicates which tiles */ + /* SD's to devices. */ +TileTypeBitMask ResCopyMask[NT]; /* Indicates which tiles */ /* are to be copied. */ resResistor *ResResList=NULL; /* Resistor list */ resNode *ResNodeList=NULL; /* Processed Nodes */ -resTransistor *ResTransList=NULL; /* Transistors */ +resDevice *ResDevList=NULL; /* Devices */ ResContactPoint *ResContactList=NULL; /* Contacts */ resNode *ResNodeQueue=NULL; /* Pending nodes */ resNode *ResOriginNode=NULL; /* node where R=0 */ @@ -52,7 +52,7 @@ extern HashTable ResNodeTable; * * ResInitializeConn-- * - * Sets up mask by Source/Drain type of transistors. This is + * Sets up mask by Source/Drain type of devices. This is * exts_deviceSDtypes turned inside out. * * Results: none @@ -65,26 +65,26 @@ extern HashTable ResNodeTable; void ResInitializeConn() { - TileType tran, diff; - char *tran_name; + TileType dev, diff; + char *dev_name; ExtDevice *devptr; - for (tran = TT_TECHDEPBASE; tran < TT_MAXTYPES; tran++) + for (dev = TT_TECHDEPBASE; dev < TT_MAXTYPES; dev++) { - devptr = ExtCurStyle->exts_device[tran]; - if ((devptr != NULL) && ((tran_name = devptr->exts_deviceName) != NULL) - && (strcmp(tran_name, "None"))) + devptr = ExtCurStyle->exts_device[dev]; + if ((devptr != NULL) && ((dev_name = devptr->exts_deviceName) != NULL) + && (strcmp(dev_name, "None"))) { for (diff = TT_TECHDEPBASE; diff < TT_MAXTYPES; diff++) { if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), diff) - TTMaskSetType(&ResConnectWithSD[diff],tran); + TTMaskSetType(&ResConnectWithSD[diff],dev); if TTMaskHasType(&(devptr->exts_deviceSubstrateTypes),diff) - TTMaskSetType(&ResConnectWithSD[diff],tran); + TTMaskSetType(&ResConnectWithSD[diff],dev); } } - TTMaskSetMask(&ResConnectWithSD[tran],&DBConnectTbl[tran]); + TTMaskSetMask(&ResConnectWithSD[dev],&DBConnectTbl[dev]); } } @@ -573,7 +573,7 @@ ResExtractNet(startlist,goodies,cellname) { SearchContext scx; int pNum; - ResTranTile *TranTiles,*lasttile; + ResDevTile *DevTiles,*lasttile; TileTypeBitMask FirstTileMask; Point startpoint; ResFixPoint *fix; @@ -583,7 +583,7 @@ ResExtractNet(startlist,goodies,cellname) ResResList=NULL; ResNodeList=NULL; - ResTransList=NULL; + ResDevList=NULL; ResNodeQueue=NULL; ResContactList = NULL; ResOriginNode = NULL; @@ -632,11 +632,11 @@ ResExtractNet(startlist,goodies,cellname) /* Copy Paint */ - TranTiles = NULL; + DevTiles = NULL; lasttile = NULL; for (fix = startlist; fix != NULL;fix=fix->fp_next) { - ResTranTile *newtrantiles,*tmp; + ResDevTile *newdevtiles,*tmp; #ifdef ARIEL if ((ResOptionsFlags & ResOpt_Power) && @@ -650,19 +650,19 @@ ResExtractNet(startlist,goodies,cellname) startpoint = fix->fp_loc; TTMaskSetOnlyType(&FirstTileMask,fix->fp_ttype); - newtrantiles = DBTreeCopyConnectDCS(&scx, &FirstTileMask, 0, + newdevtiles = DBTreeCopyConnectDCS(&scx, &FirstTileMask, 0, ResCopyMask, &TiPlaneRect, ResUse); - for (tmp = newtrantiles; tmp && tmp->nextTran; tmp = tmp->nextTran); - if (newtrantiles) + for (tmp = newdevtiles; tmp && tmp->nextDev; tmp = tmp->nextDev); + if (newdevtiles) { - if (TranTiles) + if (DevTiles) { - lasttile->nextTran = newtrantiles; + lasttile->nextDev = newdevtiles; } else { - TranTiles = newtrantiles; + DevTiles = newdevtiles; } lasttile = tmp; } @@ -696,7 +696,7 @@ ResExtractNet(startlist,goodies,cellname) (void) DBSrPaintClient((Tile *) NULL,plane,rect, &DBAllButSpaceAndDRCBits, (ClientData) CLIENTDEFAULT, ResAddPlumbing, - (ClientData) &ResTransList); + (ClientData) &ResDevList); } /* Finish preprocessing. */ @@ -704,7 +704,7 @@ ResExtractNet(startlist,goodies,cellname) ResMakePortBreakpoints(ResUse->cu_def); ResMakeLabelBreakpoints(ResUse->cu_def); ResFindNewContactTiles(ResContactList); - ResPreProcessTransistors(TranTiles, ResTransList, ResUse->cu_def); + ResPreProcessDevices(DevTiles, ResDevList, ResUse->cu_def); #ifdef LAPLACE if (ResOptionsFlags & ResOpt_DoLaplace) @@ -756,7 +756,7 @@ ResCleanUpEverything() int pNum; resResistor *oldRes; - resTransistor *oldTran; + resDevice *oldDev; ResContactPoint *oldCon; /* check integrity of internal database. Free up lists. */ @@ -786,13 +786,14 @@ ResCleanUpEverything() ResResList = ResResList->rr_nextResistor; freeMagic((char *)oldRes); } - while (ResTransList != NULL) + while (ResDevList != NULL) { - oldTran = ResTransList; - ResTransList = ResTransList->rt_nextTran; - if ((oldTran->rt_status & RES_TRAN_SAVE) == 0) + oldDev = ResDevList; + ResDevList = ResDevList->rd_nextDev; + if ((oldDev->rd_status & RES_DEV_SAVE) == 0) { - freeMagic((char *)oldTran); + freeMagic((char *)oldDev->rd_terminals); + freeMagic((char *)oldDev); } } @@ -806,7 +807,7 @@ ResCleanUpEverything() * * FindStartTile-- To start the extraction, we need to find the first driver. * The sim file gives us the location of a point in or near (within 1 - * unit) of the transistor. FindStartTile looks for the transistor, then + * unit) of the device. FindStartTile looks for the device, then * for adjoining diffusion. The diffusion tile is returned. * * Results: returns source diffusion tile, if it exists. Otherwise, return @@ -828,11 +829,11 @@ FindStartTile(goodies, SourcePoint) int pnum, t1, t2; ExtDevice *devptr; - workingPoint.p_x = goodies->rg_tranloc->p_x; - workingPoint.p_y = goodies->rg_tranloc->p_y; + workingPoint.p_x = goodies->rg_devloc->p_x; + workingPoint.p_y = goodies->rg_devloc->p_y; pnum = DBPlane(goodies->rg_ttype); - /* for drivepoints, we don't have to find a transistor */ + /* for drivepoints, we don't have to find a device */ if (goodies->rg_status & DRIVEONLY) { tile = ResUse->cu_def->cd_planes[pnum]->pl_hint; @@ -862,7 +863,7 @@ FindStartTile(goodies, SourcePoint) } } TxError("Couldn't find wire at %d %d\n", - goodies->rg_tranloc->p_x, goodies->rg_tranloc->p_y); + goodies->rg_devloc->p_x, goodies->rg_devloc->p_y); return NULL; } @@ -883,15 +884,15 @@ FindStartTile(goodies, SourcePoint) } else { - TxError("Couldn't find transistor at %d %d\n", - goodies->rg_tranloc->p_x, goodies->rg_tranloc->p_y); + TxError("Couldn't find device at %d %d\n", + goodies->rg_devloc->p_x, goodies->rg_devloc->p_y); return(NULL); } } else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetType(tile)) == 0) { - TxError("Couldn't find transistor at %d %d\n", - goodies->rg_tranloc->p_x, goodies->rg_tranloc->p_y); + TxError("Couldn't find device at %d %d\n", + goodies->rg_devloc->p_x, goodies->rg_devloc->p_y); return(NULL); } else @@ -955,11 +956,11 @@ FindStartTile(goodies, SourcePoint) /* *------------------------------------------------------------------------- * - * ResGetTransistor-- Once the net is extracted, we still have to equate - * the sim file transistors with the layout transistors. ResGetTransistor - * looks for a transistor at the given location. + * ResGetDevice -- Once the net is extracted, we still have to equate + * the sim file devices with the layout devices. ResGetDevice + * looks for a device at the given location. * - * Results: returns transistor structure at location TransistorPoint, if it + * Results: returns device structure at location DevicePoint, if it * exists. * * Side Effects: none @@ -967,8 +968,8 @@ FindStartTile(goodies, SourcePoint) *------------------------------------------------------------------------- */ -resTransistor * -ResGetTransistor(pt) +resDevice * +ResGetDevice(pt) Point *pt; { @@ -985,7 +986,7 @@ ResGetTransistor(pt) { continue; } - /*start at hint tile for transistor plane */ + /*start at hint tile for device plane */ tile = ResUse->cu_def->cd_planes[pnum]->pl_hint; GOTOPOINT(tile,&workingPoint); @@ -993,11 +994,11 @@ ResGetTransistor(pt) { if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetLeftType(tile)) || TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetRightType(tile))) - return(((tileJunk *)tile->ti_client)->transistorList); + return(((tileJunk *)tile->ti_client)->deviceList); } else if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetType(tile))) { - return(((tileJunk *)tile->ti_client)->transistorList); + return(((tileJunk *)tile->ti_client)->deviceList); } } return (NULL); diff --git a/resis/ResMakeRes.c b/resis/ResMakeRes.c index 5d874d1d..022f9ed1 100644 --- a/resis/ResMakeRes.c +++ b/resis/ResMakeRes.c @@ -27,7 +27,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "cif/CIFint.h" /* Forward declarations */ -bool ResCalcNearTransistor(); +bool ResCalcNearDevice(); bool ResCalcNorthSouth(); bool ResCalcEastWest(); @@ -58,12 +58,12 @@ ResCalcTileResistance(tile, junk, pendingList, doneList) { int MaxX = MINFINITY, MinX = INFINITY; int MaxY = MINFINITY, MinY = INFINITY; - int transistor; + int device; bool merged; Breakpoint *p1; merged = FALSE; - transistor = FALSE; + device = FALSE; if ((p1 = junk->breakList) == NULL) return FALSE; for (; p1; p1 = p1->br_next) @@ -74,18 +74,18 @@ ResCalcTileResistance(tile, junk, pendingList, doneList) if (x < MinX) MinX = x; if (y > MaxY) MaxY = y; if (y < MinY) MinY = y; - if (p1->br_this->rn_why == RES_NODE_TRANSISTOR) + if (p1->br_this->rn_why == RES_NODE_DEVICE) { - transistor = TRUE; + device = TRUE; } } /* Finally, produce resistors for partition. Keep track of */ /* whether or not the node was involved in a merge. */ - if (transistor) + if (device) { - merged |= ResCalcNearTransistor(tile, pendingList, doneList, &ResResList); + merged |= ResCalcNearDevice(tile, pendingList, doneList, &ResResList); } else if (MaxY-MinY > MaxX-MinX) { @@ -444,9 +444,9 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList) /* *------------------------------------------------------------------------- * - * ResCalcNearTransistor-- Calculating the direction of current flow near - * transistors is tricky because there are two adjoining regions with - * vastly different sheet resistances. ResCalcNearTransistor is called + * ResCalcNearDevice-- Calculating the direction of current flow near + * devices is tricky because there are two adjoining regions with + * vastly different sheet resistances. ResCalcNearDevice is called * whenever a diffusion tile adjoining a real tile is found. It makes * a guess at the correct direction of current flow, removes extra * breakpoints, and call either ResCalcEastWest or ResCalcNorthSouth @@ -460,14 +460,14 @@ ResCalcNorthSouth(tile, pendingList, doneList, resList) */ bool -ResCalcNearTransistor(tile, pendingList, doneList, resList) +ResCalcNearDevice(tile, pendingList, doneList, resList) Tile *tile; resNode **pendingList, **doneList; resResistor **resList; { bool merged; - int trancount,tranedge,deltax,deltay; + int devcount,devedge,deltax,deltay; Breakpoint *p1,*p2,*p3; tileJunk *junk = (tileJunk *)tile->ti_client; @@ -485,35 +485,35 @@ ResCalcNearTransistor(tile, pendingList, doneList, resList) junk->breakList = NULL; return(merged); } - /* count the number of transistor breakpoints */ + /* count the number of device breakpoints */ /* mark which edge they connect to */ - trancount = 0; - tranedge = 0; + devcount = 0; + devedge = 0; for (p1=junk->breakList; p1 != NULL;p1 = p1->br_next) { - if (p1->br_this->rn_why == RES_NODE_TRANSISTOR) + if (p1->br_this->rn_why == RES_NODE_DEVICE) { - trancount++; - if (p1->br_loc.p_x == LEFT(tile)) tranedge |= LEFTEDGE; - else if (p1->br_loc.p_x == RIGHT(tile)) tranedge |= RIGHTEDGE; - else if (p1->br_loc.p_y == TOP(tile)) tranedge |= TOPEDGE; - else if (p1->br_loc.p_y == BOTTOM(tile)) tranedge |= BOTTOMEDGE; + devcount++; + if (p1->br_loc.p_x == LEFT(tile)) devedge |= LEFTEDGE; + else if (p1->br_loc.p_x == RIGHT(tile)) devedge |= RIGHTEDGE; + else if (p1->br_loc.p_y == TOP(tile)) devedge |= TOPEDGE; + else if (p1->br_loc.p_y == BOTTOM(tile)) devedge |= BOTTOMEDGE; } } - /* use distance from transistor to next breakpoint as determinant */ - /* if there is only one transistor or if all the transitors are along */ + /* use distance from device to next breakpoint as determinant */ + /* if there is only one device or if all the devices are along */ /* the same edge. */ - if (trancount == 1 || - (tranedge & LEFTEDGE) == tranedge || - (tranedge & RIGHTEDGE) == tranedge || - (tranedge & TOPEDGE) == tranedge || - (tranedge & BOTTOMEDGE) == tranedge) + if (devcount == 1 || + (devedge & LEFTEDGE) == devedge || + (devedge & RIGHTEDGE) == devedge || + (devedge & TOPEDGE) == devedge || + (devedge & BOTTOMEDGE) == devedge) { ResSortBreaks(&junk->breakList,TRUE); p2 = NULL; for (p1=junk->breakList; p1 != NULL;p1 = p1->br_next) { - if (p1->br_this->rn_why == RES_NODE_TRANSISTOR) + if (p1->br_this->rn_why == RES_NODE_DEVICE) { break; } @@ -580,7 +580,7 @@ ResCalcNearTransistor(tile, pendingList, doneList, resList) p2 = NULL; for (p1=junk->breakList; p1 != NULL;p1 = p1->br_next) { - if (p1->br_this->rn_why == RES_NODE_TRANSISTOR) + if (p1->br_this->rn_why == RES_NODE_DEVICE) { break; } @@ -651,27 +651,27 @@ ResCalcNearTransistor(tile, pendingList, doneList, resList) } } - /* multiple transistors connected to the partition */ + /* multiple devices connected to the partition */ else { - if (tranedge == 0) + if (devedge == 0) { - TxError("Error in transistor current direction routine\n"); + TxError("Error in device current direction routine\n"); return(merged); } /* check to see if the current flow is north-south */ /* possible north-south conditions: */ - /* 1. there are transistors along the top and bottom edges */ + /* 1. there are devices along the top and bottom edges */ /* but not along the left or right */ - /* 2. there are transistors along two sides at right angles, */ + /* 2. there are devices along two sides at right angles, */ /* and the tile is wider than it is tall. */ - if ((tranedge & TOPEDGE) && - (tranedge & BOTTOMEDGE) && - !(tranedge & LEFTEDGE) && - !(tranedge & RIGHTEDGE) || - (tranedge & TOPEDGE || tranedge & BOTTOMEDGE) && - (tranedge & LEFTEDGE || tranedge & RIGHTEDGE) && + if ((devedge & TOPEDGE) && + (devedge & BOTTOMEDGE) && + !(devedge & LEFTEDGE) && + !(devedge & RIGHTEDGE) || + (devedge & TOPEDGE || devedge & BOTTOMEDGE) && + (devedge & LEFTEDGE || devedge & RIGHTEDGE) && RIGHT(tile)-LEFT(tile) > TOP(tile)-BOTTOM(tile)) { /* re-sort nodes south to north. */ @@ -680,7 +680,7 @@ ResCalcNearTransistor(tile, pendingList, doneList, resList) /* eliminate duplicate S/D pointers */ for (p1 = junk->breakList; p1 != NULL; p1 = p1->br_next) { - if (p1->br_this->rn_why == RES_NODE_TRANSISTOR && + if (p1->br_this->rn_why == RES_NODE_DEVICE && (p1->br_loc.p_y == BOTTOM(tile) || p1->br_loc.p_y == TOP(tile))) { @@ -721,7 +721,7 @@ ResCalcNearTransistor(tile, pendingList, doneList, resList) /* eliminate duplicate S/D pointers */ for (p1 = junk->breakList; p1 != NULL; p1 = p1->br_next) { - if (p1->br_this->rn_why == RES_NODE_TRANSISTOR && + if (p1->br_this->rn_why == RES_NODE_DEVICE && (p1->br_loc.p_x == LEFT(tile) || p1->br_loc.p_x == RIGHT(tile))) { diff --git a/resis/ResMerge.c b/resis/ResMerge.c index 8e619330..729dd937 100644 --- a/resis/ResMerge.c +++ b/resis/ResMerge.c @@ -107,7 +107,7 @@ ResDoneWithNode(resptr) } } - /* Eliminations that can be only if there are no transistors connected */ + /* Eliminations that can be only if there are no devices connected */ /* to node. Series and dangling connections fall in this group. */ if ((resptr->rn_te == NULL) && (resptr->rn_why != RES_NODE_ORIGIN) @@ -219,7 +219,7 @@ ResFixParallel(elimResis,newResis) /* *------------------------------------------------------------------------- * - * ResSeriesCheck -- for nodes with no transistors, sees if a series + * ResSeriesCheck -- for nodes with no devices, sees if a series or loop combination is possible. * * Results: returns SINGLE,LOOP,or SERIES if succesful. @@ -403,7 +403,7 @@ ResSeriesCheck(resptr) /* *------------------------------------------------------------------------- * - * ResParallelCheck -- tries to do parallel combinations of transistors. + * ResParallelCheck -- tries to do parallel combinations of devices. * * Results: returns PARALLEL if successful * @@ -641,7 +641,7 @@ ResMergeNodes(node1,node2,pendingList,doneList) { resElement *workingRes,*tRes; - tElement *workingFet,*tFet; + tElement *workingDev,*tDev; jElement *workingJunc,*tJunc; cElement *workingCon,*tCon; Tile *tile; @@ -677,13 +677,13 @@ ResMergeNodes(node1,node2,pendingList,doneList) /* combine relevant flags */ node1->rn_status |= (node2->rn_status & RN_MAXTDI); - /*merge transistor lists */ - workingFet = node2->rn_te; - while (workingFet != NULL) + /*merge device lists */ + workingDev = node2->rn_te; + while (workingDev != NULL) { - if (workingFet->te_thist->rt_status & RES_TRAN_PLUG) + if (workingDev->te_thist->rd_status & RES_DEV_PLUG) { - ResPlug *plug = (ResPlug *) workingFet->te_thist; + ResPlug *plug = (ResPlug *) workingDev->te_thist; if (plug->rpl_node == node2) { plug->rpl_node = node1; @@ -697,19 +697,18 @@ ResMergeNodes(node1,node2,pendingList,doneList) } else { - int j; - for (j=0;j!= RT_TERMCOUNT;j++) - if (workingFet->te_thist->rt_terminals[j] == node2) + for (j = 0; j != workingDev->te_thist->rd_nterms; j++) + if (workingDev->te_thist->rd_terminals[j] == node2) { - workingFet->te_thist->rt_terminals[j] = node1; + workingDev->te_thist->rd_terminals[j] = node1; } } - tFet = workingFet; - workingFet = workingFet->te_nextt; - tFet->te_nextt = node1->rn_te; - node1->rn_te = tFet; + tDev = workingDev; + workingDev = workingDev->te_nextt; + tDev->te_nextt = node1->rn_te; + node1->rn_te = tDev; } /* append junction lists */ diff --git a/resis/ResPrint.c b/resis/ResPrint.c index 1423bfac..d8839b91 100644 --- a/resis/ResPrint.c +++ b/resis/ResPrint.c @@ -63,7 +63,7 @@ ResPrintExtRes(outextfile,resistors,nodename) { /* These names shouldn't be null; they should either be set by - the transistor name or by the node printing routine. This + the device name or by the node printing routine. This code is included in case the resistor network is printed before the nodes. */ @@ -97,32 +97,32 @@ ResPrintExtRes(outextfile,resistors,nodename) /* *------------------------------------------------------------------------- * - * ResPrintExtTran-- Print out all transistors that have had at least + * ResPrintExtDev-- Print out all devices that have had at least * one terminal changed. * * Results:none * - * Side Effects:prints transistor lines to output file + * Side Effects:prints device lines to output file * *------------------------------------------------------------------------- */ void -ResPrintExtTran(outextfile, transistors) +ResPrintExtDev(outextfile, devices) FILE *outextfile; - RTran *transistors; + RDev *devices; { TileType t; char *subsName; ExtDevice *devptr; - for (; transistors != NULL; transistors = transistors->nextTran) + for (; devices != NULL; devices = devices->nextDev) { - if (transistors->status & TRUE) + if (devices->status & TRUE) { if (ResOptionsFlags & ResOpt_DoExtFile) { - t = transistors->layout->rt_trantype; + t = devices->layout->rd_devtype; devptr = ExtCurStyle->exts_device[t]; subsName = devptr->exts_deviceSubstrateName; @@ -142,22 +142,22 @@ ResPrintExtTran(outextfile, transistors) fprintf(outextfile,"fet %s %d %d %d %d %d %d " "%s \"%s\" %d %s \"%s\" %d %s \"%s\" %d %s\n", devptr->exts_deviceName, - transistors->layout->rt_inside.r_ll.p_x, - transistors->layout->rt_inside.r_ll.p_y, - transistors->layout->rt_inside.r_ll.p_x + 1, - transistors->layout->rt_inside.r_ll.p_y + 1, - transistors->layout->rt_area, - transistors->layout->rt_perim, + devices->layout->rd_inside.r_ll.p_x, + devices->layout->rd_inside.r_ll.p_y, + devices->layout->rd_inside.r_ll.p_x + 1, + devices->layout->rd_inside.r_ll.p_y + 1, + devices->layout->rd_area, + devices->layout->rd_perim, subsName, - transistors->gate->name, - transistors->layout->rt_length * 2, - transistors->rs_gattr, - transistors->source->name, - transistors->layout->rt_width, - transistors->rs_sattr, - transistors->drain->name, - transistors->layout->rt_width, - transistors->rs_dattr); + devices->gate->name, + devices->layout->rd_length * 2, + devices->rs_gattr, + devices->source->name, + devices->layout->rd_width, + devices->rs_sattr, + devices->drain->name, + devices->layout->rd_width, + devices->rs_dattr); } } } @@ -244,7 +244,7 @@ ResPrintExtNode(outextfile, nodelist, nodename) /* *------------------------------------------------------------------------- * - * ResPrintStats -- Prints out the node name, the number of transistors, + * ResPrintStats -- Prints out the node name, the number of devices, * and the number of nodes for each net added. Also keeps a running * track of the totals. * @@ -599,7 +599,7 @@ ResPrintFHRects(fp, reslist, nodename, eidx) * (FastHenry) file output. * * NOTE: For now, I am assuming that substrate = ground (GND). - * However, a transistor list is passed, and it should be parsed + * However, a device list is passed, and it should be parsed * for substrate devices, allowing the creation of VDD and GND * reference planes for both substrate and wells. * @@ -614,9 +614,9 @@ ResPrintFHRects(fp, reslist, nodename, eidx) */ void -ResPrintReference(fp, transistors, cellDef) +ResPrintReference(fp, devices, cellDef) FILE *fp; - RTran *transistors; + RDev *devices; CellDef *cellDef; { char *outfile = cellDef->cd_name; diff --git a/resis/ResReadSim.c b/resis/ResReadSim.c index 19ae304d..6d9dad10 100644 --- a/resis/ResReadSim.c +++ b/resis/ResReadSim.c @@ -36,12 +36,12 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ /* constants defining where various fields can be found in .sim files. */ -#define RTRAN_LENGTH 4 -#define RTRAN_WIDTH 5 -#define RTRAN_TRANX 6 -#define RTRAN_TRANY 7 -#define RTRAN_ATTR 8 -#define RTRAN_NUM_ATTR 3 +#define RDEV_LENGTH 4 +#define RDEV_WIDTH 5 +#define RDEV_DEVX 6 +#define RDEV_DEVY 7 +#define RDEV_ATTR 8 +#define RDEV_NUM_ATTR 3 #define RESNODENAME 1 #define NODERESISTANCE 2 #define COUPLETERMINAL1 1 @@ -80,7 +80,7 @@ ResSimNode *ResInitializeNode(); ResSimNode *ResOriginalNodes; /*Linked List of Nodes */ static float lambda=1.0; /* Scale factor */ -char RTRAN_NOATTR[1]={'0'}; +char RDEV_NOATTR[1]={'0'}; ResFixPoint *ResFixList; #define nodeinit(n)\ @@ -185,7 +185,7 @@ ResReadSim(simfile,fetproc,capproc,resproc,attrproc,mergeproc) } if (fettype == -1) { - TxError("Error in Reading tran line of sim file.\n"); + TxError("Error in Reading device line of sim file.\n"); result = 1; } else if (fettype != MINFINITY) @@ -320,29 +320,29 @@ gettokens(line,fp) /* *------------------------------------------------------------------------- * - * ResSimTransistor-- Processes a transistor line from a sim file. + * ResSimDevice-- Processes a device line from a sim file. * * Results: returns 0 if line was added correctly. * - * Side Effects: Allocates transistors and adds nodes to the node hash table. + * Side Effects: Allocates devices and adds nodes to the node hash table. * *------------------------------------------------------------------------- */ int -ResSimTransistor(line,rpersquare,ttype) +ResSimDevice(line,rpersquare,ttype) char line[][MAXTOKEN]; float rpersquare; TileType ttype; { - RTran *transistor; + RDev *device; int rvalue,i,j,k; char *newattr,tmpattr[MAXTOKEN]; static int nowarning = TRUE; - transistor = (RTran *) mallocMagic((unsigned) (sizeof(RTran))); - if ((line[RTRAN_WIDTH][0] == '\0') || (line[RTRAN_LENGTH][0] == '\0')) + device = (RDev *) mallocMagic((unsigned) (sizeof(RDev))); + if ((line[RDEV_WIDTH][0] == '\0') || (line[RDEV_LENGTH][0] == '\0')) { TxError("error in input file:\n"); return(1); @@ -355,23 +355,23 @@ ResSimTransistor(line,rpersquare,ttype) TxError("All driven nodes will be extracted\n"); nowarning = FALSE; } - transistor->resistance = MagAtof(line[RTRAN_LENGTH]) * rpersquare/MagAtof(line[RTRAN_WIDTH]); + device->resistance = MagAtof(line[RDEV_LENGTH]) * rpersquare/MagAtof(line[RDEV_WIDTH]); } - transistor->tnumber = ++Maxtnumber; - transistor->status = FALSE; - transistor->nextTran = ResTranList; - transistor->location.p_x = atoi(line[RTRAN_TRANX]); - transistor->location.p_y = atoi(line[RTRAN_TRANY]); - transistor->rs_gattr=RTRAN_NOATTR; - transistor->rs_sattr=RTRAN_NOATTR; - transistor->rs_dattr=RTRAN_NOATTR; - transistor->rs_ttype = ttype; + device->tnumber = ++Maxtnumber; + device->status = FALSE; + device->nextDev = ResRDevList; + device->location.p_x = atoi(line[RDEV_DEVX]); + device->location.p_y = atoi(line[RDEV_DEVY]); + device->rs_gattr=RDEV_NOATTR; + device->rs_sattr=RDEV_NOATTR; + device->rs_dattr=RDEV_NOATTR; + device->rs_ttype = ttype; /* sim attributes look like g=a1,a2 */ /* ext attributes are "a1","a2" */ /* do conversion from one to the other here */ - for (i=RTRAN_ATTR;i < RTRAN_ATTR+RTRAN_NUM_ATTR;i++) + for (i=RDEV_ATTR;i < RDEV_ATTR+RDEV_NUM_ATTR;i++) { if (line[i][0] == '\0') break; k=0; @@ -395,18 +395,18 @@ ResSimTransistor(line,rpersquare,ttype) strncpy(newattr,tmpattr,k); switch (line[i][0]) { - case 'g': transistor->rs_gattr = newattr; break; - case 's': transistor->rs_sattr = newattr; break; - case 'd': transistor->rs_dattr = newattr; break; + case 'g': device->rs_gattr = newattr; break; + case 's': device->rs_sattr = newattr; break; + case 'd': device->rs_dattr = newattr; break; default: TxError("Bad fet attribute\n"); break; } } - ResTranList = transistor; - transistor->layout = NULL; - rvalue = ResSimNewNode(line[GATE],GATE,transistor) + - ResSimNewNode(line[SOURCE],SOURCE,transistor) + - ResSimNewNode(line[DRAIN],DRAIN,transistor); + ResRDevList = device; + device->layout = NULL; + rvalue = ResSimNewNode(line[GATE],GATE,device) + + ResSimNewNode(line[SOURCE],SOURCE,device) + + ResSimNewNode(line[DRAIN],DRAIN,device); return(rvalue); } @@ -425,35 +425,35 @@ ResSimTransistor(line,rpersquare,ttype) */ int -ResSimNewNode(line,type,transistor) +ResSimNewNode(line,type,device) char line[]; int type; - RTran *transistor; + RDev *device; { HashEntry *entry; ResSimNode *node; - tranPtr *tptr; + devPtr *tptr; if (line[0] == '\0') { - TxError("Missing transistor connection\n"); + TxError("Missing device connection\n"); return(1); } entry = HashFind(&ResNodeTable,line); node = ResInitializeNode(entry); - tptr = (tranPtr *) mallocMagic((unsigned) (sizeof(tranPtr))); - tptr->thisTran = transistor; - tptr->nextTran = node->firstTran; - node->firstTran = tptr; + tptr = (devPtr *) mallocMagic((unsigned) (sizeof(devPtr))); + tptr->thisDev = device; + tptr->nextDev = node->firstDev; + node->firstDev = tptr; tptr->terminal = type; switch(type) { - case GATE: transistor->gate = node; + case GATE: device->gate = node; break; - case SOURCE: transistor->source = node; + case SOURCE: device->source = node; break; - case DRAIN: transistor->drain = node; + case DRAIN: device->drain = node; break; default: TxError("Bad Terminal Specifier\n"); break; @@ -806,7 +806,7 @@ ResSimMerge(line) { ResSimNode *node; - tranPtr *ptr; + devPtr *ptr; if ((line[ALIASNAME][0] == '\0') || (line[REALNAME][0] == '\0')) { @@ -818,12 +818,12 @@ ResSimMerge(line) node->forward = ResInitializeNode(HashFind(&ResNodeTable,line[REALNAME])); node->forward->resistance += node->resistance; node->forward->capacitance += node->capacitance; - while (node->firstTran != NULL) + while (node->firstDev != NULL) { - ptr=node->firstTran; - node->firstTran = node->firstTran->nextTran; - ptr->nextTran = node->forward->firstTran; - node->forward->firstTran = ptr; + ptr=node->firstDev; + node->firstDev = node->firstDev->nextDev; + ptr->nextDev = node->forward->firstDev; + node->forward->firstDev = ptr; } return(0); } @@ -860,7 +860,7 @@ ResInitializeNode(entry) node->cap_couple = 0; node->resistance = 0; node->type = 0; - node->firstTran = NULL; + node->firstDev = NULL; node->name = entry->h_key.h_name; node->oldname = NULL; node->drivepoint.p_x = INFINITY; diff --git a/resis/ResRex.c b/resis/ResRex.c index b31299e8..e98aa143 100644 --- a/resis/ResRex.c +++ b/resis/ResRex.c @@ -45,11 +45,11 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ HashTable ResNodeTable; /* Hash table of sim file nodes */ -RTran *ResTranList; /* Linked list of Sim transistors */ +RDev *ResRDevList; /* Linked list of Sim devices */ ResGlobalParams gparams; /* Junk passed between */ /* ResCheckSimNodes and */ /* ResExtractNet. */ -int Maxtnumber; /*maximum transistor number */ +int Maxtnumber; /*maximum device number */ extern ResSimNode *ResOriginalNodes; /*Linked List of Nodes */ int resNodeNum; @@ -94,21 +94,21 @@ ExtResisForDef(celldef, resisdata) CellDef *celldef; ResisData *resisdata; { - RTran *oldTran; + RDev *oldRDev; HashSearch hs; HashEntry *entry; - tranPtr *tptr,*oldtptr; + devPtr *tptr,*oldtptr; ResSimNode *node; int result; - ResTranList = NULL; + ResRDevList = NULL; ResOriginalNodes = NULL; Maxtnumber = 0; HashInit(&ResNodeTable, INITFLATSIZE, HT_STRINGKEYS); /* read in .sim file */ result = (ResReadSim(celldef->cd_name, - ResSimTransistor,ResSimCapacitor,ResSimResistor, + ResSimDevice,ResSimCapacitor,ResSimResistor, ResSimAttribute,ResSimMerge) == 0); if (result) @@ -138,7 +138,7 @@ ExtResisForDef(celldef, resisdata) while((entry = HashNext(&ResNodeTable,&hs)) != NULL) { node=(ResSimNode *) HashGetValue(entry); - tptr = node->firstTran; + tptr = node->firstDev; if (node == NULL) { TxError("Error: NULL Hash entry!\n"); @@ -147,22 +147,22 @@ ExtResisForDef(celldef, resisdata) while (tptr != NULL) { oldtptr = tptr; - tptr = tptr->nextTran; + tptr = tptr->nextDev; freeMagic((char *)oldtptr); } freeMagic((char *) node); } HashKill(&ResNodeTable); - while (ResTranList != NULL) + while (ResRDevList != NULL) { - oldTran = ResTranList; - ResTranList = ResTranList->nextTran; - if (oldTran->layout != NULL) + oldRDev = ResRDevList; + ResRDevList = ResRDevList->nextDev; + if (oldRDev->layout != NULL) { - freeMagic((char *)oldTran->layout); - oldTran->layout = NULL; + freeMagic((char *)oldRDev->layout); + oldRDev->layout = NULL; } - freeMagic((char *)oldTran); + freeMagic((char *)oldRDev); } } @@ -206,7 +206,7 @@ CmdExtResis(win, cmd) static char *cmdExtresisCmd[] = { - "tolerance [value] set ratio between resistor and transistor tol.", + "tolerance [value] set ratio between resistor and device tol.", "all extract all the nets", "simplify [on/off] turn on/off simplification of resistor nets", "extout [on/off] turn on/off writing of .res.ext file", @@ -448,7 +448,7 @@ typedef enum { if (cmd->tx_argc != 3) return; tt = DBTechNoisyNameType(cmd->tx_argv[2]); if (tt <= 0 || ToolGetBox(&def, &rect)== FALSE) return; - gparams.rg_tranloc = &rect.r_ll; + gparams.rg_devloc = &rect.r_ll; gparams.rg_ttype = tt; gparams.rg_status = DRIVEONLY; oldoptions = ResOptionsFlags; @@ -463,7 +463,7 @@ typedef enum { fp.fp_next = NULL; if (ResExtractNet(&fp, &gparams, NULL) != 0) return; ResPrintResistorList(stdout,ResResList); - ResPrintTransistorList(stdout,ResTransList); + ResPrintDeviceList(stdout,ResRDevList); #ifdef LAPLACE if (ResOptionsFlags & ResOpt_DoLaplace) { @@ -722,7 +722,7 @@ ResCheckBlackbox(cellDef) * * Subcircuit boundaries mark an area which is to be checked * explicitly for geometry information. Because there may be - * no transistors in the subcircuit cell, we must find the ports + * no devices in the subcircuit cell, we must find the ports * into the subcircuit and declare them to be "driving" nodes so * the extresis algorithm will treat them as being part of valid * networks. @@ -806,7 +806,7 @@ ResCheckPorts(cellDef) *------------------------------------------------------------------------- * * ResCheckSimNodes-- check to see if lumped resistance is greater than the - * transistor resistance; if it is, Extract the net + * device resistance; if it is, Extract the net * resistance. If the maximum point to point resistance * in the extracted net is still creater than the * tolerance, then output the extracted net. @@ -824,7 +824,7 @@ ResCheckSimNodes(celldef, resisdata) ResisData *resisdata; { ResSimNode *node; - tranPtr *ptr; + devPtr *ptr; float ftolerance, rctolerance, minRes, cumRes; int failed1=0; int failed3=0; @@ -876,7 +876,7 @@ ResCheckSimNodes(celldef, resisdata) */ if (ResOptionsFlags & ResOpt_FastHenry) { - ResPrintReference(ResFHFile, ResTranList, celldef); + ResPrintReference(ResFHFile, ResRDevList, celldef); } for (node = ResOriginalNodes; node != NULL; node=node->nextnode) @@ -913,11 +913,11 @@ ResCheckSimNodes(celldef, resisdata) continue; total++; - ResSortByGate(&node->firstTran); - /* Find largest SD transistor connected to node. */ + ResSortByGate(&node->firstDev); + /* Find largest SD device connected to node. */ minRes = FLT_MAX; - gparams.rg_tranloc = (Point *) NULL; + gparams.rg_devloc = (Point *) NULL; gparams.rg_status = FALSE; gparams.rg_nodecap = node->capacitance; @@ -925,10 +925,10 @@ ResCheckSimNodes(celldef, resisdata) /* to identify which tile the drivepoint is on. */ gparams.rg_ttype = node->rs_ttype; - for (ptr = node->firstTran; ptr != NULL; ptr=ptr->nextTran) + for (ptr = node->firstDev; ptr != NULL; ptr=ptr->nextDev) { - RTran *t1; - RTran *t2; + RDev *t1; + RDev *t2; if (ptr->terminal == GATE) { @@ -936,14 +936,14 @@ ResCheckSimNodes(celldef, resisdata) } else { - /* get cumulative resistance of all transistors */ + /* get cumulative resistance of all devices */ /* with same connections. */ - cumRes = ptr->thisTran->resistance; - t1 = ptr->thisTran; - for (; ptr->nextTran != NULL; ptr = ptr->nextTran) + cumRes = ptr->thisDev->resistance; + t1 = ptr->thisDev; + for (; ptr->nextDev != NULL; ptr = ptr->nextDev) { - t1 = ptr->thisTran; - t2 = ptr->nextTran->thisTran; + t1 = ptr->thisDev; + t2 = ptr->nextDev->thisDev; if (t1->gate != t2->gate) break; if ((t1->source != t2->source || t1->drain != t2->drain) && @@ -964,7 +964,7 @@ ResCheckSimNodes(celldef, resisdata) if (minRes > cumRes) { minRes = cumRes; - gparams.rg_tranloc = &t1->location; + gparams.rg_devloc = &t1->location; gparams.rg_ttype = t1->rs_ttype; } } @@ -985,26 +985,26 @@ ResCheckSimNodes(celldef, resisdata) } if (node->status & DRIVELOC) { - gparams.rg_tranloc = &node->drivepoint; + gparams.rg_devloc = &node->drivepoint; gparams.rg_status |= DRIVEONLY; } if (node->status & PORTNODE) { - /* The node is a port, not a transistor, so make */ + /* The node is a port, not a device, so make */ /* sure rg_ttype is set accordingly. */ gparams.rg_ttype = node->rs_ttype; } } - if (gparams.rg_tranloc == NULL && node->status & FORCE) + if (gparams.rg_devloc == NULL && node->status & FORCE) { TxError("Node %s has force label but no drive point or " - "driving transistor\n",node->name); + "driving device\n",node->name); } - if (minRes == FLT_MAX || gparams.rg_tranloc == NULL) + if (minRes == FLT_MAX || gparams.rg_devloc == NULL) { continue; } - gparams.rg_bigtranres = (int)minRes*OHMSTOMILLIOHMS; + gparams.rg_bigdevres = (int)minRes*OHMSTOMILLIOHMS; if (rctol == 0.0 || tol == 0.0) { ftolerance = 0.0; @@ -1017,7 +1017,7 @@ ResCheckSimNodes(celldef, resisdata) } /* - * Is the transistor resistance greater than the lumped node + * Is the device resistance greater than the lumped node * resistance? If so, extract net. */ @@ -1052,20 +1052,20 @@ ResCheckSimNodes(celldef, resisdata) } } #ifdef PARANOID - ResSanityChecks(node->name,ResResList,ResNodeList,ResTransList); + ResSanityChecks(node->name,ResResList,ResNodeList,ResDevList); #endif ResCleanUpEverything(); } } /* - * Print out all transistors which have had at least one terminal changed + * Print out all device which have had at least one terminal changed * by resistance extraction. */ if (ResOptionsFlags & ResOpt_DoExtFile) { - ResPrintExtTran(ResExtFile,ResTranList); + ResPrintExtDev(ResExtFile,ResRDevList); } /* @@ -1132,21 +1132,21 @@ ResCheckSimNodes(celldef, resisdata) *------------------------------------------------------------------------- * * ResFixUpConnections-- Changes the connection to a terminal of the sim - * transistor. The new name is formed by appending .t# to the old name. + * device. The new name is formed by appending .t# to the old name. * The new name is added to the hash table of node names. * * Results:none * * Side Effects: Allocates new ResSimNodes. Modifies the terminal connections - * of sim Transistors. + * of sim Devices. * *------------------------------------------------------------------------- */ void -ResFixUpConnections(simTran, layoutTran, simNode, nodename) - RTran *simTran; - resTransistor *layoutTran; +ResFixUpConnections(simDev, layoutDev, simNode, nodename) + RDev *simDev; + resDevice *layoutDev; ResSimNode *simNode; char *nodename; @@ -1162,12 +1162,12 @@ ResFixUpConnections(simTran, layoutTran, simNode, nodename) { return; } - if (simTran->layout == NULL) + if (simDev->layout == NULL) { - layoutTran->rt_status |= RES_TRAN_SAVE; - simTran->layout = layoutTran; + layoutDev->rd_status |= RES_DEV_SAVE; + simDev->layout = layoutDev; } - simTran->status |= TRUE; + simDev->status |= TRUE; if (strcmp(nodename,oldnodename) != 0) { strcpy(oldnodename,nodename); @@ -1175,11 +1175,11 @@ ResFixUpConnections(simTran, layoutTran, simNode, nodename) (void)sprintf(newname,"%s%s%d",nodename,".t",resNodeNum++); notdecremented = TRUE; - if (simTran->gate == simNode) + if (simDev->gate == simNode) { - if ((gate=layoutTran->rt_gate) != NULL) + if ((gate=layoutDev->rd_fet_gate) != NULL) { - /* cosmetic addition: If the layout tran already has a */ + /* cosmetic addition: If the layout device already has a */ /* name, the new one won't be used, so we decrement resNodeNum */ if (gate->rn_name != NULL) { @@ -1187,8 +1187,8 @@ ResFixUpConnections(simTran, layoutTran, simNode, nodename) notdecremented = FALSE; } - ResFixTranName(newname,GATE,simTran,gate); - gate->rn_name = simTran->gate->name; + ResFixDevName(newname,GATE,simDev,gate); + gate->rn_name = simDev->gate->name; (void)sprintf(newname,"%s%s%d",nodename,".t",resNodeNum++); } else @@ -1196,24 +1196,24 @@ ResFixUpConnections(simTran, layoutTran, simNode, nodename) TxError("Missing gate connection\n"); } } - if (simTran->source == simNode) + if (simDev->source == simNode) { - if (simTran->drain == simNode) + if (simDev->drain == simNode) { - if ((source=layoutTran->rt_source) && - (drain=layoutTran->rt_drain)) + if ((source=layoutDev->rd_fet_source) && + (drain=layoutDev->rd_fet_drain)) { if (source->rn_name != NULL && notdecremented) { resNodeNum--; notdecremented = FALSE; } - ResFixTranName(newname,SOURCE,simTran,source); - source->rn_name = simTran->source->name; + ResFixDevName(newname,SOURCE,simDev,source); + source->rn_name = simDev->source->name; (void)sprintf(newname,"%s%s%d",nodename,".t",resNodeNum++); if (drain->rn_name != NULL) resNodeNum--; - ResFixTranName(newname,DRAIN,simTran,drain); - drain->rn_name = simTran->drain->name; + ResFixDevName(newname,DRAIN,simDev,drain); + drain->rn_name = simDev->drain->name; /* one to each */ } else @@ -1223,9 +1223,9 @@ ResFixUpConnections(simTran, layoutTran, simNode, nodename) } else { - if (source=layoutTran->rt_source) + if (source=layoutDev->rd_fet_source) { - if (drain=layoutTran->rt_drain) + if (drain=layoutDev->rd_fet_drain) { if (source != drain) { @@ -1244,10 +1244,10 @@ ResFixUpConnections(simTran, layoutTran, simNode, nodename) drain = source; } } - layoutTran->rt_drain = (resNode *)NULL; + layoutDev->rd_fet_drain = (resNode *)NULL; if (source->rn_name != NULL) resNodeNum--; - ResFixTranName(newname,SOURCE,simTran,source); - source->rn_name = simTran->source->name; + ResFixDevName(newname,SOURCE,simDev,source); + source->rn_name = simDev->source->name; } else { @@ -1256,8 +1256,8 @@ ResFixUpConnections(simTran, layoutTran, simNode, nodename) resNodeNum--; notdecremented = FALSE; } - ResFixTranName(newname,SOURCE,simTran,source); - source->rn_name = simTran->source->name; + ResFixDevName(newname,SOURCE,simDev,source); + source->rn_name = simDev->source->name; } } @@ -1267,11 +1267,11 @@ ResFixUpConnections(simTran, layoutTran, simNode, nodename) } } } - else if (simTran->drain == simNode) + else if (simDev->drain == simNode) { - if (source=layoutTran->rt_source) + if (source=layoutDev->rd_fet_source) { - if (drain=layoutTran->rt_drain) + if (drain=layoutDev->rd_fet_drain) { if (drain != source) { @@ -1290,14 +1290,14 @@ ResFixUpConnections(simTran, layoutTran, simNode, nodename) drain = source; } } - layoutTran->rt_source = (resNode *) NULL; + layoutDev->rd_fet_source = (resNode *) NULL; if (drain->rn_name != NULL) { resNodeNum--; notdecremented = FALSE; } - ResFixTranName(newname, DRAIN, simTran, drain); - drain->rn_name = simTran->drain->name; + ResFixDevName(newname, DRAIN, simDev, drain); + drain->rn_name = simDev->drain->name; } else { @@ -1306,8 +1306,8 @@ ResFixUpConnections(simTran, layoutTran, simNode, nodename) resNodeNum--; notdecremented = FALSE; } - ResFixTranName(newname,DRAIN,simTran,source); - source->rn_name = simTran->drain->name; + ResFixDevName(newname,DRAIN,simDev,source); + source->rn_name = simDev->drain->name; } } else @@ -1325,27 +1325,27 @@ ResFixUpConnections(simTran, layoutTran, simNode, nodename) /* *------------------------------------------------------------------------- * - * ResFixTranName-- Moves transistor connection to new node. + * ResFixDevName-- Moves device connection to new node. * * Results: * None. * - * Side Effects: May create a new node. Creates a new transistor pointer. + * Side Effects: May create a new node. Creates a new device pointer. * *------------------------------------------------------------------------- */ void -ResFixTranName(line,type,transistor,layoutnode) +ResFixDevName(line,type,device,layoutnode) char line[]; int type; - RTran *transistor; + RDev *device; resNode *layoutnode; { HashEntry *entry; ResSimNode *node; - tranPtr *tptr; + devPtr *tptr; if (layoutnode->rn_name != NULL) { @@ -1358,24 +1358,24 @@ ResFixTranName(line,type,transistor,layoutnode) entry = HashFind(&ResNodeTable,line); node = ResInitializeNode(entry); } - tptr = (tranPtr *) mallocMagic((unsigned) (sizeof(tranPtr))); - tptr->thisTran = transistor; - tptr->nextTran = node->firstTran; - node->firstTran = tptr; + tptr = (devPtr *) mallocMagic((unsigned) (sizeof(devPtr))); + tptr->thisDev = device; + tptr->nextDev = node->firstDev; + node->firstDev = tptr; tptr->terminal = type; switch(type) { case GATE: - node->oldname = transistor->gate->name; - transistor->gate = node; + node->oldname = device->gate->name; + device->gate = node; break; case SOURCE: - node->oldname = transistor->source->name; - transistor->source = node; + node->oldname = device->source->name; + device->source = node; break; case DRAIN: - node->oldname = transistor->drain->name; - transistor->drain = node; + node->oldname = device->drain->name; + device->drain = node; break; default: TxError("Bad Terminal Specifier\n"); @@ -1387,59 +1387,59 @@ ResFixTranName(line,type,transistor,layoutnode) /* *------------------------------------------------------------------------- * - * ResSortByGate--sorts transistor pointers whose terminal field is either + * ResSortByGate--sorts device pointers whose terminal field is either * drain or source by gate node number, then by drain (source) number. - * This places transistors with identical connections next to one + * This places devices with identical connections next to one * another. * * Results: none * - * Side Effects: modifies order of transistors + * Side Effects: modifies order of devices * *------------------------------------------------------------------------- */ void -ResSortByGate(TranpointerList) - tranPtr **TranpointerList; +ResSortByGate(DevpointerList) + devPtr **DevpointerList; { int changed=TRUE; int localchange=TRUE; - tranPtr *working, *last=NULL, *current, *gatelist=NULL; + devPtr *working, *last=NULL, *current, *gatelist=NULL; - working = *TranpointerList; + working = *DevpointerList; while (working != NULL) { if (working->terminal == GATE) { current = working; - working = working->nextTran; + working = working->nextDev; if (last == NULL) { - *TranpointerList = working; + *DevpointerList = working; } else { - last->nextTran = working; + last->nextDev = working; } - current->nextTran = gatelist; + current->nextDev = gatelist; gatelist = current; } else { last = working; - working = working->nextTran; + working = working->nextDev; } } while (changed == TRUE) { changed = localchange = FALSE; - working = *TranpointerList; + working = *DevpointerList; last = NULL; - while (working != NULL && (current = working->nextTran) != NULL) + while (working != NULL && (current = working->nextDev) != NULL) { - RTran *w = working->thisTran; - RTran *c = current->thisTran; + RDev *w = working->thisDev; + RDev *c = current->thisDev; if (w->gate > c->gate) { @@ -1466,7 +1466,7 @@ ResSortByGate(TranpointerList) else { last = working; - working = working->nextTran; + working = working->nextDev; continue; } if (localchange) @@ -1474,31 +1474,31 @@ ResSortByGate(TranpointerList) localchange = FALSE; if (last == NULL) { - *TranpointerList = current; + *DevpointerList = current; } else { - last->nextTran = current; + last->nextDev = current; } - working->nextTran = current->nextTran; - current->nextTran = working; + working->nextDev = current->nextDev; + current->nextDev = working; last = current; } } } if (working == NULL) { - *TranpointerList = gatelist; + *DevpointerList = gatelist; } else { - if (working->nextTran != NULL) + if (working->nextDev != NULL) { - TxError("Bad Transistor pointer in sort\n"); + TxError("Bad Device pointer in sort\n"); } else { - working->nextTran = gatelist; + working->nextDev = gatelist; } } } @@ -1527,7 +1527,7 @@ ResWriteLumpFile(node) if (gparams.rg_nodecap != 0) { lumpedres = (int)((gparams.rg_Tdi/gparams.rg_nodecap - -(float)(gparams.rg_bigtranres))/OHMSTOMILLIOHMS); + -(float)(gparams.rg_bigdevres))/OHMSTOMILLIOHMS); } else { @@ -1619,36 +1619,36 @@ ResWriteExtFile(celldef, node, tol, rctol, nidx, eidx) float tol, rctol; int *nidx, *eidx; { - float RCtran; + float RCdev; char *cp, newname[MAXNAME]; - tranPtr *ptr; - resTransistor *layoutFet, *ResGetTransistor(); + devPtr *ptr; + resDevice *layoutDev, *ResGetDevice(); - RCtran = gparams.rg_bigtranres * gparams.rg_nodecap; + RCdev = gparams.rg_bigdevres * gparams.rg_nodecap; if (tol == 0.0 ||(node->status & FORCE) || (ResOptionsFlags & ResOpt_ExtractAll)|| (ResOptionsFlags & ResOpt_Simplify)==0|| - (rctol+1)*RCtran < rctol*gparams.rg_Tdi) + (rctol+1)*RCdev < rctol*gparams.rg_Tdi) { ASSERT(gparams.rg_Tdi != -1,"ResWriteExtFile"); (void)sprintf(newname,"%s",node->name); cp = newname+strlen(newname)-1; if (*cp == '!' || *cp == '#') *cp = '\0'; - if ((rctol+1)*RCtran < rctol*gparams.rg_Tdi || + if ((rctol+1)*RCdev < rctol*gparams.rg_Tdi || (ResOptionsFlags & ResOpt_Tdi) == 0) { if ((ResOptionsFlags & (ResOpt_RunSilent|ResOpt_Tdi)) == ResOpt_Tdi) { TxError("Adding %s; Tnew = %.2fns,Told = %.2fns\n", - node->name,gparams.rg_Tdi/Z_TO_N, RCtran/Z_TO_N); + node->name,gparams.rg_Tdi/Z_TO_N, RCdev/Z_TO_N); } } - for (ptr = node->firstTran; ptr != NULL; ptr=ptr->nextTran) + for (ptr = node->firstDev; ptr != NULL; ptr=ptr->nextDev) { - if (layoutFet = ResGetTransistor(&ptr->thisTran->location)) + if (layoutDev = ResGetDevice(&ptr->thisDev->location)) { - ResFixUpConnections(ptr->thisTran,layoutFet,node,newname); + ResFixUpConnections(ptr->thisDev,layoutDev,node,newname); } } if (ResOptionsFlags & ResOpt_DoExtFile) diff --git a/resis/ResSimple.c b/resis/ResSimple.c index 2e55b033..31b3b3cb 100644 --- a/resis/ResSimple.c +++ b/resis/ResSimple.c @@ -45,7 +45,7 @@ int resRemoveLoops = FALSE; /* Forward declarations */ -extern void ResMoveTransistors(); +extern void ResMoveDevices(); extern void ResAddResistorToList(); @@ -58,7 +58,7 @@ extern void ResAddResistorToList(); * * Results: none * - * Side Effects: Can eliminate nodes and resistors, and move transistors from + * Side Effects: Can eliminate nodes and resistors, and move devices from * one node to another. * *------------------------------------------------------------------------- @@ -233,7 +233,7 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance) } /* - Two resistors in series? Combine them and move transistors to + Two resistors in series? Combine them and move devices to appropriate end. */ else if (numdrive+numreceive == 2 && @@ -260,10 +260,10 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance) /* make one big resistor out of two little ones, eliminating - the current node. Transistors connected to this node are + the current node. Devices connected to this node are moved to either end depending on their resistance. */ - ResMoveTransistors(node,otherNode); + ResMoveDevices(node,otherNode); otherNode->rn_noderes = MIN(node->rn_noderes,otherNode->rn_noderes); node2->rn_float.rn_area += resistor1->rr_value*node->rn_float.rn_area/(resistor1->rr_value+resistor2->rr_value); node1->rn_float.rn_area += resistor2->rr_value*node->rn_float.rn_area/(resistor1->rr_value+resistor2->rr_value); @@ -380,34 +380,34 @@ ResSimplifyNet(nodelist,biglist,reslist,tolerance) /* *------------------------------------------------------------------------- * - * ResMoveTransistors-- move transistors from one node1 to node2 + * ResMoveDevices-- move devices from one node1 to node2 * * Results: none * - * Side Effects: Changes transistor connections and node tElements. + * Side Effects: Changes device connections and node tElements. * *------------------------------------------------------------------------- */ void -ResMoveTransistors(node1,node2) +ResMoveDevices(node1,node2) resNode *node1,*node2; { - tElement *tranptr,*oldptr; - resTransistor *transistor; + tElement *devptr,*oldptr; + resDevice *device; - tranptr = node1->rn_te; - while (tranptr != NULL) + devptr = node1->rn_te; + while (devptr != NULL) { - transistor = tranptr->te_thist; - oldptr = tranptr; - tranptr = tranptr->te_nextt; - if (transistor->rt_status & RES_TRAN_PLUG) + device = devptr->te_thist; + oldptr = devptr; + devptr = devptr->te_nextt; + if (device->rd_status & RES_DEV_PLUG) { - if (((ResPlug *)(transistor))->rpl_node == node1) + if (((ResPlug *)(device))->rpl_node == node1) { - ((ResPlug *)(transistor))->rpl_node = node2; + ((ResPlug *)(device))->rpl_node = node2; } else { @@ -416,21 +416,21 @@ ResMoveTransistors(node1,node2) } else { - if (transistor->rt_gate == node1) + if (device->rd_fet_gate == node1) { - transistor->rt_gate = node2; + device->rd_fet_gate = node2; } - else if (transistor->rt_source == node1) + else if (device->rd_fet_source == node1) { - transistor->rt_source = node2; + device->rd_fet_source = node2; } - else if (transistor->rt_drain == node1) + else if (device->rd_fet_drain == node1) { - transistor->rt_drain = node2; + device->rd_fet_drain = node2; } else { - TxError("Missing Transistor connection in squish routines at %d, %d\n",node1->rn_loc.p_x,node1->rn_loc.p_y); + TxError("Missing Device connection in squish routines at %d, %d\n",node1->rn_loc.p_x,node1->rn_loc.p_y); } } oldptr->te_nextt = node2->rn_te; @@ -728,7 +728,7 @@ ResCalculateChildCapacitance(me) { RCDelayStuff *myC; resElement *workingRes; - resTransistor *tran; + resDevice *dev; float childcap; tElement *tptr; int t; @@ -749,16 +749,16 @@ ResCalculateChildCapacitance(me) /* get capacitance for all connected gates */ for (tptr = me->rn_te; tptr != NULL; tptr = tptr->te_nextt) { - tran = tptr->te_thist; - t = TiGetType(tran->rt_tile); - if (tran->rt_gate == me) + dev = tptr->te_thist; + t = TiGetType(dev->rd_tile); + if (dev->rd_fet_gate == me) { devptr = ExtCurStyle->exts_device[t]; myC->rc_Cdownstream += - tran->rt_length* - tran->rt_width* + dev->rd_length* + dev->rd_width* devptr->exts_deviceGateCap+ - (tran->rt_width+tran->rt_width)* + (dev->rd_width+dev->rd_width)* devptr->exts_deviceSDCap; } @@ -917,7 +917,7 @@ ResDoSimplify(tolerance,rctol,goodies) goodies->rg_maxres = bigres; #ifdef PARANOID - ResSanityChecks("ExtractSingleNet",ResResList,ResNodeList,ResTransList); + ResSanityChecks("ExtractSingleNet",ResResList,ResNodeList,ResDevList); #endif /* Is extracted network still greater than the tolerance? */ @@ -958,7 +958,7 @@ ResDoSimplify(tolerance,rctol,goodies) { goodies->rg_nodecap = totalcap; ResCalculateTDi(ResOriginNode,(resResistor *)NULL, - goodies->rg_bigtranres); + goodies->rg_bigdevres); goodies->rg_Tdi = rc->rc_Tdi; slownode = ResNodeList; for (node = ResNodeList; node != NULL; node = node->rn_more) @@ -984,7 +984,7 @@ ResDoSimplify(tolerance,rctol,goodies) { goodies->rg_Tdi = 0; } - if ((rctol+1)*goodies->rg_bigtranres*goodies->rg_nodecap > + if ((rctol+1)*goodies->rg_bigdevres*goodies->rg_nodecap > rctol*goodies->rg_Tdi && (ResOptionsFlags & ResOpt_Tdi) && goodies->rg_Tdi != -1) @@ -1025,7 +1025,7 @@ ResDoSimplify(tolerance,rctol,goodies) rctol != 0) { ResPruneTree(ResOriginNode, - (rctol+1)*goodies->rg_bigtranres*goodies->rg_nodecap/rctol, + (rctol+1)*goodies->rg_bigdevres*goodies->rg_nodecap/rctol, &ResNodeList,&ResNodeQueue,&ResResList); } ResOriginNode->rn_status &= ~MARKED; @@ -1089,8 +1089,8 @@ ResSetPathRes() } if (ResOriginNode == NULL) { - resTransistor *res = ResGetTransistor(gparams.rg_tranloc); - ResOriginNode = res->rt_source; + resDevice *res = ResGetDevice(gparams.rg_devloc); + ResOriginNode = res->rd_fet_source; ResOriginNode->rn_why = RES_NODE_ORIGIN; ResOriginNode->rn_noderes = 0; } diff --git a/resis/ResUtils.c b/resis/ResUtils.c index e292a3fb..fe8258f2 100644 --- a/resis/ResUtils.c +++ b/resis/ResUtils.c @@ -122,8 +122,8 @@ ResEach(tile, pNum, arg) * ResAddPlumbing-- Each tile is a tileJunk structure associated with it * to keep track of various things used by the extractor. ResAddPlumbing * adds this structure and sets the tile's ClientData field to point to it. - * If the tile is a transistor, then a transistor structure is also added; - * all connected transistor tiles are enumerated and their transistorList + * If the tile is a device, then a device structure is also added; + * all connected device tiles are enumerated and their deviceList * fields set to the new structure. * * Results: always returns 0 @@ -140,372 +140,379 @@ ResAddPlumbing(tile, arg) { tileJunk *Junk,*junk2; - static Stack *resTransStack=NULL; + static Stack *resDevStack=NULL; TileType loctype, t1; Tile *tp1,*tp2,*source; - resTransistor *resFet; + resDevice *resDev; ExtDevice *devptr; - if (resTransStack == NULL) - { - resTransStack = StackNew(64); - } + if (resDevStack == NULL) + resDevStack = StackNew(64); + if (tile->ti_client == (ClientData) CLIENTDEFAULT) { if (IsSplit(tile)) - { loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile); - } else loctype = TiGetTypeExact(tile); - devptr = ExtCurStyle->exts_device[loctype]; - junk2 = resAddField(tile); - if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), loctype)) - { - resFet = (resTransistor *) mallocMagic((unsigned)(sizeof(resTransistor))); - { - int i; - for (i=0; i != RT_TERMCOUNT;i++) - resFet->rt_terminals[i] = (resNode *) NULL; - } - resFet->rt_tile = tile; - resFet->rt_inside.r_ll.p_x = LEFT(tile); - resFet->rt_inside.r_ll.p_y = BOTTOM(tile); - resFet->rt_inside.r_ur.p_x = RIGHT(tile); - resFet->rt_inside.r_ur.p_y = TOP(tile); - resFet->rt_trantype = loctype; - resFet->rt_tiles = 0; - resFet->rt_length = 0; - resFet->rt_width = 0; - resFet->rt_perim = 0; - resFet->rt_area = 0; - resFet->rt_status = 0; - resFet->rt_nextTran = (resTransistor *) *arg; - *arg = (ClientData)resFet; - junk2->transistorList = resFet; - junk2->tj_status |= RES_TILE_TRAN; - - source = NULL; - /* find diffusion (if present) to be source contact */ + devptr = ExtCurStyle->exts_device[loctype]; + junk2 = resAddField(tile); + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask), loctype)) + { + int i, nterms; - /* top */ - for (tp2= RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2)) - { - if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), + /* Count SD terminals of the device */ + nterms = 0; + for (i = 0; ; i++) + { + if (TTMaskIsZero(&(devptr->exts_deviceSDTypes[i]))) break; + nterms++; + } + if (nterms < devptr->exts_deviceSDCount) + nterms = devptr->exts_deviceSDCount; + + /* resDev terminals includes device identifier (e.g., gate) and + * substrate, so add two to nterms. + */ + nterms += 2; + + resDev = (resDevice *) mallocMagic((unsigned)(sizeof(resDevice))); + resDev->rd_nterms = nterms; + resDev->rd_terminals = (resNode **) mallocMagic(nterms * sizeof(resNode *)); + for (i=0; i != nterms;i++) + resDev->rd_terminals[i] = (resNode *) NULL; + + resDev->rd_tile = tile; + resDev->rd_inside.r_ll.p_x = LEFT(tile); + resDev->rd_inside.r_ll.p_y = BOTTOM(tile); + resDev->rd_inside.r_ur.p_x = RIGHT(tile); + resDev->rd_inside.r_ur.p_y = TOP(tile); + resDev->rd_devtype = loctype; + resDev->rd_tiles = 0; + resDev->rd_length = 0; + resDev->rd_width = 0; + resDev->rd_perim = 0; + resDev->rd_area = 0; + resDev->rd_status = 0; + resDev->rd_nextDev = (resDevice *) *arg; + *arg = (ClientData)resDev; + junk2->deviceList = resDev; + junk2->tj_status |= RES_TILE_DEV; + + source = NULL; + /* find diffusion (if present) to be source contact */ + + /* top */ + for (tp2= RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2)) + { + if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetBottomType(tp2)) - { - junk2->sourceEdge |= TOPEDGE; - source = tp2; - Junk = resAddField(source); - Junk->tj_status |= RES_TILE_SD; - break; - } - } + { + junk2->sourceEdge |= TOPEDGE; + source = tp2; + Junk = resAddField(source); + Junk->tj_status |= RES_TILE_SD; + break; + } + } - /*bottom*/ - if (source == NULL) - for (tp2= LB(tile); LEFT(tp2) < RIGHT(tile); tp2 = TR(tp2)) - { - if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), + /*bottom*/ + if (source == NULL) + for (tp2= LB(tile); LEFT(tp2) < RIGHT(tile); tp2 = TR(tp2)) + { + if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetTopType(tp2)) - { - junk2->sourceEdge |= BOTTOMEDGE; - source = tp2; - Junk = resAddField(source); - Junk->tj_status |= RES_TILE_SD; - break; - } - } + { + junk2->sourceEdge |= BOTTOMEDGE; + source = tp2; + Junk = resAddField(source); + Junk->tj_status |= RES_TILE_SD; + break; + } + } - /*right*/ - if (source == NULL) - for (tp2= TR(tile); TOP(tp2) > BOTTOM(tile); tp2 = LB(tp2)) - { - if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), + /*right*/ + if (source == NULL) + for (tp2= TR(tile); TOP(tp2) > BOTTOM(tile); tp2 = LB(tp2)) + { + if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetLeftType(tp2)) - { - junk2->sourceEdge |= RIGHTEDGE; - source = tp2; - Junk = resAddField(source); - Junk->tj_status |= RES_TILE_SD; - break; - } - } + { + junk2->sourceEdge |= RIGHTEDGE; + source = tp2; + Junk = resAddField(source); + Junk->tj_status |= RES_TILE_SD; + break; + } + } - /*left*/ - if (source == NULL) - for (tp2= BL(tile); BOTTOM(tp2) < TOP(tile); tp2 = RT(tp2)) - { - if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), + /*left*/ + if (source == NULL) + for (tp2= BL(tile); BOTTOM(tp2) < TOP(tile); tp2 = RT(tp2)) + { + if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), TiGetRightType(tp2)) - { - source = tp2; - Junk = resAddField(source); - Junk->tj_status |= RES_TILE_SD; - junk2->sourceEdge |= LEFTEDGE; - break; - } - } + { + source = tp2; + Junk = resAddField(source); + Junk->tj_status |= RES_TILE_SD; + junk2->sourceEdge |= LEFTEDGE; + break; + } + } - /* We need to know whether a given diffusion tile connects to - * the source or to the drain of a transistor. A single - * diffusion tile is marked, and all connecting diffusion tiles - * are enumerated and called the source. Any other SD tiles - * are assumed to be the drain. BUG: this does not work - * correctly with multi SD structures. - */ + /* We need to know whether a given diffusion tile connects to + * the source or to the drain of a device. A single + * diffusion tile is marked, and all connecting diffusion tiles + * are enumerated and called the source. Any other SD tiles + * are assumed to be the drain. BUG: this does not work + * correctly with multi SD structures. + */ - if (source != (Tile *) NULL) - { - STACKPUSH((ClientData) (source),resTransStack); - } - while (!StackEmpty(resTransStack)) - { - tp1 = (Tile *) STACKPOP(resTransStack); - if (IsSplit(tp1)) - { - t1 = (SplitSide(tp1)) ? SplitRightType(tp1) : + if (source != (Tile *) NULL) + { + STACKPUSH((ClientData) (source),resDevStack); + } + while (!StackEmpty(resDevStack)) + { + tp1 = (Tile *) STACKPOP(resDevStack); + if (IsSplit(tp1)) + { + t1 = (SplitSide(tp1)) ? SplitRightType(tp1) : SplitLeftType(tp1); - } - else - t1 = TiGetTypeExact(tp1); + } + else + t1 = TiGetTypeExact(tp1); - /* top */ - for (tp2= RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2)) - { - if (TiGetBottomType(tp2) == t1) - { - tileJunk *j= resAddField(tp2); - if ((j->tj_status & RES_TILE_SD) ==0) - { - j->tj_status |= RES_TILE_SD; - STACKPUSH((ClientData)tp2,resTransStack); - } - } - } - /*bottom*/ - for (tp2= LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2)) - { - if (TiGetTopType(tp2) == t1) - { - tileJunk *j= resAddField(tp2); - if ((j->tj_status & RES_TILE_SD) == 0) - { - j->tj_status |= RES_TILE_SD; - STACKPUSH((ClientData) (tp2),resTransStack); - } - } - } - /*right*/ - for (tp2= TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2)) - { - if (TiGetLeftType(tp2) == t1) - { - tileJunk *j= resAddField(tp2); - if ((j->tj_status & RES_TILE_SD) == 0) - { - j->tj_status |= RES_TILE_SD; - STACKPUSH((ClientData) (tp2),resTransStack); - } - } - } - /*left*/ - for (tp2= BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2)) - { - if (TiGetRightType(tp2) == t1) - { - tileJunk *j= resAddField(tp2); - if ((j->tj_status & RES_TILE_SD) == 0) - { - j->tj_status |= RES_TILE_SD; - STACKPUSH((ClientData) (tp2),resTransStack); - } - } - } - } - /* find rest of transistor; search for source edges */ - - STACKPUSH((ClientData) (tile), resTransStack); - while (!StackEmpty(resTransStack)) - { - tileJunk *j0; - - tp1= (Tile *) STACKPOP(resTransStack); - if (IsSplit(tp1)) + /* top */ + for (tp2= RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2)) + { + if (TiGetBottomType(tp2) == t1) { - t1 = (SplitSide(tp1)) ? SplitRightType(tp1) : + tileJunk *j= resAddField(tp2); + if ((j->tj_status & RES_TILE_SD) ==0) + { + j->tj_status |= RES_TILE_SD; + STACKPUSH((ClientData)tp2,resDevStack); + } + } + } + /*bottom*/ + for (tp2= LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2)) + { + if (TiGetTopType(tp2) == t1) + { + tileJunk *j= resAddField(tp2); + if ((j->tj_status & RES_TILE_SD) == 0) + { + j->tj_status |= RES_TILE_SD; + STACKPUSH((ClientData) (tp2),resDevStack); + } + } + } + /*right*/ + for (tp2= TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2)) + { + if (TiGetLeftType(tp2) == t1) + { + tileJunk *j= resAddField(tp2); + if ((j->tj_status & RES_TILE_SD) == 0) + { + j->tj_status |= RES_TILE_SD; + STACKPUSH((ClientData) (tp2),resDevStack); + } + } + } + /*left*/ + for (tp2= BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2)) + { + if (TiGetRightType(tp2) == t1) + { + tileJunk *j= resAddField(tp2); + if ((j->tj_status & RES_TILE_SD) == 0) + { + j->tj_status |= RES_TILE_SD; + STACKPUSH((ClientData) (tp2),resDevStack); + } + } + } + } + + /* find rest of device; search for source edges */ + + STACKPUSH((ClientData) (tile), resDevStack); + while (!StackEmpty(resDevStack)) + { + tileJunk *j0; + + tp1= (Tile *) STACKPOP(resDevStack); + if (IsSplit(tp1)) + { + t1 = (SplitSide(tp1)) ? SplitRightType(tp1) : SplitLeftType(tp1); - } - else - t1 = TiGetTypeExact(tp1); + } + else + t1 = TiGetTypeExact(tp1); - devptr = ExtCurStyle->exts_device[t1]; - j0 = (tileJunk *) tp1->ti_client; - /* top */ - for (tp2= RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2)) - { - if ((TiGetBottomType(tp2) == t1) && + devptr = ExtCurStyle->exts_device[t1]; + j0 = (tileJunk *) tp1->ti_client; + /* top */ + for (tp2= RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2)) + { + if ((TiGetBottomType(tp2) == t1) && (tp2->ti_client == (ClientData) CLIENTDEFAULT)) - { - Junk = resAddField(tp2); - STACKPUSH((ClientData)(tp2),resTransStack); - Junk->transistorList = resFet; - Junk->tj_status |= RES_TILE_TRAN; + { + Junk = resAddField(tp2); + STACKPUSH((ClientData)(tp2),resDevStack); + Junk->deviceList = resDev; + Junk->tj_status |= RES_TILE_DEV; - } - else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), - TiGetBottomType(tp2)) - { - Junk = resAddField(tp2); - if (Junk->tj_status & RES_TILE_SD) - { - j0->sourceEdge |= TOPEDGE; - } - } - } - /*bottom*/ - for (tp2= LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2)) - { - if ((TiGetTopType(tp2) == t1) && - (tp2->ti_client == (ClientData) CLIENTDEFAULT)) - { - Junk = resAddField(tp2); - STACKPUSH((ClientData)(tp2),resTransStack); - Junk->transistorList = resFet; - Junk->tj_status |= RES_TILE_TRAN; - } - else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), - TiGetTopType(tp2)) - { - Junk = resAddField(tp2); - if (Junk->tj_status & RES_TILE_SD) - { - j0->sourceEdge |= BOTTOMEDGE; - } - } - } - /*right*/ - for (tp2= TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2)) - { - if ((TiGetLeftType(tp2) == t1) && - (tp2->ti_client == (ClientData) CLIENTDEFAULT)) - { - Junk = resAddField(tp2); - STACKPUSH((ClientData)(tp2),resTransStack); - Junk->transistorList = resFet; - Junk->tj_status |= RES_TILE_TRAN; - } - else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), - TiGetLeftType(tp2)) - { - Junk = resAddField(tp2); - if (Junk->tj_status & RES_TILE_SD) - { - j0->sourceEdge |= RIGHTEDGE; - } - } - } - /*left*/ - for (tp2= BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2)) - { - if ((TiGetRightType(tp2) == t1) && - (tp2->ti_client == (ClientData) CLIENTDEFAULT)) - { - Junk = resAddField(tp2); - STACKPUSH((ClientData)(tp2),resTransStack); - Junk->transistorList = resFet; - Junk->tj_status |= RES_TILE_TRAN; - } - else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), - TiGetRightType(tp2)) - { - Junk = resAddField(tp2); - if (Junk->tj_status & RES_TILE_SD) - { - j0->sourceEdge |= LEFTEDGE; - } - } - } - } - - /* unmark all tiles marked as being part of source */ - - if (source != (Tile *) NULL) - { - tileJunk *j = (tileJunk *) source->ti_client; - - STACKPUSH((ClientData) (source),resTransStack); - j->tj_status &= ~RES_TILE_SD; - } - while (!StackEmpty(resTransStack)) - { - tp1 = (Tile *) STACKPOP(resTransStack); - if (IsSplit(tp1)) - { - t1 = (SplitSide(tp1)) ? SplitRightType(tp1) : - SplitLeftType(tp1); } - else - t1 = TiGetTypeExact(tp1); + else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), + TiGetBottomType(tp2)) + { + Junk = resAddField(tp2); + if (Junk->tj_status & RES_TILE_SD) + j0->sourceEdge |= TOPEDGE; + } + } + /*bottom*/ + for (tp2= LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2)) + { + if ((TiGetTopType(tp2) == t1) && + (tp2->ti_client == (ClientData) CLIENTDEFAULT)) + { + Junk = resAddField(tp2); + STACKPUSH((ClientData)(tp2),resDevStack); + Junk->deviceList = resDev; + Junk->tj_status |= RES_TILE_DEV; + } + else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), + TiGetTopType(tp2)) + { + Junk = resAddField(tp2); + if (Junk->tj_status & RES_TILE_SD) + j0->sourceEdge |= BOTTOMEDGE; + } + } + /*right*/ + for (tp2= TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2)) + { + if ((TiGetLeftType(tp2) == t1) && + (tp2->ti_client == (ClientData) CLIENTDEFAULT)) + { + Junk = resAddField(tp2); + STACKPUSH((ClientData)(tp2),resDevStack); + Junk->deviceList = resDev; + Junk->tj_status |= RES_TILE_DEV; + } + else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), + TiGetLeftType(tp2)) + { + Junk = resAddField(tp2); + if (Junk->tj_status & RES_TILE_SD) + j0->sourceEdge |= RIGHTEDGE; + } + } + /*left*/ + for (tp2= BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2)) + { + if ((TiGetRightType(tp2) == t1) && + (tp2->ti_client == (ClientData) CLIENTDEFAULT)) + { + Junk = resAddField(tp2); + STACKPUSH((ClientData)(tp2),resDevStack); + Junk->deviceList = resDev; + Junk->tj_status |= RES_TILE_DEV; + } + else if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), + TiGetRightType(tp2)) + { + Junk = resAddField(tp2); + if (Junk->tj_status & RES_TILE_SD) + j0->sourceEdge |= LEFTEDGE; + } + } + } - /* top */ - for (tp2= RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2)) - { - tileJunk *j2 = (tileJunk *) tp2->ti_client; - if (TiGetBottomType(tp2) == t1) - { - if (j2->tj_status & RES_TILE_SD) - { - j2->tj_status &= ~RES_TILE_SD; - STACKPUSH((ClientData) tp2,resTransStack); - } - } - } - /*bottom*/ - for(tp2= LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2)) - { - tileJunk *j2 = (tileJunk *) tp2->ti_client; - if (TiGetTopType(tp2) == t1) - { - if (j2->tj_status & RES_TILE_SD) - { - j2->tj_status &= ~RES_TILE_SD; - STACKPUSH((ClientData) tp2,resTransStack); - } - } - } - /*right*/ - for (tp2= TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2)) - { - tileJunk *j2 = (tileJunk *) tp2->ti_client; - if (TiGetLeftType(tp2) == t1) - { - if (j2->tj_status & RES_TILE_SD) - { - j2->tj_status &= ~RES_TILE_SD; - STACKPUSH((ClientData) tp2,resTransStack); - } - } - } - /*left*/ - for (tp2= BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2)) - { - tileJunk *j2 = (tileJunk *) tp2->ti_client; - if (TiGetRightType(tp2) == t1) - { - if (j2->tj_status & RES_TILE_SD) - { - j2->tj_status &= ~RES_TILE_SD; - STACKPUSH((ClientData) tp2,resTransStack); - } - } - } - } - } - } - return(0); + /* unmark all tiles marked as being part of source */ + + if (source != (Tile *) NULL) + { + tileJunk *j = (tileJunk *) source->ti_client; + + STACKPUSH((ClientData) (source),resDevStack); + j->tj_status &= ~RES_TILE_SD; + } + while (!StackEmpty(resDevStack)) + { + tp1 = (Tile *) STACKPOP(resDevStack); + if (IsSplit(tp1)) + { + t1 = (SplitSide(tp1)) ? SplitRightType(tp1) : + SplitLeftType(tp1); + } + else + t1 = TiGetTypeExact(tp1); + + /* top */ + for (tp2= RT(tp1); RIGHT(tp2) > LEFT(tp1); tp2 = BL(tp2)) + { + tileJunk *j2 = (tileJunk *) tp2->ti_client; + if (TiGetBottomType(tp2) == t1) + { + if (j2->tj_status & RES_TILE_SD) + { + j2->tj_status &= ~RES_TILE_SD; + STACKPUSH((ClientData) tp2,resDevStack); + } + } + } + /*bottom*/ + for(tp2= LB(tp1); LEFT(tp2) < RIGHT(tp1); tp2 = TR(tp2)) + { + tileJunk *j2 = (tileJunk *) tp2->ti_client; + if (TiGetTopType(tp2) == t1) + { + if (j2->tj_status & RES_TILE_SD) + { + j2->tj_status &= ~RES_TILE_SD; + STACKPUSH((ClientData) tp2,resDevStack); + } + } + } + /*right*/ + for (tp2= TR(tp1); TOP(tp2) > BOTTOM(tp1); tp2 = LB(tp2)) + { + tileJunk *j2 = (tileJunk *) tp2->ti_client; + if (TiGetLeftType(tp2) == t1) + { + if (j2->tj_status & RES_TILE_SD) + { + j2->tj_status &= ~RES_TILE_SD; + STACKPUSH((ClientData) tp2,resDevStack); + } + } + } + /*left*/ + for (tp2= BL(tp1); BOTTOM(tp2) < TOP(tp1); tp2 = RT(tp2)) + { + tileJunk *j2 = (tileJunk *) tp2->ti_client; + if (TiGetRightType(tp2) == t1) + { + if (j2->tj_status & RES_TILE_SD) + { + j2->tj_status &= ~RES_TILE_SD; + STACKPUSH((ClientData) tp2,resDevStack); + } + } + } + } + } + } + return(0); } /* @@ -539,39 +546,39 @@ ResRemovePlumbing(tile, arg) /* *------------------------------------------------------------------------- * - * ResPreprocessTransistors-- Given a list of all the transistor tiles and - * a list of all the transistors, this procedure calculates the width and + * ResPreprocessDevices-- Given a list of all the device tiles and + * a list of all the devices, this procedure calculates the width and * length. The width is set equal to the sum of all edges that touch * diffusion divided by 2. The length is the remaining perimeter divided by - * 2*tiles. The perimeter and area fields of transistor structures are also + * 2*tiles. The perimeter and area fields of device structures are also * fixed. * * Results: none * - * Side Effects: sets length and width of transistors. "ResTransTile" + * Side Effects: sets length and width of devices. "ResDevTile" * structures are freed. * *------------------------------------------------------------------------- */ void -ResPreProcessTransistors(TileList, TransistorList, Def) - ResTranTile *TileList; - resTransistor *TransistorList; +ResPreProcessDevices(TileList, DeviceList, Def) + ResDevTile *TileList; + resDevice *DeviceList; CellDef *Def; { Tile *tile; - ResTranTile *oldTile; + ResDevTile *oldTile; tileJunk *tstruct; TileType tt, residue; int pNum; - while (TileList != (ResTranTile *) NULL) + while (TileList != (ResDevTile *) NULL) { tt = TileList->type; if (DBIsContact(tt)) { - /* Find which residue of the contact is a transistor type. */ + /* Find which residue of the contact is a device. */ TileTypeBitMask ttresidues; DBFullResidueMask(tt, &ttresidues); @@ -598,51 +605,51 @@ ResPreProcessTransistors(TileList, TransistorList, Def) tstruct = (tileJunk *) tile->ti_client; if (!TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt) || - tstruct->transistorList == NULL) + tstruct->deviceList == NULL) { - TxError("Bad Transistor Location at %d,%d\n", + TxError("Bad Device Location at %d,%d\n", TileList->area.r_ll.p_x, TileList->area.r_ll.p_y); } else if ((tstruct->tj_status & RES_TILE_MARK) == 0) { - resTransistor *rt = tstruct->transistorList; + resDevice *rd = tstruct->deviceList; tstruct->tj_status |= RES_TILE_MARK; - rt->rt_perim += TileList->perim; - rt->rt_length += TileList->overlap; - rt->rt_area += (TileList->area.r_xtop - TileList->area.r_xbot) + rd->rd_perim += TileList->perim; + rd->rd_length += TileList->overlap; + rd->rd_area += (TileList->area.r_xtop - TileList->area.r_xbot) * (TileList->area.r_ytop - TileList->area.r_ybot); - rt->rt_tiles++; + rd->rd_tiles++; } oldTile = TileList; - TileList = TileList->nextTran; + TileList = TileList->nextDev; freeMagic((char *)oldTile); } - for(; TransistorList != NULL;TransistorList = TransistorList->rt_nextTran) + for(; DeviceList != NULL;DeviceList = DeviceList->rd_nextDev) { - int width = TransistorList->rt_perim; - int length = TransistorList->rt_length; - if (TransistorList->rt_tiles != 0) + int width = DeviceList->rd_perim; + int length = DeviceList->rd_length; + if (DeviceList->rd_tiles != 0) { if (length) { - TransistorList->rt_length = (float) length / - ((float)((TransistorList->rt_tiles) << 1)); - TransistorList->rt_width = (width-length) >> 1; + DeviceList->rd_length = (float) length / + ((float)((DeviceList->rd_tiles) << 1)); + DeviceList->rd_width = (width-length) >> 1; } else { - double perimeter = TransistorList->rt_perim; - double area = TransistorList->rt_area; + double perimeter = DeviceList->rd_perim; + double area = DeviceList->rd_area; perimeter /= 4.0; - TransistorList->rt_width = perimeter + + DeviceList->rd_width = perimeter + sqrt(perimeter * perimeter-area); - TransistorList->rt_length = (TransistorList->rt_perim - - 2 * TransistorList->rt_width) >> 1; + DeviceList->rd_length = (DeviceList->rd_perim + - 2 * DeviceList->rd_width) >> 1; } } } diff --git a/resis/ResWrite.c b/resis/ResWrite.c index a026cd54..7483c8e4 100644 --- a/resis/ResWrite.c +++ b/resis/ResWrite.c @@ -38,7 +38,7 @@ static char sccsid[] = "@(#)Write.c 4.10 MAGIC (Stanford Addition) 07/86"; #define RT_SIZE 0xf #define MAXTOKEN 256 -#define TRANFLATSIZE 1024 +#define DEVFLATSIZE 1024 #define RESGROUPSIZE 256 void @@ -136,15 +136,15 @@ resCurrentPrintFunc(node,resistor,filename) FILE *filename; { - tElement *workingTran; + tElement *workingDev; float i_sum=0.0; - for (workingTran = node->rn_te; workingTran != NULL; - workingTran=workingTran->te_nextt) + for (workingDev = node->rn_te; workingDev != NULL; + workingDev=workingDev->te_nextt) { - if ((workingTran->te_thist->rt_status & RES_TRAN_PLUG) || - workingTran->te_thist->rt_gate != node) - i_sum += workingTran->te_thist->rt_i; + if ((workingDev->te_thist->rd_status & RES_DEV_PLUG) || + workingDev->te_thist->rd_gate != node) + i_sum += workingDev->te_thist->rd_i; } if (i_sum != 0.0) { @@ -167,11 +167,11 @@ ResDeviceCounts() { int i,j,k; resNode *n; - resTransistor *t; + resDevice *t; resResistor *r; for (n=ResNodeList,i=0;n!=NULL;n=n->rn_more,i++); - for (t=ResTransList,j=0;t!=NULL;t=t->rt_nextTran,j++); + for (t=ResDevList,j=0;t!=NULL;t=t->rd_nextDev,j++); for (r=ResResList,k=0;r!=NULL;r=r->rr_nextResistor,k++); TxError("n=%d t=%d r=%d\n",i,j,k); TxFlushErr(); diff --git a/resis/resis.h b/resis/resis.h index 2848cba8..74fdd5cd 100644 --- a/resis/resis.h +++ b/resis/resis.h @@ -66,35 +66,37 @@ typedef struct resistor #define rr_connection1 rr_node[0] #define rr_connection2 rr_node[1] +/* Definitions for old FET-style MOSFET devices */ #define RT_GATE 0 #define RT_SOURCE 1 #define RT_DRAIN 2 #define RT_SUBS 3 -#define RT_TERMCOUNT 4 -typedef struct transistor -{ - int rt_status; /* status bits */ - struct transistor *rt_nextTran; /* next transistor in linked list */ - /* terminals of transistor */ - struct resnode *rt_terminals[RT_TERMCOUNT]; - int rt_perim; /* info about transistor */ - int rt_area; /* used in .ext and .sim file */ - int rt_length; /* patches. */ - int rt_width; - int rt_tiles; /* number of tiles in transistor */ - int rt_trantype; /* tiletype of transistor. */ - Rect rt_inside; /* 1x1 rectangle inside transistor */ - Tile *rt_tile; /* pointer to a tile in transistor */ -#ifdef ARIEL - float rt_i; /* Current injected from this tran */ - /* in milliamps */ -#endif -} resTransistor; -#define rt_gate rt_terminals[RT_GATE] -#define rt_source rt_terminals[RT_SOURCE] -#define rt_drain rt_terminals[RT_DRAIN] -#define rt_subs rt_terminals[RT_SUBS] +#define rd_fet_gate rd_terminals[RT_GATE] +#define rd_fet_source rd_terminals[RT_SOURCE] +#define rd_fet_drain rd_terminals[RT_DRAIN] +#define rd_fet_subs rd_terminals[RT_SUBS] + +typedef struct device +{ + int rd_status; /* status bits */ + struct device *rd_nextDev; /* next device in linked list */ + /* terminals of device */ + struct resnode **rd_terminals; + int rd_nterms; /* number of terminals in rt_terminals */ + int rd_perim; /* info about device */ + int rd_area; /* used in .ext and .sim file */ + int rd_length; /* patches. */ + int rd_width; + int rd_tiles; /* number of tiles in device */ + int rd_devtype; /* tiletype of device. */ + Rect rd_inside; /* 1x1 rectangle inside device */ + Tile *rd_tile; /* pointer to a tile in device */ +#ifdef ARIEL + float rd_i; /* Current injected from this device */ + /* in milliamps */ +#endif +} resDevice; /* a junction is formed when two tiles that connect are next to one another. @@ -149,7 +151,7 @@ typedef struct jelement typedef struct telement { struct telement *te_nextt; - resTransistor *te_thist; + resDevice *te_thist; } tElement; typedef struct celement @@ -160,7 +162,7 @@ typedef struct celement /* Nodes formed from network. These are linked both forwards and backwords - to other nodes. Lists of transistors, resistors, junctions, and contacts + to other nodes. Lists of devices, resistors, junctions, and contacts corresponding to this node are kept. */ typedef struct resnode @@ -190,7 +192,7 @@ typedef struct resnode /* for this node. */ ClientData rn_client; /* Random pointer */ int rn_id; -}resNode; +} resNode; typedef struct nelement { @@ -222,32 +224,32 @@ typedef struct breakpoint typedef struct tilejunk { cElement *contactList; /*widgets connected to this tile */ - resTransistor *transistorList; + resDevice *deviceList; resPort *portList; ResJunction *junctionList; Breakpoint *breakList; - int sourceEdge; /* used in transistor tiles to keep - of which diffusion edges are - the transistor's source - */ + int sourceEdge; /* used in device tiles to keep + * of which diffusion edges are + * a transistor's source + */ int tj_status; /* status of tile processing */ } tileJunk; -/* ResTransTile keeps track of the location and type of transistors. +/* ResDevTile keeps track of the location and type of devices. These areas are painted into our copied def after the tree is totally flattened. (They can't be painted right away becasue the copy routine uses the new def to keep track of where it is in the design. It is also - used when transistors are preproceesed. + used when devices are preproceesed. */ -typedef struct restrantile +typedef struct resdevtile { - struct restrantile *nextTran; + struct resdevtile *nextDev; Rect area; TileType type; int perim; int overlap; -} ResTranTile; +} ResDevTile; /* Goodies contains random stuff passed between the node extractor @@ -261,10 +263,10 @@ typedef struct goodstuff float rg_maxres; float rg_nodecap; float rg_Tdi; - int rg_bigtranres; + int rg_bigdevres; int rg_tilecount; int rg_status; - Point *rg_tranloc; + Point *rg_devloc; char *rg_name; } ResGlobalParams; @@ -280,26 +282,26 @@ typedef struct rcdelaystuff /* ResSim.c type declarations */ -typedef struct rtran +typedef struct rdev { - struct rtran *nextTran; /* Next transistor in linked list */ - struct rtran *realTran; /* Single Lumped Transistor for */ - /* transistors connected in parallel */ - resTransistor *layout; /* pointer to resTransistor that */ - /* corresponds to RTran */ + struct rdev *nextDev; /* Next device in linked list */ + struct rdev *realDev; /* Single Lumped Device for */ + /* devices connected in parallel */ + resDevice *layout; /* pointer to resDevice that */ + /* corresponds to RDev */ int status; struct ressimnode *gate; /* Terminals of transistor. */ struct ressimnode *source; struct ressimnode *drain; Point location; /* Location of lower left point of */ - /* transistor. */ - float resistance; /* "Resistance" of transistor. */ - int tnumber; /* Transistor number */ - int rs_ttype; /* transistor type */ + /* device. */ + float resistance; /* "Resistance" of device. */ + int tnumber; /* Device number */ + int rs_ttype; /* device type */ char *rs_gattr; /* Gate attributes, if any */ char *rs_sattr; char *rs_dattr; -} RTran; +} RDev; typedef struct ressimnode { @@ -327,7 +329,7 @@ typedef struct ressimnode /* tile in the lowest numbered */ /* plane contained in the node . */ TileType type; /* Tile type of tile at location */ - struct tranptr *firstTran; /* linked list of transistors */ + struct devptr *firstDev; /* linked list of devices */ /* connected to node. */ char *name; /* Pointer to name of node stored */ /* in hash table. */ @@ -341,15 +343,15 @@ typedef struct ressimnode #define RES_SUB_GND 0 #define RES_SUB_VDD 1 -/* `cons' cell for linked list of transistors connected to node */ +/* `cons' cell for linked list of devices connected to node */ -typedef struct tranptr +typedef struct devptr { - struct tranptr *nextTran; - struct rtran *thisTran; - int terminal; /* which terminal of transistor */ - /* is connected to node. */ -} tranPtr; + struct devptr *nextDev; + struct rdev *thisDev; + int terminal; /* which terminal of device */ + /* is connected to node. */ +} devPtr; /* ResTime.c type declarations */ @@ -360,7 +362,7 @@ typedef struct resevent /* Raw event list read in from rsim/tv */ int rv_tmin; /* minimum event time in units of 100ps */ int rv_tmax; /* maximum event time in units of 100ps */ float rv_i; /* event current in milliamps */ - resTransistor *rv_tran; /* transistor where charge drains */ + resDevice *rv_dev; /* device where charge drains */ } ResEvent; typedef struct reseventcell @@ -372,8 +374,8 @@ typedef struct reseventcell typedef struct rescurrentevent /* processed event used to feed relaxer */ { struct rescurrentevent *ri_next; - float ri_i; - resTransistor *ri_tran; + float ri_i; + resDevice *ri_dev; } ResCurrentEvent; typedef struct restimebin /* Holds one timestep's worth of Events */ @@ -406,7 +408,7 @@ typedef struct clump } ResClump; /* the first two fields of this plug must be the the same as for - resTransistor + resDevice */ typedef struct plug { @@ -437,7 +439,7 @@ typedef struct capval /* type of node flags */ #define RES_NODE_JUNCTION 0x00000001 -#define RES_NODE_TRANSISTOR 0x00000002 +#define RES_NODE_DEVICE 0x00000002 #define RES_NODE_CONTACT 0x00000004 #define RES_NODE_ORIGIN 0x00000008 @@ -452,15 +454,15 @@ typedef struct capval #define RES_REACHED_RESISTOR 0x00100000 #define RES_HEAP 0x00200000 -/* transistor flags */ -#define RES_TRAN_SAVE 0x00000001 -#define RES_TRAN_PLUG 0x00000002 +/* device flags */ +#define RES_DEV_SAVE 0x00000001 +#define RES_DEV_PLUG 0x00000002 /* flags for tiles */ /* A tile which is part of a source/drain region. */ #define RES_TILE_SD 0x1 -/* A tile which is actually a transistor */ -#define RES_TILE_TRAN 0x2 +/* A tile which is actually a device */ +#define RES_TILE_DEV 0x2 /* Indicates whether the tile has been processed or not */ #define RES_TILE_DONE 0x4 /*a temporary marking flag */ @@ -566,7 +568,7 @@ typedef struct capval /* Assorted Variables */ -extern RTran *ResTranList; +extern RDev *ResRDevList; extern REcell *ResBigEventList; extern int ResOptionsFlags; extern char *ResCurrentNode; @@ -587,24 +589,24 @@ extern TileTypeBitMask ResConnectWithSD[NT]; extern TileTypeBitMask ResCopyMask[NT]; extern resResistor *ResResList; extern resNode *ResNodeList; -extern resTransistor *ResTransList; +extern resDevice *ResDevList; extern ResContactPoint *ResContactList; extern resNode *ResNodeQueue; extern resNode *ResOriginNode; extern resNode *resCurrentNode; extern HashTable ResNodeTable; -extern HashTable ResSimTranTable; +extern HashTable ResSimDevTable; extern ResFixPoint *ResFixList; extern int ResTileCount; extern ResSimNode **ResNodeArray; extern CellDef *mainDef; extern TileTypeBitMask ResSubsTypeBitMask; -extern HashTable ResTranTable; +extern HashTable ResDevTable; extern TileTypeBitMask ResNoMergeMask[NT]; extern ResGlobalParams gparams; extern int ResPortIndex; -extern int ResSimTransistor(); +extern int ResSimDevice(); extern int ResSimCombineParallel(); extern int ResSimCapacitor(); extern int ResSimResistor(); @@ -613,16 +615,16 @@ extern int ResSimMerge(); extern int dbSrConnectStartFunc(); extern int ResEach(),ResAddPlumbing(),ResRemovePlumbing(); extern float ResCalculateChildCapacitance(); -extern ResTranTile *DBTreeCopyConnectDCS(); +extern ResDevTile *DBTreeCopyConnectDCS(); extern Tile *ResFindTile(); -extern resTransistor *ResImageAddPlug(); -extern resTransistor *ResGetTransistor(); +extern resDevice *ResImageAddPlug(); +extern resDevice *ResGetDevice(); extern tileJunk *resAddField(); extern int ResCheckPorts(); extern int ResCheckBlackbox(); extern void ResCheckSimNodes(); extern void ResSortByGate(); -extern void ResFixTranName(); +extern void ResFixDevName(); extern void ResWriteLumpFile(); extern void ResSortBreaks(); @@ -649,7 +651,7 @@ extern void ResSortBreaks(); #define ResJunkInit(Junk) \ { \ Junk->contactList = (cElement *) NULL; \ - Junk->transistorList = (resTransistor *) NULL; \ + Junk->deviceList = (resDevice *) NULL; \ Junk->junctionList = (ResJunction *) NULL; \ Junk->breakList = (Breakpoint *) NULL; \ Junk->portList = (resPort *) NULL; \ diff --git a/utils/hash.c b/utils/hash.c index e6c12aed..ca231369 100644 --- a/utils/hash.c +++ b/utils/hash.c @@ -557,6 +557,51 @@ HashStats(table) printf("# of buckets with %d entries: %d.\n", i, count[i]); printf("# of buckets with >%d entries: %d.\n", MAXCOUNT-1, overflow); } + +/*--------------------------------------------------------- + * + * HashRemove -- + * + * Remove an entry from the hash table. The entry + * is assumed to have no data (NULL value). Only + * use this routine on STRINGKEY type hash tables. + * If the entry does not exist, then the routine + * returns without doing anything. + * + * Results: + * None + *--------------------------------------------------------- + */ + +void +HashRemove(table, key) + HashTable *table; /* Hash table to search. */ + char *key; /* Interpreted according to table->ht_ptrKeys + * as described in HashInit()'s comments. + */ +{ + HashEntry *h, *hlast; + int bucket; + + bucket = hash(table, key); + h = *(table->ht_table + bucket); + hlast = NULL; + while (h != NIL) + { + if (strcmp(h->h_key.h_name, key) == 0) + { + freeMagic((char *)h); + if (hlast != NULL) + hlast->h_next = h->h_next; + else + *(table->ht_table + bucket) = h->h_next; + break; + } + hlast = h; + h = h->h_next; + } +} + /*--------------------------------------------------------- * diff --git a/utils/hash.h b/utils/hash.h index 12e32e6f..3262eff6 100644 --- a/utils/hash.h +++ b/utils/hash.h @@ -115,6 +115,7 @@ extern void HashInit(HashTable *, int, int), HashInitClient(), HashStats(), Hash HashFreeKill(); extern HashEntry *HashFind(HashTable *, char *); extern HashEntry *HashLookOnly(HashTable *, char *); +extern void HashRemove(HashTable *, char *); extern void HashStartSearch(HashSearch *); extern HashEntry *HashNext(HashTable *, HashSearch *); From 39ab59e7ecf1e1f98c846928624b398854ff93a7 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 18 Oct 2019 14:12:52 -0400 Subject: [PATCH 040/121] Corrected error causing a crash when parasitic extraction is invoked on a layout with an array of instances. Also, continued implementation of antenna violation checking (not done yet). --- ext2spice/ext2hier.c | 2 +- extflat/Depend | 3 +- extflat/EFantenna.c | 237 +++++++++++++++++++++++++++++++++++++++---- extflat/EFbuild.c | 4 +- extflat/EFflat.c | 6 +- extflat/EFint.h | 2 +- extflat/extflat.h | 4 +- extract/ExtTech.c | 12 ++- extract/extractInt.h | 3 + 9 files changed, 243 insertions(+), 30 deletions(-) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index fd06a376..7d3df37f 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1686,7 +1686,7 @@ esMakePorts(hc, cdata) // Find the cell for the instance portdef = NULL; - he = HashFind(&updef->def_uses, portname); + he = HashLookOnly(&updef->def_uses, portname); if (he != NULL) { use = (Use *)HashGetValue(he); diff --git a/extflat/Depend b/extflat/Depend index a48cf3b8..c2c89681 100644 --- a/extflat/Depend +++ b/extflat/Depend @@ -32,4 +32,5 @@ EFantenna.o: EFantenna.c ../tcltk/tclmagic.h ../utils/magic.h \ ../utils/geometry.h ../utils/hash.h ../utils/utils.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 ../utils/malloc.h + ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ + ../utils/malloc.h diff --git a/extflat/EFantenna.c b/extflat/EFantenna.c index 0048b3f9..4bbbd1c4 100644 --- a/extflat/EFantenna.c +++ b/extflat/EFantenna.c @@ -29,7 +29,8 @@ #include "textio/txcommands.h" #endif #include "extflat/extflat.h" -#include "extract/extract.h" /* for extDevTable */ +#include "extract/extract.h" +#include "extract/extractInt.h" #include "utils/malloc.h" /* Forward declarations */ @@ -103,6 +104,8 @@ CmdAntennaCheck(w, cmd) char *subname; int idx; + CellUse *editUse; + static char *cmdAntennaCheckOption[] = { "[run] [options] run antennacheck on current cell\n" " use \"run -help\" to get standard options", @@ -134,6 +137,13 @@ usage: runantennacheck: + if (ExtCurStyle->exts_planeOrderStatus == noPlaneOrder) + { + TxError("No planeorder specified for this process: " + "Cannot run antenna checks!\n"); + return; + } + EFInit(); EFCapThreshold = INFINITY; EFResistThreshold = INFINITY; @@ -162,6 +172,7 @@ runantennacheck: } inName = ((CellUse *) w->w_surfaceID)->cu_def->cd_name; } + editUse = (CellUse *)w->w_surfaceID; /* * Initializations specific to this program. @@ -178,7 +189,7 @@ runantennacheck: flatFlags = EF_FLATNODES; EFFlatBuild(inName, flatFlags); - EFVisitDevs(antennacheckVisit, (ClientData)NULL); + EFVisitDevs(antennacheckVisit, (ClientData)editUse); EFFlatDone(); EFDone(); @@ -234,9 +245,30 @@ 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); +} + /* * ---------------------------------------------------------------------------- * @@ -256,15 +288,30 @@ usage: */ int -antennacheckVisit(dev, hierName, scale, trans) +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, *source, *drain; - int l, w; + DevTerm *gate; + int pos, pNum, pNum2, pmax, p, i, j, gatearea, diffarea, total; + double difftotal; + int *antennaarea; Rect r; + EFNode *gnode; + SearchContext scx; + TileTypeBitMask gatemask; + + extern CellDef *extPathDef; /* see extract/ExtLength.c */ + extern CellUse *extPathUse; /* see extract/ExtLength.c */ + + extern int areaAccumFunc(), antennaAccumFunc(); + + antennaarea = (int *)mallocMagic(DBNumTypes * sizeof(int)); + + for (i = 0; i < DBNumTypes; i++) antennaarea[i] = 0; switch(dev->dev_class) { @@ -274,24 +321,176 @@ antennacheckVisit(dev, hierName, scale, trans) /* Procedure: * - * 1. If device is marked visited, return. - * 2. Mark device visited - * 3. Mark all connected devices visited - * 4. For each plane from metal1 up (determined by planeorder): - * a. Run SimTreeCopyConnect() + * 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 metal area of connected devices - * d. Check against antenna ratio - * e. Generate feedback if in violation of antenna rule + * 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: SimTreeCopyConnect() is used cumulatively, so that + * NOTE: DBTreeCopyConnect() is used cumulatively, so that * additional searching only needs to be done for the additional - * layer being searched. This is the reason for using - * SimTreeCopyConnect() instead of DBTreeCopyConnect(). + * layer being searched. */ - /* To be completed */ + gate = &dev->dev_terms[0]; + + gnode = AntennaGetNode(hierName, gate->dterm_node->efnode_name->efnn_hier); + if (beenVisited((nodeClient *)gnode->efnode_client, 0)) + return 0; + else + markVisited((nodeClient *)gnode->efnode_client, 0); + + /* Find the plane of the gate type */ + pNum = DBPlane(dev->dev_type); + 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]; + + /* Use the cellDef reserved for extraction */ + DBCellClearDef(extPathDef); + scx.scx_use = editUse; + scx.scx_trans = GeoIdentityTransform; + + /* 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++) + { + /* Modify DBConnectTbl to limit connectivity to the plane */ + /* of the antenna check and below */ + + /* To be completed */ + + DBTreeCopyConnect(&scx, &DBConnectTbl[dev->dev_type], 0, + DBConnectTbl, &TiPlaneRect, extPathUse); + + /* Search plane of gate type and accumulate all (new) gate area */ + DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[pNum], + &TiPlaneRect, &gatemask, areaAccumFunc, (ClientData)&gatearea); + + /* Search planes of tie type and accumulate all (new) tiedown areas */ + for (p = 0; p < DBNumPlanes; p++) + DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[p], + &TiPlaneRect, &ExtCurStyle->exts_antennaTieTypes, + areaAccumFunc, (ClientData)&diffarea); + + /* Search metal planes and accumulate all (new) antenna areas */ + for (p = 0; p < DBNumPlanes; p++) + { + if (ExtCurStyle->exts_planeOrder[p] == pos) + { + pNum2 = p; + } + if (ExtCurStyle->exts_planeOrder[p] <= pos) + DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[p], + &TiPlaneRect, &DBAllButSpaceAndDRCBits, + antennaAccumFunc, (ClientData)&antennaarea); + } + + /* To be elaborated. . . this encodes only one of several */ + /* methods of calculating antenna violations. */ + + if (diffarea == 0) + { + difftotal = 0.0; + for (i = 0; i < DBNumTypes; i++) + difftotal += antennaarea[i] / ExtCurStyle->exts_antennaRatio[i]; + + if (difftotal > gatearea) + TxError("Antenna violation detected at plane %s " + "(violation to be elaborated)", + DBPlaneLongNameTbl[pNum2]); + } + } } return 0; } +/* + * ---------------------------------------------------------------------------- + * + * areaAccumFunc -- + * + * Accumulate the total tile area searched + * + * ---------------------------------------------------------------------------- + */ + +int +areaAccumFunc(tile, totalarea) + Tile *tile; + int *totalarea; +{ + Rect rect; + int area; + + TiToRect(tile, &rect); + + area += (rect.r_xtop - rect.r_xbot) * (rect.r_ytop - rect.r_ybot); + + *totalarea += area; + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * antennaAccumFunc -- + * + * Accumulate the total tile area searched, keeping an individual + * count for each tile type. + * + * ---------------------------------------------------------------------------- + */ + +int +antennaAccumFunc(tile, typeareas) + Tile *tile; + int **typeareas; +{ + Rect rect; + int area; + int type; + + type = TiGetType(tile); + + TiToRect(tile, &rect); + + area += (rect.r_xtop - rect.r_xbot) * (rect.r_ytop - rect.r_ybot); + + *typeareas[type] += area; + + return 0; +} diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c index a7631a26..dd2c700e 100644 --- a/extflat/EFbuild.c +++ b/extflat/EFbuild.c @@ -172,7 +172,7 @@ efBuildNode(def, isSubsnode, nodeName, nodeCap, x, y, layerName, av, ac) HashSetValue(he, (char *) newname); /* New node itself */ - size = sizeof (EFNode) + (efNumResistClasses - 1) * sizeof (PerimArea); + size = sizeof (EFNode) + (efNumResistClasses - 1) * sizeof (EFPerimArea); newnode = (EFNode *) mallocMagic((unsigned)(size)); newnode->efnode_flags = (isSubsnode == TRUE) ? EF_SUBS_NODE : 0; newnode->efnode_cap = nodeCap; @@ -1182,7 +1182,7 @@ efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac) int n; Connection *conn; unsigned size = sizeof (Connection) - + (efNumResistClasses - 1) * sizeof (PerimArea); + + (efNumResistClasses - 1) * sizeof (EFPerimArea); conn = (Connection *) mallocMagic((unsigned)(size)); diff --git a/extflat/EFflat.c b/extflat/EFflat.c index 27e8d4e3..9725def9 100644 --- a/extflat/EFflat.c +++ b/extflat/EFflat.c @@ -430,7 +430,7 @@ efAddNodes(hc, stdcell) bool is_subcircuit = (def->def_flags & DEF_SUBCIRCUIT) ? TRUE : FALSE; scale = def->def_scale; - size = sizeof (EFNode) + (efNumResistClasses-1) * sizeof (PerimArea); + size = sizeof (EFNode) + (efNumResistClasses-1) * sizeof (EFPerimArea); for (node = (EFNode *) def->def_firstn.efnode_next; node != &def->def_firstn; @@ -467,10 +467,10 @@ efAddNodes(hc, stdcell) newnode->efnode_type = node->efnode_type; if (!stdcell) bcopy((char *) node->efnode_pa, (char *) newnode->efnode_pa, - efNumResistClasses * sizeof (PerimArea)); + efNumResistClasses * sizeof (EFPerimArea)); else bzero((char *) newnode->efnode_pa, - efNumResistClasses * sizeof (PerimArea)); + efNumResistClasses * sizeof (EFPerimArea)); GeoTransRect(&hc->hc_trans, &node->efnode_loc, &newnode->efnode_loc); /* Scale the result by "scale" --- hopefully we end up with an integer */ diff --git a/extflat/EFint.h b/extflat/EFint.h index 6ec90eca..9c380528 100644 --- a/extflat/EFint.h +++ b/extflat/EFint.h @@ -133,7 +133,7 @@ typedef struct conn } conn_value; struct conn *conn_next; /* Next connection in list */ - PerimArea conn_pa[1]; /* Dummy; each connection actually has + EFPerimArea conn_pa[1]; /* Dummy; each connection actually has * efNumResistClasses array elements * allocated to it. */ diff --git a/extflat/extflat.h b/extflat/extflat.h index f249e37c..d7dec156 100644 --- a/extflat/extflat.h +++ b/extflat/extflat.h @@ -142,7 +142,7 @@ typedef struct { int pa_area; int pa_perim; -} PerimArea; +} EFPerimArea; typedef struct efnhdr { @@ -219,7 +219,7 @@ typedef struct efnode */ EFAttr *efnode_attrs; /* Node attribute list */ ClientData efnode_client; /* For hire */ - PerimArea efnode_pa[1]; /* Dummy; each node actually has + EFPerimArea efnode_pa[1]; /* Dummy; each node actually has * efNumResistClasses array elements * allocated to it. */ diff --git a/extract/ExtTech.c b/extract/ExtTech.c index 21ff4ce3..94b74c79 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -71,7 +71,7 @@ typedef enum AREAC, CONTACT, CSCALE, DEFAULTAREACAP, DEFAULTOVERLAP, DEFAULTPERIMETER, DEFAULTSIDEOVERLAP, DEFAULTSIDEWALL, - DEVICE, FET, FETRESIST, HEIGHT, ANTENNA, LAMBDA, OVERC, + DEVICE, FET, FETRESIST, HEIGHT, ANTENNA, TIEDOWN, LAMBDA, OVERC, PERIMC, PLANEORDER, NOPLANEORDER, RESIST, RSCALE, SIDEHALO, SIDEOVERLAP, SIDEWALL, STEP, STYLE, SUBSTRATE, UNITS, VARIANT } Key; @@ -125,6 +125,9 @@ static keydesc keyTable[] = { "antenna", ANTENNA, 3, 3, "type antenna-ratio", + "tiedown", TIEDOWN, 2, 2, +"types", + "lambda", LAMBDA, 2, 2, "units-per-lambda", @@ -665,14 +668,17 @@ extTechStyleInit(style) style->exts_numResistClasses = 0; style->exts_planeOrderStatus = needPlaneOrder ; + TTMaskZero(&style->exts_antennaTieTypes); for (r = 0; r < DBNumTypes; r++) { + style->exts_antennaRatio[r] = 0; style->exts_resistByResistClass[r] = 0; TTMaskZero(&style->exts_typesByResistClass[r]); style->exts_typesResistChanged[r] = DBAllButSpaceAndDRCBits; TTMaskSetType(&style->exts_typesResistChanged[r], TT_SPACE); style->exts_typeToResistClass[r] = -1; + } doConvert = FALSE; @@ -1789,6 +1795,7 @@ ExtTechLine(sectionName, argc, argv) case FETRESIST: case HEIGHT: case ANTENNA: + case TIEDOWN: case OVERC: case PERIMC: case RESIST: @@ -2325,6 +2332,9 @@ ExtTechLine(sectionName, argc, argv) } } break; + case TIEDOWN: + TTMaskSetMask(&ExtCurStyle->exts_antennaTieTypes, &types1); + break; case UNITS: if (!strcmp(argv[1], "microns")) doConvert = TRUE; diff --git a/extract/extractInt.h b/extract/extractInt.h index bb30c425..44b7f7e0 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -659,6 +659,9 @@ typedef struct extstyle /* Antenna area ratio for each layer */ float exts_antennaRatio[NT]; + /* Mask of types that tie down antennas */ + TileTypeBitMask exts_antennaTieTypes; + /* * Capacitance to substrate for each tile type, in units of * attofarads per square lambda. From b8c34cb10b703efdbce1bf29dcab47812176487c Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 18 Oct 2019 14:25:28 -0400 Subject: [PATCH 041/121] Fixed an additional call to HashFind() that should have been HashLookOnly() and can potentially cause a crash. --- ext2spice/ext2hier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 7d3df37f..07143cb0 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1596,7 +1596,7 @@ esMakePorts(hc, cdata) // Find the cell for the instance portdef = NULL; - he = HashFind(&updef->def_uses, portname); + he = HashLookOnly(&updef->def_uses, portname); if (he != NULL) { use = (Use *)HashGetValue(he); From 77e8ff437b58942fa680791eae39d6f3205c8751 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Sun, 20 Oct 2019 22:12:02 -0400 Subject: [PATCH 042/121] Finished first cut at an implementation of antenna rule violation checks. Added new command "antennacheck" and a routine that adds feedback entries where violations are found. Extended the syntax of the extraction section of the techfile to support the antenna ratios and antenna calculation methods. --- extflat/Depend | 10 +- extflat/EFantenna.c | 452 ++++++++++++++++++++++++++++++++++++++----- extract/ExtTech.c | 83 +++++++- extract/extract.h | 1 + extract/extractInt.h | 16 +- 5 files changed, 498 insertions(+), 64 deletions(-) diff --git a/extflat/Depend b/extflat/Depend index c2c89681..f4e40584 100644 --- a/extflat/Depend +++ b/extflat/Depend @@ -29,8 +29,8 @@ EFvisit.o: EFvisit.c ../utils/magic.h ../utils/geometry.h \ ../utils/geofast.h ../utils/hash.h ../utils/malloc.h ../utils/utils.h \ ../extflat/extflat.h ../extflat/EFint.h ../extract/extract.h EFantenna.o: EFantenna.c ../tcltk/tclmagic.h ../utils/magic.h \ - ../utils/geometry.h ../utils/hash.h ../utils/utils.h ../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 + ../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 diff --git a/extflat/EFantenna.c b/extflat/EFantenna.c index 4bbbd1c4..470edfe8 100644 --- a/extflat/EFantenna.c +++ b/extflat/EFantenna.c @@ -14,18 +14,20 @@ #include /* for atof() */ #include #include +#include /* for INFINITY */ #include "tcltk/tclmagic.h" #include "utils/magic.h" #include "utils/geometry.h" #include "utils/hash.h" #include "utils/utils.h" +#include "utils/styles.h" #include "tiles/tile.h" #ifdef MAGIC_WRAPPER #include "database/database.h" #include "windows/windows.h" #include "textio/textio.h" -#include "dbwind/dbwind.h" /* for DBWclientID */ +#include "dbwind/dbwind.h" #include "textio/txcommands.h" #endif #include "extflat/extflat.h" @@ -70,6 +72,34 @@ typedef struct { ((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; + /* * ---------------------------------------------------------------------------- @@ -80,16 +110,18 @@ typedef struct { */ #define ANTENNACHECK_RUN 0 -#define ANTENNACHECK_HELP 1 +#define ANTENNACHECK_DEBUG 1 +#define ANTENNACHECK_HELP 2 void CmdAntennaCheck(w, cmd) MagWindow *w; TxCommand *cmd; { - int i,flatFlags; + int i, flatFlags; char *inName; FILE *f; + TileType t; int option = ANTENNACHECK_RUN; int value; @@ -109,6 +141,7 @@ CmdAntennaCheck(w, cmd) 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 }; @@ -125,6 +158,9 @@ CmdAntennaCheck(w, cmd) case ANTENNACHECK_RUN: goto runantennacheck; break; + case ANTENNACHECK_DEBUG: + efAntennaDebug = TRUE; + break; case ANTENNACHECK_HELP: usage: for (msg = &(cmdAntennaCheckOption[0]); *msg != NULL; msg++) @@ -179,6 +215,7 @@ runantennacheck: */ /* Read the hierarchical description of the input circuit */ + TxPrintf("Reading extract file.\n"); if (EFReadFile(inName, FALSE, FALSE, FALSE) == FALSE) { EFDone(); @@ -187,13 +224,24 @@ runantennacheck: /* 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; } @@ -296,28 +344,30 @@ antennacheckVisit(dev, hierName, scale, trans, editUse) CellUse *editUse; /* ClientData is edit cell use */ { DevTerm *gate; + TileType t, conType; int pos, pNum, pNum2, pmax, p, i, j, gatearea, diffarea, total; - double difftotal; + double anttotal; + float saveRatio; int *antennaarea; - Rect r; + Rect r, gaterect; EFNode *gnode; SearchContext scx; - TileTypeBitMask gatemask; + TileTypeBitMask gatemask, saveConMask; + bool antennaError; extern CellDef *extPathDef; /* see extract/ExtLength.c */ extern CellUse *extPathUse; /* see extract/ExtLength.c */ - extern int areaAccumFunc(), antennaAccumFunc(); + extern int areaAccumFunc(), antennaAccumFunc(), areaMarkFunc(); antennaarea = (int *)mallocMagic(DBNumTypes * sizeof(int)); - for (i = 0; i < DBNumTypes; i++) antennaarea[i] = 0; - switch(dev->dev_class) { case DEV_FET: case DEV_MOSFET: - GeoTransRect(trans, &dev->dev_rect, &r); + case DEV_MSUBCKT: + case DEV_ASYMMETRIC: /* Procedure: * @@ -336,16 +386,23 @@ antennacheckVisit(dev, hierName, scale, trans, editUse) * 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 */ - pNum = DBPlane(dev->dev_type); + t = EFDeviceTypes[dev->dev_type]; + pNum = DBPlane(t); pos = ExtCurStyle->exts_planeOrder[pNum]; pmax = ++pos; @@ -354,10 +411,15 @@ antennacheckVisit(dev, hierName, scale, trans, editUse) 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); + /* 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 */ @@ -387,53 +449,203 @@ antennacheckVisit(dev, hierName, scale, trans, editUse) 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 */ - /* To be completed */ + 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; + } - DBTreeCopyConnect(&scx, &DBConnectTbl[dev->dev_type], 0, + 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 plane of gate type and accumulate all (new) gate area */ - DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[pNum], - &TiPlaneRect, &gatemask, areaAccumFunc, (ClientData)&gatearea); - - /* Search planes of tie type and accumulate all (new) tiedown areas */ + /* 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)&diffarea); + areaAccumFunc, (ClientData)&gdas); + diffarea = gdas.accum; - /* Search metal planes and accumulate all (new) antenna areas */ + /* 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_planeOrder[p] == pos) - { - pNum2 = 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)&antennaarea); + antennaAccumFunc, (ClientData)&aas); } - /* To be elaborated. . . this encodes only one of several */ - /* methods of calculating antenna violations. */ - + antennaError = FALSE; if (diffarea == 0) { - difftotal = 0.0; + anttotal = 0.0; + saveRatio = 0.0; for (i = 0; i < DBNumTypes; i++) - difftotal += antennaarea[i] / ExtCurStyle->exts_antennaRatio[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 (difftotal > gatearea) - TxError("Antenna violation detected at plane %s " - "(violation to be elaborated)", - DBPlaneLongNameTbl[pNum2]); + 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].ratioDiff != INFINITY) + { + if (ExtCurStyle->exts_antennaRatio[i].ratioDiff > 0) + anttotal += (double)antennaarea[i] / + (double)ExtCurStyle->exts_antennaRatio[i].ratioDiff; + if (ExtCurStyle->exts_antennaRatio[i].ratioDiff > saveRatio) + saveRatio = ExtCurStyle->exts_antennaRatio[i].ratioDiff; + } + + 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; } @@ -448,19 +660,16 @@ antennacheckVisit(dev, hierName, scale, trans, editUse) */ int -areaAccumFunc(tile, totalarea) +areaAccumFunc(tile, gdas) Tile *tile; - int *totalarea; + GateDiffAccumStruct *gdas; { - Rect rect; - int area; - - TiToRect(tile, &rect); - - area += (rect.r_xtop - rect.r_xbot) * (rect.r_ytop - rect.r_ybot); - - *totalarea += area; + 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; } @@ -470,27 +679,164 @@ areaAccumFunc(tile, totalarea) * antennaAccumFunc -- * * Accumulate the total tile area searched, keeping an individual - * count for each tile type. + * 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, typeareas) +antennaAccumFunc(tile, aaptr) Tile *tile; - int **typeareas; + AntennaAccumStruct *aaptr; { - Rect rect; + Rect *rect = &(aaptr->r); int area; int type; + int *typeareas = aaptr->accum; + int plane = aaptr->pNum; + float thick; type = TiGetType(tile); - TiToRect(tile, &rect); + TiToRect(tile, rect); - area += (rect.r_xtop - rect.r_xbot) * (rect.r_ytop - rect.r_ybot); + if (ExtCurStyle->exts_antennaModel & ANTENNAMODEL_SIDEWALL) + { + /* Accumulate perimeter of tile where tile abuts space */ - *typeareas[type] += area; + 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 + { + /* 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; } diff --git a/extract/ExtTech.c b/extract/ExtTech.c index 94b74c79..96e3d4c7 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -71,7 +71,7 @@ typedef enum AREAC, CONTACT, CSCALE, DEFAULTAREACAP, DEFAULTOVERLAP, DEFAULTPERIMETER, DEFAULTSIDEOVERLAP, DEFAULTSIDEWALL, - DEVICE, FET, FETRESIST, HEIGHT, ANTENNA, TIEDOWN, LAMBDA, OVERC, + DEVICE, FET, FETRESIST, HEIGHT, ANTENNA, MODEL, TIEDOWN, LAMBDA, OVERC, PERIMC, PLANEORDER, NOPLANEORDER, RESIST, RSCALE, SIDEHALO, SIDEOVERLAP, SIDEWALL, STEP, STYLE, SUBSTRATE, UNITS, VARIANT } Key; @@ -122,9 +122,12 @@ static keydesc keyTable[] = { "height", HEIGHT, 4, 4, "type height-above-subtrate thickness", - "antenna", ANTENNA, 3, 3, + "antenna", ANTENNA, 4, 4, "type antenna-ratio", + "model", MODEL, 3, 3, +"partial-cumulative area-sidewall", + "tiedown", TIEDOWN, 2, 2, "types", @@ -376,6 +379,35 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr) #endif /* MAGIC_WRAPPER */ +/* + * ---------------------------------------------------------------------------- + * + * extGetDevType -- + * + * Given an extraction model device name (devname), return the associated + * magic tiletype for the device. + * + * Results: + * Tile type that represents the device "devname" in the magic database. + * + * ---------------------------------------------------------------------------- + */ + +TileType +extGetDevType(devname) + char *devname; +{ + TileType t; + ExtDevice *devptr; + + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next) + if (!strcmp(devptr->exts_deviceName, devname)) + return t; + + return -1; +} + #ifdef THREE_D /* @@ -672,7 +704,8 @@ extTechStyleInit(style) for (r = 0; r < DBNumTypes; r++) { - style->exts_antennaRatio[r] = 0; + style->exts_antennaRatio[r].ratioGate = 0.0; + style->exts_antennaRatio[r].ratioDiff = 0.0; style->exts_resistByResistClass[r] = 0; TTMaskZero(&style->exts_typesByResistClass[r]); style->exts_typesResistChanged[r] = DBAllButSpaceAndDRCBits; @@ -2321,17 +2354,53 @@ ExtTechLine(sectionName, argc, argv) if (!StrIsNumeric(argv[2])) { - TechError("Layer antenna ratio %s must be numeric\n", argv[2]); + TechError("Gate layer antenna ratio %s must be numeric\n", argv[2]); break; } antennaratio = (float)strtod(argv[2], NULL); for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) if (TTMaskHasType(&types1, t)) { - ExtCurStyle->exts_antennaRatio[t] = antennaratio; + ExtCurStyle->exts_antennaRatio[t].ratioGate = antennaratio; + } + + if (!StrIsNumeric(argv[3])) + { + if (!strcasecmp(argv[3], "none")) + antennaratio = INFINITY; + else + { + TechError("Diff layer antenna ratio %s must be numeric\n", argv[3]); + break; + } + } + else + antennaratio = (float)strtod(argv[3], NULL); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, t)) + { + ExtCurStyle->exts_antennaRatio[t].ratioDiff = 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 (!strcmp(argv[2], "area")) + ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_AREA; + else if (!strcmp(argv[2], "sidewall")) + ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_SIDEWALL; + else + TxError("Unknown antenna model \"%s\": Use \"area\" or " + "\"sidewall\""); + break; + case TIEDOWN: TTMaskSetMask(&ExtCurStyle->exts_antennaTieTypes, &types1); break; @@ -2973,6 +3042,10 @@ zinit: ec = ec->ec_next) ec->ec_cap *= 0.5; } + + /* Layer thickness and height are in microns, but are floating-point */ + style->exts_thick[r] /= dscale; + style->exts_height[r] /= dscale; } /* side halo and step size are also in microns */ diff --git a/extract/extract.h b/extract/extract.h index b63c4acc..82e143d5 100644 --- a/extract/extract.h +++ b/extract/extract.h @@ -76,6 +76,7 @@ extern void ExtSetStyle(); extern void ExtPrintStyle(); extern void ExtCell(); + #ifdef MAGIC_WRAPPER extern bool ExtGetDevInfo(); extern bool ExtCompareStyle(); diff --git a/extract/extractInt.h b/extract/extractInt.h index 44b7f7e0..7e9c7a2e 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -48,6 +48,17 @@ typedef int ResValue; /* Warning: in some places resistances are stored * as ints. This is here for documentation only. */ +typedef struct { + float ratioGate; + float ratioDiff; +} RatioValues; + +/* Antenna models */ +#define ANTENNAMODEL_PARTIAL 0x01 +#define ANTENNAMODEL_CUMULATIVE 0x02 +#define ANTENNAMODEL_AREA 0x04 +#define ANTENNAMODEL_SIDEWALL 0x08 + /* ------------------------ Parameter lists --------------------------- */ /* These lists keep track of what parameter names subcircuit definitions @@ -656,8 +667,10 @@ typedef struct extstyle float exts_height[NT]; float exts_thick[NT]; + char exts_antennaModel; + /* Antenna area ratio for each layer */ - float exts_antennaRatio[NT]; + RatioValues exts_antennaRatio[NT]; /* Mask of types that tie down antennas */ TileTypeBitMask exts_antennaTieTypes; @@ -1060,6 +1073,7 @@ extern NodeRegion *extBasic(); extern NodeRegion *extFindNodes(); extern ExtTree *extHierNewOne(); extern int extNbrPushFunc(); +extern TileType extGetDevType(); /* --------------------- Miscellaneous globals ------------------------ */ From 7a42b5b6adf8f5a32634cc593a1b3d50cb774a47 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 23 Oct 2019 09:33:37 -0400 Subject: [PATCH 043/121] Fixed a long-standing error in which "ext2spice merge" fails when used with "ext2spice hierarchy on" because the device index is not reset between calls to output cells in the hierarchy, leading to a mismatch of the index for all cells after the first one output. --- cif/CIFrdtech.c | 4 +++- ext2spice/ext2hier.c | 3 +++ ext2spice/ext2spice.c | 53 ++++++++++++++++++++++++++++++++++++++++++- ext2spice/ext2spice.h | 30 +++++------------------- 4 files changed, 64 insertions(+), 26 deletions(-) diff --git a/cif/CIFrdtech.c b/cif/CIFrdtech.c index 297ad7b6..3777df9a 100644 --- a/cif/CIFrdtech.c +++ b/cif/CIFrdtech.c @@ -621,8 +621,10 @@ CIFReadTechLine(sectionName, argc, argv) if (argc >= 3) { - if(!strncmp(argv[argc - 1], "nanom", 5)) + if (!strncmp(argv[argc - 1], "nanom", 5)) cifCurReadStyle->crs_multiplier = 10; + else if (!strncmp(argv[argc - 1], "angstr", 6)) + cifCurReadStyle->crs_multiplier = 100; } if (cifCurReadStyle->crs_scaleFactor <= 0) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 07143cb0..c1afcb00 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1883,6 +1883,9 @@ esHierVisit(hc, cdata) EFHierVisitNodes(hcf, spcnodeHierVisit, (ClientData) NULL); freeMagic(resstr); } + + /* Reset device merge index for next cell */ + if (esMergeDevsA || esMergeDevsC) esFMIndex = 0; } if ((def != topdef) || (def->def_flags & DEF_SUBCIRCUIT) || (locDoSubckt == TRUE)) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 8885bdce..e2e560f4 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -264,7 +264,8 @@ CmdExtToSpice(w, cmd) "extresist [on|off] incorporate information from extresist", "resistor tee [on|off] model resistor capacitance as a T-network", "scale [on|off] use .option card for scaling", - "subcircuits [on|off] standard cells become subcircuit calls", + "subcircuits [top|descend] [on|off|auto]\n" + " standard cells become subcircuit calls", "hierarchy [on|off] output hierarchical spice for LVS", "blackbox [on|off] output abstract views as black-box entries", "renumber [on|off] on = number instances X1, X2, etc.\n" @@ -2095,6 +2096,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; +} + /* * ---------------------------------------------------------------------------- * diff --git a/ext2spice/ext2spice.h b/ext2spice/ext2spice.h index 4247d61e..065650d1 100644 --- a/ext2spice/ext2spice.h +++ b/ext2spice/ext2spice.h @@ -36,6 +36,11 @@ extern char *nodeSpiceHierName(); extern devMerge *mkDevMerge(); extern bool extHierSDAttr(); +extern bool devIsKilled(); +extern float getCurDevMult(); +extern void addDevMult(); +extern void setDevMult(); + /* Options specific to ext2spice */ extern bool esDoExtResis; extern bool esDoPorts; @@ -166,7 +171,7 @@ typedef struct { /* *--------------------------------------------------------- - * Variables & macros used for merging parallel devs + * Variables used for merging parallel devs * The merging of devs is based on the fact that spcdevVisit * visits the devs in the same order all the time so the * value of esFMult[i] keeps the multiplier for the ith dev @@ -174,31 +179,8 @@ typedef struct { */ #define DEV_KILLED ((float) -1.0) #define FMULT_SIZE (1<<10) - -#define devIsKilled(n) ( esFMult[(n)] <=(float)0.0 ) - #define DEV_KILLED ((float) -1.0) - -/* macro to add a dev's multiplier to the table and grow it if necessary */ -#define addDevMult(f) \ -{ \ - if ( esFMult == NULL ) { \ - esFMult = (float *) mallocMagic((unsigned) (esFMSize*sizeof(float))); \ - } else if ( esFMIndex >= esFMSize ) { \ - int i; \ - float *op = esFMult ; \ - esFMult = (float *) mallocMagic((unsigned) ((esFMSize = esFMSize*2)*sizeof(float))); \ - for ( i = 0 ; i < esFMSize/2 ; i++ ) esFMult[i] = op[i]; \ - if (op) freeMagic(op); \ - } \ - esFMult[esFMIndex++] = (float)(f); \ -} - -#define setDevMult(i,f) { esFMult[(i)] = (float)(f); } - -#define getCurDevMult() ((esFMult && (esFMIndex > 0)) ? esFMult[esFMIndex-1] : (float)1.0) - #ifdef MAGIC_WRAPPER #define atoCap(s) ((EFCapValue)atof(s)) #endif From 71108a88b4b273a7f04983a6fd100fde247de74e Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 23 Oct 2019 10:18:54 -0400 Subject: [PATCH 044/121] Corrected an error that prevented the "load" command from working with the simultaneous use of "scaled" and one of the options "-force" or "-nowindow", due to the use of a wrong index value. --- commands/CmdLQ.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/commands/CmdLQ.c b/commands/CmdLQ.c index 12250815..02c04b6f 100644 --- a/commands/CmdLQ.c +++ b/commands/CmdLQ.c @@ -318,7 +318,7 @@ CmdLabel(w, cmd) * Implement the "load" command. * * Usage: - * load [name [scaled n [d]]] [-force] + * load [name [scaled n [d]]] [-force] [-nowindow] * * If name is supplied, then the window containing the point tool is * remapped so as to edit the cell with the given name. @@ -364,15 +364,16 @@ CmdLoad(w, cmd) locargc--; ignoreTech = TRUE; } - if (locargc >= 4 && !strncmp(cmd->tx_argv[2], "scale", 5) && + if ((locargc >= 4) && !strncmp(cmd->tx_argv[2], "scale", 5) && StrIsInt(cmd->tx_argv[3])) { n = atoi(cmd->tx_argv[3]); - if (cmd->tx_argc == 5 && StrIsInt(cmd->tx_argv[4])) + if ((locargc == 5) && StrIsInt(cmd->tx_argv[4])) d = atoi(cmd->tx_argv[4]); else if (locargc != 4) { - TxError("Usage: %s name scaled n [d]\n", cmd->tx_argv[0]); + TxError("Usage: %s name scaled n [d] [-force] [-nowindow]\n", + cmd->tx_argv[0]); return; } DBLambda[0] *= d; @@ -381,7 +382,8 @@ CmdLoad(w, cmd) } else if (!ignoreTech && !noWindow) { - TxError("Usage: %s [name [scaled n [d]]]\n", cmd->tx_argv[0]); + TxError("Usage: %s name [scaled n [d]] [-force] [-nowindow]\n", + cmd->tx_argv[0]); return; } } From d9ccd711d908451945421b11f0fe8bdb0e5a88e4 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 23 Oct 2019 11:59:59 -0400 Subject: [PATCH 045/121] Realizing that the "no such node" messages were directly related to the below-threshold coupling caps being removed from the hierarchy, added code to suppress the error message when it is clearly related to a below-threshold cap that has been removed. --- ext2spice/ext2hier.c | 2 +- extflat/EFflat.c | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index c1afcb00..7348a0d6 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1656,7 +1656,7 @@ esMakePorts(hc, cdata) // In particular, this keeps parasitics out of the netlist for // LVS purposes if "cthresh" is set to "infinite". - if (fabs((double)conn->conn_cap) < EFCapThreshold) continue; + if (fabs((double)conn->conn_cap / 1000) < EFCapThreshold) continue; portname = name; updef = def; diff --git a/extflat/EFflat.c b/extflat/EFflat.c index 9725def9..337c477e 100644 --- a/extflat/EFflat.c +++ b/extflat/EFflat.c @@ -1018,14 +1018,23 @@ efFlatSingleCap(hc, name1, name2, conn) EFNode *n1, *n2; HashEntry *he; EFCoupleKey ck; + static char msg0[] = "cap(1)"; + static char msg1[] = "cap(2)"; + char *msg; + + /* Connections that are below threshold (ext2spice hierarchy only) */ + /* will be missing. Do not generate errors for these. */ - if ((he = EFHNLook(hc->hc_hierName, name1, "cap(1)")) == NULL) + msg = (fabs((double)conn->conn_cap / 1000) < EFCapThreshold) ? NULL : msg0; + + if ((he = EFHNLook(hc->hc_hierName, name1, msg)) == NULL) return 0; n1 = ((EFNodeName *) HashGetValue(he))->efnn_node; if (n1->efnode_flags & EF_KILLED) return 0; - if ((he = EFHNLook(hc->hc_hierName, name2, "cap(2)")) == NULL) + if (msg) msg = msg1; + if ((he = EFHNLook(hc->hc_hierName, name2, msg)) == NULL) return 0; n2 = ((EFNodeName *) HashGetValue(he))->efnn_node; if (n2->efnode_flags & EF_KILLED) From 2046318942f7cf4b379fd956ce8f764c0a969343 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 24 Oct 2019 16:57:46 -0400 Subject: [PATCH 046/121] Corrected routine lefFileOpen() so that it will read files with extensions other than specifically ".lef" or ".def" (such as ".tlef" for technology LEF, recently encountered). --- lef/lefWrite.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 30859c11..69264fc3 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -83,6 +83,7 @@ lefFileOpen(def, file, suffix, mode, prealfile) */ { char namebuf[512], *name, *endp, *ends; + char *locsuffix; int len; FILE *rfile; @@ -115,14 +116,17 @@ lefFileOpen(def, file, suffix, mode, prealfile) (void) strncpy(namebuf, name, len); namebuf[len] = '\0'; name = namebuf; + locsuffix = suffix; } + else + locsuffix = NULL; } /* Try once as-is, and if this fails, try stripping any leading */ /* path information in case cell is in a read-only directory (mode */ /* "read" only, and if def is non-NULL). */ - if ((rfile = PaOpen(name, mode, suffix, Path, CellLibPath, prealfile)) != NULL) + if ((rfile = PaOpen(name, mode, locsuffix, Path, CellLibPath, prealfile)) != NULL) return rfile; if (def) From 0e966af9266368983d8ed450517b17a0ab86e804 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 25 Oct 2019 12:21:19 -0400 Subject: [PATCH 047/121] Modified the check for redundant label indexes in lefWrite so that it only complains about (i.e., issues an error message) ports with the same index but different text, indicating a read port number collision and a true error. --- lef/lefWrite.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 69264fc3..282b1bda 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -638,7 +638,7 @@ lefWriteMacro(def, f, scale, hide) { bool propfound; char *propvalue, *class = NULL; - Label *lab; + Label *lab, *tlab; Rect boundary, labr; SearchContext scx; CellDef *lefFlatDef; @@ -968,15 +968,21 @@ lefWriteMacro(def, f, scale, hide) if (maxport >= 0) { - /* Sanity check to see if port number is a duplicate */ - for (lab = lab->lab_next; lab != NULL; lab = lab->lab_next) + /* Sanity check to see if port number is a duplicate. ONLY */ + /* flag this if the other index has a different text, as it */ + /* is perfectly legal to have multiple ports with the same */ + /* name and index. */ + + for (tlab = lab->lab_next; tlab != NULL; tlab = tlab->lab_next) { - if (lab->lab_flags & PORT_DIR_MASK) - if ((lab->lab_flags & PORT_NUM_MASK) == idx) - { - TxError("Port index %d is used more than once\n", idx); - idx--; - } + if (tlab->lab_flags & PORT_DIR_MASK) + if ((tlab->lab_flags & PORT_NUM_MASK) == idx) + if (strcmp(lab->lab_text, lab->lab_text)) + { + TxError("Index %d is used for ports \"%s\" and \"%s\"\n", + idx, lab->lab_text, tlab->lab_text); + idx--; + } } } else From a4ea827d1e0a30f40fb1ddb49e8de2eeabfc7831 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 28 Oct 2019 13:10:16 -0400 Subject: [PATCH 048/121] More corrections to extresist, which now appears to work if used with ext2spice without the hierarchy option. More work needed to produce correct hierarchical output and to support extraction devices other than the old "fet" record. --- ext2spice/ext2hier.c | 3 +- extflat/EFbuild.c | 238 +++++++++++++++++++++++++++++-------------- extflat/EFdef.c | 22 ++-- extflat/EFflat.c | 4 +- extflat/EFhier.c | 6 +- extflat/EFint.h | 2 +- extflat/EFread.c | 3 +- extflat/EFvisit.c | 8 +- resis/ResReadSim.c | 42 ++++---- 9 files changed, 208 insertions(+), 120 deletions(-) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 7348a0d6..3f660975 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1771,7 +1771,8 @@ esHierVisit(hc, cdata) if (def != topdef) { - if ((def->def_devs == NULL) && (HashGetNumEntries(&def->def_uses) == 0)) + if ((HashGetNumEntries(&def->def_devs) == 0) && + (HashGetNumEntries(&def->def_uses) == 0)) { if (locDoSubckt == AUTO) { diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c index dd2c700e..6999f1af 100644 --- a/extflat/EFbuild.c +++ b/extflat/EFbuild.c @@ -591,23 +591,28 @@ efBuildDevice(def, class, type, r, argc, argv) Rect *r; /* Coordinates of 1x1 rectangle entirely inside device */ int argc; /* Size of argv */ char *argv[]; /* Tokens for the rest of the dev line. - * The first depend on the type of device. The rest - * are taken in groups of 3, one for each terminal. - * Each group of 3 consists of the node name to which - * the terminal connects, the length of the terminal, - * and an attribute list (or the token 0). + * Starts with the last two position values, used to + * hash the device record. The next arguments depend + * on the type of device. The rest are taken in groups + * of 3, one for each terminal. Each group of 3 consists + * of the node name to which the terminal connects, the + * length of the terminal, and an attribute list (or the + * token 0). */ { int n, nterminals, pn; + HashEntry *he; DevTerm *term; Dev *newdev, devtmp; DevParam *newparm, *devp, *sparm; char ptype, *pptr, **av; + char devhash[24]; int argstart = 1; /* start of terminal list in argv[] */ bool hasModel = strcmp(type, "None") ? TRUE : FALSE; int area, perim; /* Total area, perimeter of primary type (i.e., channel) */ + newdev = (Dev *)NULL; devtmp.dev_subsnode = NULL; devtmp.dev_cap = 0.0; devtmp.dev_res = 0.0; @@ -713,7 +718,6 @@ efBuildDevice(def, class, type, r, argc, argv) } /* Check for optional substrate node */ - switch (class) { case DEV_RES: @@ -743,93 +747,149 @@ efBuildDevice(def, class, type, r, argc, argv) nterminals = (argc - argstart) / 3; - newdev = (Dev *) mallocMagic((unsigned) DevSize(nterminals)); - newdev->dev_subsnode = devtmp.dev_subsnode; - newdev->dev_cap = devtmp.dev_cap; - newdev->dev_res = devtmp.dev_res; - newdev->dev_area = devtmp.dev_area; - newdev->dev_perim = devtmp.dev_perim; - newdev->dev_length = devtmp.dev_length; - newdev->dev_width = devtmp.dev_width; - newdev->dev_params = devtmp.dev_params; + /* Determine if this device has been seen before */ - newdev->dev_nterm = nterminals; - newdev->dev_rect = *r; - newdev->dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, type); - newdev->dev_class = class; + sprintf(devhash, "%dx%d", r->r_xbot, r->r_ybot); + he = HashFind(&def->def_devs, devhash); + newdev = (Dev *)HashGetValue(he); + if (newdev) + { + /* Duplicate device. Duplicates will only appear in res.ext files + * where a device has nodes changed. Merge all properties of the + * original device with nodes from the new device. Keep the + * original device and discard the new one. + * + * Check that the device is actually the same device type and number + * of terminals. If not, throw an error and abandon the new device. + */ + + if ((newdev->dev_class != class) || + (strcmp(EFDevTypes[newdev->dev_type], type))) + { + TxError("Device %s %s at (%d, %d) overlaps incompatible device %s %s!\n", + extDevTable[class], type, r->r_xbot, r->r_ybot, + extDevTable[newdev->dev_class], EFDevTypes[newdev->dev_type]); + return 0; + } + else if (newdev->dev_nterm != nterminals) + { + TxError("Device %s %s at (%d, %d) overlaps device with incompatible" + " number of terminals (%d vs. %d)!\n", + extDevTable[class], type, r->r_xbot, r->r_ybot, nterminals, + newdev->dev_nterm); + return 0; + } + } + else + { + newdev = (Dev *) mallocMagic((unsigned) DevSize(nterminals)); + + /* Add this dev to the hash table for def */ + HashSetValue(he, (ClientData)newdev); + + newdev->dev_cap = devtmp.dev_cap; + newdev->dev_res = devtmp.dev_res; + newdev->dev_area = devtmp.dev_area; + newdev->dev_perim = devtmp.dev_perim; + newdev->dev_length = devtmp.dev_length; + newdev->dev_width = devtmp.dev_width; + newdev->dev_params = devtmp.dev_params; + + newdev->dev_nterm = nterminals; + newdev->dev_rect = *r; + newdev->dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, type); + newdev->dev_class = class; + switch (class) + { + case DEV_FET: /* old-style "fet" record */ + newdev->dev_area = atoi(argv[0]); + newdev->dev_perim = atoi(argv[1]); + break; + case DEV_MOSFET: /* new-style "device mosfet" record */ + case DEV_ASYMMETRIC: + case DEV_BJT: + newdev->dev_length = atoi(argv[0]); + newdev->dev_width = atoi(argv[1]); + break; + case DEV_RES: + if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1])) + { + newdev->dev_length = atoi(argv[0]); + newdev->dev_width = atoi(argv[1]); + } + else if (StrIsNumeric(argv[0])) + { + newdev->dev_res = (float)atof(argv[0]); + } + else + { + if (hasModel) + { + efReadError("Error: expected L and W, got %s %s\n", argv[0], + argv[1]); + newdev->dev_length = 0; + newdev->dev_width = 0; + } + else + { + efReadError("Error: expected resistance value, got %s\n", + argv[0]); + newdev->dev_res = 0.0; + } + } + break; + case DEV_CAP: + case DEV_CAPREV: + if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1])) + { + newdev->dev_length = atoi(argv[0]); + newdev->dev_width = atoi(argv[1]); + } + else if (StrIsNumeric(argv[0])) + { + newdev->dev_cap = (float)atof(argv[0]); + } + else + { + if (hasModel) + { + efReadError("Error: expected L and W, got %s %s\n", argv[0], + argv[1]); + newdev->dev_length = 0; + newdev->dev_width = 0; + } + else + { + efReadError("Error: expected capacitance value, got %s\n", + argv[0]); + newdev->dev_cap = 0.0; + } + } + break; + } + } + + newdev->dev_subsnode = devtmp.dev_subsnode; switch (class) { case DEV_FET: /* old-style "fet" record */ - newdev->dev_area = atoi(argv[0]); - newdev->dev_perim = atoi(argv[1]); newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); break; case DEV_MOSFET: /* new-style "device mosfet" record */ case DEV_ASYMMETRIC: case DEV_BJT: - newdev->dev_length = atoi(argv[0]); - newdev->dev_width = atoi(argv[1]); - /* "None" in the place of the substrate name means substrate is ignored */ if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0)) newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); break; case DEV_RES: - if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1])) - { - newdev->dev_length = atoi(argv[0]); - newdev->dev_width = atoi(argv[1]); - } - else if (StrIsNumeric(argv[0])) - { - newdev->dev_res = (float)atof(argv[0]); - } - else - { - if (hasModel) - { - efReadError("Error: expected L and W, got %s %s\n", argv[0], - argv[1]); - newdev->dev_length = 0; - newdev->dev_width = 0; - } - else - { - efReadError("Error: expected resistance value, got %s\n", argv[0]); - newdev->dev_res = 0.0; - } - } if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0)) newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); break; case DEV_CAP: case DEV_CAPREV: - if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1])) - { - newdev->dev_length = atoi(argv[0]); - newdev->dev_width = atoi(argv[1]); - } - else if (StrIsNumeric(argv[0])) - { - newdev->dev_cap = (float)atof(argv[0]); - } - else - { - if (hasModel) - { - efReadError("Error: expected L and W, got %s %s\n", argv[0], - argv[1]); - newdev->dev_length = 0; - newdev->dev_width = 0; - } - else - { - efReadError("Error: expected capacitance value, got %s\n", argv[0]); - newdev->dev_cap = 0.0; - } - } if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0)) newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); @@ -859,10 +919,6 @@ efBuildDevice(def, class, type, r, argc, argv) #undef TERM_PERIM #undef TERM_ATTRS - /* Add this dev to the list for def */ - newdev->dev_next = def->def_devs; - def->def_devs = newdev; - return 0; } @@ -1696,6 +1752,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); + } +} /* * ---------------------------------------------------------------------------- diff --git a/extflat/EFdef.c b/extflat/EFdef.c index 0ef549f1..e0b7c30d 100644 --- a/extflat/EFdef.c +++ b/extflat/EFdef.c @@ -103,7 +103,6 @@ EFDone() Kill *kill; Def *def; Use *use; - Dev *dev; int n; HashStartSearch(&hs); @@ -114,22 +113,18 @@ EFDone() efFreeNodeTable(&def->def_nodes); efFreeNodeList(&def->def_firstn); efFreeUseTable(&def->def_uses); + efFreeDevTable(&def->def_devs); HashKill(&def->def_nodes); HashKill(&def->def_dists); HashKill(&def->def_uses); + HashKill(&def->def_devs); for (conn = def->def_conns; conn; conn = conn->conn_next) efFreeConn(conn); for (conn = def->def_caps; conn; conn = conn->conn_next) efFreeConn(conn); for (conn = def->def_resistors; conn; conn = conn->conn_next) efFreeConn(conn); - for (dev = def->def_devs; dev; dev = dev->dev_next) - { - for (n = 0; n < (int)dev->dev_nterm; n++) - if (dev->dev_terms[n].dterm_attrs) - freeMagic((char *) dev->dev_terms[n].dterm_attrs); - freeMagic((char *) dev); - } + for (kill = def->def_kills; kill; kill = kill->kill_next) { freeMagic(kill->kill_name); @@ -151,13 +146,6 @@ EFDone() EFTech = (char *)NULL; } - /* Free up all HierNames that were stored in efFreeHashTable */ -/* - HashStartSearch(&hs); - while (he = HashNext(&efFreeHashTable, &hs)) - freeMagic(he->h_key.h_ptr); -*/ - /* Free up the parameter name tables for each device */ HashStartSearch(&hs); @@ -244,7 +232,6 @@ efDefNew(name) newdef->def_conns = (Connection *) NULL; newdef->def_caps = (Connection *) NULL; newdef->def_resistors = (Connection *) NULL; - newdef->def_devs = (Dev *) NULL; newdef->def_kills = (Kill *) NULL; /* Initialize circular list of nodes */ @@ -257,6 +244,9 @@ efDefNew(name) /* Initialize hash table of node names */ HashInit(&newdef->def_nodes, INITNODESIZE, HT_STRINGKEYS); + /* Initialize hash table of devices */ + HashInit(&newdef->def_devs, INITNODESIZE, HT_STRINGKEYS); + /* Initialize hash table of distances */ HashInitClient(&newdef->def_dists, INITNODESIZE, HT_CLIENTKEYS, efHNDistCompare, efHNDistCopy, efHNDistHash, efHNDistKill); diff --git a/extflat/EFflat.c b/extflat/EFflat.c index 337c477e..49087720 100644 --- a/extflat/EFflat.c +++ b/extflat/EFflat.c @@ -205,7 +205,7 @@ EFFlatBuildOneLevel(def, flags) if (usecount > 0) efHierSrUses(&efFlatContext, efFlatNodesDeviceless, (ClientData)&usecount); - if ((usecount == 0) && (efFlatRootUse.use_def->def_devs == NULL)) + if ((usecount == 0) && (HashGetNumEntries(&efFlatRootUse.use_def->def_devs) == 0)) efFlatRootUse.use_def->def_flags |= DEF_NODEVICES; /* Record all local nodes */ @@ -372,7 +372,7 @@ efFlatNodesDeviceless(hc, cdata) if (newcount > 0) efHierSrUses(hc, efFlatNodesDeviceless, (ClientData)&newcount); - if ((hc->hc_use->use_def->def_devs == NULL) && (newcount == 0)) + if ((HashGetNumEntries(&hc->hc_use->use_def->def_devs) == 0) && (newcount == 0)) { /* Add all our own nodes to the table */ efAddNodes(hc, TRUE); diff --git a/extflat/EFhier.c b/extflat/EFhier.c index 2b38443e..cef6bd52 100644 --- a/extflat/EFhier.c +++ b/extflat/EFhier.c @@ -471,6 +471,8 @@ efHierVisitDevs(hc, ca) { Def *def = hc->hc_use->use_def; Dev *dev; + HashSearch hs; + HashEntry *he; float scale; /* @@ -482,8 +484,10 @@ efHierVisitDevs(hc, ca) scale = (efScaleChanged && def->def_scale != 1.0) ? def->def_scale : 1.0; /* Visit all devices */ - for (dev = def->def_devs; dev; dev = dev->dev_next) + HashStartSearch(&hs); + while (he = HashNext(&def->def_devs, &hs)) { + dev = (Dev *)HashGetValue(he); if (efHierDevKilled(hc, dev, hc->hc_hierName)) continue; diff --git a/extflat/EFint.h b/extflat/EFint.h index 9c380528..a9cbf2c2 100644 --- a/extflat/EFint.h +++ b/extflat/EFint.h @@ -156,6 +156,7 @@ typedef struct def HashTable def_nodes; /* Map names into EFNodeNames */ HashTable def_dists; /* Map pairs of names into Distances */ HashTable def_uses; /* Hash children of this def by name */ + HashTable def_devs; /* Devices (hash by position) */ EFNode def_firstn; /* Head of circular list of nodes */ /* The following are all NULL-terminated lists */ @@ -163,7 +164,6 @@ typedef struct def Connection *def_conns; /* Hierarchical connections/adjustments */ Connection *def_caps; /* Two-terminal capacitors */ Connection *def_resistors; /* Two-terminal resistors */ - Dev *def_devs; /* Devices */ Kill *def_kills; /* Used to modify hierarchical structure * using information present only in the * parent, e.g, to kill an old node and diff --git a/extflat/EFread.c b/extflat/EFread.c index b57477fb..c5901293 100644 --- a/extflat/EFread.c +++ b/extflat/EFread.c @@ -356,8 +356,7 @@ readfile: r.r_xtop = atoi(argv[5]); r.r_ytop = atoi(argv[6]); - if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7, - &argv[7]) != 0) + if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7, &argv[7]) != 0) { efReadError("Incomplete terminal description for device\n"); continue; diff --git a/extflat/EFvisit.c b/extflat/EFvisit.c index 8d802edd..35de6766 100644 --- a/extflat/EFvisit.c +++ b/extflat/EFvisit.c @@ -300,6 +300,8 @@ efVisitDevs(hc, ca) Dev *dev; float scale; Transform t; + HashSearch hs; + HashEntry *he; if (def->def_flags & DEF_SUBCIRCUIT) return 0; @@ -311,15 +313,17 @@ efVisitDevs(hc, ca) t = hc->hc_trans; /* Visit our own devices */ - for (dev = def->def_devs; dev; dev = dev->dev_next) + + HashStartSearch(&hs); + while (he = HashNext(&def->def_devs, &hs)) { + dev = (Dev *)HashGetValue(he); if (efDevKilled(dev, hc->hc_hierName)) continue; if ((*ca->ca_proc)(dev, hc->hc_hierName, scale, &t, ca->ca_cdata)) return 1; } - return 0; } diff --git a/resis/ResReadSim.c b/resis/ResReadSim.c index 6d9dad10..4a447aa8 100644 --- a/resis/ResReadSim.c +++ b/resis/ResReadSim.c @@ -79,7 +79,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ ResSimNode *ResInitializeNode(); ResSimNode *ResOriginalNodes; /*Linked List of Nodes */ -static float lambda=1.0; /* Scale factor */ +static float resscale=1.0; /* Scale factor */ char RDEV_NOATTR[1]={'0'}; ResFixPoint *ResFixList; @@ -146,12 +146,8 @@ ResReadSim(simfile,fetproc,capproc,resproc,attrproc,mergeproc) case '|': if (strcmp(line[NODEUNITS],"units:") == 0) { - lambda = (float)atof(line[NODELAMBDA]); - if (lambda == 0.0) lambda = 1.0; - /* NOTE: units is derived from EFScale */ - /* which needs a factor of 100 conversion */ - /* to database units. */ - lambda *= 100.0; + resscale = (float)atof(line[NODELAMBDA]); + if (resscale == 0.0) resscale = 1.0; } result=0; break; @@ -231,6 +227,14 @@ ResReadNode(nodefile) HashEntry *entry; ResSimNode *node; char *cp; + float lambda; + + /* NOTE: Units from the .sim file or the .nodes file are in centimicrons + * when multiplied by resscale (units from the .sim file 1st line). + * multiply resscale by the extract scale (exts_unitsPerLambda) used to + * generate .ext dimensions originally, to get back to database units. + */ + lambda = resscale * (float)ExtCurStyle->exts_unitsPerLambda; fp = PaOpen(nodefile,"r",".nodes",".", (char *) NULL, (char **) NULL); if (fp == NULL) @@ -243,17 +247,13 @@ ResReadNode(nodefile) entry = HashFind(&ResNodeTable,line[NODENODENAME]); node = ResInitializeNode(entry); - /* NOTE: Fixed 10/15/2019. No scalefactor is passed to EFNodeVisit() - * so there is no scaling by lambda. Values are in centimicrons always, - * and factor of 100 is required to get database units. - */ - node->location.p_x = (int)((float)atof(line[NODENODEX]) / 100.0); - node->location.p_y = (int)((float)atof(line[NODENODEY]) / 100.0); + node->location.p_x = (int)((float)atof(line[NODENODEX]) / lambda); + node->location.p_y = (int)((float)atof(line[NODENODEY]) / lambda); #ifdef ARIEL - node->rs_bbox.r_xbot = (int)((float)atof(line[NODE_BBOX_LL_X]) / 100.0); - node->rs_bbox.r_ybot = (int)((float)atof(line[NODE_BBOX_LL_Y]) / 100.0); - node->rs_bbox.r_xtop = (int)((float)atof(line[NODE_BBOX_UR_X]) / 100.0); - node->rs_bbox.r_ytop = (int)((float)atof(line[NODE_BBOX_UR_Y]) / 100.0); + node->rs_bbox.r_xbot = (int)((float)atof(line[NODE_BBOX_LL_X]) / lambda); + node->rs_bbox.r_ybot = (int)((float)atof(line[NODE_BBOX_LL_Y]) / lambda); + node->rs_bbox.r_xtop = (int)((float)atof(line[NODE_BBOX_UR_X]) / lambda); + node->rs_bbox.r_ytop = (int)((float)atof(line[NODE_BBOX_UR_Y]) / lambda); #endif if (cp = strchr(line[NODETYPE], ';')) *cp = '\0'; node->type = DBTechNameType(line[NODETYPE]); @@ -340,6 +340,7 @@ ResSimDevice(line,rpersquare,ttype) int rvalue,i,j,k; char *newattr,tmpattr[MAXTOKEN]; static int nowarning = TRUE; + float lambda; device = (RDev *) mallocMagic((unsigned) (sizeof(RDev))); if ((line[RDEV_WIDTH][0] == '\0') || (line[RDEV_LENGTH][0] == '\0')) @@ -360,8 +361,11 @@ ResSimDevice(line,rpersquare,ttype) device->tnumber = ++Maxtnumber; device->status = FALSE; device->nextDev = ResRDevList; - device->location.p_x = atoi(line[RDEV_DEVX]); - device->location.p_y = atoi(line[RDEV_DEVY]); + + lambda = resscale * (float)ExtCurStyle->exts_unitsPerLambda; + device->location.p_x = (int)((float)atof(line[RDEV_DEVX]) / lambda); + device->location.p_y = (int)((float)atof(line[RDEV_DEVY]) / lambda); + device->rs_gattr=RDEV_NOATTR; device->rs_sattr=RDEV_NOATTR; device->rs_dattr=RDEV_NOATTR; From c342178458a937750108f71b3fc705c189f40dec Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 29 Oct 2019 09:44:28 -0400 Subject: [PATCH 049/121] Made some changes to the way that ext2spice generates subcircuit ports, to avoid creating ports for node names that are redundant. It would probably be better to avoid creating the redundant node names in the first place; however, I am less certain why these are generated. The incorrect additional ports all have hierarchical names in the cell, which is a sign that they are incorrect, as the cell itself should not have any parents. The level of certainty about this fix is definitely not 100%, but it was tested on a hierarchical analog design, and setting levels of parasitic caps caused new nodes to appear in subcircuits and in no cases did information appear to be lost. --- ext2spice/ext2hier.c | 7 ++++--- ext2spice/ext2spice.c | 39 ++++++++++++++++++++++++--------------- extflat/EFflat.c | 1 + 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 3f660975..9b90f6a3 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1625,6 +1625,10 @@ esMakePorts(hc, cdata) { nn->efnn_node->efnode_flags |= EF_PORT; nn->efnn_port = -1; // Will be sorted later + + // Diagnostic + TxPrintf("Port connection in %s from net %s to net %s (%s)\n", + def->def_name, locname, name, portname); } } @@ -1634,9 +1638,6 @@ esMakePorts(hc, cdata) updef = portdef; } - // Diagnostic - // TxPrintf("Connection in %s to net %s (%s)\n", def->def_name, - // name, portname); } } diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index e2e560f4..03ac5e78 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -1615,7 +1615,7 @@ topVisit(def, doStub) Def *def; bool doStub; { - EFNode *snode; + EFNode *snode, *basenode; EFNodeName *sname, *nodeName; HashSearch hs; HashEntry *he; @@ -1668,7 +1668,9 @@ topVisit(def, doStub) snode = sname->efnn_node; if (snode->efnode_flags & EF_PORT) - if (snode->efnode_name->efnn_port < 0) + { + pname = nodeSpiceName(snode->efnode_name->efnn_hier, &basenode); + if (basenode->efnode_name->efnn_port < 0) { if (tchars > 80) { @@ -1676,11 +1678,13 @@ topVisit(def, doStub) fprintf(esSpiceF, "\n+"); tchars = 1; } - pname = nodeSpiceName(snode->efnode_name->efnn_hier); fprintf(esSpiceF, " %s", pname); tchars += strlen(pname) + 1; - snode->efnode_name->efnn_port = portorder++; + basenode->efnode_name->efnn_port = portorder++; } + if (snode->efnode_name->efnn_hier->hn_parent == NULL) + snode->efnode_name->efnn_port = basenode->efnode_name->efnn_port; + } } } else @@ -1714,7 +1718,7 @@ topVisit(def, doStub) fprintf(esSpiceF, "\n+"); tchars = 1; } - pname = nodeSpiceName(snode->efnode_name->efnn_hier); + pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL); fprintf(esSpiceF, " %s", pname); tchars += strlen(pname) + 1; break; @@ -2771,7 +2775,8 @@ FILE *outf; /* Canonical name */ nn = (EFNodeName *) HashGetValue(he); if (outf) - fprintf(outf, "%s", nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier)); + fprintf(outf, "%s", nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier, + NULL)); /* Mark node as visited */ if ((nodeClient *)nn->efnn_node->efnode_client == (ClientData)NULL) @@ -2982,7 +2987,7 @@ spcdevOutNode(prefix, suffix, name, outf) return 0; } nn = (EFNodeName *) HashGetValue(he); - nname = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier); + nname = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier, NULL); fprintf(outf, " %s", nname); /* Mark node as visited */ @@ -3028,8 +3033,8 @@ spccapVisit(hierName1, hierName2, cap) if (cap <= EFCapThreshold) return 0; - fprintf(esSpiceF, esSpiceCapFormat ,esCapNum++,nodeSpiceName(hierName1), - nodeSpiceName(hierName2), cap); + fprintf(esSpiceF, esSpiceCapFormat ,esCapNum++,nodeSpiceName(hierName1, NULL), + nodeSpiceName(hierName2, NULL), cap); return 0; } @@ -3064,8 +3069,8 @@ spcresistVisit(hierName1, hierName2, res) HierName *hierName2; float res; { - fprintf(esSpiceF, "R%d %s %s %g\n", esResNum++, nodeSpiceName(hierName1), - nodeSpiceName(hierName2), res / 1000.); + fprintf(esSpiceF, "R%d %s %s %g\n", esResNum++, nodeSpiceName(hierName1, NULL), + nodeSpiceName(hierName2, NULL), res / 1000.); return 0; } @@ -3100,7 +3105,7 @@ spcsubVisit(node, res, cap, resstr) if (node->efnode_flags & EF_SUBS_NODE) { hierName = (HierName *) node->efnode_name->efnn_hier; - nsn = nodeSpiceName(hierName); + nsn = nodeSpiceName(hierName, NULL); *resstr = StrDup((char **)NULL, nsn); return 1; } @@ -3150,7 +3155,7 @@ spcnodeVisit(node, res, cap) if (!isConnected && node->efnode_flags & EF_PORT) isConnected = TRUE; hierName = (HierName *) node->efnode_name->efnn_hier; - nsn = nodeSpiceName(hierName); + nsn = nodeSpiceName(hierName, NULL); if (esFormat == SPICE2 || esFormat == HSPICE && strncmp(nsn, "z@", 2)==0 ) { static char ntmp[MAX_STR_SIZE]; @@ -3195,7 +3200,7 @@ nodeVisitDebug(node, res, cap) EFAttr *ap; hierName = (HierName *) node->efnode_name->efnn_hier; - nsn = nodeSpiceName(hierName); + nsn = nodeSpiceName(hierName, NULL); TxError("** %s (%x)\n", nsn, node); printf("\t client.name=%s, client.m_w=%p\n", @@ -3218,23 +3223,27 @@ nodeVisitDebug(node, res, cap) * * Side effects: * Allocates nodeClients for the node. + * Returns the node in the "rnode" pointer, if non-NULL. * * ---------------------------------------------------------------------------- */ static char esTempName[MAX_STR_SIZE]; -char *nodeSpiceName(hname) +char *nodeSpiceName(hname, rnode) HierName *hname; + EFNode **rnode; { EFNodeName *nn; HashEntry *he; EFNode *node; + if (rnode) *rnode = (EFNode *)NULL; he = EFHNLook(hname, (char *) NULL, "nodeName"); if ( he == NULL ) return "errGnd!"; nn = (EFNodeName *) HashGetValue(he); node = nn->efnn_node; + if (rnode) *rnode = node; if ( (nodeClient *) (node->efnode_client) == NULL ) { initNodeClient(node); diff --git a/extflat/EFflat.c b/extflat/EFflat.c index 49087720..bd02d9c9 100644 --- a/extflat/EFflat.c +++ b/extflat/EFflat.c @@ -527,6 +527,7 @@ efAddNodes(hc, stdcell) HashSetValue(he, (char *) newname); newname->efnn_node = newnode; newname->efnn_hier = hierName; + newname->efnn_port = -1; if (newnode->efnode_name) { newname->efnn_next = newnode->efnode_name->efnn_next; From fc86f44bb16da80f37bbca7f286843d66e77d210 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 29 Oct 2019 13:55:28 -0400 Subject: [PATCH 050/121] Again revisited the problem of duplicate nodes. This time, I think I understand the problem, which is that nodes are ordered according to precedence of EFHNBest() within a circuit, but there is no concept of ordering between circuits. So ports end up listing nodes in arbitrary order, and the only way to resolve the order is to use EFHNBest() as is done within a subcircuit. Appears to work for different edge cases tested. --- ext2spice/ext2hier.c | 4 +-- ext2spice/ext2spice.c | 66 +++++++++++++++++++++++++++---------------- 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 9b90f6a3..6f6fc555 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1627,8 +1627,8 @@ esMakePorts(hc, cdata) 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); + // TxPrintf("Port connection in %s from net %s to net %s (%s)\n", + // def->def_name, locname, name, portname); } } diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 03ac5e78..168959cf 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -1372,10 +1372,11 @@ subcktVisit(use, hierName, is_top) EFNode *snode; Def *def = use->use_def; EFNodeName *nodeName; - int portorder, portmax, imp_max, tchars; + int portorder, portmax, portidx, imp_max, tchars; char stmp[MAX_STR_SIZE]; char *instname, *subcktname; DevParam *plist, *pptr; + EFNodeName **nodeList; if (is_top == TRUE) return 0; /* Ignore the top-level cell */ @@ -1467,35 +1468,53 @@ subcktVisit(use, hierName, is_top) /* Port numbers need not start at zero or be contiguous. */ /* They will be printed in numerical order. */ - portorder = 0; - while (portorder <= portmax) - { - for (snode = (EFNode *) def->def_firstn.efnode_next; + nodeList = (EFNodeName **)mallocMagic((portmax + 1) * sizeof(EFNodeName *)); + for (portidx = 0; portidx <= portmax; portidx++) + nodeList[portidx] = (EFNodeName *)NULL; + + for (snode = (EFNode *) def->def_firstn.efnode_next; snode != &def->def_firstn; snode = (EFNode *) snode->efnode_next) - { - if (!(snode->efnode_flags & EF_PORT)) continue; - for (nodeName = snode->efnode_name; nodeName != NULL; + { + if (!(snode->efnode_flags & EF_PORT)) continue; + for (nodeName = snode->efnode_name; nodeName != NULL; nodeName = nodeName->efnn_next) + { + EFNodeName *nn; + HashEntry *he; + char *pname; + + portidx = nodeName->efnn_port; + if (nodeList[portidx] == NULL) { - int portidx = nodeName->efnn_port; - if (portidx == portorder) - { - if (tchars > 80) - { - fprintf(esSpiceF, "\n+"); - tchars = 1; - } - tchars += spcdevOutNode(hierName, nodeName->efnn_hier, - "subcircuit", esSpiceF); - break; - } + nodeList[portidx] = nodeName; + } + else if (EFHNBest(nodeName->efnn_hier, nodeList[portidx]->efnn_hier)) + { + nodeList[portidx] = nodeName; } - if (nodeName != NULL) break; } - portorder++; } + for (portidx = 0; portidx <= portmax; portidx++) + { + nodeName = nodeList[portidx]; + + if (nodeName == NULL) + TxError("No port connection on port %d; need to resolve.\n", portidx); + else + { + if (tchars > 80) + { + fprintf(esSpiceF, "\n+"); + tchars = 1; + } + tchars += spcdevOutNode(hierName, nodeName->efnn_hier, + "subcircuit", esSpiceF); + } + } + freeMagic(nodeList); + /* Look for all implicit substrate connections that are */ /* declared as local node names, and put them last. */ @@ -1682,8 +1701,7 @@ topVisit(def, doStub) tchars += strlen(pname) + 1; basenode->efnode_name->efnn_port = portorder++; } - if (snode->efnode_name->efnn_hier->hn_parent == NULL) - snode->efnode_name->efnn_port = basenode->efnode_name->efnn_port; + snode->efnode_name->efnn_port = basenode->efnode_name->efnn_port; } } } From ecfdb6641793bab922e1842ee372cf29f4ef44d6 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 31 Oct 2019 15:19:30 -0400 Subject: [PATCH 051/121] Corrected one error in the recent fix for port enumeration in ext2spice (hierarchy on), where the port index was not checked for value -1 (no port) before indexing into the port list. --- ext2spice/ext2spice.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 168959cf..65eb7326 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -1485,6 +1485,7 @@ subcktVisit(use, hierName, is_top) char *pname; portidx = nodeName->efnn_port; + if (portidx < 0) continue; if (nodeList[portidx] == NULL) { nodeList[portidx] = nodeName; From 0f45014d1896591d99683dae70e5686a02b3a1d7 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 1 Nov 2019 10:16:43 -0400 Subject: [PATCH 052/121] Corrected an erroneous scalefactor used when reading geometry attached to a label in a GDS input file; the scalefactor that was being used is reset at the beginning of a GDS read, and so becomes invalid after a database rescaling, resulting in improperly scaled label geometry if "gds read" is used more than once. --- calma/CalmaRdpt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/calma/CalmaRdpt.c b/calma/CalmaRdpt.c index 61e6e87f..f0edac74 100644 --- a/calma/CalmaRdpt.c +++ b/calma/CalmaRdpt.c @@ -291,10 +291,10 @@ calmaElementBoundary() /* Convert rp to magic database units to compare to label rects */ rpc = rp->r_r; - rpc.r_xbot /= calmaReadScale1; - rpc.r_xtop /= calmaReadScale1; - rpc.r_ybot /= calmaReadScale1; - rpc.r_ytop /= calmaReadScale1; + rpc.r_xbot /= cifCurReadStyle->crs_scaleFactor; + rpc.r_xtop /= cifCurReadStyle->crs_scaleFactor; + rpc.r_ybot /= cifCurReadStyle->crs_scaleFactor; + rpc.r_ytop /= cifCurReadStyle->crs_scaleFactor; if ((ciftype >= 0) && (cifCurReadStyle->crs_labelSticky[ciftype] != LABEL_TYPE_NONE)) From 8e85c3a96e1af4a4de2dda680c6ec3f28250f8d4 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 1 Nov 2019 12:01:07 -0400 Subject: [PATCH 053/121] Corrected a long-standing error in the "widespacing" rule implementation that was intended to avoid computing maxwidth more than necessary, but ended up causing the widespacing rule to not be checked in certain situations. --- drc/DRCbasic.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drc/DRCbasic.c b/drc/DRCbasic.c index a3d2cbbf..78afd398 100644 --- a/drc/DRCbasic.c +++ b/drc/DRCbasic.c @@ -484,6 +484,7 @@ drcTile (tile, arg) int edgeX = LEFT(tile); firsttile = TRUE; + mrd = NULL; for (tpleft = BL(tile); BOTTOM(tpleft) < top; tpleft = RT(tpleft)) { /* Get the tile types to the left and right of the edge */ @@ -554,8 +555,6 @@ drcTile (tile, arg) mrd = drcCanonicalMaxwidth(tpleft, GEO_WEST, arg, cptr); else if (firsttile) mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr); - else - mrd = NULL; if (!trigpending || (DRCCurStyle->DRCFlags & DRC_FLAGS_WIDEWIDTH_NONINCLUSIVE)) cptr->drcc_dist--; @@ -610,7 +609,6 @@ drcTile (tile, arg) drcCheckMaxwidth(tile, arg, cptr); continue; } - else if (!triggered) mrd = NULL; if (cptr->drcc_flags & DRC_RECTSIZE) { @@ -870,6 +868,7 @@ checkbottom: /* Go right across bottom of tile */ firsttile = TRUE; + mrd = NULL; for (tpbot = LB(tile); LEFT(tpbot) < right; tpbot = TR(tpbot)) { /* Get the tile types to the top and bottom of the edge */ @@ -936,8 +935,6 @@ checkbottom: mrd = drcCanonicalMaxwidth(tpbot, GEO_SOUTH, arg, cptr); else if (firsttile) mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr); - else - mrd = NULL; if (!trigpending || (DRCCurStyle->DRCFlags & DRC_FLAGS_WIDEWIDTH_NONINCLUSIVE)) cptr->drcc_dist--; @@ -992,7 +989,6 @@ checkbottom: if (trigpending) cptr = cptr->drcc_next; continue; } - else if (!triggered) mrd = NULL; result = 0; arg->dCD_radial = 0; From 0aca80dbc2dee73fe9c1d800322430804499f0ad Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 1 Nov 2019 13:23:31 -0400 Subject: [PATCH 054/121] Corrected problem that can cause magic to crash on a "lef read" command due to an uninitialized variable. --- lef/lefWrite.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 282b1bda..8e2106c4 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -121,6 +121,8 @@ lefFileOpen(def, file, suffix, mode, prealfile) else locsuffix = NULL; } + else + locsuffix = suffix; /* Try once as-is, and if this fails, try stripping any leading */ /* path information in case cell is in a read-only directory (mode */ From 855e4ca134c57ad677ef80bb3b8dc08f8f28c28c Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 11 Nov 2019 15:56:17 -0500 Subject: [PATCH 055/121] Corrected an apparently long-standing error with the triggered rules (such as widespacing or directional surround) that will cause the rule to be triggered without a cause due to a failure to reset the error count from a previous triggered rule (the condition of failure is much more rare than this explanation makes it sound, which is why it went undiscovered for so long). --- drc/DRCbasic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drc/DRCbasic.c b/drc/DRCbasic.c index 78afd398..77ecd09b 100644 --- a/drc/DRCbasic.c +++ b/drc/DRCbasic.c @@ -623,6 +623,7 @@ drcTile (tile, arg) result = 0; arg->dCD_radial = 0; + arg->dCD_entries = 0; do { if (triggered) { @@ -992,6 +993,7 @@ checkbottom: result = 0; arg->dCD_radial = 0; + arg->dCD_entries = 0; do { if (triggered) { From e3624d3e5f5e6f729fa0764660b76f24bffc8ee2 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 12 Nov 2019 21:46:52 -0500 Subject: [PATCH 056/121] Added code to avoid a problem with "lef write" when a sticky label is placed over multiple types. This causes SelectChunk() to fail and the pin will have no geometry output in the LEF file. To avoid this, the area of the label is always painted into the select cell so that if SelectChunk() fails, the label area still exists with the label tile type. --- lef/lefWrite.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 8e2106c4..da03bacf 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -933,7 +933,18 @@ lefWriteMacro(def, f, scale, hide) SelectClear(); if (hide) + { SelectChunk(&scx, lab->lab_type, 0, NULL, FALSE); + + /* Note that a sticky label could be placed over multiple */ + /* tile types, which would cause SelectChunk to fail. So */ + /* always paint the label type into the label area in */ + /* SelectDef. */ + + pNum = DBPlane(lab->lab_type); + DBPaintPlane(SelectDef->cd_planes[pNum], &lab->lab_rect, + DBStdPaintTbl(lab->lab_type, pNum), (PaintUndoInfo *) NULL); + } else SelectNet(&scx, lab->lab_type, 0, NULL, FALSE); @@ -1042,6 +1053,7 @@ lefWriteMacro(def, f, scale, hide) scx.scx_area = labr; SelectClear(); SelectChunk(&scx, lab->lab_type, 0, &carea, FALSE); + if (GEO_RECTNULL(&carea)) carea = lab->lab_rect; lspace = DRCGetDefaultLayerSpacing(lab->lab_type, lab->lab_type); carea.r_xbot -= lspace; carea.r_ybot -= lspace; From 3a6f868efce5ac338fb4c85e7b8612378eacd1af Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 13 Nov 2019 13:05:03 -0500 Subject: [PATCH 057/121] Corrected an error in ext2spice caused by recent changes, that can generate an extra node in the extract output that comes out as a "(none)" node in the SPICE netlist from ext2spice. --- extflat/EFbuild.c | 4 ++-- extract/ExtBasic.c | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c index 6999f1af..f3ab37b5 100644 --- a/extflat/EFbuild.c +++ b/extflat/EFbuild.c @@ -606,7 +606,7 @@ efBuildDevice(def, class, type, r, argc, argv) Dev *newdev, devtmp; DevParam *newparm, *devp, *sparm; char ptype, *pptr, **av; - char devhash[24]; + char devhash[64]; int argstart = 1; /* start of terminal list in argv[] */ bool hasModel = strcmp(type, "None") ? TRUE : FALSE; @@ -749,7 +749,7 @@ efBuildDevice(def, class, type, r, argc, argv) /* Determine if this device has been seen before */ - sprintf(devhash, "%dx%d", r->r_xbot, r->r_ybot); + sprintf(devhash, "%dx%d%s", r->r_xbot, r->r_ybot, type); he = HashFind(&def->def_devs, devhash); newdev = (Dev *)HashGetValue(he); if (newdev) diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index e0503d20..c3067466 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -1686,6 +1686,7 @@ extOutputDevices(def, transList, outFile) while (TRUE) { + if (devptr == NULL) break; /* Bad device */ nsd = devptr->exts_deviceSDCount; for (termcount = 0; termcount < nsd; termcount++) { @@ -1726,6 +1727,7 @@ extOutputDevices(def, transList, outFile) devptr = extDevFindMatch(devptr, t); break; } + if (termcount == nsd) break; /* All terminals accounted for */ } if (termcount == nsd) break; /* All terminals accounted for */ if (devptr == deventry) break; /* No other device records available */ @@ -1771,6 +1773,11 @@ extOutputDevices(def, transList, outFile) /* It is not an error condition to have more terminals */ /* than the minimum. */ } + if (devptr == NULL) { + TxError("Warning: No matching extraction type for device at (%d %d)\n", + reg->treg_tile->ti_ll.p_x, reg->treg_tile->ti_ll.p_y); + continue; + } /* * Output the transistor record. From 8e22b1504ec6dfe1a598bc44ed4124769ccd62a2 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 13 Nov 2019 14:29:19 -0500 Subject: [PATCH 058/121] Corrected an error introduced with the extension of extraction methods to multiple entries per device; the resistor length and width calculating routine lost a break statement and would go into an infinite loop for resistors with bends in them. --- extract/ExtBasic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index c3067466..1894d30e 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -2919,7 +2919,8 @@ extResistorTileFunc(tile, pNum) extEnumTilePerim(tile, mask, pNum, extSpecialPerimFunc, (ClientData)FALSE); - if (extSpecialBounds[0] == NULL) devptr = devptr->exts_next; + if (extSpecialBounds[0] != NULL) break; + devptr = devptr->exts_next; } if (devptr != NULL) extTransRec.tr_devrec = devptr; From 5007f3f6026851a16aed9b0d0a30f3d19a548931 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 13 Nov 2019 15:10:01 -0500 Subject: [PATCH 059/121] Modified "lef write" so that if a cell has a bounding box declared by FIXED_BBOX derived from GDS and the new "boundary" cif input rule, then the bbox property values take precedence over the extent-of-geometry bounding box. --- lef/lefWrite.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lef/lefWrite.c b/lef/lefWrite.c index da03bacf..3adfc12a 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -778,6 +778,20 @@ lefWriteMacro(def, f, scale, hide) else boundary = def->cd_bbox; + /* If a bounding box has been declared with the FIXED_BBOX property */ + /* then it takes precedence over def->cd_bbox. */ + + if (def->cd_flags & CDFIXEDBBOX) + { + char *propvalue; + bool found; + + propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &found); + if (found) + sscanf(propvalue, "%d %d %d %d", &boundary.r_xbot, + &boundary.r_ybot, &boundary.r_xtop, &boundary.r_ytop); + } + /* Write position and size information */ fprintf(f, " ORIGIN %.4f %.4f ;\n", From 0eb3b1fe1c1b3ce3121d411a982b48e9356fc5b8 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 14 Nov 2019 15:18:26 -0500 Subject: [PATCH 060/121] Corrected an error in ext2spice related to the recent modification to get rid of redundant port entries in subcircuits. There is still an outstanding issue as to whether nodes and connections need to be recursively iterated to the hierarchy bottom. The current fix corrected the test case. Also, added a "-dereference" option to the "load" command to revert to the original behavior of using only search paths from "addpath" when searching for files to load. --- calma/CalmaRead.c | 2 +- calma/CalmaWrite.c | 2 +- cif/CIFwrite.c | 2 +- commands/CmdCD.c | 4 ++-- commands/CmdE.c | 2 +- commands/CmdLQ.c | 27 +++++++++++++++++++++------ commands/CmdSubrs.c | 2 +- commands/CmdTZ.c | 4 ++-- database/DBcellsrch.c | 18 +++++++++--------- database/DBcellsubr.c | 2 +- database/DBexpand.c | 8 ++++---- database/DBio.c | 19 +++++++++++-------- database/DBlabel2.c | 4 ++-- database/DBtimestmp.c | 2 +- dbwind/DBWprocs.c | 14 ++++++++------ drc/DRCmain.c | 2 +- extflat/EFflat.c | 28 +++++++++++++++++----------- extract/ExtInter.c | 6 +++--- graphics/W3Dmain.c | 2 +- lef/defRead.c | 2 +- sim/SimDBstuff.c | 2 +- windows/windView.c | 2 +- 22 files changed, 91 insertions(+), 65 deletions(-) diff --git a/calma/CalmaRead.c b/calma/CalmaRead.c index 9421a9af..0f4cab1d 100644 --- a/calma/CalmaRead.c +++ b/calma/CalmaRead.c @@ -227,7 +227,7 @@ done: if (mw != NULL) { if (calmaLookCell(libname, NULL) != (CellDef *)NULL) - DBWloadWindow(mw, libname, FALSE); + DBWloadWindow(mw, libname, FALSE, FALSE); } freeMagic(libname); } diff --git a/calma/CalmaWrite.c b/calma/CalmaWrite.c index 8a8842f3..0480238f 100644 --- a/calma/CalmaWrite.c +++ b/calma/CalmaWrite.c @@ -746,7 +746,7 @@ calmaProcessDef(def, outf) /* Read the cell in if it is not already available. */ if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) + if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return (0); /* diff --git a/cif/CIFwrite.c b/cif/CIFwrite.c index 59ff26a5..147be067 100644 --- a/cif/CIFwrite.c +++ b/cif/CIFwrite.c @@ -312,7 +312,7 @@ cifOut(outf) /* Read the cell in if it is not already available. */ if ((def->cd_flags & CDAVAILABLE) == 0) { - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) continue; + if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) continue; } /* Add any subcells to the stack. This must be done before diff --git a/commands/CmdCD.c b/commands/CmdCD.c index 88607b96..6fdcb4ad 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -3079,7 +3079,7 @@ CmdDown(w, cmd) GeoTransRect(&EditToRootTransform, &(EditCellUse->cu_def->cd_bbox), &area); (void) WindSearch(DBWclientID, (ClientData) NULL, (Rect *) NULL, cmdEditRedisplayFunc, (ClientData) &area); - DBWloadWindow(w, EditCellUse->cu_def->cd_name, TRUE, FALSE); + DBWloadWindow(w, EditCellUse->cu_def->cd_name, TRUE, FALSE, FALSE); } /* Search function to find the new edit cell: look for a cell use @@ -3777,7 +3777,7 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx) * looked for then no new error message will be printed. */ def->cd_flags &= ~CDNOTFOUND; - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) + if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return (FALSE); DBReComputeBbox(def); dummy->cu_def = def; diff --git a/commands/CmdE.c b/commands/CmdE.c index 7be73fe8..57883c25 100644 --- a/commands/CmdE.c +++ b/commands/CmdE.c @@ -130,7 +130,7 @@ CmdEdit(w, cmd) return; } else if (!(EditCellUse->cu_def->cd_flags & CDAVAILABLE)) - DBCellRead(EditCellUse->cu_def, (char *)NULL, TRUE, NULL); + DBCellRead(EditCellUse->cu_def, (char *)NULL, TRUE, FALSE, NULL); if (EditCellUse->cu_def->cd_flags & CDNOEDIT) { diff --git a/commands/CmdLQ.c b/commands/CmdLQ.c index 02c04b6f..8427fb8d 100644 --- a/commands/CmdLQ.c +++ b/commands/CmdLQ.c @@ -318,7 +318,7 @@ CmdLabel(w, cmd) * Implement the "load" command. * * Usage: - * load [name [scaled n [d]]] [-force] [-nowindow] + * load [name [scaled n [d]]] [-force] [-nowindow] [-dereference] * * If name is supplied, then the window containing the point tool is * remapped so as to edit the cell with the given name. @@ -331,6 +331,13 @@ CmdLabel(w, cmd) * An input file can be scaled by specifying the "scaled" option, for * which the geometry of the input file is multiplied by n/d. * + * Magic saves the path to instances to ensure correct versioning. But + * this interferes with attempts to re-link instances from a different + * location (such as an abstract view instead of a full view, or vice + * versa). So the "-dereference" option strips the instance paths from + * the input file and relies only on the search locations set up by the + * "path" command to find the location of instances. + * * Results: * None. * @@ -350,6 +357,7 @@ CmdLoad(w, cmd) int locargc = cmd->tx_argc; bool ignoreTech = FALSE; bool noWindow = FALSE; + bool dereference = FALSE; int keepGoing(); /* forward declaration */ if (locargc > 2) @@ -359,6 +367,11 @@ CmdLoad(w, cmd) locargc--; noWindow = TRUE; } + if (!strncmp(cmd->tx_argv[locargc - 1], "-deref", 5)) + { + locargc--; + dereference = TRUE; + } if (!strncmp(cmd->tx_argv[locargc - 1], "-force", 6)) { locargc--; @@ -372,7 +385,8 @@ CmdLoad(w, cmd) d = atoi(cmd->tx_argv[4]); else if (locargc != 4) { - TxError("Usage: %s name scaled n [d] [-force] [-nowindow]\n", + TxError("Usage: %s name scaled n [d] [-force] " + "[-nowindow] [-dereference]\n", cmd->tx_argv[0]); return; } @@ -380,9 +394,10 @@ CmdLoad(w, cmd) DBLambda[1] *= n; ReduceFraction(&DBLambda[0], &DBLambda[1]); } - else if (!ignoreTech && !noWindow) + else if (!ignoreTech && !noWindow && !dereference) { - TxError("Usage: %s name [scaled n [d]] [-force] [-nowindow]\n", + TxError("Usage: %s name [scaled n [d]] [-force] " + "[-nowindow] [-dereference]\n", cmd->tx_argv[0]); return; } @@ -408,7 +423,7 @@ CmdLoad(w, cmd) } #endif DBWloadWindow((noWindow == TRUE) ? NULL : w, cmd->tx_argv[1], - ignoreTech, FALSE); + ignoreTech, FALSE, dereference); if ((n > 1) || (d > 1)) { @@ -441,7 +456,7 @@ CmdLoad(w, cmd) ReduceFraction(&DBLambda[0], &DBLambda[1]); } } - else DBWloadWindow(w, (char *) NULL, TRUE, FALSE); + else DBWloadWindow(w, (char *) NULL, TRUE, FALSE, FALSE); } /* diff --git a/commands/CmdSubrs.c b/commands/CmdSubrs.c index bdb34cce..ec63be1c 100644 --- a/commands/CmdSubrs.c +++ b/commands/CmdSubrs.c @@ -309,7 +309,7 @@ cmdFlushCell(def) } DBCellClearDef(def); DBCellClearAvail(def); - (void) DBCellRead(def, (char *) NULL, TRUE, NULL); + (void) DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL); DBCellSetAvail(def); DBReComputeBbox(def); DBCellSetModified(def, FALSE); diff --git a/commands/CmdTZ.c b/commands/CmdTZ.c index ff9559d9..d21e3cbb 100644 --- a/commands/CmdTZ.c +++ b/commands/CmdTZ.c @@ -1885,9 +1885,9 @@ CmdXload(w, cmd) { if (CmdIllegalChars(cmd->tx_argv[1], "[],", "Cell name")) return; - DBWloadWindow(w, cmd->tx_argv[1], FALSE, TRUE); + DBWloadWindow(w, cmd->tx_argv[1], FALSE, TRUE, FALSE); } - else DBWloadWindow(w, (char *) NULL, FALSE, TRUE); + else DBWloadWindow(w, (char *) NULL, FALSE, TRUE, FALSE); } /* diff --git a/database/DBcellsrch.c b/database/DBcellsrch.c index 5590f230..e1dae80d 100644 --- a/database/DBcellsrch.c +++ b/database/DBcellsrch.c @@ -188,7 +188,7 @@ dbCellTileSrFunc(scx, fp) if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0; + if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return 0; context.tc_scx = scx; context.tc_filter = fp; @@ -307,7 +307,7 @@ dbCellUniqueTileSrFunc(scx, fp) if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0; + if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return 0; context.tc_scx = scx; context.tc_filter = fp; @@ -418,7 +418,7 @@ DBNoTreeSrTiles(scx, mask, xMask, func, cdarg) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0; + if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return 0; filter.tf_func = func; filter.tf_arg = cdarg; @@ -526,7 +526,7 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg) ASSERT(def != (CellDef *) NULL, "DBTreeSrLabels"); if (!DBDescendSubcell(cellUse, xMask)) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0; + if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return 0; for (lab = def->cd_labels; lab; lab = lab->lab_next) { @@ -627,7 +627,7 @@ dbCellLabelSrFunc(scx, fp) ASSERT(def != (CellDef *) NULL, "dbCellLabelSrFunc"); if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0; + if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return 0; if (fp->tf_tpath != (TerminalPath *) NULL) { @@ -741,7 +741,7 @@ DBTreeSrCells(scx, xMask, func, cdarg) if (!DBDescendSubcell(cellUse, xMask)) return 0; if ((cellUse->cu_def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(cellUse->cu_def, (char *) NULL, TRUE, NULL)) + if (!DBCellRead(cellUse->cu_def, (char *) NULL, TRUE, FALSE, NULL)) return 0; context.tc_scx = scx; @@ -787,7 +787,7 @@ dbTreeCellSrFunc(scx, fp) else { if ((use->cu_def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, NULL)) + if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, FALSE, NULL)) return 0; result = DBCellSrArea(scx, dbTreeCellSrFunc, (ClientData) fp); } @@ -1039,7 +1039,7 @@ DBCellSrArea(scx, func, cdarg) context.tc_scx = scx; if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, NULL)) + if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, FALSE, NULL)) return 0; /* In order to make this work with zero-size areas, we first expand @@ -1215,7 +1215,7 @@ DBCellEnum(cellDef, func, cdarg) filter.tf_func = func; filter.tf_arg = cdarg; if ((cellDef->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(cellDef, (char *) NULL, TRUE, NULL)) return 0; + if (!DBCellRead(cellDef, (char *) NULL, TRUE, FALSE, NULL)) return 0; if (TiSrArea((Tile *) NULL, cellDef->cd_planes[PL_CELL], &TiPlaneRect, dbEnumFunc, (ClientData) &filter)) return 1; diff --git a/database/DBcellsubr.c b/database/DBcellsubr.c index 4b9f96a8..9eaabcac 100644 --- a/database/DBcellsubr.c +++ b/database/DBcellsubr.c @@ -73,7 +73,7 @@ DBDescendSubcell(use, xMask) case CU_DESCEND_NO_SUBCKT: if ((use->cu_def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, NULL)) + if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, FALSE, NULL)) return FALSE; return (DBIsSubcircuit(use->cu_def)) ? FALSE : TRUE; diff --git a/database/DBexpand.c b/database/DBexpand.c index 981748c8..db0548f6 100644 --- a/database/DBexpand.c +++ b/database/DBexpand.c @@ -81,7 +81,7 @@ DBExpand(cellUse, expandMask, expandFlag) def = cellUse->cu_def; if ((def->cd_flags & CDAVAILABLE) == 0) { - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) + if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return; /* Note: we don't have to recompute the bbox here, because * if it changed, then a timestamp violation must have occurred @@ -144,7 +144,7 @@ DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg) struct expandArg arg; 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, FALSE, NULL); /* * Walk through the area and set the expansion state @@ -193,7 +193,7 @@ dbExpandFunc(scx, arg) /* If the cell is unavailable, then don't expand it. */ if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0) - if(!DBCellRead(childUse->cu_def, (char *) NULL, TRUE, NULL)) + if(!DBCellRead(childUse->cu_def, (char *) NULL, TRUE, FALSE, NULL)) { TxError("Cell %s is unavailable. It could not be expanded.\n", childUse->cu_def->cd_name); @@ -303,7 +303,7 @@ dbReadAreaFunc(scx) if ((def->cd_flags & CDAVAILABLE) == 0) { - (void) DBCellRead(def, (char *) NULL, TRUE, NULL); + (void) DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL); /* Note: we don't have to invoke DBReComputeBbox here because * if the bbox changed then there was a timestamp mismatch and * the timestamp code will take care of the bounding box later. diff --git a/database/DBio.c b/database/DBio.c index 9afe30f3..f27e8d18 100644 --- a/database/DBio.c +++ b/database/DBio.c @@ -264,7 +264,7 @@ file_is_not_writeable(name) */ bool -dbCellReadDef(f, cellDef, name, ignoreTech) +dbCellReadDef(f, cellDef, name, ignoreTech, dereference) FILE *f; /* The file, already opened by the caller */ CellDef *cellDef; /* Pointer to definition of cell to be read in */ char *name; /* Name of file from which to read definition. @@ -279,6 +279,7 @@ dbCellReadDef(f, cellDef, name, ignoreTech) * names do not match, but an attempt will be * made to read the file anyway. */ + bool dereference; /* If TRUE, ignore path references in the input */ { int cellStamp = 0, rectCount = 0, rectReport = 10000; char line[2048], tech[50], layername[50]; @@ -437,7 +438,7 @@ dbCellReadDef(f, cellDef, name, ignoreTech) */ if (sscanf(line, "<< %s >>", layername) != 1) { - if (!dbReadUse(cellDef, line, sizeof line, f, n, d)) + if (!dbReadUse(cellDef, line, sizeof line, f, n, d, dereference)) goto badfile; continue; } @@ -863,7 +864,7 @@ DBReadBackup(name) cellDef->cd_flags &= ~CDNOTFOUND; cellDef->cd_flags |= CDAVAILABLE; - if (dbCellReadDef(f, cellDef, filename, TRUE) == FALSE) + if (dbCellReadDef(f, cellDef, filename, TRUE, FALSE) == FALSE) return FALSE; if (dbFgets(line, sizeof(line), f) == NULL) @@ -919,7 +920,7 @@ DBReadBackup(name) */ bool -DBCellRead(cellDef, name, ignoreTech, errptr) +DBCellRead(cellDef, name, ignoreTech, dereference, errptr) CellDef *cellDef; /* Pointer to definition of cell to be read in */ char *name; /* Name of file from which to read definition. * If NULL, then use cellDef->cd_file; if that @@ -933,6 +934,7 @@ DBCellRead(cellDef, name, ignoreTech, errptr) * names do not match, but an attempt will be * made to read the file anyway. */ + bool dereference; /* If TRUE, ignore path references in the input */ int *errptr; /* Copy of errno set by file reading routine * is placed here, unless NULL. */ @@ -950,7 +952,7 @@ DBCellRead(cellDef, name, ignoreTech, errptr) else { - result = (dbCellReadDef(f, cellDef, name, ignoreTech)); + result = (dbCellReadDef(f, cellDef, name, ignoreTech, dereference)); #ifdef FILE_LOCKS /* Close files that were locked by another user */ @@ -1193,13 +1195,14 @@ DBTestOpen(name, fullPath) */ bool -dbReadUse(cellDef, line, len, f, scalen, scaled) +dbReadUse(cellDef, line, len, f, scalen, scaled, dereference) CellDef *cellDef; /* Cell whose cells are being read */ char *line; /* Line containing "use ..." */ int len; /* Size of buffer pointed to by line */ FILE *f; /* Input file */ int scalen; /* Multiply values in file by this */ int scaled; /* Divide values in file by this */ + bool dereference; /* If TRUE, ignore path references */ { int xlo, xhi, ylo, yhi, xsep, ysep, childStamp; int absa, absb, absd, abse, nconv; @@ -1230,7 +1233,7 @@ dbReadUse(cellDef, line, len, f, scalen, scaled) pathptr = &path[0]; while (*pathptr == ' ' || *pathptr == '\t') pathptr++; - if (*pathptr == '\n') *pathptr = '\0'; + if ((dereference == TRUE) || (*pathptr == '\n')) *pathptr = '\0'; locked = (useid[0] == CULOCKCHAR) ? TRUE : FALSE; @@ -2840,7 +2843,7 @@ DBCellWrite(cellDef, fileName) #ifdef FILE_LOCKS else /* Re-aquire the lock on the new file by opening it. */ - DBCellRead(cellDef, NULL, TRUE, NULL); + DBCellRead(cellDef, NULL, TRUE, FALSE, NULL); #endif } diff --git a/database/DBlabel2.c b/database/DBlabel2.c index 9ddba125..8fda3f99 100644 --- a/database/DBlabel2.c +++ b/database/DBlabel2.c @@ -294,7 +294,7 @@ DBTreeFindUse(name, use, scx) * is read in from disk. */ if ((def->cd_flags & CDAVAILABLE) == 0) - (void) DBCellRead(def, (char *) NULL, TRUE, NULL); + (void) DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL); cp = name; he = HashLookOnly(&def->cd_idHash, name); @@ -343,7 +343,7 @@ DBTreeFindUse(name, use, scx) /* Ensure that the leaf cell is read in */ def = use->cu_def; if ((def->cd_flags & CDAVAILABLE) == 0) - (void) DBCellRead(def, (char *) NULL, TRUE, NULL); + (void) DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL); scx->scx_use = use; } diff --git a/database/DBtimestmp.c b/database/DBtimestmp.c index d33b20fa..516135c1 100644 --- a/database/DBtimestmp.c +++ b/database/DBtimestmp.c @@ -137,7 +137,7 @@ DBFixMismatch() mismatch = mismatch->mm_next; if (cellDef->cd_flags & CDPROCESSED) continue; - (void) DBCellRead(cellDef, (char *) NULL, TRUE, NULL); + (void) DBCellRead(cellDef, (char *) NULL, TRUE, FALSE, NULL); /* Jimmy up the cell's current bounding box, so the following * procedure call will absolutely and positively know that diff --git a/dbwind/DBWprocs.c b/dbwind/DBWprocs.c index aab82f5a..56578625 100644 --- a/dbwind/DBWprocs.c +++ b/dbwind/DBWprocs.c @@ -127,10 +127,10 @@ DBWcreate(window, argc, argv) window->w_clientData = (ClientData) crec; if (argc > 0) - DBWloadWindow(window, argv[0], TRUE, FALSE); + DBWloadWindow(window, argv[0], TRUE, FALSE, FALSE); else if (ToolGetBox(&boxDef, &box)) { - DBWloadWindow(window, boxDef->cd_name, TRUE, FALSE); + DBWloadWindow(window, boxDef->cd_name, TRUE, FALSE, FALSE); /* Zoom in on the box, leaving a 10% border or at least 2 units * on each side. @@ -148,7 +148,7 @@ DBWcreate(window, argc, argv) } else { - DBWloadWindow(window, (char *) NULL, TRUE, FALSE); + DBWloadWindow(window, (char *) NULL, TRUE, FALSE, FALSE); } return TRUE; } @@ -249,7 +249,7 @@ dbwReloadFunc(w, name) MagWindow *w; char *name; { - DBWloadWindow(w, name, TRUE, FALSE); + DBWloadWindow(w, name, TRUE, FALSE, FALSE); return (0); } @@ -274,18 +274,20 @@ dbwReloadFunc(w, name) * cell doesn't change. * * If "expand" is true, unexpands all subcells of the root cell. + * If "dereference" is true, ignore path reference in the input file. * * ---------------------------------------------------------------------------- */ void -DBWloadWindow(window, name, ignoreTech, expand) +DBWloadWindow(window, name, ignoreTech, expand, dereference) MagWindow *window; /* Identifies window to which cell is to be bound */ char *name; /* Name of new cell to be bound to this window */ bool ignoreTech; /* If FALSE, indicates that the technology of * the layout must match the current technology. */ bool expand; /* Indicates whether or not to expand the cell */ + bool dereference; /* If TRUE, ignore path references in the input */ { CellDef *newEditDef; CellUse *newEditUse; @@ -383,7 +385,7 @@ DBWloadWindow(window, name, ignoreTech, expand) if (newEditDef == (CellDef *) NULL) newEditDef = DBCellNewDef(rootname, (char *) NULL); - if (!DBCellRead(newEditDef, name, ignoreTech, &error_val)) + if (!DBCellRead(newEditDef, name, ignoreTech, dereference, &error_val)) { if (error_val == ENOENT) { diff --git a/drc/DRCmain.c b/drc/DRCmain.c index 8b2d0a8c..b1906713 100644 --- a/drc/DRCmain.c +++ b/drc/DRCmain.c @@ -969,7 +969,7 @@ drcFindFunc(scx, finddata) if (HashGetValue(h) != 0) return 0; HashSetValue(h, 1); - (void) DBCellRead(def, (char *) NULL, TRUE, NULL); + (void) DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL); if (DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR], &def->cd_bbox, &DBAllButSpaceBits, drcFindFunc2, diff --git a/extflat/EFflat.c b/extflat/EFflat.c index bd02d9c9..8708259f 100644 --- a/extflat/EFflat.c +++ b/extflat/EFflat.c @@ -59,7 +59,8 @@ bool efFlatGlobCmp(HierName *, HierName *); char *efFlatGlobCopy(HierName *); void efFlatGlobError(EFNodeName *, EFNodeName *); int efAddNodes(HierContext *, bool); -int efAddOneConn(HierContext *, char *, char *, Connection *); +int efAddConns(HierContext *, bool); +int efAddOneConn(HierContext *, char *, char *, Connection *, bool); /* @@ -193,8 +194,11 @@ EFFlatBuildOneLevel(def, flags) efFlatContext.hc_x = efFlatContext.hc_y = 0; efFlatRootUse.use_def = efFlatRootDef; + /* NOTE: Do the following two routines need to be deeper than one level? */ /* Record all nodes of the next level in the hierarchy */ efHierSrUses(&efFlatContext, efAddNodes, (ClientData)TRUE); + /* Record those connections as well. */ + efHierSrUses(&efFlatContext, efAddConns, (ClientData)FALSE); /* Expand all subcells that contain connectivity information but */ /* no active devices (including those in subcells). */ @@ -210,7 +214,7 @@ EFFlatBuildOneLevel(def, flags) /* Record all local nodes */ efAddNodes(&efFlatContext, FALSE); - efAddConns(&efFlatContext); + efAddConns(&efFlatContext, TRUE); efFlatKills(&efFlatContext); if (!(flags & EF_NONAMEMERGE)) @@ -300,7 +304,7 @@ efFlatNodes(hc) efAddNodes(hc, FALSE); /* Process our own connections and adjustments */ - (void) efAddConns(hc); + (void) efAddConns(hc, TRUE); return (0); } @@ -352,7 +356,7 @@ efFlatNodesStdCell(hc) /* Process our own connections and adjustments */ if (!(hc->hc_use->use_def->def_flags & DEF_SUBCIRCUIT)) - (void) efAddConns(hc); + (void) efAddConns(hc, TRUE); return (0); } @@ -378,7 +382,7 @@ efFlatNodesDeviceless(hc, cdata) efAddNodes(hc, TRUE); /* Process our own connections and adjustments */ - efAddConns(hc); + efAddConns(hc, TRUE); /* Mark this definition as having no devices, so it will not be visited */ hc->hc_use->use_def->def_flags |= DEF_NODEVICES; @@ -562,8 +566,9 @@ efAddNodes(hc, stdcell) */ int -efAddConns(hc) +efAddConns(hc, doWarn) HierContext *hc; + bool doWarn; { Connection *conn; @@ -576,9 +581,9 @@ efAddConns(hc) { /* Special case for speed when no array info is present */ if (conn->conn_1.cn_nsubs == 0) - efAddOneConn(hc, conn->conn_name1, conn->conn_name2, conn); + efAddOneConn(hc, conn->conn_name1, conn->conn_name2, conn, doWarn); else - efHierSrArray(hc, conn, efAddOneConn, (ClientData) NULL); + efHierSrArray(hc, conn, efAddOneConn, (ClientData)doWarn); } return (0); @@ -605,16 +610,17 @@ efAddConns(hc) */ int -efAddOneConn(hc, name1, name2, conn) +efAddOneConn(hc, name1, name2, conn, doWarn) HierContext *hc; char *name1, *name2; /* These are strings, not HierNames */ Connection *conn; + bool doWarn; { HashEntry *he1, *he2; EFNode *node, *newnode; int n; - he1 = EFHNLook(hc->hc_hierName, name1, "connect(1)"); + he1 = EFHNLook(hc->hc_hierName, name1, (doWarn) ? "connect(1)" : NULL); if (he1 == NULL) return 0; @@ -630,7 +636,7 @@ efAddOneConn(hc, name1, name2, conn) /* Merge this node with conn_name2 if one was specified */ if (name2) { - he2 = EFHNLook(hc->hc_hierName, name2, "connect(2)"); + he2 = EFHNLook(hc->hc_hierName, name2, (doWarn) ? "connect(2)" : NULL); if (he2 == NULL) return 0; newnode = ((EFNodeName *) HashGetValue(he2))->efnn_node; diff --git a/extract/ExtInter.c b/extract/ExtInter.c index e0626faa..604e54f3 100644 --- a/extract/ExtInter.c +++ b/extract/ExtInter.c @@ -424,7 +424,7 @@ extTreeSrPaintArea(scx, func, cdarg) int pNum; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0; + if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return 0; filter.tf_func = func; filter.tf_arg = cdarg; @@ -461,7 +461,7 @@ extTreeSrFunc(scx, fp) int pNum; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return (0); + if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return (0); context.tc_scx = scx; context.tc_filter = fp; @@ -548,7 +548,7 @@ extCellSrArea(scx, func, cdarg) filter.tf_arg = cdarg; if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, NULL)) + if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, FALSE, NULL)) return 0; /* diff --git a/graphics/W3Dmain.c b/graphics/W3Dmain.c index 55c561df..90a4e205 100644 --- a/graphics/W3Dmain.c +++ b/graphics/W3Dmain.c @@ -1394,7 +1394,7 @@ W3DloadWindow(window, name) if (newEditDef == (CellDef *)NULL) return FALSE; - if (!DBCellRead(newEditDef, (char *)NULL, TRUE, NULL)) + if (!DBCellRead(newEditDef, (char *)NULL, TRUE, FALSE, NULL)) return FALSE; DBReComputeBbox(newEditDef); diff --git a/lef/defRead.c b/lef/defRead.c index a9026263..f890b3ca 100644 --- a/lef/defRead.c +++ b/lef/defRead.c @@ -1491,7 +1491,7 @@ DefReadComponents(f, rootDef, sname, oscale, total) /* magic .mag layout file. */ defMacro = DBCellNewDef(token, (char *)NULL); defMacro->cd_flags &= ~CDNOTFOUND; - if (!DBCellRead(defMacro, (char *)NULL, TRUE, NULL)) + if (!DBCellRead(defMacro, (char *)NULL, TRUE, FALSE, NULL)) { LefError(DEF_ERROR, "Cell %s is not defined. Maybe you " "have not read the corresponding LEF file?\n", diff --git a/sim/SimDBstuff.c b/sim/SimDBstuff.c index 72092caf..05a89a4c 100644 --- a/sim/SimDBstuff.c +++ b/sim/SimDBstuff.c @@ -789,7 +789,7 @@ SimCellTileSrFunc(scx, fp) if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0; + if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return 0; context.tc_scx = scx; context.tc_filter = fp; diff --git a/windows/windView.c b/windows/windView.c index e535dcc9..eefff34e 100644 --- a/windows/windView.c +++ b/windows/windView.c @@ -95,7 +95,7 @@ WindUnload(surfaceID) for (mw = windTopWindow; mw != NULL; mw = mw->w_nextWindow) if (mw->w_surfaceID == surfaceID) - DBWloadWindow(mw, (char *)NULL, TRUE, FALSE); + DBWloadWindow(mw, (char *)NULL, TRUE, FALSE, FALSE); } /* From e1783a42a92e1e037009c6f2ce2bc07f632f0781 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 15 Nov 2019 10:26:04 -0500 Subject: [PATCH 061/121] Added a "DRC manager" window option. This allows DRC errors to be categorized by error type and scrolled through conveniently. However, it needs work dealing with finding the actual error bounds. The "DRC count" counts tiles, which is tile-plane-geometry-specific, and "DRC listall why" fractures errors both over tiles and over the square areas that the interactive DRC splits the layout into, for performance. The DRC error plane needs to be changed to hold different types for each error class, so that errors can be scanned by boundary instead of by tile (work to be done). --- commands/CmdCD.c | 89 ++++++++------------- drc/DRCmain.c | 93 +++------------------- drc/drc.h | 11 +-- tcltk/Makefile | 1 + tcltk/drcmgr.tcl | 195 ++++++++++++++++++++++++++++++++++++++++++++++ tcltk/wrapper.tcl | 11 +++ 6 files changed, 251 insertions(+), 149 deletions(-) create mode 100644 tcltk/drcmgr.tcl diff --git a/commands/CmdCD.c b/commands/CmdCD.c index 6fdcb4ad..712b0ae4 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -3182,7 +3182,6 @@ CmdDrc(w, cmd) bool doforall = FALSE; bool dolist = FALSE; int count_total; - DRCCountList *dcl, *dclsrch; int argc = cmd->tx_argc; char **argv = cmd->tx_argv; #ifdef MAGIC_WRAPPER @@ -3199,7 +3198,7 @@ CmdDrc(w, cmd) "check recheck area under box in all cells", "count count error tiles in each cell under box", "euclidean on|off enable/disable Euclidean geometry checking", - "find [nth] locate next (or nth) error in the layout", + "find [nth] locate next (or nth) error in the layout", "help print this help information", "off turn off background checker", "on reenable background checker", @@ -3305,15 +3304,6 @@ CmdDrc(w, cmd) break; case COUNT: - count_total = -1; - if (argc == 3) - if (!strncmp(argv[2], "total", 5)) - count_total = 0; - -#ifdef MAGIC_WRAPPER - if (count_total == -1) lobj = Tcl_NewListObj(0, NULL); -#endif - if ((window = w) == NULL) { window = ToolGetBoxWindow(&rootArea, (int *) NULL); @@ -3323,61 +3313,44 @@ CmdDrc(w, cmd) rootArea = w->w_surfaceArea; rootUse = (CellUse *) window->w_surfaceID; - dcl = DRCCount(rootUse, &rootArea); - while (dcl != NULL) - { - if (count_total >= 0) - count_total += dcl->dcl_count; - else - { -#ifdef MAGIC_WRAPPER - if (dolist) - { - Tcl_Obj *pobj = Tcl_NewListObj(0, NULL); - Tcl_ListObjAppendElement(magicinterp, pobj, - Tcl_NewStringObj(dcl->dcl_def->cd_name, -1)); - Tcl_ListObjAppendElement(magicinterp, pobj, - Tcl_NewIntObj(dcl->dcl_count)); - Tcl_ListObjAppendElement(magicinterp, lobj, pobj); - } - else - { -#endif - - if (dcl->dcl_count > 1) - TxPrintf("Cell %s has %d error tiles.\n", - dcl->dcl_def->cd_name, dcl->dcl_count); - else if (dcl->dcl_count == 1) - TxPrintf("Cell %s has just one error tile.\n", - dcl->dcl_def->cd_name); -#ifdef MAGIC_WRAPPER - } -#endif - } - freeMagic((char *)dcl); - dcl = dcl->dcl_next; - } + count_total = DRCCount(rootUse, &rootArea); #ifdef MAGIC_WRAPPER - if (count_total >= 0) + if (dolist) + { + lobj = Tcl_NewListObj(0, NULL); + Tcl_ListObjAppendElement(magicinterp, lobj, + Tcl_NewStringObj(rootUse->cu_def->cd_name, -1)); + Tcl_ListObjAppendElement(magicinterp, lobj, + Tcl_NewIntObj(count_total)); + } + else + { +#endif + + if (count_total > 1) + TxPrintf("Cell %s has %d error tiles.\n", + rootUse->cu_def->cd_name, count_total); + else if (count_total == 1) + TxPrintf("Cell %s has just one error tile.\n", + rootUse->cu_def->cd_name); + +#ifdef MAGIC_WRAPPER + } +#endif + +#ifdef MAGIC_WRAPPER + if (doforall) + Tcl_SetObjResult(magicinterp, lobj); + else if (count_total >= 0) { if (dolist) Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(count_total)); else - { - if ((DRCBackGround != DRC_SET_OFF) && (count_total == -1)) - count_total = 0; - if (count_total >= 0) - TxPrintf("Total DRC errors found: %d\n", count_total); - } + TxPrintf("Total DRC errors found: %d\n", count_total); } - else if (dolist) - Tcl_SetObjResult(magicinterp, lobj); #else - if ((DRCBackGround != DRC_SET_OFF) && (count_total == -1)) - count_total = 0; - if (count_total >= 0) - TxPrintf("Total DRC errors found: %d\n", count_total); + TxPrintf("Total DRC errors found: %d\n", count_total); #endif break; diff --git a/drc/DRCmain.c b/drc/DRCmain.c index b1906713..29ab5e8f 100644 --- a/drc/DRCmain.c +++ b/drc/DRCmain.c @@ -343,7 +343,7 @@ drcListallError (celldef, rect, cptr, scx) area = &scx->scx_area; if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return; DRCErrorCount += 1; - h = HashFind(&DRCErrorTable, cptr->drcc_why); + h = HashFind(&DRCErrorTable, drcSubstitute(cptr)); lobj = (Tcl_Obj *) HashGetValue(h); if (lobj == NULL) lobj = Tcl_NewListObj(0, NULL); @@ -747,111 +747,42 @@ drcCheckFunc(scx, cdarg) * ---------------------------------------------------------------------------- */ -DRCCountList * +int DRCCount(use, area) CellUse *use; /* Top-level use of hierarchy. */ Rect *area; /* Area in which violations are counted. */ { - DRCCountList *dcl, *newdcl; - HashTable dupTable; - HashEntry *he; - HashSearch hs; int count; SearchContext scx; - extern int drcCountFunc(); /* Forward reference. */ - - /* Use a hash table to make sure that we don't output information - * for any cell more than once. - */ - - HashInit(&dupTable, 16, HT_WORDKEYS); + CellDef *def; + extern int drcCountFunc2(); scx.scx_use = use; scx.scx_x = use->cu_xlo; scx.scx_y = use->cu_ylo; scx.scx_area = *area; scx.scx_trans = GeoIdentityTransform; - (void) drcCountFunc(&scx, &dupTable); - /* Create the list from the hash table */ - - dcl = NULL; - if (dupTable.ht_table != (HashEntry **) NULL) - { - HashStartSearch(&hs); - while ((he = HashNext(&dupTable, &hs)) != (HashEntry *)NULL) - { - count = (spointertype)HashGetValue(he); - if (count > 1) - { - newdcl = (DRCCountList *)mallocMagic(sizeof(DRCCountList)); - newdcl->dcl_count = count - 1; - newdcl->dcl_def = (CellDef *)he->h_key.h_ptr; - newdcl->dcl_next = dcl; - dcl = newdcl; - } - } - } - HashKill(&dupTable); - return dcl; -} - -int -drcCountFunc(scx, dupTable) - SearchContext *scx; - HashTable *dupTable; /* Passed as client data, used to - * avoid searching any cell twice. - */ -{ - int count; - HashEntry *h; - CellDef *def; - extern int drcCountFunc2(); - - /* If we've already seen this cell definition before, then skip it - * now. - */ - - def = scx->scx_use->cu_def; - h = HashFind(dupTable, (char *)def); - if (HashGetValue(h) != 0) goto done; - HashSetValue(h, 1); + def = use->cu_def; /* Count errors in this cell definition by scanning the error plane. */ count = 0; (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR], - &def->cd_bbox, &DBAllButSpaceBits, drcCountFunc2, (ClientData) &count); - HashSetValue(h, (spointertype)count + 1); + &def->cd_bbox, &DBAllButSpaceBits, drcCountFunc2, (ClientData)(&count)); - /* Ignore children that have not been loaded---we will only report */ - /* errors that can be seen. This avoids immediately loading and */ - /* drc processing large layouts simply because we asked for an */ - /* error count. When the cell is loaded, drc will be checked */ - /* anyway, and the count can be updated in response to that check. */ - - if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) return 0; - - /* New behavior: Don't search children, instead propagate errors up. */ - /* (void) DBCellSrArea(scx, drcCountFunc, (ClientData) dupTable); */ - - /* As a special performance hack, if the complete cell area is - * handled here, don't bother to look at any more array elements. - */ - - done: if (GEO_SURROUND(&scx->scx_area, &def->cd_bbox)) return 2; - else return 0; + return count; } int -drcCountFunc2(tile, pCount) - Tile *tile; /* Tile found in error plane. */ - int *pCount; /* Address of count word. */ +drcCountFunc2(tile, countptr) + Tile *tile; /* Tile found in error plane. */ + int *countptr; /* Address of count word. */ { - if (TiGetType(tile) != (TileType) TT_SPACE) *pCount += 1; + if (TiGetType(tile) != (TileType) TT_SPACE) (*countptr)++; return 0; } - + /* * ---------------------------------------------------------------------------- * diff --git a/drc/drc.h b/drc/drc.h index e2dea941..99bf0d28 100644 --- a/drc/drc.h +++ b/drc/drc.h @@ -125,15 +125,6 @@ typedef struct drcpendingcookie struct drcpendingcookie *dpc_next; } DRCPendingCookie; -/* Structure used to pass back lists of cell definitions and error tile counts */ - -typedef struct drccountlist -{ - CellDef *dcl_def; - int dcl_count; - struct drccountlist *dcl_next; -} DRCCountList; - /* Structure used to keep information about the current DRC style */ typedef struct drckeep @@ -267,7 +258,7 @@ extern void DRCPrintRulesTable(); extern void DRCWhy(); extern void DRCPrintStats(); extern void DRCCheck(); -extern DRCCountList *DRCCount(); +extern int DRCCount(); extern int DRCFind(); extern void DRCCatchUp(); extern bool DRCFindInteractions(); diff --git a/tcltk/Makefile b/tcltk/Makefile index ac45c270..db00d511 100644 --- a/tcltk/Makefile +++ b/tcltk/Makefile @@ -18,6 +18,7 @@ TCL_FILES = \ console.tcl \ techbuilder.tcl \ cellmgr.tcl \ + drcmgr.tcl \ libmgr.tcl \ texthelper.tcl \ tools.tcl \ diff --git a/tcltk/drcmgr.tcl b/tcltk/drcmgr.tcl new file mode 100644 index 00000000..abf9277f --- /dev/null +++ b/tcltk/drcmgr.tcl @@ -0,0 +1,195 @@ +#------------------------------------------------------ +# Script for generating the "DRC manager" window. +# +# Written by Tim Edwards, November 2019 +#------------------------------------------------------ + +global Opts + +if {$::tk_version >= 8.5} { + +set Opts(drcmgr) 0 + +magic::tag addpath "magic::drcmanager" +magic::tag path "magic::drcmanager" + +# Callback to the DRC manager + +proc magic::drccallback {command} { + global Opts + + set fid [.drcmgr.box.view selection] + if {[.drcmgr.box.view parent $fid] == {}} { + set value {} + } else { + set value [.drcmgr.box.view item $fid -text] + } + + if { $Opts(target) == "default" } { + set winlist [magic::windownames layout] + set winname [lindex $winlist 0] + } else { + set winname $Opts(target) + } + + switch $command { + update { + magic::drcmanager update + } + last { + .drcmgr.box.view selection set [.drcmgr.box.view prev $fid] + magic::drccallback zoom + } + next { + .drcmgr.box.view selection set [.drcmgr.box.view next $fid] + magic::drccallback zoom + } + zoom { + if {$value != {}} { + set snaptype [snap] + snap internal + box values {*}$value + magic::suspendall + magic::findbox zoom + magic::zoom 2 + magic::resumeall + snap $snaptype + } + } + } +} + +#---------------------------------------------- +# Create the DRC manager window +#---------------------------------------------- + +proc magic::makedrcmanager { mgrpath } { + global filtered + + set filtered 1 + toplevel ${mgrpath} + wm withdraw ${mgrpath} + frame ${mgrpath}.actionbar + frame ${mgrpath}.box + frame ${mgrpath}.target + + ttk::treeview ${mgrpath}.box.view -selectmode browse \ + -yscrollcommand "${mgrpath}.box.vert set" \ + -xscrollcommand "${mgrpath}.box.vert set" \ + -columns 0 + scrollbar ${mgrpath}.box.vert -orient vertical -command "${mgrpath}.box.view yview" + ${mgrpath}.box.view heading #0 -text "DRC Rule" + ${mgrpath}.box.view heading 0 -text "Error Number" + ${mgrpath}.box.view column #0 -stretch true -anchor w -minwidth 350 + ${mgrpath}.box.view column 0 -stretch false -anchor center -minwidth 50 + + grid columnconfigure ${mgrpath}.box 0 -weight 1 -minsize 500 + grid columnconfigure ${mgrpath}.box 1 -weight 0 + grid rowconfigure ${mgrpath}.box 0 -weight 1 + grid ${mgrpath}.box.view -row 0 -column 0 -sticky news + grid ${mgrpath}.box.vert -row 0 -column 1 -sticky news + + grid rowconfigure ${mgrpath} 0 -weight 0 + grid rowconfigure ${mgrpath} 1 -weight 1 + grid rowconfigure ${mgrpath} 2 -weight 0 + grid columnconfigure ${mgrpath} 0 -weight 1 + grid ${mgrpath}.actionbar -row 0 -column 0 -sticky news + grid ${mgrpath}.box -row 1 -column 0 -sticky news + grid ${mgrpath}.target -row 2 -column 0 -sticky news + + button ${mgrpath}.actionbar.update -text "Update" \ + -command {magic::drccallback update} + button ${mgrpath}.actionbar.last -text "Last" -command {magic::drccallback last} + button ${mgrpath}.actionbar.next -text "Next" -command {magic::drccallback next} + button ${mgrpath}.actionbar.zoom -text "Zoom" -command {magic::drccallback zoom} + + pack ${mgrpath}.actionbar.update -side left + pack ${mgrpath}.actionbar.last -side left + pack ${mgrpath}.actionbar.next -side left + pack ${mgrpath}.actionbar.zoom -side right + + label ${mgrpath}.target.name -text "Target window:" + menubutton ${mgrpath}.target.list -text "default" \ + -menu ${mgrpath}.target.list.winmenu + + pack ${mgrpath}.target.name -side left -padx 2 + pack ${mgrpath}.target.list -side left + + #Withdraw the window when the close button is pressed + wm protocol ${mgrpath} WM_DELETE_WINDOW "set Opts(drcmgr) 0 ; \ + wm withdraw ${mgrpath}" + + #------------------------------------------------- + # Callback when a treeview item is opened + #------------------------------------------------- + + bind .drcmgr <> { + set s [.drcmgr.box.view selection] + foreach i [.drcmgr.box.view children $s] { + # NOTE: not hierarchical + .drcmgr.box.view item $i -open false + } + } + + bind .drcmgr <> { + set s [.drcmgr.box.view selection] + foreach i [.drcmgr.box.view children $s] { + foreach j [.drcmgr.box.view children $i] { + .drcmgr.box.view delete $j + } + } + } +} + +proc magic::adddrcentry {key valuelist} { + set id [.drcmgr.box.view insert {} end -text ${key}] + set i 0 + foreach value $valuelist { + .drcmgr.box.view insert $id end -text "$value" + incr i + } +} + + +#-------------------------------------------------------------- +# The cell manager window main callback function +#-------------------------------------------------------------- + +proc magic::drcmanager {{option "update"}} { + global editstack + global CAD_ROOT + + # Check for existence of the manager widget + if {[catch {wm state .drcmgr}]} { + if {$option == "create"} { + magic::makedrcmanager .drcmgr + } else { + return + } + } elseif { $option == "create"} { + return + } + + magic::suspendall + + # Get existing list of error classes and remove them + set currules [.drcmgr.box.view children {}] + foreach rule $currules { + .drcmgr.box.view delete ${rule} + } + + # Run DRC + select top cell + set drcdict [dict create {*}[drc listall why]] + + # set first true + dict for {key value} $drcdict { + magic::adddrcentry ${key} ${value} + # .drcmgr.box.view item ${key} -open $first + # set first false + } + magic::resumeall +} + +} ;# (if Tk version 8.5) + diff --git a/tcltk/wrapper.tcl b/tcltk/wrapper.tcl index cb1f1e73..563778d5 100644 --- a/tcltk/wrapper.tcl +++ b/tcltk/wrapper.tcl @@ -367,6 +367,10 @@ catch {source ${CAD_ROOT}/magic/tcl/cellmgr.tcl} catch {source ${CAD_ROOT}/magic/tcl/libmgr.tcl} +# Generate the DRC manager + +catch {source ${CAD_ROOT}/magic/tcl/drcmgr.tcl} + # Generate the text helper catch {source ${CAD_ROOT}/magic/tcl/texthelper.tcl} @@ -1404,6 +1408,13 @@ proc magic::openwrapper {{cell ""} {framename ""}} { } else { \ wm withdraw .techmgr } }] + $m add check -label "DRC Manager" -variable Opts(drcmgr) \ + -command [subst { magic::drcmanager create; \ + if { \$Opts(drcmgr) } { \ + wm deiconify .drcmgr ; raise .drcmgr \ + } else { \ + wm withdraw .drcmgr } }] + $m add check -label "Netlist Window" -variable Opts(netlist) \ -command [subst { if { \[windownames netlist\] != {}} { \ set Opts(netlist) 0 ; closewindow \[windownames netlist\] \ From d3eb03d19a4be03bb64c63140237fbb5508fe42a Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Sun, 17 Nov 2019 19:08:47 -0500 Subject: [PATCH 062/121] Additional correction to extraction, still part of the effort to remove redundant ports. A comment that I left in the code at the last commit asked if it was necessary to call efAddNodes and efAddConns recursively. An example came up in which the answer is apparently "yes". These routines have been replaced by efFlatNodes(), which appears to solve the problem. There is now a question of whether efFlatNodesDeviceless() does anything, and should its main behavior (to flag deviceless subcircuits) be folded into efFlatNodes. --- extflat/EFflat.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/extflat/EFflat.c b/extflat/EFflat.c index 8708259f..239edb25 100644 --- a/extflat/EFflat.c +++ b/extflat/EFflat.c @@ -127,7 +127,7 @@ EFFlatBuild(name, flags) if (flags & EF_NOFLATSUBCKT) efFlatNodesStdCell(&efFlatContext); else - efFlatNodes(&efFlatContext); + efFlatNodes(&efFlatContext, FALSE, TRUE); efFlatKills(&efFlatContext); if (!(flags & EF_NONAMEMERGE)) efFlatGlob(); @@ -194,11 +194,8 @@ EFFlatBuildOneLevel(def, flags) efFlatContext.hc_x = efFlatContext.hc_y = 0; efFlatRootUse.use_def = efFlatRootDef; - /* NOTE: Do the following two routines need to be deeper than one level? */ - /* Record all nodes of the next level in the hierarchy */ - efHierSrUses(&efFlatContext, efAddNodes, (ClientData)TRUE); - /* Record those connections as well. */ - efHierSrUses(&efFlatContext, efAddConns, (ClientData)FALSE); + /* Record all nodes down the hierarchy from here */ + efFlatNodes(&efFlatContext, (ClientData)TRUE, (ClientData)FALSE); /* Expand all subcells that contain connectivity information but */ /* no active devices (including those in subcells). */ @@ -295,16 +292,16 @@ EFFlatDone() */ int -efFlatNodes(hc) +efFlatNodes(hc, stdcell, doWarn) HierContext *hc; { (void) efHierSrUses(hc, efFlatNodes); /* Add all our own nodes to the table */ - efAddNodes(hc, FALSE); + efAddNodes(hc, stdcell); /* Process our own connections and adjustments */ - (void) efAddConns(hc, TRUE); + (void) efAddConns(hc, doWarn); return (0); } From 3aa09725cb517e5e1b43d61b0f40f9d921db07cb Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 19 Nov 2019 11:39:59 -0500 Subject: [PATCH 063/121] Changed extraction to avoid generating an error message for devices like resistors where a tile other than space may border the resistor device on its non-terminal sides (which is handled correctly, and should not be considered an error). --- cif/CIFrdcl.c | 9 +++++++-- cif/CIFrdutils.c | 10 ++++++++-- extract/ExtBasic.c | 10 ++++++++-- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/cif/CIFrdcl.c b/cif/CIFrdcl.c index 23321977..a35797d3 100644 --- a/cif/CIFrdcl.c +++ b/cif/CIFrdcl.c @@ -1508,13 +1508,18 @@ CIFReadCellCleanup(filetype) freeMagic((char *)def->cd_client); def->cd_client = (ClientData)CLIENTDEFAULT; +#if 0 /* If the CDFLATTENED flag was not set, then this geometry */ - /* was never instantiated, and should generate a warning. */ + /* was never instantiated, and should generate a message. */ + /* However, this is not an error condition as there are a */ + /* number of useful reasons to copy lots of information up */ + /* the GDS hierarchy for "just in case" scenarios. */ if (!(def->cd_flags & CDFLATTENED)) - CIFReadError("%s read error: Unresolved geometry in cell" + CIFReadWarning("%s read: Unresolved geometry in cell" " %s maps to no magic layers\n", (filetype == FILE_CIF) ? "CIF" : "GDS", def->cd_name); +#endif #if 0 /* Remove the cell if it has no parents, no children, and no geometry */ diff --git a/cif/CIFrdutils.c b/cif/CIFrdutils.c index 9da32840..1e3a8fdd 100644 --- a/cif/CIFrdutils.c +++ b/cif/CIFrdutils.c @@ -120,7 +120,10 @@ CIFReadError(char *format, ...) if (CIFWarningLevel == CIF_WARN_NONE) return; if ((cifTotalErrors < 100) || (CIFWarningLevel != CIF_WARN_LIMIT)) { - TxError("Error at line %d of CIF file: ", cifLineNumber); + if (cifLineNumber > 0) + TxError("Error at line %d of CIF file: ", cifLineNumber); + else + TxError("CIF file read error: ", cifLineNumber); va_start(args, format); Vfprintf(stderr, format, args); va_end(args); @@ -141,7 +144,10 @@ CIFReadWarning(char *format, ...) if (CIFWarningLevel == CIF_WARN_NONE) return; if ((cifTotalWarnings < 100) || (CIFWarningLevel != CIF_WARN_LIMIT)) { - TxError("Warning at line %d of CIF file: ", cifLineNumber); + if (cifLineNumber > 0) + TxError("Warning at line %d of CIF file: ", cifLineNumber); + else + TxError("CIF file read warning: "); va_start(args, format); Vfprintf(stderr, format, args); va_end(args); diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 1894d30e..d783f19c 100644 --- a/extract/ExtBasic.c +++ b/extract/ExtBasic.c @@ -2800,10 +2800,16 @@ extTransPerimFunc(bp) devptr = extDevFindMatch(devptr, tinside); if (devptr == deventry) devptr = NULL; } + if (devptr == NULL) { - TxError("Error: Cannot find valid terminals on device %s!\n", - DBTypeLongNameTbl[tinside]); + /* Outside type is not a terminal, so return to the original */ + /* device record. NOTE: Should probably check if this device */ + /* type is a FET, as being here would indicate an error. */ + /* However, failure to find all terminals will be flagged as an */ + /* error elsewhere. */ + + extTransRec.tr_devrec = deventry; } /* From adb4d2613d0db8aa4b60d529134e62430f907441 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 20 Nov 2019 13:01:14 -0500 Subject: [PATCH 064/121] Added indexed selection to the PDK toolkit script (returns an index from a selection, which can then be used to index into other lists. This lets one selection be made on a list of arbitrary names, and then additional parameters can be linked together with the same index). Also, implemented (finally!) the "offset" parameters of the "slots" function (as advertised in the documentation). --- cif/CIFgen.c | 9 ++++++--- tcltk/toolkit.tcl | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/cif/CIFgen.c b/cif/CIFgen.c index 9c95f983..d2af4afb 100644 --- a/cif/CIFgen.c +++ b/cif/CIFgen.c @@ -1790,7 +1790,7 @@ cifSlotsFillArea(op, cellDef, plane) { Tile *tile, *t, *tp; Rect bbox, area, square, cut, llcut; - int nAcross, nUp, left, spitch, lpitch, ssize, lsize; + int nAcross, nUp, left, spitch, lpitch, ssize, lsize, offset; int diff, right; int xpitch, ypitch, xborder, yborder, xdiff, ydiff; int i, j, k, savecount; @@ -2017,10 +2017,11 @@ cifSlotsFillArea(op, cellDef, plane) /* For each contact cut area, check that there is */ /* no whitespace */ + offset = 0; for (i = 0; i < nUp; i++) { - cut.r_xbot = llcut.r_xbot; - cut.r_xtop = llcut.r_xtop; + cut.r_xbot = llcut.r_xbot + offset; + cut.r_xtop = llcut.r_xtop + offset; square.r_ybot = cut.r_ybot - yborder; square.r_ytop = cut.r_ytop + yborder; @@ -2047,6 +2048,8 @@ cifSlotsFillArea(op, cellDef, plane) } cut.r_ybot += ypitch; cut.r_ytop += ypitch; + offset += slots->sl_offset; + if (offset >= xpitch) offset -= xpitch; } if (savecount != CIFTileOps) break; diff --git a/tcltk/toolkit.tcl b/tcltk/toolkit.tcl index 7412277a..9ca83264 100644 --- a/tcltk/toolkit.tcl +++ b/tcltk/toolkit.tcl @@ -628,6 +628,38 @@ proc magic::add_selectlist {pname ptext all_values parameters} { set magic::${pname}_val $value } +#---------------------------------------------------------- +# Add a selectable-list parameter to the gencell window +# Unlike the routine above, it returns the index of the +# selection, not the selection itself. This is useful for +# keying the selection to other parameter value lists. +#---------------------------------------------------------- + +proc magic::add_selectindex {pname ptext all_values parameters} { + + if [dict exists $parameters $pname] { + set value [dict get $parameters $pname] + } else { + set value 0 + } + + set numrows [lindex [grid size .params.edits] 1] + label .params.edits.${pname}_lab -text $ptext + menubutton .params.edits.${pname}_sel -menu .params.edits.${pname}_sel.menu \ + -relief groove -text [lindex ${all_values} ${value}] + grid .params.edits.${pname}_lab -row $numrows -column 0 -sticky ens + grid .params.edits.${pname}_sel -row $numrows -column 1 -sticky wns + menu .params.edits.${pname}_sel.menu -tearoff 0 + set idx 0 + foreach item ${all_values} { + .params.edits.${pname}_sel.menu add radio -label $item \ + -variable magic::${pname}_val -value $idx \ + -command ".params.edits.${pname}_sel configure -text $item" + incr idx + } + set magic::${pname}_val $value +} + #------------------------------------------------------------- # gencell_defaults --- # From be8ba0937392d0996cdcda3e404c1057de4f9b5e Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 20 Nov 2019 13:36:03 -0500 Subject: [PATCH 065/121] Created an additional argument "start" to the "slots" operator, which adds an offset value of "start" to both X and Y from the lower left corner of the fill area. This allows the use of the "offset" (from the previous git commit) to be declared on different layers without creating an exact overlap, as is often required by foundries for fill patterns. --- cif/CIFgen.c | 6 +++--- cif/CIFint.h | 1 + cif/CIFtech.c | 23 +++++++++++++++++++---- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/cif/CIFgen.c b/cif/CIFgen.c index d2af4afb..6de88309 100644 --- a/cif/CIFgen.c +++ b/cif/CIFgen.c @@ -2011,13 +2011,13 @@ cifSlotsFillArea(op, cellDef, plane) cifSlotFunc(&bbox, op, &nUp, &nAcross, &llcut, vertical); - cut.r_ybot = llcut.r_ybot; - cut.r_ytop = llcut.r_ytop; + cut.r_ybot = llcut.r_ybot + slots->sl_start; + cut.r_ytop = llcut.r_ytop + slots->sl_start; /* For each contact cut area, check that there is */ /* no whitespace */ - offset = 0; + offset = slots->sl_start; for (i = 0; i < nUp; i++) { cut.r_xbot = llcut.r_xbot + offset; diff --git a/cif/CIFint.h b/cif/CIFint.h index c9280e12..157a3cff 100644 --- a/cif/CIFint.h +++ b/cif/CIFint.h @@ -69,6 +69,7 @@ typedef struct slots_data int sl_lsize; int sl_lsep; int sl_offset; + int sl_start; } SlotsData; typedef struct cifop diff --git a/cif/CIFtech.c b/cif/CIFtech.c index 309b06e0..2040bc7f 100644 --- a/cif/CIFtech.c +++ b/cif/CIFtech.c @@ -1327,6 +1327,7 @@ bloatCheck: slots->sl_lsize = 0; slots->sl_lsep = 0; slots->sl_offset = 0; + slots->sl_start = 0; } if (argc >= 5) { @@ -1361,7 +1362,7 @@ bloatCheck: goto errorReturn; } } - if (argc == 8) + if (argc >= 8) { i = atoi(argv[7]); slots->sl_offset = i; @@ -1371,7 +1372,17 @@ bloatCheck: goto errorReturn; } } - if ((argc < 4) || (argc == 6) || (argc > 8)) + if (argc == 9) + { + i = atoi(argv[8]); + slots->sl_start = i; + if (i < 0) + { + TechError("Slot start must be non-negative.\n"); + goto errorReturn; + } + } + if ((argc < 4) || (argc == 6) || (argc > 9)) goto wrongNumArgs; break; } @@ -1685,7 +1696,7 @@ CIFTechFinal() { slots = (SlotsData *)op->co_client; - for (j = 0; j < 7; j++) + for (j = 0; j < 8; j++) { switch (j) { case 0: bvalue = slots->sl_sborder; break; @@ -1695,6 +1706,7 @@ CIFTechFinal() case 4: bvalue = slots->sl_lsize; break; case 5: bvalue = slots->sl_lsep; break; case 6: bvalue = slots->sl_offset; break; + case 7: bvalue = slots->sl_start; break; } if (bvalue != 0) { @@ -2193,7 +2205,7 @@ CIFTechOutputScale(n, d) else if (op->co_opcode == CIFOP_SLOTS) { slots = (SlotsData *)op->co_client; - for (j = 0; j < 7; j++) + for (j = 0; j < 8; j++) { switch (j) { case 0: bptr = &slots->sl_sborder; break; @@ -2203,6 +2215,7 @@ CIFTechOutputScale(n, d) case 4: bptr = &slots->sl_lsize; break; case 5: bptr = &slots->sl_lsep; break; case 6: bptr = &slots->sl_offset; break; + case 7: bptr = &slots->sl_start; break; } if (*bptr != 0) { @@ -2319,6 +2332,8 @@ CIFTechOutputScale(n, d) slots->sl_lsep /= lexpand; if (slots->sl_offset != 0) slots->sl_offset /= lexpand; + if (slots->sl_start != 0) + slots->sl_start /= lexpand; break; case CIFOP_SQUARES_G: squares = (SquaresData *)op->co_client; From 27ed2bf975f9105c2b8b6fcc8968f6f07b98118b Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 21 Nov 2019 15:48:24 -0500 Subject: [PATCH 066/121] Modified the toolkit to take a selectlist with the special variable name "gencell" and use that to create a selection that can change between (compatible or somewhat compatible) device types. --- tcltk/toolkit.tcl | 42 +++++++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/tcltk/toolkit.tcl b/tcltk/toolkit.tcl index 9ca83264..e044101d 100644 --- a/tcltk/toolkit.tcl +++ b/tcltk/toolkit.tcl @@ -280,6 +280,7 @@ proc magic::gencell_setparams {parameters} { } elseif {[regexp {^.params.edits.(.*)_sel$} $s valid pname] != 0} { set value [dict get $parameters $pname] set magic::${pname}_val $value + .params.edits.${pname}_sel configure -text $value } elseif {[regexp {^.params.edits.(.*)_txt$} $s valid pname] != 0} { if {[dict exists $parameters $pname]} { set value [dict get $parameters $pname] @@ -310,11 +311,18 @@ proc magic::gencell_change {instname gencell_type library parameters} { if {$newinstname == $instname} {set newinstname $instname} if {[instance list exists $newinstname] != ""} {set newinstname $instname} } + if {[dict exists $parameters gencell]} { + # Setting special parameter "gencell" forces the gencell to change type + set gencell_type [dict get $parameters gencell] + } if {[catch {set parameters [${library}::${gencell_type}_check $parameters]} \ checkerr]} { puts stderr $checkerr } magic::gencell_setparams $parameters + if {[dict exists $parameters gencell]} { + set parameters [dict remove $parameters gencell] + } set gname [instance list celldef $instname] @@ -346,6 +354,7 @@ proc magic::gencell_change {instname gencell_type library parameters} { puts stderr $drawerr } property parameters $parameters + property gencell ${gencell_type} tech revert popstack select cell $instname @@ -400,14 +409,24 @@ proc magic::gencell_create {gencell_type library parameters} { set newinstname "" # Get device defaults - set pdefaults [${library}::${gencell_type}_defaults] if {$parameters == {}} { # Pull user-entered values from dialog - set parameters [dict merge $pdefaults [magic::gencell_getparams]] + set dialogparams [magic::gencell_getparams] + if {[dict exists $dialogparams gencell]} { + # Setting special parameter "gencell" forces the gencell to change type + set gencell_type [dict get $dialogparams gencell] + } + set pdefaults [${library}::${gencell_type}_defaults] + set parameters [dict merge $pdefaults $dialogparams] set newinstname [.params.title.ient get] if {$newinstname == "(default)"} {set newinstname ""} if {[instance list exists $newinstname] != ""} {set newinstname ""} } else { + if {[dict exists $parameters gencell]} { + # Setting special parameter "gencell" forces the gencell to change type + set gencell_type [dict get $parameters gencell] + } + set pdefaults [${library}::${gencell_type}_defaults] set parameters [dict merge $pdefaults $parameters] } @@ -416,6 +435,9 @@ proc magic::gencell_create {gencell_type library parameters} { puts stderr $checkerr } magic::gencell_setparams $parameters + if {[dict exists $parameters gencell]} { + set parameters [dict remove $parameters gencell] + } set snaptype [snap list] snap internal @@ -546,6 +568,10 @@ proc magic::add_dependency {callback gencell_type library args} { #---------------------------------------------------------- proc magic::update_dialog {callback pname gencell_type library} { + if {[dict exists $parameters gencell]} { + # Setting special parameter "gencell" forces the gencell to change type + set gencell_type [dict get $parameters gencell] + } set pdefaults [${library}::${gencell_type}_defaults] set parameters [dict merge $pdefaults [magic::gencell_getparams]] if {$callback != {}} { @@ -605,12 +631,12 @@ proc magic::add_message {pname ptext parameters {color blue}} { # Add a selectable-list parameter to the gencell window #---------------------------------------------------------- -proc magic::add_selectlist {pname ptext all_values parameters} { +proc magic::add_selectlist {pname ptext all_values parameters {itext ""}} { if [dict exists $parameters $pname] { set value [dict get $parameters $pname] } else { - set value "" + set value $itext } set numrows [lindex [grid size .params.edits] 1] @@ -635,12 +661,12 @@ proc magic::add_selectlist {pname ptext all_values parameters} { # keying the selection to other parameter value lists. #---------------------------------------------------------- -proc magic::add_selectindex {pname ptext all_values parameters} { +proc magic::add_selectindex {pname ptext all_values parameters {ival 0}} { if [dict exists $parameters $pname] { set value [dict get $parameters $pname] } else { - set value 0 + set value $ival } set numrows [lindex [grid size .params.edits] 1] @@ -745,9 +771,7 @@ proc magic::gencell_dialog {instname gencell_type library parameters} { set instname $instroot } set gname [instance list celldef [subst $instname]] - if {$gencell_type == {}} { - set gencell_type [cellname list property $gname gencell] - } + set gencell_type [cellname list property $gname gencell] if {$library == {}} { set library [cellname list property $gname library] } From 7373d55c554d351acbc651d63657917d6e8a2237 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 22 Nov 2019 11:37:04 -0500 Subject: [PATCH 067/121] Corrected a problem from the last commit that causes error messages in the toolkit Tk window when any parameter is modified, due do the use of a variable before its being defined in the dialog update. --- tcltk/toolkit.tcl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tcltk/toolkit.tcl b/tcltk/toolkit.tcl index e044101d..c62df42d 100644 --- a/tcltk/toolkit.tcl +++ b/tcltk/toolkit.tcl @@ -568,12 +568,16 @@ proc magic::add_dependency {callback gencell_type library args} { #---------------------------------------------------------- proc magic::update_dialog {callback pname gencell_type library} { + set pdefaults [${library}::${gencell_type}_defaults] + set parameters [dict merge $pdefaults [magic::gencell_getparams]] + if {[dict exists $parameters gencell]} { # Setting special parameter "gencell" forces the gencell to change type set gencell_type [dict get $parameters gencell] + set pdefaults [${library}::${gencell_type}_defaults] + set parameters [dict merge $pdefaults [magic::gencell_getparams]] } - set pdefaults [${library}::${gencell_type}_defaults] - set parameters [dict merge $pdefaults [magic::gencell_getparams]] + if {$callback != {}} { set parameters [$callback $pname $parameters] } From b90166985d50b1dbda40cf370fd258c4637e77a3 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 25 Nov 2019 11:07:59 -0500 Subject: [PATCH 068/121] Corrected an error in the dual CIF style (output & drc) method where the output style is not set back to what it was before if there are no cif rules in the default DRC style. --- drc/DRCcif.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drc/DRCcif.c b/drc/DRCcif.c index 9031ea4c..3a4a4bbd 100644 --- a/drc/DRCcif.c +++ b/drc/DRCcif.c @@ -513,7 +513,7 @@ drcCifCheck(arg) TxPrintf("Loading DRC CIF style.\n"); CIFCurStyle = NULL; CIFLoadStyle(drcNeedStyle); - if (drcCifValid == FALSE) + if (drcCifValid != FALSE) CIFCurStyle = CIFSaveStyle; else drcCifStyle = CIFCurStyle; @@ -525,7 +525,11 @@ drcCifCheck(arg) } CIFCurStyle = drcCifStyle; } - if (drcCifValid == FALSE) return; + if (drcCifValid == FALSE) + { + CIFCurStyle = CIFSaveStyle; + return; + } scale = drcCifStyle->cs_scaleFactor; cifrect = *checkRect; From 1fe128a405a4b975d3b88fe775f69e7982022191 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 25 Nov 2019 15:14:41 -0500 Subject: [PATCH 069/121] Implemented new CIF operator "close", in the syntax "close ", which takes the existing generated CIF plane, finds all enclosed areas that have an area less than , and fills them in. This satisfies a minimum hole area rule in a way that is not possible with any of the existing CIF operators. --- cif/CIFgen.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++- cif/CIFint.h | 2 + cif/CIFtech.c | 3 ++ 3 files changed, 144 insertions(+), 1 deletion(-) diff --git a/cif/CIFgen.c b/cif/CIFgen.c index 6de88309..1316f1fd 100644 --- a/cif/CIFgen.c +++ b/cif/CIFgen.c @@ -514,7 +514,7 @@ cifGrowFunc(tile, table) CIFTileOps += 1; return 0; } - + /* * ---------------------------------------------------------------------------- * @@ -1049,6 +1049,128 @@ cifBloatAllFunc(tile, bls) 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; + 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)) + *atotal += (area.r_xtop - area.r_xbot) * (area.r_ytop - area.r_ybot); + } + 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 */ /*--------------------------------------------------------------*/ @@ -3028,6 +3150,22 @@ CIFGenLayer(op, area, cellDef, temps, clientdata) nextPlane = temp; break; + case CIFOP_CLOSE: + growDistance = op->co_distance; + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifScale = 1; + /* First copy the existing paint into the target plane */ + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &CIFSolidBits, cifPaintFunc, (ClientData)CIFPaintTable); + + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &DBSpaceBits, cifCloseFunc, (ClientData)&curPlane); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + case CIFOP_BLOAT: cifPlane = curPlane; cifSrTiles(op, area, cellDef, temps, diff --git a/cif/CIFint.h b/cif/CIFint.h index 157a3cff..d08c0ba1 100644 --- a/cif/CIFint.h +++ b/cif/CIFint.h @@ -131,6 +131,7 @@ typedef struct cifop * CIFOP_COPYUP - Added 5/5/16---make and keep a copy the resulting layer, * which will be painted into parent cells instead of the * current cell. This replaces the "fault" method. + * CIFOP_CLOSE - Added 11/25/19---close up areas smaller than indicated */ #define CIFOP_AND 1 @@ -151,6 +152,7 @@ typedef struct cifop #define CIFOP_NET 16 #define CIFOP_MAXRECT 17 #define CIFOP_COPYUP 18 +#define CIFOP_CLOSE 19 /* Added by Tim 10/21/2004 */ /* The following structure is used to pass information on how to draw diff --git a/cif/CIFtech.c b/cif/CIFtech.c index 2040bc7f..af6af38e 100644 --- a/cif/CIFtech.c +++ b/cif/CIFtech.c @@ -1049,6 +1049,8 @@ CIFTechLine(sectionName, argc, argv) newOp->co_opcode = CIFOP_MAXRECT; else if (strcmp(argv[0], "boundary") == 0) newOp->co_opcode = CIFOP_BOUNDARY; + else if (strcmp(argv[0], "close") == 0) + newOp->co_opcode = CIFOP_CLOSE; else { TechError("Unknown statement \"%s\".\n", argv[0]); @@ -1068,6 +1070,7 @@ CIFTechLine(sectionName, argc, argv) case CIFOP_GROW: case CIFOP_GROW_G: case CIFOP_SHRINK: + case CIFOP_CLOSE: if (argc != 2) goto wrongNumArgs; newOp->co_distance = atoi(argv[1]); if (newOp->co_distance <= 0) From 46eefe8c33ef35ef4ae7fe66b72e4d3a67acac51 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 25 Nov 2019 16:37:03 -0500 Subject: [PATCH 070/121] Small correction on the last commit to avoid an integer overflow error on large areas (need type dlong to encode areas in internal units). --- cif/CIFgen.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cif/CIFgen.c b/cif/CIFgen.c index 1316f1fd..4381742b 100644 --- a/cif/CIFgen.c +++ b/cif/CIFgen.c @@ -1109,6 +1109,7 @@ cifGatherFunc(tile, atotal, mode) { Tile *tp; TileType type; + dlong locarea; Rect area, newarea; ClientData cdata = (mode == CLOSE_SEARCH) ? (ClientData)CIF_UNPROCESSED : (ClientData)CIF_PENDING; @@ -1130,7 +1131,12 @@ cifGatherFunc(tile, atotal, mode) if (mode == CLOSE_SEARCH) { if ((*atotal != INFINITY) && (*atotal < growDistance)) - *atotal += (area.r_xtop - area.r_xbot) * (area.r_ytop - area.r_ybot); + 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) { From a374230d88fc75dab144c3a6b51327f7abe609e4 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 26 Nov 2019 10:57:42 -0500 Subject: [PATCH 071/121] Modified the behavior of the LEF read routine when used to annotate an existing cell. If the existing cell has labels but the labels are defined as point labels (no rectangle defined using specific layer-purpose pairs), then the LEF macro's port geometry will be used for the labels. Because the GDS file can define label sizes and fonts, which the LEF file cannot, but because the LEF file may define multiple rectangles per port, the original point label is given the first port rectangle from the LEF file, while the remainder of the labels in the LEF file generate new non-rendered labels in the cell. --- lef/lefRead.c | 51 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/lef/lefRead.c b/lef/lefRead.c index 22978f7c..2a8e8ab4 100644 --- a/lef/lefRead.c +++ b/lef/lefRead.c @@ -1212,18 +1212,21 @@ LefReadGeometry(lefMacro, f, oscale, do_list) * * Side Effects: * Reads input from file f; - * Paints into the CellDef lefMacro. + * Generates a new label entry in the CellDef lefMacro. + * If "lanno" is not NULL, then the label pointed to by + * lanno is modified. * *------------------------------------------------------------ */ void -LefReadPort(lefMacro, f, pinName, pinNum, pinDir, pinUse, oscale) +LefReadPort(lefMacro, f, pinName, pinNum, pinDir, pinUse, oscale, lanno) CellDef *lefMacro; FILE *f; char *pinName; int pinNum, pinDir, pinUse; float oscale; + Label *lanno; { Label *newlab; LinkedRect *rectList; @@ -1235,7 +1238,15 @@ LefReadPort(lefMacro, f, pinName, pinNum, pinDir, pinUse, oscale) if (pinNum >= 0) { /* Label this area */ - DBPutLabel(lefMacro, &rectList->r_r, -1, pinName, rectList->r_type, 0); + if (lanno != NULL) + { + /* Modify an existing label */ + lanno->lab_rect = rectList->r_r; + lanno->lab_type = rectList->r_type; + } + else + /* Create a new label (non-rendered) */ + DBPutLabel(lefMacro, &rectList->r_r, -1, pinName, rectList->r_type, 0); /* Set this label to be a port */ @@ -1243,13 +1254,16 @@ LefReadPort(lefMacro, f, pinName, pinNum, pinDir, pinUse, oscale) LefError(LEF_ERROR, "Internal error: No labels in cell!\n"); else { - newlab = lefMacro->cd_lastLabel; + newlab = (lanno != NULL) ? lanno : lefMacro->cd_lastLabel; if (strcmp(newlab->lab_text, pinName)) LefError(LEF_ERROR, "Internal error: Can't find the label!\n"); else /* Make this a port */ newlab->lab_flags = pinNum | pinUse | pinDir | PORT_DIR_MASK; } - /* DBAdjustLabels(lefMacro, &rectList->area); */ + /* If lanno is non-NULL then the first rectangle in the LEF */ + /* port list is used to modify it. All other LEF port geometry */ + /* generates new labels in the CellDef. */ + if (lanno != NULL) lanno = NULL; } freeMagic((char *)rectList); @@ -1383,24 +1397,43 @@ LefReadPin(lefMacro, f, pinname, pinNum, oscale, is_imported) case LEF_PORT: if (is_imported) { + bool needRect = TRUE; Label *lab; - LefSkipSection(f, NULL); /* Skip the port geometry but find the pin name and */ /* annotate with the use and direction. Note that */ /* there may be multiple instances of the label. */ + /* However, if the label is a point label, then */ + /* replace it with the geometry from the LEF file. */ for (lab = lefMacro->cd_labels; lab; lab = lab->lab_next) { if (!strcmp(lab->lab_text, pinname)) { - lab->lab_flags &= ~(PORT_USE_MASK | PORT_DIR_MASK | + if (GEO_RECTNULL(&lab->lab_rect)) + break; + else + { + needRect = FALSE; + lab->lab_flags &= ~(PORT_USE_MASK | PORT_DIR_MASK | PORT_CLASS_MASK); - lab->lab_flags = pinNum | pinUse | pinDir | PORT_DIR_MASK; + lab->lab_flags = pinNum | pinUse | pinDir | + PORT_DIR_MASK; + } } } + if (needRect) + { + if (lab == NULL) + DBEraseLabelsByContent(lefMacro, NULL, -1, pinname); + LefReadPort(lefMacro, f, pinname, pinNum, pinDir, pinUse, + oscale, lab); + } + else + LefSkipSection(f, NULL); } else - LefReadPort(lefMacro, f, pinname, pinNum, pinDir, pinUse, oscale); + LefReadPort(lefMacro, f, pinname, pinNum, pinDir, pinUse, oscale, + NULL); break; case LEF_CAPACITANCE: case LEF_ANTENNADIFF: From cfaccd973ffb102642b14f1857ea49ce0dc17a59 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 27 Nov 2019 10:38:47 -0500 Subject: [PATCH 072/121] Expanded the antenna rule violation setup and calculations to include (1) specification of sidewall or surface to use for each type individually, rather than a single method for all types, and (2) specification of a linear model R = Ax + B for the ratio limit when diodes are attached to the wire, where x is the diode surface area (unitless, as this is a ratio). --- extflat/EFantenna.c | 20 ++++---- extract/ExtTech.c | 109 ++++++++++++++++++++++++++++++++++--------- extract/extractInt.h | 6 ++- 3 files changed, 101 insertions(+), 34 deletions(-) diff --git a/extflat/EFantenna.c b/extflat/EFantenna.c index 470edfe8..661fde43 100644 --- a/extflat/EFantenna.c +++ b/extflat/EFantenna.c @@ -347,7 +347,7 @@ antennacheckVisit(dev, hierName, scale, trans, editUse) TileType t, conType; int pos, pNum, pNum2, pmax, p, i, j, gatearea, diffarea, total; double anttotal; - float saveRatio; + float saveRatio, ratioTotal; int *antennaarea; Rect r, gaterect; EFNode *gnode; @@ -566,13 +566,15 @@ antennacheckVisit(dev, hierName, scale, trans, editUse) anttotal = 0.0; saveRatio = 0.0; for (i = 0; i < DBNumTypes; i++) - if (ExtCurStyle->exts_antennaRatio[i].ratioDiff != INFINITY) + if (ExtCurStyle->exts_antennaRatio[i].ratioDiffB != INFINITY) { - if (ExtCurStyle->exts_antennaRatio[i].ratioDiff > 0) - anttotal += (double)antennaarea[i] / - (double)ExtCurStyle->exts_antennaRatio[i].ratioDiff; - if (ExtCurStyle->exts_antennaRatio[i].ratioDiff > saveRatio) - saveRatio = ExtCurStyle->exts_antennaRatio[i].ratioDiff; + 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) @@ -702,7 +704,7 @@ antennaAccumFunc(tile, aaptr) TiToRect(tile, rect); - if (ExtCurStyle->exts_antennaModel & ANTENNAMODEL_SIDEWALL) + if (ExtCurStyle->exts_antennaRatio[type].areaType & ANTENNAMODEL_SIDEWALL) { /* Accumulate perimeter of tile where tile abuts space */ @@ -799,7 +801,7 @@ antennaAccumFunc(tile, aaptr) typeareas[type] += (int)((float)perimeter * thick); } } - else + 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); diff --git a/extract/ExtTech.c b/extract/ExtTech.c index 96e3d4c7..506f0d92 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -122,11 +122,11 @@ static keydesc keyTable[] = { "height", HEIGHT, 4, 4, "type height-above-subtrate thickness", - "antenna", ANTENNA, 4, 4, -"type antenna-ratio", + "antenna", ANTENNA, 4, 6, +"type [calc-type] [antenna-ratio-proportional] antenna-ratio-const", - "model", MODEL, 3, 3, -"partial-cumulative area-sidewall", + "model", MODEL, 2, 3, +"partial-cumulative [area-sidewall]", "tiedown", TIEDOWN, 2, 2, "types", @@ -704,8 +704,10 @@ extTechStyleInit(style) for (r = 0; r < DBNumTypes; r++) { + style->exts_antennaRatio[r].areaType = (char)0; style->exts_antennaRatio[r].ratioGate = 0.0; - style->exts_antennaRatio[r].ratioDiff = 0.0; + style->exts_antennaRatio[r].ratioDiffA = 0.0; + style->exts_antennaRatio[r].ratioDiffB = 0.0; style->exts_resistByResistClass[r] = 0; TTMaskZero(&style->exts_typesByResistClass[r]); style->exts_typesResistChanged[r] = DBAllButSpaceAndDRCBits; @@ -2351,38 +2353,96 @@ ExtTechLine(sectionName, argc, argv) break; case ANTENNA: { float antennaratio; + char areaType; + bool hasModel = FALSE; + int argidx = 2; if (!StrIsNumeric(argv[2])) { - TechError("Gate layer antenna ratio %s must be numeric\n", argv[2]); - break; + 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; + } } - antennaratio = (float)strtod(argv[2], NULL); + 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].ratioGate = antennaratio; - } + ExtCurStyle->exts_antennaRatio[t].areaType = areaType; - if (!StrIsNumeric(argv[3])) + if (hasModel == TRUE) argidx = 3; + + if (!StrIsNumeric(argv[argidx])) { - if (!strcasecmp(argv[3], "none")) + 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[3]); + TechError("Diff layer antenna ratio %s must be numeric\n", + argv[argidx]); break; } } else - antennaratio = (float)strtod(argv[3], NULL); + 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])) { - ExtCurStyle->exts_antennaRatio[t].ratioDiff = antennaratio; + 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; @@ -2392,13 +2452,16 @@ ExtTechLine(sectionName, argc, argv) TxError("Unknown antenna model \"%s\": Use \"partial\" or " "\"cumulative\""); - if (!strcmp(argv[2], "area")) - ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_AREA; - else if (!strcmp(argv[2], "sidewall")) - ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_SIDEWALL; - else - TxError("Unknown antenna model \"%s\": Use \"area\" or " - "\"sidewall\""); + 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: diff --git a/extract/extractInt.h b/extract/extractInt.h index 7e9c7a2e..72e2424f 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -49,14 +49,16 @@ typedef int ResValue; /* Warning: in some places resistances are stored */ typedef struct { + char areaType; /* ANTENNAMODEL_SURFACE or ANTENNAMODEL_SIDEWALL */ float ratioGate; - float ratioDiff; + float ratioDiffA; /* Proportional */ + float ratioDiffB; /* Constant */ } RatioValues; /* Antenna models */ #define ANTENNAMODEL_PARTIAL 0x01 #define ANTENNAMODEL_CUMULATIVE 0x02 -#define ANTENNAMODEL_AREA 0x04 +#define ANTENNAMODEL_SURFACE 0x04 #define ANTENNAMODEL_SIDEWALL 0x08 /* ------------------------ Parameter lists --------------------------- */ From 31612b593fa0001c8ce47bf10afb713812cf1beb Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 2 Dec 2019 10:18:37 -0500 Subject: [PATCH 073/121] Added new CIF generation op "grow-min" that ensures a minimum width for a layer. --- cif/CIFgen.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++- cif/CIFint.h | 34 +++++++++++---------- cif/CIFtech.c | 4 +++ utils/maxrect.c | 10 ++++-- 4 files changed, 109 insertions(+), 20 deletions(-) diff --git a/cif/CIFgen.c b/cif/CIFgen.c index 4381742b..ac4b8056 100644 --- a/cif/CIFgen.c +++ b/cif/CIFgen.c @@ -111,6 +111,71 @@ cifPaintFunc(tile, table) return 0; } +/* + * ---------------------------------------------------------------------------- + * + * cifGrowMinFunc -- + * + * Called for each relevant tile during grow-min operations. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Scales the tile by cifScale, then expands its area by the + * remainder of the distance to meet the minimum dimension, as + * defined by the grid distance (growDistance) in the current + * CIFOp, then paints this area into cifNewPlane using the table + * passed as parameter. + * ---------------------------------------------------------------------------- + */ + +int +cifGrowMinFunc(tile, plane) + Tile *tile; + Plane *plane; +{ + Rect area, *maxr; + int locDist, width, height; + TileTypeBitMask mask; + TileType type; + + TiToRect(tile, &area); + type = TiGetType(tile); + + TTMaskZero(&mask); + TTMaskSetType(&mask, type); + + maxr = FindMaxRectangle2(&area, tile, plane, &mask); + if (maxr == NULL) return 0; /* Should not happen */ + + maxr->r_xbot *= cifScale; + maxr->r_xtop *= cifScale; + maxr->r_ybot *= cifScale; + maxr->r_ytop *= cifScale; + + width = maxr->r_xtop - maxr->r_xbot; + height = maxr->r_ytop - maxr->r_ybot; + locDist = (growDistance - width) / 2; + if (locDist > 0) + { + maxr->r_xbot -= locDist; + maxr->r_xtop += locDist; + } + + locDist = (growDistance - height) / 2; + if (locDist > 0) + { + maxr->r_ybot -= locDist; + maxr->r_ytop += locDist; + } + + DBPaintPlane(cifPlane, maxr, CIFPaintTable, (PaintUndoInfo *) NULL); + + CIFTileOps += 1; + return 0; +} + /* * ---------------------------------------------------------------------------- * @@ -1505,7 +1570,7 @@ cifRectBoundingBox(op, cellDef, plane) } else { - maxr = FindMaxRectangle2(&bbox, tile, plane); + maxr = FindMaxRectangle2(&bbox, tile, plane, NULL); DBPaintPlane(cifPlane, maxr, CIFPaintTable, (PaintUndoInfo *)NULL); CIFTileOps++; } @@ -3126,6 +3191,20 @@ CIFGenLayer(op, area, cellDef, temps, clientdata) nextPlane = temp; break; + /* GROWMIN grows non-uniformly to ensure minimum dimensions */ + + case CIFOP_GROWMIN: + growDistance = op->co_distance; + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifScale = 1; + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &CIFSolidBits, cifGrowMinFunc, (ClientData)curPlane); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + /* GROW_G grows non-uniformly to the indicated grid. */ case CIFOP_GROW_G: diff --git a/cif/CIFint.h b/cif/CIFint.h index d08c0ba1..79564a34 100644 --- a/cif/CIFint.h +++ b/cif/CIFint.h @@ -96,6 +96,7 @@ typedef struct cifop * the masks. * CIFOP_GROW - Grow the current results uniformly by co_distance. * CIFOP_GROW_G - Grow the current results to snap to the indicated grid. + * CIFOP_GROWMIN - Grow result such that no dimension is less than co_distance. * CIFOP_SHRINK - Shrink the current results uniformly by co_distance. * CIFOP_BLOAT - Find layers in paintMask, then bloat selectively * according to bl_distance, and OR the results into @@ -137,22 +138,23 @@ typedef struct cifop #define CIFOP_AND 1 #define CIFOP_OR 2 #define CIFOP_GROW 3 -#define CIFOP_GROW_G 4 -#define CIFOP_SHRINK 5 -#define CIFOP_BLOAT 6 -#define CIFOP_SQUARES 7 -#define CIFOP_SLOTS 8 -#define CIFOP_BLOATMAX 9 -#define CIFOP_BLOATMIN 10 -#define CIFOP_BLOATALL 11 -#define CIFOP_ANDNOT 12 -#define CIFOP_SQUARES_G 13 -#define CIFOP_BBOX 14 -#define CIFOP_BOUNDARY 15 -#define CIFOP_NET 16 -#define CIFOP_MAXRECT 17 -#define CIFOP_COPYUP 18 -#define CIFOP_CLOSE 19 +#define CIFOP_GROWMIN 4 +#define CIFOP_GROW_G 5 +#define CIFOP_SHRINK 6 +#define CIFOP_BLOAT 7 +#define CIFOP_SQUARES 8 +#define CIFOP_SLOTS 9 +#define CIFOP_BLOATMAX 10 +#define CIFOP_BLOATMIN 11 +#define CIFOP_BLOATALL 12 +#define CIFOP_ANDNOT 13 +#define CIFOP_SQUARES_G 14 +#define CIFOP_BBOX 15 +#define CIFOP_BOUNDARY 16 +#define CIFOP_NET 17 +#define CIFOP_MAXRECT 18 +#define CIFOP_COPYUP 19 +#define CIFOP_CLOSE 20 /* Added by Tim 10/21/2004 */ /* The following structure is used to pass information on how to draw diff --git a/cif/CIFtech.c b/cif/CIFtech.c index af6af38e..9639ea00 100644 --- a/cif/CIFtech.c +++ b/cif/CIFtech.c @@ -1023,6 +1023,8 @@ CIFTechLine(sectionName, argc, argv) newOp->co_opcode = CIFOP_OR; else if (strcmp(argv[0], "grow") == 0) newOp->co_opcode = CIFOP_GROW; + else if (strcmp(argv[0], "grow-min") == 0) + newOp->co_opcode = CIFOP_GROWMIN; else if (strcmp(argv[0], "grow-grid") == 0) newOp->co_opcode = CIFOP_GROW_G; else if (strcmp(argv[0], "shrink") == 0) @@ -1068,6 +1070,7 @@ CIFTechLine(sectionName, argc, argv) break; case CIFOP_GROW: + case CIFOP_GROWMIN: case CIFOP_GROW_G: case CIFOP_SHRINK: case CIFOP_CLOSE: @@ -1499,6 +1502,7 @@ cifComputeRadii(layer, des) case CIFOP_OR: break; case CIFOP_GROW: + case CIFOP_GROWMIN: case CIFOP_GROW_G: grow += op->co_distance; break; diff --git a/utils/maxrect.c b/utils/maxrect.c index 75a1f78a..7b7df302 100644 --- a/utils/maxrect.c +++ b/utils/maxrect.c @@ -234,6 +234,9 @@ FindMaxRects(tile, mrd) * example, from the router code to expand a point label into the * maximum size rectangular terminal. * + * If expandtypes is NULL, then searching is done over tiles that + * match by the ClientData record instead of types. + * * Results: * Pointer to a rectangle containing the maximum size area found. * This pointer should not be deallocated! @@ -290,7 +293,7 @@ FindMaxRectangle(bbox, startpoint, plane, expandtypes) * FindMaxRectangle2 --- * * This routine differs from FindMaxRectangle in passing a starting - * tile to the routine + * tile to the routine. * * Results: * Pointer to a rectangle containing the maximum size area found. @@ -300,10 +303,11 @@ FindMaxRectangle(bbox, startpoint, plane, expandtypes) */ Rect * -FindMaxRectangle2(bbox, starttile, plane) +FindMaxRectangle2(bbox, starttile, plane, expandtypes) Rect *bbox; /* bounding box of area searched */ Tile *starttile; /* use this tile to start */ Plane *plane; /* plane of types to expand */ + TileTypeBitMask *expandtypes; /* types to expand in, may be NULL */ { MaxRectsData *mrd; TileType tt; @@ -312,7 +316,7 @@ FindMaxRectangle2(bbox, starttile, plane) int s, sidx = -1; /* Find tile in def that surrounds or touches startpoint */ - mrd = genCanonicalMaxwidth(bbox, starttile, plane, NULL); + mrd = genCanonicalMaxwidth(bbox, starttile, plane, expandtypes); /* Return only the largest rectangle found */ From fd737dbf80a8a0a65d7e1331d9dd8768a086dd3f Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Sun, 8 Dec 2019 17:37:48 -0500 Subject: [PATCH 074/121] Overhauled the extresist code (again), this time to (1) correct for a long-standing error (introduced with the "extresist geometry" option) that can cause nets not to be extracted (due to the first record not having extraction data, which was itself a long-standing error in the code but which was not fixed correctly); (2) handle "device mosfet" type transistors (previously only handled the old "fet" type extraction devices); and (3) correct for the res.ext file having a different scalefactor relative to the .ext file. The latter item was solved by forcing all input to scale like ExtCurStyle->exts_unitsPerLambda, locally correcting all input as needed. Note that extresist still needs to handle other extraction devices (e.g., resistors and capacitors) but those will require additional handling in the routines which analyze the current path to determine how to break up wires into paths. --- cif/CIFgen.c | 176 +- cif/CIFgen.c.test | 3980 ++++++++++++++++++++++++++++++++++++++++++++ extflat/Depend | 2 +- extflat/EFbuild.c | 24 +- extflat/EFread.c | 36 +- resis/ResJunct.c | 1 - resis/ResPrint.c | 38 +- resis/ResReadSim.c | 13 +- resis/ResRex.c | 22 +- resis/ResSimple.c | 35 +- resis/resis.h | 2 - 11 files changed, 4226 insertions(+), 103 deletions(-) create mode 100644 cif/CIFgen.c.test diff --git a/cif/CIFgen.c b/cif/CIFgen.c index ac4b8056..65822fd3 100644 --- a/cif/CIFgen.c +++ b/cif/CIFgen.c @@ -122,55 +122,161 @@ cifPaintFunc(tile, table) * Always returns 0 to keep the search alive. * * Side effects: - * Scales the tile by cifScale, then expands its area by the - * remainder of the distance to meet the minimum dimension, as - * defined by the grid distance (growDistance) in the current - * CIFOp, then paints this area into cifNewPlane using the table - * passed as parameter. + * 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, plane) +cifGrowMinFunc(tile, table) Tile *tile; - Plane *plane; + PaintResultType *table; /* Table to be used for painting. */ { - Rect area, *maxr; - int locDist, width, height; - TileTypeBitMask mask; - TileType type; + Rect area, parea; + int locDist, width, height, h; + TileType type, tptype; + Tile *tp, *tp2; TiToRect(tile, &area); - type = TiGetType(tile); - TTMaskZero(&mask); - TTMaskSetType(&mask, type); + area.r_xbot *= cifScale; + area.r_xtop *= cifScale; + area.r_ybot *= cifScale; + area.r_ytop *= cifScale; - maxr = FindMaxRectangle2(&area, tile, plane, &mask); - if (maxr == NULL) return 0; /* Should not happen */ + parea = area; - maxr->r_xbot *= cifScale; - maxr->r_xtop *= cifScale; - maxr->r_ybot *= cifScale; - maxr->r_ytop *= cifScale; - - width = maxr->r_xtop - maxr->r_xbot; - height = maxr->r_ytop - maxr->r_ybot; - locDist = (growDistance - width) / 2; - if (locDist > 0) + /* Check whole tile for minimum width */ + width = area.r_xtop - area.r_xbot; + if (width < growDistance) { - maxr->r_xbot -= locDist; - maxr->r_xtop += locDist; - } + locDist = (growDistance - width) / 2; + area.r_xbot -= locDist; + area.r_xtop += locDist; - locDist = (growDistance - height) / 2; - if (locDist > 0) + /* 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)) { - maxr->r_ybot -= locDist; - maxr->r_ytop += locDist; - } + 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; - DBPaintPlane(cifPlane, maxr, CIFPaintTable, (PaintUndoInfo *) NULL); + 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; @@ -3199,7 +3305,7 @@ CIFGenLayer(op, area, cellDef, temps, clientdata) cifPlane = nextPlane; cifScale = 1; (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, - &CIFSolidBits, cifGrowMinFunc, (ClientData)curPlane); + &CIFSolidBits, cifGrowMinFunc, (ClientData)CIFPaintTable); temp = curPlane; curPlane = nextPlane; nextPlane = temp; diff --git a/cif/CIFgen.c.test b/cif/CIFgen.c.test new file mode 100644 index 00000000..e3facc8b --- /dev/null +++ b/cif/CIFgen.c.test @@ -0,0 +1,3980 @@ +/* CIFgen.c - + * + * This file provides routines that generate CIF from Magic + * tile information, using one of the styles read from the + * technology file. + * + * ********************************************************************* + * * 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. * + * ********************************************************************* + */ + +#ifndef lint +static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/cif/CIFgen.c,v 1.23 2010/06/24 20:35:54 tim Exp $"; +#endif /* not lint */ + +#include +#include /* for abs() */ +#include /* for ceil() and sqrt() */ + +#include "utils/magic.h" +#include "utils/geometry.h" +#include "tiles/tile.h" +#include "utils/hash.h" +#include "database/database.h" +#include "cif/CIFint.h" +#include "calma/calma.h" /* for CalmaContactArrays */ +#include "commands/commands.h" /* for CmdFindNetProc() */ +#include "select/selInt.h" /* for select use and def */ +#include "utils/stack.h" +#include "utils/malloc.h" +#include "utils/maxrect.h" + +/* TRUE to run (very slow) algorithm for optimizing non-manhattan tiles */ +/* (cuts size of output; see also the GDS "merge" option) */ +bool CIFUnfracture = FALSE; + +/* The following global arrays hold pointers to the CIF planes + * generated by the procedures in this module. There are two + * kinds of planes: real CIF, which will ostensibly be output, + * and temporary layers used to build up more complex geometric + * functions. + */ + +global Plane *CIFPlanes[MAXCIFLAYERS]; + +/* The following are paint tables used by the routines that implement + * the geometric operations on mask layers, such as AND, OR, GROW, + * etc. There are really only two tables. The first will paint + * CIF_SOLIDTYPE over anything else, and the second will paint + * space over anything else. These tables are used on planes with + * only two tile types, TT_SPACE and CIF_SOLIDTYPE, so they only + * have two entries each. + */ + +PaintResultType CIFPaintTable[] = {CIF_SOLIDTYPE, CIF_SOLIDTYPE}; +PaintResultType CIFEraseTable[] = {TT_SPACE, TT_SPACE}; + +/* The following local variables are used as a convenience to pass + * information between CIFGen and the various search functions. + */ + +static int growDistance; /* Distance to grow stuff. */ +static Plane *cifPlane; /* Plane acted on by search functions. */ +static int cifScale; /* Scale factor to use on tiles. */ + +extern void cifClipPlane(); +extern void cifGenClip(); + +/* + * ---------------------------------------------------------------------------- + * + * cifPaintFunc -- + * + * This search function is called during CIF_AND and CIF_OR + * and CIF_ANDNOT operations for each relevant tile. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * For the area of the tile, either paints or erases in + * cifNewPlane, depending on the paint table passed as parameter. + * The tile's area is scaled by cifScale first. + * ---------------------------------------------------------------------------- + */ + +int +cifPaintFunc(tile, table) + Tile *tile; + PaintResultType *table; /* Used for painting. */ +{ + Rect area; + + TiToRect(tile, &area); + area.r_xbot *= cifScale; + area.r_xtop *= cifScale; + area.r_ybot *= cifScale; + area.r_ytop *= cifScale; + + DBNMPaintPlane(cifPlane, TiGetTypeExact(tile), &area, table, + (PaintUndoInfo *) NULL); + CIFTileOps += 1; + 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. + * + * ---------------------------------------------------------------------------- + */ + +int +cifGrowMinFuncAbandoned(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; +} + +/* Take two */ + +int +cifClearFunc(tile, clearArea) + Tile *tile; + Rect *clearArea; +{ + Rect area; + + TiToRect(tile, &area); + + area.r_xbot *= cifScale; + area.r_xtop *= cifScale; + area.r_ybot *= cifScale; + area.r_ytop *= cifScale; + + if (area.r_xtop > clearArea->r_xtop) clearArea->r_xtop = area.r_xtop; + if (area.r_xbot < clearArea->r_xbot) clearArea->r_xbot = area.r_xbot; + if (area.r_ytop > clearArea->r_ytop) clearArea->r_ytop = area.r_ytop; + if (area.r_ybot < clearArea->r_ybot) clearArea->r_ybot = area.r_ybot; + return 0; +} + +int +cifGrowMinFunc(tile, table) + Tile *tile; + PaintResultType *table; /* Table to be used for painting. */ +{ + Rect area, clearArea; + TileType type, tptype, tp2type; + Tile *tp, *tp2; + TileTypeBitMask mask; + int hdist, vdist; + + area.r_xbot *= cifScale; + area.r_xtop *= cifScale; + area.r_ybot *= cifScale; + area.r_ytop *= cifScale; + + TTMaskZero(&mask); + TTMaskSetType(&mask, TT_SPACE); + + /* Check for eight corner situations (4 outside, 4 inside) */ + + /* (1) Outside corner at tile top right */ + tp = RT(tile); + tp2 = TR(tile); + tptype = TiGetBottomType(tp); + tp2type = TiGetLeftType(tp2); + if (tptype == tp2type == TT_SPACE) + { + area.r_xtop = RIGHT(tile); + area.r_ytop = TOP(tile); + area.r_xbot = area.r_xtop - growDistance; + area.r_ybot = area.r_ytop - growDistance; + + clearArea.r_xbot = clearArea.r_xtop = area.r_xbot; + clearArea.r_ybot = clearArea.r_ytop = area.r_ybot; + + /* Search for space tiles in this area */ + DBSrPaintArea(tile, plane, &area, + &mask, cifClearFunc, (ClientData)(&clearArea)); + + if (!GEO_RECTNULL(&clearArea)) + { + GeoClip(&clearArea, &area); + /* XXX WIP Stopped here, work in progress, or maybe abandoned */ + } + } + + /* (2) Outside corner at tile bottom left */ + tp = LB(tile); + tp2 = BL(tile); + tptype = TiGetTopType(tp); + tp2type = TiGetRightType(tp2); + if (tptype == tp2type == TT_SPACE) + { + area.r_xbot = LEFT(tile); + area.r_ybot = BOTTOM(tile); + area.r_xtop = area.r_xbot + growDistance; + area.r_ytop = area.r_ybot + growDistance; + + /* TBD */ + } + + /* (3) Outside corner at tile top left */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)); + for (tp2 = BL(tile); BOTTOM(tp2) < TOP(tile); tp2 = TR(tp2)); + tptype = TiGetBottomType(tp); + tp2type = TiGetRightType(tp2); + if (tptype == tp2type == TT_SPACE) + { + area.r_xbot = LEFT(tile); + area.r_ytop = TOP(tile); + area.r_xtop = area.r_xbot + growDistance; + area.r_ybot = area.r_ytop - growDistance; + + /* TBD */ + } + + /* (4) Outside corner at tile bottom right */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)); + for (tp2 = TR(tile); TOP(tp2) > BOTTOM(tile); tp2 = BL(tp2)); + tptype = TiGetTopType(tp); + tp2type = TiGetLeftType(tp2); + if (tptype == tp2type == TT_SPACE) + { + area.r_xtop = RIGHT(tile); + area.r_ybot = BOTTOM(tile); + area.r_xbot = area.r_xtop - growDistance; + area.r_ytop = area.r_ybot + growDistance; + + /* TBD */ + } + + /* (5) Tile top right corner is an inside corner */ + tp = RT(tile); + tp2 = TR(tile); + tptype = TiGetBottomType(tp); + tp2type = TiGetLeftType(tp2); + if (tptype != TT_SPACE && tp2type == TT_SPACE) + { + area.r_xtop = RIGHT(tile); + area.r_ybot = TOP(tile); + area.r_xbot = area.r_xtop - growDistance; + area.r_ytop = area.r_ybot + growDistance; + + /* TBD */ + } + + /* (6) Tile bottom left corner is an inside corner */ + tp = LB(tile); + tp2 = BL(tile); + tptype = TiGetTopType(tp); + tp2type = TiGetRightType(tp2); + if (tptype != TT_SPACE && tp2type == TT_SPACE) + { + area.r_xbot = LEFT(tile); + area.r_ytop = BOTTOM(tile); + area.r_xtop = area.r_xbot + growDistance; + area.r_ybot = area.r_ytop - growDistance; + + /* TBD */ + } + + /* (7) Tile top left corner is an inside corner */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)); + for (tp2 = BL(tile); BOTTOM(tp2) < TOP(tile); tp2 = TR(tp2)); + tptype = TiGetBottomType(tp); + tp2type = TiGetRightType(tp2); + if (tptype != TT_SPACE && tp2type == TT_SPACE) + { + area.r_xbot = LEFT(tile); + area.r_ybot = TOP(tile); + area.r_xtop = area.r_xbot + growDistance; + area.r_ytop = area.r_ybot + growDistance; + + /* TBD */ + } + + /* (8) Tile bottom right corner is an inside corner */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)); + for (tp2 = TR(tile); TOP(tp2) > BOTTOM(tile); tp2 = BL(tp2)); + tptype = TiGetTopType(tp); + tp2type = TiGetLeftType(tp2); + if (tptype != TT_SPACE && tp2type == TT_SPACE) + { + area.r_xtop = LEFT(tile); + area.r_ytop = BOTTOM(tile); + area.r_xbot = area.r_xtop - growDistance; + area.r_ybot = area.r_ytop - growDistance; + + /* TBD */ + } + + CIFTileOps += 1; + return 0; + } + +/* + * ---------------------------------------------------------------------------- + * + * cifRemoveFunc -- + * + * Called for each relevant tile during remove-min operations. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Scales the tile by cifScale, then expands its area by the + * remainder of the distance to meet the minimum dimension, as + * defined by the grid distance (growDistance) in the current + * CIFOp, then paints this area into cifNewPlane using the table + * passed as parameter. + * ---------------------------------------------------------------------------- + */ + +int +cifRemoveFunc(tile, table) + Tile *tile; + PaintResultType *table; /* Table to be used for painting. */ +{ + CIFTileOps += 1; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifGrowGridFunc -- + * + * Called for each relevant tile during grow-grid operations. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Scales the tile by cifScale, then expands its area by the + * remainder of the distance to the nearest grid point, as + * defined by the grid distance (growDistance) in the current + * CIFOp, then paints this area into cifNewPlane using the table + * passed as parameter. + * ---------------------------------------------------------------------------- + */ + +int +cifGrowGridFunc(tile, table) + Tile *tile; + PaintResultType *table; /* Table to be used for painting. */ +{ + Rect area; + int remainder; + + /* To be done---handle non-Manhattan geometry */ + TileType oldType = TiGetType(tile); + + TiToRect(tile, &area); + + /* In scaling the tile, watch out for infinities!! If something + * is already infinity, don't change it. */ + + if (area.r_xbot > TiPlaneRect.r_xbot) area.r_xbot *= cifScale; + if (area.r_ybot > TiPlaneRect.r_ybot) area.r_ybot *= cifScale; + if (area.r_xtop < TiPlaneRect.r_xtop) area.r_xtop *= cifScale; + if (area.r_ytop < TiPlaneRect.r_ytop) area.r_ytop *= cifScale; + + /* In scaling the tile, watch out for infinities!! If something + * is already infinity, don't change it. */ + + if (area.r_xbot > TiPlaneRect.r_xbot) + area.r_xbot -= (abs(area.r_xbot) % growDistance); + if (area.r_ybot > TiPlaneRect.r_ybot) + area.r_ybot -= (abs(area.r_ybot) % growDistance); + if (area.r_xtop < TiPlaneRect.r_xtop) + area.r_xtop += (abs(area.r_xtop) % growDistance); + if (area.r_ytop < TiPlaneRect.r_ytop) + area.r_ytop += (abs(area.r_ytop) % growDistance); + + DBPaintPlane(cifPlane, &area, table, (PaintUndoInfo *) NULL); + + CIFTileOps += 1; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifGrowEuclideanFunc -- + * + * Called for each relevant tile during grow or shrink operations. + * For growing, these are solid tiles. For shrinking, these are + * space tiles. This routine differs from cifGrowFunc in that it + * grows the minimum distance on non-Manhattan edges necessary to + * create a euclidean distance to the edge of growDistance while + * keeping corner points on-grid. This requires a substantially + * different algorithm from cifGrowFunc. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Scales the tile by cifScale, then expands its area by the + * distance in the current CIFOp, then paints this area into + * cifNewPlane using the table passed as parameter. + * ---------------------------------------------------------------------------- + */ + +#define GROW_NORTH 0x1 +#define GROW_SOUTH 0x2 +#define GROW_EAST 0x4 +#define GROW_WEST 0x8 + +#define STOP_NW 0x1 /* WN EN */ +#define STOP_SW 0x2 /* NW +-------+ NE */ +#define STOP_NE 0x4 /* | | */ +#define STOP_SE 0x8 /* | | */ +#define STOP_WN 0x10 /* SW +-------+ SE */ +#define STOP_WS 0x20 /* WS ES */ +#define STOP_EN 0x40 +#define STOP_ES 0x80 + +int +cifGrowEuclideanFunc(tile, table) + Tile *tile; + PaintResultType *table; /* Table to be used for painting. */ +{ + Tile *tp; + Rect area, rtmp; + TileType oldType = TiGetTypeExact(tile); + unsigned char growDirs = GROW_NORTH | GROW_SOUTH | GROW_EAST | GROW_WEST; + unsigned char cornerDirs = 0; + + TiToRect(tile, &area); + + /* In scaling the tile, watch out for infinities!! If something + * is already infinity, don't change it. */ + + if (area.r_xbot > TiPlaneRect.r_xbot) + area.r_xbot *= cifScale; + else + growDirs &= ~GROW_WEST; + if (area.r_ybot > TiPlaneRect.r_ybot) + area.r_ybot *= cifScale; + else + growDirs &= ~GROW_SOUTH; + if (area.r_xtop < TiPlaneRect.r_xtop) + area.r_xtop *= cifScale; + else + growDirs &= ~GROW_EAST; + if (area.r_ytop < TiPlaneRect.r_ytop) + area.r_ytop *= cifScale; + else + growDirs &= ~GROW_NORTH; + + /* Grow on diagonal tiles: grow rectangular tiles around the */ + /* straight edges of the right-triangle, then copy the diagonal */ + /* tile (at its original size) in the direction of the diagonal. */ + /* Note: A diagonal tile, by definition, can't have infinities. */ + + if (oldType & TT_DIAGONAL) + { + int growDistanceX, growDistanceY; + int height, width; + double hyp; + + if (oldType & TT_SIDE) + growDirs &= ~GROW_WEST; + else + growDirs &= ~GROW_EAST; + + if (((oldType & TT_SIDE) >> 1) == (oldType & TT_DIRECTION)) + growDirs &= ~GROW_SOUTH; + else + growDirs &= ~GROW_NORTH; + + /* Grow non-Manhattan edges to (the closest integer value */ + /* to) growDistance along the normal to the edge. This */ + /* will overestimate the distance only to the minimum */ + /* amount necessary to ensure on-grid endpoints. */ + + width = area.r_xtop - area.r_xbot; + height = area.r_ytop - area.r_ybot; + hyp = sqrt((double)(width * width + height * height)); + growDistanceY = ceil((growDistance * (hyp - height)) / width); + growDistanceX = ceil((growDistance * (hyp - width)) / height); + + /* Draw vertical tile to distance X */ + + rtmp = area; + if (!(growDirs & GROW_EAST)) rtmp.r_xtop = rtmp.r_xbot + growDistanceX; + if (!(growDirs & GROW_WEST)) rtmp.r_xbot = rtmp.r_xtop - growDistanceX; + if (!(growDirs & GROW_SOUTH)) rtmp.r_ybot -=growDistance; + if (!(growDirs & GROW_NORTH)) rtmp.r_ytop += growDistance; + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + + /* Draw horizontal tile to distance Y */ + + rtmp = area; + if (!(growDirs & GROW_EAST)) rtmp.r_xtop += growDistance; + if (!(growDirs & GROW_WEST)) rtmp.r_xbot -= growDistance; + if (!(growDirs & GROW_SOUTH)) rtmp.r_ybot = rtmp.r_ytop - growDistanceY; + if (!(growDirs & GROW_NORTH)) rtmp.r_ytop = rtmp.r_ybot + growDistanceY; + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + + /* Finally: translate, resize, and paint the diagonal tile */ + + rtmp = area; + + if (!(growDirs & GROW_NORTH)) + rtmp.r_ytop += growDistance; + else + rtmp.r_ytop -= growDistanceY; + if (!(growDirs & GROW_SOUTH)) + rtmp.r_ybot -= growDistance; + else + rtmp.r_ybot += growDistanceY; + if (!(growDirs & GROW_EAST)) + rtmp.r_xtop += growDistance; + else + rtmp.r_xtop -= growDistanceX; + if (!(growDirs & GROW_WEST)) + rtmp.r_xbot -= growDistance; + else + rtmp.r_xbot += growDistanceX; + + DBNMPaintPlane(cifPlane, oldType, &rtmp, table, (PaintUndoInfo *) NULL); + oldType = (growDirs & GROW_EAST) ? TiGetRightType(tile) : TiGetLeftType(tile); + } + else + DBPaintPlane(cifPlane, &area, table, (PaintUndoInfo *) NULL); + + /* Check tile corner areas for paint */ + + tp = TR(tile); + if (TiGetLeftType(tp) == oldType) cornerDirs |= STOP_NE; + for (; TOP(LB(tp)) > BOTTOM(tile); tp = LB(tp)); + if (TiGetLeftType(tp) == oldType) cornerDirs |= STOP_SE; + + tp = RT(tile); + if (TiGetBottomType(tp) == oldType) cornerDirs |= STOP_EN; + for (; RIGHT(BL(tp)) > LEFT(tile); tp = BL(tp)); + if (TiGetBottomType(tp) == oldType) cornerDirs |= STOP_WN; + + tp = BL(tile); + if (TiGetRightType(tp) == oldType) cornerDirs |= STOP_SW; + for (; BOTTOM(RT(tp)) < TOP(tile); tp = RT(tp)); + if (TiGetRightType(tp) == oldType) cornerDirs |= STOP_NW; + + tp = LB(tile); + if (TiGetTopType(tp) == oldType) cornerDirs |= STOP_WS; + for (; LEFT(TR(tp)) < RIGHT(tile); tp = TR(tp)); + if (TiGetTopType(tp) == oldType) cornerDirs |= STOP_ES; + + if (growDirs & GROW_NORTH) + { + rtmp = area; + rtmp.r_ybot = area.r_ytop; + rtmp.r_ytop = area.r_ytop + growDistance; + if ((cornerDirs & (STOP_EN | STOP_NE)) == 0) + if (growDirs & GROW_EAST) rtmp.r_xtop += growDistance; + if ((cornerDirs & (STOP_WN | STOP_NW)) == 0) + if (growDirs & GROW_WEST) rtmp.r_xbot -= growDistance; + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + } + + if (growDirs & GROW_EAST) + { + rtmp = area; + rtmp.r_xbot = area.r_xtop; + rtmp.r_xtop = area.r_xtop + growDistance; + if ((cornerDirs & (STOP_EN | STOP_NE)) == 0) + if (growDirs & GROW_NORTH) rtmp.r_ytop += growDistance; + if ((cornerDirs & (STOP_SE | STOP_ES)) == 0) + if (growDirs & GROW_SOUTH) rtmp.r_ybot -= growDistance; + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + } + + if (growDirs & GROW_SOUTH) + { + rtmp = area; + rtmp.r_ytop = area.r_ybot; + rtmp.r_ybot = area.r_ybot - growDistance; + if ((cornerDirs & (STOP_SE | STOP_ES)) == 0) + if (growDirs & GROW_EAST) rtmp.r_xtop += growDistance; + if ((cornerDirs & (STOP_SW | STOP_WS)) == 0) + if (growDirs & GROW_WEST) rtmp.r_xbot -= growDistance; + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + } + + if (growDirs & GROW_WEST) + { + rtmp = area; + rtmp.r_xtop = area.r_xbot; + rtmp.r_xbot = area.r_xbot - growDistance; + if ((cornerDirs & (STOP_NW | STOP_WN)) == 0) + if (growDirs & GROW_NORTH) rtmp.r_ytop += growDistance; + if ((cornerDirs & (STOP_SW | STOP_WS)) == 0) + if (growDirs & GROW_SOUTH) rtmp.r_ybot -= growDistance; + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + } + + CIFTileOps++; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifGrowFunc -- + * + * Called for each relevant tile during grow or shrink operations. + * For growing, these are solid tiles. For shrinking, these are + * space tiles. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Scales the tile by cifScale, then expands its area by the + * distance in the current CIFOp, then paints this area into + * cifNewPlane using the table passed as parameter. + * ---------------------------------------------------------------------------- + */ + +int +cifGrowFunc(tile, table) + Tile *tile; + PaintResultType *table; /* Table to be used for painting. */ +{ + Rect area; + TileType oldType = TiGetTypeExact(tile); + + TiToRect(tile, &area); + + /* In scaling the tile, watch out for infinities!! If something + * is already infinity, don't change it. */ + + if (area.r_xbot > TiPlaneRect.r_xbot) area.r_xbot *= cifScale; + if (area.r_ybot > TiPlaneRect.r_ybot) area.r_ybot *= cifScale; + if (area.r_xtop < TiPlaneRect.r_xtop) area.r_xtop *= cifScale; + if (area.r_ytop < TiPlaneRect.r_ytop) area.r_ytop *= cifScale; + + /* Grow on diagonal tiles: grow rectangular tiles around the */ + /* straight edges of the right-triangle, then copy the diagonal */ + /* tile (at its original size) in the direction of the diagonal. */ + /* Note: A diagonal tile, by definition, can't have infinities. */ + + if (oldType & TT_DIAGONAL) + { + Rect rtmp; + + /* Grow top and bottom */ + + rtmp.r_ybot = area.r_ybot - growDistance; + rtmp.r_ytop = area.r_ytop + growDistance; + + /* Grow around left or right edge */ + + if (oldType & TT_SIDE) + { + rtmp.r_xbot = area.r_xtop - growDistance; + rtmp.r_xtop = area.r_xtop + growDistance; + } + else + { + rtmp.r_xbot = area.r_xbot - growDistance; + rtmp.r_xtop = area.r_xbot + growDistance; + } + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + + /* Now do the same for the other edge. */ + + rtmp.r_xbot = area.r_xbot - growDistance; + rtmp.r_xtop = area.r_xtop + growDistance; + + if (((oldType & TT_SIDE) >> 1) == (oldType & TT_DIRECTION)) /* top */ + { + rtmp.r_ybot = area.r_ytop - growDistance; + rtmp.r_ytop = area.r_ytop + growDistance; + } + else /* bottom */ + { + rtmp.r_ybot = area.r_ybot - growDistance; + rtmp.r_ytop = area.r_ybot + growDistance; + } + DBPaintPlane(cifPlane, &rtmp, table, (PaintUndoInfo *) NULL); + + /* Finally, Move and replace the diagonal tile */ + + if (oldType & TT_SIDE) + { + rtmp.r_xtop = area.r_xtop - growDistance; + rtmp.r_xbot = area.r_xbot - growDistance; + } + else + { + rtmp.r_xtop = area.r_xtop + growDistance; + rtmp.r_xbot = area.r_xbot + growDistance; + } + + if (((oldType & TT_SIDE) >> 1) == (oldType & TT_DIRECTION)) /* top */ + { + rtmp.r_ytop = area.r_ytop - growDistance; + rtmp.r_ybot = area.r_ybot - growDistance; + } + else /* bottom */ + { + rtmp.r_ytop = area.r_ytop + growDistance; + rtmp.r_ybot = area.r_ybot + growDistance; + } + DBNMPaintPlane(cifPlane, oldType, &rtmp, table, (PaintUndoInfo *) NULL); + } + else + { + + /* In scaling the tile, watch out for infinities!! If something + * is already infinity, don't change it. */ + + if (area.r_xbot > TiPlaneRect.r_xbot) area.r_xbot -= growDistance; + if (area.r_ybot > TiPlaneRect.r_ybot) area.r_ybot -= growDistance; + if (area.r_xtop < TiPlaneRect.r_xtop) area.r_xtop += growDistance; + if (area.r_ytop < TiPlaneRect.r_ytop) area.r_ytop += growDistance; + + DBPaintPlane(cifPlane, &area, table, (PaintUndoInfo *) NULL); + } + + CIFTileOps += 1; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifBloatFunc -- + * + * Called once for each tile to be selectively bloated. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Uses the bloat table in the current CIFOp to expand the + * tile depending on which tiles it abuts, then paints the + * expanded area into the new CIF plane. The bloat table + * contains one entry for each tile type. When that tile + * type is seen next to the current tile, the area of the current + * tile is bloated by the table value in that location. The + * only exception to this rule is that internal edges (between + * two tiles of the same type) cause no bloating. + * Note: the original tile is scaled into CIF coordinates. + * ---------------------------------------------------------------------------- + */ + +int +cifBloatFunc(tile, clientData) + Tile *tile; + ClientData clientData; +{ + Rect tileArea, cifArea, bloat; + TileType oldType, type, topLeftType, bottomRightType; + Tile *t; + int tilestart, tilestop, cifstart, cifstop; + BloatData *bloats = (BloatData *)clientData; + int *bloatTable = (int *)bloats->bl_distance; + + oldType = TiGetTypeExact(tile); + TiToRect(tile, &tileArea); + + /* Output the original area of the tile. */ + + cifArea = tileArea; + cifArea.r_xbot *= cifScale; + cifArea.r_xtop *= cifScale; + cifArea.r_ybot *= cifScale; + cifArea.r_ytop *= cifScale; + + /* This is a modified version of the nonmanhattan grow function. */ + /* We grow only in the direction of the diagonal. */ + /* This will not work in all situations! Corner extensions are not */ + /* considered (but should be, for completeness). */ + + if (oldType & TT_DIAGONAL) + { + TileType otherType = (oldType & TT_SIDE) ? + TiGetLeftType(tile) : TiGetRightType(tile); + int dist = bloatTable[otherType]; + + /* The Euclidean grow function is identical to Euclidean bloat-or */ + if (CIFCurStyle->cs_flags & CWF_GROW_EUCLIDEAN) + { + growDistance = dist; + cifGrowEuclideanFunc(tile, CIFPaintTable); + } + else + { + + /* Grow top and bottom */ + + if (((oldType & TT_SIDE) >> 1) == (oldType & TT_DIRECTION)) /* top */ + { + bloat.r_ybot = cifArea.r_ytop - dist; + bloat.r_ytop = cifArea.r_ytop; + } + else /* bottom */ + { + bloat.r_ybot = cifArea.r_ybot; + bloat.r_ytop = cifArea.r_ybot + dist; + } + + /* Grow around left or right edge */ + + if (oldType & TT_SIDE) + { + bloat.r_xbot = cifArea.r_xbot - dist; + bloat.r_xtop = cifArea.r_xtop; + } + else + { + bloat.r_xbot = cifArea.r_xbot; + bloat.r_xtop = cifArea.r_xtop + dist; + } + DBPaintPlane(cifPlane, &bloat, CIFPaintTable, (PaintUndoInfo *) NULL); + + /* Now do the same for the left or right edge. */ + + if (((oldType & TT_SIDE) >> 1) == (oldType & TT_DIRECTION)) /* top */ + { + bloat.r_ybot = cifArea.r_ybot - dist; + bloat.r_ytop = cifArea.r_ytop; + } + else /* bottom */ + { + bloat.r_ybot = cifArea.r_ybot; + bloat.r_ytop = cifArea.r_ytop + dist; + } + + if (oldType & TT_SIDE) + { + bloat.r_xbot = cifArea.r_xtop - dist; + bloat.r_xtop = cifArea.r_xtop; + } + else + { + bloat.r_xbot = cifArea.r_xbot; + bloat.r_xtop = cifArea.r_xbot + dist; + } + DBPaintPlane(cifPlane, &bloat, CIFPaintTable, (PaintUndoInfo *) NULL); + + /* Finally, Move and replace the diagonal tile */ + + if (oldType & TT_SIDE) + { + bloat.r_xtop = cifArea.r_xtop - dist; + bloat.r_xbot = cifArea.r_xbot - dist; + } + else + { + bloat.r_xtop = cifArea.r_xtop + dist; + bloat.r_xbot = cifArea.r_xbot + dist; + } + + if (((oldType & TT_SIDE) >> 1) == (oldType & TT_DIRECTION)) /* top */ + { + bloat.r_ytop = cifArea.r_ytop - dist; + bloat.r_ybot = cifArea.r_ybot - dist; + } + else /* bottom */ + { + bloat.r_ytop = cifArea.r_ytop + dist; + bloat.r_ybot = cifArea.r_ybot + dist; + } + DBNMPaintPlane(cifPlane, oldType, &bloat, CIFPaintTable, + (PaintUndoInfo *) NULL); + } + } + else + DBNMPaintPlane(cifPlane, oldType, &cifArea, CIFPaintTable, + (PaintUndoInfo *) NULL); + + /* Go around the tile, scanning the neighbors along each side. + * Start with the left side, and output the bloats along that + * side, if any. + */ + + tilestop = tileArea.r_ytop; + cifstop = cifArea.r_ytop; + type = oldType; + + /* If the tile type doesn't exist on the left side, skip */ + if (oldType & TT_DIAGONAL) + { + type = TiGetLeftType(tile); + if (oldType & TT_SIDE) + { + if (oldType & TT_DIRECTION) + { + topLeftType = type; + goto dotop; + } + else + { + tilestop = tileArea.r_ybot; + cifstop = cifArea.r_ybot; + type = TiGetBottomType(tile); + } + } + } + + bloat.r_ybot = cifArea.r_ybot - bloatTable[TiGetRightType(LB(tile))]; + bloat.r_xtop = cifArea.r_xbot; + for (t = BL(tile); BOTTOM(t) < TOP(tile); t = RT(t)) + { + if (BOTTOM(t) >= tilestop) continue; + topLeftType = TiGetRightType(t); + bloat.r_xbot = bloat.r_xtop - bloatTable[topLeftType]; + if (TOP(t) > tilestop) + bloat.r_ytop = cifstop; + else bloat.r_ytop = cifScale * TOP(t); + if ((bloatTable[topLeftType] != 0) && (topLeftType != type)) + DBPaintPlane(cifPlane, &bloat, CIFPaintTable, + (PaintUndoInfo *) NULL); + bloat.r_ybot = bloat.r_ytop; + } + + /* Now do the top side. Use the type of the top-left tile to + * side-extend the left end of the top bloat in order to match + * things up at the corner. + */ + +dotop: + cifstart = cifArea.r_xtop; + tilestart = tileArea.r_xtop; + + /* If the tile type doesn't exist on the top side, skip */ + if (oldType & TT_DIAGONAL) + { + type = TiGetTopType(tile); + if (((oldType & TT_SIDE) >> 1) != (oldType & TT_DIRECTION)) + { + if (oldType & TT_SIDE) + goto doright; + else + { + cifstart = cifArea.r_xbot; + tilestart = tileArea.r_xbot; + type = TiGetLeftType(tile); + } + } + } + + bloat.r_ybot = cifArea.r_ytop; + bloat.r_xtop = cifstart; + for (t = RT(tile); RIGHT(t) > LEFT(tile); t = BL(t)) + { + TileType otherType; + if (LEFT(t) >= tilestart) continue; + otherType = TiGetBottomType(t); + bloat.r_ytop = bloat.r_ybot + bloatTable[otherType]; + if (LEFT(t) <= tileArea.r_xbot) + bloat.r_xbot = cifArea.r_xbot - bloatTable[topLeftType]; + else bloat.r_xbot = cifScale * LEFT(t); + if ((bloatTable[otherType] != 0) && (otherType != type)) + DBPaintPlane(cifPlane, &bloat, CIFPaintTable, + (PaintUndoInfo *) NULL); + bloat.r_xtop = bloat.r_xbot; + } + + /* Now do the right side. */ + +doright: + tilestop = tileArea.r_ybot; + cifstop = cifArea.r_ybot; + + /* If the tile type doesn't exist on the right side, skip */ + if (oldType & TT_DIAGONAL) + { + type = TiGetRightType(tile); + if (!(oldType & TT_SIDE)) + { + if (oldType & TT_DIRECTION) + { + bottomRightType = type; + goto dobottom; + } + else + { + tilestop = tileArea.r_ytop; + cifstop = cifArea.r_ytop; + type = TiGetTopType(tile); + } + } + } + + bloat.r_ytop = cifArea.r_ytop + bloatTable[TiGetLeftType(RT(tile))]; + bloat.r_xbot = cifArea.r_xtop; + for (t = TR(tile); TOP(t) > BOTTOM(tile); t = LB(t)) + { + if (TOP(t) <= tilestop) continue; + bottomRightType = TiGetLeftType(t); + bloat.r_xtop = bloat.r_xbot + bloatTable[bottomRightType]; + if (BOTTOM(t) < tilestop) + bloat.r_ybot = cifstop; + else bloat.r_ybot = cifScale * BOTTOM(t); + if ((bloatTable[bottomRightType] != 0) && (bottomRightType != type)) + DBPaintPlane(cifPlane, &bloat, CIFPaintTable, + (PaintUndoInfo *) NULL); + bloat.r_ytop = bloat.r_ybot; + } + + /* Now do the bottom side. Use the type of the bottom-right tile + * to side-extend the right end of the bottom bloat in order to match + * things up at the corner. + */ + +dobottom: + cifstart = cifArea.r_xbot; + tilestart = tileArea.r_xbot; + + /* If the tile type doesn't exist on the bottom side, skip */ + if (oldType & TT_DIAGONAL) + { + type = TiGetBottomType(tile); + if (((oldType & TT_SIDE) >> 1) == (oldType & TT_DIRECTION)) + { + if (!(oldType & TT_DIRECTION)) + goto endbloat; + else + { + cifstart = cifArea.r_xtop; + tilestart = tileArea.r_xtop; + type = TiGetRightType(tile); + } + } + } + + bloat.r_ytop = cifArea.r_ybot; + bloat.r_xbot = cifstart; + for (t = LB(tile); LEFT(t) < RIGHT(tile); t = TR(t)) + { + TileType otherType; + if (RIGHT(t) <= tilestart) continue; + otherType = TiGetTopType(t); + bloat.r_ybot = bloat.r_ytop - bloatTable[otherType]; + if (RIGHT(t) >= tileArea.r_xtop) + bloat.r_xtop = cifArea.r_xtop + bloatTable[bottomRightType]; + else bloat.r_xtop = cifScale * RIGHT(t); + if ((bloatTable[otherType] != 0) && (otherType != type)) + DBPaintPlane(cifPlane, &bloat, CIFPaintTable, + (PaintUndoInfo *) NULL); + bloat.r_xbot = bloat.r_xtop; + } + +endbloat: + CIFTileOps += 1; + 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; + +/* + * ---------------------------------------------------------------------------- + * + * cifBloatAllFunc -- + * + * Called once for each tile to be selectively bloated + * using the CIFOP_BLOATALL operation. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Uses the bloat table in the current CIFOp to expand the tile, + * depending on which tiles it abuts. All bordering material that + * has bl_distance = 1 is painted into the result plane. + * + * ---------------------------------------------------------------------------- + */ + +int +cifBloatAllFunc(tile, bls) + Tile *tile; /* The tile to be processed. */ + BloatStruct *bls; +{ + Rect area; + TileTypeBitMask connect; + Tile *t, *tp; + TileType type; + BloatData *bloats; + int i, locScale; + PlaneMask pmask; + CIFOp *op; + CellDef *def; + static Stack *BloatStack = (Stack *)NULL; + + op = bls->op; + def = bls->def; + bloats = (BloatData *)op->co_client; + + /* Create a mask of all connecting types (these must be in a single + * plane), then call a search function to find all connecting material + * of these types. + */ + + TTMaskZero(&connect); + for (i = 0; i < TT_MAXTYPES; i++) + if (bloats->bl_distance[i] != 0) + TTMaskSetType(&connect, i); + + /* This search function is based on drcCheckArea */ + + if (BloatStack == (Stack *)NULL) + BloatStack = StackNew(64); + + /* If the type of the tile to be processed is not in the same plane */ + /* as the bloat type(s), then find any tile under the tile to be */ + /* processed that belongs to the connect mask, and use that as the */ + /* starting tile. */ + + t = tile; + type = TiGetType(tile); + if (type == CIF_SOLIDTYPE) + { + pmask = 0; + locScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1; + + /* Get the tile into magic database coordinates if it's in CIF coords */ + TiToRect(tile, &area); + area.r_xbot /= locScale; + area.r_xtop /= locScale; + area.r_ybot /= locScale; + area.r_ytop /= locScale; + } + else + { + int pNum = DBPlane(type); + pmask = CoincidentPlanes(&connect, PlaneNumToMaskBit(pNum)); + if (pmask == 0) TiToRect(tile, &area); + locScale = cifScale; + } + if (pmask == 0) + DBSrPaintArea((Tile *)NULL, def->cd_planes[bloats->bl_plane], &area, + &connect, cifFoundFunc, (ClientData)(&BloatStack)); + else + PUSHTILE(t, BloatStack); + + while (!StackEmpty(BloatStack)) + { + t = (Tile *) STACKPOP(BloatStack); + if (t->ti_client != (ClientData)CIF_PENDING) continue; + t->ti_client = (ClientData)CIF_PROCESSED; + + /* Get the tile into CIF coordinates. */ + + TiToRect(t, &area); + area.r_xbot *= locScale; + area.r_ybot *= locScale; + area.r_xtop *= locScale; + area.r_ytop *= locScale; + + DBNMPaintPlane(cifPlane, TiGetTypeExact(t), &area, + CIFPaintTable, (PaintUndoInfo *) NULL); + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (TTMaskHasType(&connect, TiGetBottomType(tp))) + PUSHTILE(tp, BloatStack); + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (TTMaskHasType(&connect, TiGetRightType(tp))) + PUSHTILE(tp, BloatStack); + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (TTMaskHasType(&connect, TiGetTopType(tp))) + PUSHTILE(tp, BloatStack); + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (TTMaskHasType(&connect, TiGetLeftType(tp))) + PUSHTILE(tp, BloatStack); + } + + /* Clear the tiles that were processed */ + + tile->ti_client = (ClientData)CIF_UNPROCESSED; + STACKPUSH(tile, BloatStack); + while (!StackEmpty(BloatStack)) + { + t = (Tile *) STACKPOP(BloatStack); + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (tp->ti_client != (ClientData)CIF_UNPROCESSED) + { + tp->ti_client = (ClientData)CIF_UNPROCESSED; + STACKPUSH(tp, BloatStack); + } + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (tp->ti_client != (ClientData)CIF_UNPROCESSED) + { + tp->ti_client = (ClientData)CIF_UNPROCESSED; + STACKPUSH(tp, BloatStack); + } + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (tp->ti_client != (ClientData)CIF_UNPROCESSED) + { + tp->ti_client = (ClientData)CIF_UNPROCESSED; + STACKPUSH(tp, BloatStack); + } + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (tp->ti_client != (ClientData)CIF_UNPROCESSED) + { + tp->ti_client = (ClientData)CIF_UNPROCESSED; + STACKPUSH(tp, BloatStack); + } + } + 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 */ +/*--------------------------------------------------------------*/ + +/*------------------------------------------------------*/ +/* Data structure used for identifying contact strips */ +/*------------------------------------------------------*/ + +typedef struct _linkedStrip { + Rect area; + bool vertical; /* Tile is vertical */ + bool shrink_ld; /* Shrink left or down before creating cuts */ + bool shrink_ur; /* Shrink right or up before creating cuts */ + struct _linkedStrip *strip_next; +} linkedStrip; + +typedef struct +{ + int size; + int pitch; + linkedStrip *strips; +} StripsData; + +/* + *------------------------------------------------------- + * + * cifSquaresInitFunc -- + * + * Find the first unprocessed tile in the plane. + * + * Results: + * Return 1 to stop the search and process. + * Otherwise, return 0 to keep the search going. + * + *------------------------------------------------------- + */ + +int +cifSquaresInitFunc(tile, clientData) + Tile *tile; + ClientData clientData; +{ + if (tile->ti_client == (ClientData) CIF_UNPROCESSED) + return 1; + else + return 0; +} + +/* + *------------------------------------------------------- + * + * cifSquaresStripFunc -- + * + * Find vertical or horizontal strips of contact + * material that is between 1 and 2 contact cuts wide. + * Generate and return a list of all such strips. + * + * Results: Return 0 to keep the search going. + * + *------------------------------------------------------- + */ + +int +cifSquaresStripFunc(tile, stripsData) + Tile *tile; + StripsData *stripsData; +{ + bool vertical; + int width, height; + linkedStrip *newStrip; + Tile *tp, *tp2; + Rect bbox; + + if (IsSplit(tile)) + return 0; + TiToRect(tile, &bbox); + + /* Check if the tile is wide enough for exactly one cut */ + + width = bbox.r_xtop - bbox.r_xbot; + height = bbox.r_ytop - bbox.r_ybot; + + if (height > width) + { + vertical = TRUE; + height = width; + } + else + vertical = FALSE; + + if ((height < stripsData->size) || (height >= + (stripsData->size + stripsData->pitch))) + return 0; + + /* Ignore strips that are part of a larger */ + /* collection of non-manhattan geometry. */ + + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (IsSplit(tp)) + break; + if (BOTTOM(tp) < TOP(tile)) + return 0; + + /* Note that the max horizontal stripes rule guarantees */ + /* that a tile is always bounded on left and right by */ + /* TT_SPACE. Thus, we only need to search the top and */ + /* bottom boundaries of horizontal tiles. */ + + if (vertical) + { + newStrip = (linkedStrip *)mallocMagic(sizeof(linkedStrip)); + newStrip->area = bbox; + newStrip->vertical = TRUE; + newStrip->shrink_ur = (TTMaskHasType(&CIFSolidBits, + TiGetBottomType(RT(tile)))) ? TRUE : FALSE; + newStrip->shrink_ld = (TTMaskHasType(&CIFSolidBits, + TiGetTopType(LB(tile)))) ? TRUE : FALSE; + newStrip->strip_next = stripsData->strips; + stripsData->strips = newStrip; + } + else + { + int segstart, segend; + int matchstart, matchend; + + tp = RT(tile); + segend = RIGHT(tile); + while (RIGHT(tp) > LEFT(tile)) + { + /* Isolate segments of space along the top of the tile */ + + while ((RIGHT(tp) > LEFT(tile)) && + TTMaskHasType(&CIFSolidBits, TiGetBottomType(tp))) + tp = BL(tp); + segend = MIN(segend, RIGHT(tp)); + while ((RIGHT(tp) > LEFT(tile)) && + TTMaskHasType(&DBSpaceBits, TiGetBottomType(tp))) + tp = BL(tp); + segstart = MAX(LEFT(tile), RIGHT(tp)); + if (segend <= segstart) break; + + /* Find matching segments along the bottom of the tile */ + + for (tp2 = LB(tile); RIGHT(tp2) < segstart; tp2 = TR(tp2)); + + while (LEFT(tp2) < segend) + { + while (RIGHT(tp2) < segstart) tp2 = TR(tp2); + while ((LEFT(tp2) < segend) && + TTMaskHasType(&CIFSolidBits, TiGetTopType(tp2))) + tp2 = TR(tp2); + matchstart = MAX(LEFT(tp2), segstart); + while ((LEFT(tp2) < segend) && + TTMaskHasType(&DBSpaceBits, TiGetTopType(tp2))) + tp2 = TR(tp2); + matchend = MIN(LEFT(tp2), segend); + if (matchend <= matchstart) break; + + /* Process the strip */ + + newStrip = (linkedStrip *)mallocMagic(sizeof(linkedStrip)); + newStrip->area = bbox; + newStrip->area.r_xbot = matchstart; + newStrip->area.r_xtop = matchend; + newStrip->vertical = FALSE; + newStrip->strip_next = stripsData->strips; + newStrip->shrink_ur = (matchend != RIGHT(tile)) ? TRUE : FALSE; + newStrip->shrink_ld = (matchstart != LEFT(tile)) ? TRUE : FALSE; + + stripsData->strips = newStrip; + } + } + } + return 0; +} + + +/* + *------------------------------------------------------- + * + * cifSquaresResetFunc -- + * + * Unmark tiles + * + * Results: Return 0 to keep the search going. + * + *------------------------------------------------------- + */ + +int +cifSquaresResetFunc(tile, clientData) + Tile *tile; + ClientData clientData; /* unused */ +{ + tile->ti_client = (ClientData) CIF_UNPROCESSED; + return 0; +} + +/* + *------------------------------------------------------- + * + * cifUnconnectFunc -- + * + * Find space tiles inside a possible contact area + * + * Results: Return 1 to stop the ongoing search. + * + *------------------------------------------------------- + */ + + +int +cifUnconnectFunc(tile, clientData) + Tile *tile; + ClientData clientData; /* unused */ +{ + TileType t = TiGetTypeExact(tile); + if (t == TT_SPACE) return 1; + else if (t & TT_DIAGONAL) return 1; + else if (tile->ti_client != (ClientData)CIF_PROCESSED) return 1; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifRectBoundingBox -- + * + * Fill regions of the current CIF plane with rectangles that represent + * the bounding box of each unconnected area. This function "cleans + * up" areas processed by multiple rules and removes notches and + * cut-outs. + * + * Results: + * None. + * + * Side effects: + * + * ---------------------------------------------------------------------------- + */ + +void +cifRectBoundingBox(op, cellDef, plane) + CIFOp *op; + CellDef *cellDef; + Plane *plane; +{ + Tile *tile = NULL, *t, *tp; + Rect bbox, area, *maxr; + int i, j, savecount; + TileType type; + bool simple; + static Stack *BoxStack = (Stack *)NULL; + + if (BoxStack == (Stack *)NULL) + BoxStack = StackNew(64); + + while (DBSrPaintArea((Tile *)tile, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresInitFunc, (ClientData)NULL) != 0) + { + /* Now, search for (nontrivially) connected tiles in all */ + /* directions. Mark the tiles, and record the bounding box. */ + /* (Largely copied from cifSquaresFillArea) */ + + simple = TRUE; + tile = plane->pl_hint; + TiToRect(tile, &bbox); + + PUSHTILE(tile, BoxStack); + while (!StackEmpty(BoxStack)) + { + t = (Tile *) STACKPOP(BoxStack); + if (t->ti_client != (ClientData)CIF_PENDING) continue; + t->ti_client = (ClientData)CIF_PROCESSED; + + /* Adjust bounding box */ + TiToRect(t, &area); + GeoInclude(&area, &bbox); + + if (IsSplit(t)) simple = FALSE; + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetBottomType(tp))) + { + simple = FALSE; + PUSHTILE(tp, BoxStack); + } + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetRightType(tp))) + { + simple = FALSE; + PUSHTILE(tp, BoxStack); + } + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetTopType(tp))) + { + simple = FALSE; + PUSHTILE(tp, BoxStack); + } + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetLeftType(tp))) + { + simple = FALSE; + PUSHTILE(tp, BoxStack); + } + } + + if (op->co_client == (ClientData)1) /* external */ + { + DBPaintPlane(cifPlane, &bbox, CIFPaintTable, (PaintUndoInfo *)NULL); + CIFTileOps++; + } + else /* internal */ + { + if (simple) + { + DBPaintPlane(cifPlane, &bbox, CIFPaintTable, (PaintUndoInfo *)NULL); + CIFTileOps++; + } + else + { + maxr = FindMaxRectangle2(&bbox, tile, plane, NULL); + DBPaintPlane(cifPlane, maxr, CIFPaintTable, (PaintUndoInfo *)NULL); + CIFTileOps++; + } + } + + /* Clear the tiles that were processed in this set */ + + tile->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tile, BoxStack); + while (!StackEmpty(BoxStack)) + { + t = (Tile *) STACKPOP(BoxStack); + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, BoxStack); + } + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, BoxStack); + } + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, BoxStack); + } + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, BoxStack); + } + } + } + + /* Clear all the tiles that were processed */ + DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresResetFunc, (ClientData)NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifSquaresFillArea -- + * + * Fill areas in the current CIF output plane with contact cuts based on + * the SQUARES operation passed in "op". This differs from the original + * tile-based contact cut generation by collecting all connected tiles + * in an area, and placing cuts relative to that area's bounding box. + * A tile search is used to select the parts of any non-rectangular area + * inside the bounding box that allow contact cuts, which lets cuts + * be placed across tile boundaries and inside non-manhattan tiles. + * It also allows contacts to be placed inside complex structures such + * as (possibly intersecting) guardrings. + * + * Results: + * None. + * + * Side effects: + * + * ---------------------------------------------------------------------------- + */ + +void +cifSquaresFillArea(op, cellDef, plane) + CIFOp *op; + CellDef *cellDef; + Plane *plane; +{ + Tile *tile, *t, *tp; + Rect bbox, area, square, cut, llcut; + int nAcross, nUp, left, pitch, size, diff, right; + int i, j, k, savecount; + TileType type; + SquaresData *squares = (SquaresData *)op->co_client; + StripsData stripsData; + linkedStrip *stripList; + bool simple; + static Stack *CutStack = (Stack *)NULL; + + pitch = squares->sq_size + squares->sq_sep; + size = squares->sq_size + 2 * squares->sq_border; + diff = squares->sq_sep - 2 * squares->sq_border; + + if (CutStack == (Stack *)NULL) + CutStack = StackNew(64); + + /* Two-pass algorithm */ + + /* Search the plane for "strips", sections of contact that are only */ + /* wide enough for 1 cut. Process them separately, then erase the */ + /* processed areas. The purpose of this is to avoid applying the */ + /* contact matrix algorithm on non-convex spaces, such as guard */ + /* rings, where centering the matrix on the bounding box of the */ + /* contact area may produce a matrix misaligned with the contact */ + /* strips, preventing any contacts from being drawn! Due to the */ + /* maximum horizontal stripes rule for corner stitched tiles, we */ + /* need only identify vertical contact strips. After processing */ + /* and erasing them, all remaining areas will be convex. This */ + /* algorithm allows contacts to be drawn in any arbitrary geometry. */ + + stripsData.size = size; + stripsData.pitch = pitch; + stripsData.strips = NULL; + DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresStripFunc, (ClientData)&stripsData); + + /* Generate cuts in each strip found, then erase the strip */ + + stripList = stripsData.strips; + while (stripList != NULL) + { + Rect stripLess = stripList->area; + + if (diff > 0) + { + if (stripList->vertical) + { + if (stripList->shrink_ur) stripLess.r_ytop -= diff; + if (stripList->shrink_ld) stripLess.r_ybot += diff; + } + else + { + if (stripList->shrink_ur) stripLess.r_xtop -= diff; + if (stripList->shrink_ld) stripLess.r_xbot += diff; + } + } + + /* Create the cuts */ + + if (op->co_opcode == CIFOP_SQUARES) + cifSquareFunc(&stripLess, op, &nUp, &nAcross, &llcut); + else if (op->co_opcode == CIFOP_SQUARES_G) + cifSquareGridFunc(&stripLess, op, &nUp, &nAcross, &llcut); + + cut.r_ybot = llcut.r_ybot; + cut.r_ytop = llcut.r_ytop; + + for (i = 0; i < nUp; i++) + { + cut.r_xbot = llcut.r_xbot; + cut.r_xtop = llcut.r_xtop; + for (j = 0; j < nAcross; j++) + { + DBPaintPlane(cifPlane, &cut, CIFPaintTable, (PaintUndoInfo *)NULL); + cut.r_xbot += pitch; + cut.r_xtop += pitch; + } + cut.r_ybot += pitch; + cut.r_ytop += pitch; + } + if (nUp == 0) + { + if (stripList->shrink_ur == 0 && stripList->shrink_ld == 0) + { + /* The following code is backwardly-compatible with the */ + /* original behavior of allowing cuts that do not have */ + /* sufficient border. Here, we restrict that to contact */ + /* areas exactly matching the cut size. There should be */ + /* a flag to allow contacts to be generated this way. */ + + if ((stripList->area.r_xtop - stripList->area.r_xbot + == squares->sq_size) && (stripList->area.r_ytop + - stripList->area.r_ybot == squares->sq_size)) + { + DBPaintPlane(cifPlane, &stripList->area, CIFPaintTable, + (PaintUndoInfo *)NULL); + CIFTileOps++; + } + else + CIFError(&stripList->area, "no room for contact cuts in area!"); + } + + /* Ad hoc rule catches problems due to contact areas of the proper */ + /* size not fitting cuts because the grid offset prohibits it. */ + else if (((stripList->area.r_ur.p_x - stripList->area.r_ll.p_x) * + (stripList->area.r_ur.p_y - stripList->area.r_ll.p_y)) > + 2 * (pitch * pitch)) + CIFError(&stripList->area, "contact strip with no room for cuts!"); + } + + DBPaintPlane(plane, &stripList->area, CIFEraseTable, + (PaintUndoInfo *) NULL); + freeMagic(stripList); + stripList = stripList->strip_next; + } + + /* 2nd pass: Search the plane for unmarked tiles */ + + while (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresInitFunc, (ClientData)NULL) != 0) + { + /* Now, search for (nontrivially) connected tiles in all */ + /* directions. Mark the tiles, and record the bounding box. */ + /* (Largely copied from cifBloatAllFunc) */ + + simple = TRUE; + tile = plane->pl_hint; + TiToRect(tile, &bbox); + + PUSHTILE(tile, CutStack); + while (!StackEmpty(CutStack)) + { + t = (Tile *) STACKPOP(CutStack); + if (t->ti_client != (ClientData)CIF_PENDING) continue; + t->ti_client = (ClientData)CIF_PROCESSED; + + /* Adjust bounding box */ + TiToRect(t, &area); + GeoInclude(&area, &bbox); + + if (IsSplit(t)) simple = FALSE; + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetBottomType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetRightType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetTopType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetLeftType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + } + + savecount = CIFTileOps; + + for (k = 0; k < 3; k++) /* prepare for up to 3 passes */ + { + /* Determine the contact cut offsets from the bounding box */ + + if (op->co_opcode == CIFOP_SQUARES) + cifSquareFunc(&bbox, op, &nUp, &nAcross, &llcut); + else if (op->co_opcode == CIFOP_SQUARES_G) + cifSquareGridFunc(&bbox, op, &nUp, &nAcross, &llcut); + + cut.r_ybot = llcut.r_ybot; + cut.r_ytop = llcut.r_ytop; + + /* For each contact cut area, check that there is */ + /* no whitespace */ + + for (i = 0; i < nUp; i++) + { + cut.r_xbot = llcut.r_xbot; + cut.r_xtop = llcut.r_xtop; + + square.r_ybot = cut.r_ybot - squares->sq_border; + square.r_ytop = cut.r_ytop + squares->sq_border; + + for (j = 0; j < nAcross; j++) + { + square.r_xbot = cut.r_xbot - squares->sq_border; + square.r_xtop = cut.r_xtop + squares->sq_border; + + /* If there is only one simple rectangle in the */ + /* area, the area is convex, so we don't have to */ + /* check for unconnected regions. */ + + if (simple || DBSrPaintArea((Tile *)tile, plane, &square, + &DBAllTypeBits, cifUnconnectFunc, + (ClientData)NULL) == 0) + { + DBPaintPlane(cifPlane, &cut, CIFPaintTable, + (PaintUndoInfo *)NULL); + CIFTileOps++; + } + cut.r_xbot += pitch; + cut.r_xtop += pitch; + } + cut.r_ybot += pitch; + cut.r_ytop += pitch; + } + if (savecount != CIFTileOps) break; + + /* In non-Manhattan regions with beveled corners, where */ + /* the bounding box has space for 2 contacts, there may not */ + /* be space in the shape itself for more than one. We will */ + /* attempt to shrink X, Y, and/or both to fit (up to 3 */ + /* passes may be necessary). */ + + if (nUp == 2) + { + int bdiff = 1 + (bbox.r_ytop - bbox.r_ybot) - + (2 * (squares->sq_size + squares->sq_border) + + squares->sq_sep); + if (bdiff & 0x1) bdiff++; /* bdiff must be even */ + bdiff >>= 1; /* take half */ + bbox.r_ytop -= bdiff; + bbox.r_ybot += bdiff; + } + else if (nAcross == 2) + { + int bdiff = 1 + (bbox.r_xtop - bbox.r_xbot) - + (2 * (squares->sq_size + squares->sq_border) + + squares->sq_sep); + if (bdiff & 0x1) bdiff++; /* bdiff must be even */ + bdiff >>= 1; /* take half */ + bbox.r_xtop -= bdiff; + bbox.r_xbot += bdiff; + } + else + break; + } + if (savecount == CIFTileOps) + CIFError(&bbox, "no room for contacts in area!"); + + /* Clear the tiles that were processed */ + + tile->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tile, CutStack); + while (!StackEmpty(CutStack)) + { + t = (Tile *) STACKPOP(CutStack); + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + } + } + + /* Clear all the tiles that were processed */ + DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresResetFunc, (ClientData)NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifSlotsFillArea -- + * + * Fill areas in the current CIF output plane with contact cuts based on + * the SLOTS operation passed in "op". This routine is like + * cifSquaresFillArea but handles X and Y dimensions independently. + * + * Results: + * None. + * + * Side effects: + * + * ---------------------------------------------------------------------------- + */ + +void +cifSlotsFillArea(op, cellDef, plane) + CIFOp *op; + CellDef *cellDef; + Plane *plane; +{ + Tile *tile, *t, *tp; + Rect bbox, area, square, cut, llcut; + int nAcross, nUp, left, spitch, lpitch, ssize, lsize, offset; + int diff, right; + int xpitch, ypitch, xborder, yborder, xdiff, ydiff; + int i, j, k, savecount; + TileType type; + SlotsData *slots = (SlotsData *)op->co_client; + StripsData stripsData; + linkedStrip *stripList; + bool simple, vertical; + static Stack *CutStack = (Stack *)NULL; + + spitch = slots->sl_ssize + slots->sl_ssep; + lpitch = slots->sl_lsize + slots->sl_lsep; + ssize = slots->sl_ssize + 2 * slots->sl_sborder; + lsize = slots->sl_lsize + 2 * slots->sl_lborder; + + /* This may not be good in all cases! Amount to shorten a strip */ + /* depends on the orientation of the cuts on either side of the */ + /* connected strip edge. . . */ + diff = slots->sl_lsep - slots->sl_lborder - slots->sl_sborder; + + if (CutStack == (Stack *)NULL) + CutStack = StackNew(64); + + /* Two-pass algorithm */ + + /* Search the plane for "strips", sections of contact that are only */ + /* wide enough for 1 cut. Process them separately, then erase the */ + /* processed areas. The purpose of this is to avoid applying the */ + /* contact matrix algorithm on non-convex spaces, such as guard */ + /* rings, where centering the matrix on the bounding box of the */ + /* contact area may produce a matrix misaligned with the contact */ + /* strips, preventing any contacts from being drawn! Due to the */ + /* maximum horizontal stripes rule for corner stitched tiles, we */ + /* need only identify vertical contact strips. After processing */ + /* and erasing them, all remaining areas will be convex. This */ + /* algorithm allows contacts to be drawn in any arbitrary geometry. */ + + stripsData.size = ssize; + stripsData.pitch = spitch; + stripsData.strips = NULL; + DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresStripFunc, (ClientData)&stripsData); + + /* Generate cuts in each strip found, then erase the strip */ + + stripList = stripsData.strips; + while (stripList != NULL) + { + Rect stripLess = stripList->area; + + if (diff > 0) + { + if (stripList->vertical) + { + if (stripList->shrink_ur) stripLess.r_ytop -= diff; + if (stripList->shrink_ld) stripLess.r_ybot += diff; + } + else + { + if (stripList->shrink_ur) stripLess.r_xtop -= diff; + if (stripList->shrink_ld) stripLess.r_xbot += diff; + } + } + + /* Create the cuts */ + + cifSlotFunc(&stripLess, op, &nUp, &nAcross, &llcut, stripList->vertical); + + cut = llcut; + + if (stripList->vertical) + { + for (i = 0; i < nUp; i++) + { + DBPaintPlane(cifPlane, &cut, CIFPaintTable, (PaintUndoInfo *)NULL); + cut.r_ybot += lpitch; + cut.r_ytop += lpitch; + } + } + else + { + for (i = 0; i < nAcross; i++) + { + DBPaintPlane(cifPlane, &cut, CIFPaintTable, (PaintUndoInfo *)NULL); + cut.r_xbot += lpitch; + cut.r_xtop += lpitch; + } + } + + if (nUp == 0 || nAcross == 0) + { + if (stripList->shrink_ur == 0 && stripList->shrink_ld == 0) + { + /* The following code is backwardly-compatible with the */ + /* original behavior of allowing cuts that do not have */ + /* sufficient border. Here, we restrict that to contact */ + /* areas exactly matching the cut size. There should be */ + /* a flag to allow contacts to be generated this way. */ + + if (((stripList->area.r_xtop - stripList->area.r_xbot + == slots->sl_ssize) && (stripList->area.r_ytop + - stripList->area.r_ybot == slots->sl_lsize)) || + ((stripList->area.r_xtop - stripList->area.r_xbot + == slots->sl_lsize) && (stripList->area.r_ytop + - stripList->area.r_ybot == slots->sl_ssize))) + { + DBPaintPlane(cifPlane, &stripList->area, CIFPaintTable, + (PaintUndoInfo *)NULL); + CIFTileOps++; + } + else + CIFError(&stripList->area, "no room for contact cuts in area!"); + } + + /* Ad hoc rule catches problems due to contact areas of the proper */ + /* size not fitting cuts because the grid offset prohibits it. */ + else if (((stripList->area.r_ur.p_x - stripList->area.r_ll.p_x) * + (stripList->area.r_ur.p_y - stripList->area.r_ll.p_y)) > + 2 * (lpitch * spitch)) + CIFError(&stripList->area, "contact strip with no room for cuts!"); + } + + DBPaintPlane(plane, &stripList->area, CIFEraseTable, + (PaintUndoInfo *) NULL); + freeMagic(stripList); + stripList = stripList->strip_next; + } + + /* 2nd pass: Search the plane for unmarked tiles */ + + while (DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresInitFunc, (ClientData)NULL) != 0) + { + /* Now, search for (nontrivially) connected tiles in all */ + /* directions. Mark the tiles, and record the bounding box. */ + /* (Largely copied from cifBloatAllFunc) */ + + simple = TRUE; + tile = plane->pl_hint; + TiToRect(tile, &bbox); + + PUSHTILE(tile, CutStack); + while (!StackEmpty(CutStack)) + { + t = (Tile *) STACKPOP(CutStack); + if (t->ti_client != (ClientData)CIF_PENDING) continue; + t->ti_client = (ClientData)CIF_PROCESSED; + + /* Adjust bounding box */ + TiToRect(t, &area); + GeoInclude(&area, &bbox); + + if (IsSplit(t)) simple = FALSE; + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetBottomType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetRightType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetTopType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (TTMaskHasType(&CIFSolidBits, TiGetLeftType(tp))) + { + simple = FALSE; + PUSHTILE(tp, CutStack); + } + } + + /* May want to attempt a second pass with the orthogonal alignment? */ + if ((bbox.r_xtop - bbox.r_xbot) > (bbox.r_ytop - bbox.r_ybot)) + vertical = FALSE; + else + vertical = TRUE; + + if (vertical) + { + xpitch = spitch; + ypitch = lpitch; + xborder = slots->sl_sborder; + yborder = slots->sl_lborder; + xdiff = 2 * (slots->sl_ssize + slots->sl_sborder) + slots->sl_ssep; + ydiff = 2 * (slots->sl_lsize + slots->sl_lborder) + slots->sl_lsep; + } + else + { + xpitch = lpitch; + ypitch = spitch; + xborder = slots->sl_lborder; + yborder = slots->sl_sborder; + xdiff = 2 * (slots->sl_lsize + slots->sl_lborder) + slots->sl_lsep; + ydiff = 2 * (slots->sl_ssize + slots->sl_sborder) + slots->sl_ssep; + } + + savecount = CIFTileOps; + + for (k = 0; k < 3; k++) /* prepare for up to 3 passes */ + { + /* Determine the contact cut offsets from the bounding box */ + + cifSlotFunc(&bbox, op, &nUp, &nAcross, &llcut, vertical); + + cut.r_ybot = llcut.r_ybot + slots->sl_start; + cut.r_ytop = llcut.r_ytop + slots->sl_start; + + /* For each contact cut area, check that there is */ + /* no whitespace */ + + offset = slots->sl_start; + for (i = 0; i < nUp; i++) + { + cut.r_xbot = llcut.r_xbot + offset; + cut.r_xtop = llcut.r_xtop + offset; + + square.r_ybot = cut.r_ybot - yborder; + square.r_ytop = cut.r_ytop + yborder; + + for (j = 0; j < nAcross; j++) + { + square.r_xbot = cut.r_xbot - xborder; + square.r_xtop = cut.r_xtop + xborder; + + /* If there is only one simple rectangle in the */ + /* area, the area is convex, so we don't have to */ + /* check for unconnected regions. */ + + if (simple || DBSrPaintArea((Tile *)tile, plane, &square, + &DBAllTypeBits, cifUnconnectFunc, + (ClientData)NULL) == 0) + { + DBPaintPlane(cifPlane, &cut, CIFPaintTable, + (PaintUndoInfo *)NULL); + CIFTileOps++; + } + cut.r_xbot += xpitch; + cut.r_xtop += xpitch; + } + cut.r_ybot += ypitch; + cut.r_ytop += ypitch; + offset += slots->sl_offset; + if (offset >= xpitch) offset -= xpitch; + } + if (savecount != CIFTileOps) break; + + /* In non-Manhattan regions with beveled corners, where */ + /* the bounding box has space for 2 contacts, there may not */ + /* be space in the shape itself for more than one. We will */ + /* attempt to shrink X, Y, and/or both to fit (up to 3 */ + /* passes may be necessary). */ + + if (nUp == 2) + { + int bdiff = 1 + (bbox.r_ytop - bbox.r_ybot) - ydiff; + if (bdiff & 0x1) bdiff++; /* bdiff must be even */ + bdiff >>= 1; /* take half */ + bbox.r_ytop -= bdiff; + bbox.r_ybot += bdiff; + } + else if (nAcross == 2) + { + int bdiff = 1 + (bbox.r_xtop - bbox.r_xbot) - xdiff; + if (bdiff & 0x1) bdiff++; /* bdiff must be even */ + bdiff >>= 1; /* take half */ + bbox.r_xtop -= bdiff; + bbox.r_xbot += bdiff; + } + else + break; + } + if (savecount == CIFTileOps) + CIFError(&bbox, "no room for contacts in area!"); + + /* Clear the tiles that were processed */ + + tile->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tile, CutStack); + while (!StackEmpty(CutStack)) + { + t = (Tile *) STACKPOP(CutStack); + + /* Top */ + for (tp = RT(t); RIGHT(tp) > LEFT(t); tp = BL(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + + /* Left */ + for (tp = BL(t); BOTTOM(tp) < TOP(t); tp = RT(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + + /* Bottom */ + for (tp = LB(t); LEFT(tp) < RIGHT(t); tp = TR(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + + /* Right */ + for (tp = TR(t); TOP(tp) > BOTTOM(t); tp = LB(tp)) + if (tp->ti_client == (ClientData)CIF_PROCESSED) + { + tp->ti_client = (ClientData)CIF_IGNORE; + STACKPUSH(tp, CutStack); + } + } + } + + /* Clear all the tiles that were processed */ + DBSrPaintArea((Tile *)NULL, plane, &TiPlaneRect, &CIFSolidBits, + cifSquaresResetFunc, (ClientData)NULL); +} + +/* + * ---------------------------------------------------------------------------- + * + * cifBloatMaxFunc -- + * + * Called once for each tile to be selectively bloated or + * shrunk using the CIFOP_BLOATMAX or CIFOP_BLOATMIN operation. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Uses the bloat table in the current CIFOp to expand or shrink + * the tile, depending on which tiles it abuts. The rectangular + * area of the tile is modified by moving each side in or out + * by the maximum bloat distance for any of its neighbors on + * that side. The result is a new rectangle, which is OR'ed + * into the result plane. Note: any edge between two tiles of + * same type is given a zero bloat factor. + * + * ---------------------------------------------------------------------------- + */ + +int +cifBloatMaxFunc(tile, op) + Tile *tile; /* The tile to be processed. */ + CIFOp *op; /* Describes the operation to be performed + * (all we care about is the opcode and + * bloat table). + */ +{ + Rect area; + int bloat, tmp; + Tile *t; + TileType type, otherType; + BloatData *bloats = (BloatData *)op->co_client; + + /* Get the tile into CIF coordinates. */ + + type = TiGetType(tile); + TiToRect(tile, &area); + area.r_xbot *= cifScale; + area.r_ybot *= cifScale; + area.r_xtop *= cifScale; + area.r_ytop *= cifScale; + + /* See how much to adjust the left side of the tile. */ + + if (op->co_opcode == CIFOP_BLOATMAX) bloat = -10000000; + else bloat = 10000000; + for (t = BL(tile); BOTTOM(t) < TOP(tile); t = RT(t)) + { + otherType = TiGetType(t); + if (otherType == type) continue; + tmp = bloats->bl_distance[otherType]; + if (op->co_opcode == CIFOP_BLOATMAX) + { + if (tmp > bloat) bloat = tmp; + } + else if (tmp < bloat) bloat = tmp; + } + if ((bloat < 10000000) && (bloat > -10000000)) + area.r_xbot -= bloat; + + /* Now figure out how much to adjust the top side of the tile. */ + + if (op->co_opcode == CIFOP_BLOATMAX) bloat = -10000000; + else bloat = 10000000; + for (t = RT(tile); RIGHT(t) > LEFT(tile); t = BL(t)) + { + otherType = TiGetType(t); + if (otherType == type) continue; + tmp = bloats->bl_distance[otherType]; + if (op->co_opcode == CIFOP_BLOATMAX) + { + if (tmp > bloat) bloat = tmp; + } + else if (tmp < bloat) bloat = tmp; + } + if ((bloat < 10000000) && (bloat > -10000000)) + area.r_ytop += bloat; + + /* Now the right side. */ + + if (op->co_opcode == CIFOP_BLOATMAX) bloat = -10000000; + else bloat = 10000000; + for (t = TR(tile); TOP(t) > BOTTOM(tile); t = LB(t)) + { + otherType = TiGetType(t); + if (otherType == type) continue; + tmp = bloats->bl_distance[otherType]; + if (op->co_opcode == CIFOP_BLOATMAX) + { + if (tmp > bloat) bloat = tmp; + } + else if (tmp < bloat) bloat = tmp; + } + if ((bloat < 10000000) && (bloat > -10000000)) + area.r_xtop += bloat; + + /* Lastly, do the bottom side. */ + + if (op->co_opcode == CIFOP_BLOATMAX) bloat = -10000000; + else bloat = 10000000; + for (t = LB(tile); LEFT(t) < RIGHT(tile); t = TR(t)) + { + otherType = TiGetType(t); + if (otherType == type) continue; + tmp = bloats->bl_distance[otherType]; + if (op->co_opcode == CIFOP_BLOATMAX) + { + if (tmp > bloat) bloat = tmp; + } + else if (tmp < bloat) bloat = tmp; + } + if ((bloat < 10000000) && (bloat > -10000000)) + area.r_ybot -= bloat; + + /* Make sure the tile didn't shrink into negativity. If it's + * ok, paint it into the new plane being built. + */ + + if ((area.r_xbot > area.r_xtop) || (area.r_ybot > area.r_ytop)) + { + TiToRect(tile, &area); + area.r_xbot *= cifScale; + area.r_xtop *= cifScale; + area.r_ybot *= cifScale; + area.r_ytop *= cifScale; + CIFError(&area, "tile inverted by shrink"); + } + else + DBNMPaintPlane(cifPlane, TiGetTypeExact(tile), &area, + CIFPaintTable, (PaintUndoInfo *) NULL); + + CIFTileOps += 1; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * inside_triangle -- + * + * Test if the specified rectangle is completely inside the tile. + * Tile is presumed to be a split tile. + * + * Results: + * TRUE if inside, FALSE if outside or overlapping. + * + * Side Effects: + * None. + * + * Notes: + * This is an optimized version of the code in DBtiles.c. It + * assumes that the square is never infinite. + * + * ---------------------------------------------------------------------------- + */ + +bool +inside_triangle(rect, tile) + Rect *rect; + Tile *tile; +{ + int theight, twidth; + dlong f1, f2, f3, f4; + + theight = TOP(tile) - BOTTOM(tile); + twidth = RIGHT(tile) - LEFT(tile); + + f1 = (dlong)(TOP(tile) - rect->r_ybot) * twidth; + f2 = (dlong)(rect->r_ytop - BOTTOM(tile)) * twidth; + + if (SplitLeftType(tile) != TT_SPACE) + { + /* Inside-of-triangle check */ + f4 = (dlong)(rect->r_xbot - LEFT(tile)) * theight; + if (SplitDirection(tile) ? (f1 > f4) : (f2 > f4)) + return TRUE; + } + else + { + /* Inside-of-triangle check */ + f3 = (dlong)(RIGHT(tile) - rect->r_xtop) * theight; + if (SplitDirection(tile) ? (f2 > f3) : (f1 > f3)) + return TRUE; + } + return FALSE; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifContactFunc -- + * + * Called for each relevant tile when chopping up contacts into + * square cuts using the procedure of using a pre-defined cell + * definition of a single contact and arraying the cell. + * Technically, this is not a CIF function because CIF does not + * have an array method for cells, so there is no advantage to + * drawing lots of subcells in place of drawing lots of boxes. + * In GDS, however, the array method is much more compact than + * drawing individual cuts when the array size is larger than 1. + * + * Results: + * Normally returns 0 to keep the search going. Return 1 if + * the contact type cannot be found, which halts the search. + * + * Side effects: + * Stuff is painted into cifPlane. + * + * ---------------------------------------------------------------------------- + */ + +int +cifContactFunc(tile, csi) + Tile *tile; /* Tile to be diced up. */ + CIFSquaresInfo *csi; /* Describes how to generate squares. */ +{ + Rect area; + int i, nAcross, j, nUp, left, bottom, pitch, halfsize; + bool result; + SquaresData *squares = csi->csi_squares; + + /* For now, don't allow squares on non-manhattan tiles */ + if (IsSplit(tile)) + return 0; + + TiToRect(tile, &area); + pitch = squares->sq_size + squares->sq_sep; + + nAcross = (area.r_xtop - area.r_xbot + squares->sq_sep + - (2 * squares->sq_border)) / pitch; + if (nAcross == 0) + { + left = (area.r_xbot + area.r_xtop - squares->sq_size) / 2; + if (left >= area.r_xbot) nAcross = 1; + } + else + left = (area.r_xbot + area.r_xtop + squares->sq_sep + - (nAcross * pitch)) / 2; + + nUp = (area.r_ytop - area.r_ybot + squares->sq_sep + - (2 * squares->sq_border)) / pitch; + if (nUp == 0) + { + bottom = (area.r_ybot + area.r_ytop - squares->sq_size) / 2; + if (bottom >= area.r_ybot) nUp = 1; + } + else + bottom = (area.r_ybot + area.r_ytop + squares->sq_sep + - (nUp * pitch)) / 2; + + /* Lower-left coordinate should be centered on the contact cut, as + * contact definitions are centered on the origin. + */ + halfsize = (squares->sq_size / 2); + left += halfsize; + bottom += halfsize; + + result = CalmaGenerateArray((FILE *)csi->csi_client, csi->csi_type, + left, bottom, pitch, nAcross, nUp); + + return (result == TRUE) ? 0 : 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifSlotFunc -- + * + * Called for each relevant tile area when chopping areas up into + * slots (rectangles). Determines how to divide up the area into + * slots, and generates the number of rows, columns, and the lower- + * left-most cut rectangle. + * + * Results: + * Always return 0 + * + * Side effects: + * Pointers "rows", "columns", and "cut" are filled with + * appropriate values. + * + * ---------------------------------------------------------------------------- + */ + +int +cifSlotFunc(area, op, numY, numX, cut, vertical) + Rect *area; /* Area to be diced up */ + CIFOp *op; /* Describes how to generate squares. */ + int *numY, *numX; /* Return values: # rows and # columns */ + Rect *cut; /* initial (lower left) cut area */ + bool vertical; /* if TRUE, slot is aligned vertically */ +{ + int i, j, xpitch, ypitch, delta; + int *axtop, *axbot, *aytop, *aybot; + int *sxtop, *sxbot, *sytop, *sybot; + int *rows, *columns; + SlotsData *slots = (SlotsData *)op->co_client; + + /* Orient to the short/long orientation of the tile */ + + /* Assume a vertical tile; if not, reorient area and remember */ + if (vertical) + { + axbot = &area->r_xbot; + aybot = &area->r_ybot; + axtop = &area->r_xtop; + aytop = &area->r_ytop; + sxbot = &cut->r_xbot; + sybot = &cut->r_ybot; + sxtop = &cut->r_xtop; + sytop = &cut->r_ytop; + rows = numY; + columns = numX; + } + else + { + axbot = &area->r_ybot; + aybot = &area->r_xbot; + axtop = &area->r_ytop; + aytop = &area->r_xtop; + sxbot = &cut->r_ybot; + sybot = &cut->r_xbot; + sxtop = &cut->r_ytop; + sytop = &cut->r_xtop; + rows = numX; + columns = numY; + } + + xpitch = slots->sl_ssize + slots->sl_ssep; + +calcX: + *columns = (*axtop - *axbot + slots->sl_ssep - (2 * slots->sl_sborder)) / xpitch; + if (*columns == 0) + { + *rows = 0; + return 0; + // *sxbot = (*axbot + *axtop - slots->sl_ssize) / 2; + // if (*sxbot >= *axbot) *columns = 1; + } + else + *sxbot = (*axbot + *axtop + slots->sl_ssep - (*columns * xpitch)) / 2; + *sxtop = *sxbot + slots->sl_ssize; + + /* Check that we are not violating any gridlimit */ + + if (CIFCurStyle && (CIFCurStyle->cs_gridLimit > 1)) + { + delta = abs(*sxbot) % CIFCurStyle->cs_gridLimit; + if (delta > 0) + { + *axtop -= 2 * delta; + goto calcX; + } + } + + if (slots->sl_lsize > 0) + { + ypitch = slots->sl_lsize + slots->sl_lsep; +calcY: + *rows = (*aytop - *aybot + slots->sl_lsep - (2 * slots->sl_lborder)) / ypitch; + if (*rows == 0) + { + return 0; + // *sybot = (*aybot + *aytop - slots->sl_lsize) / 2; + // if (*sybot >= *aybot) *rows = 1; + } + else + *sybot = (*aybot + *aytop + slots->sl_lsep - (*rows * ypitch)) / 2; + *sytop = *sybot + slots->sl_lsize; + + /* Check that we are not violating any gridlimit */ + + if (CIFCurStyle && (CIFCurStyle->cs_gridLimit > 1)) + { + delta = abs(*sybot) % CIFCurStyle->cs_gridLimit; + if (delta > 0) + { + *aytop -= 2 * delta; + goto calcY; + } + } + } + else + { + *rows = 1; + *sybot = *aybot + slots->sl_lborder; + *sytop = *aytop - slots->sl_lborder; + /* There's no space to fit a slot */ + if (*sytop - *sybot <= 0) + return 0; + } + + /* To be done---slot offsets */ + + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifSquareFunc -- + * + * Called for each relevant rectangle when chopping areas up into + * squares. Determines the number of rows and columns in the area + * and returns these and the area of the lower-left cut. + * + * Results: + * Always return 0 + * + * Side effects: + * Results filled in the pointer positions passed to the function + * + * ---------------------------------------------------------------------------- + */ + +int +cifSquareFunc(area, op, rows, columns, cut) + Rect *area; /* Area to be diced up */ + CIFOp *op; /* Describes how to generate squares. */ + int *rows, *columns; /* Return values: # rows and # columns, */ + Rect *cut; /* initial (lower left) cut area. */ +{ + int pitch, delta; + bool glimit; + SquaresData *squares = (SquaresData *)op->co_client; + + glimit = (CIFCurStyle && (CIFCurStyle->cs_gridLimit > 1)) ? TRUE : FALSE; + pitch = squares->sq_size + squares->sq_sep; + + /* Compute the real border to leave around the sides. If only + * one square will fit in a particular direction, center it + * regardless of the requested border size. If more than one + * square will fit, then fit it in extras only if at least the + * requested border size can be left. Also center things in the + * rectangle, so that the box's exact size doesn't matter. This + * trickiness is done so that coincident contacts from overlapping + * cells always have their squares line up, regardless of the + * orientation of the cells. + * + * Update 1/13/09: Removed the "feature" that allows contact + * cuts that violate the border requirement. The "slots" rule + * can be used if necessary to generate cuts with different + * border allowances. + */ + +sqX: + *columns = (area->r_xtop - area->r_xbot + squares->sq_sep + - (2 * squares->sq_border)) / pitch; + if (*columns == 0) + { + *rows = 0; + return 0; + + // cut->r_xbot = (area->r_xbot + area->r_xtop - squares->sq_size) / 2; + // if (cut->r_xbot >= area->r_xbot) *columns = 1; + } + else + { + cut->r_xbot = (area->r_xbot + area->r_xtop + squares->sq_sep + - (*columns * pitch)) / 2; + } + + /* Check for any gridlimit violation */ + + if (glimit) + { + delta = abs(cut->r_xbot) % CIFCurStyle->cs_gridLimit; + if (delta > 0) + { + area->r_xtop -= 2 * delta; + goto sqX; + } + } + +sqY: + *rows = (area->r_ytop - area->r_ybot + squares->sq_sep + - (2 * squares->sq_border)) / pitch; + if (*rows == 0) + { + return 0; + + // cut->r_ybot = (area->r_ybot + area->r_ytop - squares->sq_size) / 2; + // if (cut->r_ybot >= area->r_ybot) *rows = 1; + } + else + { + cut->r_ybot = (area->r_ybot + area->r_ytop + squares->sq_sep + - (*rows * pitch)) / 2; + } + + /* Check for any gridlimit violation */ + + if (glimit) + { + delta = abs(cut->r_ybot) % CIFCurStyle->cs_gridLimit; + if (delta > 0) + { + area->r_ytop -= 2 * delta; + goto sqY; + } + } + + cut->r_xtop = cut->r_xbot + squares->sq_size; + cut->r_ytop = cut->r_ybot + squares->sq_size; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * cifSquareGridFunc -- + * + * Called for each relevant rectangle when chopping areas up into + * squares. Determines the number of rows and columns in the area + * and returns these and the area of the lower-left cut. + * + * Results: + * Always return 0 + * + * Side effects: + * Results filled in the pointer positions passed to the function + * + * ---------------------------------------------------------------------------- + */ + +int +cifSquareGridFunc(area, op, rows, columns, cut) + Rect *area; /* Area to be diced up */ + CIFOp *op; /* Describes how to generate squares. */ + int *rows, *columns; /* Return values: # rows and # columns, */ + Rect *cut; /* initial (lower left) cut area. */ +{ + Rect locarea; + int left, bottom, right, top, pitch; + int gridx, gridy, margin; + SquaresData *squares = (SquaresData *)op->co_client; + + /* + * It may be necessary to generate contacts on a specific grid; e.g., + * to avoid placing contacts at half-lambda. If this is the case, + * then the DRC section of the techfile should specify "no overlap" + * for these types. + * + * This routine has been simplified. It flags a warning when there + * is not enough space for a contact cut, rather than attempting to + * draw a cut without enough border area. The routine has also been + * extended to allow different x and y grids to be specified. This + * allows certain tricks, such as generating offset contact grids on + * a pad, as required by some processes. + */ + + pitch = squares->sq_size + squares->sq_sep; + gridx = squares->sq_gridx; + gridy = squares->sq_gridy; + + locarea.r_xtop = area->r_xtop - squares->sq_border; + locarea.r_ytop = area->r_ytop - squares->sq_border; + locarea.r_xbot = area->r_xbot + squares->sq_border; + locarea.r_ybot = area->r_ybot + squares->sq_border; + + left = locarea.r_xbot / gridx; + left *= gridx; + if (left < locarea.r_xbot) left += gridx; + + bottom = locarea.r_ybot / gridy; + bottom *= gridy; + if (bottom < locarea.r_ybot) bottom += gridy; + + *columns = (locarea.r_xtop - left + squares->sq_sep) / pitch; + if (*columns == 0) + { + *rows = 0; + return 0; + } + + *rows = (locarea.r_ytop - bottom + squares->sq_sep) / pitch; + if (*rows == 0) return 0; + + /* Center the contacts while remaining on-grid */ + right = left + *columns * squares->sq_size + (*columns - 1) * squares->sq_sep; + top = bottom + *rows * squares->sq_size + (*rows - 1) * squares->sq_sep; + margin = ((locarea.r_xtop - right) - (left - locarea.r_xbot)) / (gridx * 2); + locarea.r_xbot = left + margin * gridx; + margin = ((locarea.r_ytop - top) - (bottom - locarea.r_ybot)) / (gridy * 2); + locarea.r_ybot = bottom + margin * gridy; + + cut->r_ybot = locarea.r_ybot; + cut->r_ytop = cut->r_ybot + squares->sq_size; + cut->r_xbot = locarea.r_xbot; + cut->r_xtop = cut->r_xbot + squares->sq_size; + return 0; +} + + +/* + * ---------------------------------------------------------------------------- + * + * cifSrTiles -- + * + * This is a utility procedure that just calls DBSrPaintArea + * one or more times for the planes being used in processing + * one CIFOp. + * + * Results: + * None. + * + * Side effects: + * This procedure itself has no side effects. For each of the + * paint or temporary planes indicated in cifOp, we call + * DBSrPaintArea to find the desired tiles in the desired + * area for the operation. DBSrPaintArea is given func as a + * search function, and cdArg as ClientData. + * + * ---------------------------------------------------------------------------- + */ + +void +cifSrTiles(cifOp, area, cellDef, temps, func, cdArg) + CIFOp *cifOp; /* Geometric operation being processed. */ + Rect *area; /* Area of Magic paint to consider. */ + CellDef *cellDef; /* CellDef to search for paint. */ + Plane *temps[]; /* Planes to use for temporaries. */ + int (*func)(); /* Search function to pass to DBSrPaintArea. */ + ClientData cdArg; /* Client data for func. */ +{ + TileTypeBitMask maskBits; + TileType t; + Tile *tp; + int i; + BloatData *bloats; + + /* When reading data from a cell, it must first be scaled to + * CIF units. Check for CIFCurStyle, as we don't want to + * crash while reading CIF/GDS just becuase the techfile + * "cifoutput" section was blank. + */ + + cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1; + + /* Bloat operations (except bloat-all) have to be in a single plane */ + + switch (cifOp->co_opcode) { + case CIFOP_BLOAT: + case CIFOP_BLOATMIN: + case CIFOP_BLOATMAX: + bloats = (BloatData *)cifOp->co_client; + i = bloats->bl_plane; + maskBits = DBPlaneTypes[i]; + TTMaskAndMask(&maskBits, &cifOp->co_paintMask); + if (!TTMaskEqual(&maskBits, &DBZeroTypeBits)) + DBSrPaintArea((Tile *) NULL, cellDef->cd_planes[i], + area, &cifOp->co_paintMask, func, cdArg); + break; + + default: + for (i = PL_DRC_CHECK; i < DBNumPlanes; i++) + { + maskBits = DBPlaneTypes[i]; + TTMaskAndMask(&maskBits, &cifOp->co_paintMask); + if (!TTMaskEqual(&maskBits, &DBZeroTypeBits)) + (void) DBSrPaintArea((Tile *) NULL, cellDef->cd_planes[i], + area, &cifOp->co_paintMask, func, cdArg); + } + break; + } + + /* When processing CIF data, use everything in the plane. */ + + cifScale = 1; + for (t = 0; t < TT_MAXTYPES; t++, temps++) + if (TTMaskHasType(&cifOp->co_cifMask, t)) + (void) DBSrPaintArea((Tile *) NULL, *temps, &TiPlaneRect, + &CIFSolidBits, func, (ClientData) cdArg); +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFGenLayer -- + * + * This routine will generate one CIF layer. + * It provides the core of the CIF generator. + * + * Results: + * Returns a malloc'ed plane with tiles of type CIF_SOLIDTYPE + * marking the area of this CIF layer as built up by op. + * + * Side effects: + * None, except to create a new plane holding the CIF for the layer. + * The CIF that's generated may fall outside of area... it's what + * results from considering everything in area. In most cases the + * caller will clip the results down to the desired area. + * + * ---------------------------------------------------------------------------- + */ + +Plane * +CIFGenLayer(op, area, cellDef, temps, clientdata) + CIFOp *op; /* List of CIFOps telling how to make layer. */ + Rect *area; /* Area to consider when generating CIF. Only + * material in this area will be considered, so + * the caller should usually expand his desired + * area by one CIF radius. + */ + CellDef *cellDef; /* CellDef to search when paint layers are + * needed for operation. + */ + Plane *temps[]; /* Temporary layers to be used when needed + * for operation. + */ + ClientData clientdata; /* + * Data that may be passed to the CIF operation + * function. + */ +{ + Plane *temp; + static Plane *nextPlane, *curPlane; + Rect bbox; + CIFOp *tempOp; + CIFSquaresInfo csi; + SearchContext scx; + TileType ttype; + char *netname; + BloatStruct bls; + int (*cifGrowFuncPtr)() = (CIFCurStyle->cs_flags & CWF_GROW_EUCLIDEAN) ? + cifGrowEuclideanFunc : cifGrowFunc; + + /* Set up temporary planes used during computation. One of these + * will be returned as the result (whichever is curPlane at the + * end of the computation). The other is saved for later use. + */ + + if (nextPlane == NULL) + nextPlane = DBNewPlane((ClientData) TT_SPACE); + curPlane = DBNewPlane((ClientData) TT_SPACE); + + /* Go through the geometric operations and process them one + * at a time. + */ + + for ( ; op != NULL; op = op->co_next) + { + switch (op->co_opcode) + { + /* For AND, first collect all the stuff to be anded with + * plane in a temporary plane. Then find all the places + * where there isn't any stuff, and erase from the + * current plane. + */ + + case CIFOP_AND: + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifSrTiles(op, area, cellDef, temps, cifPaintFunc, + (ClientData) CIFPaintTable); + cifPlane = curPlane; + cifScale = 1; + (void) DBSrPaintArea((Tile *) NULL, nextPlane, &TiPlaneRect, + &DBSpaceBits, cifPaintFunc, + (ClientData) CIFEraseTable); + break; + + /* For OR, just use cifPaintFunc to OR the areas of all + * relevant tiles into plane. HOWEVER, if the co_client + * record is non-NULL and CalmaContactArrays is TRUE, + * then for each contact type, we do the paint function + * separately, then call the contact array generation + * procedure. + */ + + case CIFOP_OR: + cifPlane = curPlane; + cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1; + + if ((op->co_client != (ClientData)NULL) + && (CalmaContactArrays == TRUE)) + { + TileTypeBitMask paintMask, errMask, *rMask; + TileType i, j; + + TTMaskZero(&errMask); + TTMaskZero(&paintMask); + TTMaskSetMask(&paintMask, &op->co_paintMask); + for (i = TT_TECHDEPBASE; i < DBNumUserLayers; i++) + { + if (TTMaskHasType(&paintMask, i)) + { + TTMaskSetOnlyType(&op->co_paintMask, i); + for (j = DBNumUserLayers; j < DBNumTypes; j++) + { + rMask = DBResidueMask(j); + if (TTMaskHasType(rMask, i)) + TTMaskSetType(&op->co_paintMask, j); + } + + cifSrTiles(op, area, cellDef, temps, cifPaintFunc, + (ClientData) CIFPaintTable); + + csi.csi_squares = (SquaresData *)op->co_client; + csi.csi_type = i; + csi.csi_client = clientdata; + + if (DBSrPaintArea((Tile *) NULL, curPlane, + &TiPlaneRect, &CIFSolidBits, + cifContactFunc, (ClientData) &csi)) + { + /* Failure of DBSrPaintArea() (returns 1) + * indicates that a contact cell type + * could not be found for magic layer i. + * Record the error for subsequent handling. + */ + TTMaskSetType(&errMask, i); + } + DBClearPaintPlane(curPlane); + } + } + if (!TTMaskIsZero(&errMask)) + { + /* + * Handle layers for which a contact cell could + * not be found in the default manner. + */ + TTMaskZero(&op->co_paintMask); + TTMaskSetMask(&op->co_paintMask, &errMask); + cifSrTiles(op, area, cellDef, temps, cifPaintFunc, + (ClientData) CIFPaintTable); + } + + /* Recover the original magic layer mask for the cifop */ + + TTMaskZero(&op->co_paintMask); + TTMaskSetMask(&op->co_paintMask, &paintMask); + } + else + { + cifSrTiles(op, area, cellDef, temps, cifPaintFunc, + (ClientData) CIFPaintTable); + } + break; + + /* For ANDNOT, do exactly the same thing as OR, except erase + * instead of paint. + */ + + case CIFOP_ANDNOT: + cifPlane = curPlane; + cifSrTiles(op, area, cellDef, temps, cifPaintFunc, + (ClientData) CIFEraseTable); + break; + + /* For GROW, just find all solid tiles in the current plane, + * and paint a larger version into a new plane. The switch + * the current and new planes. + */ + + case CIFOP_GROW: + growDistance = op->co_distance; + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifScale = 1; + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &CIFSolidBits, *cifGrowFuncPtr, (ClientData) CIFPaintTable); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + + /* GROWMIN grows non-uniformly to ensure minimum dimensions */ + + case CIFOP_GROWMIN: + growDistance = op->co_distance; + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifScale = 1; + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &CIFSolidBits, cifGrowMinFunc, (ClientData)CIFPaintTable); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + + /* REMOVE removes areas not meeting minimum width dimension */ + + case CIFOP_REMOVE: + growDistance = op->co_distance; + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifScale = 1; + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &CIFSolidBits, cifRemoveFunc, (ClientData)CIFPaintTable); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + + /* GROW_G grows non-uniformly to the indicated grid. */ + + case CIFOP_GROW_G: + growDistance = op->co_distance; + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifScale = 1; + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &CIFSolidBits, cifGrowGridFunc, (ClientData) CIFPaintTable); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + + /* SHRINK is just like grow except work from the space tiles. */ + + case CIFOP_SHRINK: + growDistance = op->co_distance; + DBClearPaintPlane(nextPlane); + DBPaintPlane(nextPlane, &TiPlaneRect, CIFPaintTable, + (PaintUndoInfo *) NULL); + cifPlane = nextPlane; + cifScale = 1; + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &DBSpaceBits, *cifGrowFuncPtr, (ClientData) CIFEraseTable); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + + case CIFOP_CLOSE: + growDistance = op->co_distance; + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifScale = 1; + /* First copy the existing paint into the target plane */ + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &CIFSolidBits, cifPaintFunc, (ClientData)CIFPaintTable); + + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &DBSpaceBits, cifCloseFunc, (ClientData)&curPlane); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + + case CIFOP_BLOAT: + cifPlane = curPlane; + cifSrTiles(op, area, cellDef, temps, + cifBloatFunc, op->co_client); + break; + + case CIFOP_BLOATMAX: + case CIFOP_BLOATMIN: + cifPlane = curPlane; + cifSrTiles(op, area, cellDef, temps, + cifBloatMaxFunc, (ClientData) op); + break; + + case CIFOP_BLOATALL: + cifPlane = curPlane; + bls.op = op; + bls.def = cellDef; + cifSrTiles(op, area, cellDef, temps, + cifBloatAllFunc, (ClientData)&bls); + break; + + case CIFOP_SQUARES: + if (CalmaContactArrays == FALSE) + { + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifSquaresFillArea(op, cellDef, curPlane); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + } + break; + + case CIFOP_SQUARES_G: + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifSquaresFillArea(op, cellDef, curPlane); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + + case CIFOP_SLOTS: + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifSlotsFillArea(op, cellDef, curPlane); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + + case CIFOP_MAXRECT: + cifPlane = curPlane; + + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifRectBoundingBox(op, cellDef, curPlane); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + + case CIFOP_NET: + netname = (char *)op->co_client; + cifPlane = curPlane; + ttype = CmdFindNetProc(netname, CIFDummyUse, &bbox, FALSE); + if (ttype != TT_SPACE) + { + UndoDisable(); + DBCellClearDef(Select2Def); + scx.scx_area = bbox; + scx.scx_use = CIFDummyUse; + scx.scx_trans = GeoIdentityTransform; + DBTreeCopyConnect(&scx, &DBConnectTbl[ttype], 0, + DBConnectTbl, &TiPlaneRect, Select2Use); + cifSrTiles(op, area, Select2Def, temps, cifPaintFunc, + (ClientData) CIFPaintTable); + DBCellClearDef(Select2Def); + UndoEnable(); + } + break; + + case CIFOP_BOUNDARY: + cifPlane = curPlane; + /* This function for cifoutput only. cifinput handled separately. */ + if (cellDef && (cellDef->cd_flags & CDFIXEDBBOX)) + { + char *propvalue; + bool found; + + propvalue = (char *)DBPropGet(cellDef, "FIXED_BBOX", &found); + if (!found) break; + if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot, + &bbox.r_xtop, &bbox.r_ytop) != 4) break; + + cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1; + bbox.r_xbot *= cifScale; + bbox.r_xtop *= cifScale; + bbox.r_ybot *= cifScale; + bbox.r_ytop *= cifScale; + DBNMPaintPlane(cifPlane, CIF_SOLIDTYPE, &bbox, + CIFPaintTable, (PaintUndoInfo *)NULL); + } + break; + + case CIFOP_BBOX: + if (CIFErrorDef == NULL) break; + + /* co_client contains the flag (1) for top-level only */ + if ((int)op->co_client == 1) + { + /* Only generate output for the top-level cell */ + int found = 0; + CellUse *celluse; + for (celluse = CIFErrorDef->cd_parents; + celluse != (CellUse *) NULL; + celluse = celluse->cu_nextuse) + { + if (celluse->cu_parent != (CellDef *) NULL) + if ((celluse->cu_parent->cd_flags & CDINTERNAL) + != CDINTERNAL) + { + found = 1; + break; + } + } + if (found != 0) break; + } + cifPlane = curPlane; + bbox = CIFErrorDef->cd_bbox; + cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1; + bbox.r_xbot *= cifScale; + bbox.r_xtop *= cifScale; + bbox.r_ybot *= cifScale; + bbox.r_ytop *= cifScale; + DBNMPaintPlane(curPlane, CIF_SOLIDTYPE, &bbox, + CIFPaintTable, (PaintUndoInfo *)NULL); + break; + + default: + continue; + } + } + + return curPlane; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFGen -- + * + * This procedure generates a complete set of CIF layers for + * a particular area of a particular cell. NOTE: if the argument + * genAllPlanes is FALSE, only planes for those layers having + * a bit set in 'layers' are generated; the others are set + * to NULL. + * + * Results: + * None. + * + * Side effects: + * The parameters realPlanes and tempPlanes are modified + * to hold the CIF and temporary layers for area of cellDef, + * as determined by the current CIF generation rules. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFGen(cellDef, area, planes, layers, replace, genAllPlanes, clientdata) + CellDef *cellDef; /* Cell for which CIF is to be generated. */ + Rect *area; /* Any CIF overlapping this area (in coords + * of cellDef) will be generated. The CIF + * will be clipped to this area. + */ + Plane **planes; /* Pointer to array of pointers to planes + * to hold "real" CIF layers that are + * generated. Pointers may initially be + * NULL. + */ + TileTypeBitMask *layers; /* CIF layers to generate. */ + bool replace; /* TRUE means that the new CIF is to replace + * anything that was previously in planes. + * FALSE means that the new CIF is to be + * OR'ed in with the current contents of + * planes. + */ + bool genAllPlanes; /* If TRUE, generate a tile plane even for + * those layers not specified as being + * generated in the 'layers' mask above. + */ + ClientData clientdata; /* Data that may be passed along to the + * CIF operation functions. + */ +{ + int i; + Plane *new[MAXCIFLAYERS]; + Rect expanded, clip; + + /* + * Generate the area in magic coordinates to search, and the area in + * cif coordinates to use in clipping the results of CIFGenLayer(). + */ + cifGenClip(area, &expanded, &clip); + + /* + * Generate all of the new layers in a temporary place. + * If a layer isn't being generated, leave new[i] set to + * NULL to indicate this fact. + */ + for (i = 0; i < CIFCurStyle->cs_nLayers; i++) + { + if (TTMaskHasType(layers,i)) + { + CIFErrorLayer = i; + new[i] = CIFGenLayer(CIFCurStyle->cs_layers[i]->cl_ops, + &expanded, cellDef, new, clientdata); + + /* Clean up the non-manhattan geometry in the plane */ + if (CIFUnfracture) DBMergeNMTiles(new[i], &expanded, + (PaintUndoInfo *)NULL); + } + else if (genAllPlanes) new[i] = DBNewPlane((ClientData) TT_SPACE); + else new[i] = (Plane *) NULL; + } + + /* + * Now mask off all the unwanted material in the new layers, and + * either OR them into the existing layers or replace the existing + * material with them. + */ + for (i = 0; i < CIFCurStyle->cs_nLayers; i += 1) + { + if (new[i]) + cifClipPlane(new[i], &clip); + + if (replace) + { + if (planes[i]) + { + DBFreePaintPlane(planes[i]); + TiFreePlane(planes[i]); + } + planes[i] = new[i]; + continue; + } + + if (planes[i]) + { + if (new[i]) + { + cifPlane = planes[i]; + cifScale = 1; + (void) DBSrPaintArea((Tile *) NULL, new[i], &TiPlaneRect, + &CIFSolidBits, cifPaintFunc, + (ClientData) CIFPaintTable); + DBFreePaintPlane(new[i]); + TiFreePlane(new[i]); + } + } + else planes[i] = new[i]; + } +} + +/* + * ---------------------------------------------------------------------------- + * + * cifClipPlane -- + * + * Erase the portions of the plane 'plane' that lie outside of 'clip'. + * + * Results: + * None. + * + * Side effects: + * See above. + * + * ---------------------------------------------------------------------------- + */ + +void +cifClipPlane(plane, clip) + Plane *plane; + Rect *clip; +{ + Rect r; + + if (clip->r_xtop < TiPlaneRect.r_xtop) + { + r = TiPlaneRect; + r.r_xbot = clip->r_xtop; + DBPaintPlane(plane, &r, CIFEraseTable, (PaintUndoInfo *) NULL); + } + if (clip->r_ytop < TiPlaneRect.r_ytop) + { + r = TiPlaneRect; + r.r_ybot = clip->r_ytop; + DBPaintPlane(plane, &r, CIFEraseTable, (PaintUndoInfo *) NULL); + } + if (clip->r_xbot > TiPlaneRect.r_xbot) + { + r = TiPlaneRect; + r.r_xtop = clip->r_xbot; + DBPaintPlane(plane, &r, CIFEraseTable, (PaintUndoInfo *) NULL); + } + if (clip->r_ybot > TiPlaneRect.r_ybot) + { + r = TiPlaneRect; + r.r_ytop = clip->r_ybot; + DBPaintPlane(plane, &r, CIFEraseTable, (PaintUndoInfo *) NULL); + } +} + +/* + * ---------------------------------------------------------------------------- + * + * cifGenClip -- + * + * Compute two new areas from the original area: one ('expanded') + * is expanded by a CIF halo and is used to determine how much of + * the database to search to find what's relevant for CIF generation; + * the other ('clip') is the CIF equivalent of area and is used to + * clip the resulting CIF. This code is tricky because area may run + * off to infinity, and we have to be careful not to expand past infinity. + * + * Results: + * None. + * + * Side effects: + * Sets *expanded and *clip. + * + * ---------------------------------------------------------------------------- + */ + +void +cifGenClip(area, expanded, clip) + Rect *area; /* Any CIF overlapping this area (in coords + * of cellDef) will be generated. The CIF + * will be clipped to this area. + */ + Rect *expanded, *clip; +{ + if (area->r_xbot > TiPlaneRect.r_xbot) + { + clip->r_xbot = area->r_xbot * CIFCurStyle->cs_scaleFactor; + expanded->r_xbot = area->r_xbot - CIFCurStyle->cs_radius; + } + else clip->r_xbot = expanded->r_xbot = area->r_xbot; + if (area->r_ybot > TiPlaneRect.r_ybot) + { + clip->r_ybot = area->r_ybot * CIFCurStyle->cs_scaleFactor; + expanded->r_ybot = area->r_ybot - CIFCurStyle->cs_radius; + } + else clip->r_ybot = expanded->r_ybot = area->r_ybot; + if (area->r_xtop < TiPlaneRect.r_xtop) + { + clip->r_xtop = area->r_xtop * CIFCurStyle->cs_scaleFactor; + expanded->r_xtop = area->r_xtop + CIFCurStyle->cs_radius; + } + else clip->r_xtop = expanded->r_xtop = area->r_xtop; + if (area->r_ytop < TiPlaneRect.r_ytop) + { + clip->r_ytop = area->r_ytop * CIFCurStyle->cs_scaleFactor; + expanded->r_ytop = area->r_ytop + CIFCurStyle->cs_radius; + } + else clip->r_ytop = expanded->r_ytop = area->r_ytop; +} + +/* + * ---------------------------------------------------------------------------- + * + * CIFClearPlanes -- + * + * This procedure clears out a collection of CIF planes. + * + * Results: + * None. + * + * Side effects: + * Each of the planes in "planes" is re-initialized to point to + * an empty paint plane. + * + * ---------------------------------------------------------------------------- + */ + +void +CIFClearPlanes(planes) + Plane **planes; /* Pointer to an array of MAXCIFLAYERS + * planes. + */ +{ + int i; + + for (i = 0; i < MAXCIFLAYERS; i++) + { + if (planes[i] == NULL) + { + planes[i] = DBNewPlane((ClientData) TT_SPACE); + } + else + { + DBClearPaintPlane(planes[i]); + } + } +} diff --git a/extflat/Depend b/extflat/Depend index f4e40584..23daa933 100644 --- a/extflat/Depend +++ b/extflat/Depend @@ -21,7 +21,7 @@ EFread.o: EFread.c ../tcltk/tclmagic.h ../utils/magic.h ../utils/malloc.h \ ../utils/geometry.h ../utils/hash.h ../utils/utils.h ../tiles/tile.h \ ../commands/commands.h ../windows/windows.h ../database/database.h \ ../extflat/extflat.h ../extflat/EFint.h ../extract/extract.h \ - ../utils/paths.h + ../extract/extractInt.h ../extract/extDebugInt.h ../utils/paths.h EFsym.o: EFsym.c ../utils/magic.h ../utils/geometry.h ../utils/geofast.h \ ../utils/hash.h ../utils/malloc.h ../utils/utils.h ../extflat/extflat.h \ ../extflat/EFint.h diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c index f3ab37b5..46932d43 100644 --- a/extflat/EFbuild.c +++ b/extflat/EFbuild.c @@ -63,6 +63,8 @@ void efNodeMerge(); bool efConnBuildName(); bool efConnInitSubs(); +extern float locScale; + /* * ---------------------------------------------------------------------------- @@ -177,10 +179,10 @@ efBuildNode(def, isSubsnode, nodeName, nodeCap, x, y, layerName, av, ac) newnode->efnode_flags = (isSubsnode == TRUE) ? EF_SUBS_NODE : 0; newnode->efnode_cap = nodeCap; newnode->efnode_attrs = (EFAttr *) NULL; - newnode->efnode_loc.r_xbot = x; - newnode->efnode_loc.r_ybot = y; - newnode->efnode_loc.r_xtop = x + 1; - newnode->efnode_loc.r_ytop = y + 1; + newnode->efnode_loc.r_xbot = (int)(0.5 + (float)x * locScale); + newnode->efnode_loc.r_ybot = (int)(0.5 + (float)y * locScale); + newnode->efnode_loc.r_xtop = newnode->efnode_loc.r_xbot + 1; + newnode->efnode_loc.r_ytop = newnode->efnode_loc.r_ybot + 1; newnode->efnode_client = (ClientData) NULL; if (layerName) newnode->efnode_type = efBuildAddStr(EFLayerNames, &EFLayerNumNames, MAXTYPES, layerName); @@ -686,7 +688,8 @@ efBuildDevice(def, class, type, r, argc, argv) { pn = *(argv[argstart] + 1) - '0'; if (pn == 0) - devtmp.dev_area = atoi(pptr); + devtmp.dev_area = (int)(0.5 + (float)atoi(pptr) + * locScale * locScale); /* Otherwise, punt */ } break; @@ -697,15 +700,15 @@ efBuildDevice(def, class, type, r, argc, argv) { pn = *(argv[argstart] + 1) - '0'; if (pn == 0) - devtmp.dev_perim = atoi(pptr); + devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale); /* Otherwise, use verbatim */ } break; case 'l': - devtmp.dev_length = atoi(pptr); + devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale); break; case 'w': - devtmp.dev_width = atoi(pptr); + devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale); break; case 'c': devtmp.dev_cap = (float)atof(pptr); @@ -1248,8 +1251,9 @@ efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac) conn->conn_next = def->def_conns; for (n = 0; n < efNumResistClasses && ac > 1; n++, ac -= 2) { - conn->conn_pa[n].pa_area = atoi(*av++); - conn->conn_pa[n].pa_perim = atoi(*av++); + conn->conn_pa[n].pa_area = (int)(0.5 + (float)atoi(*av++) + * locScale * locScale); + conn->conn_pa[n].pa_perim = (int)(0.5 + (float)atoi(*av++) * locScale); } for ( ; n < efNumResistClasses; n++) conn->conn_pa[n].pa_area = conn->conn_pa[n].pa_perim = 0; diff --git a/extflat/EFread.c b/extflat/EFread.c index c5901293..810940d6 100644 --- a/extflat/EFread.c +++ b/extflat/EFread.c @@ -38,6 +38,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "extflat/extflat.h" #include "extflat/EFint.h" #include "extract/extract.h" +#include "extract/extractInt.h" #include "utils/paths.h" #ifndef MAGIC_WRAPPER @@ -96,6 +97,7 @@ keyTable[] = /* Data shared with EFerror.c */ char *efReadFileName; /* Name of file currently being read */ int efReadLineNum; /* Current line number in above file */ +float locScale; /* Multiply values in the file by this on read-in */ /* Data local to this file */ static bool efReadDef(); @@ -139,6 +141,7 @@ EFReadFile(name, dosubckt, resist, noscale) if (def == NULL) def = efDefNew(name); + locScale = 1.0; rc = efReadDef(def, dosubckt, resist, noscale, TRUE); if (EFArgTech) EFTech = StrDup((char **) NULL, EFArgTech); if (EFScale == 0.0) EFScale = 1.0; @@ -265,6 +268,11 @@ readfile: cscale = 1; } lscale = (float)atof(argv[3]); + if (lscale != ExtCurStyle->exts_unitsPerLambda) + { + locScale = lscale / ExtCurStyle->exts_unitsPerLambda; + lscale = ExtCurStyle->exts_unitsPerLambda; + } if (lscale == 0.0) { efReadError("Bad linear scaling = 0; reset to 1.\n"); @@ -283,10 +291,10 @@ readfile: /* attr node xlo ylo xhi yhi type text */ case ATTR: - r.r_xbot = atoi(argv[2]); - r.r_ybot = atoi(argv[3]); - r.r_xtop = atoi(argv[4]); - r.r_ytop = atoi(argv[5]), + r.r_xbot = (int)(0.5 + (float)atoi(argv[2]) * locScale); + r.r_ybot = (int)(0.5 + (float)atoi(argv[3]) * locScale); + r.r_xtop = (int)(0.5 + (float)atoi(argv[4]) * locScale); + r.r_ytop = (int)(0.5 + (float)atoi(argv[5]) * locScale), efBuildAttr(def, argv[1], &r, argv[6], argv[7]); break; @@ -351,10 +359,10 @@ readfile: break; /* we will deal with in efBuildDevice(). */ } - r.r_xbot = atoi(argv[3]); - r.r_ybot = atoi(argv[4]); - r.r_xtop = atoi(argv[5]); - r.r_ytop = atoi(argv[6]); + r.r_xbot = (int)(0.5 + (float)atoi(argv[3]) * locScale); + r.r_ybot = (int)(0.5 + (float)atoi(argv[4]) * locScale); + r.r_xtop = (int)(0.5 + (float)atoi(argv[5]) * locScale); + r.r_ytop = (int)(0.5 + (float)atoi(argv[6]) * locScale); if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7, &argv[7]) != 0) { @@ -366,10 +374,10 @@ readfile: /* for backwards compatibility */ /* fet type xlo ylo xhi yhi area perim substrate GATE T1 T2 ... */ case FET: - r.r_xbot = atoi(argv[2]); - r.r_ybot = atoi(argv[3]); - r.r_xtop = atoi(argv[4]); - r.r_ytop = atoi(argv[5]); + r.r_xbot = (int)(0.5 + (float)atoi(argv[2]) * locScale); + r.r_ybot = (int)(0.5 + (float)atoi(argv[3]) * locScale); + r.r_xtop = (int)(0.5 + (float)atoi(argv[4]) * locScale); + r.r_ytop = (int)(0.5 + (float)atoi(argv[5]) * locScale); if (efBuildDevice(def, DEV_FET, argv[1], &r, argc - 6, &argv[6]) != 0) { efReadError("Incomplete terminal description for fet\n"); @@ -563,8 +571,8 @@ resistChanged: /* distance driver receiver min max */ case DIST: efBuildDist(def, argv[1], argv[2], - (int)(lscale*atoi(argv[3])), - (int)(lscale*atoi(argv[4]))); + (int)(lscale*atoi(argv[3])*locScale), + (int)(lscale*atoi(argv[4])*locScale)); break; /* killnode nodename */ diff --git a/resis/ResJunct.c b/resis/ResJunct.c index 7c8ccc0f..2c736df2 100644 --- a/resis/ResJunct.c +++ b/resis/ResJunct.c @@ -130,7 +130,6 @@ ResProcessJunction(tile, tp, xj, yj, NodeList) return; } #endif - if (j2->tj_status & RES_TILE_DONE) return; resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); resptr->rn_te = (tElement *) NULL; diff --git a/resis/ResPrint.c b/resis/ResPrint.c index d8839b91..f3996339 100644 --- a/resis/ResPrint.c +++ b/resis/ResPrint.c @@ -135,20 +135,40 @@ ResPrintExtDev(outextfile, devices) if (varsub != NULL) subsName = varsub; } #endif + /* Output according to device type and class. */ + /* Code largely matches what's in ExtBasic.c extOutputDevices() */ - /* Output according to device type */ + if (devptr->exts_deviceClass != DEV_FET) + fprintf(outextfile,"device "); - /* fet type xl yl xh yh area perim sub gate t1 t2 */ - fprintf(outextfile,"fet %s %d %d %d %d %d %d " - "%s \"%s\" %d %s \"%s\" %d %s \"%s\" %d %s\n", + fprintf(outextfile,"%s %s %d %d %d %d ", + extDevTable[devptr->exts_deviceClass], devptr->exts_deviceName, devices->layout->rd_inside.r_ll.p_x, devices->layout->rd_inside.r_ll.p_y, devices->layout->rd_inside.r_ll.p_x + 1, - devices->layout->rd_inside.r_ll.p_y + 1, - devices->layout->rd_area, - devices->layout->rd_perim, - subsName, + devices->layout->rd_inside.r_ll.p_y + 1); + + switch (devptr->exts_deviceClass) + { + case DEV_FET: + fprintf(outextfile," %d %d", + devices->layout->rd_area, + devices->layout->rd_perim); + break; + + case DEV_MOSFET: + case DEV_ASYMMETRIC: + case DEV_BJT: + fprintf(outextfile," %d %d", + devices->layout->rd_length, + devices->layout->rd_width); + break; + } + + fprintf(outextfile, " \"%s\"", subsName); + + fprintf(outextfile, " \"%s\" %d %s \"%s\" %d %s \"%s\" %d %s\n", devices->gate->name, devices->layout->rd_length * 2, devices->rs_gattr, @@ -190,7 +210,7 @@ ResPrintExtNode(outextfile, nodelist, nodename) ResSimNode *node,*ResInitializeNode(); bool DoKillNode = TRUE; resNode *snode = nodelist; - + /* If any of the subnode names match the original node name, then */ /* we don't want to rip out that node with a "killnode" statement. */ diff --git a/resis/ResReadSim.c b/resis/ResReadSim.c index 4a447aa8..c64caa88 100644 --- a/resis/ResReadSim.c +++ b/resis/ResReadSim.c @@ -229,12 +229,12 @@ ResReadNode(nodefile) char *cp; float lambda; - /* NOTE: Units from the .sim file or the .nodes file are in centimicrons - * when multiplied by resscale (units from the .sim file 1st line). - * multiply resscale by the extract scale (exts_unitsPerLambda) used to - * generate .ext dimensions originally, to get back to database units. + /* NOTE: Units from the .nodes file are in centimicrons. + * Divide by the extract scale (exts_unitsPerLambda) to get back + * to database units. This assumes that exts_unitsPerLambda doesn't + * change between output and readback. */ - lambda = resscale * (float)ExtCurStyle->exts_unitsPerLambda; + lambda = (float)ExtCurStyle->exts_unitsPerLambda; fp = PaOpen(nodefile,"r",".nodes",".", (char *) NULL, (char **) NULL); if (fp == NULL) @@ -358,11 +358,10 @@ ResSimDevice(line,rpersquare,ttype) } device->resistance = MagAtof(line[RDEV_LENGTH]) * rpersquare/MagAtof(line[RDEV_WIDTH]); } - device->tnumber = ++Maxtnumber; device->status = FALSE; device->nextDev = ResRDevList; - lambda = resscale * (float)ExtCurStyle->exts_unitsPerLambda; + lambda = (float)ExtCurStyle->exts_unitsPerLambda / resscale; device->location.p_x = (int)((float)atof(line[RDEV_DEVX]) / lambda); device->location.p_y = (int)((float)atof(line[RDEV_DEVY]) / lambda); diff --git a/resis/ResRex.c b/resis/ResRex.c index e98aa143..eb3a57ae 100644 --- a/resis/ResRex.c +++ b/resis/ResRex.c @@ -35,21 +35,19 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #define INITFLATSIZE 1024 #define MAXNAME 1000 - -/* time constants are produced by multiplying attofarads by milliohms, */ +/* Time constants are produced by multiplying attofarads by milliohms, */ /* giving zeptoseconds (yes, really. Look it up). This constant */ -/* converts zeptoseconts to nanoseconds. */ +/* converts zeptoseconds to nanoseconds. */ + #define Z_TO_N 1e12 /* ResSimNode is a node read in from a sim file */ - HashTable ResNodeTable; /* Hash table of sim file nodes */ RDev *ResRDevList; /* Linked list of Sim devices */ ResGlobalParams gparams; /* Junk passed between */ /* ResCheckSimNodes and */ /* ResExtractNet. */ -int Maxtnumber; /*maximum device number */ extern ResSimNode *ResOriginalNodes; /*Linked List of Nodes */ int resNodeNum; @@ -104,7 +102,6 @@ ExtResisForDef(celldef, resisdata) ResRDevList = NULL; ResOriginalNodes = NULL; - Maxtnumber = 0; HashInit(&ResNodeTable, INITFLATSIZE, HT_STRINGKEYS); /* read in .sim file */ result = (ResReadSim(celldef->cd_name, @@ -870,6 +867,19 @@ ResCheckSimNodes(celldef, resisdata) return; } + /* + * Write a scale line at the top of the .res.ext file, as the + * scale may be different from the original .ext file. + */ + + if (ResExtFile != NULL) + { + fprintf(ResExtFile, "scale %d %d %g\n", + ExtCurStyle->exts_resistScale, + ExtCurStyle->exts_capScale, + ExtCurStyle->exts_unitsPerLambda); + } + /* * Write reference plane (substrate) definition and end statement * to the FastHenry geometry file. diff --git a/resis/ResSimple.c b/resis/ResSimple.c index 31b3b3cb..f55b0845 100644 --- a/resis/ResSimple.c +++ b/resis/ResSimple.c @@ -954,26 +954,25 @@ ResDoSimplify(tolerance,rctol,goodies) { RCDelayStuff *rc = (RCDelayStuff *) ResNodeList->rn_client; - if (rc != (RCDelayStuff *)NULL) - { - goodies->rg_nodecap = totalcap; - ResCalculateTDi(ResOriginNode,(resResistor *)NULL, + goodies->rg_nodecap = totalcap; + ResCalculateTDi(ResOriginNode,(resResistor *)NULL, goodies->rg_bigdevres); - goodies->rg_Tdi = rc->rc_Tdi; - slownode = ResNodeList; - for (node = ResNodeList; node != NULL; node = node->rn_more) - { - rc = (RCDelayStuff *)node->rn_client; - if (rc && (goodies->rg_Tdi < rc->rc_Tdi)) - { - slownode = node; - goodies->rg_Tdi = rc->rc_Tdi; - } - } - slownode->rn_status |= RN_MAXTDI; - } + if (rc != (RCDelayStuff *)NULL) + goodies->rg_Tdi = rc->rc_Tdi; else - goodies->rg_Tdi = 0; + goodies->rg_Tdi = 0; + + slownode = ResNodeList; + for (node = ResNodeList; node != NULL; node = node->rn_more) + { + rc = (RCDelayStuff *)node->rn_client; + if (rc && (goodies->rg_Tdi < rc->rc_Tdi)) + { + slownode = node; + goodies->rg_Tdi = rc->rc_Tdi; + } + } + slownode->rn_status |= RN_MAXTDI; } else { diff --git a/resis/resis.h b/resis/resis.h index 74fdd5cd..5eb2e1f6 100644 --- a/resis/resis.h +++ b/resis/resis.h @@ -296,7 +296,6 @@ typedef struct rdev Point location; /* Location of lower left point of */ /* device. */ float resistance; /* "Resistance" of device. */ - int tnumber; /* Device number */ int rs_ttype; /* device type */ char *rs_gattr; /* Gate attributes, if any */ char *rs_sattr; @@ -572,7 +571,6 @@ extern RDev *ResRDevList; extern REcell *ResBigEventList; extern int ResOptionsFlags; extern char *ResCurrentNode; -extern int Maxtnumber; extern ResSimNode *ResOriginalNodes; #ifdef ARIEL extern int ResMinEventTime; From be38dac9fbc2e3dce9ab8da2fcb60b102226407f Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Sat, 14 Dec 2019 18:30:48 -0500 Subject: [PATCH 075/121] Corrected .mag file read-in so that it will not complain about a layout being redefined if one records the full path name and the other records the home directory tilde expression. --- database/DBio.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/database/DBio.c b/database/DBio.c index f27e8d18..a7690b8e 100644 --- a/database/DBio.c +++ b/database/DBio.c @@ -1440,9 +1440,22 @@ badTransform: slashptr = strrchr(subCellDef->cd_file, '/'); if (slashptr != NULL) { + bool pathOK = FALSE; *slashptr = '\0'; - if (strcmp(subCellDef->cd_file, pathptr)) + /* Avoid generating error message if pathptr starts with '~' */ + /* and the tilde-expanded name matches the subCellDef name */ + + if (*pathptr == '~') + { + char *homedir = getenv("HOME"); + if (!strncmp(subCellDef->cd_file, homedir, strlen(homedir)) + && (!strcmp(subCellDef->cd_file + strlen(homedir), + pathptr + 1))) + pathOK = TRUE; + } + + if ((pathOK == FALSE) && strcmp(subCellDef->cd_file, pathptr)) { TxError("Duplicate cell in %s: Instance of cell %s is from " "path %s but cell was previously read from %s.\n", From d0f3aaeb598d1c28075772e5434b46a2b08998a4 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 16 Dec 2019 09:55:11 -0500 Subject: [PATCH 076/121] Corrected ext2hier.c so that resistance output from extresist takes the right argument type (float, not int). Otherwise all resistances from extresist come out zero when doing "ext2spice extresist on" and "ext2spice hierarchy on". Also changed the format of the resistance in the SPICE output to type float, since values are in standard units of ohms, and rounding to the nearest ohm seems excessively coarse-grained. --- ext2spice/ext2hier.c | 8 +++----- extflat/EFread.c | 6 +++++- lef/lefWrite.c | 3 ++- resis/ResPrint.c | 4 ++-- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 6f6fc555..fc010154 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1159,13 +1159,11 @@ spcresistHierVisit(hc, hierName1, hierName2, res) HierContext *hc; HierName *hierName1; HierName *hierName2; - int res; + float res; { - res = (res + 500) / 1000; - - fprintf(esSpiceF, "R%d %s %s %d\n", esResNum++, + fprintf(esSpiceF, "R%d %s %s %g\n", esResNum++, nodeSpiceHierName(hc, hierName1), - nodeSpiceHierName(hc, hierName2), res); + nodeSpiceHierName(hc, hierName2), res / 1000.); return 0; } diff --git a/extflat/EFread.c b/extflat/EFread.c index 810940d6..5cc53d43 100644 --- a/extflat/EFread.c +++ b/extflat/EFread.c @@ -581,8 +581,12 @@ resistChanged: break; /* resistor node1 node2 resistance */ + /* NOTE: Value changed to floating-point 12/16/2019; */ + /* (value * rscale) is in milliohms which is integer as */ + /* resolution finer than milliohms is deemed unnecessary. */ case RESISTOR: - efBuildResistor(def, argv[1], argv[2], rscale*atoi(argv[3])); + efBuildResistor(def, argv[1], argv[2], + (int)(0.5 + (double)rscale * atof(argv[3]))); break; /* abstract (no options/arguments) */ diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 3adfc12a..8c3f7530 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -84,6 +84,7 @@ lefFileOpen(def, file, suffix, mode, prealfile) { char namebuf[512], *name, *endp, *ends; char *locsuffix; + char *pptr; int len; FILE *rfile; @@ -109,7 +110,7 @@ lefFileOpen(def, file, suffix, mode, prealfile) if (endp = strrchr(ends, '.')) { - if (!strcmp(endp, suffix)) + if (strcmp(endp, suffix)) { len = endp - name; if (len > sizeof namebuf - 1) len = sizeof namebuf - 1; diff --git a/resis/ResPrint.c b/resis/ResPrint.c index f3996339..49cc3db6 100644 --- a/resis/ResPrint.c +++ b/resis/ResPrint.c @@ -85,10 +85,10 @@ ResPrintExtRes(outextfile,resistors,nodename) } if (ResOptionsFlags & ResOpt_DoExtFile) { - fprintf(outextfile, "resist \"%s\" \"%s\" %d\n", + fprintf(outextfile, "resist \"%s\" \"%s\" %g\n", resistors->rr_connection1->rn_name, resistors->rr_connection2->rn_name, - (int) (resistors->rr_value/ExtCurStyle->exts_resistScale)); + resistors->rr_value / (float)ExtCurStyle->exts_resistScale); } } } From f15ea2a135622ffa13f666589ae131430d4eacbd Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 19 Dec 2019 10:33:22 -0500 Subject: [PATCH 077/121] Modified "lef writeall" to only generate output for the set of subcells that are direct children of the top level cell. The "-all" option was added to enable the previous behavior, although its usefulness is doubtful. --- calma/CalmaWrite.c | 2 +- lef/lefCmd.c | 12 ++++++++++-- lef/lefWrite.c | 18 ++++++++++++------ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/calma/CalmaWrite.c b/calma/CalmaWrite.c index 0480238f..a08899fa 100644 --- a/calma/CalmaWrite.c +++ b/calma/CalmaWrite.c @@ -1024,7 +1024,7 @@ calmaOutFunc(def, f, cliprect) ((lab->lab_flags & PORT_NUM_MASK) == i)) { calmaWriteLabelFunc(lab, type, f); - break; + /* break; */ /* Do not limit to unique labels! */ } } } diff --git a/lef/lefCmd.c b/lef/lefCmd.c index 546988db..0322467a 100644 --- a/lef/lefCmd.c +++ b/lef/lefCmd.c @@ -87,6 +87,11 @@ CmdLef(w, cmd) * the macro other than pin area * immediately surrounding labels. */ + bool recurse = FALSE; /* If TRUE, recurse on all subcells + * during "writeall". By default, + * only the immediate children of the + * top level cell are output. + */ static char *cmdLefOption[] = { @@ -95,7 +100,8 @@ CmdLef(w, cmd) "write [filename] [-tech] write LEF for current cell\n" " write [filename] -hide hide all details other than ports", "writeall write all cells including the top-level cell\n" - " writeall -notop write all subcells of the top-level cell", + " writeall -notop write all children of the top-level cell\n" + " writeall -all recurse on all subcells of the top-level cell", "help print this help information", NULL }; @@ -184,11 +190,13 @@ CmdLef(w, cmd) lefTopCell = FALSE; else if (!strncmp(cmd->tx_argv[i], "-tech", 5)) lefTech = TRUE; + else if (!strncmp(cmd->tx_argv[i], "-all", 4)) + recurse = TRUE; else goto wrongNumArgs; } else goto wrongNumArgs; } - LefWriteAll(selectedUse, lefTopCell, lefTech); + LefWriteAll(selectedUse, lefTopCell, lefTech, recurse); } break; case LEF_WRITE: diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 8c3f7530..2984a2fb 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -1133,10 +1133,11 @@ lefWriteMacro(def, f, scale, hide) */ void -LefWriteAll(rootUse, writeTopCell, lefTech) +LefWriteAll(rootUse, writeTopCell, lefTech, recurse) CellUse *rootUse; bool writeTopCell; bool lefTech; + bool recurse; { CellDef *def, *rootdef; FILE *f; @@ -1155,8 +1156,12 @@ LefWriteAll(rootUse, writeTopCell, lefTech) (void) DBCellSrDefs(0, lefDefInitFunc, (ClientData) 0); /* Recursively visit all defs in the tree and push on stack */ + /* If "recurse" is false, then only the children of the root use */ + /* are pushed (this is the default behavior). */ lefDefStack = StackNew(100); - (void) lefDefPushFunc(rootUse); + if (writeTopCell) + lefDefPushFunc(rootUse, (bool *)NULL); + DBCellEnum(rootUse->cu_def, lefDefPushFunc, (ClientData)&recurse); /* Open the file for output */ @@ -1185,8 +1190,7 @@ LefWriteAll(rootUse, writeTopCell, lefTech) { def->cd_client = (ClientData) 0; if (!SigInterruptPending) - if ((writeTopCell == TRUE) || (def != rootdef)) - lefWriteMacro(def, f, scale); + lefWriteMacro(def, f, scale); } /* End the LEF file */ @@ -1217,8 +1221,9 @@ lefDefInitFunc(def) */ int -lefDefPushFunc(use) +lefDefPushFunc(use, recurse) CellUse *use; + bool *recurse; { CellDef *def = use->cu_def; @@ -1227,7 +1232,8 @@ lefDefPushFunc(use) def->cd_client = (ClientData) 1; StackPush((ClientData) def, lefDefStack); - (void) DBCellEnum(def, lefDefPushFunc, (ClientData) 0); + if (recurse && (*recurse)) + (void) DBCellEnum(def, lefDefPushFunc, (ClientData)recurse); return (0); } From 67866c79912d91016cf5577189851299dd73d1ad Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 19 Dec 2019 17:28:06 -0500 Subject: [PATCH 078/121] Apparently GDS format does not enforce the original string character limit of the Calma definition, and probably has not done so for ages. Nobody informed me of this. The restriction has been lifted from GDS input and output in Magic. It can be reinstated if necessary by setting a flag in the cifoutput section of the techfile, but it is likely that this will not be necessary unless there are other tools that enforce the limit and will not read a GDS file that exceeds it. --- calma/CalmaRdcl.c | 10 ++++++++-- calma/CalmaWrite.c | 22 ++++++++++++++++------ cif/CIFint.h | 1 + cif/CIFtech.c | 2 ++ 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/calma/CalmaRdcl.c b/calma/CalmaRdcl.c index e69bb386..8ddb065f 100644 --- a/calma/CalmaRdcl.c +++ b/calma/CalmaRdcl.c @@ -282,7 +282,7 @@ calmaParseStructure(filename) { static int structs[] = { CALMA_STRCLASS, CALMA_STRTYPE, -1 }; int nbytes, rtype, nsrefs, osrefs, npaths; - char *strname = NULL, newname[CALMANAMELENGTH*2]; + char *strname = NULL; HashEntry *he; int suffix; int mfactor; @@ -327,15 +327,21 @@ calmaParseStructure(filename) } else { + char *newname; + CalmaReadError("Cell \"%s\" was already defined in this file.\n", strname); + newname = (char *)mallocMagic(strlen(strname) + 20); for (suffix = 1; HashGetValue(he) != NULL; suffix++) { (void) sprintf(newname, "%s_%d", strname, suffix); he = HashFind(&calmaDefInitHash, newname); } CalmaReadError("Giving this cell a new name: %s\n", newname); - strncpy(strname, newname, CALMANAMELENGTH*2); + freeMagic(strname); + strname = mallocMagic(strlen(newname) + 1); + strcpy(strname, newname); + freeMagic(newname); } } cifReadCellDef = calmaFindCell(strname, &was_called); diff --git a/calma/CalmaWrite.c b/calma/CalmaWrite.c index a08899fa..d3320376 100644 --- a/calma/CalmaWrite.c +++ b/calma/CalmaWrite.c @@ -372,7 +372,7 @@ calmaDumpStructure(def, outf, calmaDefHash, filename) char *filename; { int nbytes, rtype; - char *strname = NULL, *newnameptr, newname[CALMANAMELENGTH*2]; + char *strname = NULL, *newnameptr; HashEntry *he, *he2; CellDef *edef; char *prefix = NULL; @@ -1316,7 +1316,7 @@ calmaOutStructName(type, def, f) CellDef *def; FILE *f; { - char defname[CALMANAMELENGTH+1]; + char *defname; unsigned char c; char *cp; int calmanum; @@ -1341,10 +1341,11 @@ calmaOutStructName(type, def, f) } /* We really should ensure that the new name is unique. . . */ } - if (cp <= def->cd_name + CALMANAMELENGTH) + if ((!(CIFCurStyle->cs_flags & CWF_STRING_LIMIT)) || + (cp <= def->cd_name + CALMANAMELENGTH)) { /* Yes, it's legal: use it */ - (void) strcpy(defname, def->cd_name); + defname = StrDup(NULL, def->cd_name); } else { @@ -1352,12 +1353,14 @@ calmaOutStructName(type, def, f) bad: calmanum = (int) def->cd_client; if (calmanum < 0) calmanum = -calmanum; + defname = (char *)mallocMagic(32); (void) sprintf(defname, "XXXXX%d", calmanum); TxError("Warning: string in output unprintable; changed to \'%s\'\n", defname); } calmaOutStringRecord(type, defname, f); + freeMagic(defname); } /* Added by NP 8/21/2004 */ @@ -2734,7 +2737,7 @@ calmaOutDate(t, f) void calmaOutStringRecord(type, str, f) int type; /* Type of this record (data type is ASCII string) */ - char *str; /* String to be output (<= CALMANAMELENGTH chars) */ + char *str; /* String to be output */ FILE *f; /* Stream file */ { int len; @@ -2759,9 +2762,16 @@ calmaOutStringRecord(type, str, f) * last CALMANAMELENGTH characters (since cell names are more * likely to be unique in the last characters than in the first * characters). + * + * NOTE: GDS format has not used CALMANAMELENGTH restrictions + * for ages. Since this is a 2-byte record, then is it not + * worth checking the 65536 - 4 character limit. The CALMANAMELENGTH + * restriction must be enabled in the cifoutput flags. */ + + if (len & 01) len++; - if (len > CALMANAMELENGTH) + if ((CIFCurStyle->cs_flags & CWF_STRING_LIMIT) && (len > CALMANAMELENGTH)) { TxError("Warning: Cellname %s truncated ", str); TxError("to %s (GDS format limit)\n", str + len - CALMANAMELENGTH); diff --git a/cif/CIFint.h b/cif/CIFint.h index 79564a34..a3a59788 100644 --- a/cif/CIFint.h +++ b/cif/CIFint.h @@ -297,6 +297,7 @@ typedef struct cifstyle #define CWF_GROW_EUCLIDEAN 0x08 #define CWF_SEE_VENDOR 0x10 /* Override vendor GDS flag in cells */ #define CWF_NO_ERRORS 0x20 /* Do not generate error msgs and fdbk */ +#define CWF_STRING_LIMIT 0x40 /* Use older Calma format character limit */ /* procedures */ diff --git a/cif/CIFtech.c b/cif/CIFtech.c index 9639ea00..9f2f457b 100644 --- a/cif/CIFtech.c +++ b/cif/CIFtech.c @@ -994,6 +994,8 @@ CIFTechLine(sectionName, argc, argv) CIFCurStyle->cs_flags |= CWF_SEE_VENDOR; else if (strcmp(argv[i], "no-errors") == 0) CIFCurStyle->cs_flags |= CWF_NO_ERRORS; + else if (strcmp(argv[i], "string-limit") == 0) + CIFCurStyle->cs_flags |= CWF_STRING_LIMIT; } return TRUE; } From 82e33248f2e6bb6626d23d835b84dc74bd34ae7d Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 2 Jan 2020 10:13:04 -0500 Subject: [PATCH 079/121] Corrected dereferencing of cell dependencies, which was being applied only at the time of running the command "load". But cells are generally loaded only on an as-needed basis, so the dereferencing option must be saved as a flag in the cell and honored whenever its subcells are expanded or otherwise read at a later time. --- calma/CalmaWrite.c | 5 ++++- cif/CIFwrite.c | 3 ++- commands/CmdCD.c | 5 +++-- commands/CmdE.c | 6 +++++- commands/CmdSubrs.c | 4 +++- database/DBcellsrch.c | 46 ++++++++++++++++++++++++++++++++++--------- database/DBcellsubr.c | 6 +++++- database/DBexpand.c | 16 +++++++++++---- database/DBio.c | 7 +++++-- database/DBlabel2.c | 10 ++++++++-- database/DBtimestmp.c | 5 ++++- dbwind/DBWprocs.c | 2 ++ drc/DRCmain.c | 4 +++- extract/ExtInter.c | 16 ++++++++++++--- graphics/W3Dmain.c | 4 +++- lef/defRead.c | 5 ++++- sim/SimDBstuff.c | 5 ++++- utils/Depend | 4 +--- 18 files changed, 118 insertions(+), 35 deletions(-) diff --git a/calma/CalmaWrite.c b/calma/CalmaWrite.c index d3320376..a628730f 100644 --- a/calma/CalmaWrite.c +++ b/calma/CalmaWrite.c @@ -746,8 +746,11 @@ calmaProcessDef(def, outf) /* Read the cell in if it is not already available. */ if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return (0); + } /* * Output the definitions for any of our descendants that have diff --git a/cif/CIFwrite.c b/cif/CIFwrite.c index 147be067..a46a6ca1 100644 --- a/cif/CIFwrite.c +++ b/cif/CIFwrite.c @@ -312,7 +312,8 @@ cifOut(outf) /* Read the cell in if it is not already available. */ if ((def->cd_flags & CDAVAILABLE) == 0) { - if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, 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 diff --git a/commands/CmdCD.c b/commands/CmdCD.c index 712b0ae4..5babc7c2 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -3650,7 +3650,7 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx) { Point childPoint, editPoint, rootPoint; CellDef *def, *rootDef, *editDef; - bool hasChild, hasRoot, hasTrans; + bool hasChild, hasRoot, hasTrans, dereference; Rect rootBox, bbox; Transform *tx_cell, trans_cell; char **av; @@ -3750,7 +3750,8 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx) * looked for then no new error message will be printed. */ def->cd_flags &= ~CDNOTFOUND; - if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) + dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return (FALSE); DBReComputeBbox(def); dummy->cu_def = def; diff --git a/commands/CmdE.c b/commands/CmdE.c index 57883c25..80bb83cf 100644 --- a/commands/CmdE.c +++ b/commands/CmdE.c @@ -130,7 +130,11 @@ CmdEdit(w, cmd) return; } else if (!(EditCellUse->cu_def->cd_flags & CDAVAILABLE)) - DBCellRead(EditCellUse->cu_def, (char *)NULL, TRUE, FALSE, 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) { diff --git a/commands/CmdSubrs.c b/commands/CmdSubrs.c index ec63be1c..bf39fc96 100644 --- a/commands/CmdSubrs.c +++ b/commands/CmdSubrs.c @@ -288,6 +288,7 @@ cmdFlushCell(def) CellDef *def; { CellUse *parentUse; + bool dereference; /* Disallow flushing a cell that contains the edit cell as a child */ if (EditCellUse && (EditCellUse->cu_parent == def)) @@ -309,7 +310,8 @@ cmdFlushCell(def) } DBCellClearDef(def); DBCellClearAvail(def); - (void) DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL); + dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + (void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL); DBCellSetAvail(def); DBReComputeBbox(def); DBCellSetModified(def, FALSE); diff --git a/database/DBcellsrch.c b/database/DBcellsrch.c index e1dae80d..a960bf2e 100644 --- a/database/DBcellsrch.c +++ b/database/DBcellsrch.c @@ -188,7 +188,10 @@ dbCellTileSrFunc(scx, fp) if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return 0; + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } context.tc_scx = scx; context.tc_filter = fp; @@ -307,7 +310,10 @@ dbCellUniqueTileSrFunc(scx, fp) if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return 0; + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } context.tc_scx = scx; context.tc_filter = fp; @@ -418,7 +424,10 @@ DBNoTreeSrTiles(scx, mask, xMask, func, cdarg) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return 0; + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } filter.tf_func = func; filter.tf_arg = cdarg; @@ -526,7 +535,10 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg) ASSERT(def != (CellDef *) NULL, "DBTreeSrLabels"); if (!DBDescendSubcell(cellUse, xMask)) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, 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) { @@ -627,7 +639,10 @@ dbCellLabelSrFunc(scx, fp) ASSERT(def != (CellDef *) NULL, "dbCellLabelSrFunc"); if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, 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) { @@ -741,8 +756,11 @@ DBTreeSrCells(scx, xMask, func, cdarg) if (!DBDescendSubcell(cellUse, xMask)) return 0; if ((cellUse->cu_def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(cellUse->cu_def, (char *) NULL, TRUE, FALSE, NULL)) + { + bool dereference = (cellUse->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(cellUse->cu_def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } context.tc_scx = scx; context.tc_filter = &filter; @@ -787,8 +805,11 @@ dbTreeCellSrFunc(scx, fp) else { if ((use->cu_def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, FALSE, NULL)) + { + bool dereference = (use->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } result = DBCellSrArea(scx, dbTreeCellSrFunc, (ClientData) fp); } return result; @@ -1039,8 +1060,12 @@ DBCellSrArea(scx, func, cdarg) context.tc_scx = scx; if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, FALSE, 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; + } /* In order to make this work with zero-size areas, we first expand * the area by before searching the tile plane. DbCellSrFunc will @@ -1215,7 +1240,10 @@ DBCellEnum(cellDef, func, cdarg) filter.tf_func = func; filter.tf_arg = cdarg; if ((cellDef->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(cellDef, (char *) NULL, TRUE, FALSE, NULL)) return 0; + { + bool dereference = (cellDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(cellDef, (char *) NULL, TRUE, dereference, NULL)) return 0; + } if (TiSrArea((Tile *) NULL, cellDef->cd_planes[PL_CELL], &TiPlaneRect, dbEnumFunc, (ClientData) &filter)) return 1; diff --git a/database/DBcellsubr.c b/database/DBcellsubr.c index 9eaabcac..72d9bd1a 100644 --- a/database/DBcellsubr.c +++ b/database/DBcellsubr.c @@ -73,8 +73,12 @@ DBDescendSubcell(use, xMask) case CU_DESCEND_NO_SUBCKT: if ((use->cu_def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, FALSE, NULL)) + { + bool dereference = (use->cu_def->cd_flags & CDDEREFERENCE) ? + TRUE : FALSE; + if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, dereference, NULL)) return FALSE; + } return (DBIsSubcircuit(use->cu_def)) ? FALSE : TRUE; case CU_DESCEND_NO_LOCK: diff --git a/database/DBexpand.c b/database/DBexpand.c index db0548f6..11793447 100644 --- a/database/DBexpand.c +++ b/database/DBexpand.c @@ -37,6 +37,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ */ struct expandArg { + bool ea_deref; /* TRUE if root def dereference flag is set */ int ea_xmask; /* Expand mask. */ int (*ea_func)(); /* Function to call for each cell whose * status is changed. @@ -81,7 +82,8 @@ DBExpand(cellUse, expandMask, expandFlag) def = cellUse->cu_def; if ((def->cd_flags & CDAVAILABLE) == 0) { - if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return; /* Note: we don't have to recompute the bbox here, because * if it changed, then a timestamp violation must have occurred @@ -142,9 +144,13 @@ DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg) int dbExpandFunc(), dbUnexpandFunc(); SearchContext scontext; struct expandArg arg; + bool dereference = (rootUse->cu_def->cd_flags & CDDEREFERENCE) ? + TRUE : FALSE; if ((rootUse->cu_def->cd_flags & CDAVAILABLE) == 0) - (void) DBCellRead(rootUse->cu_def, (char *) NULL, TRUE, FALSE, NULL); + { + (void) DBCellRead(rootUse->cu_def, (char *) NULL, TRUE, dereference, NULL); + } /* * Walk through the area and set the expansion state @@ -154,6 +160,7 @@ DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg) arg.ea_xmask = expandMask; arg.ea_func = func; arg.ea_arg = cdarg; + arg.ea_deref = dereference; scontext.scx_use = rootUse; scontext.scx_trans = GeoIdentityTransform; @@ -193,7 +200,7 @@ dbExpandFunc(scx, arg) /* If the cell is unavailable, then don't expand it. */ if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0) - if(!DBCellRead(childUse->cu_def, (char *) NULL, TRUE, FALSE, NULL)) + if(!DBCellRead(childUse->cu_def, (char *) NULL, TRUE, arg->ea_deref, NULL)) { TxError("Cell %s is unavailable. It could not be expanded.\n", childUse->cu_def->cd_name); @@ -303,7 +310,8 @@ dbReadAreaFunc(scx) if ((def->cd_flags & CDAVAILABLE) == 0) { - (void) DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL); + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + (void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL); /* Note: we don't have to invoke DBReComputeBbox here because * if the bbox changed then there was a timestamp mismatch and * the timestamp code will take care of the bounding box later. diff --git a/database/DBio.c b/database/DBio.c index a7690b8e..fbc76738 100644 --- a/database/DBio.c +++ b/database/DBio.c @@ -934,7 +934,7 @@ DBCellRead(cellDef, name, ignoreTech, dereference, errptr) * names do not match, but an attempt will be * made to read the file anyway. */ - bool dereference; /* If TRUE, ignore path references in the input */ + bool dereference; /* If TRUE then ignore path argument to uses */ int *errptr; /* Copy of errno set by file reading routine * is placed here, unless NULL. */ @@ -2855,8 +2855,11 @@ DBCellWrite(cellDef, fileName) #ifdef FILE_LOCKS else + { + bool dereference = (cellDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; /* Re-aquire the lock on the new file by opening it. */ - DBCellRead(cellDef, NULL, TRUE, FALSE, NULL); + DBCellRead(cellDef, NULL, TRUE, dereference, NULL); + } #endif } diff --git a/database/DBlabel2.c b/database/DBlabel2.c index 8fda3f99..444c6e92 100644 --- a/database/DBlabel2.c +++ b/database/DBlabel2.c @@ -294,7 +294,10 @@ DBTreeFindUse(name, use, scx) * is read in from disk. */ if ((def->cd_flags & CDAVAILABLE) == 0) - (void) DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL); + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + (void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL); + } cp = name; he = HashLookOnly(&def->cd_idHash, name); @@ -343,7 +346,10 @@ DBTreeFindUse(name, use, scx) /* Ensure that the leaf cell is read in */ def = use->cu_def; if ((def->cd_flags & CDAVAILABLE) == 0) - (void) DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL); + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + (void) DBCellRead(def, (char *) NULL, dereference, NULL); + } scx->scx_use = use; } diff --git a/database/DBtimestmp.c b/database/DBtimestmp.c index 516135c1..e1223b10 100644 --- a/database/DBtimestmp.c +++ b/database/DBtimestmp.c @@ -126,6 +126,8 @@ DBFixMismatch() while (mismatch != NULL) { + bool dereference; + /* Be careful to remove the front element from the mismatch * list before processing it, because while processing it we * may add new elements to the list. @@ -137,7 +139,8 @@ DBFixMismatch() mismatch = mismatch->mm_next; if (cellDef->cd_flags & CDPROCESSED) continue; - (void) DBCellRead(cellDef, (char *) NULL, TRUE, FALSE, NULL); + dereference = (cellDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + (void) DBCellRead(cellDef, (char *) NULL, TRUE, dereference, NULL); /* Jimmy up the cell's current bounding box, so the following * procedure call will absolutely and positively know that diff --git a/dbwind/DBWprocs.c b/dbwind/DBWprocs.c index 56578625..95458ec0 100644 --- a/dbwind/DBWprocs.c +++ b/dbwind/DBWprocs.c @@ -385,6 +385,8 @@ DBWloadWindow(window, name, ignoreTech, expand, dereference) if (newEditDef == (CellDef *) NULL) newEditDef = DBCellNewDef(rootname, (char *) NULL); + if (dereference) newEditDef->cd_flags |= CDDEREFERENCE; + if (!DBCellRead(newEditDef, name, ignoreTech, dereference, &error_val)) { if (error_val == ENOENT) diff --git a/drc/DRCmain.c b/drc/DRCmain.c index 29ab5e8f..72d9c456 100644 --- a/drc/DRCmain.c +++ b/drc/DRCmain.c @@ -894,13 +894,15 @@ drcFindFunc(scx, finddata) CellDef *def; HashEntry *h; int drcFindFunc2(); + bool dereference; def = scx->scx_use->cu_def; h = HashFind(finddata->deft, (char *)def); if (HashGetValue(h) != 0) return 0; HashSetValue(h, 1); - (void) DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL); + dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + (void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL); if (DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR], &def->cd_bbox, &DBAllButSpaceBits, drcFindFunc2, diff --git a/extract/ExtInter.c b/extract/ExtInter.c index 604e54f3..2e148482 100644 --- a/extract/ExtInter.c +++ b/extract/ExtInter.c @@ -424,7 +424,10 @@ extTreeSrPaintArea(scx, func, cdarg) int pNum; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return 0; + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } filter.tf_func = func; filter.tf_arg = cdarg; @@ -461,7 +464,10 @@ extTreeSrFunc(scx, fp) int pNum; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return (0); + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return (0); + } context.tc_scx = scx; context.tc_filter = fp; @@ -548,8 +554,12 @@ extCellSrArea(scx, func, cdarg) filter.tf_arg = cdarg; if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, FALSE, 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; + } /* * In order to make this work with zero-size areas, we first expand diff --git a/graphics/W3Dmain.c b/graphics/W3Dmain.c index 90a4e205..1198c375 100644 --- a/graphics/W3Dmain.c +++ b/graphics/W3Dmain.c @@ -1389,12 +1389,14 @@ W3DloadWindow(window, name) CellDef *newEditDef; CellUse *newEditUse; Rect loadBox; + bool dereference; newEditDef = DBCellLookDef(name); if (newEditDef == (CellDef *)NULL) return FALSE; - if (!DBCellRead(newEditDef, (char *)NULL, TRUE, FALSE, NULL)) + dereference = (newEditDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(newEditDef, (char *)NULL, TRUE, dereference, NULL)) return FALSE; DBReComputeBbox(newEditDef); diff --git a/lef/defRead.c b/lef/defRead.c index f890b3ca..70446ab4 100644 --- a/lef/defRead.c +++ b/lef/defRead.c @@ -1487,11 +1487,14 @@ DefReadComponents(f, rootDef, sname, oscale, total) if (defMacro == (CellDef *)NULL) { + bool dereference; + /* Before giving up, assume that this cell has a */ /* magic .mag layout file. */ defMacro = DBCellNewDef(token, (char *)NULL); defMacro->cd_flags &= ~CDNOTFOUND; - if (!DBCellRead(defMacro, (char *)NULL, TRUE, FALSE, NULL)) + dereference = (defMacro->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(defMacro, (char *)NULL, TRUE, dereference, NULL)) { LefError(DEF_ERROR, "Cell %s is not defined. Maybe you " "have not read the corresponding LEF file?\n", diff --git a/sim/SimDBstuff.c b/sim/SimDBstuff.c index 05a89a4c..2fd68956 100644 --- a/sim/SimDBstuff.c +++ b/sim/SimDBstuff.c @@ -789,7 +789,10 @@ SimCellTileSrFunc(scx, fp) if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, FALSE, NULL)) return 0; + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } context.tc_scx = scx; context.tc_filter = fp; diff --git a/utils/Depend b/utils/Depend index 4f469cb1..56e88bb4 100644 --- a/utils/Depend +++ b/utils/Depend @@ -2,9 +2,7 @@ args.o: args.c ../utils/magic.h ../utils/utils.h child.o: child.c ../utils/utils.h ../utils/magic.h ../utils/malloc.h dqueue.o: dqueue.c ../utils/magic.h ../utils/dqueue.h ../utils/malloc.h finddisp.o: finddisp.c ../utils/magic.h ../utils/utils.h -flock.o: flock.c ../utils/magic.h ../utils/hash.h ../utils/geometry.h \ - ../tiles/tile.h ../database/database.h ../windows/windows.h \ - ../utils/malloc.h +flock.o: flock.c flsbuf.o: flsbuf.c fraction.o: fraction.c ../utils/magic.h ../utils/geometry.h geometry.o: geometry.c ../utils/magic.h ../utils/geometry.h \ From ff2f2de04699be55bcd00ea7811c917d2e88a86d Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 3 Jan 2020 12:21:39 -0500 Subject: [PATCH 080/121] Corrected the dereferencing code from the last commit, where the flag definition had been put in database.h instead of database.h.in, and so was deleted on "make clean". Also, corrected a problem that causes the cif output style to be lost when running DRC-CIF checks if the first output style is the DRC style. --- database/database.h.in | 4 ++++ drc/DRCcif.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/database/database.h.in b/database/database.h.in index 5b9bd777..d3aec04a 100644 --- a/database/database.h.in +++ b/database/database.h.in @@ -391,6 +391,9 @@ typedef struct celldef * with the option "gds readonly true". * CDVISITED indicates that at least one instance of the cell was * already output during a file write. + * CDDEREFERENCE is a flag indicating that when loading or expanding + * children of a cell, the path should be ignored and the cell + * path should be searched for the location. */ #define CDAVAILABLE 0x0001 @@ -408,6 +411,7 @@ typedef struct celldef #define CDPROCESSEDGDS 0x1000 #define CDVENDORGDS 0x2000 #define CDVISITED 0x4000 +#define CDDEREFERENCE 0x8000 /* * Description of an array. diff --git a/drc/DRCcif.c b/drc/DRCcif.c index 3a4a4bbd..477ae23f 100644 --- a/drc/DRCcif.c +++ b/drc/DRCcif.c @@ -527,7 +527,8 @@ drcCifCheck(arg) } if (drcCifValid == FALSE) { - CIFCurStyle = CIFSaveStyle; + if (CIFSaveStyle != NULL) + CIFCurStyle = CIFSaveStyle; return; } From 8e6f770afa79adabff395c8b1c736ff08f5c9b3d Mon Sep 17 00:00:00 2001 From: Alex Coffin Date: Mon, 13 Jan 2020 05:29:20 -0800 Subject: [PATCH 081/121] Fixed typo --- doc/html/macro.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/html/macro.html b/doc/html/macro.html index ea790a3d..e12e96e0 100644 --- a/doc/html/macro.html +++ b/doc/html/macro.html @@ -68,7 +68,7 @@ Define or print a macro called char Buttons are treated just like keys for the purpose of defining macros. While the official names for buttons - in keysymdef.h are "XK_Pointer_Button_1", + in keysymdef.h are "XK_Pointer_Button1", etc., the macro command accepts the abbreviated forms Button1, and so forth.

From afe38c55c816373413fa5171375cbed8c28d6729 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 13 Jan 2020 12:58:04 -0500 Subject: [PATCH 082/121] Resolved some issues with working with ext2spice using abstract views. Because the abstract view does not necessarily represent actual connectivity, rely on the port indexes in the .ext file to determine the number of ports and port order. Do not use SpiceNodeName() to look up the node name, or unique ports that are deemed shorted will go missing. Also: Modified the read-in of .ext files so that use names may contain backslashes. Only backslashes that end a line will be handled differently. --- ext2spice/ext2spice.c | 23 +++++++++++++++++++---- extflat/EFread.c | 14 +++++++++----- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 65eb7326..b51215ce 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -1501,9 +1501,7 @@ subcktVisit(use, hierName, is_top) { nodeName = nodeList[portidx]; - if (nodeName == NULL) - TxError("No port connection on port %d; need to resolve.\n", portidx); - else + if (nodeName != NULL) { if (tchars > 80) { @@ -1513,6 +1511,12 @@ subcktVisit(use, hierName, is_top) 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); @@ -1717,6 +1721,7 @@ topVisit(def, doStub) HashStartSearch(&hs); while (he = HashNext(&def->def_nodes, &hs)) { + char stmp[MAX_STR_SIZE]; int portidx; EFNodeName *unnumbered; @@ -1737,7 +1742,17 @@ topVisit(def, doStub) fprintf(esSpiceF, "\n+"); tchars = 1; } - pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL); + // If view is abstract, rely on the given port name, not + // the node. Otherwise, artifacts of the abstract view + // may cause nodes to be merged and the names lost. + + if (def->def_flags & DEF_ABSTRACT) + { + EFHNSprintf(stmp, nodeName->efnn_hier); + pname = stmp; + } + else + pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL); fprintf(esSpiceF, " %s", pname); tchars += strlen(pname) + 1; break; diff --git a/extflat/EFread.c b/extflat/EFread.c index 5cc53d43..96158edb 100644 --- a/extflat/EFread.c +++ b/extflat/EFread.c @@ -728,11 +728,15 @@ start: } } - if (*get == '\\') /* Process quoted characters literally */ - { - get++; - if (*get == '\0') break; - } + /* Process backslash characters literally unless they */ + /* are followed by the end-of-line. */ + + if (*get == '\\') + if (*(get + 1) == '\0') + { + get++; + break; + } /* Copy into token receiving area */ *put++ = *get++; From fc4638634a2afb413732c874efd862d6ba6be5fa Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 17 Jan 2020 12:54:58 -0500 Subject: [PATCH 083/121] Corrected the ifdef MAGIC_WRAPPER placement in the EFantenna.c file, which should have been only around the tclmagic.h include. --- extflat/EFantenna.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extflat/EFantenna.c b/extflat/EFantenna.c index 661fde43..e7af529a 100644 --- a/extflat/EFantenna.c +++ b/extflat/EFantenna.c @@ -16,20 +16,20 @@ #include #include /* 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" -#ifdef MAGIC_WRAPPER #include "database/database.h" #include "windows/windows.h" #include "textio/textio.h" #include "dbwind/dbwind.h" #include "textio/txcommands.h" -#endif #include "extflat/extflat.h" #include "extract/extract.h" #include "extract/extractInt.h" From 61859d152d019a9b36841f79cd7becd86d8ebcb4 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Sat, 18 Jan 2020 15:55:05 -0500 Subject: [PATCH 084/121] Corrected a missing argument from the call to DBFlagMismatches() that causes the recovery option (magic -r) to fail with a segfault (which is definitely not helpful for recovering lost work). --- database/DBio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/DBio.c b/database/DBio.c index fbc76738..9043c47f 100644 --- a/database/DBio.c +++ b/database/DBio.c @@ -874,7 +874,7 @@ DBReadBackup(name) return FALSE; } /* Update timestamp flags from dbCellReadDef() */ - DBFlagMismatches(); + DBFlagMismatches(cellDef); } else { From 20a661e1ec542c33051d34b47bc4052bcff32915 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 24 Jan 2020 17:13:59 -0500 Subject: [PATCH 085/121] Corrected problem in "extresist" if a port is a label with the sticky flag set, and the type of the label does not correspond exactly to the type under the label (e.g., label defined on m1 but is on top of a contact). --- resis/ResMain.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/resis/ResMain.c b/resis/ResMain.c index e25a8e88..18c03850 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -648,7 +648,12 @@ ResExtractNet(startlist,goodies,cellname) scx.scx_area.r_ur.p_x = fix->fp_loc.p_x+2; scx.scx_area.r_ur.p_y = fix->fp_loc.p_y+2; startpoint = fix->fp_loc; - TTMaskSetOnlyType(&FirstTileMask,fix->fp_ttype); + + // Because fix->fp_ttype might come from a label with a sticky type + // that does not correspond exactly to the layer underneath, include + // all connecting types. + /* TTMaskSetOnlyType(&FirstTileMask,fix->fp_ttype); */ + TTMaskSetMask(&FirstTileMask, &DBConnectTbl[fix->fp_ttype]); newdevtiles = DBTreeCopyConnectDCS(&scx, &FirstTileMask, 0, ResCopyMask, &TiPlaneRect, ResUse); @@ -829,8 +834,31 @@ FindStartTile(goodies, SourcePoint) int pnum, t1, t2; ExtDevice *devptr; + /* If the drive point is on a contact, check for the contact residues */ + /* first, then the contact type itself. */ + + if (DBIsContact(goodies->rg_ttype)) + { + TileTypeBitMask *rmask = DBResidueMask(goodies->rg_ttype); + TileType savtype = goodies->rg_ttype; + TileType rtype; + + savtype = goodies->rg_ttype; + for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++) + if (TTMaskHasType(rmask, rtype)) + { + if ((tile = FindStartTile(goodies, SourcePoint)) != NULL) + { + goodies->rg_ttype = savtype; + return tile; + } + } + goodies->rg_ttype = savtype; + } + workingPoint.p_x = goodies->rg_devloc->p_x; workingPoint.p_y = goodies->rg_devloc->p_y; + pnum = DBPlane(goodies->rg_ttype); /* for drivepoints, we don't have to find a device */ @@ -840,6 +868,7 @@ FindStartTile(goodies, SourcePoint) GOTOPOINT(tile, &workingPoint); SourcePoint->p_x = workingPoint.p_x; SourcePoint->p_y = workingPoint.p_y; + if (TiGetTypeExact(tile) == goodies->rg_ttype) return tile; else From bc00b5578ba2b4a33e10fb04c2ba6a5597ad9395 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 28 Jan 2020 10:40:01 -0500 Subject: [PATCH 086/121] Implemented a new configuration variable "dist_prefix" for distributed installations, where the immediate installation location is different from the final installation location, but in the case where it is not desirable to put the entire install hierarchy as a subdirectory of DESTDIR. --- ext2sim/Makefile | 10 ++++----- ext2spice/Makefile | 16 +++++++------- graphics/Makefile | 16 +++++++------- lef/Makefile | 8 +++---- lisp/Makefile | 4 ++-- magic/Makefile | 40 +++++++++++++++++------------------ net2ir/Makefile | 2 +- plot/Makefile | 8 +++---- scmos/Makefile | 8 +++---- scripts/configure | 22 +++++++++++++++++++ scripts/configure.in | 15 +++++++++++++ scripts/defs.mak.in | 8 +++++++ tcltk/Makefile | 50 ++++++++++++++++++++++---------------------- utils/Depend | 4 +++- windows/Makefile | 12 +++++------ 15 files changed, 135 insertions(+), 88 deletions(-) diff --git a/ext2sim/Makefile b/ext2sim/Makefile index ff4a218c..f7730f87 100644 --- a/ext2sim/Makefile +++ b/ext2sim/Makefile @@ -26,12 +26,12 @@ exttosim${SHDLIB_EXT}: simwrap.o ${MAGICDIR}/extflat/libextflat.o ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} simwrap.o \ ${MAGICDIR}/extflat/libextflat.o ${LD_SHARED} -lc ${LIBS} -install: $(DESTDIR)${BINDIR}/${MODULE}${EXEEXT} +install: $(DESTDIR)${INSTALL_BINDIR}/${MODULE}${EXEEXT} -install-tcl: $(DESTDIR)${TCLDIR}/exttosim${SHDLIB_EXT} +install-tcl: $(DESTDIR)${INSTALL_TCLDIR}/exttosim${SHDLIB_EXT} -$(DESTDIR)${TCLDIR}/exttosim${SHDLIB_EXT}: exttosim${SHDLIB_EXT} - ${RM} $(DESTDIR)${TCLDIR}/exttosim${SHDLIB_EXT} - ${CP} exttosim${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/exttosim${SHDLIB_EXT} +$(DESTDIR)${INSTALL_TCLDIR}/exttosim${SHDLIB_EXT}: exttosim${SHDLIB_EXT} + ${RM} $(DESTDIR)${INSTALL_TCLDIR}/exttosim${SHDLIB_EXT} + ${CP} exttosim${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/exttosim${SHDLIB_EXT} include ${MAGICDIR}/rules.mak diff --git a/ext2spice/Makefile b/ext2spice/Makefile index 3a7b7e96..1a53cc67 100644 --- a/ext2spice/Makefile +++ b/ext2spice/Makefile @@ -29,16 +29,16 @@ exttospice${SHDLIB_EXT}: spicewrap.o spicehier.o ${MAGICDIR}/extflat/libextflat. ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} spicewrap.o spicehier.o \ ${MAGICDIR}/extflat/libextflat.o ${LD_SHARED} -lc ${LIBS} -install: $(DESTDIR)${BINDIR}/${MODULE}${EXEEXT} $(DESTDIR)${BINDIR}/spice2sim +install: $(DESTDIR)${INSTALL_BINDIR}/${MODULE}${EXEEXT} $(DESTDIR)${INSTALL_BINDIR}/spice2sim -install-tcl: $(DESTDIR)${TCLDIR}/exttospice${SHDLIB_EXT} $(DESTDIR)${BINDIR}/spice2sim +install-tcl: $(DESTDIR)${INSTALL_TCLDIR}/exttospice${SHDLIB_EXT} $(DESTDIR)${INSTALL_BINDIR}/spice2sim -$(DESTDIR)${TCLDIR}/exttospice${SHDLIB_EXT}: exttospice${SHDLIB_EXT} - ${RM} $(DESTDIR)${TCLDIR}/exttospice${SHDLIB_EXT} - ${CP} exttospice${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/exttospice${SHDLIB_EXT} +$(DESTDIR)${INSTALL_TCLDIR}/exttospice${SHDLIB_EXT}: exttospice${SHDLIB_EXT} + ${RM} $(DESTDIR)${INSTALL_TCLDIR}/exttospice${SHDLIB_EXT} + ${CP} exttospice${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/exttospice${SHDLIB_EXT} -$(DESTDIR)${BINDIR}/spice2sim: spice2sim - ${RM} $(DESTDIR)${BINDIR}/spice2sim - ${CP} spice2sim $(DESTDIR)${BINDIR}/spice2sim +$(DESTDIR)${INSTALL_BINDIR}/spice2sim: spice2sim + ${RM} $(DESTDIR)${INSTALL_BINDIR}/spice2sim + ${CP} spice2sim $(DESTDIR)${INSTALL_BINDIR}/spice2sim include ${MAGICDIR}/rules.mak diff --git a/graphics/Makefile b/graphics/Makefile index 7eb312ec..f22c3dfa 100644 --- a/graphics/Makefile +++ b/graphics/Makefile @@ -40,22 +40,22 @@ ${GR_HELPER_PROG}: ${GR_HELPER_SRCS} ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ${GR_HELPER_SRCS} \ -o ${GR_HELPER_PROG} ${LIBS} -install: $(DESTDIR)${BINDIR}/${GR_HELPER_PROG} glyphs fonts +install: $(DESTDIR)${INSTALL_BINDIR}/${GR_HELPER_PROG} glyphs fonts install-tcl: glyphs fonts -$(DESTDIR)${BINDIR}/${GR_HELPER_PROG}: ${GR_HELPER_PROG} - ${RM} $(DESTDIR)${BINDIR}/${GR_HELPER_PROG} - ${CP} ${GR_HELPER_PROG} $(DESTDIR)${BINDIR} +$(DESTDIR)${INSTALL_BINDIR}/${GR_HELPER_PROG}: ${GR_HELPER_PROG} + ${RM} $(DESTDIR)${INSTALL_BINDIR}/${GR_HELPER_PROG} + ${CP} ${GR_HELPER_PROG} $(DESTDIR)${INSTALL_BINDIR} glyphs: ${GLYPHS} for i in ${GLYPHS}; do \ - ${RM} $(DESTDIR)${SYSDIR}/$$i; \ - ${CP} $$i $(DESTDIR)${SYSDIR}; done + ${RM} $(DESTDIR)${INSTALL_SYSDIR}/$$i; \ + ${CP} $$i $(DESTDIR)${INSTALL_SYSDIR}; done fonts: ${OUTLINE_FONTS} for i in ${OUTLINE_FONTS}; do \ - ${RM} $(DESTDIR)${SYSDIR}/$$i; \ - ${CP} $$i $(DESTDIR)${SYSDIR}; done + ${RM} $(DESTDIR)${INSTALL_SYSDIR}/$$i; \ + ${CP} $$i $(DESTDIR)${INSTALL_SYSDIR}; done include ${MAGICDIR}/rules.mak diff --git a/lef/Makefile b/lef/Makefile index 8fb6bd22..a4b380ca 100644 --- a/lef/Makefile +++ b/lef/Makefile @@ -22,10 +22,10 @@ magiclef${SHDLIB_EXT}: tcllef.o ${OBJS} ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} tcllef.o ${OBJS} \ ${EXTRA_LIBS} -lc ${LIBS} -install-tcl: $(DESTDIR)${TCLDIR}/magiclef${SHDLIB_EXT} +install-tcl: $(DESTDIR)${INSTALL_TCLDIR}/magiclef${SHDLIB_EXT} -$(DESTDIR)${TCLDIR}/magiclef${SHDLIB_EXT}: magiclef${SHDLIB_EXT} - ${RM} $(DESTDIR)${TCLDIR}/magiclef${SHDLIB_EXT} - ${CP} magiclef${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/magiclef${SHDLIB_EXT} +$(DESTDIR)${INSTALL_TCLDIR}/magiclef${SHDLIB_EXT}: magiclef${SHDLIB_EXT} + ${RM} $(DESTDIR)${INSTALL_TCLDIR}/magiclef${SHDLIB_EXT} + ${CP} magiclef${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/magiclef${SHDLIB_EXT} include ${MAGICDIR}/rules.mak diff --git a/lisp/Makefile b/lisp/Makefile index e9a0f1d3..0ccb36a6 100644 --- a/lisp/Makefile +++ b/lisp/Makefile @@ -13,11 +13,11 @@ SCMSRC = default.scm box.scm label.scm draw.scm drc.scm \ include ${MAGICDIR}/defs.mak -INST_SCMSRC = ${SCMSRC:%=$(DESTDIR)${SCMDIR}/%} +INST_SCMSRC = ${SCMSRC:%=$(DESTDIR)${INSTALL_SCMDIR}/%} install: ${INST_SCMSRC} $(DESTDIR)${SCMDIR}/%: scm/% - ${CP} scm/$* $(DESTDIR)$(SCMDIR)/$* + ${CP} scm/$* $(DESTDIR)$(INSTALL_SCMDIR)/$* include ${MAGICDIR}/rules.mak diff --git a/magic/Makefile b/magic/Makefile index fb695b95..2079bca5 100644 --- a/magic/Makefile +++ b/magic/Makefile @@ -20,7 +20,7 @@ EXTRA_LIBS = ${MAGICDIR}/cmwind/libcmwind.o ${MAGICDIR}/commands/libcommands.o \ ${MAIN_EXTRA_LIBS} BITMAPS = up.xbm down.xbm left.xbm right.xbm zoom.xbm lock.xbm -DEST_XBM = $(BITMAPS:%=$(DESTDIR)${TCLDIR}/bitmaps/%) +DEST_XBM = $(BITMAPS:%=$(DESTDIR)${INSTALL_TCLDIR}/bitmaps/%) DFLAGS += -DMAGIC_DATE="\"`date`\"" -DCAD_DIR="${LIBDIR}" LIBS += ${GR_LIBS} ${READLINE_LIBS} -lm ${LD_EXTRA_LIBS} \ @@ -41,30 +41,30 @@ tclmagic${SHDLIB_EXT}: ${EXTRA_LIBS} proto.magicrc: proto.magicrc.in ${SCPP} ${GR_DFLAGS} ${DFLAGS} proto.magicrc.in > proto.magicrc -install: $(DESTDIR)${BINDIR}/${MODULE}${EXEEXT} $(DESTDIR)${SYSDIR}/.magicrc \ - $(DESTDIR)${SYSDIR}/magicps.pro +install: $(DESTDIR)${INSTALL_BINDIR}/${MODULE}${EXEEXT} $(DESTDIR)${INSTALL_SYSDIR}/.magicrc \ + $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro -install-tcl: $(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT} $(DESTDIR)${SYSDIR}/.magicrc \ - $(DESTDIR)${SYSDIR}/.initrc $(DESTDIR)${SYSDIR}/magicps.pro ${DEST_XBM} +install-tcl: $(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT} $(DESTDIR)${INSTALL_SYSDIR}/.magicrc \ + $(DESTDIR)${INSTALL_SYSDIR}/.initrc $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro ${DEST_XBM} -$(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT}: tclmagic${SHDLIB_EXT} - ${RM} $(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT} - ${CP} tclmagic${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT} +$(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT}: tclmagic${SHDLIB_EXT} + ${RM} $(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT} + ${CP} tclmagic${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT} -$(DESTDIR)${TCLDIR}/bitmaps/%: bitmaps/% - ${RM} $(DESTDIR)${TCLDIR}/bitmaps/$* - ${CP} bitmaps/$* $(DESTDIR)${TCLDIR}/bitmaps/$* +$(DESTDIR)${INSTALL_TCLDIR}/bitmaps/%: bitmaps/% + ${RM} $(DESTDIR)${INSTALL_TCLDIR}/bitmaps/$* + ${CP} bitmaps/$* $(DESTDIR)${INSTALL_TCLDIR}/bitmaps/$* -$(DESTDIR)${SYSDIR}/.magicrc: proto.magicrc - ${RM} $(DESTDIR)${SYSDIR}/.magicrc - ${CP} proto.magicrc $(DESTDIR)${SYSDIR}/.magicrc +$(DESTDIR)${INSTALL_SYSDIR}/.magicrc: proto.magicrc + ${RM} $(DESTDIR)${INSTALL_SYSDIR}/.magicrc + ${CP} proto.magicrc $(DESTDIR)${INSTALL_SYSDIR}/.magicrc -$(DESTDIR)${SYSDIR}/.initrc: proto.initrc - ${RM} $(DESTDIR)${SYSDIR}/.initrc - ${CP} proto.initrc $(DESTDIR)${SYSDIR}/.initrc +$(DESTDIR)${INSTALL_SYSDIR}/.initrc: proto.initrc + ${RM} $(DESTDIR)${INSTALL_SYSDIR}/.initrc + ${CP} proto.initrc $(DESTDIR)${INSTALL_SYSDIR}/.initrc -$(DESTDIR)${SYSDIR}/magicps.pro: magicps.pro - ${RM} $(DESTDIR)${SYSDIR}/magicps.pro - ${CP} magicps.pro $(DESTDIR)${SYSDIR}/magicps.pro +$(DESTDIR)${INSTALL_SYSDIR}/magicps.pro: magicps.pro + ${RM} $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro + ${CP} magicps.pro $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro include ${MAGICDIR}/rules.mak diff --git a/net2ir/Makefile b/net2ir/Makefile index 9bdb7038..3b2b3131 100644 --- a/net2ir/Makefile +++ b/net2ir/Makefile @@ -15,7 +15,7 @@ tcl-main: main: net2ir -install: $(DESTDIR)${BINDIR}/${MODULE}${EXEEXT} +install: $(DESTDIR)${INSTALL_BINDIR}/${MODULE}${EXEEXT} install-tcl: echo "Nothing to do here" diff --git a/plot/Makefile b/plot/Makefile index 2e8027f3..0f164e5d 100644 --- a/plot/Makefile +++ b/plot/Makefile @@ -28,10 +28,10 @@ tclplot${SHDLIB_EXT}: tclplot.o ${OBJS} ${CC} ${CFLAGS} ${CPPFLAGS} -o $@ ${LDDL_FLAGS} tclplot.o ${OBJS} \ ${EXTRA_LIBS} -lc ${LIBS} -install-tcl: $(DESTDIR)${TCLDIR}/tclplot${SHDLIB_EXT} +install-tcl: $(DESTDIR)${INSTALL_TCLDIR}/tclplot${SHDLIB_EXT} -$(DESTDIR)${TCLDIR}/tclplot${SHDLIB_EXT}: tclplot${SHDLIB_EXT} - ${RM} $(DESTDIR)${TCLDIR}/tclplot${SHDLIB_EXT} - ${CP} tclplot${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/tclplot${SHDLIB_EXT} +$(DESTDIR)${INSTALL_TCLDIR}/tclplot${SHDLIB_EXT}: tclplot${SHDLIB_EXT} + ${RM} $(DESTDIR)${INSTALL_TCLDIR}/tclplot${SHDLIB_EXT} + ${CP} tclplot${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/tclplot${SHDLIB_EXT} include ${MAGICDIR}/rules.mak diff --git a/scmos/Makefile b/scmos/Makefile index 647e1d79..dd513e1a 100644 --- a/scmos/Makefile +++ b/scmos/Makefile @@ -54,11 +54,11 @@ all: $(OBJS) $(DEPEND) ${TECHFILES} install-tcl: all for i in ${FILES} ${TECHFILES}; do \ - ${CP} $$i $(DESTDIR)${SYSDIR}; done + ${CP} $$i $(DESTDIR)${INSTALL_SYSDIR}; done install: all for i in ${FILES} ${TECHFILES}; do \ - ${CP} $$i $(DESTDIR)${SYSDIR}; done + ${CP} $$i $(DESTDIR)${INSTALL_SYSDIR}; done scmos.tech: $(OBJS) sed -e 's/\\/\\\\/' scmos.tech.in > scmos.tech.out @@ -96,8 +96,8 @@ $(SCIFin): $(SCIFout): cd cif_template; ${MAKE} clean; ${MAKE}; -$(DESTDIR)${SYSDIR}/%: % - cp $* $(DESTDIR)${SYSDIR}/$* +$(DESTDIR)${INSTALL_SYSDIR}/%: % + cp $* $(DESTDIR)${INSTALL_SYSDIR}/$* clean:; -rm -f *.tech *.tech27 diff --git a/scripts/configure b/scripts/configure index 3b604040..1774a4ce 100755 --- a/scripts/configure +++ b/scripts/configure @@ -640,6 +640,7 @@ gr_dflags gr_cflags rl_libs rl_defs +dist_prefix cadinstall programs unused @@ -747,6 +748,7 @@ ac_user_opts=' enable_option_checking with_gnu_ld with_x +with_distdir with_interpreter with_tcl with_tk @@ -1425,6 +1427,7 @@ Optional Packages: --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-x use the X Window System + --with-distdir=DIR install into location DIR for distribution --with-interpreter=arg enable interpreter (tcl, scheme, or no) --with-tcl=DIR Find tclConfig.sh in DIR --with-tk=DIR Find tkConfig.sh in DIR @@ -6136,6 +6139,24 @@ else fi fi +# For distributed installs, where the run-time files are installed in a +# place that is a temporary staging area, like DESTDIR, but unlike DESTDIR, +# the prefix is replaced by the destination directory, rather than appended +# to it. +dist_prefix="\${exec_prefix}" + +# Check whether --with-distdir was given. +if test "${with_distdir+set}" = set; then : + withval=$with_distdir; + if test "$withval" = "no" -o "$withval" = "NO" ; then + dist_prefix="\${exec_prefix}" + else + dist_prefix=$arg + fi + +fi + + # Check for libXi, which is required on some systems but not available on # others. use_libxi="" @@ -8259,6 +8280,7 @@ fi + ac_config_files="$ac_config_files defs.mak" diff --git a/scripts/configure.in b/scripts/configure.in index 3000438e..8f8f85d2 100644 --- a/scripts/configure.in +++ b/scripts/configure.in @@ -345,6 +345,20 @@ else fi fi +# For distributed installs, where the run-time files are installed in a +# place that is a temporary staging area, like DESTDIR, but unlike DESTDIR, +# the prefix is replaced by the destination directory, rather than appended +# to it. +dist_prefix="\${exec_prefix}" +AC_ARG_WITH(distdir, +[ --with-distdir=DIR install into location DIR for distribution], [ + if test "$withval" = "no" -o "$withval" = "NO" ; then + dist_prefix="\${exec_prefix}" + else + dist_prefix=$arg + fi +], ) + # Check for libXi, which is required on some systems but not available on # others. use_libxi="" @@ -1768,6 +1782,7 @@ AC_SUBST(modules) AC_SUBST(unused) AC_SUBST(programs) AC_SUBST(cadinstall) +AC_SUBST(dist_prefix) AC_SUBST(rl_defs) AC_SUBST(rl_libs) diff --git a/scripts/defs.mak.in b/scripts/defs.mak.in index 7338b375..a2e70954 100755 --- a/scripts/defs.mak.in +++ b/scripts/defs.mak.in @@ -33,6 +33,14 @@ SYSDIR = ${libdir}/magic/sys SCMDIR = ${libdir}/magic/scm TCLDIR = ${libdir}/magic/tcl +# Install targets may be different if dist_prefix is set by configure +INSTALL_BINDIR = @dist_prefix@/bin +INSTALL_MANDIR = @dist_prefix@/share/man +INSTALL_LIBDIR = @dist_prefix@/lib +INSTALL_SYSDIR = ${INSTALL_LIBDIR}/magic/sys +INSTALL_SCMDIR = ${INSTALL_LIBDIR}/magic/scm +INSTALL_TCLDIR = ${INSTALL_LIBDIR}/magic/tcl + MAIN_EXTRA_LIBS = @extra_libs@ LD_EXTRA_LIBS = @ld_extra_libs@ LD_SHARED = @ld_extra_objs@ diff --git a/tcltk/Makefile b/tcltk/Makefile index db00d511..a6619678 100644 --- a/tcltk/Makefile +++ b/tcltk/Makefile @@ -32,21 +32,21 @@ TCL_FILES = \ magic.tcl BIN_FILES = \ - $(DESTDIR)${BINDIR}/magic.sh \ - $(DESTDIR)${BINDIR}/ext2spice.sh \ - $(DESTDIR)${BINDIR}/ext2sim.sh + $(DESTDIR)${INSTALL_BINDIR}/magic.sh \ + $(DESTDIR)${INSTALL_BINDIR}/ext2spice.sh \ + $(DESTDIR)${INSTALL_BINDIR}/ext2sim.sh tcl-main: magicexec magicdnull magic.tcl magic.sh ext2spice.sh ext2sim.sh install-tcl: magicexec magicdnull ${BIN_FILES} ${TCL_FILES} - ${RM} $(DESTDIR)${TCLDIR}/magicexec - ${CP} magicexec $(DESTDIR)${TCLDIR}/magicexec - ${RM} $(DESTDIR)${TCLDIR}/magicdnull - ${CP} magicdnull $(DESTDIR)${TCLDIR}/magicdnull - (cd $(DESTDIR)${TCLDIR}; ${RM} ${TCL_FILES}) + ${RM} $(DESTDIR)${INSTALL_TCLDIR}/magicexec + ${CP} magicexec $(DESTDIR)${INSTALL_TCLDIR}/magicexec + ${RM} $(DESTDIR)${INSTALL_TCLDIR}/magicdnull + ${CP} magicdnull $(DESTDIR)${INSTALL_TCLDIR}/magicdnull + (cd $(DESTDIR)${INSTALL_TCLDIR}; ${RM} ${TCL_FILES}) for i in ${TCL_FILES}; do \ - ${CP} $$i $(DESTDIR)${TCLDIR}; done - (cd $(DESTDIR)${TCLDIR}; chmod 0755 tkcon.tcl tkshell.tcl) + ${CP} $$i $(DESTDIR)${INSTALL_TCLDIR}; done + (cd $(DESTDIR)${INSTALL_TCLDIR}; chmod 0755 tkcon.tcl tkshell.tcl) magicexec: magicexec.c ${MAGICDIR}/defs.mak ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS_NOSTUB} ${LDFLAGS} magicexec.c \ @@ -73,23 +73,23 @@ ext2spice.sh: ext2spice.sh.in ${MAGICDIR}/defs.mak ext2sim.sh: ext2sim.sh.in ${MAGICDIR}/defs.mak sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g ext2sim.sh.in > ext2sim.sh -$(DESTDIR)${TCLDIR}/%: % - ${RM} $(DESTDIR)${TCLDIR}/$* - ${CP} $* $(DESTDIR)${TCLDIR}/$* +$(DESTDIR)${INSTALL_TCLDIR}/%: % + ${RM} $(DESTDIR)${INSTALL_TCLDIR}/$* + ${CP} $* $(DESTDIR)${INSTALL_TCLDIR}/$* -$(DESTDIR)${BINDIR}/magic.sh: magic.sh - ${RM} $(DESTDIR)${BINDIR}/magic.sh $(DESTDIR)${BINDIR}/magic - ${CP} magic.sh $(DESTDIR)${BINDIR}/magic - (cd $(DESTDIR)${BINDIR}; chmod 0755 magic) +$(DESTDIR)${INSTALL_BINDIR}/magic.sh: magic.sh + ${RM} $(DESTDIR)${INSTALL_BINDIR}/magic.sh $(DESTDIR)${INSTALL_BINDIR}/magic + ${CP} magic.sh $(DESTDIR)${INSTALL_BINDIR}/magic + (cd $(DESTDIR)${INSTALL_BINDIR}; chmod 0755 magic) -$(DESTDIR)${BINDIR}/ext2spice.sh: ext2spice.sh - ${RM} $(DESTDIR)${BINDIR}/ext2spice - ${CP} ext2spice.sh $(DESTDIR)${BINDIR}/ext2spice - (cd $(DESTDIR)${BINDIR}; chmod 0755 ext2spice) +$(DESTDIR)${INSTALL_BINDIR}/ext2spice.sh: ext2spice.sh + ${RM} $(DESTDIR)${INSTALL_BINDIR}/ext2spice + ${CP} ext2spice.sh $(DESTDIR)${INSTALL_BINDIR}/ext2spice + (cd $(DESTDIR)${INSTALL_BINDIR}; chmod 0755 ext2spice) -$(DESTDIR)${BINDIR}/ext2sim.sh: ext2sim.sh - ${RM} $(DESTDIR)${BINDIR}/ext2sim - ${CP} ext2sim.sh $(DESTDIR)${BINDIR}/ext2sim - (cd $(DESTDIR)${BINDIR}; chmod 0755 ext2sim) +$(DESTDIR)${INSTALL_BINDIR}/ext2sim.sh: ext2sim.sh + ${RM} $(DESTDIR)${INSTALL_BINDIR}/ext2sim + ${CP} ext2sim.sh $(DESTDIR)${INSTALL_BINDIR}/ext2sim + (cd $(DESTDIR)${INSTALL_BINDIR}; chmod 0755 ext2sim) include ${MAGICDIR}/rules.mak diff --git a/utils/Depend b/utils/Depend index 56e88bb4..4f469cb1 100644 --- a/utils/Depend +++ b/utils/Depend @@ -2,7 +2,9 @@ args.o: args.c ../utils/magic.h ../utils/utils.h child.o: child.c ../utils/utils.h ../utils/magic.h ../utils/malloc.h dqueue.o: dqueue.c ../utils/magic.h ../utils/dqueue.h ../utils/malloc.h finddisp.o: finddisp.c ../utils/magic.h ../utils/utils.h -flock.o: flock.c +flock.o: flock.c ../utils/magic.h ../utils/hash.h ../utils/geometry.h \ + ../tiles/tile.h ../database/database.h ../windows/windows.h \ + ../utils/malloc.h flsbuf.o: flsbuf.c fraction.o: fraction.c ../utils/magic.h ../utils/geometry.h geometry.o: geometry.c ../utils/magic.h ../utils/geometry.h \ diff --git a/windows/Makefile b/windows/Makefile index 0b310026..56dc6795 100644 --- a/windows/Makefile +++ b/windows/Makefile @@ -15,13 +15,13 @@ include ${MAGICDIR}/defs.mak include ${MAGICDIR}/rules.mak install-tcl: - @echo --- installing glyphs to $(DESTDIR)${SYSDIR} + @echo --- installing glyphs to $(DESTDIR)${INSTALL_SYSDIR} for i in ${GLYPHS} ${FONTS}; do \ - (cd $(DESTDIR)${SYSDIR} && ${RM} $$i); \ - ${CP} $$i $(DESTDIR)${SYSDIR}; done + (cd $(DESTDIR)${INSTALL_SYSDIR} && ${RM} $$i); \ + ${CP} $$i $(DESTDIR)${INSTALL_SYSDIR}; done install: - @echo --- installing glyphs to $(DESTDIR)${SYSDIR} + @echo --- installing glyphs to $(DESTDIR)${INSTALL_SYSDIR} for i in ${GLYPHS} ${FONTS}; do \ - (cd $(DESTDIR)${SYSDIR} && ${RM} $$i); \ - ${CP} $$i $(DESTDIR)${SYSDIR}; done + (cd $(DESTDIR)${INSTALL_SYSDIR} && ${RM} $$i); \ + ${CP} $$i $(DESTDIR)${INSTALL_SYSDIR}; done From 323ce9598113a2d387a2cbd04eb2caa511560075 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 28 Jan 2020 12:17:22 -0500 Subject: [PATCH 087/121] Corrected missing references to the dist_dir install location in the top-level Makefile. --- Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 23e22d4b..f0b50d48 100644 --- a/Makefile +++ b/Makefile @@ -66,8 +66,8 @@ depend: database/database.h install: $(INSTALL_TARGET) install-magic: - @echo --- installing executable to $(DESTDIR)${BINDIR} - @echo --- installing runtime files to $(DESTDIR)${LIBDIR} + @echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR} + @echo --- installing runtime files to $(DESTDIR)${INSTALL_LIBDIR} @${MAKE} install-real 2>&1 >> install.log install-real: install-dirs @@ -77,16 +77,16 @@ install-real: install-dirs (cd $$dir && ${MAKE} install); done install-tcl-dirs: - ${MAGICDIR}/scripts/mkdirs $(DESTDIR)${BINDIR} $(DESTDIR)${MANDIR} \ - $(DESTDIR)${SYSDIR} $(DESTDIR)${TCLDIR} $(DESTDIR)${TCLDIR}/bitmaps + ${MAGICDIR}/scripts/mkdirs $(DESTDIR)${INSTALL_BINDIR} $(DESTDIR)${INSTALL_MANDIR} \ + $(DESTDIR)${SYSDIR} $(DESTDIR)${INSTALL_TCLDIR} $(DESTDIR)${INSTALL_TCLDIR}/bitmaps install-dirs: - ${MAGICDIR}/scripts/mkdirs $(DESTDIR)${BINDIR} $(DESTDIR)${MANDIR} \ - $(DESTDIR)${SYSDIR} $(DESTDIR)${SCMDIR} + ${MAGICDIR}/scripts/mkdirs $(DESTDIR)${INSTALL_BINDIR} $(DESTDIR)${INSTALL_MANDIR} \ + $(DESTDIR)${INSTALL_SYSDIR} $(DESTDIR)${INSTALL_SCMDIR} install-tcl: - @echo --- installing executable to $(DESTDIR)${BINDIR} - @echo --- installing runtime files to $(DESTDIR)${LIBDIR} + @echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR} + @echo --- installing runtime files to $(DESTDIR)${INSTALL_LIBDIR} @${MAKE} install-tcl-real 2>&1 >> install.log install-tcl-real: install-tcl-dirs From 4c5f02710469fb1c3164a9a729f6bda661e0d157 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 28 Jan 2020 12:29:44 -0500 Subject: [PATCH 088/121] Correction to the configuration for distributed install. --- scripts/configure.in | 8 ++++---- scripts/defs.mak.in | 6 +++--- tcltk/ext2sim.sh | 2 +- tcltk/ext2spice.sh | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/configure.in b/scripts/configure.in index 8f8f85d2..306ab304 100644 --- a/scripts/configure.in +++ b/scripts/configure.in @@ -349,13 +349,13 @@ fi # place that is a temporary staging area, like DESTDIR, but unlike DESTDIR, # the prefix is replaced by the destination directory, rather than appended # to it. -dist_prefix="\${exec_prefix}" +DIST_DIR="\${exec_prefix}" AC_ARG_WITH(distdir, [ --with-distdir=DIR install into location DIR for distribution], [ if test "$withval" = "no" -o "$withval" = "NO" ; then - dist_prefix="\${exec_prefix}" + DIST_DIR="\${exec_prefix}" else - dist_prefix=$arg + DIST_DIR=${withval} fi ], ) @@ -1782,7 +1782,7 @@ AC_SUBST(modules) AC_SUBST(unused) AC_SUBST(programs) AC_SUBST(cadinstall) -AC_SUBST(dist_prefix) +AC_SUBST(DIST_DIR) AC_SUBST(rl_defs) AC_SUBST(rl_libs) diff --git a/scripts/defs.mak.in b/scripts/defs.mak.in index a2e70954..98f07b37 100755 --- a/scripts/defs.mak.in +++ b/scripts/defs.mak.in @@ -34,9 +34,9 @@ SCMDIR = ${libdir}/magic/scm TCLDIR = ${libdir}/magic/tcl # Install targets may be different if dist_prefix is set by configure -INSTALL_BINDIR = @dist_prefix@/bin -INSTALL_MANDIR = @dist_prefix@/share/man -INSTALL_LIBDIR = @dist_prefix@/lib +INSTALL_BINDIR = @DIST_DIR@/bin +INSTALL_MANDIR = @DIST_DIR@/share/man +INSTALL_LIBDIR = @DIST_DIR@/lib INSTALL_SYSDIR = ${INSTALL_LIBDIR}/magic/sys INSTALL_SCMDIR = ${INSTALL_LIBDIR}/magic/scm INSTALL_TCLDIR = ${INSTALL_LIBDIR}/magic/tcl diff --git a/tcltk/ext2sim.sh b/tcltk/ext2sim.sh index 8bd40c31..b1c98edd 100644 --- a/tcltk/ext2sim.sh +++ b/tcltk/ext2sim.sh @@ -15,7 +15,7 @@ for i in $@; do esac done # -eval /usr/local/lib/magic/tcl/magicdnull -dnull -noconsole -nowrapper $mgargs < Date: Tue, 28 Jan 2020 13:10:31 -0500 Subject: [PATCH 089/121] Missed a number of Makefiles in directories two levels down. --- Makefile | 10 ++++---- doc/html/Makefile | 2 +- doc/latexfiles/Makefile | 2 +- doc/man/Makefile | 46 ++++++++++++++++++------------------- doc/tutcells/Makefile | 2 +- scmos/cif_template/Makefile | 3 +-- scripts/configure | 8 +++---- 7 files changed, 37 insertions(+), 36 deletions(-) diff --git a/Makefile b/Makefile index f0b50d48..9f288127 100644 --- a/Makefile +++ b/Makefile @@ -77,12 +77,14 @@ install-real: install-dirs (cd $$dir && ${MAKE} install); done install-tcl-dirs: - ${MAGICDIR}/scripts/mkdirs $(DESTDIR)${INSTALL_BINDIR} $(DESTDIR)${INSTALL_MANDIR} \ - $(DESTDIR)${SYSDIR} $(DESTDIR)${INSTALL_TCLDIR} $(DESTDIR)${INSTALL_TCLDIR}/bitmaps + ${MAGICDIR}/scripts/mkdirs $(DESTDIR)${INSTALL_BINDIR} \ + $(DESTDIR)${INSTALL_MANDIR} $(DESTDIR)${INSTALL_SYSDIR} \ + $(DESTDIR)${INSTALL_TCLDIR} $(DESTDIR)${INSTALL_TCLDIR}/bitmaps install-dirs: - ${MAGICDIR}/scripts/mkdirs $(DESTDIR)${INSTALL_BINDIR} $(DESTDIR)${INSTALL_MANDIR} \ - $(DESTDIR)${INSTALL_SYSDIR} $(DESTDIR)${INSTALL_SCMDIR} + ${MAGICDIR}/scripts/mkdirs $(DESTDIR)${INSTALL_BINDIR} \ + $(DESTDIR)${INSTALL_MANDIR} $(DESTDIR)${INSTALL_SYSDIR} \ + $(DESTDIR)${INSTALL_SCMDIR} install-tcl: @echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR} diff --git a/doc/html/Makefile b/doc/html/Makefile index 427ae37c..bf577bcc 100644 --- a/doc/html/Makefile +++ b/doc/html/Makefile @@ -2,7 +2,7 @@ MAGICDIR = ../.. include $(MAGICDIR)/defs.mak -HTML_INSTDIR=$(LIBDIR)/magic/doc/html +HTML_INSTDIR=$(INSTALL_LIBDIR)/magic/doc/html install: $(DESTDIR)${HTML_INSTDIR} tar cf - . | (cd $(DESTDIR)${HTML_INSTDIR}; tar xf - ) diff --git a/doc/latexfiles/Makefile b/doc/latexfiles/Makefile index 5b0ba47a..aeba340d 100644 --- a/doc/latexfiles/Makefile +++ b/doc/latexfiles/Makefile @@ -3,7 +3,7 @@ MAGICDIR = ../.. include $(MAGICDIR)/defs.mak PS_SRCDIR=../psfiles -PS_INSTDIR=$(LIBDIR)/magic/doc +PS_INSTDIR=$(INSTALL_LIBDIR)/magic/doc .SUFFIXES: .dvi .tex .ps diff --git a/doc/man/Makefile b/doc/man/Makefile index ebf937ba..da493492 100644 --- a/doc/man/Makefile +++ b/doc/man/Makefile @@ -15,36 +15,36 @@ EQN=eqn -Ppsc include ${MAGICDIR}/defs.mak MANFILES = \ - $(DESTDIR)${MANDIR}/man1/ext2spice.1 \ - $(DESTDIR)${MANDIR}/man1/extcheck.1 \ - $(DESTDIR)${MANDIR}/man1/ext2sim.1 \ - $(DESTDIR)${MANDIR}/man1/magic.1 \ - $(DESTDIR)${MANDIR}/man5/cmap.5 \ - $(DESTDIR)${MANDIR}/man5/displays.5 \ - $(DESTDIR)${MANDIR}/man5/dlys.5 \ - $(DESTDIR)${MANDIR}/man5/dstyle.5 \ - $(DESTDIR)${MANDIR}/man5/ext.5 \ - $(DESTDIR)${MANDIR}/man5/glyphs.5 \ - $(DESTDIR)${MANDIR}/man5/mag.5 \ - $(DESTDIR)${MANDIR}/man5/net.5 \ - $(DESTDIR)${MANDIR}/man5/sim.5 + $(DESTDIR)${INSTALL_MANDIR}/man1/ext2spice.1 \ + $(DESTDIR)${INSTALL_MANDIR}/man1/extcheck.1 \ + $(DESTDIR)${INSTALL_MANDIR}/man1/ext2sim.1 \ + $(DESTDIR)${INSTALL_MANDIR}/man1/magic.1 \ + $(DESTDIR)${INSTALL_MANDIR}/man5/cmap.5 \ + $(DESTDIR)${INSTALL_MANDIR}/man5/displays.5 \ + $(DESTDIR)${INSTALL_MANDIR}/man5/dlys.5 \ + $(DESTDIR)${INSTALL_MANDIR}/man5/dstyle.5 \ + $(DESTDIR)${INSTALL_MANDIR}/man5/ext.5 \ + $(DESTDIR)${INSTALL_MANDIR}/man5/glyphs.5 \ + $(DESTDIR)${INSTALL_MANDIR}/man5/mag.5 \ + $(DESTDIR)${INSTALL_MANDIR}/man5/net.5 \ + $(DESTDIR)${INSTALL_MANDIR}/man5/sim.5 install: ${MANFILES} -$(DESTDIR)${MANDIR}: - ${SCRIPTS}/mkdirs $(DESTDIR)${MANDIR} +$(DESTDIR)${INSTALL_MANDIR}: + ${SCRIPTS}/mkdirs $(DESTDIR)${INSTALL_MANDIR} -$(DESTDIR)${MANDIR}/man1: $(DESTDIR)${MANDIR} - ${SCRIPTS}/mkdirs $(DESTDIR)${MANDIR}/man1 +$(DESTDIR)${INSTALL_MANDIR}/man1: $(DESTDIR)${INSTALL_MANDIR} + ${SCRIPTS}/mkdirs $(DESTDIR)${INSTALL_MANDIR}/man1 -$(DESTDIR)${MANDIR}/man1/%: % $(DESTDIR)${MANDIR}/man1 - ${CP} $* $(DESTDIR)${MANDIR}/man1/$* +$(DESTDIR)${INSTALL_MANDIR}/man1/%: % $(DESTDIR)${INSTALL_MANDIR}/man1 + ${CP} $* $(DESTDIR)${INSTALL_MANDIR}/man1/$* -$(DESTDIR)${MANDIR}/man5: $(DESTDIR)${MANDIR} - ${SCRIPTS}/mkdirs $(DESTDIR)${MANDIR}/man5 +$(DESTDIR)${INSTALL_MANDIR}/man5: $(DESTDIR)${INSTALL_MANDIR} + ${SCRIPTS}/mkdirs $(DESTDIR)${INSTALL_MANDIR}/man5 -$(DESTDIR)${MANDIR}/man5/%: % $(DESTDIR)${MANDIR}/man5 - ${CP} $* $(DESTDIR)${MANDIR}/man5/$* +$(DESTDIR)${INSTALL_MANDIR}/man5/%: % $(DESTDIR)${INSTALL_MANDIR}/man5 + ${CP} $* $(DESTDIR)${INSTALL_MANDIR}/man5/$* mans: ${SCRIPTS}/printmans "${TROFF} ${MANMACS} -" *.1 *.5 diff --git a/doc/tutcells/Makefile b/doc/tutcells/Makefile index 7edc8cb5..a60d909b 100644 --- a/doc/tutcells/Makefile +++ b/doc/tutcells/Makefile @@ -6,7 +6,7 @@ MAGICDIR = ../.. include ${MAGICDIR}/defs.mak -TUTDIR = ${LIBDIR}/magic/tutorial +TUTDIR = ${INSTALL_LIBDIR}/magic/tutorial TUTFILES= m3a.mag maint2a.mag tut1.mag \ tut2a.mag tut2b.mag tut2c.mag tut2d.mag \ diff --git a/scmos/cif_template/Makefile b/scmos/cif_template/Makefile index 0c654441..89377a82 100644 --- a/scmos/cif_template/Makefile +++ b/scmos/cif_template/Makefile @@ -21,8 +21,7 @@ all: $(OBJS_DIR) $(CIFIN) $(CIFOUT) $(IBMCIFIN) $(IBMCIFOUT) $(TMCIFIN) \ $(TMCIFOUT) $(SUBCIFIN) $(SUBCIFOUT) clean:; - rm -f $(CIFIN) $(CIFOUT) $(IBMCIFIN) $(IBMCIFOUT) $(TMCIFIN) \ - $(TMCIFOUT) $(SUBCIFIN) $(SUBCIFOUT) + rm -rf $(OBJS_DIR) scg: cifout.c cifout-cmos26b.gen cifout.gen cifout.nw\ cifout.others cifout.pw cifout.scgnw cifout.scgpw diff --git a/scripts/configure b/scripts/configure index 1774a4ce..2114738f 100755 --- a/scripts/configure +++ b/scripts/configure @@ -640,7 +640,7 @@ gr_dflags gr_cflags rl_libs rl_defs -dist_prefix +DIST_DIR cadinstall programs unused @@ -6143,15 +6143,15 @@ fi # place that is a temporary staging area, like DESTDIR, but unlike DESTDIR, # the prefix is replaced by the destination directory, rather than appended # to it. -dist_prefix="\${exec_prefix}" +DIST_DIR="\${exec_prefix}" # Check whether --with-distdir was given. if test "${with_distdir+set}" = set; then : withval=$with_distdir; if test "$withval" = "no" -o "$withval" = "NO" ; then - dist_prefix="\${exec_prefix}" + DIST_DIR="\${exec_prefix}" else - dist_prefix=$arg + DIST_DIR=${withval} fi fi From 3af3eeffffce8fa4af94833e6e4cd18d2230421d Mon Sep 17 00:00:00 2001 From: Tim 'mithro' Ansell Date: Tue, 4 Feb 2020 12:16:29 +0100 Subject: [PATCH 090/121] Change the file used to store the LICENSE. --- COPYRIGHT => LICENSE | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename COPYRIGHT => LICENSE (100%) diff --git a/COPYRIGHT b/LICENSE similarity index 100% rename from COPYRIGHT rename to LICENSE From 6077907f77856f50684997da25499120b0f4a884 Mon Sep 17 00:00:00 2001 From: Tim 'mithro' Ansell Date: Tue, 4 Feb 2020 14:47:07 +0100 Subject: [PATCH 091/121] Adding generated files to .gitignore. --- .gitignore | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.gitignore b/.gitignore index 04cd59d6..50ebaf94 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,18 @@ scripts/defs.mak scmos/cif_template/objs/* UPDATE_ME VERSION +database/database.h +install.log +magic/proto.magicrc +make.log +readline/readline +scmos/gdsquery.tech +scmos/minimum.tech +scmos/scmos-sub.tech +scmos/scmos-tm.tech +scmos/scmos.tech +scmos/scmosWR.tech +tcltk/magic.sh +tcltk/magic.tcl +tcltk/magicdnull +tcltk/magicexec From 4f30e766880a5032e6a5fdfb10eca02199b60837 Mon Sep 17 00:00:00 2001 From: Tim 'mithro' Ansell Date: Fri, 7 Feb 2020 17:29:16 +0100 Subject: [PATCH 092/121] Make SVG output actually SVG again. Currently the SVG output is a SVG file with an embedded `image/png` file. Restricting to `CAIRO_SVG_VERSION_1_2` means the file goes back to being a vector. Signed-off-by: Tim 'mithro' Ansell --- graphics/grTCairo1.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/graphics/grTCairo1.c b/graphics/grTCairo1.c index 7e293d2f..27299739 100644 --- a/graphics/grTCairo1.c +++ b/graphics/grTCairo1.c @@ -370,6 +370,9 @@ GrTCairoPlotSVG (char *filename, MagWindow *mw) wind_context = tcairodata->context; tcairodata->surface = (cairo_surface_t *)cairo_svg_surface_create(filename, (double)screenw, (double)screenh); + cairo_svg_surface_restrict_to_version( + tcairodata->surface, CAIRO_SVG_VERSION_1_2); + tcairodata->context = cairo_create(tcairodata->surface); WindRedisplay(mw); WindUpdate(); From 2ca95111529ad06c0577d61928b337c530a0e892 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 7 Feb 2020 11:38:00 -0500 Subject: [PATCH 093/121] Added fix for SVG output. This brings back the original behavior of generating scalable output. Some libcairo update had caused the output to use the wrong version of SVG by default, which generates an SVG-wrapped PNG data block, which is not scalable, and not what was intended with the "plot svg" command. --- graphics/grTCairo1.c | 5 ++--- tcltk/ext2sim.sh | 2 +- tcltk/ext2spice.sh | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/graphics/grTCairo1.c b/graphics/grTCairo1.c index 27299739..ed5c1a5b 100644 --- a/graphics/grTCairo1.c +++ b/graphics/grTCairo1.c @@ -370,9 +370,8 @@ GrTCairoPlotSVG (char *filename, MagWindow *mw) wind_context = tcairodata->context; tcairodata->surface = (cairo_surface_t *)cairo_svg_surface_create(filename, (double)screenw, (double)screenh); - cairo_svg_surface_restrict_to_version( - tcairodata->surface, CAIRO_SVG_VERSION_1_2); - + cairo_svg_surface_restrict_to_version(tcairodata->surface, + CAIRO_SVG_VERSION_1_2); tcairodata->context = cairo_create(tcairodata->surface); WindRedisplay(mw); WindUpdate(); diff --git a/tcltk/ext2sim.sh b/tcltk/ext2sim.sh index b1c98edd..8bd40c31 100644 --- a/tcltk/ext2sim.sh +++ b/tcltk/ext2sim.sh @@ -15,7 +15,7 @@ for i in $@; do esac done # -eval /home/tim/cad/lib/magic/tcl/magicdnull -dnull -noconsole -nowrapper $mgargs < Date: Tue, 11 Feb 2020 10:21:36 -0500 Subject: [PATCH 094/121] Corrected ext2sim.c calls to hierAP and others using "scale" and declaring it to be an integer when it is actually a float. This will cause magic to crash when using, e.g., "ext2sim -f su". --- ext2sim/ext2sim.c | 19 +++++++++++-------- graphics/grTCairo1.c | 1 + 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/ext2sim/ext2sim.c b/ext2sim/ext2sim.c index 897e4f31..4efe627e 100644 --- a/ext2sim/ext2sim.c +++ b/ext2sim/ext2sim.c @@ -1078,7 +1078,7 @@ simdevVisit(dev, hierName, scale, trans) { putc(' ', esSimF); simdevSubstrate(hierName, subnode->efnode_name->efnn_hier, - dev->dev_type, 0, FALSE, esSimF); + dev->dev_type, 0.0, FALSE, esSimF); } GeoTransRect(trans, &dev->dev_rect, &r); @@ -1196,7 +1196,8 @@ int simdevSubstrate( prefix, suffix, type, scale, doAP, outf) HierName *prefix; HierName *suffix; -int type, scale; +int type; +float scale; bool doAP; FILE *outf; { @@ -1264,7 +1265,8 @@ FILE *outf; bool simnAP(node, resClass, scale, outf) EFNode *node; -int resClass, scale; +int resClass; +float scale; FILE *outf; { int a, p; @@ -1277,8 +1279,8 @@ FILE *outf; return FALSE; } markVisited((nodeClient *)node->efnode_client, resClass); - a = node->efnode_pa[resClass].pa_area*scale*scale; - p = node->efnode_pa[resClass].pa_perim*scale; + a = (int)(node->efnode_pa[resClass].pa_area*scale*scale); + p = (int)(node->efnode_pa[resClass].pa_perim*scale); if ( a < 0 ) a = 0; if ( p < 0 ) p = 0; fprintf(outf,"A_%d,P_%d", a, p); @@ -1288,7 +1290,8 @@ FILE *outf; bool simnAPHier(dterm, hierName, resClass, scale, outf) DevTerm *dterm; HierName *hierName; - int resClass, scale; + int resClass; + float scale; FILE *outf; { EFNode *node = dterm->dterm_node; @@ -1308,8 +1311,8 @@ bool simnAPHier(dterm, hierName, resClass, scale, outf) return FALSE; } markVisited((nodeClientHier *)node->efnode_client, resClass); - a = node->efnode_pa[resClass].pa_area*scale*scale; - p = node->efnode_pa[resClass].pa_perim*scale; + a = (int)(node->efnode_pa[resClass].pa_area*scale*scale); + p = (int)(node->efnode_pa[resClass].pa_perim*scale); if ( a < 0 ) a = 0; if ( p < 0 ) p = 0; fprintf(outf,"A_%d,P_%d", a, p); diff --git a/graphics/grTCairo1.c b/graphics/grTCairo1.c index ed5c1a5b..e84789a0 100644 --- a/graphics/grTCairo1.c +++ b/graphics/grTCairo1.c @@ -372,6 +372,7 @@ GrTCairoPlotSVG (char *filename, MagWindow *mw) (double)screenw, (double)screenh); cairo_svg_surface_restrict_to_version(tcairodata->surface, CAIRO_SVG_VERSION_1_2); + tcairodata->context = cairo_create(tcairodata->surface); WindRedisplay(mw); WindUpdate(); From f2dc4b37f01f427a578679c99e2a9c062c082809 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 13 Feb 2020 10:04:55 -0500 Subject: [PATCH 095/121] Corrected the connectivity search function so that it does not attempt to copy and search on a label that already exists in the flattened, copied database. Otherwise multiple labels on a single net can cause the search to go into an infinite loop, repeatedly copying and erasing the same label over and over again. --- database/DBconnect.c | 5 ++++ database/DBlabel.c | 55 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/database/DBconnect.c b/database/DBconnect.c index f1f5a6ab..826c2f48 100644 --- a/database/DBconnect.c +++ b/database/DBconnect.c @@ -679,6 +679,11 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2) if (scx->scx_use == csa2->csa2_topscx->scx_use) { + /* 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; + DBEraseLabelsByContent(def, &r, -1, lab->lab_text); DBPutFontLabel(def, &r, lab->lab_font, lab->lab_size, rotate, &offset, pos, lab->lab_text, lab->lab_type, lab->lab_flags); diff --git a/database/DBlabel.c b/database/DBlabel.c index 6fb058dd..9e95d2d5 100644 --- a/database/DBlabel.c +++ b/database/DBlabel.c @@ -313,7 +313,55 @@ DBEraseLabel(cellDef, area, mask, areaReturn) cellDef->cd_flags |= CDMODIFIED|CDGETNEWSTAMP; return (erasedAny); } - + +#define RECTEQUAL(r1, r2) ((r1)->r_xbot == (r2)->r_xbot \ + && (r1)->r_ybot == (r2)->r_ybot \ + && (r1)->r_xtop == (r2)->r_xtop \ + && (r1)->r_ytop == (r2)->r_ytop) + +/* + * ---------------------------------------------------------------------------- + * + * DBCheckLabelsByContent -- + * + * Return any label found on the label list for the given + * CellDef that matches the given specification. + * + * Results: + * Returns a label if a match is found, otherwise returns NULL. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +Label * +DBCheckLabelsByContent(def, rect, type, text) + CellDef *def; /* Where to look for label to delete. */ + Rect *rect; /* Coordinates of label. If NULL, then + * labels are searched regardless of coords. + */ + TileType type; /* Layer label is attached to. If < 0, then + * labels are searched regardless of type. + */ + char *text; /* Text associated with label. If NULL, then + * labels are searched regardless of text. + */ +{ + Label *lab; + + for (lab = def->cd_labels; lab; lab = lab->lab_next) + { + if ((rect != NULL) && !(RECTEQUAL(&lab->lab_rect, rect))) continue; + if ((type >= 0) && (type != lab->lab_type)) continue; + if ((text != NULL) && (strcmp(text, lab->lab_text) != 0)) continue; + + return lab; + } + return NULL; +} + /* * ---------------------------------------------------------------------------- * @@ -348,11 +396,6 @@ DBEraseLabelsByContent(def, rect, type, text) { Label *lab, *labPrev; -#define RECTEQUAL(r1, r2) ((r1)->r_xbot == (r2)->r_xbot \ - && (r1)->r_ybot == (r2)->r_ybot \ - && (r1)->r_xtop == (r2)->r_xtop \ - && (r1)->r_ytop == (r2)->r_ytop) - for (labPrev = NULL, lab = def->cd_labels; lab != NULL; labPrev = lab, lab = lab->lab_next) From 897a8064bab96609729dc2b3d0a6d6a44b54adb7 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 14 Feb 2020 08:48:47 -0500 Subject: [PATCH 096/121] Restored the behavior of selecting and displaying labels that are down in the hierarchy when selecting a region or net, but with a (hopefully very useful) twist: To avoid the problem of ambiguous labels in subcells, the subcell name hierarchy is generated in the same way as is done when flattening a cell, with the instance name prepended. For example, when selecting a net in a standard cell design, a terminal would highlight the name "OR2X1_1/B" instead of just "B". --- commands/CmdFI.c | 1 + database/DBconnect.c | 44 ++++++++++++++++++++++++++++++++++---------- utils/Depend | 4 +--- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/commands/CmdFI.c b/commands/CmdFI.c index 178fe9ee..f50e600e 100644 --- a/commands/CmdFI.c +++ b/commands/CmdFI.c @@ -1792,6 +1792,7 @@ FlatCopyAllLabels(scx, mask, xMask, targetUse) char pathstring[FLATTERMSIZE]; TerminalPath tpath; + pathstring[0] = '\0'; tpath.tp_first = tpath.tp_next = pathstring; tpath.tp_last = pathstring + FLATTERMSIZE; diff --git a/database/DBconnect.c b/database/DBconnect.c index 826c2f48..f81446bd 100644 --- a/database/DBconnect.c +++ b/database/DBconnect.c @@ -656,6 +656,9 @@ dbcUnconnectFunc(tile, clientData) * ---------------------------------------------------------------------------- */ +/* To do: Make the tpath entries dynamically allocated */ +#define FLATTERMSIZE 1024 + int dbcConnectLabelFunc(scx, lab, tpath, csa2) SearchContext *scx; @@ -667,6 +670,8 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2) Rect r; Point offset; int pos, rotate; + char newlabtext[FLATTERMSIZE]; + char *newlabptr; int dbcConnectFunc(); /* Forward declaration */ GeoTransRect(&scx->scx_trans, &lab->lab_rect, &r); @@ -677,17 +682,29 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2) /* Only add labels if they are on the search top level */ /* (NOTE: Could add hierachical labels using tpath) */ - if (scx->scx_use == csa2->csa2_topscx->scx_use) + if (scx->scx_use != csa2->csa2_topscx->scx_use) { - /* 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; - - DBEraseLabelsByContent(def, &r, -1, lab->lab_text); - DBPutFontLabel(def, &r, lab->lab_font, lab->lab_size, rotate, &offset, - pos, lab->lab_text, lab->lab_type, lab->lab_flags); + int newllen = tpath->tp_next - tpath->tp_first; + newlabtext[0] = '\0'; + if (newllen > 0) + strncpy(newlabtext, tpath->tp_first, newllen); + sprintf(newlabtext + newllen, "%s", lab->lab_text); + newlabptr = newlabtext; } + else + newlabptr = lab->lab_text; + + /* Do not repeat a label copy; check that the label doesn't */ + /* already exist in the destination def first. */ + if (DBCheckLabelsByContent(def, &r, lab->lab_type, lab->lab_text)) + return 0; + + if (DBCheckLabelsByContent(def, &r, lab->lab_type, newlabptr)) + return 0; + + DBEraseLabelsByContent(def, &r, -1, lab->lab_text); + DBPutFontLabel(def, &r, lab->lab_font, lab->lab_size, rotate, &offset, + pos, newlabptr, lab->lab_type, lab->lab_flags); if (lab->lab_flags & PORT_DIR_MASK) { @@ -1024,6 +1041,13 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, destUse) DBTreeSrTiles(scx, mask, xMask, dbcConnectFunc, (ClientData) &csa2); while (csa2.csa2_top >= 0) { + char pathstring[FLATTERMSIZE]; + TerminalPath tpath; + + tpath.tp_first = tpath.tp_next = pathstring; + tpath.tp_last = pathstring + FLATTERMSIZE; + pathstring[0] = '\0'; + newmask = csa2.csa2_list[csa2.csa2_top].connectMask; scx->scx_area = csa2.csa2_list[csa2.csa2_top].area; newtype = csa2.csa2_list[csa2.csa2_top].dinfo; @@ -1064,7 +1088,7 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, destUse) searchtype |= TF_LABEL_ATTACH_NOT_SE; } } - DBTreeSrLabels(scx, newmask, xMask, NULL, searchtype, + DBTreeSrLabels(scx, newmask, xMask, &tpath, searchtype, dbcConnectLabelFunc, (ClientData) &csa2); } freeMagic((char *)csa2.csa2_list); diff --git a/utils/Depend b/utils/Depend index 4f469cb1..56e88bb4 100644 --- a/utils/Depend +++ b/utils/Depend @@ -2,9 +2,7 @@ args.o: args.c ../utils/magic.h ../utils/utils.h child.o: child.c ../utils/utils.h ../utils/magic.h ../utils/malloc.h dqueue.o: dqueue.c ../utils/magic.h ../utils/dqueue.h ../utils/malloc.h finddisp.o: finddisp.c ../utils/magic.h ../utils/utils.h -flock.o: flock.c ../utils/magic.h ../utils/hash.h ../utils/geometry.h \ - ../tiles/tile.h ../database/database.h ../windows/windows.h \ - ../utils/malloc.h +flock.o: flock.c flsbuf.o: flsbuf.c fraction.o: fraction.c ../utils/magic.h ../utils/geometry.h geometry.o: geometry.c ../utils/magic.h ../utils/geometry.h \ From ed8117784e2f11abe4acd73ae3deeae926b4f153 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 14 Feb 2020 09:36:30 -0500 Subject: [PATCH 097/121] Corrected three annoying errors: (1) Select net method had been changed to ignore labels below the top level of hierarchy. This turned out to be a bad idea. However, the original behavior was problematic due to confusion over what part of the hierarchy the labels were in. The new behavior prefixes each label with the cell hierarchy, eliminating both problems. (2) Corrected the problem where the attachment box for rendered labels is not displayed if the label name is not in the viewing area. (3) Corrected the problem where redirection of input from the layout window to the console window with the ":" command gets inadvertently canceled; this turned out to be due to a missing "*bypass" in front of the command that finds the output scale to display the pointer coordinates, and this was happening whenever the mouse was moved while typing in a command. --- database/DBcellsrch.c | 5 ++++- dbwind/DBWdisplay.c | 2 +- tcltk/wrapper.tcl | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/database/DBcellsrch.c b/database/DBcellsrch.c index a960bf2e..d3eaa667 100644 --- a/database/DBcellsrch.c +++ b/database/DBcellsrch.c @@ -581,8 +581,11 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg) else is_touching = GEO_TOUCH(&lab->lab_rect, r); } - if (!is_touching && (flags & TF_LABEL_DISPLAY) && (lab->lab_font >= 0)) + if (!is_touching && (flags & TF_LABEL_DISPLAY) && lab->lab_font >= 0) + { + /* Check against bounds of the rendered label text */ is_touching = GEO_TOUCH(&lab->lab_bbox, r); + } if (is_touching && TTMaskHasType(mask, lab->lab_type)) if ((*func)(scx, lab, tpath, cdarg)) diff --git a/dbwind/DBWdisplay.c b/dbwind/DBWdisplay.c index 8ea1b3bd..0ccb80ea 100644 --- a/dbwind/DBWdisplay.c +++ b/dbwind/DBWdisplay.c @@ -418,7 +418,7 @@ DBWredisplay(w, rootArea, clipArea) /* Set style information beforehand */ GrSetStuff(STYLE_LABEL); (void) DBTreeSrLabels(&scontext, &DBAllTypeBits, bitMask, - (TerminalPath *) NULL, TF_LABEL_DISPLAY, + (TerminalPath *) NULL, TF_LABEL_DISPLAY | TF_LABEL_ATTACH, dbwLabelFunc, (ClientData) NULL); GrClipTo(&rootClip); } diff --git a/tcltk/wrapper.tcl b/tcltk/wrapper.tcl index 563778d5..271d2cd6 100644 --- a/tcltk/wrapper.tcl +++ b/tcltk/wrapper.tcl @@ -629,7 +629,7 @@ proc magic::cursorview {win} { return } set framename [winfo parent $win] - if {[catch {set cr [cif scale out]}]} {return} + if {[catch {set cr [*bypass cif scale out]}]} {return} if {$cr == 0} {return} set olst [${win} cursor internal] From 715843ca2a037530ebb38e4bd1d2fc17a346d276 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 17 Feb 2020 10:25:45 -0500 Subject: [PATCH 098/121] Changed the script drc.tcl into two routines for DRC load and save, and merged the contents into drcmgr.tcl, with a new button in the DRC manager for saving the DRC contents. Loading is somewhat less useful since the DRC error tiles are interactive. The DRC manager still has the issue that every checked edge becomes a separate entry; this is an artifact of the way the DRC checker works, but it creates large numbers of error areas, many of which are redundant. --- tcltk/Makefile | 1 - tcltk/drc.tcl | 46 -------------------- tcltk/drcmgr.tcl | 107 +++++++++++++++++++++++++++++++++++++++++++++- tcltk/wrapper.tcl | 2 +- 4 files changed, 107 insertions(+), 49 deletions(-) delete mode 100644 tcltk/drc.tcl diff --git a/tcltk/Makefile b/tcltk/Makefile index a6619678..5ff09b05 100644 --- a/tcltk/Makefile +++ b/tcltk/Makefile @@ -24,7 +24,6 @@ TCL_FILES = \ tools.tcl \ mazeroute.tcl \ strip_reflibs.tcl \ - drc.tcl \ toolkit.tcl \ toolkit_rev0.tcl \ bsitools.tcl \ diff --git a/tcltk/drc.tcl b/tcltk/drc.tcl deleted file mode 100644 index 3820b925..00000000 --- a/tcltk/drc.tcl +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/tclsh -#---------------------------------------------- -# Dump a file of DRC errors from magic -#---------------------------------------------- -namespace path {::tcl::mathop ::tcl::mathfunc} - -magic::suspendall -set fout [open "drc.out" w] -set oscale [cif scale out] - -select top cell -set origcell [cellname list self] -drc check -set celllist [drc list count] -puts stdout "celllist is $celllist" -puts stdout "" -flush stdout -foreach pair $celllist { - set cellname [lindex $pair 0] - set count [lindex $pair 1] - puts stdout "loading $cellname" - flush stdout - - load $cellname - select top cell - puts $fout "$cellname $count" - puts $fout "----------------------------------------" - set drcresult [drc listall why] - foreach {errtype coordlist} $drcresult { - puts $fout $errtype - puts $fout "----------------------------------------" - foreach coord $coordlist { - set bllx [* $oscale [lindex $coord 0]] - set blly [* $oscale [lindex $coord 1]] - set burx [* $oscale [lindex $coord 2]] - set bury [* $oscale [lindex $coord 3]] - set coords [format "%.3f %.3f %.3f %.3f" $bllx $blly $burx $bury] - puts $fout "$coords" - } - puts $fout "----------------------------------------" - } - puts $fout "" -} -close $fout -load $origcell -magic::resumeall diff --git a/tcltk/drcmgr.tcl b/tcltk/drcmgr.tcl index abf9277f..3f46203e 100644 --- a/tcltk/drcmgr.tcl +++ b/tcltk/drcmgr.tcl @@ -101,11 +101,13 @@ proc magic::makedrcmanager { mgrpath } { -command {magic::drccallback update} button ${mgrpath}.actionbar.last -text "Last" -command {magic::drccallback last} button ${mgrpath}.actionbar.next -text "Next" -command {magic::drccallback next} + button ${mgrpath}.actionbar.save -text "Save" -command {magic::drc_save_report} button ${mgrpath}.actionbar.zoom -text "Zoom" -command {magic::drccallback zoom} pack ${mgrpath}.actionbar.update -side left pack ${mgrpath}.actionbar.last -side left pack ${mgrpath}.actionbar.next -side left + pack ${mgrpath}.actionbar.save -side left pack ${mgrpath}.actionbar.zoom -side right label ${mgrpath}.target.name -text "Target window:" @@ -150,7 +152,6 @@ proc magic::adddrcentry {key valuelist} { } } - #-------------------------------------------------------------- # The cell manager window main callback function #-------------------------------------------------------------- @@ -193,3 +194,107 @@ proc magic::drcmanager {{option "update"}} { } ;# (if Tk version 8.5) +#--------------------------------------------------- +# Alternative way to view/save DRC errors in magic. +# Dump a text file of errors and positions. Note +# that the dump, using "drc listall why", enumerates +# every single edge check and is therefore more +# detailed than the areas declared by "drc count" +# or enumerated in "drc find". +#--------------------------------------------------- + +proc magic::drc_save_report {{cellname ""} {outfile ""}} { + + if {$outfile == ""} {set outfile "drc.out"} + + set fout [open $outfile w] + set oscale [cif scale out] + + # magic::suspendall + + if {$cellname == ""} { + select top cell + set cellname [cellname list self] + set origname "" + } else { + set origname [cellname list self] + puts stdout "loading $cellname\n" + flush stdout + + load $cellname + select top cell + } + + drc check + set count [drc list count] + + puts $fout "$cellname $count" + puts $fout "----------------------------------------" + set drcresult [drc listall why] + foreach {errtype coordlist} $drcresult { + puts $fout $errtype + puts $fout "----------------------------------------" + foreach coord $coordlist { + set bllx [expr {$oscale * [lindex $coord 0]}] + set blly [expr {$oscale * [lindex $coord 1]}] + set burx [expr {$oscale * [lindex $coord 2]}] + set bury [expr {$oscale * [lindex $coord 3]}] + set coords [format " %.3f %.3f %.3f %.3f" $bllx $blly $burx $bury] + puts $fout "$coords" + } + puts $fout "----------------------------------------" + } + puts $fout "" + + if {$origname != ""} { + load $origname + } + + # magic::resumeall + + close $fout + puts stdout "done with $outfile\n" + flush stdout +} + +#--------------------------------------------------- +# Read back a dumped file of DRC errors. This is of +# limited use, as any layout should have DRC errors +# already marked. This routine loads errors into +# "feedback" areas, which is redundant to the error +# tiles. However, feedback areas are more precise, +# as they mark the error area at each checked edge +#--------------------------------------------------- + +proc magic::drc_load_report {{drc_file ""}} { + + if {$drc_file == ""} { + set drc_file "drc.out" + } + set fin [open $drc_file r] + + puts stdout "Reading $drc_file\n" + flush stdout + + magic::suspendall + + set error_text "" + while {[gets $fin line] >= 0} { + if {[string first " " $line] == 0} { + if [regexp { ([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+)} $line lmatch llx lly urx ury] { + feedback add "$error_text" vert_highlights ${llx}um ${lly}um \ + ${llx}um ${ury}um ${urx}um ${ury}um ${urx}um ${lly}um + } + } elseif {[string first "-" $line] != 0} { + set error_text $line + } + } + magic::resumeall + + close $fin + + puts stdout "Done.\n" + puts stdout "Use \"feedback find\" to enumerate errors.\n" + flush stdout +} + diff --git a/tcltk/wrapper.tcl b/tcltk/wrapper.tcl index 271d2cd6..49936c8c 100644 --- a/tcltk/wrapper.tcl +++ b/tcltk/wrapper.tcl @@ -1,5 +1,5 @@ # This is the "Magic wrapper". -# It's main purpose is to redefine the "openwindow" command in magic so that +# Its main purpose is to redefine the "openwindow" command in magic so that # opening a new window creates a window wrapped by a GUI interface. # # Written by Tim Edwards, August 23, 2002. From 25724211620cb026dd791eded428cad75c835488 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 17 Feb 2020 15:13:54 -0500 Subject: [PATCH 099/121] Added new option setting Opts(toolsize) that makes the toolbar icons scale with the given size (default 16). This can be put in the site.def or .magicrc file as, e.g., "set Opts(toolsize) 32". This is the first part of an attempt to get everything to scale properly on ultra-high- resolution monitors. --- tcltk/wrapper.tcl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tcltk/wrapper.tcl b/tcltk/wrapper.tcl index 49936c8c..3252fea0 100644 --- a/tcltk/wrapper.tcl +++ b/tcltk/wrapper.tcl @@ -537,6 +537,7 @@ set Opts(crosshair) 0 set Opts(hidelocked) 0 set Opts(hidespecial) 0 set Opts(toolbar) 0 +set Opts(toolsize) 16 set Opts(drc) 1 set Opts(autobuttontext) 1 @@ -720,18 +721,21 @@ proc magic::toolupdate {win {yesno "yes"} {layerlist "none"}} { # Generate the toolbar images for a technology proc magic::maketoolimages {} { + global Opts + + set tsize $Opts(toolsize) # Generate a layer image for "space" that will be used when layers are # invisible. - image create layer img_space -name none + image create layer img_space -name none -width $tsize -height $tsize set all_layers [concat {errors labels subcell} [magic::tech layer "*"]] foreach layername $all_layers { - image create layer img_$layername -name $layername + image create layer img_$layername -name $layername -width $tsize -height $tsize image create layer pale_$layername -name $layername \ - -disabled true -icon 23 + -disabled true -icon 23 -width $tsize -height $tsize } } From 6049b7e00e288d7bb57d962300610281b21756da Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 17 Feb 2020 16:51:30 -0500 Subject: [PATCH 100/121] Further dealing with retinal displays: The scrollbars and related glyphs now scale with Opts(scale), which is a zoom scalefactor (default 1), and Opts(toolscale) sets an independent sizing for the toolbar icons, which is multiplied by the Opts(scale) scalefactor. Also: Added GR_LIBS to the link options for magicexec and magicdnull, to avoid compile-time problems on some systems (thank you to Charlene of OpenBSD for the patch!). --- magic/Makefile | 2 +- magic/bitmaps/down.png | Bin 0 -> 290 bytes magic/bitmaps/left.png | Bin 0 -> 291 bytes magic/bitmaps/right.png | Bin 0 -> 289 bytes magic/bitmaps/up.png | Bin 0 -> 290 bytes magic/bitmaps/zoom.png | Bin 0 -> 276 bytes tcltk/Makefile | 6 ++- tcltk/wrapper.tcl | 95 ++++++++++++++++++++++++++-------------- 8 files changed, 67 insertions(+), 36 deletions(-) create mode 100644 magic/bitmaps/down.png create mode 100644 magic/bitmaps/left.png create mode 100644 magic/bitmaps/right.png create mode 100644 magic/bitmaps/up.png create mode 100644 magic/bitmaps/zoom.png diff --git a/magic/Makefile b/magic/Makefile index 2079bca5..4dc62515 100644 --- a/magic/Makefile +++ b/magic/Makefile @@ -19,7 +19,7 @@ EXTRA_LIBS = ${MAGICDIR}/cmwind/libcmwind.o ${MAGICDIR}/commands/libcommands.o \ ${MAGICDIR}/plow/libplow.o ${MAGICDIR}/utils/libutils.o \ ${MAIN_EXTRA_LIBS} -BITMAPS = up.xbm down.xbm left.xbm right.xbm zoom.xbm lock.xbm +BITMAPS = up.png down.png left.png right.png zoom.png lock.xbm DEST_XBM = $(BITMAPS:%=$(DESTDIR)${INSTALL_TCLDIR}/bitmaps/%) DFLAGS += -DMAGIC_DATE="\"`date`\"" -DCAD_DIR="${LIBDIR}" diff --git a/magic/bitmaps/down.png b/magic/bitmaps/down.png new file mode 100644 index 0000000000000000000000000000000000000000..78c995180b6f428b733ea99c8ed6cb8c0b2037de GIT binary patch literal 290 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4%JB>7u;-UBI?bVpxD28NCO+&S3Dk zz__fXwULpbQiP>m$K%LXpeEH4*NBpo#FA92@!;O_l%v literal 0 HcmV?d00001 diff --git a/magic/bitmaps/left.png b/magic/bitmaps/left.png new file mode 100644 index 0000000000000000000000000000000000000000..dd63f521c244b352b45a1b720c8043480dd02e23 GIT binary patch literal 291 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4%JB>7u;-UBI?bVpxD28NCO+1b=SGH7YyFz6Q5 z;|^oL$asaDVdFj4q7$B7^MJZkOI#yLQW8s2t&)pUffR$0fsui(fswAEd5EEzm5G^^ qfr+kxsg;4j^huHFC>nC}Q!>*kacg*X{^4z)1_n=8KbLh*2~7a=eorR= literal 0 HcmV?d00001 diff --git a/magic/bitmaps/right.png b/magic/bitmaps/right.png new file mode 100644 index 0000000000000000000000000000000000000000..4ae31e9c8a9e5fa3ed5a98ce2ba08c56beed6590 GIT binary patch literal 289 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4%JB>7u;-UBI?bVpxD28NCO+N1$1#t{3&#{_4-=zBos7JNLHKHUXu_V85l%cME*q4kei>9nO2EggI4N8SD*$4Pgg&ebxsLQ0LG?G{Qv*} literal 0 HcmV?d00001 diff --git a/magic/bitmaps/up.png b/magic/bitmaps/up.png new file mode 100644 index 0000000000000000000000000000000000000000..cbe449739f642a032b31865f9d89db956199e578 GIT binary patch literal 290 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4%JB>7u;-UBI?bVpxD28NCO+!C8<`)MX5lF!N|bKK-a)X*U&t~(9Fuvz{>aG}y12r&sy85}Sb4q9e0Mh_XK>z>% literal 0 HcmV?d00001 diff --git a/magic/bitmaps/zoom.png b/magic/bitmaps/zoom.png new file mode 100644 index 0000000000000000000000000000000000000000..7d0f4484bd9c2c09304652e061442d6f7638571c GIT binary patch literal 276 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4%JB>7u;-UBI?bVpxD28NCO+?an+uemJjk_iV$dUGRaSY+Oo}AFYeC>jO#6bln aPsvQH#I2!Wf0hwY1B0ilpUXO@geCyo)k?Vl literal 0 HcmV?d00001 diff --git a/tcltk/Makefile b/tcltk/Makefile index 5ff09b05..efa12d00 100644 --- a/tcltk/Makefile +++ b/tcltk/Makefile @@ -49,11 +49,13 @@ install-tcl: magicexec magicdnull ${BIN_FILES} ${TCL_FILES} magicexec: magicexec.c ${MAGICDIR}/defs.mak ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS_NOSTUB} ${LDFLAGS} magicexec.c \ - -o magicexec ${LD_RUN_PATH} ${LIBS} ${LIB_SPECS_NOSTUB} + -o magicexec ${LD_RUN_PATH} ${LIB_SPECS_NOSTUB} ${LIBS} \ + ${GR_LIBS} magicdnull: magicdnull.c ${MAGICDIR}/defs.mak ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS_NOSTUB} ${LDFLAGS} magicdnull.c \ - -o magicdnull ${LD_RUN_PATH} ${LIBS} ${LIB_SPECS_NOSTUB} + -o magicdnull ${LD_RUN_PATH} ${LIB_SPECS_NOSTUB} ${LIBS} \ + ${GR_LIBS} magic.tcl: magic.tcl.in ${MAGICDIR}/defs.mak sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g \ diff --git a/tcltk/wrapper.tcl b/tcltk/wrapper.tcl index 3252fea0..2758cd96 100644 --- a/tcltk/wrapper.tcl +++ b/tcltk/wrapper.tcl @@ -22,26 +22,43 @@ if {[lsearch [namespace children] ::tkshell] < 0} { catch {source ${CAD_ROOT}/magic/tcl/tkshell.tcl} } -# Button images +proc magic::makeglyphimages {} { + global Opts + global Glyph + global CAD_ROOT -set Glyph(up) [image create bitmap \ - -file ${CAD_ROOT}/magic/tcl/bitmaps/up.xbm \ - -background gray -foreground steelblue] -set Glyph(down) [image create bitmap \ - -file ${CAD_ROOT}/magic/tcl/bitmaps/down.xbm \ - -background gray -foreground steelblue] -set Glyph(left) [image create bitmap \ - -file ${CAD_ROOT}/magic/tcl/bitmaps/left.xbm \ - -background gray -foreground steelblue] -set Glyph(right) [image create bitmap \ - -file ${CAD_ROOT}/magic/tcl/bitmaps/right.xbm \ - -background gray -foreground steelblue] -set Glyph(zoom) [image create bitmap \ - -file ${CAD_ROOT}/magic/tcl/bitmaps/zoom.xbm \ - -background gray -foreground steelblue] -set Glyph(lock) [image create bitmap \ + # Check if glyphs exist---don't need to make them more than once + if {![catch {set Glyph(up)}]} {return} + + # Glyph images + + set gsize [expr {int($Opts(scale) * 13)}] + set gscale [expr {int($Opts(scale))}] + + image create photo stdglyph -file ${CAD_ROOT}/magic/tcl/bitmaps/up.png + image create photo Glyph(up) -width $gsize -height $gsize + Glyph(up) copy stdglyph -zoom $gscale + + image create photo stdglyph -file ${CAD_ROOT}/magic/tcl/bitmaps/down.png + image create photo Glyph(down) -width $gsize -height $gsize + Glyph(down) copy stdglyph -zoom $gscale + + image create photo stdglyph -file ${CAD_ROOT}/magic/tcl/bitmaps/left.png + image create photo Glyph(left) -width $gsize -height $gsize + Glyph(left) copy stdglyph -zoom $gscale + + image create photo stdglyph -file ${CAD_ROOT}/magic/tcl/bitmaps/right.png + image create photo Glyph(right) -width $gsize -height $gsize + Glyph(right) copy stdglyph -zoom $gscale + + image create photo stdglyph -file ${CAD_ROOT}/magic/tcl/bitmaps/zoom.png + image create photo Glyph(zoom) -width $gsize -height $gsize + Glyph(zoom) copy stdglyph -zoom $gscale + + image create bitmap Glyph(lock) \ -file ${CAD_ROOT}/magic/tcl/bitmaps/lock.xbm \ -background gray80 -foreground steelblue4] +} # Menu button callback functions @@ -537,7 +554,8 @@ set Opts(crosshair) 0 set Opts(hidelocked) 0 set Opts(hidespecial) 0 set Opts(toolbar) 0 -set Opts(toolsize) 16 +set Opts(scale) 1.0 +set Opts(toolscale) 1.0 set Opts(drc) 1 set Opts(autobuttontext) 1 @@ -723,7 +741,8 @@ proc magic::toolupdate {win {yesno "yes"} {layerlist "none"}} { proc magic::maketoolimages {} { global Opts - set tsize $Opts(toolsize) + # Tool size expands with the GUI scale but can also be expanded independently. + set tsize [expr {int($Opts(scale) * $Opts(toolscale) * 16)}] # Generate a layer image for "space" that will be used when layers are # invisible. @@ -900,6 +919,8 @@ proc magic::techrebuild {winpath {cmdstr ""}} { # current view in magic (in pixels) proc magic::setscrollvalues {win} { + global Opts + set svalues [${win} view get] set bvalues [${win} view bbox] @@ -926,16 +947,19 @@ proc magic::setscrollvalues {win} { set ya [expr { $wheight - $ya }] set yb [expr { $wheight - $yb }] - ${framename}.xscroll.bar coords slider $xa 2 $xb 15 - ${framename}.yscroll.bar coords slider 2 $ya 15 $yb + set swidth [expr {int($Opts(scale) * 13)}] + set slength [expr {$swidth + 2}] + + ${framename}.xscroll.bar coords slider $xa 2 $xb $slength + ${framename}.yscroll.bar coords slider 2 $ya $slength $yb set xb [expr { 1 + ($xa + $xb) / 2 }] set xa [expr { $xb - 2 }] - ${framename}.xscroll.bar coords centre $xa 4 $xb 13 + ${framename}.xscroll.bar coords centre $xa 4 $xb $swidth set yb [expr { 1 + ($ya + $yb) / 2 }] set ya [expr { $yb - 2 }] - ${framename}.yscroll.bar coords centre 4 $ya 13 $yb + ${framename}.yscroll.bar coords centre 4 $ya $swidth $yb } # Procedure to update scrollbars in response to an internal command @@ -1019,6 +1043,9 @@ proc magic::dragscroll { w v orient } { proc magic::makescrollbar { fname orient win } { global scale global Glyph + global Opts + + set swidth [expr {int($Opts(scale) * 13)}] set scale($orient,update) 0 set scale($orient,origin) 0 @@ -1026,19 +1053,19 @@ proc magic::makescrollbar { fname orient win } { # To be done: add glyphs for the arrows if { "$orient" == "x" } { - canvas ${fname}.bar -height 13 -relief sunken -borderwidth 1 - button ${fname}.lb -image $Glyph(left) -borderwidth 1 \ + canvas ${fname}.bar -height $swidth -relief sunken -borderwidth 1 + button ${fname}.lb -image Glyph(left) -borderwidth 1 \ -command "${win} scroll left .1 w" - button ${fname}.ub -image $Glyph(right) -borderwidth 1 \ + button ${fname}.ub -image Glyph(right) -borderwidth 1 \ -command "${win} scroll right .1 w" pack ${fname}.lb -side left pack ${fname}.bar -fill $orient -expand true -side left pack ${fname}.ub -side right } else { - canvas ${fname}.bar -width 13 -relief sunken -borderwidth 1 - button ${fname}.lb -image $Glyph(down) -borderwidth 1 \ + canvas ${fname}.bar -width $swidth -relief sunken -borderwidth 1 + button ${fname}.lb -image Glyph(down) -borderwidth 1 \ -command "${win} scroll down .1 w" - button ${fname}.ub -image $Glyph(up) -borderwidth 1 \ + button ${fname}.ub -image Glyph(up) -borderwidth 1 \ -command "${win} scroll up .1 w" pack ${fname}.ub pack ${fname}.bar -fill $orient -expand true @@ -1054,7 +1081,7 @@ proc magic::makescrollbar { fname orient win } { # Create a small mark in the center of the scrolling rectangle which aids # in determining how much the window is being scrolled when the full # scrollbar extends past the window edges. - ${fname}.bar create rect 4 4 13 13 -fill black -width 0 -tag centre + ${fname}.bar create rect 4 4 $swidth $swidth -fill black -width 0 -tag centre ${fname}.bar bind centre "magic::setscroll %W %$orient $orient" ${fname}.bar bind centre "magic::scrollview %W $win $orient" ${fname}.bar bind centre "magic::dragscroll %W %$orient $orient" @@ -1127,12 +1154,14 @@ proc magic::openwrapper {{cell ""} {framename ""}} { pack ${framename}.pane -side top -fill both -expand true - frame ${layoutframe}.xscroll -height 13 - frame ${layoutframe}.yscroll -width 13 + set swidth [expr {int($Opts(scale) * 13)}] + frame ${layoutframe}.xscroll -height $swidth + frame ${layoutframe}.yscroll -width $swidth + magic::makeglyphimages magic::makescrollbar ${layoutframe}.xscroll x ${winname} magic::makescrollbar ${layoutframe}.yscroll y ${winname} - button ${layoutframe}.zb -image $Glyph(zoom) -borderwidth 1 -command "${winname} zoom 2" + button ${layoutframe}.zb -image Glyph(zoom) -borderwidth 1 -command "${winname} zoom 2" # Add bindings for mouse buttons 2 and 3 to the zoom button bind ${layoutframe}.zb "${winname} zoom 0.5" From 2db6a6849a22aae2b3cc149c2a68b08d8d515e6b Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 19 Feb 2020 14:25:58 -0500 Subject: [PATCH 101/121] Finally rid myself of the C preprocessor. Took a moderately-developed preproc.py script from another project. Had to further develop it to get around the amazingly complicated preprocessor usage in the scmos subdirectory. Needed to add handling of parameterized definitions; could not figure out how to align the syntax used in scmos/extract_template with any consistent syntax. Gave up and rewrote some of the contents of extract_template to avoid the more ambiguous usage. All of this is to support a completely deprecated scmos.tech. However, it does avoid both the M4 and cpp preprocessors altogether. Also did auto-detection of python3 in the configure script for use of the preproc.py preprocessor, and applied the same preprocessor to the macro definitions. --- magic/Makefile | 2 +- scmos/Makefile | 27 +- scmos/extract_template/scmosExt.tech.in | 14 +- .../extract_template/scmosExt060_orb.tech.in | 6 +- scmos/extract_template/scmosExt100.tech.in | 4 +- .../extract_template/scmosExt14b-sub.tech.in | 30 +- scmos/extract_template/scmosExt14b-tm.tech.in | 30 +- .../extract_template/scmosExt26b-sub.tech.in | 30 +- scmos/extract_template/scmosExt26b.tech.in | 30 +- scmos/extract_template/scmosExt34.tech.in | 16 +- scmos/test.out | 3256 ----------------- scripts/configure | 224 +- scripts/configure.in | 111 +- scripts/defs.mak.in | 3 +- scripts/preproc.py | 230 +- 15 files changed, 436 insertions(+), 3577 deletions(-) diff --git a/magic/Makefile b/magic/Makefile index 4dc62515..bb38fdcc 100644 --- a/magic/Makefile +++ b/magic/Makefile @@ -39,7 +39,7 @@ tclmagic${SHDLIB_EXT}: ${EXTRA_LIBS} -lc ${LIBS} ${LIB_SPECS} ${LDFLAGS} proto.magicrc: proto.magicrc.in - ${SCPP} ${GR_DFLAGS} ${DFLAGS} proto.magicrc.in > proto.magicrc + ${MCPP} ${GR_DFLAGS} ${DFLAGS} proto.magicrc.in > proto.magicrc install: $(DESTDIR)${INSTALL_BINDIR}/${MODULE}${EXEEXT} $(DESTDIR)${INSTALL_SYSDIR}/.magicrc \ $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro diff --git a/scmos/Makefile b/scmos/Makefile index dd513e1a..dc30a1e8 100644 --- a/scmos/Makefile +++ b/scmos/Makefile @@ -17,9 +17,7 @@ MAGICDIR = .. include ${MAGICDIR}/defs.mak -SC_M4 = ${M4} -#SC_CPP = ${MCPP} -I./extract_template -SC_CPP = ${SCPP} -I./extract_template +SC_PP = ${MCPP} -I./extract_template FILES = mos.7bit.dstyle mos.7bit.std.cmap \ mos.24bit.dstyle mos.24bit.std.cmap \ @@ -61,30 +59,33 @@ install: all ${CP} $$i $(DESTDIR)${INSTALL_SYSDIR}; done scmos.tech: $(OBJS) - sed -e 's/\\/\\\\/' scmos.tech.in > scmos.tech.out - $(SC_CPP) -DV5 -DSTANDARD scmos.tech.out > scmos.tech + $(MSED) scmos.tech.in > scmos.tech.out + $(SC_PP) -DV5 -DSTANDARD scmos.tech.out > scmos.tech $(RM) scmos.tech.out scmos-tm.tech: $(OBJS) - sed -e 's/\\/\\\\/' scmos.tech.in > scmos.tech.out - $(SC_CPP) -DV5 -DHPTECH -DTIGHTMETAL scmos.tech.out > scmos-tm.tech + $(MSED) scmos.tech.in > scmos.tech.out + cat scmos.tech.in > scmos.tech.out + $(SC_PP) -DV5 -DHPTECH -DTIGHTMETAL scmos.tech.out > scmos-tm.tech $(RM) scmos.tech.out scmos-sub.tech: $(OBJS) - sed -e 's/\\/\\\\/' scmos.tech.in > scmos.tech.out - $(SC_CPP) -DV5 -DSUBMICRON scmos.tech.out > scmos-sub.tech + $(MSED) scmos.tech.in > scmos.tech.out + cat scmos.tech.in > scmos.tech.out + $(SC_PP) -DV5 -DSUBMICRON scmos.tech.out > scmos-sub.tech $(RM) scmos.tech.out scmosWR.tech: $(OBJS) - sed -e 's/\\/\\\\/' scmos.tech.in > scmos.tech.out - $(SC_CPP) -DV5 -DSTANDARD -DWELL_ROUTE_CHECK scmos.tech.out > scmosWR.tech + $(MSED) scmos.tech.in > scmos.tech.out + cat scmos.tech.in > scmos.tech.out + $(SC_PP) -DV5 -DSTANDARD -DWELL_ROUTE_CHECK scmos.tech.out > scmosWR.tech $(RM) scmos.tech.out minimum.tech: minimum.tech.in - $(SC_M4) minimum.tech.in > minimum.tech + $(SC_PP) minimum.tech.in > minimum.tech gdsquery.tech: gdsquery.tech.in - $(SC_M4) gdsquery.tech.in > gdsquery.tech + $(SC_PP) gdsquery.tech.in > gdsquery.tech $(CIFin): $(CIFout): diff --git a/scmos/extract_template/scmosExt.tech.in b/scmos/extract_template/scmosExt.tech.in index 9492f356..942cf189 100644 --- a/scmos/extract_template/scmosExt.tech.in +++ b/scmos/extract_template/scmosExt.tech.in @@ -23,8 +23,7 @@ || defined (M1Res) \ || defined (PolyRes) \ || defined (M2Res) \ - || defined (M3Res) \ - || defined (nothing) + || defined (M3Res) THERE_IS_AN_ERROR_SOME_LOCAL_CAPACITANCE_DEFINITIONS_HAVE_ALREADY_BEEN_DEFINED #endif @@ -45,21 +44,20 @@ THERE_IS_AN_ERROR_SOME_LOCAL_CAPACITANCE_DEFINITIONS_HAVE_ALREADY_BEEN_DEFINED #define M3Res (metal3,pad/m3,via2/m3) -#define nothing - /* Use macros for planeorder and sideoverlap for backwards compatibility */ #if defined(V5) -#define planeOrder(l,ord) planeorder l ord +#define planeOrder(name,idx) planeorder name idx #define noplaneOrdering noplaneordering -#define sideOverlap(l1,sep,l2,cap,shield)\ +#define sideOverlap(l1,sep,l2,cap,shield) \ sideoverlap l1 sep l2 cap shield +#define Comma , #else /* V5 */ -#define planeOrder(l,ord) +#define planeOrder(name,idx) #define noplaneOrdering -#define sideOverlap(l1,sep,l2,cap,shield)\ +#define sideOverlap(l1,sep,l2,cap,shield) \ sideoverlap l1 sep l2 cap #endif /* V5 */ diff --git a/scmos/extract_template/scmosExt060_orb.tech.in b/scmos/extract_template/scmosExt060_orb.tech.in index 9620ffad..265e6223 100644 --- a/scmos/extract_template/scmosExt060_orb.tech.in +++ b/scmos/extract_template/scmosExt060_orb.tech.in @@ -52,8 +52,8 @@ style lambda_irsim=0.6(orb_scne12) overlap M1Cap PolyCap 19 perimc M1Cap ~M1Cap 41 - sideOverlap(M1Cap, ~M1Cap, allWell, 41, (PolyCap,PNplusCap)) - sideOverlap(M1Cap, ~M1Cap, PNplusCap, 41, nothing) + sideOverlap(M1Cap, ~M1Cap, allWell, 41, PolyCapCommaPNplusCap) + sideOverlap(M1Cap, ~M1Cap, PNplusCap, 41, ) /* ------------------------------------------------- */ @@ -65,7 +65,7 @@ style lambda_irsim=0.6(orb_scne12) overlap M2Cap M1Cap 14 perimc M2Cap ~M2Cap 42 - sideOverlap(M2Cap, ~M2Cap, allWell, 42, (M1Cap,PolyCap,PNplusCap) ) + sideOverlap(M2Cap, ~M2Cap, allWell, 42, M1CapCommaPolyCapCommaPNplusCap ) sideOverlap(M2Cap, ~M2Cap, PNplusCap, 42, M1Cap) /* ------------------------------------------------- */ diff --git a/scmos/extract_template/scmosExt100.tech.in b/scmos/extract_template/scmosExt100.tech.in index 1ba88042..17a1d823 100644 --- a/scmos/extract_template/scmosExt100.tech.in +++ b/scmos/extract_template/scmosExt100.tech.in @@ -43,7 +43,7 @@ style lambda_irsim=1.0(scna20_orb) areacap poly2,ec/a 50 perimc PolyCap ~PolyCap 80 - sideOverlap(PolyCap, ~PolyCap, allWell, 80, nothing) + sideOverlap(PolyCap, ~PolyCap, allWell, 80, ) /* ------------------------------------------------- */ @@ -172,7 +172,7 @@ style lambda=1.0(scpe20_orb) overlap PolyCap allWell 57 perimc PolyCap ~PolyCap 168 - sideOverlap(PolyCap, ~PolyCap, allWell, 168, nothing) + sideOverlap(PolyCap, ~PolyCap, allWell, 168, ) /* ------------------------------------------------- */ diff --git a/scmos/extract_template/scmosExt14b-sub.tech.in b/scmos/extract_template/scmosExt14b-sub.tech.in index 0099dcad..400fc3a6 100644 --- a/scmos/extract_template/scmosExt14b-sub.tech.in +++ b/scmos/extract_template/scmosExt14b-sub.tech.in @@ -56,10 +56,10 @@ style lambda_irsim=0.30 overlap PolyCap allWell 8.2 perimc PolyCap ~PolyCap 12.6 - sideOverlap(PolyCap, ~PolyCap, allWell, 12.6, nothing) - sideOverlap(PolyCap, ~PolyCap, M1Cap, 5.7, nothing) + sideOverlap(PolyCap, ~PolyCap, allWell, 12.6, ) + sideOverlap(PolyCap, ~PolyCap, M1Cap, 5.7, ) sideOverlap(PolyCap, ~PolyCap, M2Cap, 2.7, M1Cap) - sideOverlap(PolyCap, ~PolyCap, M3Cap, 1.8, (M1Cap,M2Cap)) + sideOverlap(PolyCap, ~PolyCap, M3Cap, 1.8, M1CapCommaM2Cap) sidewall PolyCap ~PolyCap ~PolyCap PolyCap 7.2 /* ------------------------------------------------- */ @@ -72,10 +72,10 @@ style lambda_irsim=0.30 overlap M1Cap PolyCap 5.7 perimc M1Cap ~M1Cap 15 - sideOverlap(M1Cap, ~M1Cap, allWell, 15, (PolyCap,PNplusCap)) - sideOverlap(M1Cap, ~M1Cap, PNplusCap, 17.4, nothing) - sideOverlap(M1Cap, ~M1Cap, PolyCap, 17.4, nothing) - sideOverlap(M1Cap, ~M1Cap, M2Cap, 8.7, nothing) + sideOverlap(M1Cap, ~M1Cap, allWell, 15, PolyCapCommaPNplusCap) + sideOverlap(M1Cap, ~M1Cap, PNplusCap, 17.4, ) + sideOverlap(M1Cap, ~M1Cap, PolyCap, 17.4, ) + sideOverlap(M1Cap, ~M1Cap, M2Cap, 8.7, ) sideOverlap(M1Cap, ~M1Cap, M3Cap, 4.8, M2Cap) sidewall M1Cap ~M1Cap ~M1Cap M1Cap 19.2 @@ -90,11 +90,11 @@ style lambda_irsim=0.30 overlap M2Cap M1Cap 3.5 perimc M2Cap ~M2Cap 12.3 - sideOverlap(M2Cap, ~M2Cap, allWell, 12.3, (M1Cap,PolyCap,PNplusCap) ) + sideOverlap(M2Cap, ~M2Cap, allWell, 12.3, M1CapCommaPolyCapCommaPNplusCap ) sideOverlap(M2Cap, ~M2Cap, PNplusCap, 12.9, M1Cap) sideOverlap(M2Cap, ~M2Cap, PolyCap, 12.9, M1Cap) - sideOverlap(M2Cap, ~M2Cap, M1Cap, 15, nothing) - sideOverlap(M2Cap, ~M2Cap, M3Cap, 10.8, nothing) + sideOverlap(M2Cap, ~M2Cap, M1Cap, 15, ) + sideOverlap(M2Cap, ~M2Cap, M3Cap, 10.8, ) sidewall M2Cap ~M2Cap ~M2Cap M2Cap 21.6 /* ------------------------------------------------- */ @@ -109,11 +109,11 @@ style lambda_irsim=0.30 overlap M3Cap M2Cap 3.3 perimc M3Cap ~M3Cap 12.3 - sideOverlap(M3Cap, ~M3Cap, allWell, 12.3, (PNplusCap,PolyCap,M1Cap,M2Cap)) - sideOverlap(M3Cap, ~M3Cap, PNplusCap, 12.9, (M1Cap,M2Cap)) - sideOverlap(M3Cap, ~M3Cap, PolyCap, 12.9, (M1Cap,M2Cap)) - sideOverlap(M3Cap, ~M3Cap, M1Cap, 15.3, (M2Cap)) - sideOverlap(M3Cap, ~M3Cap, M2Cap, 19.2, nothing) + sideOverlap(M3Cap, ~M3Cap, allWell, 12.3, PNplusCapCommaPolyCapCommaM1CapCommaM2Cap) + sideOverlap(M3Cap, ~M3Cap, PNplusCap, 12.9, M1CapCommaM2Cap) + sideOverlap(M3Cap, ~M3Cap, PolyCap, 12.9, M1CapCommaM2Cap) + sideOverlap(M3Cap, ~M3Cap, M1Cap, 15.3, M2Cap) + sideOverlap(M3Cap, ~M3Cap, M2Cap, 19.2, ) sidewall M3Cap ~M3Cap ~M3Cap M3Cap 34.3 /* ------------------------------------------------- */ diff --git a/scmos/extract_template/scmosExt14b-tm.tech.in b/scmos/extract_template/scmosExt14b-tm.tech.in index 3de6d854..8937cdeb 100644 --- a/scmos/extract_template/scmosExt14b-tm.tech.in +++ b/scmos/extract_template/scmosExt14b-tm.tech.in @@ -56,10 +56,10 @@ style lambda_irsim=0.35 overlap PolyCap allWell 11.1 perimc PolyCap ~PolyCap 14.7 - sideOverlap(PolyCap, ~PolyCap, allWell, 14.7, nothing) - sideOverlap(PolyCap, ~PolyCap, M1Cap, 6.7, nothing) + sideOverlap(PolyCap, ~PolyCap, allWell, 14.7, ) + sideOverlap(PolyCap, ~PolyCap, M1Cap, 6.7, ) sideOverlap(PolyCap, ~PolyCap, M2Cap, 3.2, M1Cap) - sideOverlap(PolyCap, ~PolyCap, M3Cap, 2.1, (M1Cap,M2Cap)) + sideOverlap(PolyCap, ~PolyCap, M3Cap, 2.1, M1CapCommaM2Cap) sidewall PolyCap ~PolyCap ~PolyCap PolyCap 8.4 /* ------------------------------------------------- */ @@ -72,10 +72,10 @@ style lambda_irsim=0.35 overlap M1Cap PolyCap 7.7 perimc M1Cap ~M1Cap 17.5 - sideOverlap(M1Cap, ~M1Cap, allWell, 17.5, (PolyCap,PNplusCap)) - sideOverlap(M1Cap, ~M1Cap, PNplusCap, 20.3, nothing) - sideOverlap(M1Cap, ~M1Cap, PolyCap, 20.3, nothing) - sideOverlap(M1Cap, ~M1Cap, M2Cap, 10.2, nothing) + sideOverlap(M1Cap, ~M1Cap, allWell, 17.5, PolyCapCommaPNplusCap) + sideOverlap(M1Cap, ~M1Cap, PNplusCap, 20.3, ) + sideOverlap(M1Cap, ~M1Cap, PolyCap, 20.3, ) + sideOverlap(M1Cap, ~M1Cap, M2Cap, 10.2, ) sideOverlap(M1Cap, ~M1Cap, M3Cap, 5.6, M2Cap) sidewall M1Cap ~M1Cap ~M1Cap M1Cap 22.4 @@ -90,11 +90,11 @@ style lambda_irsim=0.35 overlap M2Cap M1Cap 4.7 perimc M2Cap ~M2Cap 14.4 - sideOverlap(M2Cap, ~M2Cap, allWell, 14.4, (M1Cap,PolyCap,PNplusCap) ) + sideOverlap(M2Cap, ~M2Cap, allWell, 14.4, M1CapCommaPolyCapCommaPNplusCap ) sideOverlap(M2Cap, ~M2Cap, PNplusCap, 15.1, M1Cap) sideOverlap(M2Cap, ~M2Cap, PolyCap, 15.1, M1Cap) - sideOverlap(M2Cap, ~M2Cap, M1Cap, 17.5, nothing) - sideOverlap(M2Cap, ~M2Cap, M3Cap, 12.6, nothing) + sideOverlap(M2Cap, ~M2Cap, M1Cap, 17.5, ) + sideOverlap(M2Cap, ~M2Cap, M3Cap, 12.6, ) sidewall M2Cap ~M2Cap ~M2Cap M2Cap 25.2 /* ------------------------------------------------- */ @@ -109,11 +109,11 @@ style lambda_irsim=0.35 overlap M3Cap M2Cap 4.5 perimc M3Cap ~M3Cap 14.4 - sideOverlap(M3Cap, ~M3Cap, allWell, 14.4, (PNplusCap,PolyCap,M1Cap,M2Cap)) - sideOverlap(M3Cap, ~M3Cap, PNplusCap, 15.1, (M1Cap,M2Cap)) - sideOverlap(M3Cap, ~M3Cap, PolyCap, 15.1, (M1Cap,M2Cap)) - sideOverlap(M3Cap, ~M3Cap, M1Cap, 17.9, (M2Cap)) - sideOverlap(M3Cap, ~M3Cap, M2Cap, 22.4, nothing) + sideOverlap(M3Cap, ~M3Cap, allWell, 14.4, PNplusCapCommaPolyCapCommaM1CapCommaM2Cap) + sideOverlap(M3Cap, ~M3Cap, PNplusCap, 15.1, M1CapCommaM2Cap) + sideOverlap(M3Cap, ~M3Cap, PolyCap, 15.1, M1CapCommaM2Cap) + sideOverlap(M3Cap, ~M3Cap, M1Cap, 17.9, M2Cap) + sideOverlap(M3Cap, ~M3Cap, M2Cap, 22.4, ) sidewall M3Cap ~M3Cap ~M3Cap M3Cap 40 /* ------------------------------------------------- */ diff --git a/scmos/extract_template/scmosExt26b-sub.tech.in b/scmos/extract_template/scmosExt26b-sub.tech.in index 9bf9de6a..a636b162 100644 --- a/scmos/extract_template/scmosExt26b-sub.tech.in +++ b/scmos/extract_template/scmosExt26b-sub.tech.in @@ -47,10 +47,10 @@ style lambda_irsim=0.4 overlap PolyCap allWell 10 perimc PolyCap ~PolyCap 18 - sideOverlap(PolyCap, ~PolyCap, allWell, 18, nothing) - sideOverlap(PolyCap, ~PolyCap, M1Cap, 8, nothing) + sideOverlap(PolyCap, ~PolyCap, allWell, 18, ) + sideOverlap(PolyCap, ~PolyCap, M1Cap, 8, ) sideOverlap(PolyCap, ~PolyCap, M2Cap, 5, M1Cap) - sideOverlap(PolyCap, ~PolyCap, M3Cap, 3, (M1Cap,M2Cap)) + sideOverlap(PolyCap, ~PolyCap, M3Cap, 3, M1CapCommaM2Cap) sidewall PolyCap ~PolyCap ~PolyCap PolyCap 9 /* ------------------------------------------------- */ @@ -63,10 +63,10 @@ style lambda_irsim=0.4 overlap M1Cap PolyCap 9 perimc M1Cap ~M1Cap 18 - sideOverlap(M1Cap, ~M1Cap, allWell, 18, (PolyCap,PNplusCap)) - sideOverlap(M1Cap, ~M1Cap, PNplusCap, 20, nothing) - sideOverlap(M1Cap, ~M1Cap, PolyCap, 20, nothing) - sideOverlap(M1Cap, ~M1Cap, M2Cap, 10, nothing) + sideOverlap(M1Cap, ~M1Cap, allWell, 18, PolyCapCommaPNplusCap) + sideOverlap(M1Cap, ~M1Cap, PNplusCap, 20, ) + sideOverlap(M1Cap, ~M1Cap, PolyCap, 20, ) + sideOverlap(M1Cap, ~M1Cap, M2Cap, 10, ) sideOverlap(M1Cap, ~M1Cap, M3Cap, 6, M2Cap) sidewall M1Cap ~M1Cap ~M1Cap M1Cap 22 @@ -81,11 +81,11 @@ style lambda_irsim=0.4 overlap M2Cap M1Cap 6 perimc M2Cap ~M2Cap 15 - sideOverlap(M2Cap, ~M2Cap, allWell, 15, (M1Cap,PolyCap,PNplusCap) ) + sideOverlap(M2Cap, ~M2Cap, allWell, 15, M1CapCommaPolyCapCommaPNplusCap ) sideOverlap(M2Cap, ~M2Cap, PNplusCap, 16, M1Cap) sideOverlap(M2Cap, ~M2Cap, PolyCap, 16, M1Cap) - sideOverlap(M2Cap, ~M2Cap, M1Cap, 18, nothing) - sideOverlap(M2Cap, ~M2Cap, M3Cap, 8, nothing) + sideOverlap(M2Cap, ~M2Cap, M1Cap, 18, ) + sideOverlap(M2Cap, ~M2Cap, M3Cap, 8, ) sidewall M2Cap ~M2Cap ~M2Cap M2Cap 26 /* ------------------------------------------------- */ @@ -100,11 +100,11 @@ style lambda_irsim=0.4 overlap M3Cap M2Cap 6 perimc M3Cap ~M3Cap 14 - sideOverlap(M3Cap, ~M3Cap, allWell, 14, (PNplusCap,PolyCap,M1Cap,M2Cap)) - sideOverlap(M3Cap, ~M3Cap, PNplusCap, 14, (M1Cap,M2Cap)) - sideOverlap(M3Cap, ~M3Cap, PolyCap, 14, (M1Cap,M2Cap)) - sideOverlap(M3Cap, ~M3Cap, M1Cap, 16, (M2Cap)) - sideOverlap(M3Cap, ~M3Cap, M2Cap, 20, nothing) + sideOverlap(M3Cap, ~M3Cap, allWell, 14, PNplusCapCommaPolyCapCommaM1CapCommaM2Cap) + sideOverlap(M3Cap, ~M3Cap, PNplusCap, 14, M1CapCommaM2Cap) + sideOverlap(M3Cap, ~M3Cap, PolyCap, 14, M1CapCommaM2Cap) + sideOverlap(M3Cap, ~M3Cap, M1Cap, 16, M2Cap) + sideOverlap(M3Cap, ~M3Cap, M2Cap, 20, ) sidewall M3Cap ~M3Cap ~M3Cap M3Cap 40 /* ------------------------------------------------- */ diff --git a/scmos/extract_template/scmosExt26b.tech.in b/scmos/extract_template/scmosExt26b.tech.in index f9d22162..3d7ebe59 100644 --- a/scmos/extract_template/scmosExt26b.tech.in +++ b/scmos/extract_template/scmosExt26b.tech.in @@ -52,10 +52,10 @@ style lambda_irsim=0.5 overlap PolyCap allWell 15 perimc PolyCap ~PolyCap 22 - sideOverlap(PolyCap, ~PolyCap, allWell, 22, nothing) - sideOverlap(PolyCap, ~PolyCap, M1Cap, 10, nothing) + sideOverlap(PolyCap, ~PolyCap, allWell, 22, ) + sideOverlap(PolyCap, ~PolyCap, M1Cap, 10, ) sideOverlap(PolyCap, ~PolyCap, M2Cap, 6, M1Cap) - sideOverlap(PolyCap, ~PolyCap, M3Cap, 4, (M1Cap,M2Cap)) + sideOverlap(PolyCap, ~PolyCap, M3Cap, 4, M1CapCommaM2Cap) sidewall PolyCap ~PolyCap ~PolyCap PolyCap 11 /* ------------------------------------------------- */ @@ -68,10 +68,10 @@ style lambda_irsim=0.5 overlap M1Cap PolyCap 14 perimc M1Cap ~M1Cap 22 - sideOverlap(M1Cap, ~M1Cap, allWell, 22, (PolyCap,PNplusCap)) - sideOverlap(M1Cap, ~M1Cap, PNplusCap, 25, nothing) - sideOverlap(M1Cap, ~M1Cap, PolyCap, 25, nothing) - sideOverlap(M1Cap, ~M1Cap, M2Cap, 12, nothing) + sideOverlap(M1Cap, ~M1Cap, allWell, 22, PolyCapCommaPNplusCap) + sideOverlap(M1Cap, ~M1Cap, PNplusCap, 25, ) + sideOverlap(M1Cap, ~M1Cap, PolyCap, 25, ) + sideOverlap(M1Cap, ~M1Cap, M2Cap, 12, ) sideOverlap(M1Cap, ~M1Cap, M3Cap, 7, M2Cap) sidewall M1Cap ~M1Cap ~M1Cap M1Cap 27 @@ -86,11 +86,11 @@ style lambda_irsim=0.5 overlap M2Cap M1Cap 9 perimc M2Cap ~M2Cap 18 - sideOverlap(M2Cap, ~M2Cap, allWell, 18, (M1Cap,PolyCap,PNplusCap) ) + sideOverlap(M2Cap, ~M2Cap, allWell, 18, M1CapCommaPolyCapCommaPNplusCap ) sideOverlap(M2Cap, ~M2Cap, PNplusCap, 19, M1Cap) sideOverlap(M2Cap, ~M2Cap, PolyCap, 20, M1Cap) - sideOverlap(M2Cap, ~M2Cap, M1Cap, 23, nothing) - sideOverlap(M2Cap, ~M2Cap, M3Cap, 10, nothing) + sideOverlap(M2Cap, ~M2Cap, M1Cap, 23, ) + sideOverlap(M2Cap, ~M2Cap, M3Cap, 10, ) sidewall M2Cap ~M2Cap ~M2Cap M2Cap 33 /* ------------------------------------------------- */ @@ -105,11 +105,11 @@ style lambda_irsim=0.5 overlap M3Cap M2Cap 9 perimc M3Cap ~M3Cap 17 - sideOverlap(M3Cap, ~M3Cap, allWell, 17, (PNplusCap,PolyCap,M1Cap,M2Cap)) - sideOverlap(M3Cap, ~M3Cap, PNplusCap, 17, (M1Cap,M2Cap)) - sideOverlap(M3Cap, ~M3Cap, PolyCap, 17, (M1Cap,M2Cap)) - sideOverlap(M3Cap, ~M3Cap, M1Cap, 20, (M2Cap)) - sideOverlap(M3Cap, ~M3Cap, M2Cap, 25, nothing) + sideOverlap(M3Cap, ~M3Cap, allWell, 17, PNplusCapCommaPolyCapCommaM1CapCommaM2Cap) + sideOverlap(M3Cap, ~M3Cap, PNplusCap, 17, M1CapCommaM2Cap) + sideOverlap(M3Cap, ~M3Cap, PolyCap, 17, M1CapCommaM2Cap) + sideOverlap(M3Cap, ~M3Cap, M1Cap, 20, M2Cap) + sideOverlap(M3Cap, ~M3Cap, M2Cap, 25, ) sidewall M3Cap ~M3Cap ~M3Cap M3Cap 50 /* ------------------------------------------------- */ diff --git a/scmos/extract_template/scmosExt34.tech.in b/scmos/extract_template/scmosExt34.tech.in index 2909f0db..c0dca915 100644 --- a/scmos/extract_template/scmosExt34.tech.in +++ b/scmos/extract_template/scmosExt34.tech.in @@ -43,8 +43,8 @@ style lambda_irsim=0.6(hp) overlap PolyCap allWell 28 perimc PolyCap ~PolyCap 38 - sideOverlap(PolyCap, ~PolyCap, allWell, 38, nothing) - sideOverlap(PolyCap, ~PolyCap, M1Cap, 34, nothing) + sideOverlap(PolyCap, ~PolyCap, allWell, 38, ) + sideOverlap(PolyCap, ~PolyCap, M1Cap, 34, ) sideOverlap(PolyCap, ~PolyCap, M2Cap, 27, M1Cap) sidewall PolyCap ~PolyCap ~PolyCap PolyCap 15 @@ -57,10 +57,10 @@ style lambda_irsim=0.6(hp) overlap M1Cap PolyCap 46 perimc M1Cap ~M1Cap 33 - sideOverlap(M1Cap, ~M1Cap, allWell, 33, (PolyCap,PNplusCap)) - sideOverlap(M1Cap, ~M1Cap, PNplusCap, 33, nothing) - sideOverlap(M1Cap, ~M1Cap, PolyCap, 33, nothing) - sideOverlap(M1Cap, ~M1Cap, M2Cap, 28, nothing) + sideOverlap(M1Cap, ~M1Cap, allWell, 33, PolyCapCommaPNplusCap) + sideOverlap(M1Cap, ~M1Cap, PNplusCap, 33, ) + sideOverlap(M1Cap, ~M1Cap, PolyCap, 33, ) + sideOverlap(M1Cap, ~M1Cap, M2Cap, 28, ) sidewall M1Cap ~M1Cap ~M1Cap M1Cap 27 /* ------------------------------------------------- */ @@ -74,10 +74,10 @@ style lambda_irsim=0.6(hp) overlap M2Cap M1Cap 30 perimc M2Cap ~M2Cap 22 - sideOverlap(M2Cap, ~M2Cap, allWell, 22, (M1Cap,PolyCap,PNplusCap) ) + sideOverlap(M2Cap, ~M2Cap, allWell, 22, M1CapCommaPolyCapCommaPNplusCap ) sideOverlap(M2Cap, ~M2Cap, PNplusCap, 20, M1Cap) sideOverlap(M2Cap, ~M2Cap, PolyCap, 22, M1Cap) - sideOverlap(M2Cap, ~M2Cap, M1Cap, 28, nothing) + sideOverlap(M2Cap, ~M2Cap, M1Cap, 28, ) sidewall M2Cap ~M2Cap ~M2Cap M2Cap 33 /* ------------------------------------------------- */ diff --git a/scmos/test.out b/scmos/test.out index 5213039d..e69de29b 100644 --- a/scmos/test.out +++ b/scmos/test.out @@ -1,3256 +0,0 @@ -/* --------------------------------------------------------------------* - * * - * scmos.tech -- MOSIS Scalable CMOS (SCMOS) Magic technology file. * - * * - * MOSIS distribution Version 8.2 * - * * - * Defines the MOSIS 0.6/0.8/1.0/1.2/2.0 micron Scalable CMOS * - * (SCMOS) technology. * - * * - * (C) Copyright 1992, 1993, 1994, 1995 by * - * * - * Jen-I Pi pi@isi.edu * - * The MOSIS Service * - * USC Information Sciences Institute * - * 4676 Admiralty Way * - * Marina del Rey, CA 90292 * - * voice: (310) 822-1511 x640, fax: (310)823-5624 * - * * - * All Rights Reserved. * - * Last Modified Date: 04/26/1995 * - * * - * Permission to use, copy, modify, and distribute this technology * - * file and its associated documentation for any purpose and without * - * fee is hereby granted, provided that the above copyright notice * - * appears in all copies and that both that copyright notice and this * - * permission notice appear in supporting documentation, and that the * - * name of the University of Southern California not be used in * - * advertising or publicity pertaining to distribution of this * - * technology file without specific, written prior permission. * - * The University of Southern California makes no representations * - * about the suitability of this technology file for any purpose. * - * This technology file is provided "as is" without express or implied * - * warranty and the University of Southern California retains the * - * right to change its content at any time without notice any other * - * party. * - * * - * THE UNIVERSITY OF SOUTHERN CALIFORNIA DISCLAIMS ALL WARRANTIES WITH * - * REGARD TO THIS TECHNOLOGY FILE, INCLUDING ALL IMPLIED WARRANTIES OF * - * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF * - * SOUTHERN CALIFORNIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR * - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * - * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS TECHNOLOGY FILE. * - * * - * ------------------------------------------------------------------- */ - -/* --------------------------------------------------------------------* - * Some of the characteristics of this technology are: * - * * - * 1. 3 levels of metal - for HP's CMOS26B (lambda=0.5) and CMOS26G * - * (lambda=0.4) and CMOS14TB (lambda=0.35 or 0.3) processes * - * 3 levels of metal stack via - for IBM's CMSX2185 (lambda=0.4) * - * process * - * 2 levels of metal interconnection for all other technologies * - * 2. 2 levels of poly - for ORBIT's low-noise analog process * - * second poly is used for poly-capacitor or electrode fet (efet) * - * 3. Vertical NPN transistor, BCCD device, Floating-gate device for * - * ORBIT's low-noise anaolog process * - * 4. All contacts are composite (with the necessary enclosure) * - * 5. No stacked contacts (all contacts are to 1st-level metal) * - * 6. An open layer is added for fabrication of micromachined devices * - * as in Janet C. Marshall's paper in IEEE Circuit and Devices, * - * Vol. 8, N0. 6, 1992. * - * This layer is currently NOT available for standard MOSIS SCMOS * - * techonology installation. You need to define OPEN with the C- * - * preprocessor for installation. See README file for detail... * - * 7 A pstop layer is used also in micromachineing device fabrication * - * to stop the EDP etchant as used in Marshall's article. * - * 8 A Cap-well (cwell) for HP's CMOS34 (lambda=0.6) process, It is * - * used for consctruction of linear capacitors * - * Must be drawn explicitly * - * 9. Wells (Pwell or Nwell) can be implicit or explicit in the layout * - * and both types of diffusion must have well contacts * - *10. Painting Nwell over N-type diffusion will result in P-type * - * diffusion * - *11. Scalable with Default to be 2.0 micron rules for Nwell process * - *12. Substrate contacts must be 3 units away from gates * - *13. Stacked via supported through special compiled option -DSTACKVIA * - * for IBM process. * - * * - * Revision 8.2.8 (pi) * - * fix CCD CIF input style for "bd" layer. * - * 12/13/95 pi@isi.edu * - * Revision 8.2.7 (pi) * - * Add Magic 6.4.4 new extraction plane orders. * - * 07/25/95 pi@isi.edu * - * Revision 8.2.5 (pi) * - * Fix some typos... * - * 05/12/95 pi@isi.edu * - * Revision 8.2.4 (pi) * - * Fix CBA generation for pbase and add extension rules for pbase * - * as resistors. * - * Gratitude goes to Tetsuya Kajita (kaj@ssac.yamatake.co.jp) * - * 04/26/95 pi@isi.edu * - * Revision 8.2.3 (pi) * - * fix for SUBMICRON DRC rule. * - * Thanks goes to Toby Schaffer (jtschaff@eos.ncsu.edu) * - * 04/06/95 pi@isi.edu * - * Revision 8.2.2 (pi) * - * add XP GDS official number to fix CIF input problem for "pad". * - * Thanks goes to Brian Kingsbury (bedk@ICSI.Berkeley.EDU). * - * 04/03/95 pi@isi.edu * - * Revision 8.2.1 (pi) * - * Some fixes for CMOS14B CIF output section. * - * 03/21/95 pi@isi.edu * - * Revision 8.2.0 (pi) * - * support for HP CMOS26G and CMOS14TB process. * - * 03/15/95 pi@isi.edu * - * Revision 8.1.1 (pi) * - * add connection of "ndiff" to "psd". Thank goes to Alireza Moini* - * (moini@eleceng.adelaide.edu.au). * - * 12/21/94 pi@isi.edu * - * Revision 8.1.0 (pi) * - * major revision of bipolar transistor rules. It now support * - * both ORBIT 2.0 and 1.2 micron processes. NOTE: active layer * - * for pbase is now generated in CIF file explicitly. * - * 10/31/94 pi@isi.edu * - * Revision 8.0.7 (pi) * - * remove both VTI and IBM support * - * 10/10/94 pi@isi.edu * - * Revision 8.0.7 (pi) * - * compose for high-voltage transistors corrected. Thank goes to * - * Bob Durie (bobd@ee.cornell.edu) * - * 8/25/94 pi@isi.edu * - * Revision 8.0.6 (pi) * - * DRC rule 2.2 add allNOhmic to allNOhmic and allPOhmic to * - * allPOhmic rule. Thank goes to Shih-Lien Lu. * - * (sllu@caleb.ECE.ORST.EDU) * - * 6/28/94 pi@isi.edu * - * Revision 8.0.5 (pi) * - * DRC rule 3.5 reverse back to old style to avoid a mischeck on * - * corners. Thank goes to Wen-King Su. * - * (wen-king@vlsi.cs.caltech.edu) * - * 4/20/94 pi@isi.edu * - * Revision 8.0.4 (pi) * - * SCPE20(ORB) extraction P-well sheet resistance fixed. Thank * - * goes to Nagendra Shivakumar (nshivaku@phyast.nhn.uoknor.edu). * - * 3/04/94 pi@isi.edu * - * Revision 8.0.3 (pi) * - * Wellcap drawing problem fixed. Thank goes to Mario Aranha * - * (mario@cad4.lbl.gov). * - * 2/03/94 pi@isi.edu * - * Revision 8.0.2 (pi) * - * CIF read fix for linear capacitor. Thank goes to Issy Kipnis * - * (kipnis@cad4.lbl.gov). * - * 2/03/94 pi@isi.edu * - * Revision 8.0.1 (pi) * - * DRC updates for separate diffusion width check. Thank goes to * - * John Poulton (jp@cs.unc.edu). * - * 10/04/93 pi@isi.edu * - * Revision 8.0.0 (pi) * - * DRC revision 8 installed and layer support for High-Voltage * - * MOSFETs for SCNA16 process. * - * 10/04/93 pi@isi.edu * - * Revision 7.4.0 (pi) * - * Brand new extraction section and other fixes :-) * - * 10/01/93 pi@isi.edu * - * Revision 7.3.3 (pi) * - * pbc surrounding rule fixed. 4.1.c fixed also * - * 6/01/93 pi@isi.edu * - * Revision 7.3.2 (pi) * - * exchnage CCD and CBA calma (GDS) number to the correct setting * - * 4/27/93 pi@isi.edu * - * Revision 7.3.1 (pi) * - * Various DRC rule changes contributed by Barry Boes at AuE * - * (boes@corona.AuE.com). * - * allNDiff/allPOhmic in connection section update, thanks go to * - * Brian Kingsbury from Bekerley (bedk@icsi.berkeley.edu). * - * 3/30/93 pi@isi.edu * - * Revision 7.3.0 (pi) * - * add three new layers intended for ESD preotection devices * - * remove the temporary "pad2" layer, now all pads use "pad" * - * CIFin and CIFout now in templates, thank goes to Shih-Lien Lu * - * at Origon State Univ. sllu@caleb.ECE.ORST.EDU. * - * Some design rule changes (relabeling for doc)... * - * 3/19/93 pi@isi.edu * - * Revision 7.2.2 (pi) * - * change all "bloat-min" select generation back to "bloat-or" * - * restore all lambda=0.8 style since some people use ORBIT's run * - * though MOSIS does NOT provide HP's process anymore * - * 3/09/93 pi@isi.edu * - * Revision 7.2.1 (pi) * - * add missing Cifinput "pbase" layer for lambda=1.0(oldnwell) * - * style. Thank goes to Brian Von Herzen at Synaptics, Inc. * - * 2/18/93 pi@isi.edu * - * Revision 7.2.0 (pi) * - * A serious bug in CIF well generation is fixed... * - * 1/14/93 pi@isi.edu * - * Revision 7.1.4 (pi) * - * Remove lambda=1.5 and lambda=0.8 technology which are not * - * provided by MOSIS any more. * - * 1/12/93 pi@isi.edu * - * Revision 7.1.3 (pi) * - * Add pstop layer and the corresponding CIFin CIFout stuff * - * Reverse the last change about CCA layer under pad for CMOS26B * - * 1/08/93 pi@isi.edu * - * Revision 7.1.2 (pi) * - * Various problem fix... and make the "open" layer as an option * - * Reverse the last change about CCA layer under pad for CMOS26B * - * 12/29/92 pi@isi.edu * - * Revision 7.1.1 (pi) * - * A series bug fix for HP's CMOS26B pad layers - remove CCA CIF * - * layer. Thank goes to ndu@aue.com * - * 12/12/92 pi@isi.edu * - * Revision 7.1.0 (pi) * - * A new layer "open" for micromachined device fabracation. * - * Thanks goes to Janet Marchall from NIST. * - * (marshall@sed.eeel.nist.gov) * - * 12/15/92 pi@isi.edu * - * Revision 7.0.4 (pi) * - * C-preprocessing fix. Thanks goes to Jeffrey C. Gealow form * - * MIT (jgealow@mtl.mit.edu). * - * 10/20/92 pi@isi.edu * - * Revision 7.0.3 (pi) * - * Colorversatec support. Thanks got to Jeffrey C. Gealow form * - * MIT (jgealow@mtl.mit.edu). * - * 10/8/92 pi@isi.edu * - * Revision 7.0.2 (pi) * - * Separate 'spacing allWell...' rule into two rules to avoid * - * well adjacency problem... * - * 10/2/92 pi@isi.edu * - * Revision 7.0.1 (pi) * - * CIFoutput for "pad2" layer, CCA contact fix, CIFinput for HP's * - * 1.0 um process... * - * 9/28/92 pi@isi.edu * - * Revision 7.0 (pi) * - * Major revision which includes * - * HP's cap_well and well-capacitance, NPN & BCCD DRC rules... * - * 9/22/92 pi@isi.edu * - * Revision 6.2.0 (pi) * - * Merging 'scmos26.tech' into scmos.tech * - * 9/7/92 pi@isi.edu * - * Revision 6.1.4 (pi) * - * Select CIF layers generation is revised based on Brian * - * Kingsbury's (bedk@icsi.berkeley.edu) notice of inconsistency * - * 9/4/92 pi@isi.edu * - * Revision 6.1.3 (pi) * - * Install MITRE's (Mike Butler) fix for CIFinput "cap" layer and * - * poly1/poly2 crossing in DRC section * - * 9/3/92 pi@isi.edu * - * Revision 6.1.2 (pi) * - * Fixed metal2 contact on falt surface bug for poly2 layer * - * 8/3/92 pi@lepton.isi.edu * - * Revision 6.1.1 (pi) * - * fixed CIFoutput CSP layer bug for lambda=0.8(gen) technology * - * 4/13/92 pi@lepton.isi.edu * - * Revision 6.1.0 (pi) * - * add implant plane for Buried CCD devices * - * both cifin and cifoutput are changed correspondingly * - * Revision 6.0.2 (pi) * - * remove bug for nbdc not generate CMF in cifoutput section * - * Revision 6.0.1 (sllu) * - * added CX for collector layer * - * Revised for Magic Version 6. * - * Revision 6.0 90/05/11 20:12:34 pi * - * include color versatech support * - * eliminated active2 plane * - * (rule version # 5.01 (S. Lu) = rule 5.0 + mod. for cc spacing * - * (rule version # 5.0 (Shih-Lien Lu sllu@MOSIS.EDU) 8/15/89) * - * (rule 5.0 = rule 4.01 + new layers for analog process * - * (rule 4.01 = rule 4.0 + comments + cifout style lambda=0.8(pwell) * - * (correction made by L. McMurchie of UW) * - * (rule 4.0 = rule 3.1 + new layer : electrode) * - * (rule 3.1 = rule 3.0 + new cifout method for select layers ) * - * (design can be more compact now with this version ) * - * (layout should be upward compatible:: you old layout will not) * - * (flag any drc violations) * - * (rule 3.0 = rule 2.0 + rev #6 + new cifin section for new nwell) * - * * - * (rule version # 2.0 10/28/87) * - * (rule 2.0 = rule 1.9 + modification to extract section * - * (rule 1.9 = rule 1.82 + additions of two more CIF in/output styles * - * (rule 1.82 = rule 1.81+ modification of drc #4.1 & cifoutput of * - * wells * - * (rule 1.81 = rule 1.8 + modification on line 1761 * - * (rule 1.8 = rule 1.7 + Rev 5 of the SCMOS rules) * - * (difference from rule 1.7: * - * (1) well width = 9 lambda * - * (2) N well process accepts both N and P selects * - * ------------------------------------------------------------------- */ - -/* Definition for actives */ -/* NOTE: Some version of cpp may have problem with two consective tabs - * or even two consective space... So we put only single space - * here... */ -#define allNDiff ndiff,ndc/a -#define allPDiff pdiff,pdc/a -#define allNActive ndiff,ndc/a,nfet,enfet,nffet,wcap -#define allPActive pdiff,pdc/a,pfet,epfet,pffet -#define allNOhmic nsd,nsc/a -#define allPOhmic psd,psc/a -#define allOhmic allNOhmic,allPOhmic -#define allBiNDiff emit,emc/a,col,clc/a -#define allBiPDiff pbase,pbc/a -#define allBiDiff allBiNDiff,allBiPDiff -#define allCCDiff bd,nbd,nbdc/a -#define allDiff allNDiff,allPDiff -#define allActive allNActive,allPActive,allOhmic -#define PNplus ndiff,pdiff,ndc/a,pdc/a -#define allHVNDiff hndiff,hndc/a -#define allHVPDiff hpdiff,hpdc/a -#define allHVNOhmic hnsd,hnsc/a -#define allHVPOhmic hpsd,hpsc/a -#define allHVDiff allHVNDiff,allHVPDiff -#define allHVOhmic allHVNOhmic,allHVPOhmic - -/* first poly without those overlapped with the second */ -#define allP poly,pc/a -#define allP1 poly,pc/a,nfet,pfet,wcap -/* all first poly */ -#define allPoly allP1,cap,capc/a,nffet,pffet -/* second poly without those overlapped with the first */ -#define allP2 poly2,ec/a,enfet,epfet -/* all second poly */ -#define allPoly2 allP2,cap,capc/a,nffet,pffet,hnfet,hpfet - -/* MOSFETs */ -#define NFet nfet,enfet,nffet -#define PFet pfet,epfet,pffet -#define allFet NFet,PFet - -/* Definitions for contacts */ -#define DiffCut pdc,ndc,psc,nsc -#define HVDiffCut hpdc,hndc,hpsc,hnsc -#define PolyCut pc -#define CapCut ec,capc -#define BiCut clc,emc,pbc -#define allCut DiffCut,HVDiffCut,PolyCut,CapCut,nbdc - -/* Definitions for metals */ -#define DiffMetal pdc/m1,ndc/m1,psc/m1,nsc/m1 -#define HVDiffMetal hpdc/m1,hndc/m1,hpsc/m1,hnsc/m1 -#define PolyMetal pc/m1,ec/m1,capc/m1 -#define BiMetal clc/m1,emc/m1,pbc/m1 -#define CCDMetal nbdc/m1 -#define allMetal1 DiffMetal,HVDiffMetal,PolyMetal,BiMetal,CCDMetal,m1,m2c/m1,gc -#define allMetal2 m2,m2c/m2,m3c/m2,pad -#define allMetal3 m3,m3c/m3 - -/* All types containing metal, on their respective home planes */ -#define homeMetal1 allCut,m1,m2c,gc - -/* Definitions for wells */ -#define allWell nwell,pwell -#define allNwell nwell,nsc,nsd -#define allPwell pwell,psc,psd -#define allHVNwell hnwell,hnsc,hnsd -#define allHVPwell hpwell,hpsc,hpsd - - -tech - format 28 - scmos -end - -#if V4 || V5 -version - version 8.2.8 -#ifdef SUBMICRON - description "MOSIS Scalable CMOS Technology for HP CMOS26G and CMOS14B processes" -#else /* TIGHTMETAL */ -#ifdef IBMTECH - description "MOSIS Scalable CMOS Technology for IBM" -#else /* IBMTECH */ -#ifdef HPTECH - description "MOSIS Scalable CMOS Technology for Tight Metal Rules" -#else -#ifndef WELL_ROUTE_CHECK - description "MOSIS Scalable CMOS Technology for Standard Rules" -#else - description "MOSIS Scalable CMOS Technology for Standard Rules (No routing through wells)" -#endif -#endif /* HPTECH */ -#endif /* IBMTECH */ -#endif /* TIGHTMETAL */ -end -#endif /* V4 */ - -planes - well,w - implant,i - active,a - metal1,m1 - metal2,m2 -#ifdef STACKVIA - v2oxide,v2x -#endif - metal3,m3 - oxide,ox -end - - -types - /* primary layers -16 */ - - well pwell,pw - well nwell,nw - well capwell,cwell,cw - well highvoltnwell,hvnwell,hnwell,hnw - well highvoltpwell,hvpwell,hpwell,hpw - active polysilicon,red,poly,p - active electrode,poly2,el,p2 - active capacitor,polycap,pcap,cap - active wellcapacitor,wellcap,wcap - active ndiffusion,ndiff,green - active pdiffusion,pdiff,brown - active highvoltndiffusion,hvndiff,hndiff - active highvoltpdiffusion,hvpdiff,hpdiff - metal1 metal1,m1,blue - metal2 metal2,m2,purple - metal3 metal3,m3,cyan - - /* MOSFETs -8 */ - - active ntransistor,nfet - active ptransistor,pfet - active entransistor,enfet - active eptransistor,epfet - active doublentransistor,nfloating-gate,nfloatg,nfg,nffet - active doubleptransistor,pfloating-gate,pfloatg,pfg,pffet - active highvoltntransistor,hvnfet,hnfet - active highvoltptransistor,hvpfet,hpfet - - /* NPN transistor layers -3 */ - - active collector,coll,col,co,cl - active emitter,emit,em - active pbase,pb - - /* layers for BCCD devices -2 */ - - implant bccdiffusion,bd - active nbccdiffusion,nbd - - /* Contacts between interconnection layers -13 */ - - active polycontact,pcontact,polycut,pc - active ndcontact,ndiffcut,ndc - active pdcontact,pdiffcut,pdc - active highvoltndcontact,hndiffcut,hndc - active highvoltpdcontact,hpdiffcut,hpdc - active capcontact,ccontact,capc,cc - active electrodecontact,econtact,ec,poly2contact,p2c - active collectorcontact,colcontact,colc,coc,clc - active emittercontact,emitcontact,emc - active pbasecontact,pbcontact,pbc - active nbccdiffcontact,nbdc - metal1 m2contact,m2cut,m2c,via,v -#ifdef STACKVIA - v2x m3contact,m3cut,m3c,via2,v2 -#else - metal2 m3contact,m3cut,m3c,via2,v2 -#endif - - /* Well contacts -8 */ - /* pohmic and nohmic are included for compatibility */ - /* nwc, pwc, etc ... are included for compatibility */ - - active psubstratepcontact,ppcontact,ppc,pwcontact,pwc,psc - active nsubstratencontact,nncontact,nnc,nwcontact,nwc,nsc - active psubstratepdiff,ppdiff,pohmic,ppd,psd - active nsubstratendiff,nndiff,nohmic,nnd,nsd - - active highvoltpsubcontact,hpwcontact,hpsc - active highvoltnsubcontact,hnwcontact,hnsc - active highvoltpsubdiff,hpohmic,hpsd - active highvoltnsubdiff,hnohmic,hnsd - - /* Special tiles needed for ESD protection design -3 */ - active nplusdoping,ndoping,ndop - active pplusdoping,pdoping,pdop - metal1 genericcontact,gcontact,gc - - /* Special tiles needed for micromachine fab. in CMOS -2 */ - oxide substrateopen,subopen,open - oxide pdiffusionstop,pdiffstop,pstop - - /* Additional stuff, used in pads. -2 */ - - metal2 pad - oxide glass -end - -contact - /* polys */ - ec poly2 metal1 - cc cap metal1 - pc poly metal1 - /* active contacts */ - ndc ndiff metal1 - pdc pdiff metal1 - nsc nsd metal1 - psc psd metal1 - hndc hndiff metal1 - hpdc hpdiff metal1 - hnsc hnsd metal1 - hpsc hpsd metal1 - /* bipolar contacts */ - clc col metal1 - emc emit metal1 - pbc pbase metal1 - /* BCCD contact */ - nbdc nbd metal1 - /* vias */ - m2c metal1 metal2 -#ifdef STACKVIA - m3c metal2 m3c metal3 -#else - m3c metal2 metal3 -#endif -/* - pad metal1 metal2 metal3 - */ - -end - -styles - styletype mos - - /* wells */ - cwell 10 - nwell 12 - pwell 13 - hnwell 18 - hpwell 11 - /* poly */ - poly 1 - poly2 14 - /* diffusions */ - ndiff 2 - pdiff 4 - psd 5 - nsd 3 - hndiff 2 - hndiff 11 - hpdiff 4 - hpdiff 18 - hpsd 5 - hpsd 11 - hnsd 3 - hnsd 18 - ndop 2 - ndop 38 - pdop 4 - pdop 38 - /* transistors */ - nfet 6 - nfet 7 - pfet 8 - pfet 9 - - enfet 6 - enfet 30 -/* enfet 14 */ - epfet 8 - epfet 31 -/* epfet 14 */ - - nffet 6 - nffet 7 -/* nffet 14 */ - nffet 30 - pffet 8 - pffet 9 -/* pffet 14 */ - pffet 31 - - hnfet 6 - hnfet 7 - hnfet 30 - - hpfet 8 - hpfet 9 - hpfet 31 - /* base */ - pbase 15 - pbc 15 - pbc 20 - pbc 32 - /* emitter */ - emit 16 - emc 16 - emc 20 - emc 32 - /* collector */ - col 3 - clc 3 - clc 20 - clc 32 - /* capacitors */ - cap 1 - cap 14 - wcap 6 - wcap 10 - cc 1 - cc 14 - cc 20 - cc 32 - /* metals */ - metal1 20 - metal2 21 - metal3 22 - /* generic contact */ - gc 19 - /* poly contacts */ - pcontact 26 - pcontact 32 - ec 14 - ec 20 - ec 32 - /* diffusion contacts */ - ndc 2 - ndc 20 - ndc 32 - pdc 4 - pdc 20 - pdc 32 - psc 5 - psc 20 - psc 32 - nsc 3 - nsc 20 - nsc 32 - /* high-voltage diffusion contacts */ - hndc 2 - hndc 20 - hndc 32 - hndc 11 - hpdc 4 - hpdc 20 - hpdc 32 - hpdc 18 - hpsc 5 - hpsc 20 - hpsc 32 - hpsc 11 - hnsc 3 - hnsc 20 - hnsc 32 - hnsc 18 - /* vias */ - m2contact 20 - m2contact 21 - m2contact 33 - m3contact 21 - m3contact 22 - m3contact 37 - /* pads and overglass */ - pad 20 - pad 21 - pad 33 - pad 34 - glass 34 - /* CCDs */ - bd 17 - nbd 17 - nbd 3 - nbdc 3 - nbdc 17 - nbdc 20 - nbdc 32 - /* MEMs */ - open 2 - open 20 - pstop 8 - /* System */ - error_p 42 - error_s 42 - error_ps 42 -end - -compose - /* MOSFET combination rules */ - compose nfet poly hndiff - compose pfet poly hpdiff - compose nfet poly ndiff - compose pfet poly pdiff - compose hnfet poly2 hndiff - compose hpfet poly2 hpdiff - compose enfet poly2 ndiff - compose epfet poly2 pdiff - compose nffet nfet poly2 - compose pffet pfet poly2 - compose nffet enfet poly - compose pffet epfet poly - compose cap poly poly2 - /* Transistor combination rules */ - paint clc col clc - paint emc emit emc - paint emc pbase emc - /* Poly2 capacitor combination rules */ - paint poly2 poly cap - paint poly poly2 cap - paint poly cap cap - paint poly2 cap cap - paint cap poly cap - paint cap poly2 cap -/* ILLEGAL declaration by 7.3 standards */ -/* paint poly ec cc */ - paint ec poly cc - /* These rules allow nwell to be painted over an area to - * flip all the p-well types to n-well types. Pwell can be - * painted to flip in the reverse. */ - paint pdc pwell ndc - paint pfet pwell nfet - paint epfet pwell enfet - paint pffet pwell nffet - paint pdiff pwell ndiff - paint nsd pwell psd - paint nsc pwell psc - paint ndc nwell pdc - paint nfet nwell pfet - paint enfet nwell epfet - paint nffet nwell pffet - paint ndiff nwell pdiff - paint psd nwell nsd - paint psc nwell nsc - - paint pdc hpwell hndc - paint epfet hpwell hnfet - paint pffet hpwell hnfet - paint pdiff hpwell hndiff - paint nsd hpwell hpsd - paint nsc hpwell hpsc - paint ndc hnwell hpdc - paint enfet hnwell hpfet - paint nffet hnwell hpfet - paint ndiff hnwell hpdiff - paint psd hnwell hnsd - paint psc hnwell hnsc - /* BCCD layers combination rules */ -/* paint bd ndiff 0 implant */ -/* - erase nbd bd ndiff - erase nbd ndiff bd - erase nbdc/a bd ndc/a -*/ - /* Well capacitor combination rules */ - paint nfet cwell wcap - paint poly wcap wcap - paint ndiff wcap wcap - paint wcap poly wcap - paint wcap ndiff wcap - erase wcap poly ndiff - erase wcap ndiff poly - erase wcap cwell nfet - paint cwell nfet wcap active - erase wcap nfet cwell well - - /* Generic contact */ - paint gc m1 gc - - /* For pads */ - paint pad m1 pad - paint pad m2 pad - paint pad m3 pad - paint pad m2c pad - - /* These rules allow nwell to be painted over an area to - * flip all the p-well types to n-well types. Pwell can be - * painted to flip in the reverse. */ - paint hpdc hpwell hndc - paint hpfet hpwell hnfet - paint hpdiff hpwell hndiff - paint hnsd hpwell hpsd - paint hnsc hpwell hpsc - paint hndc hnwell hpdc - paint hnfet hnwell hpfet - paint hndiff hnwell hpdiff - paint hpsd hnwell hnsd - paint hpsc hnwell hnsc - - paint hpdc pwell ndc - paint hpfet pwell enfet - paint hpdiff pwell ndiff - paint hnsd pwell psd - paint hnsc pwell psc - paint hndc nwell pdc - paint hnfet nwell epfet - paint hndiff nwell pdiff - paint hpsd nwell nsd - paint hpsc nwell nsc - -end - -connect -#ifndef WELL_ROUTE_CHECK -/* This creates a tech file where the wells are not connected therefore - enabling extractions to check whether the wells are used accidentaly - to route signals or power. To check for these cases you have to compare - the netlists generated with the normal tech file with those generated - with the special one (eg. using gemini). -*/ - allNwell allNwell - allPwell allPwell -#endif - allHVNwell allHVNwell - allHVPwell allHVPwell - /* for capacitor-well */ - allNDiff cwell - /* for all metals */ - allMetal1 allMetal1 - allMetal2 allMetal2 - allMetal3 allMetal3 - /* for all polys */ - allP1 allP1 - allPoly2 allPoly2 - /* for all diffusions/well plugs */ - /* Ndiffusion and Ohmic wells dont connect !! */ - /* you get a diode instead */ - allNDiff,ndop allPOhmic,pdop,pstop - allPDiff,pdop,pstop allNOhmic,ndop - allHVNDiff,ndop allHVPOhmic,pdop,pstop - allHVPDiff,pdop,pstop allHVNOhmic,ndop - ndiff ndc - pdiff pdc - hndiff hndc - hpdiff hpdc - /* for BCCD device */ - nbd nbdc - /* for NPN transistor */ - pbase pbc - collector clc,nwell - emitter emc - /* for new generic contact */ - gc allActive,allOhmic,allHVDiff,metal1 - gc allP1 - gc allPoly2 - /* for pad */ - pad allMetal1 - pad allMetal2 - pad allMetal3 - -end - -/* WARNING ::::: automatic generation of wells does not guarantee */ -/* rules on width and spacing of wells are followed !! */ -/* It is strongly recommanded that designers layout their own wells */ - -/* PWELL styles cannot generate CBA and CCD correctly */ -/* BOTH NWELL and GEN can do CCD and CBA */ -/* ONLY GEN can be used for micro-machining fabrication */ - -cifoutput -/* default: fab on 2.0 micron (Nwell) rules each magic unit is 100 */ -/* centimicrons */ -/* SCN technology : Both CSN and CSP are generated to reduce field */ -/* poly sheet resistance */ - -#ifdef STANDARD -#include "cif_template/objs/CIFout" -#endif /* STANDARD */ - -#ifdef TIGHTMETAL -#include "cif_template/objs/TMCIFout" -#endif /* TIGHTMETAL */ - -#ifdef SUBMICRON -#include "cif_template/objs/SUBCIFout" -#endif /* SUBMICRON */ - -#ifdef IBMTECH -#include "cif_template/objs/IBMCIFout" -#endif /* IBMTECH */ - -style plot /* pplot output style */ - scalefactor 100 50 - layer CM2 m2,m2c/m2,pad/m2 - labels m2 - layer CM1 pad - grow 100 - or m1,m2c/m1,pc/m1,ndc/m1,pdc/m1,ppcont/m1,nncont/m1 - labels m1,m2c/m1,pc/m1,ndc/m1,pdc/m1,ppcont/m1,nncont/m1,pad/m1 - layer CP poly,pc/active,nfet,pfet - labels poly,nfet,pfet - layer CND ndiff,ndc,nfet,pwc,psd - labels ndiff - layer CPD pdiff,pdc,pfet,nwc,nsd - labels pdiff - layer CNP - bloat-or nsd,nwc * 150 ndiff,pdiff,ndc/active,pdc/active,ppcont/active,nncont/active,pfet,nfet,psd,nsd 0 - layer CPP - bloat-or psd,pwc * 150 ndiff,pdiff,ndc/active,pdc/active,ppcont/active,nncont/active,pfet,nfet,psd,nsd 0 - layer CV m2c - squares 100 200 300 - layer CC ndc,pdc,pc,pwc,nwc - squares 200 - layer CNW nwell - grow 400 - shrink 400 - layer CG pad - shrink 600 - or glass - labels glass - - -end - -/* -------------------------------------------------------------------- * - * In the CIFinput section, the order of layer specifications is very * - * important. Each layer overrides any of the previous layers. There * - * are places where one layer is generated over an area that is too * - * large, but with the knowledge that later layers will "take over" * - * the extraneous area, leaving the first layer only where it belongs. * - * This happens for various flavors of diffusion, for example. * - * Note: when reading in CMOS, wells are created in the Magic files. * - * They can be eliminated manually if desired. * - * ---------------------------------------------------------------------*/ -cifinput - -#ifdef STANDARD -#include "cif_template/objs/CIFin" -#endif /* STANDARD */ - -#ifdef TIGHTMETAL -#include "cif_template/objs/TMCIFin" -#endif /* TIGHTMETAL */ - -#ifdef SUBMICRON -#include "cif_template/objs/SUBCIFin" -#endif /* SUBMICRON */ - -#ifdef IBMTECH -#include "cif_template/objs/IBMCIFin" -#endif /* IBMTECH */ - -end - -mzrouter - style irouter - layer m2 32 64 256 1 - layer m1 64 32 256 1 - layer poly 128 128 512 1 - contact m2contact metal1 metal2 1024 - contact pcontact metal1 poly 2056 - notactive poly pcontact - style garouter - layer m2 32 64 256 1 - layer m1 64 32 256 1 - contact m2contact metal1 metal2 1024 -end - - -/* SCMOS rules revision 7 */ -drc -/* ---------------------------------------------------------------- */ -/* Well */ -/* ---------------------------------------------------------------- */ - -/* 1.1 */ -/* Now use "edge" for width DRC... A test only for rule1 */ -/* Other rules may follow in the near future... */ -#ifdef SUBMICRON - edge4way (~nwell)/w nwell 12 nwell nwell 12\\ - "N-Well width must be at least 12 (MOSIS rule #1.1)" - edge4way (~pwell)/w pwell 12 pwell pwell 12\\ - "P-Well width must be at least 12 (MOSIS rule #1.1)" -#else - edge4way (~nwell)/w nwell 10 nwell nwell 10\\ - "N-Well width must be at least 10 (MOSIS rule #1.1)" - edge4way (~pwell)/w pwell 10 pwell pwell 10\\ - "P-Well width must be at least 10 (MOSIS rule #1.1)" -#endif - -/* original "width" rule which use 'width'command: - width allWell 10 \\ - "Well width must be at least 10 (MOSIS rule #1.1)" - */ - -/* 1.2 */ -/* Now use "edge4way" for spacing DRC... A test only for rule1 */ -/* Other rules may follow in the near future... */ -#ifdef SUBMICRON - edge4way nwell ~(nwell)/w 18 (~nwell)/w (~nwell)/w 18\\ - "N-Well spacing must be at least 18 (MOSIS rule #1.2)" - edge4way pwell (~pwell)/w 18 (~pwell)/w (~pwell)/w 18\\ - "P-Well spacing must be at least 18 (MOSIS rule #1.2)" -#else - edge4way nwell (~nwell)/w 9 (~nwell)/w (~nwell)/w 9\\ - "N-Well spacing must be at least 9 (MOSIS rule #1.2)" - edge4way pwell (~pwell)/w 9 (~pwell)/w (~pwell)/w 9\\ - "P-Well spacing must be at least 9 (MOSIS rule #1.2)" -#endif - -/* original spacing rule which use 'spacing' command: - spacing allWell allWell 9 touching_ok \\ - "Well spacing must be at least 9 (MOSIS rule #1.2)" - */ - -/* NOTE: rule 1.2 is equivalent to the following three rules where - the third is a new one. This rule is added to force designers - to be cautious about the wells... - - spacing nwell nwell 9 touching_ok \\ - "N-well spacing must be at least 9 (MOSIS rule #1.2)" - spacing pwell pwell 9 touching_ok \\ - "P-well spacing must be at least 9 (MOSIS rule #1.2)" - spacing nwell pwell 9 touching_ok \\ - "Well spacing must be at least 9 (MOSIS rule #1.2)" -*/ - -/* 1.3 is not checked */ -/* NOTE: for digital ckts where wells are not explicitly put, * - * auto-generation may not ensure the minimul spacing and width * - * rule: this happens usually when two geometries are in diagonal * - * positions. * - * NOTE: when both pwell and nwell are submitted they cannot * - * overlap this is assured with the compose section - painting one * - * well over another will erase the original well. */ - -/* ---------------------------------------------------------------- */ -/* Active */ -/* ---------------------------------------------------------------- */ - -/* 2.1 */ -/* Test active width separately... */ - width allNActive 3 \\ - "N-type Diffusion width must be at least 3 (MOSIS rule #2.1a)" - width allPActive 3 \\ - "P-type Diffusion width must be at least 3 (MOSIS rule #2.1b)" - width allOhmic 3 \\ - "Ohmic diffusion width must be at least 3 (MOSIS rule #2.1c)" - -/* 2.2 */ - spacing allNActive allNActive 3 touching_ok \\ - "Diffusion spacing must be at least 3 (MOSIS rule #2.2)" - spacing allPActive allPActive 3 touching_ok \\ - "Diffusion spacing must be at least 3 (MOSIS rule #2.2)" - spacing allNOhmic allNOhmic 3 touching_ok \\ - "Diffusion spacing must be at least 3 (MOSIS rule #2.2)" - spacing allPOhmic allPOhmic 3 touching_ok \\ - "Diffusion spacing must be at least 3 (MOSIS rule #2.2)" - -/* 2.3 without explicit well definition: 6+6 and 5+5 respectively */ -#ifdef SUBMICRON - spacing allNDiff allPDiff 12 touching_illegal \\ - "P-type diffusion must be 12 away from N-type diffusion (MOSIS rule #2.3b)" -#else - spacing allNDiff allPDiff 10 touching_illegal \\ - "P-type diffusion must be 10 away from N-type diffusion (MOSIS rule #2.3a)" -#endif - -/* 2.3 + 2.4 without explicit well definition: 6+3 and 5+3 respectively */ -#ifdef SUBMICRON - spacing allNDiff allNOhmic 9 touching_illegal \\ - "N-type diffusion must be 9 away from N-substrate contact (MOSIS rule #2.3b,4b)" - spacing allPDiff allPOhmic 9 touching_illegal \\ - "P-type diffusion must be 9 away from P-substrate contact (MOSIS rule #2.3b,4b)" -#else - spacing allNDiff allNOhmic 8 touching_illegal \\ - "N-type diffusion must be 8 away from N-substrate contact (MOSIS rule #2.3a,4a)" - spacing allPDiff allPOhmic 8 touching_illegal \\ - "P-type diffusion must be 8 away from P-substrate contact (MOSIS rule #2.3a,4a)" -#endif - -/* 2.4 3 + 3 */ - spacing allNOhmic allPOhmic 6 touching_illegal \\ - "Opposite well contacts must be separated by 6 (MOSIS rule #2.4)" - -/* 2.3 with explicit well: 6 and 5 respectively */ -#ifdef SUBMICRON - spacing allNActive nwell 6 touching_illegal \\ - "N-diffusion and N-well must be separated by 6 (MOSIS rule #2.3b)" - spacing allPActive pwell 6 touching_illegal \\ - "P-diffusion and P-well must be separated by 6 (MOSIS rule #2.3b)" -#else - spacing allNActive nwell 5 touching_illegal \\ - "N-diffusion and N-well must be separated by 5 (MOSIS rule #2.3a)" - spacing allPActive pwell 5 touching_illegal \\ - "P-diffusion and P-well must be separated by 5 (MOSIS rule #2.3a)" -#endif - -/* 2.4 with explicit well */ - spacing allNOhmic pwell 3 touching_illegal \\ - "N-substrate diffusion and P-well must be separated by 3 (MOSIS rule #2.4)" - spacing allPOhmic nwell 3 touching_illegal \\ - "P-substrate diffusion and N-well must be separated by 3 (MOSIS rule #2.4)" - -/* MOSIS extension rule for diffusion and substrate contact of */ -/* opposite type. We could do without this rule, but it is now */ -/* added for safety reason. */ - spacing allNActive allPOhmic 4 touching_ok \\ - "Opposite diffusion spacing must be at least 4 (MOSIS extension rule)" - spacing allPActive allNOhmic 4 touching_ok \\ - "Opposite diffusion spacing must be at least 4 (MOSIS extension rule)" - -/* ---------------------------------------------------------------- */ -/* Poly */ -/* ---------------------------------------------------------------- */ - -/* 3.1 */ - width allPoly 2 \\ - "Polysilicon width must be at least 2 (MOSIS rule #3.1)" - -/* 3.2 */ -#ifdef SUBMICRON - spacing allPoly allPoly 3 touching_ok \\ - "Polysilicon spacing must be at least 3 (MOSIS rule #3.2b)" -#else - spacing allPoly allPoly 2 touching_ok \\ - "Polysilicon spacing must be at least 2 (MOSIS rule #3.2a)" -#endif - -/* 3.3 */ - edge4way nfet,pfet poly,pc/act 2 poly,pc/act 0 0 \\ - "Poly must overhang transistor by at least 2 (MOSIS rule #3.3)" - -/* 3.4 */ - edge4way nfet,enfet ndiff,ndc/a 3 allNActive ndiff,ndc/a 3 \\ - "Diffusion must overhang transistor by at least 3 (MOSIS rule #3.4)" - edge4way pfet,epfet pdiff,pdc/a 3 allPActive ndiff,ndc/a 3 \\ - "Diffusion must overhang transistor by at least 3 (MOSIS rule #3.4)" - -/* 3.3 + 3.4 */ - edge4way nfet,pfet space 1 poly 0 0 \\ - "Transistor overhang is missing (MOSIS rule #3.3,4)" - edge4way enfet,epfet space 1 poly2 0 0 \\ - "Transistor overhang is missing (MOSIS rule #3.3,4)" - edge4way nffet,pffet space 1 poly 0 0 \\ - "Transistor overhang is missing (MOSIS rule #3.3,4)" - edge4way nffet,pffet space 1 poly2 0 0 \\ - "Transistor overhang is missing (MOSIS rule #3.3,4)" - -/* 3.5 */ - edge4way allDiff,allOhmic poly,pc 1 space/a 0 1 \\ - "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5)" - edge4way poly,pc allDiff,allOhmic 1 space/a 0 1 \\ - "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5)" - edge poly,pc space/a 1 space/a space/a 1 \\ - "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5)" - edge allOhmic,allDiff space/a 1 space/a space/a 1 \\ - "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5)" -/* - These following checks will miss the corner, so we add something above - - edge4way allDiff,allOhmic poly,pc 1 space space 1 \\ - "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5.a)" - spacing allDiff,allOhmic poly,pc 1 touching_illegal \\ - "Poly and diffusion must be separated by at least 1 (MOSIS rule #3.5.b)" - */ - -/* Extra transistor rules */ -/* These rules is really NOT necessary because others have already - taken care of it. It is here for future reference... - - edge4way poly,pc/act pfet 3 pfet 0 0 \\ - "Transistors must be at least 3 units wide (MOSIS rule #2)" - edge4way poly,pc/act nfet 3 nfet 0 0 \\ - "Transistors must be at least 3 units wide (MOSIS rule #2)" -*/ - -/* ---------------------------------------------------------------- */ -/* Select */ -/* ---------------------------------------------------------------- */ -/* 4.1 */ - spacing PFet allNOhmic 3 touching_illegal \\ - "Transistors must be separated from substrate contacts by 3 (MOSIS rule #4.1.a)" - spacing NFet allPOhmic 3 touching_illegal \\ - "Transistors must be separated from substrate contacts by 3 (MOSIS rule #4.1.b)" - - edge4way allPOhmic space/act 3 ~(NFet)/act allPOhmic,allNDiff 3 \\ - "Transistors must be separated from selects(generated by well cont) by 3 (MOSIS rule #4.1.c)" - - edge4way allNOhmic space/act 3 ~(PFet)/act allNOhmic,allPDiff 3 \\ - "Transistors must be separated from selects(generated by well cont) by 3 (MOSIS rule #4.1.d)" - - edge4way allPOhmic ~(ndiff,ndc,psc,psd)/act 4 ~(nfet,enfet)/act ~(ndiff,ndc,psc,psd)/act 4 \\ - "Transistors must be separated from selects(generated by well cont) by 4 (MOSIS rule #4.1.e)" - - edge4way allNOhmic ~(pdiff,pdc,nsc,nsd)/act 4 ~(pfet,epfet)/act ~(pdiff,pdc,nsc,nsd)/act 4 \\ - "Transistors must be separated from selects(generated by well cont) by 4 (MOSIS rule #4.1.f)" - -/* 4.2 */ -/* This one is very difficult.... Most likely done by CIF output */ - edge4way ~(allPActive)/act pdiff,pdc,pfet 4 ~(allNOhmic)/act allPActive 2 \\ - "Backedge of diffusion must be 4 from substrate diff (MOSIS rule #4.2.a)" - edge4way ~(allNActive)/act ndiff,ndc,nfet 4 ~(allPOhmic)/act allNActive 2 \\ - "Backedge of diffusion must be 4 from substrate diff (MOSIS rule #4.2.b)" - -/* 4.3 -- guaranteed automatically by CIF generator. */ -/* 4.4 -- guaranteed automatically by CIF generator except diag. where - this rule is not crucial */ - - -/* ---------------------------------------------------------------- */ -/* Contact to Poly */ -/* ---------------------------------------------------------------- */ - -/* 5B.1 + 5B.2 + 5B.3 */ - width pc 4 \\ - "Poly contact width must be at least 4 (MOSIS rule #5B.1,2,3)" - -/* 5B.4 is guaranteed by 5B.1,2,3 with rule 7.2 (metal1 spacing) */ - -/* 5B.5 -- - * Watch out here: a spacing "touching_ok" rule CANNOT be used here: - * it will miss certain checks. - */ - edge4way allPoly ~(allPoly)/act 3 ~pc/act ~(allPoly)/act 3 \\ - "Poly contact must be at least 3 from other poly (MOSIS rule #5B.4,5)" - -/* 5B.6 -- - * This is mostly handled by 3.5 already, but need rule here to handle - * case of pc abutting transistor. - */ - spacing pc allActive 1 touching_illegal \\ - "Poly contact must be 1 unit from diffusion (MOSIS rule #5B.6)" - -/* 5B.7 -- not implemented */ - -/* ---------------------------------------------------------------- */ -/* Contact to Active */ -/* ---------------------------------------------------------------- */ - -/* 6B.1 + 6B.2 + 6B.3 */ - width ndc,pdc 4 \\ - "Diffusion contact width must be at least 4 (MOSIS rule #6B.1,2,3)" - width nsc,psc 4 \\ - "Substrate contact width must be at least 4 (MOSIS rule #6B.1,2,3)" - -/* 6B.2 this is here to explicit check the contact spacing rule 3. */ -#ifdef SUBMICRON - spacing nsc pdc 1 touching_illegal \\ - "Substrate contact must be 1 unit from diffusion contact (MOSIS rule #6B.2b)" - spacing psc ndc 1 touching_illegal \\ - "Substrate contact must be 1 unit from diffusion contact (MOSIS rule #6B.2b)" -#endif - -/* - edge4way psc (~psc)/a 1 psd psd 1 \\ - "Substrate contact must overlapped by diffusion by at least 1 (MOSIS 26G rule)" - edge4way nsc (~nsc)/a 1 nsd nsd 1 \\ - "Substrate contact must overlapped by diffusion by at least 1 (MOSIS 26G rule)" -*/ - -/* 6B.4 & 6B.5 -- - * Watch out here: a spacing "touching_ok" rule CANNOT be used here: - * it will miss certain checks. - */ - edge4way allActive ~(allActive)/act 4 ~(ndc,pdc,nsc,psc)/act \\ - ~(allActive)/act 4 \\ - "Diffusion contacts must be 4 from other diffusions (MOSIS rule #6B.4,5)" - -/* 6B.6 */ - spacing DiffCut allFet 1 touching_illegal \\ - "Diffusion contacts cannot touch transistors (MOSIS rule #6B.6)" - -/* 6B.7 */ - spacing DiffCut poly 1 touching_illegal \\ - "Diffusion contact to field poly must be at least 1 (MOSIS rule #6B.7)" - -/* 6.8 -- not implemented */ - -/* 6B.9 */ - spacing DiffCut pc/act 2 touching_illegal \\ - "Poly contacts must be 2 away from diffusion contacts (MOSIS rule #6B.9)" - -/* ---------------------------------------------------------------- */ -/* Contacts must all be rectangular (no adjacent contacts */ -/* of same type) because of the way their contact is generated by */ -/* CIFoutput section rules. This is handled using the corner checks */ -/* in the rules below. Overlaps between contacts must be exact */ -/* overlaps. The only exception is overpad, which doesn't matter. */ - - edge4way m3c/m3 ~m3c/m3 1 ~m3c/m3 (~m3c,m3c)/m3 1 \\ - "Metal3 contacts must be rectangular (Magic rules)" - edge4way m2c/m2 ~m2c/m2 1 ~m2c/m2 (~m2c,m2c)/m2 1 \\ - "Metal2 contacts must be rectangular (Magic rules)" - - edge4way ndc/m1 ~ndc/m1 1 ~ndc/m1 (~ndc,ndc)/m1 1 \\ - "N-diffusion contacts must be rectangular (Magic rules)" - edge4way pdc/m1 ~pdc/m1 1 ~pdc/m1 (~pdc,pdc)/m1 1 \\ - "P-diffusion contacts must be rectangular (Magic rules)" - edge4way psc/m1 ~psc/m1 1 ~psc/m1 (~psc,psc)/m1 1 \\ - "P-substrate contacts must be rectangular (Magic rules)" - edge4way nsc/m1 ~nsc/m1 1 ~nsc/m1 (~nsc,nsc)/m1 1 \\ - "N-substrate contacts must be rectangular (Magic rules)" - - edge4way pc/m1 ~pc/m1 1 ~pc/m1 (~pc,pc)/m1 1 \\ - "Polysilicon contacts must be rectangular (Magic rules)" - edge4way ec/m1 ~ec/m1 1 ~ec/m1 (~ec,ec)/m1 1 \\ - "Electrode contacts must be rectangular (Magic rules)" - edge4way cc/m1 ~cc/m1 1 ~cc/m1 (~cc,cc)/m1 1 \\ - "Capacitor contacts must be rectangular (Magic rules)" - - edge4way emc/m1 ~emc/m1 1 ~emc/m1 (~emc,emc)/m1 1 \\ - "Emitter contacts must be rectangular (Magic rules)" - edge4way clc/m1 ~clc/m1 1 ~clc/m1 (~clc,clc)/m1 1 \\ - "Collector contacts must be rectangular (Magic rules)" - edge4way pbc/m1 ~pbc/m1 1 ~pbc/m1 (~pbc,pbc)/m1 1 \\ - "P-base Contacts must be rectangular (Magic rules)" - edge4way nbdc/m1 ~nbdc/m1 1 ~nbdc/m1 (~nbdc,nbdc)/m1 1 \\ - "CCD-diffusion Contacts must be rectangular (Magic rules)" - -/* ---------------------------------------------------------------- */ -/* Metal 1 */ -/* ---------------------------------------------------------------- */ -/* 7.1 + 7.2 */ - width allMetal1,pad/m1 3 \\ - "First-level metal width must be at least 3 (MOSIS rule #7.1)" -#ifdef TIGHTMETAL - spacing allMetal1,pad/m1 allMetal1,pad/m1 2 touching_ok \\ - "First-level metal spacing must be at least 2 (MOSIS rule #7.2)" -#else - spacing allMetal1,pad/m1 allMetal1,pad/m1 3 touching_ok \\ - "First-level metal spacing must be at least 3 (MOSIS rule #7.2)" -#endif /* TIGHTMETAL */ - -/* 7.3 + 7.4 */ -/* guaranteed with 4x4 poly and diffusion contacts */ - - -/* ---------------------------------------------------------------- */ -/* Via */ -/* ---------------------------------------------------------------- */ - -/* 8.1 + 8.2 + 8.3 */ - width m2c 4 \\ - "Contact width must be at least 4 (MOSIS rule #8.1,2,3)" - -/* 8.4 + 8.5 */ -/* Vias have to be on flat surface */ -/* Don't allow poly or diffusion edges underneath metal2 contacts: */ -/* this rule is only valid for standard processes, not for those */ -/* processes use planarized interconnection technology. */ -#ifdef STANDARD - edge4way allPoly ~(allPoly)/a 1 ~m2c/m2 ~(allPoly)/a 1 \\ - "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 - edge4way allPoly2 ~(allPoly2)/a 1 ~m2c/m2 ~(allPoly2)/a 1 \\ - "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 - edge4way allActive ~(allActive)/a 1 ~m2c/m2 ~(allActive)/a 1 \\ - "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 - - edge4way ~(allPoly)/a allPoly 1 ~m2c/m2 allPoly 1 \\ - "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 - edge4way ~(allPoly2)/a allPoly2 1 ~m2c/m2 allPoly2 1 \\ - "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 - edge4way ~(allActive)/a allActive 1 ~m2c/m2 allActive 1 \\ - "Via must be on a flat surface (MOSIS rule #8.4,5)" metal2 -#endif /* STANDARD */ - - -/* ---------------------------------------------------------------- */ -/* Metal 2 */ -/* ---------------------------------------------------------------- */ -/* 9.1 */ - width allMetal2 3 \\ - "Second-level metal width must be at least 3 (MOSIS rule #9.1)" - -/* 9.2 */ -#ifdef TIGHTMETAL - spacing allMetal2 allMetal2 3 touching_ok \\ - "Second-level metal spacing must be at least 3 (MOSIS rule #9.2b)" -#else -#ifdef SUBMICRON - spacing allMetal2 allMetal2 3 touching_ok \\ - "Second-level metal spacing must be at least 3 (MOSIS rule #9.2b)" -#else - spacing allMetal2 allMetal2 4 touching_ok \\ - "Second-level metal spacing must be at least 4 (MOSIS rule #9.2a)" -#endif /* SUBMICRON */ -#endif /* TIGHTMETAL */ - -/* 9.3 */ -/* achieved with via size of 4x4 */ - - -/* ---------------------------------------------------------------- */ -/* Overglass */ -/* ---------------------------------------------------------------- */ -/* Rules for overglass (10.1-5) are not check because they are */ -/* either */ -/* 1. absolute micron rules, and */ -/* 2. vender/process dependent. */ -/* except the metal overlap of overglass rule (10.3) can be handled */ -/* case by case in CIFoutput section. */ -/* NOTE: glass layer is NOT usually used. Use "pad" layer for pad */ -/* and the corresponding overglass will be generated automatically. */ - -/* MOSIS rules to make sure there are m2 under glass - for those */ -/* users who like to use explicit "glass" layer... */ -/* */ -/* edge4way space glass 1 allMetal2 0 0 \ */ -/* "There must be metal 2 under the glass opening" metal2 */ -/* */ -/* I am removing this rule simply we have metal3 now and there's no */ -/* way to tell which process the pad is intended for. Basically, I */ -/* am enforcing the use of "pad" layer... */ - - - -/* ---------------------------------------------------------------- */ -/* Open and Pstop */ -/* ---------------------------------------------------------------- */ -/* The open layer is actually a combination of overglass and */ -/* contacts to expose the intrinsic silicon surface for future */ -/* etchimg process for micromachining device fabrication. */ -/* Since lots of applications are possible, there is no rules */ -/* enforced by Magic. Designers aimed at micromachining devices */ -/* must do DRC themself :-) */ -/* See the following reference for detail: */ -/* "High-Level CAD Melds Micromachined Devices with Foundaries", */ -/* Janet C. Marshall, M. Parameswaran, Mona E. Zaghloul, and */ -/* Michael Gaitan, IEEE Circuit and Devices, Vol. 8, No. 6, */ -/* pp. 10-17, 1992 */ - - - -/* ---------------------------------------------------------------- */ -/* Poly2 as Capacitor */ -/* ---------------------------------------------------------------- */ -/* 11.1 */ -/* The exact rule asks for 3 lambda minimum width for 'capacitor'. */ -/* But there are overlaps of poly/eletrode structures such that 2 */ -/* is fine, such as the overlaps in floating gates. So we are risk- */ -/* ing a little here... */ - width cap,capc/a 2 \\ - "Electrode capacitor width must be at least 3 (MOSIS rule #11.1)" - -/* 11.2 + 12.2 */ - spacing allPoly2 allPoly2 3 touching_ok \\ - "Second-level poly spacing must be at least 3 (MOSIS rule #11.2,12.2)" - -/* 11.3 */ - edge4way cap,cc space 1 0 0 0 \\ - "Cap must be overlapped by poly or poly2 (MOSIS rule #11.3)" - edge4way cap,cc poly 2 poly poly 2 \\ - "Cap must be overlapped by poly or poly2 (MOSIS rule #11.3)" - edge4way cap,cc poly2 2 poly2 poly2 2 \\ - "Cap must be overlapped by poly or poly2 (MOSIS rule #11.3)" - -/* 11.4 */ - edge4way nw,pw,cw ~(nw,pw,cw)/w 2 ~(cap,cc)/a ~(nw,pw,cw)/w 2 \\ - "Cap must be on a flat surface (MOSIS rule #11.4)" active - edge4way ~(nw,pw,cw)/w nw,pw,cw 2 ~(cap,cc)/a nw,pw,cw 2 \\ - "Cap must be on a flat surface (MOSIS rule #11.4)" active - edge4way cap ~(cap)/a 2 allFet,poly,poly2,space/a,cc/a \\ - allDiff,poly 2 "Cap must be on a flat surface (MOSIS rule #11.4)" active - -/* 11.5 */ -/* Done by 11.3 and 11.4 */ - - -/* ---------------------------------------------------------------- */ -/* Poly2 as Transistor */ -/* ---------------------------------------------------------------- */ -/* 12.1 */ - width allPoly2 2 \\ - "Electrode width must be at least 2 (MOSIS rule #12.1)" - -/* 12.2 */ -/* Done by 11.2 */ - -/* 12.3 */ - edge4way enfet,epfet poly2,ec/a 2 poly2,ec/a 0 0 \\ - "Poly2 must overhang transistor by at least 2 (MOSIS rule #12.3)" - edge4way nffet,pffet cap 2 cap 0 0 \\ - "Cap must overhang transistor by at least 2 (MOSIS rule #12.3)" - edge4way nffet ~(cap,nffet,enfet,nfet)/a 2 cap 0 0 \\ - "Cap must overhang doubletransistor by at least 2 (MOSIS rule #12.3)" - edge4way pffet ~(cap,pffet,epfet,pfet)/a 2 cap 0 0 \\ - "Cap must overhang doubletransistor by at least 2 (MOSIS rule #12.3)" - -/* 12.4 */ - edge4way allDiff,allOhmic el 1 space/a 0 1 \\ - "Poly2 and diffusion must be separated by at least 1 (MOSIS rule #12.4)" - -/* 12.5 */ - -/* 12.6 */ - spacing allPoly2 pc,ndc,pdc 2 touching_illegal \\ - "Poly2 spacing to poly or diffusion contact must be at least 3 (MOSIS rule #12.6)" -/* - edge4way poly2,ec/a epfet 3 epfet 0 0 \\ - "Transistors must be at least 3 units wide (MOSIS rule #2)" - edge4way poly2,ec/a enfet 3 enfet 0 0 \\ - "Transistors must be at least 3 units wide (MOSIS rule #2)" - edge4way cap,capc/a pffet 3 pffet 0 0 \\ - "Transistors must be at least 3 units wide (MOSIS rule #2)" - edge4way cap,capc/a nffet 3 nffet 0 0 \\ - "Transistors must be at least 3 units wide (MOSIS rule #2)" -*/ - - -/* ---------------------------------------------------------------- */ -/* Poly2 Contact */ -/* ---------------------------------------------------------------- */ -/* 13.1 + 13.2 */ - width ec,capc 4 \\ - "Electrode contact width must be at least 4 (MOSIS rule #13.1)" - -/* 13.3 */ -/* Done by 11.3 */ - -/* 13.4 */ - edge4way ec/a space 1 poly2 poly2 1 \\ - "Electrode contact must be overlaped by poly2 (MOSIS rule #13.4)" - edge4way ec/a poly2 1 poly2 poly2 1 \\ - "Electrode contact must be overlaped by poly2 by 1 (MOSIS rule #13.4)" - -/* 13.5 */ - edge4way allDiff,allOhmic ec 2 space/a 0 2 \\ - "Poly2 and diffusion contact must be separated by at least 2 (MOSIS rule #13.5)" - - -/* ---------------------------------------------------------------- */ -/* Via 2 */ -/* ---------------------------------------------------------------- */ -/* 14.1 + 14.2 + 14.3 */ -/* By CIF output generation */ - width m3c 4 \\ - "Third-level metal contact width must be at least 4 (MOSIS rule #14.1,2,3)" - -/* 14.4 */ -/* guaranteed by 4x4 m2c and 4x4 m3c */ -/* Via2, i.e "m3c" can overlap anything except m2c layer */ - - -/* ---------------------------------------------------------------- */ -/* Metal 3 */ -/* ---------------------------------------------------------------- */ -/* 15.1 */ -#ifdef SUBMICRON - width allMetal3 5 \\ - "Third-level metal width must be at least 5 (MOSIS rule #15.1b)" -#else - width allMetal3 6 \\ - "Third-level metal width must be at least 6 (MOSIS rule #15.1a)" -#endif - -/* 15.2 */ -#ifdef SUBMICRON - spacing allMetal3 allMetal3 3 touching_ok \\ - "Third-level metal spacing must be at least 3 from other third-level metal (MOSIS rule #15.2b)" -#else - spacing allMetal3 allMetal3 4 touching_ok \\ - "Third-level metal spacing must be at least 4 from other third-level metal (MOSIS rule #15.2a)" -#endif - -/* 15.3 */ - edge4way m3c/m3 ~m3c/m3 1 m3 m3 1 \\ - "Mimimum metal3 overlap of via must be at least 1 (MOSIS rule #15.3)" - - -/* ---------------------------------------------------------------- */ -/* NPN Bipolar */ -/* ---------------------------------------------------------------- */ -/* 16.1 */ -/* As always, composite contacts are 4x4, where the actual */ -/* transistor contacts are 2x2 by CIF output generator */ - width clc,pbc,emc 4 \\ - "Transistor contact width must be at least 4 (MOSIS rule #16.1)" - -/* 16.2 */ -/* Done by 16.1 4x4 emc and CIF output generation */ - -/* 16.3 */ -/* This rule is guaranteed by the way the CIF output generates */ -/* N-Select for emitter (expand by 2 lambda), so we have Pbase */ -/* overlap of emitter(or emc) by 2+2 =4 */ - edge4way emc/a,emit pbase 4 pbase pbase 4 \\ - "Pbase overlap of emitter must be at least 4 (MOSIS rule #16.3)" - -/* 16.4 */ -/* NOTE; NO need to make this an edge rule... */ - spacing pbc emc/a,emit 7 touching_illegal \\ - "Base must be 7 (4+2+1) away from emitter (MOSIS rule #16.3,4,11)" - -/* 16.5 */ -/* This rule is guaranteed by requiring that base contact has */ -/* at least 3 (1+2) lambda base enclosure... */ -/* edge4way pbc/a pb,space 3 pb pb,space 3 */ - edge4way pbc (~pbc)/a 3 pb,pbc/a pb,pbc/a 3 \\ - "Pbase overlap of base contact must be at least 3 (MOSIS rule #16.5)" - -/* 16.6 */ -/* This rule is guaranteed by the CIF output generation of P-select */ - -/* 16.6 */ -/* This rule is enforced by checking whether collector is out of */ -/* Nwell and the fact that collector width is required to be at */ -/* least 6 */ - width col,clc/a 6 \\ - "Collector width must be at least 6 (MOSIS rule #16.6)" - -/* 16.7 */ -/* Explicit Nwell required for Bipolar transistors... */ - edge4way pbase space/a 6 nwell space/a 6 \\ - "Nwell overlap of Pbase must be at least 6 (MOSIS rule #16.7)" well - -/* 16.8 */ - edge4way pbase (~pbase)/a 4 ~(col,clc)/a ~(col,clc)/a 4 \\ - "Pbase must be at least 4 away from collector (MOSIS rule #16.8)" - -/* 16.9 */ - edge4way clc (~clc)/a 1 col col 1 \\ - "Collector overlap of contact must be at least 1 (MOSIS rule #16.9)" - -/* 16.10 */ -/* This rule is guaranteed by making sure that collector is within */ -/* PBase and the corresponding CIF output generation */ - -/* 16.11 */ - edge4way nw ~(nw)/w 3 ~(col,clc)/a ~(nw)/w 3 \\ - "N-well overlap of collector must be at least 3 (MOSIS rule #16.11)" active - edge4way ~(nw)/w nw 3 ~(col,clc)/a nw 3 \\ - "N-well overlap of collector must be at least 3 (MOSIS rule #16.11)" active - -/* This is a special rule to guarantee the emitter width */ - width em,emc/a 4 \\ - "Emitter width must be at least 4 (Magic Bipolar Transistor rule)" - -/* This is a special rule for multi-emitters transistor according */ -/* to rule 16.2 and 2.2 */ - spacing em,emc/a em,emc/a 7 touching_ok \\ - "Unrelated emitter must be at least 7 apart (Magic Bipolar transistor rule)" - -/* The following rules are added for pbase resistor implementation. */ -/* They are not in the official SCMOS design rules since I have no */ -/* foundry rules available at this moment and the numbers here is */ -/* considered to be conservative... */ - width pbase,pbc/a 4 \\ - "Pbase width must be at least 4 (MOSIS extension rule)" - - spacing pbase,pbc/a pbase,pbc/a 4 touching_ok \\ - "Pbase spacing must be at least 4 (MOSIS extension rule)" - -/* ---------------------------------------------------------------- */ -/* Capacitor Well */ -/* ---------------------------------------------------------------- */ -/* These are DRC rules for Capacitor Well (CWell) according to HP's */ -/* 1.2um linear capacitor process pi@isi.edu 9/18/92 */ -/* ---------------------------------------------------------------- */ - -/* 17.1 */ - width cwell 10 \\ - "Cap-well width must be at least 10 (MOSIS rule #17.1)" - -/* 17.2 */ - spacing cwell cwell 9 touching_ok \\ - "Cap-well spacing must be at least 9 (MOSIS rule #17.2)" - spacing cwell nwell 9 touching_illegal \\ - "Cap-well spacing must be at least 9 (MOSIS rule #17.2)" - -/* 17.3 */ - edge4way cwell space 5 ~(allNActive)/a ~(allNActive)/w 5 \\ - "Cap-well spacing to external active must be at least 5 (MOSIS rule #17.3)" active - edge4way cwell space 3 ~(allPOhmic)/a ~(allPOhmic)/w 3 \\ - "P-substrate diffusion and Cap-well must be separated by 3 (MOSIS rule #17.3)" active - - -/* 17.4 */ -/* Need to do this check from the Cap-well plane - in order Not */ -/* to conflict with the general rules for N-diffusion */ - edge4way space cwell 3 (space,poly,pc)/a 0 0 \\ - "Cap-well overlap of diffusion must be at least 3 (MOSIS rule #17.4)" active - -/* ---------------------------------------------------------------- */ -/* Well-capacitor */ -/* ---------------------------------------------------------------- */ -/* These are DRC rules for Well-capacitor (wcap) according to HP's */ -/* 1.2um linear capacitor process pi@isi.edu 9/18/92 */ -/* Rule 18.5 and 18.6 are preliminary, they are conservative here! */ -/* ---------------------------------------------------------------- */ -/* 18.1 */ - width wcap 3 \\ - "Well-capacitor must be at least 3 (MOSIS rule #18.1)" - -/* 18.2 */ -/* achieved by rule 3.5 */ - -/* 18.3 */ - edge4way wcap space 1 poly poly 1 \\ - "Well-capacitor overhang is missing (MOSIS rule #18.3)" - -/* 18.4 */ - edge4way wcap ndiff 3 ndiff ndiff 3 \\ - "N-diffusion overlap of well-capacitor must be at least 3 (MOSIS rule #18.4)" - -/* 18.5 */ -/* achieved by rule 5B.6 */ - spacing wcap pc 2 touching_illegal \\ - "Well-capacitor spacing to poly contact must be at least 2 (MOSIS rule #18.5)" - - -/* 18.6 */ -/* similar to rule 6A.4 or 6B.6 */ - spacing wcap ndc 4 touching_illegal \\ - "Well-capacitor spacing to diffusion contact must be at least 4 (MOSIS rule #18.6)" - - -/* ---------------------------------------------------------------- */ -/* Buried CCD */ -/* ---------------------------------------------------------------- */ -/* 19.1 */ -/* Have to do it seperately... */ - width nbd,nbdc,bd/a 4 \\ - "CCD channel width must be at least 4 (MOSIS rule #19.1)" - width nbdc 4 \\ - "CCD contact width must be at least 4 (MOSIS rule #19.1)" - - -/* 19.2 */ -/* The 4 lambda spacing is a conservative guess here... */ -/* This following rule will NOT work! Need to check 2 planes */ -/* separately.... */ -/* - spacing bd/a,nbd,nbdc bd/a,nbd,nbdc 4 touching_ok \\ - "CCD channel spacing must be at least 4 (MOSIS rule #19.2)" -*/ - edge4way nbd,nbdc ~(bd,nbd,nbdc)/a 4 (bd,space)/i 0 0 \\ - "CCD channel spacing must be at least 4 (MOSIS rule #19.2)" implant - edge4way nbd,nbdc ~(poly,nbd,nbdc)/a 4 ~(poly,nbd,nbdc)/a ~(poly,nbd,nbdc)/a 4 \\ - "CCD channel spacing must be at least 4 (MOSIS rule #19.2)" active - -/* 19.3 + 19.4 + 19.5 */ -/* guaranteed by the CIF output generation */ - -/* 19.6 */ -/* This first one check poly and electrode overhang */ - edge4way bd space 2 nbd,poly,cap,el 0 0 \\ - "CCD channel overhang is missing (MOSIS rule #19.6)" active -/* There is a problem with capacitor overhang, I have no way to do */ -/* it now... */ - -/* MOSIS extension BCCD layout rule */ - spacing nbdc poly,el 1 touching_illegal \\ - "CCD-diffusion contact spacing to poly must be at least 1 (MOSIS CCD rule)" - edge4way nbd poly,el 1 bd 0 0 \\ - "Missing Buried CCD Difussion layer (MOSIS CCD rule)" implant - -/* ---------------------------------------------------------------- */ -/* High-Voltage MOSFETs */ -/* ---------------------------------------------------------------- */ -/* These are DRC rules for AMI 1.5 micron process for high-voltage */ -/* MOSFETs pi@isi.edu 10/01/92 */ -/* */ -/* ---------------------------------------------------------------- */ -/* 20.1 */ -/* Well spacing for different potential must be 12 lambda away now. */ -/* These rules correspond to 1.1 + 1.2 rules */ -/* width rule is as usual */ - edge (~hnwell)/w hnwell 10 hnwell hnwell 10\\ - "High-Voltage N-Well width must be at least 10 (MOSIS rule #1.1)" - edge (~hpwell)/w hpwell 10 hpwell hpwell 10\\ - "High-Voltage P-Well width must be at least 10 (MOSIS rule #1.1)" -/* spacing rules are new */ - edge hnwell space,pw,hpw 9 space,pw,hpw space,pw,hpw 9\\ - "High-Voltage N-Well spacing to N-Well must be at least 9 (MOSIS rule #1.2)" - edge hpwell space,nw,hnw 9 space,nw,hnw space,nw,hnw 9\\ - "High-Voltage P-Well spacing to P-Well must be at least 9 (MOSIS rule #1.2)" - edge hnwell space,pw,hpw,nw 12 space,pw,hpw,nw space,pw,hpw,nw 12\\ - "High-Voltage N-Well spacing must be at least 12 (MOSIS rule #20.1)" - edge hpwell space,nw,hnw,pw 12 space,nw,hnw,pw space,nw,hnw,pw 12\\ - "High-Voltage P-Well spacing must be at least 12 (MOSIS rule #20.1)" - -/* 20.2 */ -/* High-Voltage Active spacing must be at least 5 lambda away */ -/* This rule corresponds to 2.2 rule */ -#define allHVNActive hndiff,hndc/a,hnfet -#define allHVPActive hpdiff,hpdc/a,hpfet - edge4way ~(allHVDiff)/a allHVDiff 3 allHVDiff allHVDiff 3\\ - "High-Voltage Diffusion width must be at least 3 (MOSIS rule #2.1)" - spacing allHVNActive allHVNActive 5 touching_ok \\ - "High-Voltage Diffusion spacing must be at least 5 (MOSIS rule #20.2)" - spacing allHVPActive allHVPActive 5 touching_ok \\ - "High-Voltage Diffusion spacing must be at least 5 (MOSIS rule #20.2)" - -/* 20.3 */ -/* High-Voltage transistors spacing to Well edge must be 7 lambda */ -/* This rule corresponds to rule 2.3 */ -/* without explicit well definition */ - spacing hndiff,hndc/a hpdiff,hpdc/a 14 touching_illegal \\ - "P-type diffusion must be 14 away from N-type diffusion (MOSIS rule #20.3)" - spacing hndiff,hndc/a allPDiff 12 touching_illegal \\ - "P-type diffusion must be 12 away from N-type diffusion (MOSIS rule #20.3+2.3)" - spacing hpdiff,hpdc/a allNDiff 12 touching_illegal \\ - "P-type diffusion must be 12 away from N-type diffusion (MOSIS rule #20.3+2.3)" - -/* with explicit well definition */ - spacing hndiff,hnfet,hndc/a hnwell 7 touching_illegal \\ - "HVN-diffusion and HVN-well must be separated by 7 (MOSIS rule #20.3)" - spacing hpdiff,hpfet,hpdc/a hpwell 7 touching_illegal \\ - "HVP-diffusion and HVP-well must be separated by 7 (MOSIS rule #20.3)" - spacing allNOhmic hpwell 3 touching_illegal \\ - "N-substrate diffusion and HVP-well must be separated by 3 (MOSIS rule #2.4+20.3)" - spacing allPOhmic hnwell 3 touching_illegal \\ - "P-substrate diffusion and HVN-well must be separated by 3 (MOSIS rule #2.4+20.3)" - -/* 20.4 */ -/* Poly1 must not be used as an transistor for high-voltage design */ -/* guaranteed by the composition rules */ - -/* 20.5 */ -/* High-Voltage Active overlap of contact is now 2 lambda */ -/* This rule corresponds to rule 6B.2 */ - edge (~hndc)/a hndc/a 6 hndc/a hndc/a 6\\ - "High-Voltage Diffusion contact width must be at least 6 (MOSIS rule #20.5)" - edge (~hpdc)/a hpdc/a 6 hpdc/a hpdc/a 6\\ - "High-Voltage Diffusion contact width must be at least 6 (MOSIS rule #20.5)" - -/* 20.6 */ -/* High-Voltage transistor channel length must be at least 4 lambda */ - edge hpdiff,hpdc/a hpfet 4 hpfet 0 0 \\ - "High-Voltage transistor must be at least 4 units long (MOSIS rule #20.6)" - edge hndiff,hndc/a hnfet 4 hnfet 0 0 \\ - "High-Voltage transistor must be at least 4 units long (MOSIS rule #20.6)" - - - -/* ---------------------------------------------------------------- */ -/* overlapping rules */ - exact_overlap m3c,m2c,ndc,pdc,pc,psc,nsc,ec,capc,clc,emc,pbc,hndc,hpdc,hnsc,hpsc - no_overlap pfet,nfet pfet,nfet - no_overlap epfet,enfet epfet,enfet - no_overlap pffet,nffet pffet,nffet - no_overlap hpfet,hnfet hpfet,hnfet - -end - - -extract - - - -#ifndef OLD_EXTRACT_STYLE - -#include "scmosExt.tech.in" - -#else -/* In the following, MOSIS provides 9 extraction styles as follows: - - SCNA20(ORB) - ORBIT 2.0 micron low-noise analog N-well CMOS/BJT - process. *default* - SCPE20(ORB) - ORBIT 2.0 micron P-well CMOS/Bulk process. - SCNA16(AMI) - AMI 1.6 micron N-well CMOS/Junction-isolated BJT - process. - SCN12LC(HP) - HP CMOS34 1.2 micron N-well CMOS/Bulk process with - linear capacitor option. - SCNE12(ORB) - ORBIT 1.2 micron 2 poly N/P-well CMOS process. - SCN10(MOT) - MOTOROLA 1.0 micron N-well/P-epi CMOS process. - * Not Available at this moment * - SCN08(HP) - HP CMOS26B 1.0 micron N-well CMOS/Bulk process. - SCN08(IBM) - IBM 0.8 micron N-well CMOS/Bulk process. - * Not Available at this moment * - - Whenever it is available, measured data on MOSIS test structures - is used. Data is obtained from a representitive run (usually the - latest run at the time). If not available, typical (or nominal) - data from vendor wafer specification is used if not specifically - noted. - -*/ - -/* Have to redefine allMetal1 to make it pure metal line here... */ - -#undef allMetal1 -#define allMetal1 m1,m2c/m1 - - -#ifdef STANDARD -style SCNA20(ORB) -/* The following data is obtained from MOSIS run 'n34o' */ -/* Last modified by pi@isi.edu, 9/29/93 */ - - /* Define plane order first */ -#ifdef V5 - planeorder well 0 - planeorder implant 1 - planeorder active 2 - planeorder metal1 3 - planeorder metal2 4 - planeorder metal3 5 - planeorder oxide 6 -#endif - - cscale 1 - lambda 100 - step 100 - /* No parallel wire coupling capacitances */ - sidehalo 0 - - /* Sheet resistance (in milliohms per square) */ - resist ndiff,nsd,ndc/a,nsc/a 27260 - resist pdiff,psd,pdc/a,psc/a 59550 - resist allPoly 23430 - resist allPoly2 19690 - resist em,emc/a 27260 - resist pbase,pbc/a 2000000 - resist metal1,m2c/metal1 52 - resist metal2,pad 26 - resist nwell 2505830 - - /* Contact resistance (in milliohms per square) */ - contact pc/a 4 11000 - contact ec/a,capc/a 4 9000 - contact ndc/a,nsc/a 4 18710 - contact pdc/a,psc/a 4 100560 - - /* Area parasitic capacitance to substrate (in attofarads per - lambda square) - [ 1 lambda = 1.0 micron ---> multiplication factor 1.0 ] - NOTE: Since most of the simulation tools have already - included the gate-oxide capacitance, it is NOT - extracted here. If you need it explictly, remove the - following comment. */ - areacap poly,pc/a 39 - areacap metal1,pad,m2c/metal1 24 - areacap metal2 19 -/* - areacap ndiff,ndc/a 220 - areacap pdiff,pdc/a 270 -*/ - areacap cc/a,cap 39 - areacap poly2,ec/a 50 - - /* Inter-layer capacitance */ - overlap metal1 pdiff,ndiff,psd,nsd 47 - overlap metal2 pdiff,ndiff,psd,nsd 22 metal1 - overlap metal1 poly 30 - overlap metal2 poly 19 metal1 - overlap metal2 metal1 45 - overlap metal1 poly2 40 - - /* Perimeter parasitic capacitances (in attofarads per lambda) - [ 1 lambda = 1.0 micron ---> multiplication factor 1.0 ] */ -/* - perimc ndiff,ndc/a space,pwell 559 - perimc pdiff,pdc/a space,nwell 402 -*/ - perimc poly,pc/a space,pwell,nwell 80 - - /* Active devices: N-Well process */ - fet pfet pdiff,pdc,pffet 2 pfet Vdd! nwell 0 0 - fet nfet ndiff,ndc,nffet 2 nfet GND! pwell 0 0 - fet epfet pdiff,pdc,pffet 2 epfet Vdd! 0 0 - fet enfet ndiff,ndc,nffet 2 enfet GND! 0 0 - - /* Kludge for MOS capacitance extraction, where source and drain - are connected together */ - fet pfet pdiff,pdc,pffet 1 pfet Vdd! nwell 0 0 - fet nfet ndiff,ndc,nffet 1 nfet GND! pwell 0 0 - - /* Electrode capacitance extraction */ - device capacitor None cap,capc/a poly,pc 120 735 - - /* DRAM capacitance extraction */ - device capacitor None wcap ndiff,ndc 300 0 - - /* bipolar NPN extraction */ - device bjt npn emit,emc/a pbase,pbc/a nwell - -style SCPE20(ORB) - -/* The following data is obtained from MOSIS run 'n35s', 6/93 */ -/* Last modified by pi@isi.edu, 9/29/93 */ - - cscale 1 - lambda 100 - step 100 - /* No parallel wire coupling capacitances */ - sidehalo 0 - - /* Define plane order first */ -#ifdef V5 - planeorder well 0 - planeorder implant 1 - planeorder active 2 - planeorder metal1 3 - planeorder metal2 4 - planeorder metal3 5 - planeorder oxide 6 -#endif - - /* Sheet resistance (in milliohms per square) */ - resist ndiff,nsd,ndc/a,nsc/a 26670 - resist pdiff,psd,pdc/a,psc/a 72860 - resist allPoly 23860 - resist allPoly2 18540 - resist metal1,m2c/metal1 49 - resist metal2,pad 26 - resist pwell 2128280 - - /* Contact resistance (in milliohm per contact) */ - contact pc/a 4 12800 - contact ec/a,capc/a 4 8420 - contact ndc/a,nsc/a 4 36660 - contact pdc/a,psc/a 4 56300 - contact m2c/m1 5 30 - - /* Area parasitic capacitance to substrate (in attofarads per - lambda square) - [ 1 lambda = 1.0 micron ---> multiplication factor 1.0 ] - NOTE: Since most of the simulation tools have already - included the gate-oxide capacitance, it is NOT - extracted here. If you need it explictly, remove the - following comment. */ - areacap poly,pc/a 57 - areacap allMetal1,DiffMetal,HVDiffMetal 41 - areacap PolyMetal,BiMetal,CCDMetal 41 - areacap allMetal2 21 -/* - areacap ndiff,ndc/a 398 - areacap pdiff,pdc/a 230 -*/ - - /* Inter-layer capacitance */ - overlap metal1 pdiff,ndiff,psd,nsd 36 - overlap metal2 pdiff,ndiff,psd,nsd 16 metal1 - overlap metal1 poly 33 - overlap metal2 poly 15 metal1 - overlap metal2 metal1 29 - overlap metal1 poly2,cap 33 - - /* Perimeter parasitic capacitances (in attofarads per lambda) - [ 1 lambda = 1.0 micron ---> multiplication factor 1.0 ] */ -/* - perimc ndiff,ndc/a space,pwell 423 - perimc pdiff,pdc/a space,nwell 85 -*/ - perimc poly,pc/a space,pwell,nwell 168 - - /* Active devices: P-Well process */ - fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 - fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 - - -style SCNA16(AMI) - -/* The following data is obtained from MOSIS run 'n34l', 6/93 */ -/* Last modified by pi@isi.edu, 9/29/93 */ - - cscale 1 - lambda 80 - step 100 - /* No parallel wire coupling capacitances */ - sidehalo 0 - - /* Define plane order first */ -#ifdef V5 - planeorder well 0 - planeorder implant 1 - planeorder active 2 - planeorder metal1 3 - planeorder metal2 4 - planeorder metal3 5 - planeorder oxide 6 -#endif - - /* Sheet resistance (in milliohms per square) */ - resist ndiff,nsd,ndc/a,nsc/a 51680 - resist pdiff,psd,pdc/a,psc/a 74800 - resist allPoly 34780 - resist allPoly2 22400 - resist allMetal1 48 - resist allMetal2 28 - resist nwell 1446400 - - /* Contact resistance (in milliohm per contact) */ - contact pc 4 61560 - contact ec 4 12010 - contact ndc,nsc 4 45780 - contact pdc,psc 4 32310 - contact m2c 5 37570 - - /* Area parasitic capacitances (in attofarads per lambda square) - [ 1 lambda = 0.8 micron ---> multiplication factor 0.64 ] - NOTE: Since most of the simulation tools have already - included the gate-oxide capacitance, it is NOT - extracted here. If you need it explictly, remove the - following comment. */ - /* areacap nfet 709 */ - /* areacap pfet 669 */ - areacap poly,pc/a 22 - areacap allMetal1,DiffMetal,HVDiffMetal 15 - areacap PolyMetal,BiMetal,CCDMetal 15 - areacap allMetal2 10 - - /* Inter-layer capacitance */ - overlap allMetal1 ndiff,nsd 27 - overlap allMetal1 pdiff,psd 27 - overlap allMetal2 pdiff,psd 12 metal1 - overlap allMetal1 allPoly 25 - overlap allMetal1 allP2 25 - overlap allMetal2 allPoly 11 metal1 - overlap metal2 metal1 23 - /* Junction capacitance */ -/* - overlap ndiff,ndc/a space,pwell 172 - overlap pdiff,pdc/a space,nwell 200 -*/ - - /* Perimeter parasitic capacitances (in attofarads per lambda) - [ 1 lambda = 0.8 micron ---> multiplication factor 0.8 ] */ -/* - perimc ndiff,ndc/a space,allWell 6 - perimc pdiff,pdc/a space,allWell 68 -*/ - - /* Active devices: N-Well process, */ - fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 - fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 - - -style SCNE12(ORB) - -/* The following data is obtained from MOSIS run 'n37d', 7/93 */ -/* Last modified by pi@isi.edu, 9/29/93 */ - - cscale 1 - lambda 60 - step 100 - /* No parallel wire coupling capacitances */ - sidehalo 0 - - /* Define plane order first */ -#ifdef V5 - planeorder well 0 - planeorder implant 1 - planeorder active 2 - planeorder metal1 3 - planeorder metal2 4 - planeorder metal3 5 - planeorder oxide 6 -#endif - - /* Sheet resistances (in milliohms per square) */ - resist ndiff,nsd,ndc/a,nsc/a 43180 - resist pdiff,psd,pdc/a,psc/a 79770 - resist allPoly 22160 - resist allPoly2 21140 - resist allMetal1 51 - resist allMetal2 26 - resist nwell 1195000 - - /* Contact resistances (in milliohm per contact) */ - contact pc 4 13230 - contact ec 4 13510 - contact ndc,nsc 4 56490 - contact pdc,psc 4 181400 - contact m2c 5 43330 - - - /* Area parasitic capacitances (in attofarads per lambda square) - [ 1 lambda = 0.6 micron ---> multiplication factor 0.36 ] - NOTE: Since most of the simulation tools have already - included the gate-oxide capacitance, it is NOT - extracted here. If you need it explictly, remove the - following comment. */ - /* areacap nfet 454 */ - /* areacap pfet 368 */ - areacap poly,pc/a 29 - areacap allMetal1,DiffMetal,HVDiffMetal 16 - areacap PolyMetal,BiMetal,CCDMetal 16 - areacap allMetal2 10 - - overlap allMetal1 ndiff,ndc/a 22 - overlap allMetal1 allPoly 19 - overlap allMetal1 allP2 21 - overlap allMetal2 ndiff,ndc/a 8 - overlap allMetal2 allPoly 7 - overlap metal2 metal1 12 - /* Junction capacitance */ - overlap ndiff,ndc/a space,pwell 185 - overlap pdiff,pdc/a space,nwell 148 - - /* Perimeter parasitic capacitances (in attofarads per lambda) - [ 1 lambda = 0.6 micron ---> multiplication factor 0.6 ] */ - perimc allMetal1 space,allWell 41 - perimc allMetal2 space,allWell 42 - /* Junction capacitances */ -/* - perimc ndiff,ndc/a space,pwell 236 - perimc pdiff,pdc/a space,nwell 147 -*/ - - /* No measurements for this run, but leave here for future... - sideoverlap allMetal1 space,allWell PNplus 60 - sideoverlap allMetal2 space,allWell allPoly 60 - sideoverlap allMetal2 space,allWell PNplus 57 - sideoverlap allMetal2 space,allWell allPoly 57 - sideoverlap allMetal2 space,allWell allMetal1 64 - */ - - /* Nwell process, so PMOS has "nwell" defined for analog - designs... */ - fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 - fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 - - -#endif /* STANDARD */ - -#ifdef TIGHTMETAL -style SCN12LC(HP) - -/* The following data is obtained from MOSIS run 'n36y', 7/93 */ -/* Last modified by pi@isi.edu, 9/29/93 */ - - cscale 1 - lambda 60 - step 100 - /* No parallel wire coupling capacitances */ - sidehalo 0 - - /* Define plane order first */ -#ifdef V5 - planeorder well 0 - planeorder implant 1 - planeorder active 2 - planeorder metal1 3 - planeorder metal2 4 - planeorder metal3 5 - planeorder oxide 6 -#endif - - /* Sheet resistance (in milliohms per square) */ - resist ndiff,nnd,ndc/a,nsc/a 74630 - resist pdiff,ppd,pdc/a,psc/a 109590 - resist poly,pc/a,pfet,nfet 26620 - resist allMetal1 60 - resist allMetal2 39 - resist nwell 1500000 - - /* Contact resistance (in milliohm per contact) */ - contact ndc 4 77000 - contact pdc 4 44260 - contact pc 4 16210 - contact m2c 5 86560 - - /* Area parasitic capacitances (in attofarads per lambda square) - [ 1 lambda = 0.6 micron ---> multiplication factor 0.36 ] - NOTE: Since most of the simulation tools have already - included the gate-oxide capacitance, it is NOT - extracted here. If you need it explictly, remove the - following comment. */ - /* areacap nfet 556 */ - /* areacap pfet 489 */ - areacap poly,pc/a 22 - areacap allMetal1,DiffMetal,HVDiffMetal 14 - areacap PolyMetal,BiMetal,CCDMetal 14 - areacap allMetal2 9 - - /* Inter-layer capacitance */ - overlap allMetal1 allPoly 24 - overlap allMetal2 allPoly 7 metal1 - overlap metal2 metal1 14 - /* Junction capacitance */ -/* - overlap ndiff,ndc/a space,pwell 106 - overlap pdiff,pdc/a space,nwell 183 -*/ - - /* Perimeter parasitic capacitances (in attofarads per lambda) - [ 1 lambda = 0.6 micron ---> multiplication factor 0.6 ] */ - /* perimc nfet ndiff 90 */ - /* perimc pfet pdiff 817 */ - /* Junction capacitances */ -/* - perimc ndiff,ndc/a space,allWell 102 - perimc pdiff,pdc/a space,allWell 2 -*/ - - /* Active devices: Nwell process, so PMOS has "nwell" defined - for analog designs... */ - fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 - fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 - /* Kludge for DRAM capacitance extraction */ - fet wcap ndiff,ndc 1 wcap GND! 300 0 - -/* These stuff are experimental..... - fake npn: - fet emit,emc/a pbase 1 d1np XSLLU! nwell 0 0 - fet fpb nwell 1 d2pn YSLLU! col,clc 0 0 - */ - -/* saturation :: R = V (5V) / Idss - fetresist nfet saturation 12000 - fetresist pfet saturation 28000 - fetresist enfet saturation 12000 - fetresist epfet saturation 28000 - - I am not sure how to do this yet, so I give the same value as - saturation! - - fetresist nfet linear 12000 - fetresist pfet linear 28000 - fetresist enfet linear 12000 - fetresist epfet linear 28000 - */ - - -style SCN08(HP) - -/* The following data is obtained from MOSIS run 'n33h', 7/93 */ -/* Last modified by pi@isi.edu, 9/29/93 */ - - cscale 1 - lambda 50 - step 100 - /* Parallel wire coupling capacitance enabled */ - sidehalo 8 - - /* Define plane order first */ -#ifdef V5 - planeorder well 0 - planeorder implant 1 - planeorder active 2 - planeorder metal1 3 - planeorder metal2 4 - planeorder metal3 5 - planeorder oxide 6 -#endif - - /* Sheet resistance (in milliohms per square) */ - resist ndiff,nsd,ndc/a,nsc/a 2280 - resist pdiff,psd,pdc/a,psc/a 1990 - resist poly 3480 - resist allMetal1 67 - resist allMetal2 65 - resist allMetal3 29 - resist nwell 1265560 - - /* Contact resistance (in milliohm per contact) */ - contact pc 4 1680 - contact ndc,pdc,nsc,psc 4 1100 - contact m2c 5 305 - contact m3c 5 259 - - /* Area parasitic capacitances (in attofarads per lambda square) - [ 1 lambda = 0.5 micron ---> multiplication factor 0.25 ] - NOTE: Since most of the simulation tools have already - included the gate-oxide capacitance, it is NOT - extracted here. If you need it explictly, remove the - following comment. */ - /* areacap nfet 457 */ - /* areacap pfet 403 */ - areacap poly,pc/a 16 - areacap allMetal1,DiffMetal,HVDiffMetal 9 - areacap PolyMetal,BiMetal,CCDMetal 9 - areacap allMetal2 5 - areacap allMetal3 4 - - /* Inter-layer capacitance */ - overlap allMetal1 PNplus 13 - overlap allMetal1 allPoly 13 - overlap allMetal2 PNplus 4 - overlap allMetal2 allPoly 4 - overlap allMetal2 allMetal1 6 - overlap allMetal3 PNplus 2 - overlap allMetal3 allPoly 2 - overlap allMetal3 allMetal1 3 - overlap allMetal3 allMetal2 7 - /* Junction capacitance */ - overlap ndiff,ndc/a space,pwell 27 - overlap pdiff,pdc/a space,nwell 148 - - /* Perimeter parasitic capacitance (in attofarads per lambda) - [ 1 lambda = 0.5 micron ---> multiplication factor 0.5 ] */ - perimc allMetal1 space,allWell 43 - perimc allMetal2 space,allWell 36 - perimc allMetal3 space,allWell 36 - - sideoverlap allMetal1 space,allWell allPoly 14 - sideoverlap allMetal2 space,allWell allPoly 5 - /* no such data for m2-to-m1, use data from specification file */ - sideoverlap allMetal2 space,allWell allMetal1 13 - sideoverlap allMetal3 space,allWell allPoly 1 - sideoverlap allMetal3 space,allWell allMetal1 4 - sideoverlap allMetal3 space,allWell allMetal2 13 - - /* Active devices: N-well process */ - fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 - fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 - -#endif /* TIGHTMETAL */ - -#ifdef IBMTECH -style SCN08(IBM) - -/* The following data is obtained from MOSIS run 'n42s', 1/94 */ -/* Last modified by pi@isi.edu, 6/27/94 */ - - cscale 1 - lambda 40 - step 100 - /* Parallel wire coupling capacitance disabled */ - sidehalo 0 - - /* Define plane order first */ -#ifdef V5 - planeorder well 0 - planeorder implant 1 - planeorder active 2 - planeorder metal1 3 - planeorder metal2 4 - planeorder metal3 5 - planeorder oxide 6 -#endif - - /* Sheet resistance (in milliohms per square) */ - resist ndiff,nsd,ndc/a,nsc/a 3300 - resist pdiff,psd,pdc/a,psc/a 3180 - resist poly 3630 - resist allMetal1 43 - resist allMetal2 36 - resist allMetal3 36 - /* not monitored on PCM, use specification value */ - resist nwell 520000 - - /* Contact resistance (in milliohm per contact) */ - contact ndc,nsc 4 2530 - contact pc 4 7510 - contact pdc,psc 4 2160 - contact m2c 5 330 - contact m3c 5 292 - - /* Area parasitic capacitances (in attofarads per lambda square) - [ 1 lambda = 0.4 micron ---> multiplication factor 0.16 ] */ -#endif /* IBMTECH */ - -#ifdef SUBMICRON -style SCN08(HP26G) - -/* The following data is obtained from MOSIS run 'n48r', 10/94 */ -/* Last modified by pi@isi.edu, 11/02/94 */ - - cscale 1 - lambda 40 - step 100 - /* Parallel wire coupling capacitance enabled */ - sidehalo 8 - - /* Define plane order first */ -#ifdef V5 - planeorder well 0 - planeorder implant 1 - planeorder active 2 - planeorder metal1 3 - planeorder metal2 4 - planeorder metal3 5 - planeorder oxide 6 -#endif - - /* Sheet resistance (in milliohms per square) */ - resist ndiff,nsd,ndc/a,nsc/a 2375 - resist pdiff,psd,pdc/a,psc/a 2000 - resist allPoly 2350 - resist allMetal1 70 - resist allMetal2 67 - resist allMetal3 30 - resist nwell 1265000 - - /* Contact resistance (in milliohm per contact) */ - contact pc 4 1250 - contact ndc,nsc 4 1300 - contact pdc,psc 4 1125 - contact m2c 5 430 - contact m3c 5 300 - - /* The following are 10 types of capacitance extracted: - 1. poly to substrate. - 2. metal1 to substrate. - 3. metal1 to poly. - 4. metal2 to substrate. - 5. metal2 to poly. - 6. metal2 to metal1. - 7. metal3 to substrate. - 8. metal3 to poly. - 9. metal3 to metal1. - 10. metal3 to metal2. - - NOTE: Since most of the simulation tools have already - included the gate-oxide capacitance, it is NOT - extracted here. If you need it explictly, - remove the following comment. */ - /* areacap nfet 334 */ - /* areacap pfet 315 */ - - /* Type 1,2,4,7 (to substrate) */ - /* Area parasitic capacitances (in attofarads per lambda square) - [ 1 lambda = 0.4 micron ---> multiplication factor 0.16 ] */ - areacap poly,pc/a 13 - areacap allMetal1,DiffMetal,HVDiffMetal 6 - areacap PolyMetal,BiMetal,CCDMetal 6 - areacap allMetal2 3 - areacap allMetal3 2 - - /* Perimeter parasitic capacitance (in attofarads per lambda) - [ 1 lambda = 0.4 micron ---> multiplication factor 0.4 ] */ - perimc poly,pc/a ~(poly,pc/a) 19 - perimc allMetal1 ~(allMetal1) 20 - perimc allMetal2 ~(allMetal2) 16 - perimc allMetal3 ~(allMetal3) 14 - - /* Inter-layer capacitance, type 3,5,6,8,9,10 */ - /* Area parasitic capacitances (in attofarads per lambda square) - [ 1 lambda = 0.4 micron ---> multiplication factor 0.16 ] */ - overlap allMetal1 allPoly 9 - overlap allMetal2 allPoly 3 - overlap allMetal2 allMetal1 5 - overlap allMetal3 allPoly 2 - overlap allMetal3 allMetal1 3 - overlap allMetal3 allMetal2 5 - - /* Perimeter parasitic capacitance (in attofarads per lambda) - [ 1 lambda = 0.4 micron ---> multiplication factor 0.4 ] */ - sideoverlap allMetal1 space,allWell allPoly 23 - sideoverlap allMetal2 space,allWell allPoly 17 - sideoverlap allMetal2 space,allWell allMetal1 19 - sideoverlap allMetal3 space,allWell allPoly 15 - sideoverlap allMetal3 space,allWell allMetal1 17 - sideoverlap allMetal3 space,allWell allMetal2 21 - - /* Cross-couple capacitance */ - /* Perimeter parasitic capacitance (in attofarads per lambda) - [ 1 lambda = 0.4 micron ---> multiplication factor 0.4 ] */ - sidewall allP ~(allP) ~(allP) allP 11 - sidewall allMetal1 ~(allMetal1) ~(allMetal1) allMetal1 24 - sidewall allMetal2 ~(allMetal2) ~(allMetal2) allMetal2 27 - sidewall allMetal3 ~(allMetal3) ~(allMetal3) allMetal3 39 - - /* Active devices: N-well process */ - fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 - fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 - - -style SCN06(HP14B) - -/* Not yet.... */ -/* Last modified by pi@isi.edu, 03/10/95 */ - - cscale 1 - lambda 30 - step 100 - /* Parallel wire coupling capacitance enabled */ - sidehalo 8 - - /* Define plane order first */ -#ifdef V5 - planeorder well 0 - planeorder implant 1 - planeorder active 2 - planeorder metal1 3 - planeorder metal2 4 - planeorder metal3 5 - planeorder oxide 6 -#endif - - /* Sheet resistance (in milliohms per square) */ - resist ndiff,nsd,ndc/a,nsc/a 2375 - resist pdiff,psd,pdc/a,psc/a 2000 - resist allPoly 2350 - resist allMetal1 70 - resist allMetal2 67 - resist allMetal3 30 - resist nwell 1265000 - - /* Contact resistance (in milliohm per contact) */ - contact pc 4 1250 - contact ndc,nsc 4 1300 - contact pdc,psc 4 1125 - contact m2c 5 430 - contact m3c 5 300 - - /* The following are 10 types of capacitance extracted: - 1. poly to substrate. - 2. metal1 to substrate. - 3. metal1 to poly. - 4. metal2 to substrate. - 5. metal2 to poly. - 6. metal2 to metal1. - 7. metal3 to substrate. - 8. metal3 to poly. - 9. metal3 to metal1. - 10. metal3 to metal2. - - NOTE: Since most of the simulation tools have already - included the gate-oxide capacitance, it is NOT - extracted here. If you need it explictly, - remove the following comment. */ - /* areacap nfet 334 */ - /* areacap pfet 315 */ - - /* Type 1,2,4,7 (to substrate) */ - /* Area parasitic capacitances (in attofarads per lambda square) - [ 1 lambda = 0.3 micron ---> multiplication factor 0.09 ] */ - areacap poly,pc/a 7 - areacap allMetal1,DiffMetal,HVDiffMetal 3 - areacap PolyMetal,BiMetal,CCDMetal 3 - areacap allMetal2 1 - areacap allMetal3 1 - - /* Perimeter parasitic capacitance (in attofarads per lambda) - [ 1 lambda = 0.3 micron ---> multiplication factor 0.3 ] */ - perimc poly,pc/a ~(poly,pc/a) 14 - perimc allMetal1 ~(allMetal1) 15 - perimc allMetal2 ~(allMetal2) 12 - perimc allMetal3 ~(allMetal3) 10 - - /* Inter-layer capacitance, type 3,5,6,8,9,10 */ - /* Area parasitic capacitances (in attofarads per lambda square) - [ 1 lambda = 0.3 micron ---> multiplication factor 0.09 ] */ - overlap allMetal1 allPoly 5 - overlap allMetal2 allPoly 2 - overlap allMetal2 allMetal1 3 - overlap allMetal3 allPoly 1 - overlap allMetal3 allMetal1 1 - overlap allMetal3 allMetal2 3 - - /* Perimeter parasitic capacitance (in attofarads per lambda) - [ 1 lambda = 0.3 micron ---> multiplication factor 0.3 ] */ - sideoverlap allMetal1 space,allWell allPoly 17 - sideoverlap allMetal2 space,allWell allPoly 14 - sideoverlap allMetal2 space,allWell allMetal1 15 - sideoverlap allMetal3 space,allWell allPoly 11 - sideoverlap allMetal3 space,allWell allMetal1 13 - sideoverlap allMetal3 space,allWell allMetal2 16 - - /* Cross-couple capacitance */ - /* Perimeter parasitic capacitance (in attofarads per lambda) - [ 1 lambda = 0.3 micron ---> multiplication factor 0.3 ] */ - sidewall allP ~(allP) ~(allP) allP 9 - sidewall allMetal1 ~(allMetal1) ~(allMetal1) allMetal1 19 - sidewall allMetal2 ~(allMetal2) ~(allMetal2) allMetal2 21 - sidewall allMetal3 ~(allMetal3) ~(allMetal3) allMetal3 31 - - /* Active devices: N-well process */ - fet pfet pdiff,pdc 2 pfet Vdd! nwell 0 0 - fet nfet ndiff,ndc 2 nfet GND! pwell 0 0 - -#endif /* SUBMICRON */ - -#endif /* OLD_EXTRACT_STYLE */ -end - - -wiring - contact pdcontact 4 pdiff 0 metal1 0 - contact ndcontact 4 ndiff 0 metal1 0 - contact pcontact 4 poly 0 metal1 0 - contact ec 6 poly2 0 metal1 0 - contact m2contact 4 metal1 0 metal2 0 - contact m3contact 5 metal2 0 metal3 0 -end - -router - layer1 metal1 3 allMetal1 3 - layer2 metal2 3 allMetal2 4 allPoly,allDiff 1 - contacts m2contact 4 - gridspacing 8 -end - -plowing - fixed allFet,glass,pad - covered allFet - drag allFet -end - -plot - /* based on Jeffrey C. Gealow's (jgealow@mtl.mit.edu) contribution */ - style colorversatec - - ndiff,ndc yellow \\ - 5555 AAAA 5555 AAAA \\ - 5555 AAAA 5555 AAAA \\ - 5555 AAAA 5555 AAAA \\ - 5555 AAAA 5555 AAAA - - ndiff,ndc cyan \\ - 0000 5555 0000 5555 \\ - 0000 5555 0000 5555 \\ - 0000 5555 0000 5555 \\ - 0000 5555 0000 5555 - - - nsd,nsc,col,clc yellow \\ - 1515 2A2A 5151 A2A2 \\ - 1515 2A2A 5151 A2A2 \\ - 1515 2A2A 5151 A2A2 \\ - 1515 2A2A 5151 A2A2 - - nsd,nsc,col,clc cyan \\ - 0000 1515 0000 5151 \\ - 0000 1515 0000 5151 \\ - 0000 1515 0000 5151 \\ - 0000 1515 0000 5151 - - - pdiff,pdc yellow \\ - 5555 AAAA 5555 AAAA \\ - 5555 AAAA 5555 AAAA \\ - 5555 AAAA 5555 AAAA \\ - 5555 AAAA 5555 AAAA - - pdiff,pdc cyan \\ - 0000 5555 0000 5555 \\ - 0000 5555 0000 5555 \\ - 0000 5555 0000 5555 \\ - 0000 5555 0000 5555 - - pdiff,pdc magenta \\ - AAAA 0000 AAAA 0000 \\ - AAAA 0000 AAAA 0000 \\ - AAAA 0000 AAAA 0000 \\ - AAAA 0000 AAAA 0000 - - - psd,psc yellow \\ - 1515 2A2A 5151 A2A2 \\ - 1515 2A2A 5151 A2A2 \\ - 1515 2A2A 5151 A2A2 \\ - 1515 2A2A 5151 A2A2 - - psd,psc cyan \\ - 0000 1515 0000 5151 \\ - 0000 1515 0000 5151 \\ - 0000 1515 0000 5151 \\ - 0000 1515 0000 5151 - - psd,psc magenta \\ - 2A2A 0000 A2A2 0000 \\ - 2A2A 0000 A2A2 0000 \\ - 2A2A 0000 A2A2 0000 \\ - 2A2A 0000 A2A2 0000 - - - poly,pc/a magenta \\ - 5555 AAAA 5555 AAAA \\ - 5555 AAAA 5555 AAAA \\ - 5555 AAAA 5555 AAAA \\ - 5555 AAAA 5555 AAAA - - - poly2,ec/a yellow \\ - FFFF FFFF FFFF FFFF \\ - FFFF FFFF FFFF FFFF \\ - FFFF FFFF FFFF FFFF \\ - FFFF FFFF FFFF FFFF - - - nfet yellow \\ - 0505 8282 1414 0A0A \\ - 5050 2828 4141 A0A0 \\ - 0505 8282 1414 0A0A \\ - 5050 2828 4141 A0A0 - - nfet cyan \\ - 0000 0505 0000 1414 \\ - 0000 5050 0000 4141 \\ - 0000 0505 0000 1414 \\ - 0000 5050 0000 4141 - - nfet magenta \\ - 5050 2828 4141 A0A0 \\ - 0505 8282 1414 0A0A \\ - 5050 2828 4141 A0A0 \\ - 0505 8282 1414 0A0A - - - enfet yellow \\ - BABA 7575 EAEA D5D5 \\ - ABAB 5757 AEAE 5D5D \\ - BABA 7575 EAEA D5D5 \\ - ABAB 5757 AEAE 5D5D - - enfet cyan \\ - 4141 0A0A 0505 2828 \\ - 1414 A0A0 5050 8282 \\ - 4141 0A0A 0505 2828 \\ - 1414 A0A0 5050 8282 - - - nffet yellow \\ - 8E8E 0707 8B8B D5D5 \\ - E8E8 7070 B8B8 5D5D \\ - 8E8E 0707 8B8B D5D5 \\ - E8E8 7070 B8B8 5D5D - - nffet cyan \\ - 0101 0808 1414 2828 \\ - 1010 8080 4141 8282 \\ - 0101 0808 1414 2828 \\ - 1010 8080 4141 8282 - - nffet magenta \\ - 5050 A0A0 4040 0202 \\ - 0505 0A0A 0404 2020 \\ - 5050 A0A0 4040 0202 \\ - 0505 0A0A 0404 2020 - - - pfet yellow \\ - 6363 A0A0 5050 2828 \\ - 3636 0A0A 0505 8282 \\ - 6363 A0A0 5050 2828 \\ - 3636 0A0A 0505 8282 - - pfet cyan \\ - 0000 5151 0000 5454 \\ - 0000 1515 0000 1515 \\ - 0000 5151 0000 5454 \\ - 0000 1515 0000 1515 - - pfet magenta \\ - 9494 0A0A 2525 8282 \\ - 4949 A0A0 5252 2828 \\ - 9494 0A0A 2525 8282 \\ - 4949 A0A0 5252 2828 - - - epfet yellow \\ - BCBC 4F4F 2F2F D3D3 \\ - CBCB F4F4 F2F2 3D3D \\ - BCBC 4F4F 2F2F D3D3 \\ - CBCB F4F4 F2F2 3D3D - - epfet cyan \\ - 0000 A0A0 0000 2828 \\ - 0000 0A0A 0000 8282 \\ - 0000 A0A0 0000 2828 \\ - 0000 0A0A 0000 8282 - - epfet magenta \\ - 4141 0000 5050 0000 \\ - 1414 0000 0505 0000 \\ - 4141 0000 5050 0000 \\ - 1414 0000 0505 0000 - - - pffet yellow \\ - 7B7B F0F0 F0F0 E9E9 \\ - B7B7 0F0F 0F0F 9E9E \\ - 7B7B F0F0 F0F0 E9E9 \\ - B7B7 0F0F 0F0F 9E9E - - pffet cyan \\ - 0000 0101 0000 1414 \\ - 0000 1010 0000 4141 \\ - 0000 0101 0000 1414 \\ - 0000 1010 0000 4141 - - pffet magenta \\ - 8484 0A0A 2525 8282 \\ - 4848 A0A0 5252 2828 \\ - 8484 0A0A 2525 8282 \\ - 4848 A0A0 5252 2828 - - - cap,cc/a yellow \\ - 3E3E 7777 E3E3 C1C1 \\ - E3E3 7777 3E3E 1C1C \\ - 3E3E 7777 E3E3 C1C1 \\ - E3E3 7777 3E3E 1C1C - - cap,cc/a magenta \\ - 4141 8888 1414 2A2A \\ - 1414 8888 4141 A2A2 \\ - 4141 8888 1414 2A2A \\ - 1414 8888 4141 A2A2 - - - allMetal1 cyan \\ - AAAA 0000 AAAA 0000 \\ - AAAA 0000 AAAA 0000 \\ - AAAA 0000 AAAA 0000 \\ - AAAA 0000 AAAA 0000 - - - allMetal2 cyan \\ - 0000 1111 0000 4444 \\ - 0000 1111 0000 4444 \\ - 0000 1111 0000 4444 \\ - 0000 1111 0000 4444 - - allMetal2 magenta \\ - 0000 4444 0000 1111 \\ - 0000 4444 0000 1111 \\ - 0000 4444 0000 1111 \\ - 0000 4444 0000 1111 - - - m2c/m1 black \\ - 0000 6666 6666 0000 \\ - 0000 9999 9999 0000 \\ - 0000 6666 6666 0000 \\ - 0000 9999 9999 0000 - - - pad,glass black \\ - 0300 0700 0E00 1C00 \\ - 3800 7000 E000 C000 \\ - 00C0 00E0 0070 0038 \\ - 001C 000E 0007 0003 - - - nwell yellow \\ - 0800 1000 2000 4000 \\ - 8000 0001 0002 0004 \\ - 0008 0010 0020 0040 \\ - 0080 0010 0200 0400 - - nwell cyan \\ - 1000 2000 4000 8000 \\ - 0001 0002 0004 0008 \\ - 0010 0020 0040 0080 \\ - 0100 0200 0400 0800 - - - pwell yellow \\ - 1000 0400 0400 0100 \\ - 0100 0040 0040 0010 \\ - 0010 0004 0004 0001 \\ - 0001 4000 4000 1000 - - pwell cyan \\ - 0000 0800 0000 0200 \\ - 0000 0080 0000 0020 \\ - 0000 0008 0000 0002 \\ - 0000 8000 0000 2000 - - pwell magenta \\ - 0800 0000 0200 0000 \\ - 0080 0000 0020 0000 \\ - 0008 0000 0002 0000 \\ - 8000 0000 2000 0000 - - - bd yellow \\ - 4444 8888 4444 8888 \\ - 4444 8888 4444 8888 \\ - 4444 8888 4444 8888 \\ - 4444 8888 4444 8888 - - bd cyan \\ - 0000 4444 0000 4444 \\ - 0000 4444 0000 4444 \\ - 0000 4444 0000 4444 \\ - 0000 4444 0000 4444 - - bd magenta \\ - 8888 0000 8888 0000 \\ - 8888 0000 8888 0000 \\ - 8888 0000 8888 0000 \\ - 8888 0000 8888 0000 - - - nbd,nbdc yellow \\ - 5555 AAAA 5555 AAAA \\ - 5555 AAAA 5555 AAAA \\ - 5555 AAAA 5555 AAAA \\ - 5555 AAAA 5555 AAAA - - nbd,nbdc cyan \\ - 0000 5555 0000 5555 \\ - 0000 5555 0000 5555 \\ - 0000 5555 0000 5555 \\ - 0000 5555 0000 5555 - - nbd,nbdc magenta \\ - 8888 0000 8888 0000 \\ - 8888 0000 8888 0000 \\ - 8888 0000 8888 0000 \\ - 8888 0000 8888 0000 - - - em,emc yellow \\ - 4444 8888 4444 8888 \\ - 4444 8888 4444 8888 \\ - 4444 8888 4444 8888 \\ - 4444 8888 4444 8888 - - em,emc cyan \\ - 0000 4444 0000 4444 \\ - 0000 4444 0000 4444 \\ - 0000 4444 0000 4444 \\ - 0000 4444 0000 4444 - - - pbase,pbc yellow \\ - 5555 AAAA 0000 0000 \\ - 5555 AAAA 0000 0000 \\ - 5555 AAAA 0000 0000 \\ - 5555 AAAA 0000 0000 - - pbase,pbc cyan \\ - 0000 5555 0000 0000 \\ - 0000 5555 0000 0000 \\ - 0000 5555 0000 0000 \\ - 0000 5555 0000 0000 - - pbase,pbc magenta \\ - AAAA 0000 0000 0000 \\ - AAAA 0000 0000 0000 \\ - AAAA 0000 0000 0000 \\ - AAAA 0000 0000 0000 - - - allMetal3 black \\ - 0100 0000 0000 0000 \\ - 1010 0000 0000 0000 \\ - 0001 0000 0000 0000 \\ - 1010 0000 0000 0000 - - allMetal3 cyan \\ - 0280 0000 0820 0000 \\ - 2008 0000 8002 0000 \\ - 8002 0000 2008 0000 \\ - 0820 0000 0280 0000 - - allMetal3 magenta \\ - 0100 06C0 0440 1830 \\ - 1010 600C 4004 8003 \\ - 0001 C006 4004 3018 \\ - 1010 0C60 0440 0380 - - - m3c/m2 black \\ - 0820 0820 0820 0FE0 \\ - E00F 2008 2008 2008 \\ - 2008 2008 2008 E00F \\ - 0000 0FE0 0820 0820 - - - error_p,error_s,error_ps black \\ - 0000 3C3C 4646 4A4A \\ - 5252 6262 3C3C 0000 \\ - 0000 3C3C 4646 4A4A \\ - 5252 6262 3C3C 0000 - - - magnet yellow \\ - AAAA 0000 5555 0000 \\ - AAAA 0000 5555 0000 \\ - AAAA 0000 5555 0000 \\ - AAAA 0000 5555 0000 - - - fence magenta \\ - FFFF 0000 0000 0000 \\ - 0000 0000 0000 0000 \\ - FFFF 0000 0000 0000 \\ - 0000 0000 0000 0000 - - - rotate cyan \\ - 0000 E0E0 E0E0 E0E0 \\ - 0000 0000 0000 0000 \\ - 0000 E0E0 E0E0 E0E0 \\ - 0000 0000 0000 0000 - - - allCut,BiCut X - - - style versatec - - pfet \\ - 07c0 0f80 1f00 3e00 \\ - 7c00 f800 f001 e003 \\ - c007 800f 001f 003e \\ - 00c7 00f8 01f0 03e0 - - - nfet \\ - 1f00 0f80 07c0 03e0 \\ - 01f0 00f8 007c 003e \\ - 001f 800f c007 e003 \\ - f001 f800 7c00 3e00 - - - m2c \\ - c3c3 c3c3 0000 0000 \\ - 0000 0000 c3c3 c3c3 \\ - c3c3 c3c3 0000 0000 \\ - 0000 0000 c3c3 c3c3 - - - pwell \\ - 2020 2020 2020 2020 \\ - 2020 2020 2020 2020 \\ - 0000 0000 0000 0000 \\ - 0000 0000 0000 0000 - - - nwell \\ - 0808 0404 0202 0101 \\ - 0000 0000 0000 0000 \\ - 0808 0404 0202 0101 \\ - 0000 0000 0000 0000 - - - allPoly \\ - 0808 0400 0202 0101 \\ - 8080 4000 2020 1010 \\ - 0808 0004 0202 0101 \\ - 8080 0040 2020 1010 - - - allMetal1 \\ - 8080 0000 0000 0000 \\ - 0808 0000 0000 0000 \\ - 8080 0000 0000 0000 \\ - 0808 0000 0000 0000 - - - pad,glass \\ - 0000 0000 1c1c 3e3e \\ - 3636 3e3e 1c1c 0000 \\ - 0000 0000 1c1c 3e3e \\ - 3636 3e3e 1c1c 0000 - - - nsd,nsc,col,clc \\ - 0808 1414 2222 4141 \\ - 8080 4040 2020 1010 \\ - 0808 1414 2222 4141 \\ - 8080 4040 2020 1010 - - - allMetal2 \\ - 0000 1111 0000 0000 \\ - 0000 1111 0000 0000 \\ - 0000 1111 0000 0000 \\ - 0000 1111 0000 0000 - - - pdiff,pdc,pfet \\ - 0000 0808 5555 8080 \\ - 0000 8080 5555 0808 \\ - 0000 0808 5555 8080 \\ - 0000 8080 5555 0808 - - - psd,psc \\ - 1414 2222 0000 2222 \\ - 4141 2222 0000 2222 \\ - 1414 2222 0000 2222 \\ - 4141 2222 0000 2222 - - - ndiff,nfet,ndc \\ - 0808 1010 2020 4040 \\ - 8080 4141 2222 1414 \\ - 0808 1010 2020 4040 \\ - 8080 4141 2222 1414 - - - allPoly2 \\ - 0000 2020 5050 2020 \\ - 0000 0202 0505 0202 \\ - 0000 2020 5050 2020 \\ - 0000 0202 0505 0202 - - - allCut,BiCut X - -/* -------------------------------------------------------------- */ - style gremlin - pfet 9 - nfet 10 - m2c 11 - pwell 15 - nwell 16 - allPoly 19 - allMetal1 22 - pad,glass 23 - nsd,nsc 24 - allMetal2 28 - pdiff,pdc,pfet 29 - psd,psc 30 - ndiff,nfet,ndc 31 - m2c/m1,pc/m1,ndc/m1,pdc/m1,psc/m1,nsc/m1,pad/m1 X -/* -------------------------------------------------------------- */ - style postscript -/* - * stipple definitions for 32x8 bitmaps - * # row1 row2 row3 row4 row5 row6 row7 row8 - */ - 1 C0C0C0C0 C0C0C0C0 00000000 00000000 0C0C0C0C 0C0C0C0C 00000000 00000000 - 2 A0A0A0A0 0A0A0A0A A0A0A0A0 0A0A0A0A A0A0A0A0 0A0A0A0A A0A0A0A0 0A0A0A0A - 3 00030003 000C000C 00300030 00C000C0 03000300 0C000C00 30003000 C000C000 - 4 00000000 00000000 C0C0C0C0 00000000 00000000 00000000 0C0C0C0C 00000000 - 5 FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF - 6 07070707 0E0E0E0E 1C1C1C1C 38383838 70707070 E0E0E0E0 C1C1C1C1 83838383 - 7 18181818 30303030 60606060 C0C0C0C0 81818181 03030303 06060606 0C0C0C0C - 8 18181818 0C0C0C0C 06060606 03030303 81818181 C0C0C0C0 60606060 30303030 - 9 18181818 3C3C3C3C 3C3C3C3C 18181818 81818181 C3C3C3C3 C3C3C3C3 81818181 - 10 F0F0F0F0 60606060 06060606 0F0F0F0F 0F0F0F0F 06060606 60606060 F0F0F0F0 - 11 01000080 02000040 0C000030 F000000F 000FF000 00300C00 00400200 00800100 - 12 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 - 13 00000000 00000000 33333333 33333333 00000000 00000000 CCCCCCCC CCCCCCCC -/* - * color definitions in CMYK format - * # C M Y K closest named color in RGB space - */ - 1 47 95 111 0 /* RosyBrown3 */ - 2 223 31 223 0 /* limegreen */ - 3 0 0 0 192 /* gray25 */ - 4 31 111 31 0 /* plum */ - 5 31 111 255 0 /* orange2 */ - 6 63 95 191 0 /* goldenrod3 */ - 7 255 63 255 0 /* green3 */ - 8 0 0 0 127 /* gray50 */ - 9 223 47 223 0 /* limegreen */ - 10 0 255 255 0 /* red */ - 11 0 0 255 0 /* yellow */ - 12 191 127 0 0 /* RoyalBlue1 */ - 13 95 223 63 0 /* DarkOrchid3 */ - 14 0 0 0 255 /* black */ - 15 191 127 63 0 /* steelblue */ - 16 111 151 244 0 /* goldenrod4 */ - 17 23 175 183 0 /* tomato2 */ -/* - * magic layer definitions (plotted top to bottom) - * layer(s) color# stipple# (plus B=box, X=cross & box) - */ - cc,pc,ndc,pdc,psc,nsc 14 X - m2c,pad,glass 14 B - pad,glass 14 11 - m2c 14 13 - m2,m2c,pad 13 10 - pdc,ndc,psc,nsc,hpdc,hndc,hpsc,hnsc,pc,ec,capc,clc,emc,pbc,nbdc,m1,m2c,gc 12 9 - cap,cc,poly2 11 7 - nsd,nsc 7 1 - psd,psc 6 1 - nfet,nffet 9 8 - pfet,wcap,pffet 1 7 - poly,pc,cap,cc 10 5 - nfet 16 5 - pfet,wcap 17 5 - pdiff,pdc,pffet 1 5 - ndiff,ndc,nffet 9 5 - pwell 1 4 - nwell 2 4 - -/* ------------------------------------------------------------------------ */ - style pnm - draw metal1 - draw metal2 - draw polysilicon - draw ndiffusion - draw pdiffusion - draw ntransistor - draw ptransistor - map psubstratepdiff pdiffusion - map nsubstratendiff ndiffusion - map polycontact polysilicon metal1 - map m2contact metal1 metal2 - map m3contact metal2 metal3 - map ndcontact ndiffusion metal1 - map pdcontact pdiffusion metal1 - map nsubstratencontact ndiffusion metal1 - map psubstratepcontact pdiffusion metal1 - -end diff --git a/scripts/configure b/scripts/configure index 2114738f..a2d9cb28 100755 --- a/scripts/configure +++ b/scripts/configure @@ -628,7 +628,7 @@ OA_LIBS OA MAGIC_REVISION MAGIC_VERSION -SCPP +MSED MCPP LD_RUN_PATH SHLIB_CFLAGS @@ -672,12 +672,11 @@ X_LIBS X_PRE_LIBS X_CFLAGS XMKMF +PYTHON3 CSH GCORE EGREP GREP -PYTHON3 -M4 RANLIB INSTALL_DATA INSTALL_SCRIPT @@ -4038,114 +4037,6 @@ else fi -for ac_prog in gm4 gnum4 m4 -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_M4+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $M4 in - [\\/]* | ?:[\\/]*) - ac_cv_path_M4="$M4" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_M4="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -M4=$ac_cv_path_M4 -if test -n "$M4"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $M4" >&5 -$as_echo "$M4" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$M4" && break -done -test -n "$M4" || M4="no" - -if test x$M4 = xno; then - as_fn_error $? "M4 is required" "$LINENO" 5 -fi - -# Extract the first word of "python3", so it can be a program name with args. -set dummy python3; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_PYTHON3+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $PYTHON3 in - [\\/]* | ?:[\\/]*) - ac_cv_path_PYTHON3="$PYTHON3" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_PYTHON3="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - test -z "$ac_cv_path_PYTHON3" && ac_cv_path_PYTHON3="no" - ;; -esac -fi -PYTHON3=$ac_cv_path_PYTHON3 -if test -n "$PYTHON3"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON3" >&5 -$as_echo "$PYTHON3" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -if test "x${PYTHON3}" == "x"; then - - - if test "$CPP" = "$CC -E" ; then - MCPP="$CPP -x c" - fi - -else - MCPP="\${MAGICDIR}/scripts/preproc.py" -fi - -if test "$CPP" = "$CC -E" ; then - SCPP="$CPP -x c" -else - SCPP="$CPP" -fi - #------------------------------------------------------------ # AC_PROG_LD - find the path to the GNU or non-GNU linker @@ -5343,6 +5234,7 @@ use_libglu="-lGLU" usingTcl=1 usingOA=0 usingCairo=1 +usingPython3=1 # Extract the first word of "gcore", so it can be a program name with args. @@ -5434,6 +5326,65 @@ if test "x${CSH}" = "x"; then as_fn_error $? "cannot find /bin/csh---cannot compile!" "$LINENO" 5 fi +# Extract the first word of "python3", so it can be a program name with args. +set dummy python3; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PYTHON3+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PYTHON3 in + [\\/]* | ?:[\\/]*) + ac_cv_path_PYTHON3="$PYTHON3" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PYTHON3="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_PYTHON3" && ac_cv_path_PYTHON3="no" + ;; +esac +fi +PYTHON3=$ac_cv_path_PYTHON3 +if test -n "$PYTHON3"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON3" >&5 +$as_echo "$PYTHON3" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test "x${PYTHON3}" == "x"; then + + + usingPython3= + if test "$CPP" = "$CC -E" ; then + MCPP="$CPP -x c" + MSED="sed -e 's/\\/\\\\/'" + else + MCPP="$CPP" + MSED="sed -e 's/\\/\\\\/'" + fi + +else + MCPP="\${MAGICDIR}/scripts/preproc.py -ccomm" + MSED="cat" + usingPython3=1 +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5 $as_echo_n "checking for X... " >&6; } @@ -9470,6 +9421,19 @@ else echo fi +${ECHO_N} "Python3: " +if test $usingPython3 ; then + echo "yes" +else + echo "no" + echo + echo " Magic installation will use the gcc preprocessor for forming" + echo " the default SCMOS technology files and the macro definitions." + echo " This usually works, but in case of preprocessor failure, you" + echo " may need python3 installed." + echo +fi + ${ECHO_N} "OpenGL: " if test $usingOGL ; then echo "yes" @@ -9482,14 +9446,18 @@ if test $usingOGL ; then else echo "no" echo - echo " OpenGL graphics are considerably better than the standard 8-bit" - echo " and 24-bit X11 graphics, provided that you have a video card and" - echo " driver supporting accelerated OpenGL graphics. If you get this" - echo " message, you may need to download OpenGL libraries and header" - echo " files, which are usually available from the video card manufacturer." - echo " Magic with un-accelerated OpenGL, such as using Mesa GL without" - echo " a supported graphics card, is usually a very bad combination." - echo + if test $usingCairo ; then + echo " Cairo graphics are available so OpenGL is purely optional." + else + echo " OpenGL graphics are considerably better than the standard 8-bit" + echo " and 24-bit X11 graphics, provided that you have a video card and" + echo " driver supporting accelerated OpenGL graphics. If you get this" + echo " message, you may need to download OpenGL libraries and header" + echo " files, which are usually available from the video card manufacturer." + echo " Magic with un-accelerated OpenGL, such as using Mesa GL without" + echo " a supported graphics card, is usually a very bad combination." + echo + fi fi ${ECHO_N} "Cairo: " @@ -9498,12 +9466,18 @@ if test $usingCairo ; then else echo "no" echo - echo " Cairo graphics are considerably better than the standard 8-bit" - echo " and 24-bit X11 graphics, provided that you have a video card and" - echo " driver supporting hardware-accelerated graphics. If you get this" - echo " message, you may need to download Cairo and fontconfig libraries" - echo " and header files, which are usually found in package cairo-devel." - echo + if test $usingOGL ; then + echo " OpenGL graphics are available so Cairo is purely optional" + echo " unless there are issues with the video card driver's" + echo " implementation of OpenGL." + else + echo " Cairo graphics are considerably better than the standard 8-bit" + echo " and 24-bit X11 graphics, provided that you have a video card and" + echo " driver supporting hardware-accelerated graphics. If you get this" + echo " message, you may need to download Cairo and fontconfig libraries" + echo " and header files, which are usually found in package cairo-devel." + echo + fi fi if test $usingTcl ; then diff --git a/scripts/configure.in b/scripts/configure.in index 306ab304..8a00ba27 100644 --- a/scripts/configure.in +++ b/scripts/configure.in @@ -28,37 +28,6 @@ AC_ISC_POSIX AC_PROG_INSTALL AC_PROG_RANLIB -dnl GNU M4 is preferred due to some of the option switches. -AC_PATH_PROGS([M4], [gm4 gnum4 m4], [no]) -if test x$M4 = xno; then - AC_MSG_ERROR([M4 is required]) -fi - -dnl Python3 is preferred for running the preprocessor script -dnl but CPP can be used instead. -AC_PATH_PROG([PYTHON3], [python3], [no]) -if test "x${PYTHON3}" == "x"; then - - dnl check size of pointer for correct behavior on 64-bit systems - dnl If the C preprocessor is GCC, we need to force the flag to - dnl assert that input files are of type C, or else the preprocessing - dnl stage will not execute correctly on the ".in" files in the scmos - dnl directory. - - if test "$CPP" = "$CC -E" ; then - MCPP="$CPP -x c" - fi - -else - MCPP="\${MAGICDIR}/scripts/preproc.py" -fi - -if test "$CPP" = "$CC -E" ; then - SCPP="$CPP -x c" -else - SCPP="$CPP" -fi - dnl check if the linker is a GNU linker #------------------------------------------------------------ @@ -306,6 +275,7 @@ use_libglu="-lGLU" usingTcl=1 usingOA=0 usingCairo=1 +usingPython3=1 dnl Check for gcore, used by niceabort.c @@ -321,6 +291,32 @@ if test "x${CSH}" = "x"; then AC_MSG_ERROR([cannot find /bin/csh---cannot compile!]) fi +dnl Python3 is preferred for running the preprocessor script +dnl but CPP can be used instead. +AC_PATH_PROG([PYTHON3], [python3], [no]) +if test "x${PYTHON3}" == "x"; then + + dnl check size of pointer for correct behavior on 64-bit systems + dnl If the C preprocessor is GCC, we need to force the flag to + dnl assert that input files are of type C, or else the preprocessing + dnl stage will not execute correctly on the ".in" files in the scmos + dnl directory. + + usingPython3= + if test "$CPP" = "$CC -E" ; then + MCPP="$CPP -x c" + MSED="sed -e 's/\\/\\\\/'" + else + MCPP="$CPP" + MSED="sed -e 's/\\/\\\\/'" + fi + +else + MCPP="\${MAGICDIR}/scripts/preproc.py -ccomm" + MSED="cat" + usingPython3=1 +fi + dnl Check for X enabled/disabled AC_PATH_XTRA @@ -1802,7 +1798,7 @@ AC_SUBST(DEPEND_FLAG) AC_SUBST(SHLIB_CFLAGS) AC_SUBST(LD_RUN_PATH) AC_SUBST(MCPP) -AC_SUBST(SCPP) +AC_SUBST(MSED) AC_SUBST(MAGIC_VERSION) AC_SUBST(MAGIC_REVISION) @@ -1839,6 +1835,19 @@ else echo fi +${ECHO_N} "Python3: " +if test $usingPython3 ; then + echo "yes" +else + echo "no" + echo + echo " Magic installation will use the gcc preprocessor for forming" + echo " the default SCMOS technology files and the macro definitions." + echo " This usually works, but in case of preprocessor failure, you" + echo " may need python3 installed." + echo +fi + ${ECHO_N} "OpenGL: " if test $usingOGL ; then echo "yes" @@ -1851,14 +1860,18 @@ if test $usingOGL ; then else echo "no" echo - echo " OpenGL graphics are considerably better than the standard 8-bit" - echo " and 24-bit X11 graphics, provided that you have a video card and" - echo " driver supporting accelerated OpenGL graphics. If you get this" - echo " message, you may need to download OpenGL libraries and header" - echo " files, which are usually available from the video card manufacturer." - echo " Magic with un-accelerated OpenGL, such as using Mesa GL without" - echo " a supported graphics card, is usually a very bad combination." - echo + if test $usingCairo ; then + echo " Cairo graphics are available so OpenGL is purely optional." + else + echo " OpenGL graphics are considerably better than the standard 8-bit" + echo " and 24-bit X11 graphics, provided that you have a video card and" + echo " driver supporting accelerated OpenGL graphics. If you get this" + echo " message, you may need to download OpenGL libraries and header" + echo " files, which are usually available from the video card manufacturer." + echo " Magic with un-accelerated OpenGL, such as using Mesa GL without" + echo " a supported graphics card, is usually a very bad combination." + echo + fi fi ${ECHO_N} "Cairo: " @@ -1867,12 +1880,18 @@ if test $usingCairo ; then else echo "no" echo - echo " Cairo graphics are considerably better than the standard 8-bit" - echo " and 24-bit X11 graphics, provided that you have a video card and" - echo " driver supporting hardware-accelerated graphics. If you get this" - echo " message, you may need to download Cairo and fontconfig libraries" - echo " and header files, which are usually found in package cairo-devel." - echo + if test $usingOGL ; then + echo " OpenGL graphics are available so Cairo is purely optional" + echo " unless there are issues with the video card driver's" + echo " implementation of OpenGL." + else + echo " Cairo graphics are considerably better than the standard 8-bit" + echo " and 24-bit X11 graphics, provided that you have a video card and" + echo " driver supporting hardware-accelerated graphics. If you get this" + echo " message, you may need to download Cairo and fontconfig libraries" + echo " and header files, which are usually found in package cairo-devel." + echo + fi fi if test $usingTcl ; then diff --git a/scripts/defs.mak.in b/scripts/defs.mak.in index 98f07b37..0404e2ee 100755 --- a/scripts/defs.mak.in +++ b/scripts/defs.mak.in @@ -58,9 +58,8 @@ AR = ar ARFLAGS = crv LINK = ld -r LD = @LD@ -M4 = @M4@ MCPP = @MCPP@ -SCPP = @SCPP@ +MSED = @MSED@ RANLIB = @RANLIB@ SHDLIB_EXT = @SHDLIB_EXT@ LDDL_FLAGS = ${LDFLAGS} @LDDL_FLAGS@ diff --git a/scripts/preproc.py b/scripts/preproc.py index 7a2fc7cf..1fca5bef 100755 --- a/scripts/preproc.py +++ b/scripts/preproc.py @@ -1,4 +1,4 @@ -#!/usr/bin/python3 +#!/usr/bin/env python3 #-------------------------------------------------------------------- # # preproc.py @@ -25,6 +25,7 @@ # #endif # # #define [...] +# #define () [...] # #undef # # #include @@ -146,10 +147,27 @@ def solve_condition(condition, keys, defines, keyrex): else: return 0 +def sortkeys(keys): + newkeys = [] + for i in range(0, len(keys)): + keyword = keys[i] + found = False + for j in range(0, len(newkeys)): + inword = newkeys[j] + if inword in keyword: + # Insert keyword before inword + newkeys.insert(j, keyword) + found = True + break + if not found: + newkeys.append(keyword) + return newkeys + def runpp(keys, keyrex, defines, ccomm, incdirs, inputfile, ofile): includerex = re.compile('^[ \t]*#include[ \t]+"*([^ \t\n\r"]+)') definerex = re.compile('^[ \t]*#define[ \t]+([^ \t]+)[ \t]+(.+)') + paramrex = re.compile('^([^\(]+)\(([^\)]+)\)') defrex = re.compile('^[ \t]*#define[ \t]+([^ \t\n\r]+)') undefrex = re.compile('^[ \t]*#undef[ \t]+([^ \t\n\r]+)') ifdefrex = re.compile('^[ \t]*#ifdef[ \t]+(.+)') @@ -160,7 +178,8 @@ def runpp(keys, keyrex, defines, ccomm, incdirs, inputfile, ofile): endifrex = re.compile('^[ \t]*#endif') commentrex = re.compile('^###[^#]*$') ccstartrex = re.compile('/\*') # C-style comment start - ccendrex = re.compile('\*/') # C-style comment end + ccendrex = re.compile('\*/') # C-style comment end + contrex = re.compile('.*\\\\$') # Backslash continuation line badifrex = re.compile('^[ \t]*#if[ \t]*.*') badelserex = re.compile('^[ \t]*#else[ \t]*.*') @@ -187,7 +206,7 @@ def runpp(keys, keyrex, defines, ccomm, incdirs, inputfile, ofile): break if not ifile: - print("Error: Cannot open file " + inputfile + " for reading.\n") + print("Error: Cannot open file " + inputfile + " for reading.\n", file=sys.stderr) return ccblock = -1 @@ -196,6 +215,8 @@ def runpp(keys, keyrex, defines, ccomm, incdirs, inputfile, ofile): lineno = 0 filetext = ifile.readlines() + lastline = [] + for line in filetext: lineno += 1 @@ -206,7 +227,7 @@ def runpp(keys, keyrex, defines, ccomm, incdirs, inputfile, ofile): if pmatch: ematch = ccendrex.search(line[pmatch.end(0):]) if ematch: - line = line[0:pmatch.start(0)] + line[ematch.end(0)+2:] + line = line[0:pmatch.start(0)] + line[pmatch.end(0) + ematch.end(0):] else: line = line[0:pmatch.start(0)] ccblock = 1 @@ -218,55 +239,31 @@ def runpp(keys, keyrex, defines, ccomm, incdirs, inputfile, ofile): else: continue + # Handle continuation detected in previous line + if lastline: + # Note: Apparently there is a character retained after the backslash, + # so strip the last two characters from the line. + line = lastline[0:-2] + line + lastline = [] + + # Continuation lines have the next highest priority. However, this + # script will attempt to keep continuation lines in the body of the + # text and only collapse lines where continuation lines occur in + # a preprocessor statement. + + cmatch = contrex.match(line) + # Ignore lines beginning with "###" pmatch = commentrex.match(line) if pmatch: continue - # Handle include. Note that this code does not expect or - # handle 'if' blocks that cross file boundaries. - pmatch = includerex.match(line) - if pmatch: - inclfile = pmatch.group(1) - runpp(keys, keyrex, defines, ccomm, incdirs, inclfile, ofile) - continue - - # Handle define (with value) - pmatch = definerex.match(line) - if pmatch: - condition = pmatch.group(1) - value = pmatch.group(2) - defines[condition] = value - keyrex[condition] = re.compile(condition) - if condition not in keys: - keys.append(condition) - continue - - # Handle define (simple case, no value) - pmatch = defrex.match(line) - if pmatch: - condition = pmatch.group(1) - print("Defrex condition is " + condition) - defines[condition] = '1' - keyrex[condition] = re.compile(condition) - if condition not in keys: - keys.append(condition) - print("Defrex value is " + defines[condition]) - continue - - # Handle undef - pmatch = undefrex.match(line) - if pmatch: - condition = pmatch.group(1) - if condition in keys: - defines.pop(condition) - keyrex.pop(condition) - keys.remove(condition) - continue - # Handle ifdef pmatch = ifdefrex.match(line) if pmatch: + if cmatch: + lastline = line + continue if ifblock != -1: ifstack.append(ifblock) @@ -280,6 +277,9 @@ def runpp(keys, keyrex, defines, ccomm, incdirs, inputfile, ofile): # Handle ifndef pmatch = ifndefrex.match(line) if pmatch: + if cmatch: + lastline = line + continue if ifblock != -1: ifstack.append(ifblock) @@ -294,6 +294,9 @@ def runpp(keys, keyrex, defines, ccomm, incdirs, inputfile, ofile): # Handle if pmatch = ifrex.match(line) if pmatch: + if cmatch: + lastline = line + continue if ifblock != -1: ifstack.append(ifblock) @@ -307,8 +310,11 @@ def runpp(keys, keyrex, defines, ccomm, incdirs, inputfile, ofile): # Handle elseif pmatch = elseifrex.match(line) if pmatch: + if cmatch: + lastline = line + continue if ifblock == -1: - print("Error: #elseif without preceding #if at line " + str(lineno) + ".") + print("Error: #elseif without preceding #if at line " + str(lineno) + ".", file=sys.stderr) ifblock = 0 if ifblock == 1: @@ -321,8 +327,11 @@ def runpp(keys, keyrex, defines, ccomm, incdirs, inputfile, ofile): # Handle else pmatch = elserex.match(line) if pmatch: + if cmatch: + lastline = line + continue if ifblock == -1: - print("Error: #else without preceding #if at line " + str(lineno) + ".") + print("Error: #else without preceding #if at line " + str(lineno) + ".", file=sys.stderr) ifblock = 0 if ifblock == 1: @@ -334,8 +343,11 @@ def runpp(keys, keyrex, defines, ccomm, incdirs, inputfile, ofile): # Handle endif pmatch = endifrex.match(line) if pmatch: + if cmatch: + lastline = line + continue if ifblock == -1: - print("Error: #endif outside of #if block at line " + str(lineno) + " (ignored)") + print("Error: #endif outside of #if block at line " + str(lineno) + " (ignored)", file=sys.stderr) elif ifstack: ifblock = ifstack.pop() else: @@ -345,7 +357,7 @@ def runpp(keys, keyrex, defines, ccomm, incdirs, inputfile, ofile): # Check for 'if' or 'else' that were not properly formed pmatch = badifrex.match(line) if pmatch: - print("Error: Badly formed #if statement at line " + str(lineno) + " (ignored)") + print("Error: Badly formed #if statement at line " + str(lineno) + " (ignored)", file=sys.stderr) if ifblock != -1: ifstack.append(ifblock) @@ -357,7 +369,7 @@ def runpp(keys, keyrex, defines, ccomm, incdirs, inputfile, ofile): pmatch = badelserex.match(line) if pmatch: - print("Error: Badly formed #else statement at line " + str(lineno) + " (ignored)") + print("Error: Badly formed #else statement at line " + str(lineno) + " (ignored)", file=sys.stderr) ifblock = 2 continue @@ -365,15 +377,120 @@ def runpp(keys, keyrex, defines, ccomm, incdirs, inputfile, ofile): if ifblock == 0 or ifblock == 2: continue + # Handle include. Note that this code does not expect or + # handle 'if' blocks that cross file boundaries. + pmatch = includerex.match(line) + if pmatch: + if cmatch: + lastline = line + continue + inclfile = pmatch.group(1) + runpp(keys, keyrex, defines, ccomm, incdirs, inclfile, ofile) + continue + + # Handle define (with value) + pmatch = definerex.match(line) + if pmatch: + if cmatch: + lastline = line + continue + condition = pmatch.group(1) + + # Additional handling of definition w/parameters: #define X(a,b,c) ..." + rmatch = paramrex.match(condition) + if rmatch: + # 'condition' as a key into keyrex only needs to be unique. + # Use the definition word without everything in parentheses + condition = rmatch.group(1) + + # 'pcondition' is the actual search regexp and must capture all + # the parameters individually for substitution + + parameters = rmatch.group(2).split(',') + + # Generate the regexp string to match comma-separate values + # Note that this is based on the cpp preprocessor, which + # apparently allows commas in arguments if surrounded by + # parentheses; e.g., "def(a, b, (c1,c2))". This is NOT + # handled. + + pcondition = condition + '\(' + for param in parameters[0:-1]: + pcondition += '(.*),' + pcondition += '(.*)\)' + + # Generate the substitution string with group substitutions + pvalue = pmatch.group(2) + idx = 1 + for param in parameters: + pvalue = pvalue.replace(param, '\g<' + str(idx) + '>') + idx = idx + 1 + + defines[condition] = pvalue + keyrex[condition] = re.compile(pcondition) + else: + parameters = [] + value = pmatch.group(2) + # Note: Need to check for infinite recursion here, but it's tricky. + defines[condition] = value + keyrex[condition] = re.compile(condition) + + if condition not in keys: + # Parameterized keys go to the front of the list + if parameters: + keys.insert(0, condition) + else: + keys.append(condition) + keys = sortkeys(keys) + continue + + # Handle define (simple case, no value) + pmatch = defrex.match(line) + if pmatch: + if cmatch: + lastline = line + continue + condition = pmatch.group(1) + defines[condition] = '1' + keyrex[condition] = re.compile(condition) + if condition not in keys: + keys.append(condition) + keys = sortkeys(keys) + continue + + # Handle undef + pmatch = undefrex.match(line) + if pmatch: + if cmatch: + lastline = line + continue + condition = pmatch.group(1) + if condition in keys: + defines.pop(condition) + keyrex.pop(condition) + keys.remove(condition) + continue + # Now do definition replacement on what's left (if anything) - for keyword in keys: - line = keyrex[keyword].sub(defines[keyword], line) + # This must be done repeatedly from the top until there are no + # more substitutions to make. + + while True: + origline = line + for keyword in keys: + newline = keyrex[keyword].sub(defines[keyword], line) + if newline != line: + line = newline + break + + if line == origline: + break # Output the line print(line, file=ofile, end='') if ifblock != -1 or ifstack != []: - print("Error: input file ended with an unterminated #if block.") + print("Error: input file ended with an unterminated #if block.", file=sys.stderr) if ifile != sys.stdin: ifile.close() @@ -433,6 +550,7 @@ if __name__ == '__main__': defines[keyword] = value keyrex[keyword] = re.compile(keyword) keys.append(keyword) + keys = sortkeys(keys) else: print('Bad option ' + item + ', options are -help, -ccomm, -D -I

\n') sys.exit(1) @@ -446,6 +564,12 @@ if __name__ == '__main__': print("Error: Cannot open file " + output_file + " for writing.") sys.exit(1) + # Sort keys so that if any definition contains another definition, the + # subset word is handled last; otherwise the subset word will get + # substituted, screwing up the definition names in which it occurs. + + keys = sortkeys(keys) + runpp(keys, keyrex, defines, ccomm, incdirs, inputfile, ofile) if ofile != sys.stdout: ofile.close() From 421ff1fa0d9b882c698c7f64c2a2b6060c9df46c Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 19 Feb 2020 14:49:55 -0500 Subject: [PATCH 102/121] Removed a temporary diagnostic output file that ended up in the last commit by mistake. --- scmos/test.out | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 scmos/test.out diff --git a/scmos/test.out b/scmos/test.out deleted file mode 100644 index e69de29b..00000000 From fd6de6391f19a49406562313f8ce31fe68835c5a Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 21 Feb 2020 16:17:57 -0500 Subject: [PATCH 103/121] Modified the TODO list, partly becuase it's outdated, and partly to force an update of the repository, which caused the script handling the tarball generation and mirror to github to be hosed, which I did not notice for three weeks. --- TODO | 20 ++++++++++++++------ VERSION | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/TODO b/TODO index 6cb60002..43a8972b 100644 --- a/TODO +++ b/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 - the new "device" types in the extract file. + 1. The "extresist" code needs to extract substrate networks. Moreover, + the "extresist" code really needs to have the dependence on + ext2sim removed, and instead read directly from .ext files. The + .sim format has no substrate connections, so this cannot be properly + represented. Also, there is nothing that is read from the .sim file + that is not already present in the .ext file. - 2. "plow" has been broken for some time. It should derive its rules - from the DRC decks (using the new routines that are meant for just - that sort of thing). + 2. "plow" should derive its rules from the DRC decks (using the new + routines that are meant for just that sort of thing). + + 3. It is possible to trick the net selection into an infinite loop in + unusual geometry situations. That these situations would be DRC + errors does not excuse the infinite loop behavior. The geometry + required is unusual enough that this is not a high priority item. diff --git a/VERSION b/VERSION index 25e98fb9..407701ce 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.101 +8.2.183 From 592776098e5ceda2576cf56d7233bd763b5f2bef Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 24 Feb 2020 10:06:39 -0500 Subject: [PATCH 104/121] Removed VERSION from gitignore; will rewrite scripts to handle it properly without causing perpetual updates. --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index 50ebaf94..beef7e8d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,8 +10,6 @@ scripts/defs.mak *.so *~ scmos/cif_template/objs/* -UPDATE_ME -VERSION database/database.h install.log magic/proto.magicrc From 4c67d2dbe552bca3b4f57c4c2c3fb5c95e5cfc7f Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 24 Feb 2020 17:21:26 -0500 Subject: [PATCH 105/121] Forcing a version update. --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 407701ce..4f61d2d9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.183 +8.2.184 From 509e936edb575ead3a07107d5e4dcbfa9aca25ee Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 24 Feb 2020 17:26:20 -0500 Subject: [PATCH 106/121] One more version update, checking fixes. . . --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 4f61d2d9..c96501a2 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.184 +8.2.185 From 75292d1d1fbd6ee9351b136c3f402659126b3bc0 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 24 Feb 2020 17:30:18 -0500 Subject: [PATCH 107/121] Corrected Makefile to use -include instead of include on defs.mak so that "make distclean" works. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9f288127..ef4c1301 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ MODULES = cmwind commands database dbwind debug drc extflat extract \ MAKEFLAGS = INSTALL_CAD_DIRS = windows doc ${TECH} -include defs.mak +-include defs.mak all: $(ALL_TARGET) From b2c6193589e2ad2698191ef6e685e1a075b05df5 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 24 Feb 2020 17:34:02 -0500 Subject: [PATCH 108/121] Manual VERSION update, checking regeneration of tarball build. --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index c96501a2..c0768957 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.185 +8.2.186 From fba66b7dff9402ba30ee0e4653002b5f91daaf5d Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 24 Feb 2020 21:47:44 -0500 Subject: [PATCH 109/121] Reverted the "drc count" command to the way it was. There is more to be investigated here. I am no longer sure why I removed the cell search from DRC count, but it appears that the cell search is non-functional, and it should be determined why. There is no particular reason not to have a DRC count search. It could be implemented such that "list" vs. "listall" counts the top cell vs. all cells. First it must be determined why there are no subcell counts. --- commands/CmdCD.c | 84 +++++++++++++++++++++++++++++++----------------- drc/DRCmain.c | 74 +++++++++++++++++++++++++++++++++++++++--- drc/drc.h | 11 ++++++- 3 files changed, 135 insertions(+), 34 deletions(-) diff --git a/commands/CmdCD.c b/commands/CmdCD.c index 5babc7c2..d91da3a6 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -3182,6 +3182,7 @@ CmdDrc(w, cmd) bool doforall = FALSE; bool dolist = FALSE; int count_total; + DRCCountList *dcl; int argc = cmd->tx_argc; char **argv = cmd->tx_argv; #ifdef MAGIC_WRAPPER @@ -3196,7 +3197,7 @@ CmdDrc(w, cmd) "*stepsize [d] change DRC step size to d units", "catchup run checker and wait for it to complete", "check recheck area under box in all cells", - "count count error tiles in each cell under box", + "count [total] count error tiles in each cell under box", "euclidean on|off enable/disable Euclidean geometry checking", "find [nth] locate next (or nth) error in the layout", "help print this help information", @@ -3304,6 +3305,14 @@ CmdDrc(w, cmd) break; case COUNT: + count_total = -1; + if (argc == 3) + if (!strncmp(argv[2], "total", 5)) + count_total = 0; + +#ifdef MAGIC_WRAPPER + if (count_total == -1) lobj = Tcl_NewListObj(0, NULL); +#endif if ((window = w) == NULL) { window = ToolGetBoxWindow(&rootArea, (int *) NULL); @@ -3313,44 +3322,61 @@ CmdDrc(w, cmd) rootArea = w->w_surfaceArea; rootUse = (CellUse *) window->w_surfaceID; - count_total = DRCCount(rootUse, &rootArea); - -#ifdef MAGIC_WRAPPER - if (dolist) - { - lobj = Tcl_NewListObj(0, NULL); - Tcl_ListObjAppendElement(magicinterp, lobj, - Tcl_NewStringObj(rootUse->cu_def->cd_name, -1)); - Tcl_ListObjAppendElement(magicinterp, lobj, - Tcl_NewIntObj(count_total)); - } - else + dcl = DRCCount(rootUse, &rootArea); + while (dcl != NULL) { + if (count_total >= 0) + count_total += dcl->dcl_count; + else + { +#ifdef MAGIC_WRAPPER + if (dolist) + { + Tcl_Obj *pobj = Tcl_NewListObj(0, NULL); + Tcl_ListObjAppendElement(magicinterp, pobj, + Tcl_NewStringObj(dcl->dcl_def->cd_name, -1)); + Tcl_ListObjAppendElement(magicinterp, pobj, + Tcl_NewIntObj(dcl->dcl_count)); + Tcl_ListObjAppendElement(magicinterp, lobj, pobj); + } + else + { #endif - - if (count_total > 1) - TxPrintf("Cell %s has %d error tiles.\n", - rootUse->cu_def->cd_name, count_total); - else if (count_total == 1) - TxPrintf("Cell %s has just one error tile.\n", - rootUse->cu_def->cd_name); + if (dcl->dcl_count > 1) + TxPrintf("Cell %s has %d error tiles.\n", + dcl->dcl_def->cd_name, dcl->dcl_count); + else if (dcl->dcl_count == 1) + TxPrintf("Cell %s has just one error tile.\n", + dcl->dcl_def->cd_name); +#ifdef MAGIC_WRAPPER + } +#endif + } + freeMagic((char *)dcl); + dcl = dcl->dcl_next; + } #ifdef MAGIC_WRAPPER - } -#endif - -#ifdef MAGIC_WRAPPER - if (doforall) - Tcl_SetObjResult(magicinterp, lobj); - else if (count_total >= 0) + if (count_total >= 0) { if (dolist) Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(count_total)); else - TxPrintf("Total DRC errors found: %d\n", count_total); + { + if ((DRCBackGround != DRC_SET_OFF) && (count_total == -1)) + count_total = 0; + if (count_total >= 0) + TxPrintf("Total DRC errors found: %d\n", count_total); + } } + else if (dolist) + Tcl_SetObjResult(magicinterp, lobj); + #else - TxPrintf("Total DRC errors found: %d\n", count_total); + if ((DRCBackGround != DRC_SET_OFF) && (count_total == -1)) + count_total = 0; + if (count_gotal >= 0) + TxPrintf("Total DRC errors found: %d\n", count_total); #endif break; diff --git a/drc/DRCmain.c b/drc/DRCmain.c index 72d9c456..2b365224 100644 --- a/drc/DRCmain.c +++ b/drc/DRCmain.c @@ -747,31 +747,97 @@ drcCheckFunc(scx, cdarg) * ---------------------------------------------------------------------------- */ -int +DRCCountList * DRCCount(use, area) CellUse *use; /* Top-level use of hierarchy. */ Rect *area; /* Area in which violations are counted. */ { + DRCCountList *dcl, *newdcl; + HashTable dupTable; + HashEntry *he; + HashSearch hs; int count; SearchContext scx; CellDef *def; - extern int drcCountFunc2(); + extern int drcCountFunc(); + + /* Use a hash table to make sure that we don't output information + * for any cell more than once. + */ + + HashInit(&dupTable, 16, HT_WORDKEYS); scx.scx_use = use; scx.scx_x = use->cu_xlo; scx.scx_y = use->cu_ylo; scx.scx_area = *area; scx.scx_trans = GeoIdentityTransform; + (void) drcCountFunc(&scx, &dupTable); - def = use->cu_def; + /* Create the list from the hash table */ + + dcl = NULL; + if (dupTable.ht_table != (HashEntry **) NULL) + { + HashStartSearch(&hs); + while ((he = HashNext(&dupTable, &hs)) != (HashEntry *)NULL) + { + count = (spointertype)HashGetValue(he); + if (count > 1) + { + newdcl = (DRCCountList *)mallocMagic(sizeof(DRCCountList)); + newdcl->dcl_count = count - 1; + newdcl->dcl_def = (CellDef *)he->h_key.h_ptr; + newdcl->dcl_next = dcl; + dcl = newdcl; + } + } + } + HashKill(&dupTable); + return dcl; +} + +int +drcCountFunc(scx, dupTable) + SearchContext *scx; + HashTable *dupTable; /* Passed as client data, used to + * avoid searching any cell twice. + */ +{ + int count; + HashEntry *h; + CellDef *def; + extern int drcCountFunc2(); + + /* If we've already seen this cell definition before, then skip it + * now. + */ + + def = scx->scx_use->cu_def; + h = HashFind(dupTable, (char *)def); + if (HashGetValue(h) != 0) goto done; + HashSetValue(h, 1); /* Count errors in this cell definition by scanning the error plane. */ count = 0; (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR], &def->cd_bbox, &DBAllButSpaceBits, drcCountFunc2, (ClientData)(&count)); + HashSetValue(h, (spointertype)count + 1); - return count; + /* Ignore children that have not been loaded---we will only report */ + /* errors that can be seen. This avoids immediately loading and */ + /* drc processing large layouts simply because we asked for an */ + /* error count. When the cell is loaded, drc will be checked */ + /* anyway, and the count can be updated in response to that check. */ + + if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) return 0; + + /* As a special performance hack, if the complete cell area is + * handled here, don't bother to look at any more array elements. + */ + done: if (GEO_SURROUND(&scx->scx_area, &def->cd_bbox)) return 2; + else return 0; } int diff --git a/drc/drc.h b/drc/drc.h index 99bf0d28..6f3e98c6 100644 --- a/drc/drc.h +++ b/drc/drc.h @@ -125,6 +125,15 @@ typedef struct drcpendingcookie struct drcpendingcookie *dpc_next; } DRCPendingCookie; +/* Structure used to pass back lists of cell definitions and error tile counts */ + +typedef struct drccountlist +{ + CellDef *dcl_def; + int dcl_count; + struct drccountlist *dcl_next; +} DRCCountList; + /* Structure used to keep information about the current DRC style */ typedef struct drckeep @@ -258,7 +267,7 @@ extern void DRCPrintRulesTable(); extern void DRCWhy(); extern void DRCPrintStats(); extern void DRCCheck(); -extern int DRCCount(); +extern DRCCountList *DRCCount(); extern int DRCFind(); extern void DRCCatchUp(); extern bool DRCFindInteractions(); From 458631df41719ed6a61a9c9775c4950c51359d36 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 24 Feb 2020 21:50:15 -0500 Subject: [PATCH 110/121] updated VERSION for the night (to be checked tomorrow---versioning, git, and the update script should all be working smoothly now). --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index c0768957..6022050e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.186 +8.2.187 From b62efea43df54a08d3a928d90378d7c68f499dd7 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 25 Feb 2020 09:52:06 -0500 Subject: [PATCH 111/121] Corrected the last commit for fixing the "drc count" command option, which had been changed a few months back to remove the individual cell count and only list the top level cell. The behavior has been changed a bit so that "list" returns values for the top level cell only, but "listall" returns a complete list. "drc list count total" gives the DRC count for the top cell, but "drc listall count total" gives the DRC count for everything (probably not very useful). Also: Implemented a behavior by request to automatically removed the (UNNAMED) cell whenever a new cell is loaded and the (UNNAMED) cell has not been modified. --- VERSION | 2 +- commands/CmdCD.c | 2 +- dbwind/DBWprocs.c | 22 +++++++++++++++++++++- drc/DRCmain.c | 19 ++++++++++++++++++- windows/windMove.c | 1 + 5 files changed, 42 insertions(+), 4 deletions(-) diff --git a/VERSION b/VERSION index 6022050e..8ca3c547 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.187 +8.2.188 diff --git a/commands/CmdCD.c b/commands/CmdCD.c index d91da3a6..0d31dff3 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -3322,7 +3322,7 @@ CmdDrc(w, cmd) rootArea = w->w_surfaceArea; rootUse = (CellUse *) window->w_surfaceID; - dcl = DRCCount(rootUse, &rootArea); + dcl = DRCCount(rootUse, &rootArea, doforall); while (dcl != NULL) { if (count_total >= 0) diff --git a/dbwind/DBWprocs.c b/dbwind/DBWprocs.c index 95458ec0..2bf4fca1 100644 --- a/dbwind/DBWprocs.c +++ b/dbwind/DBWprocs.c @@ -289,13 +289,14 @@ DBWloadWindow(window, name, ignoreTech, expand, dereference) bool expand; /* Indicates whether or not to expand the cell */ bool dereference; /* If TRUE, ignore path references in the input */ { - CellDef *newEditDef; + CellDef *newEditDef, *deleteDef; CellUse *newEditUse; void DisplayWindow(); int res, newEdit, error_val; int xadd, yadd; Rect loadBox; char *rootname; + bool isUnnamed; int UnexpandFunc(); /* forward declaration */ loadBox.r_xbot = loadBox.r_ybot = 0; @@ -305,6 +306,19 @@ DBWloadWindow(window, name, ignoreTech, expand, dereference) newEdit = !WindSearch((WindClient) DBWclientID, (ClientData) NULL, (Rect *) NULL, dbwLoadFunc, (ClientData) window); + /* The (UNNAMED) cell generally gets in the way, so delete it if */ + /* any new cell is loaded and (UNNAMED) has no contents. */ + + if (window->w_surfaceID == (ClientData)NULL) + deleteDef = NULL; + else + { + deleteDef = ((CellUse *)window->w_surfaceID)->cu_def; + if (strcmp(deleteDef->cd_name, "(UNNAMED)") || + deleteDef->cd_flags & (CDMODIFIED|CDBOXESCHANGED|CDSTAMPSCHANGED)) + deleteDef = NULL; + } + if ((name == (char *) NULL) || (name[0] == '\0')) { /* @@ -503,6 +517,12 @@ DBWloadWindow(window, name, ignoreTech, expand, dereference) if (newEdit) DBWAreaChanged(newEditDef, &newEditDef->cd_bbox, DBW_ALLWINDOWS, &DBAllButSpaceBits); + + /* If the cell before loading was (UNNAMED) and it was */ + /* never modified, then delete it now. */ + + if (deleteDef != NULL) + DBCellDelete(deleteDef->cd_name, TRUE); } /* This function is called for each cell whose expansion status changed. diff --git a/drc/DRCmain.c b/drc/DRCmain.c index 2b365224..09d6e2d9 100644 --- a/drc/DRCmain.c +++ b/drc/DRCmain.c @@ -748,9 +748,10 @@ drcCheckFunc(scx, cdarg) */ DRCCountList * -DRCCount(use, area) +DRCCount(use, area, recurse) CellUse *use; /* Top-level use of hierarchy. */ Rect *area; /* Area in which violations are counted. */ + bool recurse; /* If TRUE, count errors in all subcells */ { DRCCountList *dcl, *newdcl; HashTable dupTable; @@ -761,12 +762,19 @@ DRCCount(use, area) CellDef *def; extern int drcCountFunc(); + /* Shouldn't happen? */ + if (!(use->cu_def->cd_flags & CDAVAILABLE)) return NULL; + /* Use a hash table to make sure that we don't output information * for any cell more than once. */ HashInit(&dupTable, 16, HT_WORDKEYS); + /* Clearing CDAVAILABLE from cd_flags keeps the count from recursing */ + if (recurse == FALSE) + use->cu_def->cd_flags &= ~CDAVAILABLE; + scx.scx_use = use; scx.scx_x = use->cu_xlo; scx.scx_y = use->cu_ylo; @@ -794,6 +802,11 @@ DRCCount(use, area) } } HashKill(&dupTable); + + /* Restore the CDAVAILABLE flag */ + if (recurse == FALSE) + use->cu_def->cd_flags |= CDAVAILABLE; + return dcl; } @@ -833,6 +846,10 @@ drcCountFunc(scx, dupTable) if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) return 0; + /* Scan children recursively. */ + + DBCellSrArea(scx, drcCountFunc, (ClientData)dupTable); + /* As a special performance hack, if the complete cell area is * handled here, don't bother to look at any more array elements. */ diff --git a/windows/windMove.c b/windows/windMove.c index 0f91b5f4..d1420ef8 100644 --- a/windows/windMove.c +++ b/windows/windMove.c @@ -290,6 +290,7 @@ WindCreate(client, frameArea, isHint, argc, argv) w->w_grdata2 = (ClientData) NULL; w->w_backingStore = (ClientData)NULL; w->w_redrawAreas = (ClientData) NULL; + w->w_surfaceID = (ClientData) NULL; w->w_iconname = NULL; for (id = 0; ((1 << id) & windWindowMask) != 0; id++) /* advance id */ ; windWindowMask |= (1 << id); From 2beb5ee0e9412870fec76c92464477b79d5f28bc Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 25 Feb 2020 13:57:41 -0500 Subject: [PATCH 112/121] Modified the handling of "why" strings in the DRC mechanism, so that DRC records contain an index into a string array instead of containing a copy of a string. This is preliminary to changing the way the DRC error plane is painted, so that the types painted will mark the error type. This will (1) allow "drc why" to simply scan the DRC error plane rather than running the DRC engine, (2) allow DRC errors to be counted by area rather than by tile, and (3) let the DRC count be the same whether done by "drc listall why" or "drc count". --- drc/DRCarray.c | 2 +- drc/DRCbasic.c | 2 +- drc/DRCcif.c | 9 ++- drc/DRCmain.c | 49 ++++++++-------- drc/DRCsubcell.c | 2 +- drc/DRCtech.c | 142 ++++++++++++++++++++++++++++++----------------- drc/drc.h | 28 ++++------ 7 files changed, 130 insertions(+), 104 deletions(-) diff --git a/drc/DRCarray.c b/drc/DRCarray.c index 75039503..4e1aa133 100644 --- a/drc/DRCarray.c +++ b/drc/DRCarray.c @@ -46,7 +46,7 @@ static DRCCookie drcArrayCookie = { 0, 0, 0, 0, { 0 }, { 0 }, 0, 0, 0, - "This layer can't abut or partially overlap between array elements", + DRC_ARRAY_OVERLAP_TAG, (DRCCookie *) NULL }; diff --git a/drc/DRCbasic.c b/drc/DRCbasic.c index 77ecd09b..a25b51ec 100644 --- a/drc/DRCbasic.c +++ b/drc/DRCbasic.c @@ -47,7 +47,7 @@ static DRCCookie drcOverlapCookie = { 0, 0, 0, 0, { 0 }, { 0 }, 0, 0, 0, - "Can't overlap those layers", + DRC_OVERLAP_TAG, (DRCCookie *) NULL }; diff --git a/drc/DRCcif.c b/drc/DRCcif.c index 477ae23f..e3382fc5 100644 --- a/drc/DRCcif.c +++ b/drc/DRCcif.c @@ -48,7 +48,6 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "utils/malloc.h" #include "utils/utils.h" -extern char *drcWhyDup(); extern int drcCifTile(); extern int areaCifCheck(); extern void drcCheckCifMaxwidth(); @@ -169,7 +168,7 @@ drcCifWidth(argc, argv) char *layername = argv[1]; int scalefactor; int centidistance = atoi(argv[2]); - char *why = drcWhyDup(argv[3]); + int why = drcWhyCreate(argv[3]); TileTypeBitMask set, setC, tmp1; int thislayer = -1; DRCCookie *dpnew,*dpnext; @@ -228,7 +227,7 @@ drcCifSpacing(argc, argv) char *argv[]; { char *adjacency = argv[4]; - char *why = drcWhyDup(argv[5]); + int why = drcWhyCreate(argv[5]); DRCCookie *dpnext, *dpnew; int needReverse = FALSE; TileType i, j; @@ -1065,7 +1064,7 @@ drcCifArea(argc, argv) char *layers = argv[1]; int centiarea = atoi(argv[2]); int centihorizon = atoi(argv[3]); - char *why = drcWhyDup(argv[4]); + int why = drcWhyCreate(argv[4]); TileTypeBitMask set, setC, tmp1; DRCCookie *dpnext, *dpnew; TileType i, j; @@ -1126,7 +1125,7 @@ drcCifMaxwidth(argc, argv) char *layers = argv[1]; int centidistance = atoi(argv[2]); char *bends = argv[3]; - char *why = drcWhyDup(argv[4]); + int why = drcWhyCreate(argv[4]); TileTypeBitMask set, setC, tmp1; DRCCookie *dpnext, *dpnew; TileType i, j; diff --git a/drc/DRCmain.c b/drc/DRCmain.c index 09d6e2d9..6bb67818 100644 --- a/drc/DRCmain.c +++ b/drc/DRCmain.c @@ -69,9 +69,8 @@ TileType DRCErrorType; /* Type of error tile to paint. */ /* Used by drcPrintError: */ -HashTable DRCErrorTable; /* Hash table used to eliminate duplicate - * error strings. - */ +int *DRCErrorList; /* List of DRC error type counts */ +HashTable DRCErrorTable; /* Table of DRC errors and geometry */ /* Global variables used by all DRC modules to record statistics. * For each statistic we keep two values, the count since stats @@ -183,11 +182,12 @@ drcSubstitute (cptr) DRCCookie * cptr; /* Design rule violated */ { static char *why_out = NULL; - char *whyptr = cptr->drcc_why, *sptr, *wptr; + char *whyptr, *sptr, *wptr; int subscnt = 0, whylen; float oscale, value; extern float CIFGetOutputScale(); + whyptr = DRCCurStyle->DRCWhyList[cptr->drcc_tag]; while ((sptr = strchr(whyptr, '%')) != NULL) { subscnt++; @@ -195,7 +195,7 @@ drcSubstitute (cptr) } if (subscnt == 0) return whyptr; /* No substitutions */ - whyptr = cptr->drcc_why; + whyptr = DRCCurStyle->DRCWhyList[cptr->drcc_tag]; whylen = strlen(whyptr) + 20 * subscnt; if (why_out != NULL) freeMagic(why_out); why_out = (char *)mallocMagic(whylen * sizeof(char)); @@ -256,7 +256,7 @@ drcSubstitute (cptr) * * Side effects: * DRCErrorCount is incremented. The text associated with - * the error is entered into DRCErrorTable, and, if this is + * the error is entered into DRCErrorList, and, if this is * the first time that entry has been seen, then the error * text is printed. If the area parameter is non-NULL, then * only errors intersecting that area are considered. @@ -279,12 +279,11 @@ drcPrintError (celldef, rect, cptr, scx) area = &scx->scx_area; if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return; DRCErrorCount += 1; - h = HashFind(&DRCErrorTable, cptr->drcc_why); - i = (spointertype) HashGetValue(h); + + i = DRCErrorList[cptr->drcc_tag]; if (i == 0) TxPrintf("%s\n", drcSubstitute(cptr)); - i++; - HashSetValue(h, (spointertype)i); + DRCErrorList[cptr->drcc_tag] = i + 1; } /* Same routine as above, but output goes to a Tcl list and is appended */ @@ -308,8 +307,7 @@ drcListError (celldef, rect, cptr, scx) area = &scx->scx_area; if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return; DRCErrorCount += 1; - h = HashFind(&DRCErrorTable, cptr->drcc_why); - i = (spointertype) HashGetValue(h); + i = DRCErrorList[cptr->drcc_tag]; if (i == 0) { Tcl_Obj *lobj; @@ -318,8 +316,7 @@ drcListError (celldef, rect, cptr, scx) Tcl_NewStringObj(drcSubstitute(cptr), -1)); Tcl_SetObjResult(magicinterp, lobj); } - i += 1; - HashSetValue(h, (spointertype)i); + DRCErrorList[cptr->drcc_tag] = i + 1; } /* Same routine as above, but output for every single error is recorded */ @@ -475,11 +472,15 @@ DRCWhy(dolist, use, area) { SearchContext scx; Rect box; + int i; extern int drcWhyFunc(); /* Forward reference. */ - /* Create a hash table to used for eliminating duplicate messages. */ + /* Create a hash table to eliminate duplicate messages. */ + + DRCErrorList = (int *)mallocMagic((DRCCurStyle->DRCWhySize + 1) * sizeof(int)); + for (i = 0; i <= DRCCurStyle->DRCWhySize; i++) + DRCErrorList[i] = 0; - HashInit(&DRCErrorTable, 16, HT_STRINGKEYS); DRCErrorCount = 0; box = DRCdef->cd_bbox; @@ -494,12 +495,9 @@ DRCWhy(dolist, use, area) drcWhyFunc(&scx, (pointertype)dolist); UndoEnable(); - /* Delete the hash table now that we're finished (otherwise there - * will be a core leak. - */ - - HashKill(&DRCErrorTable); - + /* Delete the error list */ + freeMagic(DRCErrorList); + /* Redisplay the DRC yank definition in case anyone is looking * at it. */ @@ -532,7 +530,7 @@ DRCWhyAll(use, area, fout) HashEntry *he; Tcl_Obj *lobj, *robj; - /* Create a hash table to used for eliminating duplicate messages. */ + /* Create a hash table for storing all of the results */ HashInit(&DRCErrorTable, 16, HT_STRINGKEYS); DRCErrorCount = 0; @@ -566,10 +564,7 @@ DRCWhyAll(use, area, fout) } Tcl_SetObjResult(magicinterp, robj); - /* Delete the hash table now that we're finished (otherwise there - * will be a core leak. - */ - + /* Delete the error table now that we're finished */ HashKill(&DRCErrorTable); /* Redisplay the DRC yank definition in case anyone is looking diff --git a/drc/DRCsubcell.c b/drc/DRCsubcell.c index 53eca616..7688a826 100644 --- a/drc/DRCsubcell.c +++ b/drc/DRCsubcell.c @@ -59,7 +59,7 @@ static DRCCookie drcSubcellCookie = { 0, 0, 0, 0, { 0 }, { 0 }, 0, 0, 0, - "This layer can't abut or partially overlap between subcells", + DRC_SUBCELL_OVERLAP_TAG, (DRCCookie *) NULL }; diff --git a/drc/DRCtech.c b/drc/DRCtech.c index dd49a0d4..48009a51 100644 --- a/drc/DRCtech.c +++ b/drc/DRCtech.c @@ -61,6 +61,11 @@ global int DRCRuleOptimization = TRUE; static int drcRulesSpecified = 0; static int drcRulesOptimized = 0; +/* Rules with unique names are tagged with a reference number */ +/* for use in placing errors into the DRC error plane. */ + +static int DRCtag = 0; + /* * Forward declarations. */ @@ -281,21 +286,14 @@ drcTechFreeStyle() dp = DRCCurStyle->DRCRulesTbl[i][j]; while (dp != NULL) { - char *old = (char *) dp; + char *old = (char *)dp; dp = dp->drcc_next; freeMagic(old); } } - /* Clear the DRCWhyList */ - - while (DRCCurStyle->DRCWhyList != NULL) - { - old = (char *) DRCCurStyle->DRCWhyList; - StrDup(&(DRCCurStyle->DRCWhyList->dwl_string), (char *) NULL); - DRCCurStyle->DRCWhyList = DRCCurStyle->DRCWhyList->dwl_next; - freeMagic(old); - } + /* Clear the Why string list */ + freeMagic(DRCCurStyle->DRCWhyList); freeMagic(DRCCurStyle); DRCCurStyle = NULL; @@ -329,31 +327,54 @@ drcTechNewStyle() /* * ---------------------------------------------------------------------------- - * drcWhyDup -- + * drcWhyCreate -- * - * Duplicate a shared "why" string using StrDup() and remember it so we can - * free it sometime later, in drcWhyClear(). + * Create a hash entry for the DRC "why" string, if it does not already + * exist. * * Returns: - * A copy of the given string. + * A pointer to the drcWhy structure containing the string and tag. * * Side effects: - * Adds to the DRCWhyList. Calls StrDup(). + * Adds to the DRCWhyList if whystring has not been used before. + * Calls StrDup() and increments DRCWhySize. DRCWhyList is allocated + * in blocks of 50 at a time and only expands when filled. + * Temporary hash table DRCErrorTable is used to determine if a + * string entry is unique. It is cleared after the technology file + * has been processed. * ---------------------------------------------------------------------------- */ -char * -drcWhyDup(why) - char * why; +int +drcWhyCreate(whystring) + char *whystring; { - struct drcwhylist * new; + HashEntry *he; - new = (struct drcwhylist *) mallocMagic((unsigned) (sizeof *new)); - new->dwl_string = StrDup((char **) NULL, why); - new->dwl_next = DRCCurStyle->DRCWhyList; - DRCCurStyle->DRCWhyList = new; + he = HashLookOnly(&DRCErrorTable, whystring); + if (he != NULL) + return (int)((pointertype)HashGetValue(he)); - return new->dwl_string; + /* Grow the list in increments of 50 */ + if ((DRCCurStyle->DRCWhySize % 50) == 0) + { + int i; + char **newList; + newList = (char **)mallocMagic((DRCCurStyle->DRCWhySize + 51) * sizeof(char *)); + for (i = 0; i < DRCCurStyle->DRCWhySize; i++) + newList[i] = DRCCurStyle->DRCWhyList[i]; + if (DRCCurStyle->DRCWhySize > 0) + freeMagic((char *)DRCCurStyle->DRCWhyList); + DRCCurStyle->DRCWhyList = newList; + } + DRCCurStyle->DRCWhySize++; + + he = HashFind(&DRCErrorTable, whystring); + HashSetValue(he, (char *)((pointertype)DRCCurStyle->DRCWhySize)); + + DRCCurStyle->DRCWhyList[DRCCurStyle->DRCWhySize] = StrDup((char **)NULL, whystring); + + return DRCCurStyle->DRCWhySize; } /* @@ -535,12 +556,29 @@ DRCTechStyleInit() DRCCurStyle->ds_status = TECH_NOT_LOADED; TTMaskZero(&DRCCurStyle->DRCExactOverlapTypes); - DRCCurStyle->DRCWhyList = NULL; DRCCurStyle->DRCTechHalo = 0; DRCCurStyle->DRCScaleFactorN = 1; DRCCurStyle->DRCScaleFactorD = 1; DRCCurStyle->DRCStepSize = 0; DRCCurStyle->DRCFlags = (char)0; + DRCCurStyle->DRCWhySize = 0; + + HashInit(&DRCErrorTable, 16, HT_STRINGKEYS); + + /* First DRC entry is associated with the statically-allocated */ + /* drcArrayCookie and has a tag of DRC_ARRAY_OVERLAP_TAG = 1 */ + /* (see DRCarray.c). */ + drcWhyCreate("This layer can't abut or partially overlap between array elements"); + + /* Second DRC entry is associated with the statically-allocated */ + /* drcOverlapCookie and has a tag of DRC_OVERLAP_TAG = 2 */ + /* (see DRCbasic.c). */ + drcWhyCreate("Can't overlap those layers"); + + /* Third DRC entry is associated with the statically-allocated */ + /* drcSubcellCookie and has a tag of DRC_SUBCELL_OVERLAP_TAG = 3 */ + /* (see DRCsubcell.c). */ + drcWhyCreate("This layer can't abut or partially overlap between subcells"); DRCTechHalo = 0; @@ -872,18 +910,18 @@ DRCTechLine(sectionName, argc, argv) } void -drcCifAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefrom) +drcCifAssign(cookie, dist, next, mask, corner, tag, cdist, flags, planeto, planefrom) DRCCookie *cookie, *next; int dist, cdist; TileTypeBitMask *mask, *corner; - char *why; + int tag; int flags, planeto, planefrom; { (cookie)->drcc_dist = dist; (cookie)->drcc_next = next; (cookie)->drcc_mask = *mask; (cookie)->drcc_corner = *corner; - (cookie)->drcc_why = why; + (cookie)->drcc_tag = tag; (cookie)->drcc_cdist = cdist; (cookie)->drcc_flags = flags; (cookie)->drcc_edgeplane = planefrom; @@ -900,7 +938,7 @@ drcAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefro DRCCookie *cookie, *next; int dist, cdist; TileTypeBitMask *mask, *corner; - char *why; + int why; int flags, planeto, planefrom; { /* Diagnostic */ @@ -1088,7 +1126,7 @@ drcExtend(argc, argv) char *layers1 = argv[1]; char *layers2 = argv[2]; int distance = atoi(argv[3]); - char *why; + int why; TileTypeBitMask set1, setC; DRCCookie *dp, *dpnew, *dptrig; TileType i, j; @@ -1100,10 +1138,10 @@ drcExtend(argc, argv) if (!strncmp(argv[4], "exact_", 6)) { exact = TRUE; - why = drcWhyDup(argv[5]); + why = drcWhyCreate(argv[5]); } else - why = drcWhyDup(argv[4]); + why = drcWhyCreate(argv[4]); ptest = DBTechNoisyNameMask(layers1, &set1); pMask1 = CoincidentPlanes(&set1, ptest); @@ -1257,7 +1295,7 @@ drcWidth(argc, argv) { char *layers = argv[1]; int distance = atoi(argv[2]); - char *why = drcWhyDup(argv[3]); + int why = drcWhyCreate(argv[3]); TileTypeBitMask set, setC; PlaneMask pmask, pset, ptest; DRCCookie *dp, *dpnew; @@ -1342,7 +1380,7 @@ drcArea(argc, argv) char *layers = argv[1]; int distance = atoi(argv[2]); int horizon = atoi(argv[3]); - char *why = drcWhyDup(argv[4]); + int why = drcWhyCreate(argv[4]); TileTypeBitMask set, setC; DRCCookie *dp, *dpnew; TileType i, j; @@ -1442,7 +1480,7 @@ drcMaxwidth(argc, argv) char *layers = argv[1]; int distance = atoi(argv[2]); char *bends = argv[3]; - char *why; + int why; TileTypeBitMask set, setC; DRCCookie *dp, *dpnew; TileType i, j; @@ -1469,7 +1507,7 @@ drcMaxwidth(argc, argv) bend = 0; else bend = DRC_BENDS; - why = drcWhyDup(argv[3]); + why = drcWhyCreate(argv[3]); } else { @@ -1480,7 +1518,7 @@ drcMaxwidth(argc, argv) TechError("unknown bend option %s\n",bends); return (0); } - why = drcWhyDup(argv[4]); + why = drcWhyCreate(argv[4]); } for (i = 0; i < DBNumTypes; i++) @@ -1531,7 +1569,7 @@ drcAngles(argc, argv) { char *layers = argv[1]; int angles = atoi(argv[2]); - char *why = drcWhyDup(argv[3]); + int why = drcWhyCreate(argv[3]); TileTypeBitMask set; DRCCookie *dp, *dpnew; int plane; @@ -1599,7 +1637,7 @@ drcSpacing3(argc, argv) char *layers3 = argv[5]; int distance = atoi(argv[3]); char *adjacency = argv[4]; - char *why = drcWhyDup(argv[6]); + int why = drcWhyCreate(argv[6]); TileTypeBitMask set1, set2, set3; int plane; DRCCookie *dp, *dpnew; @@ -2151,7 +2189,7 @@ drcSpacing(argc, argv) { char *layers1 = argv[1], *layers2; char *adjacency; - char *why; + int why; TileTypeBitMask set1, set2, tmp1, tmp2; PlaneMask pmask1, pmask2, pmaskA, pmaskB, ptest; int wwidth, distance, plane, plane2, runlength; @@ -2172,7 +2210,7 @@ drcSpacing(argc, argv) layers2 = argv[4]; distance = atoi(argv[5]); adjacency = argv[6]; - why = drcWhyDup(argv[7]); + why = drcWhyCreate(argv[7]); } else { @@ -2180,7 +2218,7 @@ drcSpacing(argc, argv) distance = atoi(argv[4]); runlength = distance; adjacency = argv[5]; - why = drcWhyDup(argv[6]); + why = drcWhyCreate(argv[6]); } /* TxPrintf("Info: DRCtech: widespacing rule for %s width %d:" " spacing must be %d\n", layers1, wwidth, distance); */ @@ -2191,7 +2229,7 @@ drcSpacing(argc, argv) distance = atoi(argv[3]); adjacency = argv[4]; wwidth = distance; - why = drcWhyDup(argv[5]); + why = drcWhyCreate(argv[5]); runlength = distance; if (argc >= 7) { @@ -2325,7 +2363,7 @@ drcEdge(argc, argv) int distance = atoi(argv[3]); char *okTypes = argv[4], *cornerTypes = argv[5]; int cdist = atoi(argv[6]); - char *why = drcWhyDup(argv[7]); + int why = drcWhyCreate(argv[7]); bool fourway = (strcmp(argv[0], "edge4way") == 0); TileTypeBitMask set1, set2, setC, setM; DRCCookie *dp, *dpnew; @@ -2491,7 +2529,7 @@ drcOverhang(argc, argv) { char *layers2 = argv[1], *layers1 = argv[2]; int distance = atoi(argv[3]); - char *why = drcWhyDup(argv[4]); + int why = drcWhyCreate(argv[4]); TileTypeBitMask set1, set2, setM, setC, setN, set2inv; DRCCookie *dp, *dpnew, *dptrig; int plane, plane2; @@ -2627,7 +2665,7 @@ drcRectOnly(argc, argv) char *argv[]; { char *layers = argv[1]; - char *why = drcWhyDup(argv[2]); + int why = drcWhyCreate(argv[2]); TileTypeBitMask set1, set2, setC; PlaneMask pmask, pset, ptest; DRCCookie *dp, *dpnew; @@ -2727,7 +2765,7 @@ drcSurround(argc, argv) char *layers1 = argv[1], *layers2 = argv[2]; int distance = atoi(argv[3]); char *presence = argv[4]; - char *why = drcWhyDup(argv[5]); + int why = drcWhyCreate(argv[5]); TileTypeBitMask set1, set2, setM, invM, setR; DRCCookie *dp, *dpnew, *dptrig; int plane1, plane2; @@ -3100,7 +3138,7 @@ drcRectangle(argc, argv) char *argv[]; { char *layers = argv[1]; - char *why = drcWhyDup(argv[4]); + int why = drcWhyCreate(argv[4]); TileTypeBitMask types, nottypes; int maxwidth; static char *drcRectOpt[4] = {"any", "even", "odd", 0}; @@ -3466,6 +3504,9 @@ drcTechFinalStyle(style) DRCCookie **dpp, **dp2back; TileType i, j; + /* Done with DRCErrorTable */ + HashKill(&DRCErrorTable); + /* If the scale factor is not 1, then divide all distances by */ /* the scale factor, take the ceiling, and save the (negative) */ /* remainder. */ @@ -3587,7 +3628,6 @@ drcTechFinalStyle(style) } else { - /* Don't free the shared drcc_why string here! */ freeMagic((char *)dptest); drcRulesOptimized++; } @@ -3682,7 +3722,8 @@ drcTechFinalStyle(style) /* TxPrintf("For edge %s-%s, \"%s\" covers \"%s\"\n", DBTypeShortName(i), DBTypeShortName(j), - next->drcc_why, dp->drcc_why); + DRCCurStyle->DRCWhyList[next->drcc_tag], + DRCCurStyle->DRCWhyList[dp->drcc_tag]); */ dp2back = &(style->DRCRulesTbl[i][j]); while (*dp2back != dp) @@ -3704,7 +3745,6 @@ drcTechFinalStyle(style) else *dp2back = dp->drcc_next; - /* Don't free the shared drcc_why string here! */ freeMagic((char *) dp); drcRulesOptimized += 1; } diff --git a/drc/drc.h b/drc/drc.h index 6f3e98c6..69f6ff35 100644 --- a/drc/drc.h +++ b/drc/drc.h @@ -39,10 +39,15 @@ typedef struct drccookie int drcc_edgeplane; /* Plane of edge */ int drcc_plane; /* Index of plane on which to check * legal types. */ - char *drcc_why; /* Explanation of error found */ + int drcc_tag; /* Tag to explanation of error found */ struct drccookie *drcc_next; } DRCCookie; +/* These DRC tags in DRCcookie are predefined. */ +#define DRC_ARRAY_OVERLAP_TAG 1 +#define DRC_OVERLAP_TAG 2 +#define DRC_SUBCELL_OVERLAP_TAG 3 + /* *This is size "int" because it holds an area for DRC_AREA rules, */ /* and therefore may have twice the bit length of a normal rule distance. */ @@ -142,22 +147,6 @@ typedef struct drckeep char *ds_name; } DRCKeep; -/* - * DRC "why" strings are potentially referred to hundreds of times by - * DRC cookies in the rule table. Rather than creating hundreds of - * copies of each string, we create just one copy and let all the cookies - * point to that one copy. - * - * Since we can't free these shared "why" strings when we delete a cookie, - * we keep a list of these strings and free them all when convenient. - */ - -typedef struct drcwhylist -{ - char * dwl_string; - struct drcwhylist * dwl_next; -} drcWhyList; - /* * Structure defining a DRC style */ @@ -173,7 +162,8 @@ typedef struct drcstyle int DRCTechHalo; /* largest action distance of design rules */ int DRCStepSize; /* chunk size for decomposing large areas */ char DRCFlags; /* Option flags */ - drcWhyList *DRCWhyList; + char **DRCWhyList; /* Indexed list of "why" text strings */ + int DRCWhySize; /* Length of DRCWhyList */ PaintResultType DRCPaintTable[NP][NT][NT]; } DRCStyle; @@ -229,6 +219,7 @@ extern DRCKeep *DRCStyleList; /* List of available DRC styles */ extern DRCStyle *DRCCurStyle; /* Current DRC style in effect */ extern CellDef *DRCdef; /* Current cell being checked for DRC */ extern CellUse *DRCuse, *DRCDummyUse; +extern HashTable DRCErrorTable; /* DRC errors, hashed by name */ /* * Internal procedures @@ -241,6 +232,7 @@ extern int drcExactOverlapTile(); extern void drcInitRulesTbl(); extern void drcAssign(); extern void drcCifAssign(); +extern int drcWhyCreate(); /* * Exported procedures From 612251b2b007761f8025fe34b72749c2a23c36cd Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 26 Feb 2020 10:10:55 -0500 Subject: [PATCH 113/121] Changed the PNG bitmaps to GIF, because PNG is not supported in Tcl/Tk 8.5, which is still installed and considered current/stable on a lot of systems. --- VERSION | 2 +- magic/Makefile | 2 +- magic/bitmaps/down.gif | Bin 0 -> 103 bytes magic/bitmaps/down.png | Bin 290 -> 0 bytes magic/bitmaps/left.gif | Bin 0 -> 103 bytes magic/bitmaps/left.png | Bin 291 -> 0 bytes magic/bitmaps/right.gif | Bin 0 -> 102 bytes magic/bitmaps/right.png | Bin 289 -> 0 bytes magic/bitmaps/up.gif | Bin 0 -> 102 bytes magic/bitmaps/up.png | Bin 290 -> 0 bytes magic/bitmaps/zoom.gif | Bin 0 -> 103 bytes magic/bitmaps/zoom.png | Bin 276 -> 0 bytes tcltk/wrapper.tcl | 10 +++++----- 13 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 magic/bitmaps/down.gif delete mode 100644 magic/bitmaps/down.png create mode 100644 magic/bitmaps/left.gif delete mode 100644 magic/bitmaps/left.png create mode 100644 magic/bitmaps/right.gif delete mode 100644 magic/bitmaps/right.png create mode 100644 magic/bitmaps/up.gif delete mode 100644 magic/bitmaps/up.png create mode 100644 magic/bitmaps/zoom.gif delete mode 100644 magic/bitmaps/zoom.png diff --git a/VERSION b/VERSION index 8ca3c547..877ae370 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.188 +8.2.189 diff --git a/magic/Makefile b/magic/Makefile index bb38fdcc..7eb68682 100644 --- a/magic/Makefile +++ b/magic/Makefile @@ -19,7 +19,7 @@ EXTRA_LIBS = ${MAGICDIR}/cmwind/libcmwind.o ${MAGICDIR}/commands/libcommands.o \ ${MAGICDIR}/plow/libplow.o ${MAGICDIR}/utils/libutils.o \ ${MAIN_EXTRA_LIBS} -BITMAPS = up.png down.png left.png right.png zoom.png lock.xbm +BITMAPS = up.gif down.gif left.gif right.gif zoom.gif lock.xbm DEST_XBM = $(BITMAPS:%=$(DESTDIR)${INSTALL_TCLDIR}/bitmaps/%) DFLAGS += -DMAGIC_DATE="\"`date`\"" -DCAD_DIR="${LIBDIR}" diff --git a/magic/bitmaps/down.gif b/magic/bitmaps/down.gif new file mode 100644 index 0000000000000000000000000000000000000000..7962f6f5ef6951fc71c8bc768cef0436e00cbcbd GIT binary patch literal 103 zcmZ?wbhEHbVkP47y1}5ni*~)6kGcqwnN~w;y>#E<@hW`k7sIn*`Oplep8USke BAA$e? literal 0 HcmV?d00001 diff --git a/magic/bitmaps/down.png b/magic/bitmaps/down.png deleted file mode 100644 index 78c995180b6f428b733ea99c8ed6cb8c0b2037de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 290 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4%JB>7u;-UBI?bVpxD28NCO+&S3Dk zz__fXwULpbQiP>m$K%LXpeEH4*NBpo#FA92@!;O_l%v diff --git a/magic/bitmaps/left.gif b/magic/bitmaps/left.gif new file mode 100644 index 0000000000000000000000000000000000000000..85b7e28cf66427cf58be544b3de90086df880987 GIT binary patch literal 103 zcmZ?wbhEHbVkP47y1}5ni`Q=hO@5p7nyO^>5p3S%Hj3AHR6w@TN1}RnsYXFQl BAW#4R literal 0 HcmV?d00001 diff --git a/magic/bitmaps/left.png b/magic/bitmaps/left.png deleted file mode 100644 index dd63f521c244b352b45a1b720c8043480dd02e23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 291 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4%JB>7u;-UBI?bVpxD28NCO+1b=SGH7YyFz6Q5 z;|^oL$asaDVdFj4q7$B7^MJZkOI#yLQW8s2t&)pUffR$0fsui(fswAEd5EEzm5G^^ qfr+kxsg;4j^huHFC>nC}Q!>*kacg*X{^4z)1_n=8KbLh*2~7a=eorR= diff --git a/magic/bitmaps/right.gif b/magic/bitmaps/right.gif new file mode 100644 index 0000000000000000000000000000000000000000..11853ba84d61c0e3fb3f8245c0910f9c6014738e GIT binary patch literal 102 zcmZ?wbhEHbVkP47y1}3Q%`Q_3(@65{zWQy9jto-+R+gYuVbDbAG31(oh1^{R1 BAmac4 literal 0 HcmV?d00001 diff --git a/magic/bitmaps/right.png b/magic/bitmaps/right.png deleted file mode 100644 index 4ae31e9c8a9e5fa3ed5a98ce2ba08c56beed6590..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 289 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4%JB>7u;-UBI?bVpxD28NCO+N1$1#t{3&#{_4-=zBos7JNLHKHUXu_V85l%cME*q4kei>9nO2EggI4N8SD*$4Pgg&ebxsLQ0LG?G{Qv*} diff --git a/magic/bitmaps/up.gif b/magic/bitmaps/up.gif new file mode 100644 index 0000000000000000000000000000000000000000..7f46b82a2ea7712f80c16fa9fbea9e6b4a35f8f2 GIT binary patch literal 102 zcmZ?wbhEHbVkP47y1}3Q%`Q=i3@7(Dwx!A3D?arxmmxO6O4H=6TXNfRa0|0%# BA>;r6 literal 0 HcmV?d00001 diff --git a/magic/bitmaps/up.png b/magic/bitmaps/up.png deleted file mode 100644 index cbe449739f642a032b31865f9d89db956199e578..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 290 zcmeAS@N?(olHy`uVBq!ia0vp@Ak4%JB>7u;-UBI?bVpxD28NCO+!C8<`)MX5lF!N|bKK-a)X*U&t~(9Fuvz{>aG}y12r&sy85}Sb4q9e0Mh_XK>z>% diff --git a/magic/bitmaps/zoom.gif b/magic/bitmaps/zoom.gif new file mode 100644 index 0000000000000000000000000000000000000000..a05342d4dd6d95dee5d89d25a735710914455422 GIT binary patch literal 103 zcmZ?wbhEHbVkP47y1}5p2{*}^i`{wm1nr6M;=}`Q+an_8$pbDqcr{q`}tO1i- BA$7u;-UBI?bVpxD28NCO+?an+uemJjk_iV$dUGRaSY+Oo}AFYeC>jO#6bln aPsvQH#I2!Wf0hwY1B0ilpUXO@geCyo)k?Vl diff --git a/tcltk/wrapper.tcl b/tcltk/wrapper.tcl index 2758cd96..b798b5ef 100644 --- a/tcltk/wrapper.tcl +++ b/tcltk/wrapper.tcl @@ -35,23 +35,23 @@ proc magic::makeglyphimages {} { set gsize [expr {int($Opts(scale) * 13)}] set gscale [expr {int($Opts(scale))}] - image create photo stdglyph -file ${CAD_ROOT}/magic/tcl/bitmaps/up.png + image create photo stdglyph -file ${CAD_ROOT}/magic/tcl/bitmaps/up.gif image create photo Glyph(up) -width $gsize -height $gsize Glyph(up) copy stdglyph -zoom $gscale - image create photo stdglyph -file ${CAD_ROOT}/magic/tcl/bitmaps/down.png + image create photo stdglyph -file ${CAD_ROOT}/magic/tcl/bitmaps/down.gif image create photo Glyph(down) -width $gsize -height $gsize Glyph(down) copy stdglyph -zoom $gscale - image create photo stdglyph -file ${CAD_ROOT}/magic/tcl/bitmaps/left.png + image create photo stdglyph -file ${CAD_ROOT}/magic/tcl/bitmaps/left.gif image create photo Glyph(left) -width $gsize -height $gsize Glyph(left) copy stdglyph -zoom $gscale - image create photo stdglyph -file ${CAD_ROOT}/magic/tcl/bitmaps/right.png + image create photo stdglyph -file ${CAD_ROOT}/magic/tcl/bitmaps/right.gif image create photo Glyph(right) -width $gsize -height $gsize Glyph(right) copy stdglyph -zoom $gscale - image create photo stdglyph -file ${CAD_ROOT}/magic/tcl/bitmaps/zoom.png + image create photo stdglyph -file ${CAD_ROOT}/magic/tcl/bitmaps/zoom.gif image create photo Glyph(zoom) -width $gsize -height $gsize Glyph(zoom) copy stdglyph -zoom $gscale From cb7926ab0d2e453749cee402a213f2870e0e6b15 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 28 Feb 2020 14:25:57 -0500 Subject: [PATCH 114/121] Corrected lefTech.c not to issue a warning if defining a contact type as an obstruction; that should be perfectly acceptible. --- VERSION | 2 +- lef/lefTech.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 877ae370..77db8419 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.189 +8.2.190 diff --git a/lef/lefTech.c b/lef/lefTech.c index 272e4302..1dc68572 100644 --- a/lef/lefTech.c +++ b/lef/lefTech.c @@ -270,7 +270,7 @@ LefTechLine(sectionName, argc, argv) isContact = DBIsContact(mtype); if (option == LEFTECH_LAYER) option = (isContact) ? LEFTECH_CUT : LEFTECH_ROUTE; - else if (isContact && (option != LEFTECH_CUT && option != LEFTECH_CONTACT)) + else if (isContact && (option != LEFTECH_CUT && option != LEFTECH_CONTACT && option != LEFTECH_OBS)) TechError("Attempt to define cut type %s as %s.\n", DBTypeLongNameTbl[mtype], keywords[option]); else if (!isContact && (option == LEFTECH_CUT || option == LEFTECH_CONTACT)) From b6cb1fb54a1935c9cb6c2c90f392a846c149b5ed Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Tue, 3 Mar 2020 17:13:37 -0500 Subject: [PATCH 115/121] Modified the LEF VIAGEN reading such that it can accomodate a different order of layers than specified in the LEF/DEF spec. It is not clear whether this is common practice, or a bug in the tool that produced the DEF file that prompted this change. NOTE: The "grow" function applied in this case should be replaced by the actual GDS input rule sequence, that includes the grow and shrink merge. Otherwise, vias read from DEF files do not match the layout from those read from GDS, even though the mask layers represented by the layouts are the same. --- ext2spice/ext2spice.c | 9 ++++++++- lef/defRead.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index b51215ce..94b2eb53 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -2873,7 +2873,14 @@ int spcnAP(node, resClass, scale, asterm, psterm, m, outf, w) if (!esDistrJunct || w == -1) goto oldFmt; - dsc = w / ((nodeClient*)node->efnode_client)->m_w.widths[resClass]; + if (((nodeClient*)node->efnode_client)->m_w.widths != NULL) + dsc = w / ((nodeClient*)node->efnode_client)->m_w.widths[resClass]; + else + { + TxError("Device missing records for source/drain area/perim.\n"); + dsc = w; + } + if (esScale < 0) { if (asterm) diff --git a/lef/defRead.c b/lef/defRead.c index 70446ab4..7091c1c9 100644 --- a/lef/defRead.c +++ b/lef/defRead.c @@ -1287,6 +1287,35 @@ DefReadVias(f, sname, oscale, total) blayer = LefReadLayer(f, FALSE); clayer = LefReadLayer(f, FALSE); tlayer = LefReadLayer(f, FALSE); + + /* Provisional behavior: A known tool generating */ + /* DEF uses the order (bottom, top, cut). This may */ + /* be a bug in the tool and an issue is being */ + /* raised. However, there is no harm in detecting */ + /* which layer is the cut and swapping as needed. */ + + if (!DBIsContact(clayer)) + { + TileType swaplayer; + LefError(DEF_WARNING, "Improper layer order for" + " VIARULE.\n"); + if (DBIsContact(tlayer)) + { + swaplayer = clayer; + clayer = tlayer; + tlayer = swaplayer; + } + else if (DBIsContact(blayer)) + { + swaplayer = clayer; + clayer = blayer; + blayer = swaplayer; + } + else + LefError(DEF_ERROR, "No cut layer specified in" + " VIARULE.\n"); + } + generated = TRUE; break; case DEF_VIAS_PROP_CUTSPACING: From 7413d89da1deef60f780a471ccf0866da3add6d7 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 5 Mar 2020 13:14:47 -0500 Subject: [PATCH 116/121] Corrected the "lef writeall" command to add the "-hide" option, as is available for "lef write". This was inadvertently omitted. --- VERSION | 2 +- commands/CmdCD.c | 2 +- drc/DRCtech.c | 3 ++- lef/lefCmd.c | 4 +++- lef/lefWrite.c | 5 +++-- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/VERSION b/VERSION index 77db8419..e3635811 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.190 +8.2.192 diff --git a/commands/CmdCD.c b/commands/CmdCD.c index 0d31dff3..dc817c6f 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -1434,7 +1434,7 @@ CmdCif(w, cmd) if (!ToolGetBox(&rootDef, &box)) { TxError("Use the box to select the area in"); - TxError(" which you want to see CIF.\n"); + TxError(" which you want to paint CIF.\n"); return; } if (argc == 5) diff --git a/drc/DRCtech.c b/drc/DRCtech.c index 48009a51..d56bdaaf 100644 --- a/drc/DRCtech.c +++ b/drc/DRCtech.c @@ -361,7 +361,8 @@ drcWhyCreate(whystring) int i; char **newList; newList = (char **)mallocMagic((DRCCurStyle->DRCWhySize + 51) * sizeof(char *)); - for (i = 0; i < DRCCurStyle->DRCWhySize; i++) + newList[0] = (char *)NULL; + for (i = 1; i <= DRCCurStyle->DRCWhySize; i++) newList[i] = DRCCurStyle->DRCWhyList[i]; if (DRCCurStyle->DRCWhySize > 0) freeMagic((char *)DRCCurStyle->DRCWhyList); diff --git a/lef/lefCmd.c b/lef/lefCmd.c index 0322467a..df80f310 100644 --- a/lef/lefCmd.c +++ b/lef/lefCmd.c @@ -190,13 +190,15 @@ CmdLef(w, cmd) lefTopCell = FALSE; else if (!strncmp(cmd->tx_argv[i], "-tech", 5)) lefTech = TRUE; + else if (!strncmp(cmd->tx_argv[i], "-hide", 5)) + lefHide = TRUE; else if (!strncmp(cmd->tx_argv[i], "-all", 4)) recurse = TRUE; else goto wrongNumArgs; } else goto wrongNumArgs; } - LefWriteAll(selectedUse, lefTopCell, lefTech, recurse); + LefWriteAll(selectedUse, lefTopCell, lefTech, lefHide, recurse); } break; case LEF_WRITE: diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 2984a2fb..b522684c 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -1133,10 +1133,11 @@ lefWriteMacro(def, f, scale, hide) */ void -LefWriteAll(rootUse, writeTopCell, lefTech, recurse) +LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, recurse) CellUse *rootUse; bool writeTopCell; bool lefTech; + bool lefHide; bool recurse; { CellDef *def, *rootdef; @@ -1190,7 +1191,7 @@ LefWriteAll(rootUse, writeTopCell, lefTech, recurse) { def->cd_client = (ClientData) 0; if (!SigInterruptPending) - lefWriteMacro(def, f, scale); + lefWriteMacro(def, f, scale, lefHide); } /* End the LEF file */ From a37fc1e242be934891b26a2ced211caebbca746d Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Thu, 5 Mar 2020 14:29:54 -0500 Subject: [PATCH 117/121] Implemented the "def read ... -labels" option, which labels each net with the name given to the net in the DEF file. Especially useful for LVS. --- lef/Depend | 6 +++--- lef/defRead.c | 35 ++++++++++++++++++++++++++++------- lef/lefCmd.c | 34 +++++++++++++++++++++++++--------- utils/main.c | 2 +- 4 files changed, 57 insertions(+), 20 deletions(-) diff --git a/lef/Depend b/lef/Depend index 9b997139..76825257 100644 --- a/lef/Depend +++ b/lef/Depend @@ -23,6 +23,6 @@ lefRead.o: lefRead.c ../tcltk/tclmagic.h ../utils/magic.h \ ../lef/lefInt.h defRead.o: defRead.c ../tcltk/tclmagic.h ../utils/magic.h \ ../utils/geometry.h ../tiles/tile.h ../utils/hash.h ../utils/undo.h \ - ../database/database.h ../windows/windows.h ../dbwind/dbwind.h \ - ../utils/malloc.h ../graphics/graphics.h ../utils/main.h ../cif/cif.h \ - ../lef/lefInt.h + ../utils/utils.h ../database/database.h ../windows/windows.h \ + ../dbwind/dbwind.h ../utils/malloc.h ../graphics/graphics.h \ + ../utils/main.h ../cif/cif.h ../lef/lefInt.h diff --git a/lef/defRead.c b/lef/defRead.c index 7091c1c9..a62a5099 100644 --- a/lef/defRead.c +++ b/lef/defRead.c @@ -26,6 +26,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "tiles/tile.h" #include "utils/hash.h" #include "utils/undo.h" +#include "utils/utils.h" #include "database/database.h" #include "windows/windows.h" #include "dbwind/dbwind.h" @@ -73,11 +74,12 @@ enum def_netspecial_shape_keys { DEF_SPECNET_SHAPE_DRCFILL}; char * -DefAddRoutes(rootDef, f, oscale, special, defLayerMap) +DefAddRoutes(rootDef, f, oscale, special, netname, defLayerMap) CellDef *rootDef; /* Cell to paint */ FILE *f; /* Input file */ float oscale; /* Scale factor between LEF and magic units */ bool special; /* True if this section is SPECIALNETS */ + char *netname; /* Name of the net, if net is to be labeled */ LefMapping *defLayerMap; /* magic-to-lef layer mapping array */ { char *token; @@ -85,6 +87,7 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) Point refp; /* reference point */ bool valid = FALSE; /* is there a valid reference point? */ bool initial = TRUE; + bool labeled = TRUE; Rect locarea; int extend, lextend, hextend; float x, y, z, w; @@ -124,6 +127,8 @@ DefAddRoutes(rootDef, f, oscale, special, defLayerMap) NULL }; + if (netname != NULL) labeled = FALSE; + while (initial || (token = LefNextToken(f, TRUE)) != NULL) { /* Get next point, token "NEW", or via name */ @@ -605,6 +610,16 @@ endCoord: /* paint */ DBPaint(rootDef, &routeTop->r_r, routeTop->r_type); + /* label */ + if (labeled == FALSE) + { + Rect r; + r.r_xbot = r.r_xtop = (routeTop->r_r.r_xbot + routeTop->r_r.r_xtop) / 2; + r.r_ybot = r.r_ytop = (routeTop->r_r.r_ybot + routeTop->r_r.r_ytop) / 2; + DBPutLabel(rootDef, &r, GEO_CENTER, netname, routeTop->r_type, 0); + labeled = TRUE; + } + /* advance to next point and free record (1-delayed) */ freeMagic((char *)routeTop); routeTop = routeTop->r_next; @@ -636,15 +651,17 @@ enum def_netprop_keys { DEF_NETPROP_PROPERTY}; void -DefReadNets(f, rootDef, sname, oscale, special, total) +DefReadNets(f, rootDef, sname, oscale, special, dolabels, total) FILE *f; CellDef *rootDef; char *sname; float oscale; bool special; /* True if this section is SPECIALNETS */ + bool dolabels; /* If true, create a label for each net */ int total; { char *token; + char *netname = NULL; int keyword, subkey; int processed = 0; LefMapping *defLayerMap; @@ -684,8 +701,8 @@ DefReadNets(f, rootDef, sname, oscale, special, total) case DEF_NET_START: /* Get net name */ - /* Presently, we ignore net names completely. */ token = LefNextToken(f, TRUE); + if (dolabels) netname = StrDup((char **)NULL, token); /* Update the record of the number of nets processed */ /* and spit out a message for every 5% finished. */ @@ -725,10 +742,11 @@ DefReadNets(f, rootDef, sname, oscale, special, total) case DEF_NETPROP_FIXED: case DEF_NETPROP_COVER: token = DefAddRoutes(rootDef, f, oscale, special, - defLayerMap); + netname, defLayerMap); break; } } + if (dolabels) freeMagic(netname); break; case DEF_NET_END: @@ -1648,8 +1666,9 @@ enum def_sections {DEF_VERSION = 0, DEF_NAMESCASESENSITIVE, DEF_END}; void -DefRead(inName) +DefRead(inName, dolabels) char *inName; + bool dolabels; { CellDef *rootDef; FILE *f; @@ -1825,13 +1844,15 @@ DefRead(inName) token = LefNextToken(f, TRUE); if (sscanf(token, "%d", &total) != 1) total = 0; LefEndStatement(f); - DefReadNets(f, rootDef, sections[DEF_SPECIALNETS], oscale, TRUE, total); + DefReadNets(f, rootDef, sections[DEF_SPECIALNETS], oscale, TRUE, + dolabels, total); break; case DEF_NETS: token = LefNextToken(f, TRUE); if (sscanf(token, "%d", &total) != 1) total = 0; LefEndStatement(f); - DefReadNets(f, rootDef, sections[DEF_NETS], oscale, FALSE, total); + DefReadNets(f, rootDef, sections[DEF_NETS], oscale, FALSE, + dolabels, total); break; case DEF_IOTIMINGS: LefSkipSection(f, sections[DEF_IOTIMINGS]); diff --git a/lef/lefCmd.c b/lef/lefCmd.c index df80f310..b5ba0b12 100644 --- a/lef/lefCmd.c +++ b/lef/lefCmd.c @@ -92,6 +92,10 @@ CmdLef(w, cmd) * 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[] = { @@ -101,7 +105,8 @@ CmdLef(w, cmd) " write [filename] -hide hide all details other than ports", "writeall write all cells including the top-level cell\n" " writeall -notop write all children of the top-level cell\n" - " writeall -all recurse on all subcells of the top-level cell", + " writeall -all recurse on all subcells of the top-level cell\n", + " writeall -hide hide all details other than ports", "help print this help information", NULL }; @@ -109,7 +114,8 @@ CmdLef(w, cmd) static char *cmdDefOption[] = { "read [filename] read a DEF file filename[.def]", - "write [cell] [-allspecial] write DEF for current or indicated cell", + "write [cell] [-allspecial] write DEF for current or indicated cell\n", + "write -labels label every net in NETS with the net name", "writeall (use \"flatten -nosubckt\" + \"def" " write\" instead)", "help print this help information", @@ -157,22 +163,32 @@ CmdLef(w, cmd) switch (option) { case LEF_READ: - if (cmd->tx_argc != 3) + if (cmd->tx_argc > 3) { - if (cmd->tx_argc == 4) + for (i = 3; i < cmd->tx_argc; i++) { - if (*(cmd->tx_argv[3]) == '-') - if (!strncmp(cmd->tx_argv[3], "-import", 7)) + if (*(cmd->tx_argv[i]) == '-') + { + if (!strncmp(cmd->tx_argv[i], "-import", 7)) lefImport = TRUE; + else if (!strncmp(cmd->tx_argv[i], "-label", 6)) + { + if (is_lef) + TxPrintf("The \"-labels\" option is only for def read\n"); + else + defLabelNets = TRUE; + } + } } - else - goto wrongNumArgs; } + else if (cmd->tx_argc < 3) + goto wrongNumArgs; + namep = cmd->tx_argv[2]; if (is_lef) LefRead(namep, lefImport); else - DefRead(namep); + DefRead(namep, defLabelNets); break; case LEF_WRITEALL: if (!is_lef) diff --git a/utils/main.c b/utils/main.c index 73eea16a..708f0354 100644 --- a/utils/main.c +++ b/utils/main.c @@ -1156,7 +1156,7 @@ mainInitFinal() LefRead(temporary->fn, FALSE); break; case FN_DEF_FILE: - DefRead(temporary->fn); + DefRead(temporary->fn, FALSE); break; #endif #ifdef MAGIC_WRAPPER From 86cad629eca03f0c66cb49d7499e801b63113eb9 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 6 Mar 2020 09:15:22 -0500 Subject: [PATCH 118/121] Modified the LEF read routine to use the via geometry manipulations from the cifoutput section, NOT the cifinput section. This change underscores the point that LEF and DEF formats define mask data, and therefore all LEF and DEF routines should be using the CIF input/output methods and layers. That is a major code change; meanwhile, getting via layer values from the cifoutput parameters is slightly more reliable than using cifinput, since there is good reason to use templayers to read vias, and that sort of indirection makes it difficult to determine a simple relationship between a LEF cut layer and a magic contact. --- lef/lefRead.c | 48 +++++++++++++++--------------------------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/lef/lefRead.c b/lef/lefRead.c index 2a8e8ab4..cbe484ec 100644 --- a/lef/lefRead.c +++ b/lef/lefRead.c @@ -1770,10 +1770,18 @@ origin_error: * * For LEF contact types matching magic contact types, size the * LEF contact cut to cover the minimum rectangle in the other - * layers that satisfies the CIF/GDS contact generation. Use - * the "cifinput" style to determine how much the via layer - * needs to grow to make a contact area. If the "cifinput" - * style is not defined, then determine rules from "cifoutput". + * layers that satisfies the CIF/GDS contact generation. + * + * NOTE: If a "cifinput" style is defined, then the via + * remains the size declared in LEF or DEF file, and the + * magic view of the via is generated by applying "cifinput" + * rules when painting into the magic database. If no input + * style is defined, then the output style rules are used to + * modify the cut size to match the way the via is defined in + * magic, and the result is painted directly. + * + * If a "cifinput" style exists, then this routine does + * nothing and has no side effects. * *------------------------------------------------------------ */ @@ -1783,36 +1791,10 @@ void LefGrowVia(curlayer, currect, lefl) Rect *currect; lefLayer *lefl; { - if (DBIsContact(curlayer) && cifCurReadStyle != NULL) - { - int growSize; + /* To be completed: This should be deprecated by moving the entire */ + /* LEF and DEF read routines to use the cifinput style. */ - /* Get the amount (in magic units) that the layer needs to */ - /* expand according to the "cifinput" style rules to convert */ - /* a contact cut to a magic contact layer. */ - - growSize = CIFReadGetGrowSize(curlayer); - - /* All internal LEF via geometry values are doubled */ - growSize <<= 1; - - if (growSize % cifCurReadStyle->crs_scaleFactor == 0) - growSize /= cifCurReadStyle->crs_scaleFactor; - else - growSize = growSize / cifCurReadStyle->crs_scaleFactor + 1; - - if (growSize > 0) - { - /* cifinput styles expect the cut size to be correct, so */ - /* there is no check for correctness of the layer. */ - - currect->r_xbot = currect->r_xbot - growSize; - currect->r_ybot = currect->r_ybot - growSize; - currect->r_xtop = currect->r_xtop + growSize; - currect->r_ytop = currect->r_ytop + growSize; - } - } - else if (DBIsContact(curlayer) && CIFCurStyle != NULL) + if (DBIsContact(curlayer) && CIFCurStyle != NULL) { int edgeSize = 0, contSize, halfSize; From 5a7eb37d6e559ff19481132ad29ca3873d98a175 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 6 Mar 2020 09:19:50 -0500 Subject: [PATCH 119/121] Updated VERSION along with the LEF/DEF input correction. --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index e3635811..8c913ded 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.192 +8.2.193 From 12833170848452bf0410ac8eb967c66683107772 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Fri, 6 Mar 2020 13:46:40 -0500 Subject: [PATCH 120/121] Corrected the improper use of the variable DRCErrorTable twice, which results in conflicting hash tables and a crash, if a DRC section is reloaded when doing an error count. --- drc/DRCtech.c | 13 +++++++------ drc/drc.h | 1 - 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drc/DRCtech.c b/drc/DRCtech.c index d56bdaaf..19a906dc 100644 --- a/drc/DRCtech.c +++ b/drc/DRCtech.c @@ -40,6 +40,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ CIFStyle *drcCifStyle = NULL; bool DRCForceReload = FALSE; +HashTable DRCWhyErrorTable; /* Table of DRC errors */ /* * DRC interaction radius being used (not necessarily the same as @@ -339,7 +340,7 @@ drcTechNewStyle() * 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 DRCErrorTable is used to determine if a + * Temporary hash table DRCWhyErrorTable is used to determine if a * string entry is unique. It is cleared after the technology file * has been processed. * ---------------------------------------------------------------------------- @@ -351,7 +352,7 @@ drcWhyCreate(whystring) { HashEntry *he; - he = HashLookOnly(&DRCErrorTable, whystring); + he = HashLookOnly(&DRCWhyErrorTable, whystring); if (he != NULL) return (int)((pointertype)HashGetValue(he)); @@ -370,7 +371,7 @@ drcWhyCreate(whystring) } DRCCurStyle->DRCWhySize++; - he = HashFind(&DRCErrorTable, whystring); + he = HashFind(&DRCWhyErrorTable, whystring); HashSetValue(he, (char *)((pointertype)DRCCurStyle->DRCWhySize)); DRCCurStyle->DRCWhyList[DRCCurStyle->DRCWhySize] = StrDup((char **)NULL, whystring); @@ -564,7 +565,7 @@ DRCTechStyleInit() DRCCurStyle->DRCFlags = (char)0; DRCCurStyle->DRCWhySize = 0; - HashInit(&DRCErrorTable, 16, HT_STRINGKEYS); + 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 */ @@ -3505,8 +3506,8 @@ drcTechFinalStyle(style) DRCCookie **dpp, **dp2back; TileType i, j; - /* Done with DRCErrorTable */ - HashKill(&DRCErrorTable); + /* Done with DRCWhyErrorTable */ + HashKill(&DRCWhyErrorTable); /* If the scale factor is not 1, then divide all distances by */ /* the scale factor, take the ceiling, and save the (negative) */ diff --git a/drc/drc.h b/drc/drc.h index 69f6ff35..aa3c5def 100644 --- a/drc/drc.h +++ b/drc/drc.h @@ -219,7 +219,6 @@ extern DRCKeep *DRCStyleList; /* List of available DRC styles */ extern DRCStyle *DRCCurStyle; /* Current DRC style in effect */ extern CellDef *DRCdef; /* Current cell being checked for DRC */ extern CellUse *DRCuse, *DRCDummyUse; -extern HashTable DRCErrorTable; /* DRC errors, hashed by name */ /* * Internal procedures From aa738bb350016221fa7e3c07c001bacb080f27eb Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Mon, 9 Mar 2020 20:44:03 -0400 Subject: [PATCH 121/121] Corrected an obscure error in GDS generation caused by an uninitialized variable, with the result that writing GDS would claim that it cannot scale down enough and that the output units are either wrong or the output style must have "units angstroms". Using angstrom units would solve the problem but did not treat the root of the problem. --- VERSION | 2 +- cif/CIFtech.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index 8c913ded..3bce592d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.2.193 +8.2.194 diff --git a/cif/CIFtech.c b/cif/CIFtech.c index 9f2f457b..441b3c32 100644 --- a/cif/CIFtech.c +++ b/cif/CIFtech.c @@ -2117,7 +2117,7 @@ CIFTechOutputScale(n, d) SquaresData *squares; SlotsData *slots; BloatData *bloats; - bool has_odd_space; + bool has_odd_space = FALSE; if (ostyle == NULL) return;