diff --git a/.gitignore b/.gitignore index 04cd59d6..beef7e8d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,18 @@ scripts/defs.mak *.so *~ scmos/cif_template/objs/* -UPDATE_ME -VERSION +database/database.h +install.log +magic/proto.magicrc +make.log +readline/readline +scmos/gdsquery.tech +scmos/minimum.tech +scmos/scmos-sub.tech +scmos/scmos-tm.tech +scmos/scmos.tech +scmos/scmosWR.tech +tcltk/magic.sh +tcltk/magic.tcl +tcltk/magicdnull +tcltk/magicexec 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 diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..015556c5 --- /dev/null +++ b/LICENSE @@ -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. diff --git a/Makefile b/Makefile index afaed0d1..da70dad7 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ MODULES = bplane cmwind commands database dbwind debug drc extflat \ MAKEFLAGS = INSTALL_CAD_DIRS = windows doc ${TECH} -include defs.mak +-include defs.mak all: $(ALL_TARGET) @@ -66,8 +66,8 @@ depend: database/database.h install: $(INSTALL_TARGET) install-magic: - @echo --- installing executable to $(DESTDIR)${BINDIR} - @echo --- installing runtime files to $(DESTDIR)${LIBDIR} + @echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR} + @echo --- installing runtime files to $(DESTDIR)${INSTALL_LIBDIR} @${MAKE} install-real 2>&1 >> install.log install-real: install-dirs @@ -77,16 +77,18 @@ install-real: install-dirs (cd $$dir && ${MAKE} install); done install-tcl-dirs: - ${MAGICDIR}/scripts/mkdirs $(DESTDIR)${BINDIR} $(DESTDIR)${MANDIR} \ - $(DESTDIR)${SYSDIR} $(DESTDIR)${TCLDIR} $(DESTDIR)${TCLDIR}/bitmaps + ${MAGICDIR}/scripts/mkdirs $(DESTDIR)${INSTALL_BINDIR} \ + $(DESTDIR)${INSTALL_MANDIR} $(DESTDIR)${INSTALL_SYSDIR} \ + $(DESTDIR)${INSTALL_TCLDIR} $(DESTDIR)${INSTALL_TCLDIR}/bitmaps install-dirs: - ${MAGICDIR}/scripts/mkdirs $(DESTDIR)${BINDIR} $(DESTDIR)${MANDIR} \ - $(DESTDIR)${SYSDIR} $(DESTDIR)${SCMDIR} + ${MAGICDIR}/scripts/mkdirs $(DESTDIR)${INSTALL_BINDIR} \ + $(DESTDIR)${INSTALL_MANDIR} $(DESTDIR)${INSTALL_SYSDIR} \ + $(DESTDIR)${INSTALL_SCMDIR} install-tcl: - @echo --- installing executable to $(DESTDIR)${BINDIR} - @echo --- installing runtime files to $(DESTDIR)${LIBDIR} + @echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR} + @echo --- installing runtime files to $(DESTDIR)${INSTALL_LIBDIR} @${MAKE} install-tcl-real 2>&1 >> install.log install-tcl-real: install-tcl-dirs 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 a2f28f43..2bf50aaf 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.4.0 +8.3.0 diff --git a/calma/CalmaRdcl.c b/calma/CalmaRdcl.c index 28acae08..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); @@ -405,17 +411,18 @@ calmaParseStructure(filename) */ if (CalmaFlattenUses && (!was_called) && (npaths < 10) && (nsrefs == 0)) { - /* To-do: If CDFLATGDS is already set, need to remove */ + /* If CDFLATGDS is already set, may need to remove */ /* existing planes and free memory. */ - if (cifReadCellDef->cd_flags & CDFLATGDS) + if ((cifReadCellDef->cd_client != (ClientData)CLIENTDEFAULT) && + (cifReadCellDef->cd_flags & CDFLATGDS)) { Plane **cifplanes = (Plane **)cifReadCellDef->cd_client; int pNum; for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) { - if (cifplanes[pNum] != NULL) + if (cifplanes[pNum] != NULL) { DBFreePaintPlane(cifplanes[pNum]); TiFreePlane(cifplanes[pNum]); @@ -903,7 +910,8 @@ calmaElementSref(filename) for (pNum = 0; pNum < MAXCIFRLAYERS; pNum++) { - if (gdsplanes[pNum] != NULL) + if ((def->cd_client != (ClientData)CLIENTDEFAULT) && + (gdsplanes[pNum] != NULL)) { gdsCopyRec.plane = cifCurReadPlanes[pNum]; if (isArray) 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)) 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 82b1929f..a628730f 100644 --- a/calma/CalmaWrite.c +++ b/calma/CalmaWrite.c @@ -372,10 +372,10 @@ calmaDumpStructure(def, outf, calmaDefHash, filename) char *filename; { int nbytes, rtype; - char *strname = NULL, *newnameptr, newname[CALMANAMELENGTH*2]; + char *strname = NULL, *newnameptr; HashEntry *he, *he2; CellDef *edef; - char *prefix; + char *prefix = NULL; /* Make sure this is a structure; if not, let the caller know we're done */ PEEKRH(nbytes, rtype); @@ -397,23 +397,35 @@ calmaDumpStructure(def, outf, calmaDefHash, filename) calmaOutDate(def->cd_timestamp, outf); calmaOutDate(time((time_t *) 0), outf); + /* Find the structure's unique prefix, in case structure calls subcells */ + /* that are not yet defined. */ + + he2 = HashFind(&calmaLibHash, filename); + if (he2 == NULL) + TxError("Fatal error: Library %s not recorded!\n", filename); + else + prefix = (char *)HashGetValue(he2); + /* Prefix structure name with def name, and output new structure name */ he = HashFind(calmaDefHash, strname); if ((newnameptr = (char *)HashGetValue(he)) != NULL) { /* Structure is defined more than once */ - TxError("Structure %s defined redundantly in GDS\n", strname); + if (*newnameptr != '0') + TxError("Structure %s defined redundantly in GDS\n", strname); + else + *newnameptr = '1'; /* To be considered: Should the structure be output more than once? */ - calmaOutStringRecord(CALMA_STRNAME, newnameptr, outf); + calmaOutStringRecord(CALMA_STRNAME, newnameptr + 1, outf); } else if (!strcmp(strname, def->cd_name)) { /* This is the top level cell being defined. Its name */ /* does not get modified. */ - newnameptr = mallocMagic(strlen(strname) + 1); - sprintf(newnameptr, "%s", strname); - calmaOutStringRecord(CALMA_STRNAME, newnameptr, outf); + newnameptr = mallocMagic(strlen(strname) + 2); + sprintf(newnameptr, "1%s", strname); + calmaOutStringRecord(CALMA_STRNAME, newnameptr + 1, outf); HashSetValue(he, (char *)newnameptr); } else @@ -444,26 +456,20 @@ calmaDumpStructure(def, outf, calmaDefHash, filename) /* Same library, so keep the cellname and mark the cell */ /* as having been written to GDS. */ - newnameptr = mallocMagic(strlen(strname) + 1); - sprintf(newnameptr, "%s", strname); + newnameptr = mallocMagic(strlen(strname) + 2); + sprintf(newnameptr, "1%s", strname); HashSetValue(he, (char *)newnameptr); } else { /* Find the unique library prefix and prepend it to the cell name */ - he2 = HashFind(&calmaLibHash, filename); - if (he2 == NULL) - { - /* Should never happen */ - TxError("Fatal error: Library %s not recorded!\n", filename); - newnameptr = strname; - } + if (prefix == NULL) + newnameptr = strname; /* Should never happen */ else { - prefix = (char *)HashGetValue(he2); - newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 8); - sprintf(newnameptr, "%s_%s", prefix, strname); + newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 9); + sprintf(newnameptr, "1%s_%s", prefix, strname); HashSetValue(he, (char *)newnameptr); } } @@ -472,22 +478,16 @@ calmaDumpStructure(def, outf, calmaDefHash, filename) { /* Find the unique library prefix and prepend it to the cell name */ - he2 = HashFind(&calmaLibHash, filename); - if (he2 == NULL) - { - /* Should never happen */ - TxError("Fatal error: Library %s not recorded!\n", filename); - newnameptr = strname; - } + if (prefix == NULL) + newnameptr = strname; /* Should never happen */ else { - prefix = (char *)HashGetValue(he2); - newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 8); - sprintf(newnameptr, "%s_%s", prefix, strname); + newnameptr = mallocMagic(strlen(strname) + strlen(prefix) + 9); + sprintf(newnameptr, "1%s_%s", prefix, strname); HashSetValue(he, (char *)newnameptr); } } - calmaOutStringRecord(CALMA_STRNAME, newnameptr, outf); + calmaOutStringRecord(CALMA_STRNAME, newnameptr + 1, outf); } freeMagic(strname); @@ -525,7 +525,7 @@ calmaDumpStructure(def, outf, calmaDefHash, filename) newnameptr = (char *)HashGetValue(he); if (newnameptr != NULL) { - calmaOutStringRecord(CALMA_SNAME, newnameptr, outf); + calmaOutStringRecord(CALMA_SNAME, newnameptr + 1, outf); } else { @@ -535,14 +535,14 @@ calmaDumpStructure(def, outf, calmaDefHash, filename) /* the same way used for structure definitions. */ newnameptr = (char *)mallocMagic(strlen(strname) + - strlen(prefix) + 8); - sprintf(newnameptr, "%s_%s", prefix, strname); + strlen(prefix) + 9); + sprintf(newnameptr, "0%s_%s", prefix, strname); - edef = DBCellLookDef(newnameptr); + edef = DBCellLookDef(newnameptr + 1); if (edef != NULL) - sprintf(newnameptr, "%s_%s[[0]]", prefix, strname); + sprintf(newnameptr, "0%s_%s[[0]]", prefix, strname); HashSetValue(he, (char *)newnameptr); - calmaOutStringRecord(CALMA_SNAME, newnameptr, outf); + calmaOutStringRecord(CALMA_SNAME, newnameptr + 1, outf); } break; @@ -746,8 +746,11 @@ calmaProcessDef(def, outf) /* Read the cell in if it is not already available. */ if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return (0); + } /* * Output the definitions for any of our descendants that have @@ -1024,7 +1027,7 @@ calmaOutFunc(def, f, cliprect) ((lab->lab_flags & PORT_NUM_MASK) == i)) { calmaWriteLabelFunc(lab, type, f); - break; + /* break; */ /* Do not limit to unique labels! */ } } } @@ -1316,7 +1319,7 @@ calmaOutStructName(type, def, f) CellDef *def; FILE *f; { - char defname[CALMANAMELENGTH+1]; + char *defname; unsigned char c; char *cp; int calmanum; @@ -1341,10 +1344,11 @@ calmaOutStructName(type, def, f) } /* We really should ensure that the new name is unique. . . */ } - if (cp <= def->cd_name + CALMANAMELENGTH) + if ((!(CIFCurStyle->cs_flags & CWF_STRING_LIMIT)) || + (cp <= def->cd_name + CALMANAMELENGTH)) { /* Yes, it's legal: use it */ - (void) strcpy(defname, def->cd_name); + defname = StrDup(NULL, def->cd_name); } else { @@ -1352,12 +1356,14 @@ calmaOutStructName(type, def, f) bad: calmanum = (int) def->cd_client; if (calmanum < 0) calmanum = -calmanum; + defname = (char *)mallocMagic(32); (void) sprintf(defname, "XXXXX%d", calmanum); TxError("Warning: string in output unprintable; changed to \'%s\'\n", defname); } calmaOutStringRecord(type, defname, f); + freeMagic(defname); } /* Added by NP 8/21/2004 */ @@ -2734,7 +2740,7 @@ calmaOutDate(t, f) void calmaOutStringRecord(type, str, f) int type; /* Type of this record (data type is ASCII string) */ - char *str; /* String to be output (<= CALMANAMELENGTH chars) */ + char *str; /* String to be output */ FILE *f; /* Stream file */ { int len; @@ -2759,9 +2765,16 @@ calmaOutStringRecord(type, str, f) * last CALMANAMELENGTH characters (since cell names are more * likely to be unique in the last characters than in the first * characters). + * + * NOTE: GDS format has not used CALMANAMELENGTH restrictions + * for ages. Since this is a 2-byte record, then is it not + * worth checking the 65536 - 4 character limit. The CALMANAMELENGTH + * restriction must be enabled in the cifoutput flags. */ + + if (len & 01) len++; - if (len > CALMANAMELENGTH) + if ((CIFCurStyle->cs_flags & CWF_STRING_LIMIT) && (len > CALMANAMELENGTH)) { TxError("Warning: Cellname %s truncated ", str); TxError("to %s (GDS format limit)\n", str + len - CALMANAMELENGTH); diff --git a/cif/CIFgen.c b/cif/CIFgen.c index d063a087..65822fd3 100644 --- a/cif/CIFgen.c +++ b/cif/CIFgen.c @@ -111,6 +111,177 @@ cifPaintFunc(tile, table) return 0; } +/* + * ---------------------------------------------------------------------------- + * + * cifGrowMinFunc -- + * + * Called for each relevant tile during grow-min operations. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * May paint into cifNewPlane + * + * Algorithm (based on maximum horizontal stripes rule): + * Scan top and bottom boundaries from left to right. For any + * distance (including distance zero) sharing the same type (0 or 1) + * on both the tile top and bottom, find the diagonal length. If + * less than co_distance, then expand this area and paint. + * NOTE: This algorithm does not cover a number of geometry cases + * and needs to be reworked. It should be restricted to cases of + * layers that have "rect_only" DRC rules. Since the rule is usually + * needed for implants on FET gates to maintain the implant width for + * small gates, the "rect_only" requirement is not particularly + * constraining. + * + * ---------------------------------------------------------------------------- + */ + +int +cifGrowMinFunc(tile, table) + Tile *tile; + PaintResultType *table; /* Table to be used for painting. */ +{ + Rect area, parea; + int locDist, width, height, h; + TileType type, tptype; + Tile *tp, *tp2; + + TiToRect(tile, &area); + + area.r_xbot *= cifScale; + area.r_xtop *= cifScale; + area.r_ybot *= cifScale; + area.r_ytop *= cifScale; + + parea = area; + + /* Check whole tile for minimum width */ + width = area.r_xtop - area.r_xbot; + if (width < growDistance) + { + locDist = (growDistance - width) / 2; + area.r_xbot -= locDist; + area.r_xtop += locDist; + + /* If there is another tile on top or bottom, and the height is */ + /* less than minimum, then extend height in the direction of */ + /* the bordering tile. Otherwise, if the height is less than */ + /* minimum, then grow halfway in both directions. */ + + height = area.r_ytop - area.r_ybot; + if (height < growDistance) + { + bool freeTop, freeBot; + + freeTop = freeBot = TRUE; + + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + if (TiGetTopType(tp) == TiGetBottomType(tile)) + { + freeBot = FALSE; + break; + } + + for (tp2 = RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2)) + if (TiGetBottomType(tp2) == TiGetTopType(tile)) + { + freeTop = FALSE; + break; + } + + /* In the following, value h ensures that the euclidean */ + /* distance between inside corners of the layer */ + /* satisfies growDistance. */ + + if (freeTop == TRUE && freeBot == FALSE) + { + locDist = (growDistance - height) / 2; + h = (int)sqrt((double)(growDistance * growDistance) - + 0.25 * (double)((growDistance + width) * + (growDistance + width)) + 0.5); + area.r_ybot -= h; + } + else if (freeTop == FALSE && freeBot == TRUE) + { + h = (int)sqrt((double)(growDistance * growDistance) - + 0.25 * (double)((growDistance + width) * + (growDistance + width)) + 0.5); + area.r_ytop += h; + } + else { + locDist = (growDistance - height) / 2; + area.r_ybot -= locDist; + area.r_ytop += locDist; + } + } + } + DBPaintPlane(cifPlane, &area, table, (PaintUndoInfo *) NULL); + + area = parea; + + /* Scan bottom from left to right */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + { + tptype = TiGetTopType(tp); + /* Scan top from right to left across range of tp */ + for (tp2 = RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2)) + if (TiGetBottomType(tp2) == tptype) + { + /* Set range to length of overlap */ + if ((LEFT(tp2) <= RIGHT(tp)) && (LEFT(tp2) >= LEFT(tp))) + { + area.r_xbot = LEFT(tp2) < LEFT(tile) ? LEFT(tile) : LEFT(tp2); + area.r_xtop = RIGHT(tp) > RIGHT(tile) ? RIGHT(tile) : RIGHT(tp); + } + else if ((RIGHT(tp2) >= LEFT(tp)) && (RIGHT(tp2) <= RIGHT(tp))) + { + area.r_xbot = LEFT(tp) < LEFT(tile) ? LEFT(tile) : LEFT(tp); + area.r_xtop = RIGHT(tp2) > RIGHT(tile) ? RIGHT(tile) : RIGHT(tp2); + } + else continue; + + area.r_xbot *= cifScale; + area.r_xtop *= cifScale; + + /* Does area violate minimum width requirement? */ + width = area.r_xtop - area.r_xbot; + height = area.r_ytop - area.r_ybot; + + /* Manhattan requirement (to-do: Euclidean) */ + if (width < growDistance) + { + locDist = (growDistance - width) / 2; + parea.r_xbot = area.r_xbot - locDist; + parea.r_xtop = area.r_xtop + locDist; + } + else + { + parea.r_xbot = area.r_xbot; + parea.r_xtop = area.r_xtop; + } + if (height < growDistance) + { + locDist = (growDistance - height) / 2; + parea.r_ybot = area.r_ybot - locDist; + parea.r_ytop = area.r_ytop + locDist; + } + else + { + parea.r_ybot = area.r_ybot; + parea.r_ytop = area.r_ytop; + } + if ((width < growDistance) || (height < growDistance)) + DBPaintPlane(cifPlane, &parea, table, (PaintUndoInfo *) NULL); + } + } + + CIFTileOps += 1; + return 0; +} + /* * ---------------------------------------------------------------------------- * @@ -514,7 +685,7 @@ cifGrowFunc(tile, table) CIFTileOps += 1; return 0; } - + /* * ---------------------------------------------------------------------------- * @@ -842,6 +1013,46 @@ endbloat: return 0; } +#define CIF_PENDING 0 +#define CIF_UNPROCESSED CLIENTDEFAULT +#define CIF_PROCESSED 1 +#define CIF_IGNORE 2 + +#define PUSHTILE(tp, stack) \ + if ((tp)->ti_client == (ClientData) CIF_UNPROCESSED) { \ + (tp)->ti_client = (ClientData) CIF_PENDING; \ + STACKPUSH((ClientData) (tp), stack); \ + } + +/* + *------------------------------------------------------- + * + * cifFoundFunc -- + * + * Find the first tile in the given area. + * + * Results: + * Return 1 to stop the search and process. + * Set clientData to the tile found. + * + *------------------------------------------------------- + */ + +int +cifFoundFunc(tile, BloatStackPtr) + Tile *tile; + Stack **BloatStackPtr; +{ + PUSHTILE(tile, *BloatStackPtr); + return 0; +} + +/* Data structure for bloat-all function */ +typedef struct _bloatStruct { + CIFOp *op; + CellDef *def; +} BloatStruct; + /* * ---------------------------------------------------------------------------- * @@ -861,30 +1072,26 @@ endbloat: * ---------------------------------------------------------------------------- */ -#define CIF_PENDING 0 -#define CIF_UNPROCESSED CLIENTDEFAULT -#define CIF_PROCESSED 1 -#define CIF_IGNORE 2 - -#define PUSHTILE(tp, stack) \ - if ((tp)->ti_client == (ClientData) CIF_UNPROCESSED) { \ - (tp)->ti_client = (ClientData) CIF_PENDING; \ - STACKPUSH((ClientData) (tp), stack); \ - } - int -cifBloatAllFunc(tile, op) +cifBloatAllFunc(tile, bls) Tile *tile; /* The tile to be processed. */ - CIFOp *op; /* Describes the operation to be performed */ + BloatStruct *bls; { Rect area; TileTypeBitMask connect; Tile *t, *tp; TileType type; - BloatData *bloats = (BloatData *)op->co_client; - int i; + BloatData *bloats; + int i, locScale; + PlaneMask pmask; + CIFOp *op; + CellDef *def; static Stack *BloatStack = (Stack *)NULL; + op = bls->op; + def = bls->def; + bloats = (BloatData *)op->co_client; + /* Create a mask of all connecting types (these must be in a single * plane), then call a search function to find all connecting material * of these types. @@ -900,7 +1107,38 @@ cifBloatAllFunc(tile, op) if (BloatStack == (Stack *)NULL) BloatStack = StackNew(64); - PUSHTILE(tile, BloatStack); + /* If the type of the tile to be processed is not in the same plane */ + /* as the bloat type(s), then find any tile under the tile to be */ + /* processed that belongs to the connect mask, and use that as the */ + /* starting tile. */ + + t = tile; + type = TiGetType(tile); + if (type == CIF_SOLIDTYPE) + { + pmask = 0; + locScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1; + + /* Get the tile into magic database coordinates if it's in CIF coords */ + TiToRect(tile, &area); + area.r_xbot /= locScale; + area.r_xtop /= locScale; + area.r_ybot /= locScale; + area.r_ytop /= locScale; + } + else + { + int pNum = DBPlane(type); + pmask = CoincidentPlanes(&connect, PlaneNumToMaskBit(pNum)); + if (pmask == 0) TiToRect(tile, &area); + locScale = cifScale; + } + if (pmask == 0) + DBSrPaintArea((Tile *)NULL, def->cd_planes[bloats->bl_plane], &area, + &connect, cifFoundFunc, (ClientData)(&BloatStack)); + else + PUSHTILE(t, BloatStack); + while (!StackEmpty(BloatStack)) { t = (Tile *) STACKPOP(BloatStack); @@ -910,10 +1148,10 @@ cifBloatAllFunc(tile, op) /* Get the tile into CIF coordinates. */ TiToRect(t, &area); - area.r_xbot *= cifScale; - area.r_ybot *= cifScale; - area.r_xtop *= cifScale; - area.r_ytop *= cifScale; + area.r_xbot *= locScale; + area.r_ybot *= locScale; + area.r_xtop *= locScale; + area.r_ytop *= locScale; DBNMPaintPlane(cifPlane, TiGetTypeExact(t), &area, CIFPaintTable, (PaintUndoInfo *) NULL); @@ -982,6 +1220,134 @@ cifBloatAllFunc(tile, op) return 0; /* Keep the search alive. . . */ } +/* + * ---------------------------------------------------------------------------- + * + * cifCloseFunc -- + * + * Called for each relevant tile during close operations. + * + * Results: + * Always returns 0 to keep the search alive. + * + * Side effects: + * Paints into cifNewPlane. Tiles in old plane are tagged with + * a static value in ClientData, which does not need to be reset + * since the old plane will be free'd. + * ---------------------------------------------------------------------------- + */ + +#define CLOSE_SEARCH 0 +#define CLOSE_FILL 1 +#define CLOSE_DONE 2 + +int +cifCloseFunc(tile, plane) + Tile *tile; + Plane *plane; +{ + Rect area, newarea; + int atotal; + int cifGatherFunc(); + + /* If tile is marked, then it has been handled, so ignore it */ + if (tile->ti_client != (ClientData)CIF_UNPROCESSED) return 0; + + atotal = 0; + + /* Search all sides for connected space tiles, and accumulate the total */ + /* area. If any connected tile borders infinity, then stop searching */ + /* because the area is not enclosed. */ + + cifGatherFunc(tile, &atotal, CLOSE_SEARCH); + + /* If the total area is smaller than the rule area, then paint all the */ + /* tile areas into the destination plane. */ + + if ((atotal != INFINITY) && (atotal < growDistance)) + cifGatherFunc(tile, &atotal, CLOSE_FILL); + else + cifGatherFunc(tile, &atotal, CLOSE_DONE); + + return 0; +} + +int +cifGatherFunc(tile, atotal, mode) + Tile *tile; + int *atotal; + bool mode; +{ + Tile *tp; + TileType type; + dlong locarea; + Rect area, newarea; + ClientData cdata = (mode == CLOSE_SEARCH) ? (ClientData)CIF_UNPROCESSED : + (ClientData)CIF_PENDING; + + /* Ignore if tile has already been processed */ + if (tile->ti_client != cdata) return 0; + + TiToRect(tile, &area); + + /* Boundary tiles indicate an unclosed area, so set the area total to */ + /* INFINITY and don't try to run calculations on it. */ + + if ((area.r_xbot == TiPlaneRect.r_xbot) || (area.r_ybot == TiPlaneRect.r_ybot) || + (area.r_xtop == TiPlaneRect.r_xtop) || (area.r_ytop == TiPlaneRect.r_ytop)) + *atotal = INFINITY; + + /* Stop accumulating if already larger than growDistance to avoid the */ + /* possibility of integer overflow. */ + if (mode == CLOSE_SEARCH) + { + if ((*atotal != INFINITY) && (*atotal < growDistance)) + locarea = (dlong)(area.r_xtop - area.r_xbot) + * (dlong)(area.r_ytop - area.r_ybot); + if (locarea > (dlong)INFINITY) + *atotal = INFINITY; + else + *atotal += (int)locarea; + } + else if (mode == CLOSE_FILL) + { + DBPaintPlane(cifPlane, &area, CIFPaintTable, (PaintUndoInfo *)NULL); + CIFTileOps++; + } + + if (mode == CLOSE_SEARCH) + tile->ti_client = (ClientData)CIF_PENDING; + else + tile->ti_client = (ClientData)CIF_PROCESSED; + + /* Look for additional neighboring space tiles */ + /* Check top */ + if (area.r_ytop != TiPlaneRect.r_ytop) + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + if (tp->ti_client == cdata && TiGetType(tp) == TT_SPACE) + cifGatherFunc(tp, atotal, mode); + + /* Check bottom */ + if (area.r_ybot != TiPlaneRect.r_ybot) + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + if (tp->ti_client == cdata && TiGetType(tp) == TT_SPACE) + cifGatherFunc(tp, atotal, mode); + + /* Check left */ + if (area.r_xbot != TiPlaneRect.r_xbot) + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + if (tp->ti_client == cdata && TiGetType(tp) == TT_SPACE) + cifGatherFunc(tp, atotal, mode); + + /* Check right */ + if (area.r_xtop != TiPlaneRect.r_xtop) + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + if (tp->ti_client == cdata && TiGetType(tp) == TT_SPACE) + cifGatherFunc(tp, atotal, mode); + + return 0; +} + /*--------------------------------------------------------------*/ /* Support routines and definitions for cifSquaresFillArea */ /*--------------------------------------------------------------*/ @@ -1310,7 +1676,7 @@ cifRectBoundingBox(op, cellDef, plane) } else { - maxr = FindMaxRectangle2(&bbox, tile, plane); + maxr = FindMaxRectangle2(&bbox, tile, plane, NULL); DBPaintPlane(cifPlane, maxr, CIFPaintTable, (PaintUndoInfo *)NULL); CIFTileOps++; } @@ -1723,7 +2089,7 @@ cifSlotsFillArea(op, cellDef, plane) { Tile *tile, *t, *tp; Rect bbox, area, square, cut, llcut; - int nAcross, nUp, left, spitch, lpitch, ssize, lsize; + int nAcross, nUp, left, spitch, lpitch, ssize, lsize, offset; int diff, right; int xpitch, ypitch, xborder, yborder, xdiff, ydiff; int i, j, k, savecount; @@ -1944,16 +2310,17 @@ cifSlotsFillArea(op, cellDef, plane) cifSlotFunc(&bbox, op, &nUp, &nAcross, &llcut, vertical); - cut.r_ybot = llcut.r_ybot; - cut.r_ytop = llcut.r_ytop; + cut.r_ybot = llcut.r_ybot + slots->sl_start; + cut.r_ytop = llcut.r_ytop + slots->sl_start; /* For each contact cut area, check that there is */ /* no whitespace */ + offset = slots->sl_start; for (i = 0; i < nUp; i++) { - cut.r_xbot = llcut.r_xbot; - cut.r_xtop = llcut.r_xtop; + cut.r_xbot = llcut.r_xbot + offset; + cut.r_xtop = llcut.r_xtop + offset; square.r_ybot = cut.r_ybot - yborder; square.r_ytop = cut.r_ytop + yborder; @@ -1980,6 +2347,8 @@ cifSlotsFillArea(op, cellDef, plane) } cut.r_ybot += ypitch; cut.r_ytop += ypitch; + offset += slots->sl_offset; + if (offset >= xpitch) offset -= xpitch; } if (savecount != CIFTileOps) break; @@ -2688,6 +3057,7 @@ cifSrTiles(cifOp, area, cellDef, temps, func, cdArg) { TileTypeBitMask maskBits; TileType t; + Tile *tp; int i; BloatData *bloats; @@ -2699,7 +3069,7 @@ cifSrTiles(cifOp, area, cellDef, temps, func, cdArg) cifScale = (CIFCurStyle) ? CIFCurStyle->cs_scaleFactor : 1; - /* Bloat operations have to be in a single plane */ + /* Bloat operations (except bloat-all) have to be in a single plane */ switch (cifOp->co_opcode) { case CIFOP_BLOAT: @@ -2783,6 +3153,7 @@ CIFGenLayer(op, area, cellDef, temps, clientdata) SearchContext scx; TileType ttype; char *netname; + BloatStruct bls; int (*cifGrowFuncPtr)() = (CIFCurStyle->cs_flags & CWF_GROW_EUCLIDEAN) ? cifGrowEuclideanFunc : cifGrowFunc; @@ -2926,6 +3297,20 @@ CIFGenLayer(op, area, cellDef, temps, clientdata) nextPlane = temp; break; + /* GROWMIN grows non-uniformly to ensure minimum dimensions */ + + case CIFOP_GROWMIN: + growDistance = op->co_distance; + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifScale = 1; + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &CIFSolidBits, cifGrowMinFunc, (ClientData)CIFPaintTable); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + /* GROW_G grows non-uniformly to the indicated grid. */ case CIFOP_GROW_G: @@ -2956,6 +3341,22 @@ CIFGenLayer(op, area, cellDef, temps, clientdata) nextPlane = temp; break; + case CIFOP_CLOSE: + growDistance = op->co_distance; + DBClearPaintPlane(nextPlane); + cifPlane = nextPlane; + cifScale = 1; + /* First copy the existing paint into the target plane */ + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &CIFSolidBits, cifPaintFunc, (ClientData)CIFPaintTable); + + (void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect, + &DBSpaceBits, cifCloseFunc, (ClientData)&curPlane); + temp = curPlane; + curPlane = nextPlane; + nextPlane = temp; + break; + case CIFOP_BLOAT: cifPlane = curPlane; cifSrTiles(op, area, cellDef, temps, @@ -2971,8 +3372,10 @@ CIFGenLayer(op, area, cellDef, temps, clientdata) case CIFOP_BLOATALL: cifPlane = curPlane; + bls.op = op; + bls.def = cellDef; cifSrTiles(op, area, cellDef, temps, - cifBloatAllFunc, (ClientData) op); + cifBloatAllFunc, (ClientData)&bls); break; case CIFOP_SQUARES: 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/cif/CIFint.h b/cif/CIFint.h index 6d3ef7ba..a3a59788 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 @@ -95,6 +96,7 @@ typedef struct cifop * the masks. * CIFOP_GROW - Grow the current results uniformly by co_distance. * CIFOP_GROW_G - Grow the current results to snap to the indicated grid. + * CIFOP_GROWMIN - Grow result such that no dimension is less than co_distance. * CIFOP_SHRINK - Shrink the current results uniformly by co_distance. * CIFOP_BLOAT - Find layers in paintMask, then bloat selectively * according to bl_distance, and OR the results into @@ -130,26 +132,29 @@ typedef struct cifop * CIFOP_COPYUP - Added 5/5/16---make and keep a copy the resulting layer, * which will be painted into parent cells instead of the * current cell. This replaces the "fault" method. + * CIFOP_CLOSE - Added 11/25/19---close up areas smaller than indicated */ #define CIFOP_AND 1 #define CIFOP_OR 2 #define CIFOP_GROW 3 -#define CIFOP_GROW_G 4 -#define CIFOP_SHRINK 5 -#define CIFOP_BLOAT 6 -#define CIFOP_SQUARES 7 -#define CIFOP_SLOTS 8 -#define CIFOP_BLOATMAX 9 -#define CIFOP_BLOATMIN 10 -#define CIFOP_BLOATALL 11 -#define CIFOP_ANDNOT 12 -#define CIFOP_SQUARES_G 13 -#define CIFOP_BBOX 14 -#define CIFOP_BOUNDARY 15 -#define CIFOP_NET 16 -#define CIFOP_MAXRECT 17 -#define CIFOP_COPYUP 18 +#define CIFOP_GROWMIN 4 +#define CIFOP_GROW_G 5 +#define CIFOP_SHRINK 6 +#define CIFOP_BLOAT 7 +#define CIFOP_SQUARES 8 +#define CIFOP_SLOTS 9 +#define CIFOP_BLOATMAX 10 +#define CIFOP_BLOATMIN 11 +#define CIFOP_BLOATALL 12 +#define CIFOP_ANDNOT 13 +#define CIFOP_SQUARES_G 14 +#define CIFOP_BBOX 15 +#define CIFOP_BOUNDARY 16 +#define CIFOP_NET 17 +#define CIFOP_MAXRECT 18 +#define CIFOP_COPYUP 19 +#define CIFOP_CLOSE 20 /* Added by Tim 10/21/2004 */ /* The following structure is used to pass information on how to draw @@ -292,6 +297,7 @@ typedef struct cifstyle #define CWF_GROW_EUCLIDEAN 0x08 #define CWF_SEE_VENDOR 0x10 /* Override vendor GDS flag in cells */ #define CWF_NO_ERRORS 0x20 /* Do not generate error msgs and fdbk */ +#define CWF_STRING_LIMIT 0x40 /* Use older Calma format character limit */ /* procedures */ @@ -310,6 +316,7 @@ extern void CIFLoadStyle(); extern Plane *CIFPlanes[]; /* Normal place to store CIF. */ extern CIFKeep *CIFStyleList; /* List of all CIF styles. */ extern CIFStyle *CIFCurStyle; /* Current style being used. */ +extern CIFStyle *CIFDRCStyle; /* CIF style for DRC checking (optional) */ extern CellUse *CIFComponentUse; /* Flatten stuff in here if needed. */ extern CellDef *CIFComponentDef; /* Corresponds to CIFComponentUse. */ extern CellUse *CIFDummyUse; /* Used to dummy up a CellUse for a diff --git a/cif/CIFrdcl.c b/cif/CIFrdcl.c index 2157b15a..a35797d3 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); } } @@ -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/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/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/cif/CIFtech.c b/cif/CIFtech.c index 54bb05c6..441b3c32 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; } @@ -1023,6 +1025,8 @@ CIFTechLine(sectionName, argc, argv) newOp->co_opcode = CIFOP_OR; else if (strcmp(argv[0], "grow") == 0) newOp->co_opcode = CIFOP_GROW; + else if (strcmp(argv[0], "grow-min") == 0) + newOp->co_opcode = CIFOP_GROWMIN; else if (strcmp(argv[0], "grow-grid") == 0) newOp->co_opcode = CIFOP_GROW_G; else if (strcmp(argv[0], "shrink") == 0) @@ -1049,6 +1053,8 @@ CIFTechLine(sectionName, argc, argv) newOp->co_opcode = CIFOP_MAXRECT; else if (strcmp(argv[0], "boundary") == 0) newOp->co_opcode = CIFOP_BOUNDARY; + else if (strcmp(argv[0], "close") == 0) + newOp->co_opcode = CIFOP_CLOSE; else { TechError("Unknown statement \"%s\".\n", argv[0]); @@ -1066,8 +1072,10 @@ CIFTechLine(sectionName, argc, argv) break; case CIFOP_GROW: + case CIFOP_GROWMIN: case CIFOP_GROW_G: case CIFOP_SHRINK: + case CIFOP_CLOSE: if (argc != 2) goto wrongNumArgs; newOp->co_distance = atoi(argv[1]); if (newOp->co_distance <= 0) @@ -1080,14 +1088,18 @@ CIFTechLine(sectionName, argc, argv) case CIFOP_BLOATALL: if (argc != 3) goto wrongNumArgs; cifParseLayers(argv[1], CIFCurStyle, &newOp->co_paintMask, - (TileTypeBitMask *)NULL, FALSE); - bloatLayers = newOp->co_paintMask; + &newOp->co_cifMask, FALSE); bloats = (BloatData *)mallocMagic(sizeof(BloatData)); for (i = 0; i < TT_MAXTYPES; i++) bloats->bl_distance[i] = 0; newOp->co_client = (ClientData)bloats; - cifParseLayers(argv[2], CIFCurStyle, &mask, &tempMask, TRUE); + + /* 10/15/2019: Lifting restriction that the types that */ + /* trigger the bloating must be in the same plane as the */ + /* types that are bloated into. */ + + TTMaskZero(&bloatLayers); TTMaskSetMask(&bloatLayers, &mask); if (!TTMaskEqual(&tempMask, &DBZeroTypeBits)) TechError("Can't use templayers in bloat statement.\n"); @@ -1323,6 +1335,7 @@ bloatCheck: slots->sl_lsize = 0; slots->sl_lsep = 0; slots->sl_offset = 0; + slots->sl_start = 0; } if (argc >= 5) { @@ -1357,7 +1370,7 @@ bloatCheck: goto errorReturn; } } - if (argc == 8) + if (argc >= 8) { i = atoi(argv[7]); slots->sl_offset = i; @@ -1367,7 +1380,17 @@ bloatCheck: goto errorReturn; } } - if ((argc < 4) || (argc == 6) || (argc > 8)) + if (argc == 9) + { + i = atoi(argv[8]); + slots->sl_start = i; + if (i < 0) + { + TechError("Slot start must be non-negative.\n"); + goto errorReturn; + } + } + if ((argc < 4) || (argc == 6) || (argc > 9)) goto wrongNumArgs; break; } @@ -1481,6 +1504,7 @@ cifComputeRadii(layer, des) case CIFOP_OR: break; case CIFOP_GROW: + case CIFOP_GROWMIN: case CIFOP_GROW_G: grow += op->co_distance; break; @@ -1681,7 +1705,7 @@ CIFTechFinal() { slots = (SlotsData *)op->co_client; - for (j = 0; j < 7; j++) + for (j = 0; j < 8; j++) { switch (j) { case 0: bvalue = slots->sl_sborder; break; @@ -1691,6 +1715,7 @@ CIFTechFinal() case 4: bvalue = slots->sl_lsize; break; case 5: bvalue = slots->sl_lsep; break; case 6: bvalue = slots->sl_offset; break; + case 7: bvalue = slots->sl_start; break; } if (bvalue != 0) { @@ -1945,7 +1970,7 @@ CIFLoadStyle(stylename) { SectionID invcif; - if (CIFCurStyle->cs_name == stylename) return; + if (CIFCurStyle && (CIFCurStyle->cs_name == stylename)) return; cifTechNewStyle(); CIFCurStyle->cs_name = stylename; @@ -2092,7 +2117,7 @@ CIFTechOutputScale(n, d) SquaresData *squares; SlotsData *slots; BloatData *bloats; - bool has_odd_space; + bool has_odd_space = FALSE; if (ostyle == NULL) return; @@ -2189,7 +2214,7 @@ CIFTechOutputScale(n, d) else if (op->co_opcode == CIFOP_SLOTS) { slots = (SlotsData *)op->co_client; - for (j = 0; j < 7; j++) + for (j = 0; j < 8; j++) { switch (j) { case 0: bptr = &slots->sl_sborder; break; @@ -2199,6 +2224,7 @@ CIFTechOutputScale(n, d) case 4: bptr = &slots->sl_lsize; break; case 5: bptr = &slots->sl_lsep; break; case 6: bptr = &slots->sl_offset; break; + case 7: bptr = &slots->sl_start; break; } if (*bptr != 0) { @@ -2315,6 +2341,8 @@ CIFTechOutputScale(n, d) slots->sl_lsep /= lexpand; if (slots->sl_offset != 0) slots->sl_offset /= lexpand; + if (slots->sl_start != 0) + slots->sl_start /= lexpand; break; case CIFOP_SQUARES_G: squares = (SquaresData *)op->co_client; diff --git a/cif/CIFwrite.c b/cif/CIFwrite.c index 59ff26a5..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, 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 f83a3d5c..bec96c57 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) @@ -3079,7 +3079,7 @@ CmdDown(w, cmd) GeoTransRect(&EditToRootTransform, &(EditCellUse->cu_def->cd_bbox), &area); (void) WindSearch(DBWclientID, (ClientData) NULL, (Rect *) NULL, cmdEditRedisplayFunc, (ClientData) &area); - DBWloadWindow(w, EditCellUse->cu_def->cd_name, TRUE, FALSE); + DBWloadWindow(w, EditCellUse->cu_def->cd_name, TRUE, FALSE, FALSE); } /* Search function to find the new edit cell: look for a cell use @@ -3182,7 +3182,7 @@ CmdDrc(w, cmd) bool doforall = FALSE; bool dolist = FALSE; int count_total; - DRCCountList *dcl, *dclsrch; + DRCCountList *dcl; int argc = cmd->tx_argc; char **argv = cmd->tx_argv; #ifdef MAGIC_WRAPPER @@ -3197,9 +3197,9 @@ CmdDrc(w, cmd) "*stepsize [d] change DRC step size to d units", "catchup run checker and wait for it to complete", "check recheck area under box in all cells", - "count count error tiles in each cell under box", + "count [total] count error tiles in each cell under box", "euclidean on|off enable/disable Euclidean geometry checking", - "find [nth] locate next (or nth) error in the layout", + "find [nth] locate next (or nth) error in the layout", "help print this help information", "off turn off background checker", "on reenable background checker", @@ -3313,7 +3313,6 @@ CmdDrc(w, cmd) #ifdef MAGIC_WRAPPER if (count_total == -1) lobj = Tcl_NewListObj(0, NULL); #endif - if ((window = w) == NULL) { window = ToolGetBoxWindow(&rootArea, (int *) NULL); @@ -3323,7 +3322,7 @@ CmdDrc(w, cmd) rootArea = w->w_surfaceArea; rootUse = (CellUse *) window->w_surfaceID; - dcl = DRCCount(rootUse, &rootArea); + dcl = DRCCount(rootUse, &rootArea, doforall); while (dcl != NULL) { if (count_total >= 0) @@ -3343,7 +3342,6 @@ CmdDrc(w, cmd) else { #endif - if (dcl->dcl_count > 1) TxPrintf("Cell %s has %d error tiles.\n", dcl->dcl_def->cd_name, dcl->dcl_count); @@ -3372,11 +3370,12 @@ CmdDrc(w, cmd) } } else if (dolist) - Tcl_SetObjResult(magicinterp, lobj); + Tcl_SetObjResult(magicinterp, lobj); + #else if ((DRCBackGround != DRC_SET_OFF) && (count_total == -1)) count_total = 0; - if (count_total >= 0) + if (count_gotal >= 0) TxPrintf("Total DRC errors found: %d\n", count_total); #endif break; @@ -3677,7 +3676,7 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx) { Point childPoint, editPoint, rootPoint; CellDef *def, *rootDef, *editDef; - bool hasChild, hasRoot, hasTrans; + bool hasChild, hasRoot, hasTrans, dereference; Rect rootBox, bbox; Transform *tx_cell, trans_cell; char **av; @@ -3777,7 +3776,8 @@ cmdDumpParseArgs(cmdName, w, cmd, dummy, scx) * looked for then no new error message will be printed. */ def->cd_flags &= ~CDNOTFOUND; - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) + dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return (FALSE); DBReComputeBbox(def); dummy->cu_def = def; diff --git a/commands/CmdE.c b/commands/CmdE.c index 7be73fe8..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, 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/CmdFI.c b/commands/CmdFI.c index c1568efc..68f4ef00 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, @@ -1789,6 +1793,7 @@ FlatCopyAllLabels(scx, mask, xMask, targetUse) char pathstring[FLATTERMSIZE]; TerminalPath tpath; + pathstring[0] = '\0'; tpath.tp_first = tpath.tp_next = pathstring; tpath.tp_last = pathstring + FLATTERMSIZE; diff --git a/commands/CmdLQ.c b/commands/CmdLQ.c index 7f3f2310..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] + * load [name [scaled n [d]]] [-force] [-nowindow] [-dereference] * * If name is supplied, then the window containing the point tool is * remapped so as to edit the cell with the given name. @@ -331,6 +331,13 @@ CmdLabel(w, cmd) * An input file can be scaled by specifying the "scaled" option, for * which the geometry of the input file is multiplied by n/d. * + * Magic saves the path to instances to ensure correct versioning. But + * this interferes with attempts to re-link instances from a different + * location (such as an abstract view instead of a full view, or vice + * versa). So the "-dereference" option strips the instance paths from + * the input file and relies only on the search locations set up by the + * "path" command to find the location of instances. + * * Results: * None. * @@ -350,6 +357,7 @@ CmdLoad(w, cmd) int locargc = cmd->tx_argc; bool ignoreTech = FALSE; bool noWindow = FALSE; + bool dereference = FALSE; int keepGoing(); /* forward declaration */ if (locargc > 2) @@ -359,29 +367,38 @@ CmdLoad(w, cmd) locargc--; noWindow = TRUE; } + if (!strncmp(cmd->tx_argv[locargc - 1], "-deref", 5)) + { + locargc--; + dereference = TRUE; + } if (!strncmp(cmd->tx_argv[locargc - 1], "-force", 6)) { locargc--; ignoreTech = TRUE; } - if (locargc >= 4 && !strncmp(cmd->tx_argv[2], "scale", 5) && + if ((locargc >= 4) && !strncmp(cmd->tx_argv[2], "scale", 5) && StrIsInt(cmd->tx_argv[3])) { n = atoi(cmd->tx_argv[3]); - if (cmd->tx_argc == 5 && StrIsInt(cmd->tx_argv[4])) + if ((locargc == 5) && StrIsInt(cmd->tx_argv[4])) d = atoi(cmd->tx_argv[4]); else if (locargc != 4) { - TxError("Usage: %s name scaled n [d]\n", cmd->tx_argv[0]); + TxError("Usage: %s name scaled n [d] [-force] " + "[-nowindow] [-dereference]\n", + cmd->tx_argv[0]); return; } DBLambda[0] *= d; DBLambda[1] *= n; ReduceFraction(&DBLambda[0], &DBLambda[1]); } - else if (!ignoreTech && !noWindow) + else if (!ignoreTech && !noWindow && !dereference) { - TxError("Usage: %s [name [scaled n [d]]]\n", cmd->tx_argv[0]); + TxError("Usage: %s name [scaled n [d]] [-force] " + "[-nowindow] [-dereference]\n", + cmd->tx_argv[0]); return; } } @@ -406,7 +423,7 @@ CmdLoad(w, cmd) } #endif DBWloadWindow((noWindow == TRUE) ? NULL : w, cmd->tx_argv[1], - ignoreTech, FALSE); + ignoreTech, FALSE, dereference); if ((n > 1) || (d > 1)) { @@ -439,7 +456,7 @@ CmdLoad(w, cmd) ReduceFraction(&DBLambda[0], &DBLambda[1]); } } - else DBWloadWindow(w, (char *) NULL, TRUE, FALSE); + else DBWloadWindow(w, (char *) NULL, TRUE, FALSE, FALSE); } /* @@ -1882,8 +1899,16 @@ printPropertiesFunc(name, value) #ifdef MAGIC_WRAPPER char *keyvalue; - keyvalue = (char *)mallocMagic(strlen(name) + strlen((char *)value) + 2); - sprintf(keyvalue, "%s %s", name, (char *)value); + if (value == NULL) + { + keyvalue = (char *)mallocMagic(strlen(name) + 4); + sprintf(keyvalue, "%s {}", name); + } + else + { + keyvalue = (char *)mallocMagic(strlen(name) + strlen((char *)value) + 2); + sprintf(keyvalue, "%s %s", name, (char *)value); + } Tcl_AppendElement(magicinterp, keyvalue); freeMagic(keyvalue); diff --git a/commands/CmdSubrs.c b/commands/CmdSubrs.c index bdb34cce..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, 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/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 7c5e792a..48191ed1 100644 --- a/database/DBcellsrch.c +++ b/database/DBcellsrch.c @@ -234,7 +234,10 @@ dbCellPlaneSrFunc(scx, fp) if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0; + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } context.tc_scx = scx; context.tc_filter = fp; @@ -353,7 +356,10 @@ dbCellUniqueTileSrFunc(scx, fp) if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0; + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } context.tc_scx = scx; context.tc_filter = fp; @@ -462,7 +468,10 @@ DBNoTreeSrTiles(scx, mask, xMask, func, cdarg) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0; + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } filter.tf_func = func; filter.tf_arg = cdarg; @@ -570,7 +579,10 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg) ASSERT(def != (CellDef *) NULL, "DBTreeSrLabels"); if (!DBDescendSubcell(cellUse, xMask)) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0; + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } for (lab = def->cd_labels; lab; lab = lab->lab_next) { @@ -613,8 +625,11 @@ DBTreeSrLabels(scx, mask, xMask, tpath, flags, func, cdarg) else is_touching = GEO_TOUCH(&lab->lab_rect, r); } - if (!is_touching && (flags & TF_LABEL_DISPLAY) && (lab->lab_font >= 0)) + if (!is_touching && (flags & TF_LABEL_DISPLAY) && lab->lab_font >= 0) + { + /* Check against bounds of the rendered label text */ is_touching = GEO_TOUCH(&lab->lab_bbox, r); + } if (is_touching && TTMaskHasType(mask, lab->lab_type)) if ((*func)(scx, lab, tpath, cdarg)) @@ -671,7 +686,10 @@ dbCellLabelSrFunc(scx, fp) ASSERT(def != (CellDef *) NULL, "dbCellLabelSrFunc"); if (!DBDescendSubcell(scx->scx_use, fp->tf_xmask)) return 0; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return 0; + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } if (fp->tf_tpath != (TerminalPath *) NULL) { @@ -785,8 +803,11 @@ DBTreeSrCells(scx, xMask, func, cdarg) if (!DBDescendSubcell(cellUse, xMask)) return 0; if ((cellUse->cu_def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(cellUse->cu_def, (char *) NULL, TRUE, NULL)) + { + bool dereference = (cellUse->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(cellUse->cu_def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } context.tc_scx = scx; context.tc_filter = &filter; @@ -831,8 +852,11 @@ dbTreeCellSrFunc(scx, fp) else { if ((use->cu_def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, NULL)) + { + bool dereference = (use->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(use->cu_def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } result = DBCellSrArea(scx, dbTreeCellSrFunc, (ClientData) fp); } return result; @@ -1082,8 +1106,12 @@ DBCellSrArea(scx, func, cdarg) context.tc_scx = scx; if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, NULL)) + { + bool dereference = (scx->scx_use->cu_def->cd_flags & CDDEREFERENCE) ? + TRUE : FALSE; + if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } if (DBSrCellPlaneArea(scx->scx_use->cu_def->cd_cellPlane, &scx->scx_area, dbCellSrFunc, (ClientData) &context)) @@ -1205,7 +1233,10 @@ DBCellEnum(cellDef, func, cdarg) filter.tf_func = func; filter.tf_arg = cdarg; if ((cellDef->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(cellDef, (char *) NULL, TRUE, NULL)) return 0; + { + bool dereference = (cellDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(cellDef, (char *) NULL, TRUE, dereference, NULL)) return 0; + } if (DBSrCellPlaneArea(cellDef->cd_cellPlane, &TiPlaneRect, dbEnumFunc, (ClientData) &filter)) return 1; diff --git a/database/DBcellsubr.c b/database/DBcellsubr.c index 1ad4d6a1..16d70e0e 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, 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/DBconnect.c b/database/DBconnect.c index 76ae1b10..72135a08 100644 --- a/database/DBconnect.c +++ b/database/DBconnect.c @@ -661,6 +661,9 @@ dbcUnconnectFunc(tile, clientData) * ---------------------------------------------------------------------------- */ +/* To do: Make the tpath entries dynamically allocated */ +#define FLATTERMSIZE 1024 + int dbcConnectLabelFunc(scx, lab, tpath, csa2) SearchContext *scx; @@ -672,6 +675,8 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2) Rect r; Point offset; int pos, rotate; + char newlabtext[FLATTERMSIZE]; + char *newlabptr; int dbcConnectFunc(); /* Forward declaration */ GeoTransRect(&scx->scx_trans, &lab->lab_rect, &r); @@ -683,12 +688,29 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2) /* the top level (Note: Could alter label to be placed with */ /* tpath). */ - if (csa2->csa2_topscx->scx_use == scx->scx_use) + if (scx->scx_use != csa2->csa2_topscx->scx_use) { - DBEraseLabelsByContent(def, &r, -1, lab->lab_text); - DBPutFontLabel(def, &r, lab->lab_font, lab->lab_size, rotate, &offset, - pos, lab->lab_text, lab->lab_type, lab->lab_flags); + int newllen = tpath->tp_next - tpath->tp_first; + newlabtext[0] = '\0'; + if (newllen > 0) + strncpy(newlabtext, tpath->tp_first, newllen); + sprintf(newlabtext + newllen, "%s", lab->lab_text); + newlabptr = newlabtext; } + else + newlabptr = lab->lab_text; + + /* Do not repeat a label copy; check that the label doesn't */ + /* already exist in the destination def first. */ + if (DBCheckLabelsByContent(def, &r, lab->lab_type, lab->lab_text)) + return 0; + + if (DBCheckLabelsByContent(def, &r, lab->lab_type, newlabptr)) + return 0; + + DBEraseLabelsByContent(def, &r, -1, lab->lab_text); + DBPutFontLabel(def, &r, lab->lab_font, lab->lab_size, rotate, &offset, + pos, newlabptr, lab->lab_type, lab->lab_flags); if (lab->lab_flags & PORT_DIR_MASK) { @@ -1024,6 +1046,13 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, destUse) DBTreeSrTiles(scx, mask, xMask, dbcConnectFunc, (ClientData) &csa2); while (csa2.csa2_top >= 0) { + char pathstring[FLATTERMSIZE]; + TerminalPath tpath; + + tpath.tp_first = tpath.tp_next = pathstring; + tpath.tp_last = pathstring + FLATTERMSIZE; + pathstring[0] = '\0'; + newmask = csa2.csa2_list[csa2.csa2_top].connectMask; scx->scx_area = csa2.csa2_list[csa2.csa2_top].area; newtype = csa2.csa2_list[csa2.csa2_top].dinfo; @@ -1064,7 +1093,7 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, destUse) searchtype |= TF_LABEL_ATTACH_NOT_SE; } } - DBTreeSrLabels(scx, newmask, xMask, NULL, searchtype, + DBTreeSrLabels(scx, newmask, xMask, &tpath, searchtype, dbcConnectLabelFunc, (ClientData) &csa2); } freeMagic((char *)csa2.csa2_list); diff --git a/database/DBexpand.c b/database/DBexpand.c index 981748c8..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, NULL)) + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return; /* Note: we don't have to recompute the bbox here, because * if it changed, then a timestamp violation must have occurred @@ -142,9 +144,13 @@ DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg) int dbExpandFunc(), dbUnexpandFunc(); SearchContext scontext; struct expandArg arg; + bool dereference = (rootUse->cu_def->cd_flags & CDDEREFERENCE) ? + TRUE : FALSE; if ((rootUse->cu_def->cd_flags & CDAVAILABLE) == 0) - (void) DBCellRead(rootUse->cu_def, (char *) NULL, TRUE, NULL); + { + (void) DBCellRead(rootUse->cu_def, (char *) NULL, TRUE, dereference, NULL); + } /* * Walk through the area and set the expansion state @@ -154,6 +160,7 @@ DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg) arg.ea_xmask = expandMask; arg.ea_func = func; arg.ea_arg = cdarg; + arg.ea_deref = dereference; scontext.scx_use = rootUse; scontext.scx_trans = GeoIdentityTransform; @@ -193,7 +200,7 @@ dbExpandFunc(scx, arg) /* If the cell is unavailable, then don't expand it. */ if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0) - if(!DBCellRead(childUse->cu_def, (char *) NULL, TRUE, NULL)) + if(!DBCellRead(childUse->cu_def, (char *) NULL, TRUE, arg->ea_deref, NULL)) { TxError("Cell %s is unavailable. It could not be expanded.\n", childUse->cu_def->cd_name); @@ -303,7 +310,8 @@ dbReadAreaFunc(scx) if ((def->cd_flags & CDAVAILABLE) == 0) { - (void) DBCellRead(def, (char *) NULL, TRUE, NULL); + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + (void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL); /* Note: we don't have to invoke DBReComputeBbox here because * if the bbox changed then there was a timestamp mismatch and * the timestamp code will take care of the bounding box later. diff --git a/database/DBio.c b/database/DBio.c index f27ddde0..0e833c92 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; } @@ -619,6 +620,9 @@ done: } } } + /* Update timestamp flags */ + DBFlagMismatches(cellDef); + cellDef->cd_timestamp = cellStamp; if (cellStamp == 0) { @@ -860,7 +864,7 @@ DBReadBackup(name) cellDef->cd_flags &= ~CDNOTFOUND; cellDef->cd_flags |= CDAVAILABLE; - if (dbCellReadDef(f, cellDef, filename, TRUE) == FALSE) + if (dbCellReadDef(f, cellDef, filename, TRUE, FALSE) == FALSE) return FALSE; if (dbFgets(line, sizeof(line), f) == NULL) @@ -869,6 +873,8 @@ DBReadBackup(name) name); return FALSE; } + /* Update timestamp flags from dbCellReadDef() */ + DBFlagMismatches(cellDef); } else { @@ -914,7 +920,7 @@ DBReadBackup(name) */ bool -DBCellRead(cellDef, name, ignoreTech, errptr) +DBCellRead(cellDef, name, ignoreTech, dereference, errptr) CellDef *cellDef; /* Pointer to definition of cell to be read in */ char *name; /* Name of file from which to read definition. * If NULL, then use cellDef->cd_file; if that @@ -928,6 +934,7 @@ DBCellRead(cellDef, name, ignoreTech, errptr) * names do not match, but an attempt will be * made to read the file anyway. */ + bool dereference; /* If TRUE then ignore path argument to uses */ int *errptr; /* Copy of errno set by file reading routine * is placed here, unless NULL. */ @@ -945,7 +952,7 @@ DBCellRead(cellDef, name, ignoreTech, errptr) else { - result = (dbCellReadDef(f, cellDef, name, ignoreTech)); + result = (dbCellReadDef(f, cellDef, name, ignoreTech, dereference)); #ifdef FILE_LOCKS /* Close files that were locked by another user */ @@ -1188,13 +1195,14 @@ DBTestOpen(name, fullPath) */ bool -dbReadUse(cellDef, line, len, f, scalen, scaled) +dbReadUse(cellDef, line, len, f, scalen, scaled, dereference) CellDef *cellDef; /* Cell whose cells are being read */ char *line; /* Line containing "use ..." */ int len; /* Size of buffer pointed to by line */ FILE *f; /* Input file */ int scalen; /* Multiply values in file by this */ int scaled; /* Divide values in file by this */ + bool dereference; /* If TRUE, ignore path references */ { int xlo, xhi, ylo, yhi, xsep, ysep, childStamp; int absa, absb, absd, abse, nconv; @@ -1225,7 +1233,7 @@ dbReadUse(cellDef, line, len, f, scalen, scaled) pathptr = &path[0]; while (*pathptr == ' ' || *pathptr == '\t') pathptr++; - if (*pathptr == '\n') *pathptr = '\0'; + if ((dereference == TRUE) || (*pathptr == '\n')) *pathptr = '\0'; locked = (useid[0] == CULOCKCHAR) ? TRUE : FALSE; @@ -1432,9 +1440,22 @@ badTransform: slashptr = strrchr(subCellDef->cd_file, '/'); if (slashptr != NULL) { + bool pathOK = FALSE; *slashptr = '\0'; - if (strcmp(subCellDef->cd_file, pathptr)) + /* Avoid generating error message if pathptr starts with '~' */ + /* and the tilde-expanded name matches the subCellDef name */ + + if (*pathptr == '~') + { + char *homedir = getenv("HOME"); + if (!strncmp(subCellDef->cd_file, homedir, strlen(homedir)) + && (!strcmp(subCellDef->cd_file + strlen(homedir), + pathptr + 1))) + pathOK = TRUE; + } + + if ((pathOK == FALSE) && strcmp(subCellDef->cd_file, pathptr)) { TxError("Duplicate cell in %s: Instance of cell %s is from " "path %s but cell was previously read from %s.\n", @@ -2345,6 +2366,8 @@ DBCellWriteFile(cellDef, f) int reducer; char *estring; char lstring[256]; + char *propvalue; + bool propfound; #define FPRINTF(f,s)\ {\ @@ -2537,12 +2560,43 @@ DBCellWriteFile(cellDef, f) } /* And any properties */ + + /* NOTE: FIXED_BBOX is treated specially; values are database */ + /* values and should be divided by reducer. Easiest to do it */ + /* here and revert values after. */ + + propvalue = (char *)DBPropGet(cellDef, "FIXED_BBOX", &propfound); + if (propfound) + { + char *proporig, *propscaled; + Rect scalebox, bbox; + + proporig = StrDup((char **)NULL, propvalue); + propscaled = mallocMagic(strlen(propvalue) + 5); + if (sscanf(propvalue, "%d %d %d %d", &bbox.r_xbot, &bbox.r_ybot, + &bbox.r_xtop, &bbox.r_ytop) == 4) + { + scalebox.r_xbot = bbox.r_xbot / reducer; + scalebox.r_xtop = bbox.r_xtop / reducer; + scalebox.r_ybot = bbox.r_ybot / reducer; + scalebox.r_ytop = bbox.r_ytop / reducer; + sprintf(propscaled, "%d %d %d %d", + bbox.r_xbot / reducer, bbox.r_ybot / reducer, + bbox.r_xtop / reducer, bbox.r_ytop / reducer); + + DBPropPut(cellDef, "FIXED_BBOX", propscaled); + propvalue = proporig; + } + } + if (cellDef->cd_props != (ClientData)NULL) { FPRINTF(f, "<< properties >>\n"); DBPropEnum(cellDef, dbWritePropFunc, (ClientData)f); } + if (propfound) DBPropPut(cellDef, "FIXED_BBOX", propvalue); + FPRINTF(f, "<< end >>\n"); if (fflush(f) == EOF || ferror(f)) @@ -2801,8 +2855,11 @@ DBCellWrite(cellDef, fileName) #ifdef FILE_LOCKS else + { + bool dereference = (cellDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; /* Re-aquire the lock on the new file by opening it. */ - DBCellRead(cellDef, NULL, TRUE, NULL); + DBCellRead(cellDef, NULL, TRUE, dereference, NULL); + } #endif } 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) diff --git a/database/DBlabel2.c b/database/DBlabel2.c index 91c1908d..444c6e92 100644 --- a/database/DBlabel2.c +++ b/database/DBlabel2.c @@ -294,20 +294,31 @@ DBTreeFindUse(name, use, scx) * is read in from disk. */ if ((def->cd_flags & CDAVAILABLE) == 0) - (void) DBCellRead(def, (char *) NULL, TRUE, NULL); + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + (void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL); + } - /* - * Pull off the next component of path up to but not including - * any array subscripts. - */ - for (cp = name; *cp && *cp != '[' && *cp != '/'; cp++) - /* Nothing */; - csave = *cp; - *cp = '\0'; + cp = name; he = HashLookOnly(&def->cd_idHash, name); - *cp = csave; if (he == NULL || HashGetValue(he) == NULL) - return; + { + /* + * Pull off the next component of path up to but not including + * any array subscripts. + * NOTE: This should check the array bounds and only remove + * array components that are expected, not array components + * embedded in the name. + */ + for (; *cp && *cp != '[' && *cp != '/'; cp++) + /* Nothing */; + csave = *cp; + *cp = '\0'; + he = HashLookOnly(&def->cd_idHash, name); + *cp = csave; + if (he == NULL || HashGetValue(he) == NULL) + return; + } use = (CellUse *) HashGetValue(he); def = use->cu_def; @@ -335,7 +346,10 @@ DBTreeFindUse(name, use, scx) /* Ensure that the leaf cell is read in */ def = use->cu_def; if ((def->cd_flags & CDAVAILABLE) == 0) - (void) DBCellRead(def, (char *) NULL, TRUE, NULL); + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + (void) DBCellRead(def, (char *) NULL, dereference, NULL); + } scx->scx_use = use; } diff --git a/database/DBprop.c b/database/DBprop.c index c2ded840..0936ec3d 100644 --- a/database/DBprop.c +++ b/database/DBprop.c @@ -66,11 +66,23 @@ DBPropPut(cellDef, name, value) HashInit( (HashTable *) cellDef->cd_props, 8, 0); } htab = (HashTable *) cellDef->cd_props; + + /* Special handling of FIXED_BBOX, which uses CDFIXEDBBOX as a quick lookup */ + if (!strcmp(name, "FIXED_BBOX")) + { + if (value == (ClientData)NULL) + cellDef->cd_flags &= ~CDFIXEDBBOX; + else + cellDef->cd_flags |= CDFIXEDBBOX; + } entry = HashFind(htab, name); oldvalue = (char *)HashGetValue(entry); if (oldvalue != NULL) freeMagic(oldvalue); - HashSetValue(entry, value); + if (value == (ClientData)NULL) + HashRemove(htab, name); + else + HashSetValue(entry, value); } /* ---------------------------------------------------------------------------- @@ -202,4 +214,8 @@ DBPropClearAll(cellDef) HashKill(htab); freeMagic((char *) htab); cellDef->cd_props = (ClientData) NULL; + + /* Since CDFIXEDBBOX requires a FIXED_BBOX property, clearing all */ + /* properties necessarily means this flag must be clear. */ + cellDef->cd_flags &= ~CDFIXEDBBOX; } diff --git a/database/DBtechtype.c b/database/DBtechtype.c index 2bd4c03b..b1d05b7c 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/database/DBtimestmp.c b/database/DBtimestmp.c index ce34b2e8..21683065 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, NULL); + dereference = (cellDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + (void) DBCellRead(cellDef, (char *) NULL, TRUE, dereference, NULL); /* Jimmy up the cell's current bounding box, so the following * procedure call will absolutely and positively know that @@ -267,6 +270,16 @@ dbStampFunc(cellDef) * processing. When DBFixMismatch is called, it will notify * the design-rule checker to recheck both wrongArea, and * the cell's eventual correct area. + * + * This routine has been modified from a poor implementation. Previously + * the parent def of all uses of the cell being checked would be marked + * for a stamp mismatch check. However, when reading a cell with large + * numbers of instances, the list of instances would be parsed for every + * instance added, leading to an O(N^2) computation. Routine DBStampMismatch() + * has been broken into two parts. DBStampMismatch() only records the + * area to be checked. DBFlagMismatches() looks at the parents of each + * celldef only once, after all instances have been read. + * * ---------------------------------------------------------------------------- */ @@ -278,16 +291,27 @@ DBStampMismatch(cellDef, wrongArea) */ { Mismatch *mm; - CellUse *parentUse; mm = (Mismatch *) mallocMagic((unsigned) (sizeof (Mismatch))); mm->mm_cellDef = cellDef; mm->mm_oldArea = *wrongArea; mm->mm_next = mismatch; mismatch = mm; +} - for (parentUse = cellDef->cd_parents; parentUse != NULL; - parentUse = parentUse->cu_nextuse) +/* + * ---------------------------------------------------------------------------- + * ---------------------------------------------------------------------------- + */ + +void +DBFlagMismatches(checkDef) + CellDef *checkDef; +{ + CellUse *parentUse; + + for (parentUse = checkDef->cd_parents; parentUse != NULL; + parentUse = parentUse->cu_nextuse) { if (parentUse->cu_parent == NULL) continue; parentUse->cu_parent->cd_flags |= CDSTAMPSCHANGED; diff --git a/database/database.h.in b/database/database.h.in index 4202e074..a5bee425 100644 --- a/database/database.h.in +++ b/database/database.h.in @@ -396,6 +396,9 @@ typedef struct celldef * with the option "gds readonly true". * CDVISITED indicates that at least one instance of the cell was * already output during a file write. + * CDDEREFERENCE is a flag indicating that when loading or expanding + * children of a cell, the path should be ignored and the cell + * path should be searched for the location. */ #define CDAVAILABLE 0x0001 @@ -413,6 +416,7 @@ typedef struct celldef #define CDPROCESSEDGDS 0x1000 #define CDVENDORGDS 0x2000 #define CDVISITED 0x4000 +#define CDDEREFERENCE 0x8000 /* * Description of an array. 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(); 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/dbwind/DBWdisplay.c b/dbwind/DBWdisplay.c index 3082a380..ca1ea0a6 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/dbwind/DBWprocs.c b/dbwind/DBWprocs.c index aab82f5a..2bf4fca1 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,26 +274,29 @@ dbwReloadFunc(w, name) * cell doesn't change. * * If "expand" is true, unexpands all subcells of the root cell. + * If "dereference" is true, ignore path reference in the input file. * * ---------------------------------------------------------------------------- */ void -DBWloadWindow(window, name, ignoreTech, expand) +DBWloadWindow(window, name, ignoreTech, expand, dereference) MagWindow *window; /* Identifies window to which cell is to be bound */ char *name; /* Name of new cell to be bound to this window */ bool ignoreTech; /* If FALSE, indicates that the technology of * the layout must match the current technology. */ bool expand; /* Indicates whether or not to expand the cell */ + bool dereference; /* If TRUE, ignore path references in the input */ { - CellDef *newEditDef; + CellDef *newEditDef, *deleteDef; CellUse *newEditUse; void DisplayWindow(); int res, newEdit, error_val; int xadd, yadd; Rect loadBox; char *rootname; + bool isUnnamed; int UnexpandFunc(); /* forward declaration */ loadBox.r_xbot = loadBox.r_ybot = 0; @@ -303,6 +306,19 @@ DBWloadWindow(window, name, ignoreTech, expand) newEdit = !WindSearch((WindClient) DBWclientID, (ClientData) NULL, (Rect *) NULL, dbwLoadFunc, (ClientData) window); + /* The (UNNAMED) cell generally gets in the way, so delete it if */ + /* any new cell is loaded and (UNNAMED) has no contents. */ + + if (window->w_surfaceID == (ClientData)NULL) + deleteDef = NULL; + else + { + deleteDef = ((CellUse *)window->w_surfaceID)->cu_def; + if (strcmp(deleteDef->cd_name, "(UNNAMED)") || + deleteDef->cd_flags & (CDMODIFIED|CDBOXESCHANGED|CDSTAMPSCHANGED)) + deleteDef = NULL; + } + if ((name == (char *) NULL) || (name[0] == '\0')) { /* @@ -383,7 +399,9 @@ DBWloadWindow(window, name, ignoreTech, expand) if (newEditDef == (CellDef *) NULL) newEditDef = DBCellNewDef(rootname, (char *) NULL); - if (!DBCellRead(newEditDef, name, ignoreTech, &error_val)) + if (dereference) newEditDef->cd_flags |= CDDEREFERENCE; + + if (!DBCellRead(newEditDef, name, ignoreTech, dereference, &error_val)) { if (error_val == ENOENT) { @@ -499,6 +517,12 @@ DBWloadWindow(window, name, ignoreTech, expand) if (newEdit) DBWAreaChanged(newEditDef, &newEditDef->cd_bbox, DBW_ALLWINDOWS, &DBAllButSpaceBits); + + /* If the cell before loading was (UNNAMED) and it was */ + /* never modified, then delete it now. */ + + if (deleteDef != NULL) + DBCellDelete(deleteDef->cd_name, TRUE); } /* This function is called for each cell whose expansion status changed. 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/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/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.

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/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 a3d2cbbf..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 }; @@ -484,6 +484,7 @@ drcTile (tile, arg) int edgeX = LEFT(tile); firsttile = TRUE; + mrd = NULL; for (tpleft = BL(tile); BOTTOM(tpleft) < top; tpleft = RT(tpleft)) { /* Get the tile types to the left and right of the edge */ @@ -554,8 +555,6 @@ drcTile (tile, arg) mrd = drcCanonicalMaxwidth(tpleft, GEO_WEST, arg, cptr); else if (firsttile) mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr); - else - mrd = NULL; if (!trigpending || (DRCCurStyle->DRCFlags & DRC_FLAGS_WIDEWIDTH_NONINCLUSIVE)) cptr->drcc_dist--; @@ -610,7 +609,6 @@ drcTile (tile, arg) drcCheckMaxwidth(tile, arg, cptr); continue; } - else if (!triggered) mrd = NULL; if (cptr->drcc_flags & DRC_RECTSIZE) { @@ -625,6 +623,7 @@ drcTile (tile, arg) result = 0; arg->dCD_radial = 0; + arg->dCD_entries = 0; do { if (triggered) { @@ -870,6 +869,7 @@ checkbottom: /* Go right across bottom of tile */ firsttile = TRUE; + mrd = NULL; for (tpbot = LB(tile); LEFT(tpbot) < right; tpbot = TR(tpbot)) { /* Get the tile types to the top and bottom of the edge */ @@ -936,8 +936,6 @@ checkbottom: mrd = drcCanonicalMaxwidth(tpbot, GEO_SOUTH, arg, cptr); else if (firsttile) mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr); - else - mrd = NULL; if (!trigpending || (DRCCurStyle->DRCFlags & DRC_FLAGS_WIDEWIDTH_NONINCLUSIVE)) cptr->drcc_dist--; @@ -992,10 +990,10 @@ checkbottom: if (trigpending) cptr = cptr->drcc_next; continue; } - else if (!triggered) mrd = NULL; result = 0; arg->dCD_radial = 0; + arg->dCD_entries = 0; do { if (triggered) { diff --git a/drc/DRCcif.c b/drc/DRCcif.c index 6fe7321b..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(); @@ -67,9 +66,10 @@ extern bool DRCForceReload; TileTypeBitMask drcCifGenLayers; DRCCookie *drcCifRules[MAXCIFLAYERS][2]; -DRCCookie *drcCifCur=NULL; +DRCCookie *drcCifCur = NULL; int drcCifValid = FALSE; -int beenWarned; +bool beenWarned = FALSE; +char *drcNeedStyle = NULL; #define DRC_CIF_SPACE 0 #define DRC_CIF_SOLID 1 @@ -112,14 +112,12 @@ drcCifSetStyle(argc, argv) { if (!strcmp(new->cs_name, argv[1])) { + drcNeedStyle = new->cs_name; DRCForceReload = TRUE; if (!strcmp(new->cs_name, CIFCurStyle->cs_name)) drcCifStyle = CIFCurStyle; else { - TechError("DRC cif extensions are not enabled.\n\t" - "Use \"cif ostyle %s\" to enable them.\n", - new->cs_name); drcCifStyle = NULL; beenWarned = TRUE; /* post no more error messages */ } @@ -170,7 +168,7 @@ drcCifWidth(argc, argv) char *layername = argv[1]; int scalefactor; int centidistance = atoi(argv[2]); - char *why = drcWhyDup(argv[3]); + int why = drcWhyCreate(argv[3]); TileTypeBitMask set, setC, tmp1; int thislayer = -1; DRCCookie *dpnew,*dpnext; @@ -200,7 +198,7 @@ drcCifWidth(argc, argv) dpnext = drcCifRules[thislayer][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, centidistance, dpnext, &CIFSolidBits, + drcCifAssign(dpnew, centidistance, dpnext, &CIFSolidBits, &CIFSolidBits, why, centidistance, DRC_FORWARD, thislayer, 0); drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew; @@ -229,7 +227,7 @@ drcCifSpacing(argc, argv) char *argv[]; { char *adjacency = argv[4]; - char *why = drcWhyDup(argv[5]); + int why = drcWhyCreate(argv[5]); DRCCookie *dpnext, *dpnew; int needReverse = FALSE; TileType i, j; @@ -292,7 +290,7 @@ drcCifSpacing(argc, argv) centidistance *= drcCifStyle->cs_expander; // BSI dpnext = drcCifRules[layer[0]][DRC_CIF_SOLID]; dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie)); - drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, + drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, why, centidistance, DRC_FORWARD, layer[1], 0); drcCifRules[layer[0]][DRC_CIF_SOLID] = dpnew; if (needReverse) dpnew->drcc_flags |= DRC_BOTHCORNERS; @@ -300,7 +298,7 @@ drcCifSpacing(argc, argv) // Add rule in reverse direction dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie)); - drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, + drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, why, centidistance, DRC_REVERSE, layer[1], 0); drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew; @@ -312,14 +310,14 @@ drcCifSpacing(argc, argv) dpnew->drcc_flags |= DRC_BOTHCORNERS; dpnext = drcCifRules[layer[1]][DRC_CIF_SOLID]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, + drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, why, centidistance, DRC_FORWARD|DRC_BOTHCORNERS, layer[0], 0); drcCifRules[layer[1]][DRC_CIF_SOLID] = dpnew; // Add rule in reverse direction dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) sizeof (DRCCookie)); - drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, + drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, why, centidistance, DRC_REVERSE|DRC_BOTHCORNERS, layer[0], 0); drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew; @@ -327,14 +325,14 @@ drcCifSpacing(argc, argv) { dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, + drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, why, centidistance, DRC_REVERSE | DRC_BOTHCORNERS, layer[0], 0); drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew; dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, + drcCifAssign(dpnew, centidistance, dpnext, &DBSpaceBits, &cmask, why, centidistance, DRC_REVERSE | DRC_BOTHCORNERS, layer[1], 0); drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew; @@ -345,13 +343,13 @@ drcCifSpacing(argc, argv) { dpnext = drcCifRules[layer[1]][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, scalefactor, dpnext, &DBSpaceBits, &DBZeroTypeBits, + drcCifAssign(dpnew, scalefactor, dpnext, &DBSpaceBits, &DBZeroTypeBits, why, scalefactor, DRC_FORWARD, layer[0], 0); drcCifRules[layer[1]][DRC_CIF_SPACE] = dpnew; dpnext = drcCifRules[layer[0]][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, scalefactor, dpnext, &DBSpaceBits, &DBZeroTypeBits, + drcCifAssign(dpnew, scalefactor, dpnext, &DBSpaceBits, &DBZeroTypeBits, why, scalefactor, DRC_FORWARD, layer[1], 0); drcCifRules[layer[0]][DRC_CIF_SPACE] = dpnew; } @@ -501,9 +499,37 @@ drcCifCheck(arg) int scale; int i,j; int oldTiles; + CIFStyle *CIFSaveStyle = NULL; - if (drcCifValid == FALSE) return; - else if (CIFCurStyle != drcCifStyle) return; + if (CIFCurStyle != drcCifStyle) + { + if (drcNeedStyle == NULL) return; + + CIFSaveStyle = CIFCurStyle; + + if (drcCifStyle == NULL) + { + TxPrintf("Loading DRC CIF style.\n"); + CIFCurStyle = NULL; + CIFLoadStyle(drcNeedStyle); + if (drcCifValid != FALSE) + CIFCurStyle = CIFSaveStyle; + else + drcCifStyle = CIFCurStyle; + } + if (drcCifStyle == NULL) + { + TxError("Error: Failed to load CIF DRC style.\n"); + return; + } + CIFCurStyle = drcCifStyle; + } + if (drcCifValid == FALSE) + { + if (CIFSaveStyle != NULL) + CIFCurStyle = CIFSaveStyle; + return; + } scale = drcCifStyle->cs_scaleFactor; cifrect = *checkRect; @@ -534,6 +560,9 @@ drcCifCheck(arg) } arg->dCD_rect = checkRect; DRCstatCifTiles += DRCstatTiles - oldTiles; + + /* Put it back the way you found it */ + if (CIFSaveStyle != NULL) CIFCurStyle = CIFSaveStyle; } /* @@ -1035,7 +1064,7 @@ drcCifArea(argc, argv) char *layers = argv[1]; int centiarea = atoi(argv[2]); int centihorizon = atoi(argv[3]); - char *why = drcWhyDup(argv[4]); + int why = drcWhyCreate(argv[4]); TileTypeBitMask set, setC, tmp1; DRCCookie *dpnext, *dpnew; TileType i, j; @@ -1066,7 +1095,7 @@ drcCifArea(argc, argv) centiarea *= (drcCifStyle->cs_expander * drcCifStyle->cs_expander); dpnext = drcCifRules[thislayer][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, centihorizon, dpnext, &CIFSolidBits, &CIFSolidBits, + drcCifAssign(dpnew, centihorizon, dpnext, &CIFSolidBits, &CIFSolidBits, why, centiarea, DRC_AREA | DRC_FORWARD, thislayer, 0); drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew; @@ -1096,7 +1125,7 @@ drcCifMaxwidth(argc, argv) char *layers = argv[1]; int centidistance = atoi(argv[2]); char *bends = argv[3]; - char *why = drcWhyDup(argv[4]); + int why = drcWhyCreate(argv[4]); TileTypeBitMask set, setC, tmp1; DRCCookie *dpnext, *dpnew; TileType i, j; @@ -1136,11 +1165,10 @@ drcCifMaxwidth(argc, argv) centidistance *= drcCifStyle->cs_expander; // BSI dpnext = drcCifRules[thislayer][DRC_CIF_SPACE]; dpnew = (DRCCookie *) mallocMagic((unsigned) (sizeof (DRCCookie))); - drcAssign(dpnew, centidistance, dpnext, &CIFSolidBits, &CIFSolidBits, + drcCifAssign(dpnew, centidistance, dpnext, &CIFSolidBits, &CIFSolidBits, why, centidistance, DRC_MAXWIDTH | bend, thislayer, 0); drcCifRules[thislayer][DRC_CIF_SPACE] = dpnew; - return ((centidistance+scalefactor-1)/scalefactor); } diff --git a/drc/DRCmain.c b/drc/DRCmain.c index 8b2d0a8c..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 */ @@ -343,7 +340,7 @@ drcListallError (celldef, rect, cptr, scx) area = &scx->scx_area; if ((area != NULL) && (!GEO_OVERLAP(area, rect))) return; DRCErrorCount += 1; - h = HashFind(&DRCErrorTable, cptr->drcc_why); + h = HashFind(&DRCErrorTable, drcSubstitute(cptr)); lobj = (Tcl_Obj *) HashGetValue(h); if (lobj == NULL) lobj = Tcl_NewListObj(0, NULL); @@ -475,11 +472,15 @@ DRCWhy(dolist, use, area) { SearchContext scx; Rect box; + int i; extern int drcWhyFunc(); /* Forward reference. */ - /* Create a hash table to used for eliminating duplicate messages. */ + /* Create a hash table to eliminate duplicate messages. */ + + DRCErrorList = (int *)mallocMagic((DRCCurStyle->DRCWhySize + 1) * sizeof(int)); + for (i = 0; i <= DRCCurStyle->DRCWhySize; i++) + DRCErrorList[i] = 0; - HashInit(&DRCErrorTable, 16, HT_STRINGKEYS); DRCErrorCount = 0; box = DRCdef->cd_bbox; @@ -494,12 +495,9 @@ DRCWhy(dolist, use, area) drcWhyFunc(&scx, (pointertype)dolist); UndoEnable(); - /* Delete the hash table now that we're finished (otherwise there - * will be a core leak. - */ - - HashKill(&DRCErrorTable); - + /* Delete the error list */ + freeMagic(DRCErrorList); + /* Redisplay the DRC yank definition in case anyone is looking * at it. */ @@ -532,7 +530,7 @@ DRCWhyAll(use, area, fout) HashEntry *he; Tcl_Obj *lobj, *robj; - /* Create a hash table to used for eliminating duplicate messages. */ + /* Create a hash table for storing all of the results */ HashInit(&DRCErrorTable, 16, HT_STRINGKEYS); DRCErrorCount = 0; @@ -566,10 +564,7 @@ DRCWhyAll(use, area, fout) } Tcl_SetObjResult(magicinterp, robj); - /* Delete the hash table now that we're finished (otherwise there - * will be a core leak. - */ - + /* Delete the error table now that we're finished */ HashKill(&DRCErrorTable); /* Redisplay the DRC yank definition in case anyone is looking @@ -748,9 +743,10 @@ drcCheckFunc(scx, cdarg) */ DRCCountList * -DRCCount(use, area) +DRCCount(use, area, recurse) CellUse *use; /* Top-level use of hierarchy. */ Rect *area; /* Area in which violations are counted. */ + bool recurse; /* If TRUE, count errors in all subcells */ { DRCCountList *dcl, *newdcl; HashTable dupTable; @@ -758,7 +754,11 @@ DRCCount(use, area) HashSearch hs; int count; SearchContext scx; - extern int drcCountFunc(); /* Forward reference. */ + CellDef *def; + extern int drcCountFunc(); + + /* Shouldn't happen? */ + if (!(use->cu_def->cd_flags & CDAVAILABLE)) return NULL; /* Use a hash table to make sure that we don't output information * for any cell more than once. @@ -766,6 +766,10 @@ DRCCount(use, area) HashInit(&dupTable, 16, HT_WORDKEYS); + /* Clearing CDAVAILABLE from cd_flags keeps the count from recursing */ + if (recurse == FALSE) + use->cu_def->cd_flags &= ~CDAVAILABLE; + scx.scx_use = use; scx.scx_x = use->cu_xlo; scx.scx_y = use->cu_ylo; @@ -781,7 +785,7 @@ DRCCount(use, area) HashStartSearch(&hs); while ((he = HashNext(&dupTable, &hs)) != (HashEntry *)NULL) { - count = (spointertype)HashGetValue(he); + count = (spointertype)HashGetValue(he); if (count > 1) { newdcl = (DRCCountList *)mallocMagic(sizeof(DRCCountList)); @@ -793,15 +797,20 @@ DRCCount(use, area) } } HashKill(&dupTable); + + /* Restore the CDAVAILABLE flag */ + if (recurse == FALSE) + use->cu_def->cd_flags |= CDAVAILABLE; + return dcl; } int drcCountFunc(scx, dupTable) SearchContext *scx; - HashTable *dupTable; /* Passed as client data, used to - * avoid searching any cell twice. - */ + HashTable *dupTable; /* Passed as client data, used to + * avoid searching any cell twice. + */ { int count; HashEntry *h; @@ -821,7 +830,7 @@ drcCountFunc(scx, dupTable) count = 0; (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR], - &def->cd_bbox, &DBAllButSpaceBits, drcCountFunc2, (ClientData) &count); + &def->cd_bbox, &DBAllButSpaceBits, drcCountFunc2, (ClientData)(&count)); HashSetValue(h, (spointertype)count + 1); /* Ignore children that have not been loaded---we will only report */ @@ -832,26 +841,26 @@ drcCountFunc(scx, dupTable) if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) return 0; - /* New behavior: Don't search children, instead propagate errors up. */ - /* (void) DBCellSrArea(scx, drcCountFunc, (ClientData) dupTable); */ + /* Scan children recursively. */ + + DBCellSrArea(scx, drcCountFunc, (ClientData)dupTable); /* As a special performance hack, if the complete cell area is * handled here, don't bother to look at any more array elements. */ - done: if (GEO_SURROUND(&scx->scx_area, &def->cd_bbox)) return 2; else return 0; } int -drcCountFunc2(tile, pCount) - Tile *tile; /* Tile found in error plane. */ - int *pCount; /* Address of count word. */ +drcCountFunc2(tile, countptr) + Tile *tile; /* Tile found in error plane. */ + int *countptr; /* Address of count word. */ { - if (TiGetType(tile) != (TileType) TT_SPACE) *pCount += 1; + if (TiGetType(tile) != (TileType) TT_SPACE) (*countptr)++; return 0; } - + /* * ---------------------------------------------------------------------------- * @@ -963,13 +972,15 @@ drcFindFunc(scx, finddata) CellDef *def; HashEntry *h; int drcFindFunc2(); + bool dereference; def = scx->scx_use->cu_def; h = HashFind(finddata->deft, (char *)def); if (HashGetValue(h) != 0) return 0; HashSetValue(h, 1); - (void) DBCellRead(def, (char *) NULL, TRUE, NULL); + dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + (void) DBCellRead(def, (char *) NULL, TRUE, dereference, NULL); if (DBSrPaintArea((Tile *) NULL, def->cd_planes[PL_DRC_ERROR], &def->cd_bbox, &DBAllButSpaceBits, drcFindFunc2, diff --git a/drc/DRCsubcell.c b/drc/DRCsubcell.c index ae53645d..65be4bdf 100644 --- a/drc/DRCsubcell.c +++ b/drc/DRCsubcell.c @@ -56,7 +56,7 @@ static DRCCookie drcSubcellCookie = { 0, 0, 0, 0, { 0 }, { 0 }, 0, 0, 0, - "This layer can't abut or partially overlap between subcells", + DRC_SUBCELL_OVERLAP_TAG, (DRCCookie *) NULL }; diff --git a/drc/DRCtech.c b/drc/DRCtech.c index 62c09066..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 @@ -61,6 +62,11 @@ global int DRCRuleOptimization = TRUE; static int drcRulesSpecified = 0; static int drcRulesOptimized = 0; +/* Rules with unique names are tagged with a reference number */ +/* for use in placing errors into the DRC error plane. */ + +static int DRCtag = 0; + /* * Forward declarations. */ @@ -281,21 +287,14 @@ drcTechFreeStyle() dp = DRCCurStyle->DRCRulesTbl[i][j]; while (dp != NULL) { - char *old = (char *) dp; + char *old = (char *)dp; dp = dp->drcc_next; freeMagic(old); } } - /* Clear the DRCWhyList */ - - while (DRCCurStyle->DRCWhyList != NULL) - { - old = (char *) DRCCurStyle->DRCWhyList; - StrDup(&(DRCCurStyle->DRCWhyList->dwl_string), (char *) NULL); - DRCCurStyle->DRCWhyList = DRCCurStyle->DRCWhyList->dwl_next; - freeMagic(old); - } + /* Clear the Why string list */ + freeMagic(DRCCurStyle->DRCWhyList); freeMagic(DRCCurStyle); DRCCurStyle = NULL; @@ -329,31 +328,55 @@ drcTechNewStyle() /* * ---------------------------------------------------------------------------- - * drcWhyDup -- + * drcWhyCreate -- * - * Duplicate a shared "why" string using StrDup() and remember it so we can - * free it sometime later, in drcWhyClear(). + * Create a hash entry for the DRC "why" string, if it does not already + * exist. * * Returns: - * A copy of the given string. + * A pointer to the drcWhy structure containing the string and tag. * * Side effects: - * Adds to the DRCWhyList. Calls StrDup(). + * Adds to the DRCWhyList if whystring has not been used before. + * Calls StrDup() and increments DRCWhySize. DRCWhyList is allocated + * in blocks of 50 at a time and only expands when filled. + * Temporary hash table DRCWhyErrorTable is used to determine if a + * string entry is unique. It is cleared after the technology file + * has been processed. * ---------------------------------------------------------------------------- */ -char * -drcWhyDup(why) - char * why; +int +drcWhyCreate(whystring) + char *whystring; { - struct drcwhylist * new; + HashEntry *he; - new = (struct drcwhylist *) mallocMagic((unsigned) (sizeof *new)); - new->dwl_string = StrDup((char **) NULL, why); - new->dwl_next = DRCCurStyle->DRCWhyList; - DRCCurStyle->DRCWhyList = new; + he = HashLookOnly(&DRCWhyErrorTable, whystring); + if (he != NULL) + return (int)((pointertype)HashGetValue(he)); - return new->dwl_string; + /* Grow the list in increments of 50 */ + if ((DRCCurStyle->DRCWhySize % 50) == 0) + { + int i; + char **newList; + newList = (char **)mallocMagic((DRCCurStyle->DRCWhySize + 51) * sizeof(char *)); + newList[0] = (char *)NULL; + for (i = 1; i <= DRCCurStyle->DRCWhySize; i++) + newList[i] = DRCCurStyle->DRCWhyList[i]; + if (DRCCurStyle->DRCWhySize > 0) + freeMagic((char *)DRCCurStyle->DRCWhyList); + DRCCurStyle->DRCWhyList = newList; + } + DRCCurStyle->DRCWhySize++; + + he = HashFind(&DRCWhyErrorTable, whystring); + HashSetValue(he, (char *)((pointertype)DRCCurStyle->DRCWhySize)); + + DRCCurStyle->DRCWhyList[DRCCurStyle->DRCWhySize] = StrDup((char **)NULL, whystring); + + return DRCCurStyle->DRCWhySize; } /* @@ -535,12 +558,29 @@ DRCTechStyleInit() DRCCurStyle->ds_status = TECH_NOT_LOADED; TTMaskZero(&DRCCurStyle->DRCExactOverlapTypes); - DRCCurStyle->DRCWhyList = NULL; DRCCurStyle->DRCTechHalo = 0; DRCCurStyle->DRCScaleFactorN = 1; DRCCurStyle->DRCScaleFactorD = 1; DRCCurStyle->DRCStepSize = 0; DRCCurStyle->DRCFlags = (char)0; + DRCCurStyle->DRCWhySize = 0; + + HashInit(&DRCWhyErrorTable, 16, HT_STRINGKEYS); + + /* First DRC entry is associated with the statically-allocated */ + /* drcArrayCookie and has a tag of DRC_ARRAY_OVERLAP_TAG = 1 */ + /* (see DRCarray.c). */ + drcWhyCreate("This layer can't abut or partially overlap between array elements"); + + /* Second DRC entry is associated with the statically-allocated */ + /* drcOverlapCookie and has a tag of DRC_OVERLAP_TAG = 2 */ + /* (see DRCbasic.c). */ + drcWhyCreate("Can't overlap those layers"); + + /* Third DRC entry is associated with the statically-allocated */ + /* drcSubcellCookie and has a tag of DRC_SUBCELL_OVERLAP_TAG = 3 */ + /* (see DRCsubcell.c). */ + drcWhyCreate("This layer can't abut or partially overlap between subcells"); DRCTechHalo = 0; @@ -872,22 +912,18 @@ DRCTechLine(sectionName, argc, argv) } void -drcAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefrom) +drcCifAssign(cookie, dist, next, mask, corner, tag, cdist, flags, planeto, planefrom) DRCCookie *cookie, *next; int dist, cdist; TileTypeBitMask *mask, *corner; - char *why; + int tag; int flags, planeto, planefrom; { - /* Diagnostic */ - if (planeto >= DBNumPlanes) { - TxError("Bad plane in DRC assign!\n"); - } (cookie)->drcc_dist = dist; (cookie)->drcc_next = next; (cookie)->drcc_mask = *mask; (cookie)->drcc_corner = *corner; - (cookie)->drcc_why = why; + (cookie)->drcc_tag = tag; (cookie)->drcc_cdist = cdist; (cookie)->drcc_flags = flags; (cookie)->drcc_edgeplane = planefrom; @@ -896,6 +932,27 @@ drcAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefro (cookie)->drcc_cmod = 0; } +// This is like drcCifAssign, but checks for bad plane numbers in planeto and +// planefrom + +void +drcAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, planefrom) + DRCCookie *cookie, *next; + int dist, cdist; + TileTypeBitMask *mask, *corner; + int why; + int flags, planeto, planefrom; +{ + /* Diagnostic */ + if (planeto >= DBNumPlanes) + TechError("Bad plane in DRC assignment.\n"); + if (planefrom >= DBNumPlanes) + TechError("Bad edge plane in DRC assignment.\n"); + + drcCifAssign(cookie, dist, next, mask, corner, why, cdist, flags, planeto, + planefrom); +} + /* * ---------------------------------------------------------------------------- * @@ -1071,7 +1128,7 @@ drcExtend(argc, argv) char *layers1 = argv[1]; char *layers2 = argv[2]; int distance = atoi(argv[3]); - char *why; + int why; TileTypeBitMask set1, setC; DRCCookie *dp, *dpnew, *dptrig; TileType i, j; @@ -1083,10 +1140,10 @@ drcExtend(argc, argv) if (!strncmp(argv[4], "exact_", 6)) { exact = TRUE; - why = drcWhyDup(argv[5]); + why = drcWhyCreate(argv[5]); } else - why = drcWhyDup(argv[4]); + why = drcWhyCreate(argv[4]); ptest = DBTechNoisyNameMask(layers1, &set1); pMask1 = CoincidentPlanes(&set1, ptest); @@ -1240,7 +1297,7 @@ drcWidth(argc, argv) { char *layers = argv[1]; int distance = atoi(argv[2]); - char *why = drcWhyDup(argv[3]); + int why = drcWhyCreate(argv[3]); TileTypeBitMask set, setC; PlaneMask pmask, pset, ptest; DRCCookie *dp, *dpnew; @@ -1325,7 +1382,7 @@ drcArea(argc, argv) char *layers = argv[1]; int distance = atoi(argv[2]); int horizon = atoi(argv[3]); - char *why = drcWhyDup(argv[4]); + int why = drcWhyCreate(argv[4]); TileTypeBitMask set, setC; DRCCookie *dp, *dpnew; TileType i, j; @@ -1425,7 +1482,7 @@ drcMaxwidth(argc, argv) char *layers = argv[1]; int distance = atoi(argv[2]); char *bends = argv[3]; - char *why; + int why; TileTypeBitMask set, setC; DRCCookie *dp, *dpnew; TileType i, j; @@ -1452,7 +1509,7 @@ drcMaxwidth(argc, argv) bend = 0; else bend = DRC_BENDS; - why = drcWhyDup(argv[3]); + why = drcWhyCreate(argv[3]); } else { @@ -1463,7 +1520,7 @@ drcMaxwidth(argc, argv) TechError("unknown bend option %s\n",bends); return (0); } - why = drcWhyDup(argv[4]); + why = drcWhyCreate(argv[4]); } for (i = 0; i < DBNumTypes; i++) @@ -1514,7 +1571,7 @@ drcAngles(argc, argv) { char *layers = argv[1]; int angles = atoi(argv[2]); - char *why = drcWhyDup(argv[3]); + int why = drcWhyCreate(argv[3]); TileTypeBitMask set; DRCCookie *dp, *dpnew; int plane; @@ -1582,7 +1639,7 @@ drcSpacing3(argc, argv) char *layers3 = argv[5]; int distance = atoi(argv[3]); char *adjacency = argv[4]; - char *why = drcWhyDup(argv[6]); + int why = drcWhyCreate(argv[6]); TileTypeBitMask set1, set2, set3; int plane; DRCCookie *dp, *dpnew; @@ -2134,7 +2191,7 @@ drcSpacing(argc, argv) { char *layers1 = argv[1], *layers2; char *adjacency; - char *why; + int why; TileTypeBitMask set1, set2, tmp1, tmp2; PlaneMask pmask1, pmask2, pmaskA, pmaskB, ptest; int wwidth, distance, plane, plane2, runlength; @@ -2155,7 +2212,7 @@ drcSpacing(argc, argv) layers2 = argv[4]; distance = atoi(argv[5]); adjacency = argv[6]; - why = drcWhyDup(argv[7]); + why = drcWhyCreate(argv[7]); } else { @@ -2163,7 +2220,7 @@ drcSpacing(argc, argv) distance = atoi(argv[4]); runlength = distance; adjacency = argv[5]; - why = drcWhyDup(argv[6]); + why = drcWhyCreate(argv[6]); } /* TxPrintf("Info: DRCtech: widespacing rule for %s width %d:" " spacing must be %d\n", layers1, wwidth, distance); */ @@ -2174,7 +2231,7 @@ drcSpacing(argc, argv) distance = atoi(argv[3]); adjacency = argv[4]; wwidth = distance; - why = drcWhyDup(argv[5]); + why = drcWhyCreate(argv[5]); runlength = distance; if (argc >= 7) { @@ -2308,7 +2365,7 @@ drcEdge(argc, argv) int distance = atoi(argv[3]); char *okTypes = argv[4], *cornerTypes = argv[5]; int cdist = atoi(argv[6]); - char *why = drcWhyDup(argv[7]); + int why = drcWhyCreate(argv[7]); bool fourway = (strcmp(argv[0], "edge4way") == 0); TileTypeBitMask set1, set2, setC, setM; DRCCookie *dp, *dpnew; @@ -2474,7 +2531,7 @@ drcOverhang(argc, argv) { char *layers2 = argv[1], *layers1 = argv[2]; int distance = atoi(argv[3]); - char *why = drcWhyDup(argv[4]); + int why = drcWhyCreate(argv[4]); TileTypeBitMask set1, set2, setM, setC, setN, set2inv; DRCCookie *dp, *dpnew, *dptrig; int plane, plane2; @@ -2610,7 +2667,7 @@ drcRectOnly(argc, argv) char *argv[]; { char *layers = argv[1]; - char *why = drcWhyDup(argv[2]); + int why = drcWhyCreate(argv[2]); TileTypeBitMask set1, set2, setC; PlaneMask pmask, pset, ptest; DRCCookie *dp, *dpnew; @@ -2710,7 +2767,7 @@ drcSurround(argc, argv) char *layers1 = argv[1], *layers2 = argv[2]; int distance = atoi(argv[3]); char *presence = argv[4]; - char *why = drcWhyDup(argv[5]); + int why = drcWhyCreate(argv[5]); TileTypeBitMask set1, set2, setM, invM, setR; DRCCookie *dp, *dpnew, *dptrig; int plane1, plane2; @@ -3083,7 +3140,7 @@ drcRectangle(argc, argv) char *argv[]; { char *layers = argv[1]; - char *why = drcWhyDup(argv[4]); + int why = drcWhyCreate(argv[4]); TileTypeBitMask types, nottypes; int maxwidth; static char *drcRectOpt[4] = {"any", "even", "odd", 0}; @@ -3449,6 +3506,9 @@ drcTechFinalStyle(style) DRCCookie **dpp, **dp2back; TileType i, j; + /* Done with DRCWhyErrorTable */ + HashKill(&DRCWhyErrorTable); + /* If the scale factor is not 1, then divide all distances by */ /* the scale factor, take the ceiling, and save the (negative) */ /* remainder. */ @@ -3570,7 +3630,6 @@ drcTechFinalStyle(style) } else { - /* Don't free the shared drcc_why string here! */ freeMagic((char *)dptest); drcRulesOptimized++; } @@ -3665,7 +3724,8 @@ drcTechFinalStyle(style) /* TxPrintf("For edge %s-%s, \"%s\" covers \"%s\"\n", DBTypeShortName(i), DBTypeShortName(j), - next->drcc_why, dp->drcc_why); + DRCCurStyle->DRCWhyList[next->drcc_tag], + DRCCurStyle->DRCWhyList[dp->drcc_tag]); */ dp2back = &(style->DRCRulesTbl[i][j]); while (*dp2back != dp) @@ -3687,7 +3747,6 @@ drcTechFinalStyle(style) else *dp2back = dp->drcc_next; - /* Don't free the shared drcc_why string here! */ freeMagic((char *) dp); drcRulesOptimized += 1; } diff --git a/drc/drc.h b/drc/drc.h index 0ca8847a..aa3c5def 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. */ @@ -129,9 +134,9 @@ typedef struct drcpendingcookie typedef struct drccountlist { - CellDef *dcl_def; - int dcl_count; - struct drccountlist *dcl_next; + CellDef *dcl_def; + int dcl_count; + struct drccountlist *dcl_next; } DRCCountList; /* Structure used to keep information about the current DRC style */ @@ -142,22 +147,6 @@ typedef struct drckeep char *ds_name; } DRCKeep; -/* - * DRC "why" strings are potentially referred to hundreds of times by - * DRC cookies in the rule table. Rather than creating hundreds of - * copies of each string, we create just one copy and let all the cookies - * point to that one copy. - * - * Since we can't free these shared "why" strings when we delete a cookie, - * we keep a list of these strings and free them all when convenient. - */ - -typedef struct drcwhylist -{ - char * dwl_string; - struct drcwhylist * dwl_next; -} drcWhyList; - /* * Structure defining a DRC style */ @@ -173,7 +162,8 @@ typedef struct drcstyle int DRCTechHalo; /* largest action distance of design rules */ int DRCStepSize; /* chunk size for decomposing large areas */ char DRCFlags; /* Option flags */ - drcWhyList *DRCWhyList; + char **DRCWhyList; /* Indexed list of "why" text strings */ + int DRCWhySize; /* Length of DRCWhyList */ PaintResultType DRCPaintTable[NP][NT][NT]; } DRCStyle; @@ -239,6 +229,9 @@ extern void drcPrintError(); extern int drcIncludeArea(); extern int drcExactOverlapTile(); extern void drcInitRulesTbl(); +extern void drcAssign(); +extern void drcCifAssign(); +extern int drcWhyCreate(); /* * Exported procedures 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/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/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/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index e5686cbf..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; } @@ -1572,27 +1570,39 @@ esMakePorts(hc, cdata) while (tptr != NULL) { - /* Ignore array information for the purpose of tracing */ - /* the cell definition hierarchy. */ + int idum[6]; + bool is_array; - aptr = strchr(portname, '['); - if ((aptr == NULL) || (aptr > tptr)) - *tptr = '\0'; - else - *aptr = '\0'; + /* Ignore array information for the purpose of tracing */ + /* the cell definition hierarchy. If a cell use name */ + /* contains a bracket, check first if the complete name */ + /* matches a use. If not, then check if the part */ + /* the last opening bracket matches a known use. */ + + aptr = strrchr(portname, '['); + *tptr = '\0'; + is_array = FALSE; + if (aptr != NULL) + { + he = HashLookOnly(&updef->def_uses, portname); + if (he == NULL) + { + *aptr = '\0'; + is_array = TRUE; + } + } // Find the cell for the instance portdef = NULL; - he = HashFind(&updef->def_uses, portname); + he = HashLookOnly(&updef->def_uses, portname); if (he != NULL) { use = (Use *)HashGetValue(he); portdef = use->use_def; } - if ((aptr == NULL) || (aptr > tptr)) - *tptr = '/'; - else + if (is_array) *aptr = '['; + *tptr = '/'; portname = tptr + 1; // Find the net of portname in the subcell and @@ -1613,6 +1623,10 @@ esMakePorts(hc, cdata) { nn->efnn_node->efnode_flags |= EF_PORT; nn->efnn_port = -1; // Will be sorted later + + // Diagnostic + // TxPrintf("Port connection in %s from net %s to net %s (%s)\n", + // def->def_name, locname, name, portname); } } @@ -1622,9 +1636,6 @@ esMakePorts(hc, cdata) updef = portdef; } - // Diagnostic - // TxPrintf("Connection in %s to net %s (%s)\n", def->def_name, - // name, portname); } } @@ -1644,34 +1655,46 @@ esMakePorts(hc, cdata) // In particular, this keeps parasitics out of the netlist for // LVS purposes if "cthresh" is set to "infinite". - if (fabs((double)conn->conn_cap) < EFCapThreshold) continue; + if (fabs((double)conn->conn_cap / 1000) < EFCapThreshold) continue; portname = name; updef = def; while (tptr != NULL) { + int idum[6]; + bool is_array; + /* Ignore array information for the purpose of tracing */ /* the cell definition hierarchy. */ aptr = strchr(portname, '['); - if ((aptr == NULL) || (aptr > tptr)) - *tptr = '\0'; - else + if (aptr && (aptr < tptr) && + (sscanf(aptr, "[%d:%d:%d][%d:%d:%d]", + &idum[0], &idum[1], &idum[2], + &idum[3], &idum[4], &idum[5]) == 6)) + { *aptr = '\0'; + is_array = TRUE; + } + else + { + *tptr = '\0'; + is_array = FALSE; + } // Find the cell for the instance portdef = NULL; - he = HashFind(&updef->def_uses, portname); + he = HashLookOnly(&updef->def_uses, portname); if (he != NULL) { use = (Use *)HashGetValue(he); portdef = use->use_def; } - if ((aptr == NULL) || (aptr > tptr)) - *tptr = '/'; - else + if (is_array) *aptr = '['; + else + *tptr = '/'; portname = tptr + 1; // Find the net of portname in the subcell and @@ -1747,7 +1770,8 @@ esHierVisit(hc, cdata) if (def != topdef) { - if ((def->def_devs == NULL) && (HashGetNumEntries(&def->def_uses) == 0)) + if ((HashGetNumEntries(&def->def_devs) == 0) && + (HashGetNumEntries(&def->def_uses) == 0)) { if (locDoSubckt == AUTO) { @@ -1859,6 +1883,9 @@ esHierVisit(hc, cdata) EFHierVisitNodes(hcf, spcnodeHierVisit, (ClientData) NULL); freeMagic(resstr); } + + /* Reset device merge index for next cell */ + if (esMergeDevsA || esMergeDevsC) esFMIndex = 0; } if ((def != topdef) || (def->def_flags & DEF_SUBCIRCUIT) || (locDoSubckt == TRUE)) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 6947027a..94b2eb53 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 = ':'; @@ -257,7 +264,8 @@ CmdExtToSpice(w, cmd) "extresist [on|off] incorporate information from extresist", "resistor tee [on|off] model resistor capacitance as a T-network", "scale [on|off] use .option card for scaling", - "subcircuits [on|off] standard cells become subcircuit calls", + "subcircuits [top|descend] [on|off|auto]\n" + " standard cells become subcircuit calls", "hierarchy [on|off] output hierarchical spice for LVS", "blackbox [on|off] output abstract views as black-box entries", "renumber [on|off] on = number instances X1, X2, etc.\n" @@ -607,7 +615,7 @@ CmdExtToSpice(w, cmd) case EXTTOSPC_DEFAULT: LocCapThreshold = 2; LocResistThreshold = INFINITE_THRESHOLD; - EFTrimFlags = EF_CONVERTCOMMAS | EF_CONVERTEQUAL; + EFTrimFlags = EF_CONVERTCOMMA | EF_CONVERTEQUAL; EFScale = 0.0; if (EFArgTech) { @@ -821,7 +829,7 @@ runexttospice: // This forces options TRIMGLOB and CONVERTEQUAL, not sure that's such a // good idea. . . - EFTrimFlags |= EF_TRIMGLOB | EF_CONVERTEQUAL; + EFTrimFlags |= EF_TRIMGLOB | EF_CONVERTEQUAL | EF_CONVERTCOMMA; if (IS_FINITE_F(EFCapThreshold)) flatFlags |= EF_FLATCAPS; if (esFormat == HSPICE) EFTrimFlags |= EF_TRIMLOCAL; @@ -1140,6 +1148,17 @@ spcmainArgs(pargc, pargv) char **argv = *pargv, *cp; int argc = *pargc; + char usage_text[] = "Usage: ext2spice " + "[-B] [-o spicefile] [-M|-m] [-y cap_digits] " + "[-J flat|hier]\n" + "[-f spice2|spice3|hspice|ngspice] [-M] [-m] " +#ifdef MAGIC_WRAPPER + "[file]\n"; +#else + "[-j device:sdRclass[/subRclass]/defaultSubstrate]\n" + "file\n\n or else see options to extcheck(1)\n"; +#endif + switch (argv[0][1]) { case 'd': @@ -1236,6 +1255,9 @@ spcmainArgs(pargc, pargv) break; } #endif /* MAGIC_WRAPPER */ + case 'h': /* -h or -help, as suggested by "ext2spice help" */ + TxPrintf(usage_text); + break; default: TxError("Unrecognized flag: %s\n", argv[0]); goto usage; @@ -1246,16 +1268,7 @@ spcmainArgs(pargc, pargv) return 0; usage: - TxError("Usage: ext2spice [-B] [-o spicefile] [-M|-m] [-y cap_digits] " - "[-J flat|hier]\n" - "[-f spice2|spice3|hspice] [-M] [-m] " -#ifdef MAGIC_WRAPPER - "[file]\n" -#else - "[-j device:sdRclass[/subRclass]/defaultSubstrate]\n" - "file\n\n or else see options to extcheck(1)\n" -#endif - ); + TxError(usage_text); #ifdef MAGIC_WRAPPER return 1; @@ -1359,10 +1372,11 @@ subcktVisit(use, hierName, is_top) EFNode *snode; Def *def = use->use_def; EFNodeName *nodeName; - int portorder, portmax, imp_max, tchars; + int portorder, portmax, portidx, imp_max, tchars; char stmp[MAX_STR_SIZE]; char *instname, *subcktname; DevParam *plist, *pptr; + EFNodeName **nodeList; if (is_top == TRUE) return 0; /* Ignore the top-level cell */ @@ -1379,7 +1393,7 @@ subcktVisit(use, hierName, is_top) else { int savflags = EFTrimFlags; - EFTrimFlags = 0; // Do no substitutions on subcircuit names + EFTrimFlags = EF_CONVERTCOMMA; // Only substitute commas on subcircuit names /* Use full hierarchical decomposition for name */ /* (not just use->use_id. hierName already has use->use_id at end) */ @@ -1454,35 +1468,58 @@ subcktVisit(use, hierName, is_top) /* Port numbers need not start at zero or be contiguous. */ /* They will be printed in numerical order. */ - portorder = 0; - while (portorder <= portmax) - { - for (snode = (EFNode *) def->def_firstn.efnode_next; + nodeList = (EFNodeName **)mallocMagic((portmax + 1) * sizeof(EFNodeName *)); + for (portidx = 0; portidx <= portmax; portidx++) + nodeList[portidx] = (EFNodeName *)NULL; + + for (snode = (EFNode *) def->def_firstn.efnode_next; snode != &def->def_firstn; snode = (EFNode *) snode->efnode_next) - { - if (!(snode->efnode_flags & EF_PORT)) continue; - for (nodeName = snode->efnode_name; nodeName != NULL; + { + if (!(snode->efnode_flags & EF_PORT)) continue; + for (nodeName = snode->efnode_name; nodeName != NULL; nodeName = nodeName->efnn_next) + { + EFNodeName *nn; + HashEntry *he; + char *pname; + + portidx = nodeName->efnn_port; + if (portidx < 0) continue; + if (nodeList[portidx] == NULL) { - int portidx = nodeName->efnn_port; - if (portidx == portorder) - { - if (tchars > 80) - { - fprintf(esSpiceF, "\n+"); - tchars = 1; - } - tchars += spcdevOutNode(hierName, nodeName->efnn_hier, - "subcircuit", esSpiceF); - break; - } + nodeList[portidx] = nodeName; + } + else if (EFHNBest(nodeName->efnn_hier, nodeList[portidx]->efnn_hier)) + { + nodeList[portidx] = nodeName; } - if (nodeName != NULL) break; } - portorder++; } + for (portidx = 0; portidx <= portmax; portidx++) + { + nodeName = nodeList[portidx]; + + if (nodeName != NULL) + { + if (tchars > 80) + { + fprintf(esSpiceF, "\n+"); + tchars = 1; + } + tchars += spcdevOutNode(hierName, nodeName->efnn_hier, + "subcircuit", esSpiceF); + } + else + { + // As port indexes do not have to be contiguous, this does not + // necessarily indicate an error condition. No need to report? + // TxError("No port connection on port %d; need to resolve.\n", portidx); + } + } + freeMagic(nodeList); + /* Look for all implicit substrate connections that are */ /* declared as local node names, and put them last. */ @@ -1602,7 +1639,7 @@ topVisit(def, doStub) Def *def; bool doStub; { - EFNode *snode; + EFNode *snode, *basenode; EFNodeName *sname, *nodeName; HashSearch hs; HashEntry *he; @@ -1655,7 +1692,9 @@ topVisit(def, doStub) snode = sname->efnn_node; if (snode->efnode_flags & EF_PORT) - if (snode->efnode_name->efnn_port < 0) + { + pname = nodeSpiceName(snode->efnode_name->efnn_hier, &basenode); + if (basenode->efnode_name->efnn_port < 0) { if (tchars > 80) { @@ -1663,11 +1702,12 @@ topVisit(def, doStub) fprintf(esSpiceF, "\n+"); tchars = 1; } - pname = nodeSpiceName(snode->efnode_name->efnn_hier); fprintf(esSpiceF, " %s", pname); tchars += strlen(pname) + 1; - snode->efnode_name->efnn_port = portorder++; + basenode->efnode_name->efnn_port = portorder++; } + snode->efnode_name->efnn_port = basenode->efnode_name->efnn_port; + } } } else @@ -1681,6 +1721,7 @@ topVisit(def, doStub) HashStartSearch(&hs); while (he = HashNext(&def->def_nodes, &hs)) { + char stmp[MAX_STR_SIZE]; int portidx; EFNodeName *unnumbered; @@ -1701,7 +1742,17 @@ topVisit(def, doStub) fprintf(esSpiceF, "\n+"); tchars = 1; } - pname = nodeSpiceName(snode->efnode_name->efnn_hier); + // If view is abstract, rely on the given port name, not + // the node. Otherwise, artifacts of the abstract view + // may cause nodes to be merged and the names lost. + + if (def->def_flags & DEF_ABSTRACT) + { + EFHNSprintf(stmp, nodeName->efnn_hier); + pname = stmp; + } + else + pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL); fprintf(esSpiceF, " %s", pname); tchars += strlen(pname) + 1; break; @@ -2083,6 +2134,56 @@ esOutputResistor(dev, hierName, scale, term1, term2, has_model, l, w, dscale) } } +/* Report if device at index n has been deleted due to merging */ + +bool +devIsKilled(n) + int n; +{ + return (esFMult[(n)] <= (float)0.0) ? TRUE : FALSE; +} + +/* Add a dev's multiplier to the table and grow it if necessary */ + +void +addDevMult(f) + float f; +{ + int i; + float *op; + + if (esFMult == NULL) { + esFMult = (float *) mallocMagic((unsigned) (esFMSize*sizeof(float))); + } + else if (esFMIndex >= esFMSize) + { + op = esFMult; + esFMSize *= 2; + esFMult = (float *)mallocMagic((unsigned)(esFMSize * sizeof(float))); + for (i = 0; i < esFMSize / 2; i++) esFMult[i] = op[i]; + if (op) freeMagic(op); + } + esFMult[esFMIndex++] = f; +} + +/* Set the multiplier value f of device at index i */ + +void +setDevMult(i, f) + int i; + float f; +{ + esFMult[i] = f; +} + +/* Get the multiplier value of the device at the current index esFMIndex */ + +float +getCurDevMult() +{ + return (esFMult && (esFMIndex > 0)) ? esFMult[esFMIndex-1] : (float)1.0; +} + /* * ---------------------------------------------------------------------------- * @@ -2708,13 +2809,16 @@ FILE *outf; /* Canonical name */ nn = (EFNodeName *) HashGetValue(he); if (outf) - fprintf(outf, "%s", nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier)); + fprintf(outf, "%s", nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier, + NULL)); /* Mark node as visited */ if ((nodeClient *)nn->efnn_node->efnode_client == (ClientData)NULL) initNodeClientHier(nn->efnn_node); - ((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= DEV_CONNECT_MASK; + if (!esDistrJunct) + ((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= + DEV_CONNECT_MASK; return nn->efnn_node; } } @@ -2769,7 +2873,14 @@ int spcnAP(node, resClass, scale, asterm, psterm, m, outf, w) if (!esDistrJunct || w == -1) goto oldFmt; - dsc = w / ((nodeClient*)node->efnode_client)->m_w.widths[resClass]; + if (((nodeClient*)node->efnode_client)->m_w.widths != NULL) + dsc = w / ((nodeClient*)node->efnode_client)->m_w.widths[resClass]; + else + { + TxError("Device missing records for source/drain area/perim.\n"); + dsc = w; + } + if (esScale < 0) { if (asterm) @@ -2917,10 +3028,13 @@ spcdevOutNode(prefix, suffix, name, outf) return 0; } nn = (EFNodeName *) HashGetValue(he); - nname = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier); + nname = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier, NULL); fprintf(outf, " %s", nname); + /* Mark node as visited */ - ((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= DEV_CONNECT_MASK; + if (!esDistrJunct) + ((nodeClient *)nn->efnn_node->efnode_client)->m_w.visitMask |= DEV_CONNECT_MASK; + return (1 + strlen(nname)); } @@ -2960,8 +3074,8 @@ spccapVisit(hierName1, hierName2, cap) if (cap <= EFCapThreshold) return 0; - fprintf(esSpiceF, esSpiceCapFormat ,esCapNum++,nodeSpiceName(hierName1), - nodeSpiceName(hierName2), cap); + fprintf(esSpiceF, esSpiceCapFormat ,esCapNum++,nodeSpiceName(hierName1, NULL), + nodeSpiceName(hierName2, NULL), cap); return 0; } @@ -2996,8 +3110,8 @@ spcresistVisit(hierName1, hierName2, res) HierName *hierName2; float res; { - fprintf(esSpiceF, "R%d %s %s %g\n", esResNum++, nodeSpiceName(hierName1), - nodeSpiceName(hierName2), res / 1000.); + fprintf(esSpiceF, "R%d %s %s %g\n", esResNum++, nodeSpiceName(hierName1, NULL), + nodeSpiceName(hierName2, NULL), res / 1000.); return 0; } @@ -3032,7 +3146,7 @@ spcsubVisit(node, res, cap, resstr) if (node->efnode_flags & EF_SUBS_NODE) { hierName = (HierName *) node->efnode_name->efnn_hier; - nsn = nodeSpiceName(hierName); + nsn = nodeSpiceName(hierName, NULL); *resstr = StrDup((char **)NULL, nsn); return 1; } @@ -3082,7 +3196,7 @@ spcnodeVisit(node, res, cap) if (!isConnected && node->efnode_flags & EF_PORT) isConnected = TRUE; hierName = (HierName *) node->efnode_name->efnn_hier; - nsn = nodeSpiceName(hierName); + nsn = nodeSpiceName(hierName, NULL); if (esFormat == SPICE2 || esFormat == HSPICE && strncmp(nsn, "z@", 2)==0 ) { static char ntmp[MAX_STR_SIZE]; @@ -3127,7 +3241,7 @@ nodeVisitDebug(node, res, cap) EFAttr *ap; hierName = (HierName *) node->efnode_name->efnn_hier; - nsn = nodeSpiceName(hierName); + nsn = nodeSpiceName(hierName, NULL); TxError("** %s (%x)\n", nsn, node); printf("\t client.name=%s, client.m_w=%p\n", @@ -3150,23 +3264,27 @@ nodeVisitDebug(node, res, cap) * * Side effects: * Allocates nodeClients for the node. + * Returns the node in the "rnode" pointer, if non-NULL. * * ---------------------------------------------------------------------------- */ static char esTempName[MAX_STR_SIZE]; -char *nodeSpiceName(hname) +char *nodeSpiceName(hname, rnode) HierName *hname; + EFNode **rnode; { EFNodeName *nn; HashEntry *he; EFNode *node; + if (rnode) *rnode = (EFNode *)NULL; he = EFHNLook(hname, (char *) NULL, "nodeName"); if ( he == NULL ) return "errGnd!"; nn = (EFNodeName *) HashGetValue(he); node = nn->efnn_node; + if (rnode) *rnode = node; if ( (nodeClient *) (node->efnode_client) == NULL ) { initNodeClient(node); @@ -3215,7 +3333,7 @@ EFHNSprintf(str, hierName) char *str; HierName *hierName; { - bool trimGlob, trimLocal, convertComma, convertEqual; + bool trimGlob, trimLocal, convertComma, convertEqual, convertBrackets; char *s, *cp, c; char *efHNSprintfPrefix(HierName *, char *); @@ -3226,8 +3344,9 @@ EFHNSprintf(str, hierName) cp = hierName->hn_name; trimGlob = (EFTrimFlags & EF_TRIMGLOB); trimLocal = (EFTrimFlags & EF_TRIMLOCAL); - convertComma = (EFTrimFlags & EF_CONVERTCOMMAS); + convertComma = (EFTrimFlags & EF_CONVERTCOMMA); convertEqual = (EFTrimFlags & EF_CONVERTEQUAL); + convertBrackets = (EFTrimFlags & EF_CONVERTBRACKETS); while (c = *cp++) { switch (c) @@ -3235,7 +3354,9 @@ EFHNSprintf(str, hierName) case '!': if (!trimGlob) *str++ = c; break; case '.': *str++ = (esFormat == HSPICE)?'@':'.'; break; case '=': if (convertEqual) *str++ = ':'; break; - case ',': if (convertComma) *str++ = ';'; break; + case ',': if (convertComma) *str++ = '|'; break; + case '[': *str++ = (convertBrackets) ? '_' : '['; break; + case ']': *str++ = (convertBrackets) ? '_' : ']'; break; case '#': if (trimLocal) break; // else fall through default: *str++ = c; break; } @@ -3252,6 +3373,8 @@ char *efHNSprintfPrefix(hierName, str) { char *cp, c; bool convertEqual = (EFTrimFlags & EF_CONVERTEQUAL) ? TRUE : FALSE; + bool convertComma = (EFTrimFlags & EF_CONVERTCOMMA) ? TRUE : FALSE; + bool convertBrackets = (EFTrimFlags & EF_CONVERTBRACKETS) ? TRUE : FALSE; if (hierName->hn_parent) str = efHNSprintfPrefix(hierName->hn_parent, str); @@ -3260,6 +3383,13 @@ char *efHNSprintfPrefix(hierName, str) while (1) { if (convertEqual && (*cp == '=')) *str = ':'; + else if (convertBrackets && ((*cp == '[') || (*cp == ']'))) + *str = '_'; + else if (*cp == ',') + { + if (convertComma) *str = '|'; + else str--; + } else *str = *cp; if (!(*str)) break; 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 diff --git a/extflat/Depend b/extflat/Depend index eed9d00d..e65b48e1 100644 --- a/extflat/Depend +++ b/extflat/Depend @@ -23,10 +23,16 @@ EFread.o: EFread.c ../tcltk/tclmagic.h ../utils/magic.h ../utils/malloc.h \ ../bplane/bplane.h ../bplane/bpOpaque.h ../utils/ihash.h \ ../bplane/bpEnum.h ../utils/geofast.h ../bplane/bplaneInt.h \ ../extflat/extflat.h ../extflat/EFint.h ../extract/extract.h \ - ../utils/paths.h + ../extract/extractInt.h ../extract/extDebugInt.h ../utils/paths.h EFsym.o: EFsym.c ../utils/magic.h ../utils/geometry.h ../utils/geofast.h \ ../utils/hash.h ../utils/malloc.h ../utils/utils.h ../extflat/extflat.h \ ../extflat/EFint.h EFvisit.o: EFvisit.c ../utils/magic.h ../utils/geometry.h \ ../utils/geofast.h ../utils/hash.h ../utils/malloc.h ../utils/utils.h \ ../extflat/extflat.h ../extflat/EFint.h ../extract/extract.h +EFantenna.o: EFantenna.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/geometry.h ../utils/hash.h ../utils/utils.h ../utils/styles.h \ + ../tiles/tile.h ../database/database.h ../windows/windows.h \ + ../textio/textio.h ../dbwind/dbwind.h ../textio/txcommands.h \ + ../extflat/extflat.h ../extract/extract.h ../extract/extractInt.h \ + ../extract/extDebugInt.h ../utils/malloc.h diff --git a/extflat/EFantenna.c b/extflat/EFantenna.c new file mode 100644 index 00000000..e7af529a --- /dev/null +++ b/extflat/EFantenna.c @@ -0,0 +1,844 @@ +/* + * EFantenna.c -- + * + * Program to flatten hierarchical .ext files and then execute an + * antenna violation check for every MOSFET device in the flattened + * design. + * + * Flattens the tree rooted at file.ext, reading in additional .ext + * files as specified by "use" lines in file.ext. + * + */ + +#include +#include /* for atof() */ +#include +#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" +#include "database/database.h" +#include "windows/windows.h" +#include "textio/textio.h" +#include "dbwind/dbwind.h" +#include "textio/txcommands.h" +#include "extflat/extflat.h" +#include "extract/extract.h" +#include "extract/extractInt.h" +#include "utils/malloc.h" + +/* Forward declarations */ +int antennacheckArgs(); +int antennacheckVisit(); + +typedef struct { + long visitMask:MAXDEVTYPES; +} nodeClient; + +typedef struct { + HierName *lastPrefix; + long visitMask:MAXDEVTYPES; +} nodeClientHier; + +#define NO_RESCLASS -1 + +#define markVisited(client, rclass) \ + { (client)->visitMask |= (1<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; \ +} + +/* Diagnostic */ +int efGates; +static int efAntennaDebug = FALSE; + +/* The extract file is designed to be independent of the magic database, */ +/* but that means that the device types do not match magic database types. */ +/* A lookup table is needed to cross-reference the device types. */ + +TileType *EFDeviceTypes; + +typedef struct _aas { + int *accum; /* Pointer to array of accumulated areas per type */ + int pNum; /* Plane of check */ + Rect r; /* Holds any one visited rectangle */ + CellDef *def; /* CellDef for adding feedback */ +} AntennaAccumStruct; + +typedef struct _gdas { + int accum; /* Accumulated area of all gates/diff */ + Rect r; /* Holds any one visited rectangle */ + CellDef *def; /* CellDef for adding feedback */ +} GateDiffAccumStruct; + +typedef struct _ams { + int pNum; /* Plane of check */ + CellDef *def; /* CellDef for adding feedback */ +} AntennaMarkStruct; + + +/* + * ---------------------------------------------------------------------------- + * + * Main Tcl callback for command "magic::antennacheck" + * + * ---------------------------------------------------------------------------- + */ + +#define ANTENNACHECK_RUN 0 +#define ANTENNACHECK_DEBUG 1 +#define ANTENNACHECK_HELP 2 + +void +CmdAntennaCheck(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int i, flatFlags; + char *inName; + FILE *f; + TileType t; + + int option = ANTENNACHECK_RUN; + int value; + int argc = cmd->tx_argc; + char **argv = cmd->tx_argv; + char **msg; + bool err_result; + + short sd_rclass; + short sub_rclass; + char *devname; + char *subname; + int idx; + + CellUse *editUse; + + static char *cmdAntennaCheckOption[] = { + "[run] [options] run antennacheck on current cell\n" + " use \"run -help\" to get standard options", + "debug print detailed information about each error", + "help print help information", + NULL + }; + + if (cmd->tx_argc > 1) + { + option = Lookup(cmd->tx_argv[1], cmdAntennaCheckOption); + if (option < 0) option = ANTENNACHECK_RUN; + else argv++; + } + + switch (option) + { + case ANTENNACHECK_RUN: + goto runantennacheck; + break; + case ANTENNACHECK_DEBUG: + efAntennaDebug = TRUE; + break; + case ANTENNACHECK_HELP: +usage: + for (msg = &(cmdAntennaCheckOption[0]); *msg != NULL; msg++) + { + TxPrintf(" %s\n", *msg); + } + break; + } + return; + +runantennacheck: + + if (ExtCurStyle->exts_planeOrderStatus == noPlaneOrder) + { + TxError("No planeorder specified for this process: " + "Cannot run antenna checks!\n"); + return; + } + + EFInit(); + EFCapThreshold = INFINITY; + EFResistThreshold = INFINITY; + + /* Process command line arguments */ + inName = EFArgs(argc, argv, &err_result, antennacheckArgs, (ClientData) NULL); + + if (err_result == TRUE) + { + EFDone(); + return /* TCL_ERROR */; + } + + if (inName == NULL) + { + /* Assume that we want to do exttospice on the currently loaded cell */ + + if (w == (MagWindow *) NULL) + windCheckOnlyWindow(&w, DBWclientID); + + if (w == (MagWindow *) NULL) + { + TxError("Point to a window or specify a cell name.\n"); + EFDone(); + return /* TCL_ERROR */; + } + inName = ((CellUse *) w->w_surfaceID)->cu_def->cd_name; + } + editUse = (CellUse *)w->w_surfaceID; + + /* + * Initializations specific to this program. + */ + + /* Read the hierarchical description of the input circuit */ + TxPrintf("Reading extract file.\n"); + if (EFReadFile(inName, FALSE, FALSE, FALSE) == FALSE) + { + EFDone(); + return /* TCL_ERROR */; + } + + /* Convert the hierarchical description to a flat one */ + flatFlags = EF_FLATNODES; + TxPrintf("Building flattened netlist.\n"); + EFFlatBuild(inName, flatFlags); + + /* Build device lookup table */ + EFDeviceTypes = (TileType *)mallocMagic(MAXDEVTYPES * sizeof(TileType)); + for (i = 0; i < MAXDEVTYPES; i++) + if (EFDevTypes[i]) + EFDeviceTypes[i] = extGetDevType(EFDevTypes[i]); + + efGates = 0; + TxPrintf("Running antenna checks.\n"); + EFVisitDevs(antennacheckVisit, (ClientData)editUse); + EFFlatDone(); + EFDone(); + + TxPrintf("antennacheck finished.\n"); + freeMagic(EFDeviceTypes); + efAntennaDebug = FALSE; +} + + +/* + * ---------------------------------------------------------------------------- + * + * antennacheckArgs -- + * + * Process those arguments that are specific to antennacheck. + * Assumes that *pargv[0][0] is '-', indicating a flag + * argument. + * + * Results: + * None. TCL version returns False if an error is encountered + * while parsing arguments, True otherwise. + * + * Side effects: + * After processing an argument, updates *pargc and *pargv + * to point to after the argument. + * + * May initialize various global variables based on the + * arguments given to us. + * + * Exits in the event of an improper argument. + * + * ---------------------------------------------------------------------------- + */ + +int +antennacheckArgs(pargc, pargv) + int *pargc; + char ***pargv; +{ + char **argv = *pargv, *cp; + int argc = *pargc; + + switch (argv[0][1]) + { + default: + TxError("Unrecognized flag: %s\n", argv[0]); + goto usage; + } + + *pargv = argv; + *pargc = argc; + return 0; + +usage: + TxError("Usage: antennacheck\n"); + return 1; +} + +/* + * ---------------------------------------------------------------------------- + * + * AntennaGetNode -- + * + * function to find a node given its hierarchical prefix and suffix + * + * Results: + * a pointer to the node struct or NULL + * + * ---------------------------------------------------------------------------- + */ +EFNode * +AntennaGetNode(prefix, suffix) +HierName *prefix; +HierName *suffix; +{ + HashEntry *he; + + he = EFHNConcatLook(prefix, suffix, "output"); + return(((EFNodeName *) HashGetValue(he))->efnn_node); +} + +/* + * ---------------------------------------------------------------------------- + * + * antennacheckVisit -- + * + * Procedure to check for antenna violations from a single device. + * Called by EFVisitDevs(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * May tag other device records to avoid double-counting devices. + * Generates feedback entries if an antenna violation is found. + * + * ---------------------------------------------------------------------------- + */ + +int +antennacheckVisit(dev, hierName, scale, trans, editUse) + Dev *dev; /* Device being output */ + HierName *hierName; /* Hierarchical path down to this device */ + float scale; /* Scale transform for output */ + Transform *trans; /* Coordinate transform */ + CellUse *editUse; /* ClientData is edit cell use */ +{ + DevTerm *gate; + TileType t, conType; + int pos, pNum, pNum2, pmax, p, i, j, gatearea, diffarea, total; + double anttotal; + float saveRatio, ratioTotal; + int *antennaarea; + Rect r, gaterect; + EFNode *gnode; + SearchContext scx; + TileTypeBitMask gatemask, saveConMask; + bool antennaError; + + extern CellDef *extPathDef; /* see extract/ExtLength.c */ + extern CellUse *extPathUse; /* see extract/ExtLength.c */ + + extern int areaAccumFunc(), antennaAccumFunc(), areaMarkFunc(); + + antennaarea = (int *)mallocMagic(DBNumTypes * sizeof(int)); + + switch(dev->dev_class) + { + case DEV_FET: + case DEV_MOSFET: + case DEV_MSUBCKT: + case DEV_ASYMMETRIC: + + /* Procedure: + * + * 1. If device gate node is marked visited, return. + * 2. Mark device gate node visited + * 3. For each plane from metal1 up (determined by planeorder): + * a. Run DBTreeCopyConnect() + * b. Accumulate gate area of connected devices + * c. Accumulate diffusion area of connected devices + * d. Accumulate metal area of connected devices + * e. Check against antenna ratio(s) + * f. Generate feedback if in violation of antenna rule + * + * NOTE: DBTreeCopyConnect() is used cumulatively, so that + * additional searching only needs to be done for the additional + * layer being searched. + */ + + GeoTransRect(trans, &dev->dev_rect, &r); + gate = &dev->dev_terms[0]; + gnode = AntennaGetNode(hierName, gate->dterm_node->efnode_name->efnn_hier); + if (gnode->efnode_client == (ClientData) NULL) + initNodeClient(gnode); + if (beenVisited((nodeClient *)gnode->efnode_client, 0)) + return 0; + else + markVisited((nodeClient *)gnode->efnode_client, 0); + + /* Diagnostic stuff */ + efGates++; + if (efGates % 100 == 0) TxPrintf(" %d gates analyzed.\n", efGates); + + /* Find the plane of the gate type */ + t = EFDeviceTypes[dev->dev_type]; + pNum = DBPlane(t); + pos = ExtCurStyle->exts_planeOrder[pNum]; + pmax = ++pos; + + /* Find the highest plane in the technology */ + for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++) + if (ExtCurStyle->exts_planeOrder[p] > pmax) + pmax = ExtCurStyle->exts_planeOrder[p]; + + /* Create the yank cell if it doesn't already exist */ + if (extPathDef == (CellDef *) NULL) + DBNewYank("__PATHYANK__", &extPathUse, &extPathDef); + + /* Use the cellDef reserved for extraction */ + /* DBCellClearDef(extPathDef); */ /* See below */ + scx.scx_use = editUse; + scx.scx_trans = GeoIdentityTransform; + scx.scx_area = r; + + /* gatemask is a mask of all gate types for MOSFET devices */ + + TTMaskZero(&gatemask); + for (i = 0; i < DBNumTypes; i++) + { + ExtDevice *ed; + char devclass; + + if (ExtCurStyle->exts_device[i] != NULL) + { + for (ed = ExtCurStyle->exts_device[i]; ed; ed = ed->exts_next) + { + devclass = ed->exts_deviceClass; + switch (devclass) + { + case DEV_MOSFET: + case DEV_FET: + case DEV_ASYMMETRIC: + case DEV_MSUBCKT: + TTMaskSetType(&gatemask, i); + break; + } + } + } + } + + for (; pos <= pmax; pos++) + { + GateDiffAccumStruct gdas; + AntennaAccumStruct aas; + AntennaMarkStruct ams; + + /* Find the plane of pos */ + + for (p = 0; p < DBNumPlanes; p++) + if (ExtCurStyle->exts_planeOrder[p] == pos) + pNum2 = p; + + /* Find the tiletype which is a contact and whose base is pNum2 */ + /* (NOTE: Need to extend to all such contacts, as there may be */ + /* more than one.) (Also should find these types up top, not */ + /* within the loop.) */ + + /* Modify DBConnectTbl to limit connectivity to the plane */ + /* of the antenna check and below */ + + conType = -1; + for (i = 0; i < DBNumTypes; i++) + if (DBIsContact(i) && DBPlane(i) == pNum2) + { + conType = i; + TTMaskZero(&saveConMask); + TTMaskSetMask(&saveConMask, &DBConnectTbl[i]); + TTMaskZero(&DBConnectTbl[i]); + for (j = 0; j < DBNumTypes; j++) + if (TTMaskHasType(&saveConMask, j) && + (DBPlane(j) <= pNum2)) + TTMaskSetType(&DBConnectTbl[i], j); + break; + } + + for (i = 0; i < DBNumTypes; i++) antennaarea[i] = 0; + gatearea = 0; + diffarea = 0; + + /* Note: Ideally, the addition of material in the next */ + /* metal plane is additive. But that requires enumerating */ + /* all the vias and using those as starting points for the */ + /* next connectivity search, which needs to be coded. */ + + DBCellClearDef(extPathDef); + + /* To do: Mark tiles so area count can be progressive */ + + DBTreeCopyConnect(&scx, &DBConnectTbl[t], 0, + DBConnectTbl, &TiPlaneRect, extPathUse); + + /* Search planes of tie types and accumulate all tiedown areas */ + gdas.accum = 0; + for (p = 0; p < DBNumPlanes; p++) + DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[p], + &TiPlaneRect, &ExtCurStyle->exts_antennaTieTypes, + areaAccumFunc, (ClientData)&gdas); + diffarea = gdas.accum; + + /* Search plane of gate type and accumulate all gate area */ + gdas.accum = 0; + DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[pNum], + &TiPlaneRect, &gatemask, areaAccumFunc, (ClientData)&gdas); + gatearea = gdas.accum; + + /* Search metal planes and accumulate all antenna areas */ + for (p = 0; p < DBNumPlanes; p++) + { + if (ExtCurStyle->exts_antennaModel & ANTENNAMODEL_PARTIAL) + if (p != pNum2) continue; + + aas.pNum = p; + aas.accum = &antennaarea[0]; + if (ExtCurStyle->exts_planeOrder[p] <= pos) + DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[p], + &TiPlaneRect, &DBAllButSpaceAndDRCBits, + antennaAccumFunc, (ClientData)&aas); + } + + antennaError = FALSE; + if (diffarea == 0) + { + anttotal = 0.0; + saveRatio = 0.0; + for (i = 0; i < DBNumTypes; i++) + { + if (ExtCurStyle->exts_antennaRatio[i].ratioGate > 0) + { + anttotal += (double)antennaarea[i] / + (double)ExtCurStyle->exts_antennaRatio[i].ratioGate; + } + if (ExtCurStyle->exts_antennaRatio[i].ratioGate > saveRatio) + saveRatio = ExtCurStyle->exts_antennaRatio[i].ratioGate; + } + + if (anttotal > (double)gatearea) + { + antennaError = TRUE; + if (efAntennaDebug == TRUE) + { + TxError("Antenna violation detected at plane %s\n", + DBPlaneLongNameTbl[pNum2]); + TxError("Effective antenna ratio %g > limit %g\n", + saveRatio * (float)anttotal / (float)gatearea, + saveRatio); + TxError("Gate rect (%d %d) to (%d %d)\n", + gdas.r.r_xbot, gdas.r.r_ybot, + gdas.r.r_xtop, gdas.r.r_ytop); + TxError("Antenna rect (%d %d) to (%d %d)\n", + aas.r.r_xbot, aas.r.r_ybot, + aas.r.r_xtop, aas.r.r_ytop); + } + } + } + else + { + anttotal = 0.0; + saveRatio = 0.0; + for (i = 0; i < DBNumTypes; i++) + if (ExtCurStyle->exts_antennaRatio[i].ratioDiffB != INFINITY) + { + ratioTotal = ExtCurStyle->exts_antennaRatio[i].ratioDiffB + + diffarea * ExtCurStyle->exts_antennaRatio[i].ratioDiffA; + + if (ratioTotal > 0) + anttotal += (double)antennaarea[i] / (double)ratioTotal; + if (ratioTotal > saveRatio) + saveRatio = ratioTotal; + } + + if (anttotal > (double)gatearea) + { + antennaError = TRUE; + if (efAntennaDebug == TRUE) + { + TxError("Antenna violation detected at plane %s\n", + DBPlaneLongNameTbl[pNum2]); + TxError("Effective antenna ratio %g > limit %g\n", + saveRatio * (float)anttotal / (float)gatearea, + saveRatio); + TxError("Gate rect (%d %d) to (%d %d)\n", + gdas.r.r_xbot, gdas.r.r_ybot, + gdas.r.r_xtop, gdas.r.r_ytop); + TxError("Antenna rect (%d %d) to (%d %d)\n", + aas.r.r_xbot, aas.r.r_ybot, + aas.r.r_xtop, aas.r.r_ytop); + } + } + } + + if (antennaError) + { + /* Search plane of gate type and mark all gate areas */ + ams.def = editUse->cu_def; + ams.pNum = pNum2; + DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[pNum], + &TiPlaneRect, &gatemask, areaMarkFunc, (ClientData)&ams); + + /* Search metal planes and accumulate all antenna areas */ + for (p = 0; p < DBNumPlanes; p++) + { + if (ExtCurStyle->exts_antennaModel & ANTENNAMODEL_PARTIAL) + if (p != pNum2) continue; + + if (ExtCurStyle->exts_planeOrder[p] <= pos) + DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[p], + &TiPlaneRect, &DBAllButSpaceAndDRCBits, + areaMarkFunc, (ClientData)&ams); + } + } + + /* Put the connect table back the way it was */ + if (conType >= 0) + TTMaskSetMask(&DBConnectTbl[conType], &saveConMask); + } + } + freeMagic(antennaarea); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * areaMarkFunc -- + * + * Mark the tile areas searched with feedback entries + * + * ---------------------------------------------------------------------------- + */ + +int +areaMarkFunc(tile, ams) + Tile *tile; + AntennaMarkStruct *ams; +{ + Rect rect; + char msg[200]; + + TiToRect(tile, &rect); + sprintf(msg, "Antenna error at plane %s\n", DBPlaneLongNameTbl[ams->pNum]); + DBWFeedbackAdd(&rect, msg, ams->def, 1, STYLE_PALEHIGHLIGHTS); + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * areaAccumFunc -- + * + * Accumulate the total tile area searched + * + * ---------------------------------------------------------------------------- + */ + +int +areaAccumFunc(tile, gdas) + Tile *tile; + GateDiffAccumStruct *gdas; +{ + Rect *rect = &(gdas->r); + int area, type; + + TiToRect(tile, rect); + area = (rect->r_xtop - rect->r_xbot) * (rect->r_ytop - rect->r_ybot); + gdas->accum += area; + return 0; +} + +/* + * ---------------------------------------------------------------------------- + * + * antennaAccumFunc -- + * + * Accumulate the total tile area searched, keeping an individual + * count for each tile type. If the antenna model is SIDEWALL, then + * calculate the area of the tile sidewall (tile perimeter * layer + * thickness), rather than the drawn tile area. + * + * ---------------------------------------------------------------------------- + */ + +int +antennaAccumFunc(tile, aaptr) + Tile *tile; + AntennaAccumStruct *aaptr; +{ + Rect *rect = &(aaptr->r); + int area; + int type; + int *typeareas = aaptr->accum; + int plane = aaptr->pNum; + float thick; + + type = TiGetType(tile); + + TiToRect(tile, rect); + + if (ExtCurStyle->exts_antennaRatio[type].areaType & ANTENNAMODEL_SIDEWALL) + { + /* Accumulate perimeter of tile where tile abuts space */ + + Tile *tp; + int perimeter = 0, pmax, pmin; + + /* Top */ + for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp = BL(tp)) + { + if (TiGetBottomType(tp) == TT_SPACE) + { + pmin = MAX(LEFT(tile), LEFT(tp)); + pmax = MIN(RIGHT(tile), RIGHT(tp)); + perimeter += (pmax - pmin); + } + } + /* Bottom */ + for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp)) + { + if (TiGetTopType(tp) == TT_SPACE) + { + pmin = MAX(LEFT(tile), LEFT(tp)); + pmax = MIN(RIGHT(tile), RIGHT(tp)); + perimeter += (pmax - pmin); + } + } + /* Left */ + for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp = RT(tp)) + { + if (TiGetRightType(tp) == TT_SPACE) + { + pmin = MAX(BOTTOM(tile), BOTTOM(tp)); + pmax = MIN(TOP(tile), TOP(tp)); + perimeter += (pmax - pmin); + } + } + /* Right */ + for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp = LB(tp)) + { + if (TiGetLeftType(tp) == TT_SPACE) + { + pmin = MAX(BOTTOM(tile), BOTTOM(tp)); + pmax = MIN(TOP(tile), TOP(tp)); + perimeter += (pmax - pmin); + } + } + + if (DBIsContact(type)) + { + int cperim; + TileType ttype; + TileTypeBitMask sMask; + float thick; + + cperim = ((rect->r_xtop - rect->r_xbot) + (rect->r_ytop - rect->r_ybot)) << 1; + + /* For contacts, add the area of the perimeter to the */ + /* residue (metal) type on the plane being searched. */ + /* Then, if the plane is the same as the base type of */ + /* the contact, add the entire perimeter area of the */ + /* tile to the total for the contact type itself. */ + + DBFullResidueMask(type, &sMask); + for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++) + if (TTMaskHasType(&sMask, ttype)) + if (DBTypeOnPlane(ttype, plane)) + { + thick = ExtCurStyle->exts_thick[ttype]; + typeareas[ttype] += (int)((float)perimeter * thick); + } + + if (type >= DBNumUserLayers) + { + DBResidueMask(type, &sMask); + for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++) + if (TTMaskHasType(&sMask, ttype)) + if (DBTypeOnPlane(ttype, plane)) + { + thick = ExtCurStyle->exts_thick[ttype]; + typeareas[ttype] += (int)((float)perimeter * thick); + break; + } + } + else + { + thick = ExtCurStyle->exts_thick[type]; + typeareas[type] += (int)((float)perimeter * thick); + } + } + else + { + /* Area is perimeter times layer thickness */ + thick = ExtCurStyle->exts_thick[type]; + typeareas[type] += (int)((float)perimeter * thick); + } + } + else if (ExtCurStyle->exts_antennaRatio[type].areaType & ANTENNAMODEL_SURFACE) + { + /* Simple tile area calculation */ + area = (rect->r_xtop - rect->r_xbot) * (rect->r_ytop - rect->r_ybot); + + /* If type is a contact, then add area to both residues as well */ + /* as the contact type. */ + + /* NOTE: Restrict area counts per plane so areas of contacts */ + /* are not double-counted. */ + + if (DBIsContact(type)) + { + TileType ttype; + TileTypeBitMask sMask; + + DBFullResidueMask(type, &sMask); + for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++) + if (TTMaskHasType(&sMask, ttype)) + if (DBTypeOnPlane(ttype, plane)) + typeareas[ttype] += area; + + if (type >= DBNumUserLayers) + { + DBResidueMask(type, &sMask); + for (ttype = TT_TECHDEPBASE; ttype < DBNumTypes; ttype++) + if (TTMaskHasType(&sMask, ttype)) + if (DBTypeOnPlane(ttype, plane)) + { + typeareas[ttype] += area; + break; + } + } + else + typeareas[type] += area; + } + else + typeareas[type] += area; + } + return 0; +} diff --git a/extflat/EFargs.c b/extflat/EFargs.c index 40b57278..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 */ @@ -209,8 +218,10 @@ EFArgs(argc, argv, err_result, argsProc, cdata) goto usage; if (strchr(cp, '!')) EFTrimFlags |= EF_TRIMGLOB; if (strchr(cp, '#')) EFTrimFlags |= EF_TRIMLOCAL; - if (strchr(cp, ',')) EFTrimFlags |= EF_CONVERTCOMMAS; + if (strchr(cp, ',')) EFTrimFlags |= EF_CONVERTCOMMA; if (strchr(cp, '=')) EFTrimFlags |= EF_CONVERTEQUAL; + if (strchr(cp, '[')) EFTrimFlags |= EF_CONVERTBRACKETS; + if (strchr(cp, ']')) EFTrimFlags |= EF_CONVERTBRACKETS; break; case 'C': EFCapThreshold = (EFCapValue)INFINITE_THRESHOLD_F; @@ -268,6 +279,11 @@ EFArgs(argc, argv, err_result, argsProc, cdata) case 'z': efHNStats = TRUE; break; + case 'h': + if (argsProc != NULL) (*argsProc)(&argc, &argv, cdata); + TxPrintf(usage_text); + if (err_result != NULL) *err_result = TRUE; + return NULL; /*** Try a caller-supplied argument processing function ***/ default: @@ -310,19 +326,15 @@ EFArgs(argc, argv, err_result, argsProc, cdata) realIn[cp - inname] = '\0'; inname = realIn; } - return inname; usage: - TxError("Standard arguments: [-R] [-C] [-r rthresh] [-c cthresh] [-v]\n" - "[-p searchpath] [-s sym=value] [-S symfile] [-t trimchars]\n" + TxError(usage_text); #ifdef MAGIC_WRAPPER - "[rootfile]\n"); if (err_result != NULL) *err_result = TRUE; return NULL; #else - "[-T techname] rootfile\n"); exit (1); /*NOTREACHED*/ #endif diff --git a/extflat/EFbuild.c b/extflat/EFbuild.c index 684168f1..46932d43 100644 --- a/extflat/EFbuild.c +++ b/extflat/EFbuild.c @@ -63,6 +63,8 @@ void efNodeMerge(); bool efConnBuildName(); bool efConnInitSubs(); +extern float locScale; + /* * ---------------------------------------------------------------------------- @@ -172,15 +174,15 @@ efBuildNode(def, isSubsnode, nodeName, nodeCap, x, y, layerName, av, ac) HashSetValue(he, (char *) newname); /* New node itself */ - size = sizeof (EFNode) + (efNumResistClasses - 1) * sizeof (PerimArea); + size = sizeof (EFNode) + (efNumResistClasses - 1) * sizeof (EFPerimArea); newnode = (EFNode *) mallocMagic((unsigned)(size)); newnode->efnode_flags = (isSubsnode == TRUE) ? EF_SUBS_NODE : 0; newnode->efnode_cap = nodeCap; newnode->efnode_attrs = (EFAttr *) NULL; - newnode->efnode_loc.r_xbot = x; - newnode->efnode_loc.r_ybot = y; - newnode->efnode_loc.r_xtop = x + 1; - newnode->efnode_loc.r_ytop = y + 1; + newnode->efnode_loc.r_xbot = (int)(0.5 + (float)x * locScale); + newnode->efnode_loc.r_ybot = (int)(0.5 + (float)y * locScale); + newnode->efnode_loc.r_xtop = newnode->efnode_loc.r_xbot + 1; + newnode->efnode_loc.r_ytop = newnode->efnode_loc.r_ybot + 1; newnode->efnode_client = (ClientData) NULL; if (layerName) newnode->efnode_type = efBuildAddStr(EFLayerNames, &EFLayerNumNames, MAXTYPES, layerName); @@ -553,8 +555,8 @@ efBuildDeviceParams(name, argc, argv) if (name[0] == ':') { newparm->parm_name = StrDup((char **)NULL, argv[n]); - newparm->parm_type[1] = '0' + n / 10; - newparm->parm_type[0] = '0' + n % 10; + newparm->parm_type[0] = '0' + n / 10; + newparm->parm_type[1] = '0' + n % 10; } else newparm->parm_name = StrDup((char **)NULL, pptr + 1); @@ -591,23 +593,28 @@ efBuildDevice(def, class, type, r, argc, argv) Rect *r; /* Coordinates of 1x1 rectangle entirely inside device */ int argc; /* Size of argv */ char *argv[]; /* Tokens for the rest of the dev line. - * The first depend on the type of device. The rest - * are taken in groups of 3, one for each terminal. - * Each group of 3 consists of the node name to which - * the terminal connects, the length of the terminal, - * and an attribute list (or the token 0). + * Starts with the last two position values, used to + * hash the device record. The next arguments depend + * on the type of device. The rest are taken in groups + * of 3, one for each terminal. Each group of 3 consists + * of the node name to which the terminal connects, the + * length of the terminal, and an attribute list (or the + * token 0). */ { int n, nterminals, pn; + HashEntry *he; DevTerm *term; Dev *newdev, devtmp; DevParam *newparm, *devp, *sparm; char ptype, *pptr, **av; + char devhash[64]; int argstart = 1; /* start of terminal list in argv[] */ bool hasModel = strcmp(type, "None") ? TRUE : FALSE; int area, perim; /* Total area, perimeter of primary type (i.e., channel) */ + newdev = (Dev *)NULL; devtmp.dev_subsnode = NULL; devtmp.dev_cap = 0.0; devtmp.dev_res = 0.0; @@ -681,7 +688,8 @@ efBuildDevice(def, class, type, r, argc, argv) { pn = *(argv[argstart] + 1) - '0'; if (pn == 0) - devtmp.dev_area = atoi(pptr); + devtmp.dev_area = (int)(0.5 + (float)atoi(pptr) + * locScale * locScale); /* Otherwise, punt */ } break; @@ -692,15 +700,15 @@ efBuildDevice(def, class, type, r, argc, argv) { pn = *(argv[argstart] + 1) - '0'; if (pn == 0) - devtmp.dev_perim = atoi(pptr); + devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale); /* Otherwise, use verbatim */ } break; case 'l': - devtmp.dev_length = atoi(pptr); + devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale); break; case 'w': - devtmp.dev_width = atoi(pptr); + devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale); break; case 'c': devtmp.dev_cap = (float)atof(pptr); @@ -713,7 +721,6 @@ efBuildDevice(def, class, type, r, argc, argv) } /* Check for optional substrate node */ - switch (class) { case DEV_RES: @@ -743,93 +750,149 @@ efBuildDevice(def, class, type, r, argc, argv) nterminals = (argc - argstart) / 3; - newdev = (Dev *) mallocMagic((unsigned) DevSize(nterminals)); - newdev->dev_subsnode = devtmp.dev_subsnode; - newdev->dev_cap = devtmp.dev_cap; - newdev->dev_res = devtmp.dev_res; - newdev->dev_area = devtmp.dev_area; - newdev->dev_perim = devtmp.dev_perim; - newdev->dev_length = devtmp.dev_length; - newdev->dev_width = devtmp.dev_width; - newdev->dev_params = devtmp.dev_params; + /* Determine if this device has been seen before */ - newdev->dev_nterm = nterminals; - newdev->dev_rect = *r; - newdev->dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, type); - newdev->dev_class = class; + sprintf(devhash, "%dx%d%s", r->r_xbot, r->r_ybot, type); + he = HashFind(&def->def_devs, devhash); + newdev = (Dev *)HashGetValue(he); + if (newdev) + { + /* Duplicate device. Duplicates will only appear in res.ext files + * where a device has nodes changed. Merge all properties of the + * original device with nodes from the new device. Keep the + * original device and discard the new one. + * + * Check that the device is actually the same device type and number + * of terminals. If not, throw an error and abandon the new device. + */ + + if ((newdev->dev_class != class) || + (strcmp(EFDevTypes[newdev->dev_type], type))) + { + TxError("Device %s %s at (%d, %d) overlaps incompatible device %s %s!\n", + extDevTable[class], type, r->r_xbot, r->r_ybot, + extDevTable[newdev->dev_class], EFDevTypes[newdev->dev_type]); + return 0; + } + else if (newdev->dev_nterm != nterminals) + { + TxError("Device %s %s at (%d, %d) overlaps device with incompatible" + " number of terminals (%d vs. %d)!\n", + extDevTable[class], type, r->r_xbot, r->r_ybot, nterminals, + newdev->dev_nterm); + return 0; + } + } + else + { + newdev = (Dev *) mallocMagic((unsigned) DevSize(nterminals)); + + /* Add this dev to the hash table for def */ + HashSetValue(he, (ClientData)newdev); + + newdev->dev_cap = devtmp.dev_cap; + newdev->dev_res = devtmp.dev_res; + newdev->dev_area = devtmp.dev_area; + newdev->dev_perim = devtmp.dev_perim; + newdev->dev_length = devtmp.dev_length; + newdev->dev_width = devtmp.dev_width; + newdev->dev_params = devtmp.dev_params; + + newdev->dev_nterm = nterminals; + newdev->dev_rect = *r; + newdev->dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, type); + newdev->dev_class = class; + switch (class) + { + case DEV_FET: /* old-style "fet" record */ + newdev->dev_area = atoi(argv[0]); + newdev->dev_perim = atoi(argv[1]); + break; + case DEV_MOSFET: /* new-style "device mosfet" record */ + case DEV_ASYMMETRIC: + case DEV_BJT: + newdev->dev_length = atoi(argv[0]); + newdev->dev_width = atoi(argv[1]); + break; + case DEV_RES: + if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1])) + { + newdev->dev_length = atoi(argv[0]); + newdev->dev_width = atoi(argv[1]); + } + else if (StrIsNumeric(argv[0])) + { + newdev->dev_res = (float)atof(argv[0]); + } + else + { + if (hasModel) + { + efReadError("Error: expected L and W, got %s %s\n", argv[0], + argv[1]); + newdev->dev_length = 0; + newdev->dev_width = 0; + } + else + { + efReadError("Error: expected resistance value, got %s\n", + argv[0]); + newdev->dev_res = 0.0; + } + } + break; + case DEV_CAP: + case DEV_CAPREV: + if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1])) + { + newdev->dev_length = atoi(argv[0]); + newdev->dev_width = atoi(argv[1]); + } + else if (StrIsNumeric(argv[0])) + { + newdev->dev_cap = (float)atof(argv[0]); + } + else + { + if (hasModel) + { + efReadError("Error: expected L and W, got %s %s\n", argv[0], + argv[1]); + newdev->dev_length = 0; + newdev->dev_width = 0; + } + else + { + efReadError("Error: expected capacitance value, got %s\n", + argv[0]); + newdev->dev_cap = 0.0; + } + } + break; + } + } + + newdev->dev_subsnode = devtmp.dev_subsnode; switch (class) { case DEV_FET: /* old-style "fet" record */ - newdev->dev_area = atoi(argv[0]); - newdev->dev_perim = atoi(argv[1]); newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); break; case DEV_MOSFET: /* new-style "device mosfet" record */ case DEV_ASYMMETRIC: case DEV_BJT: - newdev->dev_length = atoi(argv[0]); - newdev->dev_width = atoi(argv[1]); - /* "None" in the place of the substrate name means substrate is ignored */ if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0)) newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); break; case DEV_RES: - if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1])) - { - newdev->dev_length = atoi(argv[0]); - newdev->dev_width = atoi(argv[1]); - } - else if (StrIsNumeric(argv[0])) - { - newdev->dev_res = (float)atof(argv[0]); - } - else - { - if (hasModel) - { - efReadError("Error: expected L and W, got %s %s\n", argv[0], - argv[1]); - newdev->dev_length = 0; - newdev->dev_width = 0; - } - else - { - efReadError("Error: expected resistance value, got %s\n", argv[0]); - newdev->dev_res = 0.0; - } - } if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0)) newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); break; case DEV_CAP: case DEV_CAPREV: - if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1])) - { - newdev->dev_length = atoi(argv[0]); - newdev->dev_width = atoi(argv[1]); - } - else if (StrIsNumeric(argv[0])) - { - newdev->dev_cap = (float)atof(argv[0]); - } - else - { - if (hasModel) - { - efReadError("Error: expected L and W, got %s %s\n", argv[0], - argv[1]); - newdev->dev_length = 0; - newdev->dev_width = 0; - } - else - { - efReadError("Error: expected capacitance value, got %s\n", argv[0]); - newdev->dev_cap = 0.0; - } - } if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0)) newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); @@ -859,10 +922,6 @@ efBuildDevice(def, class, type, r, argc, argv) #undef TERM_PERIM #undef TERM_ATTRS - /* Add this dev to the list for def */ - newdev->dev_next = def->def_devs; - def->def_devs = newdev; - return 0; } @@ -1123,12 +1182,26 @@ efBuildUse(def, subDefName, subUseId, ta, tb, tc, td, te, tf) } else { - *cp = '\0'; - newuse->use_id = StrDup((char **) NULL, subUseId); - *cp = '['; - (void) sscanf(cp, "[%d:%d:%d][%d:%d:%d]", + /* Note: Preserve any use of brackets as-is other than the */ + /* standard magic array notation below. This allows, for */ + /* example, verilog instance arrays read from DEF files to */ + /* be passed through correctly. */ + + if ((sscanf(cp, "[%d:%d:%d][%d:%d:%d]", &newuse->use_xlo, &newuse->use_xhi, &newuse->use_xsep, - &newuse->use_ylo, &newuse->use_yhi, &newuse->use_ysep); + &newuse->use_ylo, &newuse->use_yhi, &newuse->use_ysep)) == 6) + { + *cp = '\0'; + newuse->use_id = StrDup((char **) NULL, subUseId); + *cp = '['; + } + else + { + newuse->use_id = StrDup((char **) NULL, subUseId); + newuse->use_xlo = newuse->use_xhi = 0; + newuse->use_ylo = newuse->use_yhi = 0; + newuse->use_xsep = newuse->use_ysep = 0; + } } he = HashFind(&def->def_uses, newuse->use_id); @@ -1168,7 +1241,7 @@ efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac) int n; Connection *conn; unsigned size = sizeof (Connection) - + (efNumResistClasses - 1) * sizeof (PerimArea); + + (efNumResistClasses - 1) * sizeof (EFPerimArea); conn = (Connection *) mallocMagic((unsigned)(size)); @@ -1178,8 +1251,9 @@ efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac) conn->conn_next = def->def_conns; for (n = 0; n < efNumResistClasses && ac > 1; n++, ac -= 2) { - conn->conn_pa[n].pa_area = atoi(*av++); - conn->conn_pa[n].pa_perim = atoi(*av++); + conn->conn_pa[n].pa_area = (int)(0.5 + (float)atoi(*av++) + * locScale * locScale); + conn->conn_pa[n].pa_perim = (int)(0.5 + (float)atoi(*av++) * locScale); } for ( ; n < efNumResistClasses; n++) conn->conn_pa[n].pa_area = conn->conn_pa[n].pa_perim = 0; @@ -1211,14 +1285,14 @@ efBuildResistor(def, nodeName1, nodeName2, resistance) Def *def; /* Def to which this connection is to be added */ char *nodeName1; /* Name of first node in resistor */ char *nodeName2; /* Name of second node in resistor */ - float resistance; /* Resistor value */ + int resistance; /* Resistor value */ { Connection *conn; conn = (Connection *) mallocMagic((unsigned)(sizeof (Connection))); if (efConnInitSubs(conn, nodeName1, nodeName2)) { - conn->conn_res = resistance; + conn->conn_res = (float)resistance; conn->conn_next = def->def_resistors; def->def_resistors = conn; } @@ -1682,6 +1756,36 @@ efFreeUseTable(table) } } +/* + * ---------------------------------------------------------------------------- + * + * efFreeDevTable -- + * + * Free the device records allocated for each entry in the device hash table, + * the memory allocated by the device, leaving the hash entry null. + * + * ---------------------------------------------------------------------------- + */ + +void +efFreeDevTable(table) + HashTable *table; +{ + Dev *dev; + HashSearch hs; + HashEntry *he; + int n; + + HashStartSearch(&hs); + while (he = HashNext(table, &hs)) + { + dev = (Dev *)HashGetValue(he); + for (n = 0; n < (int)dev->dev_nterm; n++) + if (dev->dev_terms[n].dterm_attrs) + freeMagic((char *) dev->dev_terms[n].dterm_attrs); + freeMagic((char *) dev); + } +} /* * ---------------------------------------------------------------------------- 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 27e8d4e3..239edb25 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); /* @@ -126,7 +127,7 @@ EFFlatBuild(name, flags) if (flags & EF_NOFLATSUBCKT) efFlatNodesStdCell(&efFlatContext); else - efFlatNodes(&efFlatContext); + efFlatNodes(&efFlatContext, FALSE, TRUE); efFlatKills(&efFlatContext); if (!(flags & EF_NONAMEMERGE)) efFlatGlob(); @@ -193,8 +194,8 @@ EFFlatBuildOneLevel(def, flags) efFlatContext.hc_x = efFlatContext.hc_y = 0; efFlatRootUse.use_def = efFlatRootDef; - /* Record all nodes of the next level in the hierarchy */ - efHierSrUses(&efFlatContext, efAddNodes, (ClientData)TRUE); + /* Record all nodes down the hierarchy from here */ + efFlatNodes(&efFlatContext, (ClientData)TRUE, (ClientData)FALSE); /* Expand all subcells that contain connectivity information but */ /* no active devices (including those in subcells). */ @@ -205,12 +206,12 @@ EFFlatBuildOneLevel(def, flags) if (usecount > 0) efHierSrUses(&efFlatContext, efFlatNodesDeviceless, (ClientData)&usecount); - if ((usecount == 0) && (efFlatRootUse.use_def->def_devs == NULL)) + if ((usecount == 0) && (HashGetNumEntries(&efFlatRootUse.use_def->def_devs) == 0)) efFlatRootUse.use_def->def_flags |= DEF_NODEVICES; /* Record all local nodes */ efAddNodes(&efFlatContext, FALSE); - efAddConns(&efFlatContext); + efAddConns(&efFlatContext, TRUE); efFlatKills(&efFlatContext); if (!(flags & EF_NONAMEMERGE)) @@ -291,16 +292,16 @@ EFFlatDone() */ int -efFlatNodes(hc) +efFlatNodes(hc, stdcell, doWarn) HierContext *hc; { (void) efHierSrUses(hc, efFlatNodes); /* Add all our own nodes to the table */ - efAddNodes(hc, FALSE); + efAddNodes(hc, stdcell); /* Process our own connections and adjustments */ - (void) efAddConns(hc); + (void) efAddConns(hc, doWarn); return (0); } @@ -352,7 +353,7 @@ efFlatNodesStdCell(hc) /* Process our own connections and adjustments */ if (!(hc->hc_use->use_def->def_flags & DEF_SUBCIRCUIT)) - (void) efAddConns(hc); + (void) efAddConns(hc, TRUE); return (0); } @@ -372,13 +373,13 @@ efFlatNodesDeviceless(hc, cdata) if (newcount > 0) efHierSrUses(hc, efFlatNodesDeviceless, (ClientData)&newcount); - if ((hc->hc_use->use_def->def_devs == NULL) && (newcount == 0)) + if ((HashGetNumEntries(&hc->hc_use->use_def->def_devs) == 0) && (newcount == 0)) { /* Add all our own nodes to the table */ efAddNodes(hc, TRUE); /* Process our own connections and adjustments */ - efAddConns(hc); + efAddConns(hc, TRUE); /* Mark this definition as having no devices, so it will not be visited */ hc->hc_use->use_def->def_flags |= DEF_NODEVICES; @@ -430,7 +431,7 @@ efAddNodes(hc, stdcell) bool is_subcircuit = (def->def_flags & DEF_SUBCIRCUIT) ? TRUE : FALSE; scale = def->def_scale; - size = sizeof (EFNode) + (efNumResistClasses-1) * sizeof (PerimArea); + size = sizeof (EFNode) + (efNumResistClasses-1) * sizeof (EFPerimArea); for (node = (EFNode *) def->def_firstn.efnode_next; node != &def->def_firstn; @@ -467,10 +468,10 @@ efAddNodes(hc, stdcell) newnode->efnode_type = node->efnode_type; if (!stdcell) bcopy((char *) node->efnode_pa, (char *) newnode->efnode_pa, - efNumResistClasses * sizeof (PerimArea)); + efNumResistClasses * sizeof (EFPerimArea)); else bzero((char *) newnode->efnode_pa, - efNumResistClasses * sizeof (PerimArea)); + efNumResistClasses * sizeof (EFPerimArea)); GeoTransRect(&hc->hc_trans, &node->efnode_loc, &newnode->efnode_loc); /* Scale the result by "scale" --- hopefully we end up with an integer */ @@ -527,6 +528,7 @@ efAddNodes(hc, stdcell) HashSetValue(he, (char *) newname); newname->efnn_node = newnode; newname->efnn_hier = hierName; + newname->efnn_port = -1; if (newnode->efnode_name) { newname->efnn_next = newnode->efnode_name->efnn_next; @@ -561,8 +563,9 @@ efAddNodes(hc, stdcell) */ int -efAddConns(hc) +efAddConns(hc, doWarn) HierContext *hc; + bool doWarn; { Connection *conn; @@ -575,9 +578,9 @@ efAddConns(hc) { /* Special case for speed when no array info is present */ if (conn->conn_1.cn_nsubs == 0) - efAddOneConn(hc, conn->conn_name1, conn->conn_name2, conn); + efAddOneConn(hc, conn->conn_name1, conn->conn_name2, conn, doWarn); else - efHierSrArray(hc, conn, efAddOneConn, (ClientData) NULL); + efHierSrArray(hc, conn, efAddOneConn, (ClientData)doWarn); } return (0); @@ -604,16 +607,17 @@ efAddConns(hc) */ int -efAddOneConn(hc, name1, name2, conn) +efAddOneConn(hc, name1, name2, conn, doWarn) HierContext *hc; char *name1, *name2; /* These are strings, not HierNames */ Connection *conn; + bool doWarn; { HashEntry *he1, *he2; EFNode *node, *newnode; int n; - he1 = EFHNLook(hc->hc_hierName, name1, "connect(1)"); + he1 = EFHNLook(hc->hc_hierName, name1, (doWarn) ? "connect(1)" : NULL); if (he1 == NULL) return 0; @@ -629,7 +633,7 @@ efAddOneConn(hc, name1, name2, conn) /* Merge this node with conn_name2 if one was specified */ if (name2) { - he2 = EFHNLook(hc->hc_hierName, name2, "connect(2)"); + he2 = EFHNLook(hc->hc_hierName, name2, (doWarn) ? "connect(2)" : NULL); if (he2 == NULL) return 0; newnode = ((EFNodeName *) HashGetValue(he2))->efnn_node; @@ -1018,14 +1022,23 @@ efFlatSingleCap(hc, name1, name2, conn) EFNode *n1, *n2; HashEntry *he; EFCoupleKey ck; + static char msg0[] = "cap(1)"; + static char msg1[] = "cap(2)"; + char *msg; + + /* Connections that are below threshold (ext2spice hierarchy only) */ + /* will be missing. Do not generate errors for these. */ - if ((he = EFHNLook(hc->hc_hierName, name1, "cap(1)")) == NULL) + msg = (fabs((double)conn->conn_cap / 1000) < EFCapThreshold) ? NULL : msg0; + + if ((he = EFHNLook(hc->hc_hierName, name1, msg)) == NULL) return 0; n1 = ((EFNodeName *) HashGetValue(he))->efnn_node; if (n1->efnode_flags & EF_KILLED) return 0; - if ((he = EFHNLook(hc->hc_hierName, name2, "cap(2)")) == NULL) + if (msg) msg = msg1; + if ((he = EFHNLook(hc->hc_hierName, name2, msg)) == NULL) return 0; n2 = ((EFNodeName *) HashGetValue(he))->efnn_node; if (n2->efnode_flags & EF_KILLED) 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 6ec90eca..a9cbf2c2 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. */ @@ -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 81384a5c..96158edb 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,13 +359,12 @@ readfile: break; /* we will deal with in efBuildDevice(). */ } - r.r_xbot = atoi(argv[3]); - r.r_ybot = atoi(argv[4]); - r.r_xtop = atoi(argv[5]); - r.r_ytop = atoi(argv[6]); + r.r_xbot = (int)(0.5 + (float)atoi(argv[3]) * locScale); + r.r_ybot = (int)(0.5 + (float)atoi(argv[4]) * locScale); + r.r_xtop = (int)(0.5 + (float)atoi(argv[5]) * locScale); + r.r_ytop = (int)(0.5 + (float)atoi(argv[6]) * locScale); - if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7, - &argv[7]) != 0) + if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7, &argv[7]) != 0) { efReadError("Incomplete terminal description for device\n"); continue; @@ -367,10 +374,10 @@ readfile: /* for backwards compatibility */ /* fet type xlo ylo xhi yhi area perim substrate GATE T1 T2 ... */ case FET: - r.r_xbot = atoi(argv[2]); - r.r_ybot = atoi(argv[3]); - r.r_xtop = atoi(argv[4]); - r.r_ytop = atoi(argv[5]); + r.r_xbot = (int)(0.5 + (float)atoi(argv[2]) * locScale); + r.r_ybot = (int)(0.5 + (float)atoi(argv[3]) * locScale); + r.r_xtop = (int)(0.5 + (float)atoi(argv[4]) * locScale); + r.r_ytop = (int)(0.5 + (float)atoi(argv[5]) * locScale); if (efBuildDevice(def, DEV_FET, argv[1], &r, argc - 6, &argv[6]) != 0) { efReadError("Incomplete terminal description for fet\n"); @@ -426,10 +433,8 @@ readfile: /* port name num xl yl xh yh type */ case PORT: if (DoSubCircuit) - { - DoResist = FALSE; def->def_flags |= DEF_SUBCIRCUIT; - } + efBuildPortNode(def, argv[1], atoi(argv[2]), atoi(argv[3]), atoi(argv[4]), argv[7], toplevel); break; @@ -566,8 +571,8 @@ resistChanged: /* distance driver receiver min max */ case DIST: efBuildDist(def, argv[1], argv[2], - (int)(lscale*atoi(argv[3])), - (int)(lscale*atoi(argv[4]))); + (int)(lscale*atoi(argv[3])*locScale), + (int)(lscale*atoi(argv[4])*locScale)); break; /* killnode nodename */ @@ -576,8 +581,12 @@ resistChanged: break; /* resistor node1 node2 resistance */ + /* NOTE: Value changed to floating-point 12/16/2019; */ + /* (value * rscale) is in milliohms which is integer as */ + /* resolution finer than milliohms is deemed unnecessary. */ case RESISTOR: - efBuildResistor(def, argv[1], argv[2], rscale*atoi(argv[3])); + efBuildResistor(def, argv[1], argv[2], + (int)(0.5 + (double)rscale * atof(argv[3]))); break; /* abstract (no options/arguments) */ @@ -719,11 +728,15 @@ start: } } - if (*get == '\\') /* Process quoted characters literally */ - { - get++; - if (*get == '\0') break; - } + /* Process backslash characters literally unless they */ + /* are followed by the end-of-line. */ + + if (*get == '\\') + if (*(get + 1) == '\0') + { + get++; + break; + } /* Copy into token receiving area */ *put++ = *get++; diff --git a/extflat/EFvisit.c b/extflat/EFvisit.c index aadb98ff..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; } @@ -859,7 +863,7 @@ EFHNOut(hierName, outf) HierName *hierName; FILE *outf; { - bool trimGlob, trimLocal, trimComma; + bool trimGlob, trimLocal, convComma, convBrackets; char *cp, c; if (hierName->hn_parent) efHNOutPrefix(hierName->hn_parent, outf); @@ -868,13 +872,19 @@ EFHNOut(hierName, outf) cp = hierName->hn_name; trimGlob = (EFTrimFlags & EF_TRIMGLOB); trimLocal = (EFTrimFlags & EF_TRIMLOCAL); - trimComma = (EFTrimFlags & EF_CONVERTCOMMAS); + convComma = (EFTrimFlags & EF_CONVERTCOMMA); + convBrackets = (EFTrimFlags & EF_CONVERTBRACKETS); while (c = *cp++) { if (*cp) { - if (trimComma && (c == ',')) - putc(';', outf); + if (c == ',') + { + if (convComma) + putc('|', outf); + } + else if (convBrackets && ((c == '[') || (c == ']'))) + putc('_', outf); else putc(c, outf); } 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/extflat/extflat.h b/extflat/extflat.h index 8d8f1dba..d7dec156 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 @@ -141,7 +142,7 @@ typedef struct { int pa_area; int pa_perim; -} PerimArea; +} EFPerimArea; typedef struct efnhdr { @@ -218,7 +219,7 @@ typedef struct efnode */ EFAttr *efnode_attrs; /* Node attribute list */ ClientData efnode_client; /* For hire */ - PerimArea efnode_pa[1]; /* Dummy; each node actually has + EFPerimArea efnode_pa[1]; /* Dummy; each node actually has * efNumResistClasses array elements * allocated to it. */ diff --git a/extract/ExtBasic.c b/extract/ExtBasic.c index 153fc69d..8855da98 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 */ @@ -115,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 */ @@ -134,6 +130,7 @@ void extOutputNodes(); int extTransTileFunc(); int extTransPerimFunc(); int extTransFindSubs(); +int extTransFindId(); int extAnnularTileFunc(); int extResistorTileFunc(); @@ -145,6 +142,8 @@ void extOutputParameters(); void extTransOutTerminal(); void extTransBad(); +ExtDevice *extDevFindMatch(); + bool extLabType(); /* Function returns 1 if a tile is found by DBTreeSrTiles() */ @@ -214,8 +213,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 +240,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 +1428,7 @@ extOutputParameters(def, transList, outFile) TransRegion *reg; TileType t; TileTypeBitMask tmask; + ExtDevice *devptr; TTMaskZero(&tmask); @@ -1450,86 +1450,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 +1510,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 +1546,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 +1586,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,11 +1602,12 @@ extOutputDevices(def, transList, outFile) { NodeRegion *node, *subsNode; TransRegion *reg; + 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; @@ -1663,13 +1625,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 +1650,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,26 +1675,65 @@ extOutputDevices(def, transList, outFile) /* search fails, give up and proceed with the reduced */ /* number of terminals. */ - while (extTransRec.tr_nterm < nsd) - { - TileTypeBitMask *tmask; + devptr = extTransRec.tr_devrec; + if (devptr == NULL) continue; /* Bad device; do not output */ + deventry = devptr; - tmask = &ExtCurStyle->exts_transSDTypes[t][extTransRec.tr_nterm]; - if (TTMaskIsZero(tmask)) break; - if (!TTMaskIntersect(tmask, &DBPlaneTypes[reg->treg_pnum])) + /* 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) + { + if (devptr == NULL) break; /* Bad device */ + nsd = devptr->exts_deviceSDCount; + for (termcount = 0; termcount < nsd; termcount++) { - node = NULL; - extTransFindSubs(reg->treg_tile, t, tmask, def, &node); - 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; + } + if (termcount == nsd) break; /* All terminals accounted for */ } - 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, @@ -1771,21 +1773,26 @@ 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. - * 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 +1816,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 +1837,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\"", @@ -1884,10 +1891,10 @@ 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 && (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 +1936,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 +1952,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 +2066,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 +2079,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); @@ -2084,7 +2091,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 && @@ -2142,7 +2149,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) */ } @@ -2162,9 +2169,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); @@ -2172,8 +2179,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 */ } @@ -2190,7 +2197,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 */ @@ -2202,17 +2209,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++) @@ -2220,7 +2239,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; } } @@ -2228,24 +2305,99 @@ 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, k, 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; + i = 0; + match = True; + for (k = 0; k < devptr->exts_deviceSDCount; k++) + { + if (extTransRec.tr_termnode[k] == 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; + + /* 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; } - return 0; + return (devptr == deventry) ? NULL : devptr; } /* @@ -2272,10 +2424,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; @@ -2305,7 +2459,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(...) */ @@ -2316,32 +2470,159 @@ 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 = 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 (!TTMaskIsZero(&cmask)) + { + if (TTMaskHasType(&cmask, TT_SPACE)) { allow_globsubsnode = TRUE; - TTMaskClearType(smask, TT_SPACE); + TTMaskClearType(&cmask, TT_SPACE); } - extTransFindSubs(tile, loctype, smask, arg->fra_def, &extTransRec.tr_subsnode); - if (allow_globsubsnode) - TTMaskSetType(smask, 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))) + { + /* 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) + { + /* 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; + if (devptr == NULL) return 0; /* No matching devices, so forget it. */ } - /* 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 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. */ - if (extTransRec.tr_subsnode == (NodeRegion *)NULL) - if (allow_globsubsnode) - extTransRec.tr_subsnode = glob_subsnode; + TTMaskZero(&cmask); + for (devtest = ExtCurStyle->exts_device[loctype]; devtest; + devtest = devtest->exts_next) + TTMaskSetMask(&cmask, &devtest->exts_deviceIdentifierTypes); - return (0); + 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 @@ -2351,6 +2632,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; @@ -2369,115 +2651,164 @@ 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; + } + } + + /* 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; } - SDterm = TRUE; + } + if (toutside == TT_SPACE) break; + 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; } + + /* 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 (!SDterm && extConnectsTo(tinside, toutside, ExtCurStyle->exts_nodeConn)) + if (devptr == NULL) { - /* Not in a terminal, but are in something that connects to gate */ - extTransRec.tr_gatelen += len; + /* 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; } /* @@ -2531,7 +2862,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); @@ -2568,6 +2899,7 @@ extResistorTileFunc(tile, pNum) { TileTypeBitMask mask; TileType loctype; + ExtDevice *devptr; /* * Visit each segment of the perimeter of this tile that @@ -2580,11 +2912,22 @@ 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) break; + devptr = devptr->exts_next; + } + if (devptr != NULL) extTransRec.tr_devrec = devptr; return (0); } @@ -2604,6 +2947,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 */ @@ -2632,11 +2976,15 @@ extSpecialPerimFunc(bp, sense) break; } + /* 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 (i = 0; !TTMaskIsZero(&ExtCurStyle->exts_transSDTypes[tinside][i]); i++) + for (i = 0; !TTMaskIsZero(&devptr->exts_deviceSDTypes[i]); i++) { - if (TTMaskHasType(&ExtCurStyle->exts_transSDTypes[tinside][i], toutside)) + if (TTMaskHasType(&devptr->exts_deviceSDTypes[i], toutside)) { needSurvey = TRUE; break; @@ -3120,9 +3468,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++) @@ -3142,19 +3492,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); } @@ -3212,7 +3595,11 @@ extSubsFunc(tile, arg) Tile *tile; FindRegion *arg; { + int pNum; + Rect tileArea; TileType type; + TileTypeBitMask *smask; + int extSubsFunc3(); if (IsSplit(tile)) { @@ -3220,6 +3607,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); @@ -3227,6 +3625,50 @@ extSubsFunc(tile, arg) return (0); } +int +extSubsFunc2(tile, arg) + Tile *tile; + FindRegion *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; + + 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) diff --git a/extract/ExtInter.c b/extract/ExtInter.c index 9c7a5e35..60359b5a 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, NULL)) return 0; + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return 0; + } filter.tf_func = func; filter.tf_arg = cdarg; @@ -461,7 +464,10 @@ extTreeSrFunc(scx, fp) int pNum; if ((def->cd_flags & CDAVAILABLE) == 0) - if (!DBCellRead(def, (char *) NULL, TRUE, NULL)) return (0); + { + bool dereference = (def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(def, (char *) NULL, TRUE, dereference, NULL)) return (0); + } context.tc_scx = scx; context.tc_filter = fp; @@ -480,3 +486,176 @@ extTreeSrFunc(scx, fp) return (DBCellSrArea(scx, extTreeSrFunc, (ClientData) fp)); } +int +extCellSrArea(scx, func, cdarg) + SearchContext *scx; + /* Pointer to search context specifying a cell use to + * search, an area in the coordinates of the cell's + * def, and a transform back to "root" coordinates. + * The area may have zero size. + */ + int (*func)(); /* Function to apply at every tile found */ + ClientData cdarg; /* Argument to pass to function */ +{ + int xlo, xhi, ylo, yhi, xbase, ybase, xsep, ysep, clientResult; + int srchBot, srchRight; + Plane *plane = scx->scx_use->cu_def->cd_planes[PL_CELL]; + Tile *tp, *tpnew; + Rect *rect, *bbox; + CellUse *use; + SearchContext newScx; + CellTileBody *body; + Transform t, tinv; + TreeFilter filter; + Rect expanded; + Point start; + + filter.tf_func = func; + filter.tf_arg = cdarg; + + if ((scx->scx_use->cu_def->cd_flags & CDAVAILABLE) == 0) + { + bool dereference = (scx->scx_use->cu_def->cd_flags & CDDEREFERENCE) ? + TRUE : FALSE; + if (!DBCellRead(scx->scx_use->cu_def, (char *) NULL, TRUE, dereference, NULL)) + return 0; + } + + /* + * In order to make this work with zero-size areas, we first expand + * the area by before searching the tile plane. extCellSrFunc will + * check carefully to throw out things that don't overlap the original + * area. The expansion is tricky because we mustn't expand infinities. + */ + + expanded = scx->scx_area; + if (expanded.r_xbot > TiPlaneRect.r_xbot) expanded.r_xbot -= 1; + if (expanded.r_ybot > TiPlaneRect.r_ybot) expanded.r_ybot -= 1; + if (expanded.r_xtop < TiPlaneRect.r_xtop) expanded.r_xtop += 1; + if (expanded.r_ytop < TiPlaneRect.r_ytop) expanded.r_ytop += 1; + rect = &expanded; + + /* Start along the top of the LHS of the search area */ + start.p_x = rect->r_xbot; + start.p_y = rect->r_ytop - 1; + tp = plane->pl_hint; + GOTOPOINT(tp, &start); + + /* Each iteration visits another tile on the LHS of the search area */ + while (TOP(tp) > rect->r_ybot) + { + /* Each iteration enumerates another tile */ +enumerate: + plane->pl_hint = tp; + if (SigInterruptPending) + return (1); + + /* + * Since subcells are allowed to overlap, a single tile body may + * refer to many subcells and a single subcell may be referred to + * by many tile bodies. To insure that each CellUse is enumerated + * exactly once, the procedure given to DBCellSrArea is only applied + * to a CellUse when its lower right corner is contained in the + * tile to dbCellSrFunc (or otherwise at the last tile encountered + * in the event the lower right corner of the CellUse is outside the + * search rectangle). + */ + srchBot = scx->scx_area.r_ybot; + srchRight = scx->scx_area.r_xtop; + for (body = (CellTileBody *) TiGetBody(tp); + body != NULL; + body = body->ctb_next) + { + use = newScx.scx_use = body->ctb_use; + ASSERT(use != (CellUse *) NULL, "dbCellSrFunc"); + + /* + * The check below is to ensure that we only enumerate each + * cell once, even though it appears in many different tiles + * in the subcell plane. + */ + bbox = &use->cu_bbox; + if ( (BOTTOM(tp) <= bbox->r_ybot || + (BOTTOM(tp) <= srchBot && bbox->r_ybot < srchBot)) + && (RIGHT(tp) >= bbox->r_xtop || + (RIGHT(tp) >= srchRight && bbox->r_xtop >= srchRight))) + { + /* + * Make sure that this cell really does overlap the + * search area (it could be just touching because of + * the expand-by-one in DBCellSrArea). + */ + if (!GEO_OVERLAP(&scx->scx_area, bbox)) continue; + + /* If not an array element, it's much simpler */ + if (use->cu_xlo == use->cu_xhi && use->cu_ylo == use->cu_yhi) + { + newScx.scx_x = use->cu_xlo, newScx.scx_y = use->cu_yhi; + if (SigInterruptPending) return 1; + GEOINVERTTRANS(&use->cu_transform, &tinv); + GEOTRANSTRANS(&use->cu_transform, &scx->scx_trans, + &newScx.scx_trans); + GEOTRANSRECT(&tinv, &scx->scx_area, &newScx.scx_area); + if ((*func)(&newScx, filter.tf_arg) == 1) + return 1; + continue; + } + + /* + * More than a single array element; + * check to see which ones overlap our search area. + */ + DBArrayOverlap(use, &scx->scx_area, &xlo, &xhi, &ylo, &yhi); + xsep = (use->cu_xlo > use->cu_xhi) + ? -use->cu_xsep : use->cu_xsep; + ysep = (use->cu_ylo > use->cu_yhi) + ? -use->cu_ysep : use->cu_ysep; + for (newScx.scx_y = ylo; newScx.scx_y<=yhi; newScx.scx_y++) + for (newScx.scx_x = xlo; newScx.scx_x<=xhi; newScx.scx_x++) + { + if (SigInterruptPending) return 1; + xbase = xsep * (newScx.scx_x - use->cu_xlo); + ybase = ysep * (newScx.scx_y - use->cu_ylo); + GEOTRANSTRANSLATE(xbase, ybase, &use->cu_transform, &t); + GEOINVERTTRANS(&t, &tinv); + GEOTRANSTRANS(&t, &scx->scx_trans, &newScx.scx_trans); + GEOTRANSRECT(&tinv, &scx->scx_area, &newScx.scx_area); + clientResult = (*func)(&newScx, filter.tf_arg); + if (clientResult == 2) goto skipArray; + else if (clientResult == 1) return 1; + } + } + skipArray: continue; + } + + tpnew = TR(tp); + if (LEFT(tpnew) < rect->r_xtop) + { + while (BOTTOM(tpnew) >= rect->r_ytop) tpnew = LB(tpnew); + if (BOTTOM(tpnew) >= BOTTOM(tp) || BOTTOM(tp) <= rect->r_ybot) + { + tp = tpnew; + goto enumerate; + } + } + + /* Each iteration returns one tile further to the left */ + while (LEFT(tp) > rect->r_xbot) + { + if (BOTTOM(tp) <= rect->r_ybot) + return (0); + tpnew = LB(tp); + tp = BL(tp); + if (BOTTOM(tpnew) >= BOTTOM(tp) || BOTTOM(tp) <= rect->r_ybot) + { + tp = tpnew; + goto enumerate; + } + } + + /* At left edge -- walk down to next tile along the left edge */ + for (tp = LB(tp); RIGHT(tp) <= rect->r_xbot; tp = TR(tp)) + /* Nothing */; + } + return (0); +} diff --git a/extract/ExtTech.c b/extract/ExtTech.c index c79c55e9..3878d784 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, MODEL, TIEDOWN, LAMBDA, OVERC, PERIMC, PLANEORDER, NOPLANEORDER, RESIST, RSCALE, SIDEHALO, SIDEOVERLAP, SIDEWALL, STEP, STYLE, SUBSTRATE, UNITS, VARIANT } Key; @@ -122,6 +122,15 @@ static keydesc keyTable[] = { "height", HEIGHT, 4, 4, "type height-above-subtrate thickness", + "antenna", ANTENNA, 4, 6, +"type [calc-type] [antenna-ratio-proportional] antenna-ratio-const", + + "model", MODEL, 2, 3, +"partial-cumulative [area-sidewall]", + + "tiedown", TIEDOWN, 2, 2, +"types", + "lambda", LAMBDA, 2, 2, "units-per-lambda", @@ -157,7 +166,7 @@ static keydesc keyTable[] = { "style", STYLE, 2, 4, "stylename", - "substrate", SUBSTRATE, 3, 3, + "substrate", SUBSTRATE, 3, 4, "types plane", "units", UNITS, 2, 2, @@ -298,37 +307,47 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr) TileType t; TileTypeBitMask *rmask, *tmask; int n, i = 0, j; - bool repeat; + bool repeat, found; + ExtDevice *devptr; char *locdname; char **uniquenamelist = (char **)mallocMagic(DBNumTypes * sizeof(char *)); - + found = FALSE; for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) { - locdname = ExtCurStyle->exts_transName[t]; - if (locdname != NULL) + for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next) { - repeat = FALSE; - for (j = 0; j < i; j++) - if (!strcmp(uniquenamelist[j], locdname)) - { - repeat = TRUE; - break; - } - if (repeat == FALSE) + locdname = devptr->exts_deviceName; + if (locdname != NULL) { - if (i == idx) break; - uniquenamelist[i] = locdname; - i++; + repeat = FALSE; + for (j = 0; j < i; j++) + if (!strcmp(uniquenamelist[j], locdname)) + { + repeat = TRUE; + break; + } + if (repeat == FALSE) + { + if (i == idx) + { + found = TRUE; + break; + } + uniquenamelist[i] = locdname; + i++; + } } } + if (found == TRUE) break; } if (t == DBNumTypes) return FALSE; + if (devptr == NULL) return FALSE; *devnameptr = locdname; - *subnameptr = ExtCurStyle->exts_transSubstrateName[t]; + *subnameptr = devptr->exts_deviceSubstrateName; - tmask = &ExtCurStyle->exts_transSDTypes[t][0]; + tmask = &devptr->exts_deviceSDTypes[0]; *sd_rclassptr = (short)(-1); /* NO_RESCLASS */ for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) @@ -341,7 +360,7 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr) } } - tmask = &ExtCurStyle->exts_transSubstrateTypes[t]; + tmask = &devptr->exts_deviceSubstrateTypes; *sub_rclassptr = (short)(-1); /* NO_RESCLASS */ for (n = 0; n < ExtCurStyle->exts_numResistClasses; n++) @@ -360,6 +379,35 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr) #endif /* MAGIC_WRAPPER */ +/* + * ---------------------------------------------------------------------------- + * + * extGetDevType -- + * + * Given an extraction model device name (devname), return the associated + * magic tiletype for the device. + * + * Results: + * Tile type that represents the device "devname" in the magic database. + * + * ---------------------------------------------------------------------------- + */ + +TileType +extGetDevType(devname) + char *devname; +{ + TileType t; + ExtDevice *devptr; + + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next) + if (!strcmp(devptr->exts_deviceName, devname)) + return t; + + return -1; +} + #ifdef THREE_D /* @@ -538,23 +586,10 @@ extTechStyleAlloc() TileType r; style = (ExtStyle *) mallocMagic(sizeof (ExtStyle)); - - /* Make sure that the memory for character strings is NULL, */ - /* because we want the Init section to free memory if it */ - /* has been previously allocated. */ - - for (r = 0; r < NT; r++) - { - style->exts_transSubstrateName[r] = (char *) NULL; - style->exts_transName[r] = (char *) NULL; - style->exts_transSDTypes[r] = (TileTypeBitMask *) NULL; - style->exts_deviceParams[r] = (ParamList *) NULL; - style->exts_deviceClass[r] = (char) 0; - style->exts_transResist[r].ht_table = (HashEntry **) NULL; - } return style; } + /* * ---------------------------------------------------------------------------- * @@ -575,7 +610,7 @@ extTechStyleInit(style) style->exts_status = TECH_NOT_LOADED; style->exts_sidePlanes = style->exts_overlapPlanes = 0; - TTMaskZero(&style->exts_transMask); + TTMaskZero(&style->exts_deviceMask); style->exts_activeTypes = DBAllButSpaceAndDRCBits; for (r = 0; r < NP; r++) @@ -589,7 +624,7 @@ extTechStyleInit(style) { TTMaskZero(&style->exts_nodeConn[r]); TTMaskZero(&style->exts_resistConn[r]); - TTMaskZero(&style->exts_transConn[r]); + TTMaskZero(&style->exts_deviceConn[r]); style->exts_allConn[r] = DBAllTypeBits; style->exts_sheetResist[r] = 0; @@ -620,43 +655,41 @@ extTechStyleInit(style) #ifdef ARIEL TTMaskZero(&style->exts_subsTransistorTypes[r]); #endif - if (style->exts_transSDTypes[r] != NULL) - freeMagic(style->exts_transSDTypes[r]); - style->exts_transSDTypes[r] = NULL; - style->exts_transSDCount[r] = 0; - style->exts_transGateCap[r] = (CapValue) 0; - style->exts_transSDCap[r] = (CapValue) 0; - if (style->exts_transSubstrateName[r] != (char *) NULL) + if (style->exts_device[r] != NULL) { - freeMagic(style->exts_transSubstrateName[r]); - style->exts_transSubstrateName[r] = (char *) NULL; - } - if (style->exts_transName[r] != (char *) NULL) - { - freeMagic(style->exts_transName[r]); - style->exts_transName[r] = (char *) NULL; - } - while (style->exts_deviceParams[r] != (ParamList *) NULL) - { - /* Parameter lists are shared. Only free the last one! */ + ExtDevice *devptr; + for (devptr = style->exts_device[r]; devptr; devptr = devptr->exts_next) + { - if (style->exts_deviceParams[r]->pl_count > 1) - { - style->exts_deviceParams[r]->pl_count--; - style->exts_deviceParams[r] = (ParamList *)NULL; - } - else - { - freeMagic(style->exts_deviceParams[r]->pl_name); - freeMagic(style->exts_deviceParams[r]); - style->exts_deviceParams[r] = style->exts_deviceParams[r]->pl_next; + if (devptr->exts_deviceSDTypes != NULL) + freeMagic(devptr->exts_deviceSDTypes); + if (devptr->exts_deviceSubstrateName != (char *) NULL) + freeMagic(devptr->exts_deviceSubstrateName); + if (devptr->exts_deviceName != (char *) NULL) + freeMagic(devptr->exts_deviceName); + while (devptr->exts_deviceParams != (ParamList *) NULL) + { + /* Parameter lists are shared. Only free the last one! */ + + if (devptr->exts_deviceParams->pl_count > 1) + { + devptr->exts_deviceParams->pl_count--; + devptr->exts_deviceParams = (ParamList *)NULL; + } + else + { + freeMagic(devptr->exts_deviceParams->pl_name); + freeMagic(devptr->exts_deviceParams); + devptr->exts_deviceParams = devptr->exts_deviceParams->pl_next; + } + } + if (devptr->exts_deviceResist.ht_table != (HashEntry **) NULL) + HashKill(&devptr->exts_deviceResist); + + freeMagic(devptr); } + style->exts_device[r] = (ExtDevice *)NULL; } - style->exts_deviceClass[r] = (char)0; - if (style->exts_transResist[r].ht_table != (HashEntry **) NULL) - HashKill(&style->exts_transResist[r]); - HashInit(&style->exts_transResist[r], 8, HT_STRINGKEYS); - style->exts_linearResist[r] = 0; } style->exts_sideCoupleHalo = 0; @@ -667,14 +700,20 @@ extTechStyleInit(style) style->exts_numResistClasses = 0; style->exts_planeOrderStatus = needPlaneOrder ; + TTMaskZero(&style->exts_antennaTieTypes); for (r = 0; r < DBNumTypes; r++) { + style->exts_antennaRatio[r].areaType = (char)0; + style->exts_antennaRatio[r].ratioGate = 0.0; + style->exts_antennaRatio[r].ratioDiffA = 0.0; + style->exts_antennaRatio[r].ratioDiffB = 0.0; style->exts_resistByResistClass[r] = 0; TTMaskZero(&style->exts_typesByResistClass[r]); style->exts_typesResistChanged[r] = DBAllButSpaceAndDRCBits; TTMaskSetType(&style->exts_typesResistChanged[r], TT_SPACE); style->exts_typeToResistClass[r] = -1; + } doConvert = FALSE; @@ -685,6 +724,7 @@ extTechStyleInit(style) style->exts_globSubstratePlane = -1; TTMaskZero(&style->exts_globSubstrateTypes); + TTMaskZero(&style->exts_globSubstrateShieldTypes); } @@ -798,14 +838,6 @@ ExtTechInit() if (ExtCurStyle != NULL) { extTechStyleInit(ExtCurStyle); - - /* Everything has been freed except the hash tables, which */ - /* were just reinitialized by extTechStyleInit(). */ - for (r = 0; r < NT; r++) - { - if (ExtCurStyle->exts_transResist[r].ht_table != (HashEntry **) NULL) - HashKill(&ExtCurStyle->exts_transResist[r]); - } ExtCurStyle = NULL; } @@ -1569,7 +1601,7 @@ ExtTechLine(sectionName, argc, argv) PlaneMask pshield, pov; CapValue capVal, gscap, gccap; TileTypeBitMask types1, types2, termtypes[MAXSD]; - TileTypeBitMask near, far, ov, shield, subsTypes; + TileTypeBitMask near, far, ov, shield, subsTypes, idTypes; char *subsName, *transName, *cp, *endptr, *paramName; TileType s, t, r, o; keydesc *kp, *dv; @@ -1578,6 +1610,7 @@ ExtTechLine(sectionName, argc, argv) EdgeCap *cnew; ExtKeep *es, *newStyle; ParamList *subcktParams, *newParam; + ExtDevice *devptr; int refcnt; double dhalo; bool bad; @@ -1796,6 +1829,8 @@ ExtTechLine(sectionName, argc, argv) case FET: case FETRESIST: case HEIGHT: + case ANTENNA: + case TIEDOWN: case OVERC: case PERIMC: case RESIST: @@ -1888,24 +1923,32 @@ ExtTechLine(sectionName, argc, argv) gccap = (argc > 7) ? aToCap(argv[7]) : (CapValue) 0; } - TTMaskSetMask(&ExtCurStyle->exts_transMask, &types1); + TTMaskSetMask(&ExtCurStyle->exts_deviceMask, &types1); for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) if (TTMaskHasType(&types1, t)) { - TTMaskSetMask(ExtCurStyle->exts_transConn+t,&types1); - ExtCurStyle->exts_transSDTypes[t] = (TileTypeBitMask *) + devptr = (ExtDevice *)mallocMagic(sizeof(ExtDevice)); + devptr->exts_deviceSDTypes = (TileTypeBitMask *) mallocMagic(2 * sizeof(TileTypeBitMask)); - ExtCurStyle->exts_transSDTypes[t][0] = termtypes[0]; - ExtCurStyle->exts_transSDTypes[t][1] = DBZeroTypeBits; - ExtCurStyle->exts_transSDCount[t] = nterm; - ExtCurStyle->exts_transSDCap[t] = gscap; - ExtCurStyle->exts_transGateCap[t] = gccap; - ExtCurStyle->exts_deviceClass[t] = DEV_FET; - ExtCurStyle->exts_transName[t] = - StrDup((char **) NULL, transName); - ExtCurStyle->exts_transSubstrateName[t] = + devptr->exts_deviceSDTypes[0] = termtypes[0]; + devptr->exts_deviceSDTypes[1] = DBZeroTypeBits; + devptr->exts_deviceSDCount = nterm; + devptr->exts_deviceSDCap = gscap; + devptr->exts_deviceGateCap = gccap; + devptr->exts_deviceClass = DEV_FET; + devptr->exts_deviceName = StrDup((char **) NULL, transName); + devptr->exts_deviceSubstrateName = StrDup((char **) NULL, subsName); - ExtCurStyle->exts_transSubstrateTypes[t] = subsTypes; + devptr->exts_deviceSubstrateTypes = subsTypes; + devptr->exts_deviceIdentifierTypes = DBZeroTypeBits; + devptr->exts_deviceParams = (ParamList *) NULL; + devptr->exts_deviceResist.ht_table = (HashEntry **) NULL; + HashInit(&devptr->exts_deviceResist, 8, HT_STRINGKEYS); + + TTMaskSetMask(ExtCurStyle->exts_deviceConn + t, &types1); + + devptr->exts_next = ExtCurStyle->exts_device[t]; + ExtCurStyle->exts_device[t] = devptr; #ifdef ARIEL { int z; @@ -1936,12 +1979,11 @@ ExtTechLine(sectionName, argc, argv) case DEFAULTSIDEWALL: ExtTechSimpleSidewallCap(argv); break; - case DEVICE: /* Parse second argument for device type */ - n = LookupStruct(argv[1], (LookupTable *) devTable, sizeof devTable[0]); + n = LookupStruct(argv[1], (LookupTable *)devTable, sizeof devTable[0]); if (n < 0) { TechError("Illegal device. Legal devices are:\n\t"); @@ -1999,6 +2041,18 @@ ExtTechLine(sectionName, argc, argv) argc--; } + /* If the last entry before any parameters starts with '+', */ + /* then use it to set the identity marker. Otherwise, the */ + /* identity marker is NULL. */ + + idTypes = DBZeroTypeBits; + if (*argv[argc - 1] == '+') + { + if ((DBTechNameMask(argv[argc - 1] + 1, &idTypes)) == 0) + idTypes = DBZeroTypeBits; + argc--; + } + /* Check the number of arguments after splitting out */ /* parameter entries. There is no limit on arguments in */ /* DEV_SUBCKT and DEV_MSUBCKT. */ @@ -2194,31 +2248,47 @@ ExtTechLine(sectionName, argc, argv) break; } - TTMaskSetMask(&ExtCurStyle->exts_transMask, &types1); + TTMaskSetMask(&ExtCurStyle->exts_deviceMask, &types1); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) { if (TTMaskHasType(&types1, t)) { - TTMaskSetMask(ExtCurStyle->exts_transConn + t, &types1); + devptr = (ExtDevice *)mallocMagic(sizeof(ExtDevice)); for (i = 0; !TTMaskIsZero(&termtypes[i]); i++); - ExtCurStyle->exts_transSDTypes[t] = (TileTypeBitMask *) + devptr->exts_deviceSDTypes = (TileTypeBitMask *) mallocMagic((i + 1) * sizeof(TileTypeBitMask)); for (i = 0; !TTMaskIsZero(&termtypes[i]); i++) - ExtCurStyle->exts_transSDTypes[t][i] = termtypes[i]; - ExtCurStyle->exts_transSDTypes[t][i] = DBZeroTypeBits; + devptr->exts_deviceSDTypes[i] = termtypes[i]; + devptr->exts_deviceSDTypes[i] = DBZeroTypeBits; - ExtCurStyle->exts_transSDCount[t] = nterm; - ExtCurStyle->exts_transSDCap[t] = gscap; - ExtCurStyle->exts_transGateCap[t] = gccap; - ExtCurStyle->exts_deviceClass[t] = class; - ExtCurStyle->exts_transName[t] = - StrDup((char **) NULL, transName); + devptr->exts_deviceSDCount = nterm; + devptr->exts_deviceSDCap = gscap; + devptr->exts_deviceGateCap = gccap; + devptr->exts_deviceClass = class; + devptr->exts_deviceName = StrDup((char **) NULL, transName); if (subsName != NULL) - ExtCurStyle->exts_transSubstrateName[t] = + devptr->exts_deviceSubstrateName = StrDup((char **) NULL, subsName); - ExtCurStyle->exts_transSubstrateTypes[t] = subsTypes; + else + devptr->exts_deviceSubstrateName = (char *)NULL; + devptr->exts_deviceSubstrateTypes = subsTypes; + devptr->exts_deviceIdentifierTypes = idTypes; + devptr->exts_deviceParams = (ParamList *) NULL; + if (subcktParams != NULL) + { + devptr->exts_deviceParams = subcktParams; + subcktParams->pl_count++; + } + devptr->exts_deviceResist.ht_table = (HashEntry **) NULL; + HashInit(&devptr->exts_deviceResist, 8, HT_STRINGKEYS); + + devptr->exts_next = ExtCurStyle->exts_device[t]; + ExtCurStyle->exts_device[t] = devptr; + + TTMaskSetMask(ExtCurStyle->exts_deviceConn + t, &types1); #ifdef ARIEL { int z; @@ -2231,11 +2301,6 @@ ExtTechLine(sectionName, argc, argv) } } #endif - if (subcktParams != NULL) - { - ExtCurStyle->exts_deviceParams[t] = subcktParams; - subcktParams->pl_count++; - } } } break; @@ -2249,13 +2314,19 @@ ExtTechLine(sectionName, argc, argv) val = atoi(argv[3]); isLinear = (strcmp(argv[2], "linear") == 0); for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + { + ExtDevice *devptr; if (TTMaskHasType(&types1, t)) { - he = HashFind(&ExtCurStyle->exts_transResist[t], argv[2]); - HashSetValue(he, (spointertype)val); - if (isLinear) - ExtCurStyle->exts_linearResist[t] = val; + for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next) + { + he = HashFind(&devptr->exts_deviceResist, argv[2]); + HashSetValue(he, (spointertype)val); + if (isLinear) + devptr->exts_linearResist = val; + } } + } break; case HEIGHT: { float height, thick; @@ -2280,6 +2351,122 @@ ExtTechLine(sectionName, argc, argv) } } break; + case ANTENNA: { + float antennaratio; + char areaType; + bool hasModel = FALSE; + int argidx = 2; + + if (!StrIsNumeric(argv[2])) + { + if (!strcmp(argv[2], "surface") || !strcmp(argv[2], "area")) + { + areaType = ANTENNAMODEL_SURFACE; + hasModel = TRUE; + } + else if (!strcmp(argv[2], "sidewall") || !strcmp(argv[2], "perimeter")) + { + areaType = ANTENNAMODEL_SIDEWALL; + hasModel = TRUE; + } + else + { + TechError("Error in layer antenna calculation type \"%s\"; " + " must be \"surface\" or \"sidewall\"\n", argv[2]); + break; + } + } + if (hasModel == FALSE) + { + if (ExtCurStyle->exts_antennaModel & ANTENNAMODEL_SURFACE) + areaType = ANTENNAMODEL_SURFACE; + else if (ExtCurStyle->exts_antennaModel & ANTENNAMODEL_SIDEWALL) + areaType = ANTENNAMODEL_SIDEWALL; + else + TechError("No antenna calculation type given for layer(s) %s " + " and no default calculation type found.\n", argv[1]); + } + + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, t)) + ExtCurStyle->exts_antennaRatio[t].areaType = areaType; + + if (hasModel == TRUE) argidx = 3; + + if (!StrIsNumeric(argv[argidx])) + { + TechError("Gate layer antenna ratio %s must be numeric\n", argv[argidx]); + break; + } + antennaratio = (float)strtod(argv[argidx], NULL); + + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, t)) + ExtCurStyle->exts_antennaRatio[t].ratioGate = antennaratio; + + argidx++; + if (!StrIsNumeric(argv[argidx])) + { + if (!strcasecmp(argv[argidx], "none")) + antennaratio = INFINITY; + else + { + TechError("Diff layer antenna ratio %s must be numeric\n", + argv[argidx]); + break; + } + } + else + antennaratio = (float)strtod(argv[argidx], NULL); + + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, t)) + ExtCurStyle->exts_antennaRatio[t].ratioDiffB = antennaratio; + + argidx++; + if (argidx < argc) + { + if (!StrIsNumeric(argv[argidx])) + { + TechError("Diff layer antenna ratio %s must be numeric\n", + argv[argidx]); + break; + } + antennaratio = (float)strtod(argv[argidx], NULL); + } + else + antennaratio = 0; + + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, t)) + ExtCurStyle->exts_antennaRatio[t].ratioDiffA = antennaratio; + + break; + } + case MODEL: + if (!strcmp(argv[1], "partial")) + ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_PARTIAL; + else if (!strcmp(argv[1], "cumulative")) + ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_CUMULATIVE; + else + TxError("Unknown antenna model \"%s\": Use \"partial\" or " + "\"cumulative\""); + + if (argc > 2) + { + if (!strcmp(argv[2], "surface") || !strcmp(argv[2], "area")) + ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_SURFACE; + else if (!strcmp(argv[2], "sidewall") || !strcmp(argv[2], "perimeter")) + ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_SIDEWALL; + else + TxError("Unknown antenna model \"%s\": Use \"surface\" or " + "\"sidewall\""); + } + break; + + case TIEDOWN: + TTMaskSetMask(&ExtCurStyle->exts_antennaTieTypes, &types1); + break; case UNITS: if (!strcmp(argv[1], "microns")) doConvert = TRUE; @@ -2569,8 +2756,22 @@ ExtTechLine(sectionName, argc, argv) ExtCurStyle->exts_stepSize = val; break; case SUBSTRATE: + /* If the last entry starts with '-', then use it to set */ + /* the shield types. Otherwise, the shield types mask is */ + /* NULL. */ + + idTypes = DBZeroTypeBits; + if (*argv[argc - 1] == '-') + { + if ((DBTechNameMask(argv[argc - 1] + 1, &idTypes)) == 0) + idTypes = DBZeroTypeBits; + argc--; + } + TTMaskZero(&ExtCurStyle->exts_globSubstrateTypes); + TTMaskZero(&ExtCurStyle->exts_globSubstrateShieldTypes); TTMaskSetMask(&ExtCurStyle->exts_globSubstrateTypes, &types1); + ExtCurStyle->exts_globSubstrateShieldTypes = idTypes; ExtCurStyle->exts_globSubstratePlane = DBTechNoisyNamePlane(argv[2]); break; case NOPLANEORDER: { @@ -2619,7 +2820,7 @@ diffplane: * * Postprocess the technology specific information for extraction. * Builds the connectivity tables exts_nodeConn[], exts_resistConn[], - * and exts_transConn[]. + * and exts_deviceConn[]. * * Results: * None. @@ -2664,9 +2865,9 @@ extTechFinalStyle(style) for (r = TT_TECHDEPBASE; r < DBNumTypes; r++) { maskBits = style->exts_nodeConn[r] = DBConnectTbl[r]; - if (!TTMaskHasType(&style->exts_transMask, r)) + if (!TTMaskHasType(&style->exts_deviceMask, r)) { - TTMaskZero(&style->exts_transConn[r]); + TTMaskZero(&style->exts_deviceConn[r]); } for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) { @@ -2870,10 +3071,15 @@ zinit: for (r = 0; r < DBNumTypes; r++) { - style->exts_areaCap[r] *= sqfac; - style->exts_transSDCap[r] *= sqfac; - style->exts_transGateCap[r] *= sqfac; + ExtDevice *devptr; + for (devptr = style->exts_device[r]; devptr; devptr = devptr->exts_next) + { + devptr->exts_deviceSDCap *= sqfac; + devptr->exts_deviceGateCap *= sqfac; + } + + style->exts_areaCap[r] *= sqfac; for (s = 0; s < DBNumTypes; s++) { EdgeCap *ec; @@ -2899,6 +3105,10 @@ zinit: ec = ec->ec_next) ec->ec_cap *= 0.5; } + + /* Layer thickness and height are in microns, but are floating-point */ + style->exts_thick[r] /= dscale; + style->exts_height[r] /= dscale; } /* side halo and step size are also in microns */ @@ -2953,13 +3163,18 @@ ExtTechScale(scalen, scaled) for (i = 0; i < DBNumTypes; i++) { + ExtDevice *devptr; + style->exts_areaCap[i] *= sqn; style->exts_areaCap[i] /= sqd; - style->exts_transSDCap[i] *= sqn; - style->exts_transSDCap[i] /= sqd; - style->exts_transGateCap[i] *= sqn; - style->exts_transGateCap[i] /= sqd; + for (devptr = style->exts_device[i]; devptr; devptr = devptr->exts_next) + { + devptr->exts_deviceSDCap *= sqn; + devptr->exts_deviceSDCap /= sqd; + devptr->exts_deviceGateCap *= sqn; + devptr->exts_deviceGateCap /= sqd; + } style->exts_height[i] *= scaled; style->exts_height[i] /= scalen; 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/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 ee264862..72e2424f 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -48,6 +48,19 @@ typedef int ResValue; /* Warning: in some places resistances are stored * as ints. This is here for documentation only. */ +typedef struct { + char areaType; /* ANTENNAMODEL_SURFACE or ANTENNAMODEL_SIDEWALL */ + float ratioGate; + float ratioDiffA; /* Proportional */ + float ratioDiffB; /* Constant */ +} RatioValues; + +/* Antenna models */ +#define ANTENNAMODEL_PARTIAL 0x01 +#define ANTENNAMODEL_CUMULATIVE 0x02 +#define ANTENNAMODEL_SURFACE 0x04 +#define ANTENNAMODEL_SIDEWALL 0x08 + /* ------------------------ Parameter lists --------------------------- */ /* These lists keep track of what parameter names subcircuit definitions @@ -483,6 +496,82 @@ typedef struct extkeep char *exts_name; } ExtKeep; +/* + * Structure used to define transistors and other extracted devices + * One of these records is kept per tile type. However, the record + * can link to additional records through the "exts_next" record, + * so that multiple extraction devices can be defined for the same + * tile type, provided that each definition has a unique combination + * of exts_deviceSDTypes and exts_deviceSubstrateTypes. + */ + +typedef struct extDevice +{ + /* Name of each transistor type as output in .ext file */ + char *exts_deviceName; + + /* List of parameter names for each subcircuit type */ + ParamList *exts_deviceParams; + + /* Device class for each layer type */ + char exts_deviceClass; + + /* + * Per-square resistances for each possible transistor type, + * in the various regions that such a type might operate. + * The only operating region currently used is "linear", + * which the resistance extractor uses in its thresholding + * operation. NOTE: resistances in this table are in OHMS + * per square, not MILLIOHMS! + */ + + HashTable exts_deviceResist; + ResValue exts_linearResist; + + /* + * Mask of the types of tiles that connect to the channel terminals + * of a transistor type. The intent is that these will be the + * diffusion terminals of a transistor, ie, its source and drain. + * UPDATED May, 2008: Record is a list of type masks, allowing + * multiple terminal types in the case of, e.g., high-voltage + * or other asymmetric devices. The last entry in the list should + * be equal to DBSpaceBits. + */ + TileTypeBitMask *exts_deviceSDTypes; + + /* + * Maximum number of terminals (source/drains) per transistor type. + * This table exists to allow the possibility of transistors with + * more than two diffusion terminals at some point in the future. + */ + int exts_deviceSDCount; + + /* Currently unused: gate-source capacitance per unit perimeter */ + CapValue exts_deviceSDCap; + + /* Currently unused: gate-channel capacitance per unit area */ + CapValue exts_deviceGateCap; + + /* + * Each type of transistor has a substrate node. By default, + * it is the one given by exts_deviceSubstrateName[t]. However, + * if the mask exts_deviceSubstrateTypes is non-zero, and if + * the transistor overlaps material of one of the types in the + * mask, then the transistor substrate node is the node of the + * material it overlaps. + */ + char *exts_deviceSubstrateName; + TileTypeBitMask exts_deviceSubstrateTypes; + + /* + * Each device type can have any number of extract models based + * on identifier layers (such as thickox, esd, etc.) + */ + TileTypeBitMask exts_deviceIdentifierTypes; + + struct extDevice *exts_next; +} ExtDevice; + /* * Parameters for the process being extracted. * We try to use use integers here, rather than floats, to be nice to @@ -524,11 +613,11 @@ typedef struct extstyle TileTypeBitMask exts_resistConn[NT]; /* - * Connectivity for determining transistors. - * Each transistor type should connect only to itself. + * Connectivity for determining devices. + * Each devices type should connect only to itself. * Nothing else should connect to anything else. */ - TileTypeBitMask exts_transConn[NT]; + TileTypeBitMask exts_deviceConn[NT]; /* * Set of types to be considered for extraction. Types not in @@ -580,6 +669,14 @@ typedef struct extstyle float exts_height[NT]; float exts_thick[NT]; + char exts_antennaModel; + + /* Antenna area ratio for each layer */ + RatioValues exts_antennaRatio[NT]; + + /* Mask of types that tie down antennas */ + TileTypeBitMask exts_antennaTieTypes; + /* * Capacitance to substrate for each tile type, in units of * attofarads per square lambda. @@ -779,65 +876,14 @@ typedef struct extstyle */ TileTypeBitMask exts_sideEdges[NT]; - /* Transistors */ + /* Devices */ - /* Name of each transistor type as output in .ext file */ - char *exts_transName[NT]; + /* Contains one for each type of device, zero for all other tile types */ + TileTypeBitMask exts_deviceMask; - /* List of parameter names for each subcircuit type */ - ParamList *exts_deviceParams[NT]; + /* All information about a device goes in this record (see above) */ + ExtDevice *exts_device[NT]; - /* Device class for each layer type */ - char exts_deviceClass[NT]; - - /* Contains one for each type of fet, zero for all other types */ - TileTypeBitMask exts_transMask; - - /* - * Per-square resistances for each possible transistor type, - * in the various regions that such a type might operate. - * The only operating region currently used is "linear", - * which the resistance extractor uses in its thresholding - * operation. NOTE: resistances in this table are in OHMS - * per square, not MILLIOHMS! - */ - HashTable exts_transResist[NT]; - ResValue exts_linearResist[NT]; - - /* - * Mask of the types of tiles that connect to the channel terminals - * of a transistor type. The intent is that these will be the - * diffusion terminals of a transistor, ie, its source and drain. - * UPDATED May, 2008: Record is a list of type masks, allowing - * multiple terminal types in the case of, e.g., high-voltage - * or other asymmetric devices. The last entry in the list should - * be equal to DBSpaceBits. - */ - TileTypeBitMask *exts_transSDTypes[NT]; - - /* - * Maximum number of terminals (source/drains) per transistor type. - * This table exists to allow the possibility of transistors with - * more than two diffusion terminals at some point in the future. - */ - int exts_transSDCount[NT]; - - /* Currently unused: gate-source capacitance per unit perimeter */ - CapValue exts_transSDCap[NT]; - - /* Currently unused: gate-channel capacitance per unit area */ - CapValue exts_transGateCap[NT]; - - /* - * Each type of transistor has a substrate node. By default, - * it is the one given by exts_transSubstrateName[t]. However, - * if the mask exts_transSubstrateTypes[t] is non-zero, and if - * the transistor overlaps material of one of the types in the - * mask, then the transistor substrate node is the node of the - * material it overlaps. If exts_transSub - */ - char *exts_transSubstrateName[NT]; - TileTypeBitMask exts_transSubstrateTypes[NT]; #ifdef ARIEL TileTypeBitMask exts_subsTransistorTypes[NT]; #endif /* ARIEL */ @@ -847,11 +893,16 @@ typedef struct extstyle * types that connect to the substrate. Since for non-SOI * processes, this generally is used to specify that space on * the well plane is the substrate, the plane number for the - * well plane is given, too. + * well plane is given, too. The "shield types" mask is a + * mask of types that prevent any types in exts_globSubstrateTypes + * from contacting the substrate (e.g., deep nwell might be a + * shielding type, or it could be a special marker layer like + * "not_substrate"). */ char *exts_globSubstrateName; TileTypeBitMask exts_globSubstrateTypes; int exts_globSubstratePlane; + TileTypeBitMask exts_globSubstrateShieldTypes; /* Scaling */ /* @@ -1024,6 +1075,7 @@ extern NodeRegion *extBasic(); extern NodeRegion *extFindNodes(); extern ExtTree *extHierNewOne(); extern int extNbrPushFunc(); +extern TileType extGetDevType(); /* --------------------- Miscellaneous globals ------------------------ */ 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/graphics/W3Dmain.c b/graphics/W3Dmain.c index 55c561df..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, NULL)) + dereference = (newEditDef->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(newEditDef, (char *)NULL, TRUE, dereference, NULL)) return FALSE; DBReComputeBbox(newEditDef); diff --git a/graphics/grTCairo1.c b/graphics/grTCairo1.c index 7e293d2f..e84789a0 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(); 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/lef/defRead.c b/lef/defRead.c index d513315e..bc182fff 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: @@ -775,11 +793,12 @@ enum def_orient {DEF_NORTH, DEF_SOUTH, DEF_EAST, DEF_WEST, DEF_FLIPPED_WEST}; int -DefReadLocation(use, f, oscale, tptr) +DefReadLocation(use, f, oscale, tptr, noplace) CellUse *use; FILE *f; float oscale; Transform *tptr; + bool noplace; { Rect *r, tr, rect; int keyword; @@ -791,21 +810,32 @@ DefReadLocation(use, f, oscale, tptr) "N", "S", "E", "W", "FN", "FS", "FE", "FW" }; - token = LefNextToken(f, TRUE); - if (*token != '(') goto parse_error; - token = LefNextToken(f, TRUE); - if (sscanf(token, "%f", &x) != 1) goto parse_error; - token = LefNextToken(f, TRUE); - if (sscanf(token, "%f", &y) != 1) goto parse_error; - token = LefNextToken(f, TRUE); - if (*token != ')') goto parse_error; - token = LefNextToken(f, TRUE); - - keyword = Lookup(token, orientations); - if (keyword < 0) + if (noplace) { - LefError(DEF_ERROR, "Unknown macro orientation \"%s\".\n", token); - return -1; + LefError(DEF_WARNING, "Unplaced component \"%s\" will be put at origin.\n", + use->cu_id); + x = 0; + y = 0; + keyword = DEF_NORTH; + } + else + { + token = LefNextToken(f, TRUE); + if (*token != '(') goto parse_error; + token = LefNextToken(f, TRUE); + if (sscanf(token, "%f", &x) != 1) goto parse_error; + token = LefNextToken(f, TRUE); + if (sscanf(token, "%f", &y) != 1) goto parse_error; + token = LefNextToken(f, TRUE); + if (*token != ')') goto parse_error; + token = LefNextToken(f, TRUE); + + keyword = Lookup(token, orientations); + if (keyword < 0) + { + LefError(DEF_ERROR, "Unknown macro orientation \"%s\".\n", token); + return -1; + } } /* The standard transformations are all defined to rotate */ @@ -1062,7 +1092,7 @@ DefReadPins(f, rootDef, sname, oscale, total) break; case DEF_PINS_PROP_FIXED: case DEF_PINS_PROP_PLACED: - DefReadLocation(NULL, f, oscale, &t); + DefReadLocation(NULL, f, oscale, &t, FALSE); if (curlayer == -1) pending = TRUE; else @@ -1275,6 +1305,35 @@ DefReadVias(f, sname, oscale, total) blayer = LefReadLayer(f, FALSE); clayer = LefReadLayer(f, FALSE); tlayer = LefReadLayer(f, FALSE); + + /* Provisional behavior: A known tool generating */ + /* DEF uses the order (bottom, top, cut). This may */ + /* be a bug in the tool and an issue is being */ + /* raised. However, there is no harm in detecting */ + /* which layer is the cut and swapping as needed. */ + + if (!DBIsContact(clayer)) + { + TileType swaplayer; + LefError(DEF_WARNING, "Improper layer order for" + " VIARULE.\n"); + if (DBIsContact(tlayer)) + { + swaplayer = clayer; + clayer = tlayer; + tlayer = swaplayer; + } + else if (DBIsContact(blayer)) + { + swaplayer = clayer; + clayer = blayer; + blayer = swaplayer; + } + else + LefError(DEF_ERROR, "No cut layer specified in" + " VIARULE.\n"); + } + generated = TRUE; break; case DEF_VIAS_PROP_CUTSPACING: @@ -1450,18 +1509,22 @@ DefReadComponents(f, rootDef, sname, oscale, total) /* Does use name contain brackets? If so, this can */ /* interfere with magic's use of arrays. */ + /* NOTE: This has been commented out. I think */ + /* the only confusion is in ext2spice and can be */ + /* avoided by allowing any bracket notation in an */ + /* instance name other than that used by the .ext */ + /* file for dealing with arrays, which uses the */ + /* specific syntax [xlo:xsep:xhi][ylo:ysep:yhi] and */ + /* is easy enough to distinguish. */ - /* NOTE: It is not clear that this needs to be */ - /* done during DEF read. The only confusion comes */ - /* from the arrays being parsed by ExtFlat when */ - /* doing ext2spice. */ - - dptr = strchr(usename, '['); - if (dptr != NULL) { - *dptr = '_'; - dptr = strchr(dptr + 1, ']'); - if (dptr != NULL) *dptr = '_'; - } + /* + dptr = strchr(usename, '['); + if (dptr != NULL) { + *dptr = '_'; + dptr = strchr(dptr + 1, ']'); + if (dptr != NULL) *dptr = '_'; + } + */ token = LefNextToken(f, TRUE); @@ -1471,11 +1534,14 @@ DefReadComponents(f, rootDef, sname, oscale, total) if (defMacro == (CellDef *)NULL) { + bool dereference; + /* Before giving up, assume that this cell has a */ /* magic .mag layout file. */ defMacro = DBCellNewDef(token, (char *)NULL); defMacro->cd_flags &= ~CDNOTFOUND; - if (!DBCellRead(defMacro, (char *)NULL, TRUE, NULL)) + dereference = (defMacro->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; + if (!DBCellRead(defMacro, (char *)NULL, TRUE, dereference, NULL)) { LefError(DEF_ERROR, "Cell %s is not defined. Maybe you " "have not read the corresponding LEF file?\n", @@ -1518,10 +1584,12 @@ DefReadComponents(f, rootDef, sname, oscale, total) switch (subkey) { case DEF_PROP_PLACED: - case DEF_PROP_UNPLACED: case DEF_PROP_FIXED: case DEF_PROP_COVER: - DefReadLocation(defUse, f, oscale, &t); + DefReadLocation(defUse, f, oscale, &t, FALSE); + break; + case DEF_PROP_UNPLACED: + DefReadLocation(defUse, f, oscale, &t, TRUE); break; case DEF_PROP_SOURCE: case DEF_PROP_WEIGHT: @@ -1598,8 +1666,9 @@ enum def_sections {DEF_VERSION = 0, DEF_NAMESCASESENSITIVE, DEF_END}; void -DefRead(inName) +DefRead(inName, dolabels) char *inName; + bool dolabels; { CellDef *rootDef; FILE *f; @@ -1775,13 +1844,15 @@ DefRead(inName) token = LefNextToken(f, TRUE); if (sscanf(token, "%d", &total) != 1) total = 0; LefEndStatement(f); - DefReadNets(f, rootDef, sections[DEF_SPECIALNETS], oscale, TRUE, total); + DefReadNets(f, rootDef, sections[DEF_SPECIALNETS], oscale, TRUE, + dolabels, total); break; case DEF_NETS: token = LefNextToken(f, TRUE); if (sscanf(token, "%d", &total) != 1) total = 0; LefEndStatement(f); - DefReadNets(f, rootDef, sections[DEF_NETS], oscale, FALSE, total); + DefReadNets(f, rootDef, sections[DEF_NETS], oscale, FALSE, + dolabels, total); break; case DEF_IOTIMINGS: LefSkipSection(f, sections[DEF_IOTIMINGS]); diff --git a/lef/lefCmd.c b/lef/lefCmd.c index 546988db..b5ba0b12 100644 --- a/lef/lefCmd.c +++ b/lef/lefCmd.c @@ -87,6 +87,15 @@ CmdLef(w, cmd) * the macro other than pin area * immediately surrounding labels. */ + bool recurse = FALSE; /* If TRUE, recurse on all subcells + * during "writeall". By default, + * only the immediate children of the + * top level cell are output. + */ + bool defLabelNets = FALSE; /* If TRUE, attach a label to the + * center of the first rectangle + * found on that net. + */ static char *cmdLefOption[] = { @@ -95,7 +104,9 @@ CmdLef(w, cmd) "write [filename] [-tech] write LEF for current cell\n" " write [filename] -hide hide all details other than ports", "writeall write all cells including the top-level cell\n" - " writeall -notop write all subcells of the top-level cell", + " writeall -notop write all children of the top-level cell\n" + " writeall -all recurse on all subcells of the top-level cell\n", + " writeall -hide hide all details other than ports", "help print this help information", NULL }; @@ -103,7 +114,8 @@ CmdLef(w, cmd) static char *cmdDefOption[] = { "read [filename] read a DEF file filename[.def]", - "write [cell] [-allspecial] write DEF for current or indicated cell", + "write [cell] [-allspecial] write DEF for current or indicated cell\n", + "write -labels label every net in NETS with the net name", "writeall (use \"flatten -nosubckt\" + \"def" " write\" instead)", "help print this help information", @@ -151,22 +163,32 @@ CmdLef(w, cmd) switch (option) { case LEF_READ: - if (cmd->tx_argc != 3) + if (cmd->tx_argc > 3) { - if (cmd->tx_argc == 4) + for (i = 3; i < cmd->tx_argc; i++) { - if (*(cmd->tx_argv[3]) == '-') - if (!strncmp(cmd->tx_argv[3], "-import", 7)) + if (*(cmd->tx_argv[i]) == '-') + { + if (!strncmp(cmd->tx_argv[i], "-import", 7)) lefImport = TRUE; + else if (!strncmp(cmd->tx_argv[i], "-label", 6)) + { + if (is_lef) + TxPrintf("The \"-labels\" option is only for def read\n"); + else + defLabelNets = TRUE; + } + } } - else - goto wrongNumArgs; } + else if (cmd->tx_argc < 3) + goto wrongNumArgs; + namep = cmd->tx_argv[2]; if (is_lef) LefRead(namep, lefImport); else - DefRead(namep); + DefRead(namep, defLabelNets); break; case LEF_WRITEALL: if (!is_lef) @@ -184,11 +206,15 @@ CmdLef(w, cmd) lefTopCell = FALSE; else if (!strncmp(cmd->tx_argv[i], "-tech", 5)) lefTech = TRUE; + else if (!strncmp(cmd->tx_argv[i], "-hide", 5)) + lefHide = TRUE; + else if (!strncmp(cmd->tx_argv[i], "-all", 4)) + recurse = TRUE; else goto wrongNumArgs; } else goto wrongNumArgs; } - LefWriteAll(selectedUse, lefTopCell, lefTech); + LefWriteAll(selectedUse, lefTopCell, lefTech, lefHide, recurse); } break; case LEF_WRITE: diff --git a/lef/lefRead.c b/lef/lefRead.c index 22978f7c..cbe484ec 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: @@ -1737,10 +1770,18 @@ origin_error: * * For LEF contact types matching magic contact types, size the * LEF contact cut to cover the minimum rectangle in the other - * layers that satisfies the CIF/GDS contact generation. Use - * the "cifinput" style to determine how much the via layer - * needs to grow to make a contact area. If the "cifinput" - * style is not defined, then determine rules from "cifoutput". + * layers that satisfies the CIF/GDS contact generation. + * + * NOTE: If a "cifinput" style is defined, then the via + * remains the size declared in LEF or DEF file, and the + * magic view of the via is generated by applying "cifinput" + * rules when painting into the magic database. If no input + * style is defined, then the output style rules are used to + * modify the cut size to match the way the via is defined in + * magic, and the result is painted directly. + * + * If a "cifinput" style exists, then this routine does + * nothing and has no side effects. * *------------------------------------------------------------ */ @@ -1750,36 +1791,10 @@ void LefGrowVia(curlayer, currect, lefl) Rect *currect; lefLayer *lefl; { - if (DBIsContact(curlayer) && cifCurReadStyle != NULL) - { - int growSize; + /* To be completed: This should be deprecated by moving the entire */ + /* LEF and DEF read routines to use the cifinput style. */ - /* Get the amount (in magic units) that the layer needs to */ - /* expand according to the "cifinput" style rules to convert */ - /* a contact cut to a magic contact layer. */ - - growSize = CIFReadGetGrowSize(curlayer); - - /* All internal LEF via geometry values are doubled */ - growSize <<= 1; - - if (growSize % cifCurReadStyle->crs_scaleFactor == 0) - growSize /= cifCurReadStyle->crs_scaleFactor; - else - growSize = growSize / cifCurReadStyle->crs_scaleFactor + 1; - - if (growSize > 0) - { - /* cifinput styles expect the cut size to be correct, so */ - /* there is no check for correctness of the layer. */ - - currect->r_xbot = currect->r_xbot - growSize; - currect->r_ybot = currect->r_ybot - growSize; - currect->r_xtop = currect->r_xtop + growSize; - currect->r_ytop = currect->r_ytop + growSize; - } - } - else if (DBIsContact(curlayer) && CIFCurStyle != NULL) + if (DBIsContact(curlayer) && CIFCurStyle != NULL) { int edgeSize = 0, contSize, halfSize; 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)) diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 30859c11..b522684c 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -83,6 +83,8 @@ lefFileOpen(def, file, suffix, mode, prealfile) */ { char namebuf[512], *name, *endp, *ends; + char *locsuffix; + char *pptr; int len; FILE *rfile; @@ -108,21 +110,26 @@ lefFileOpen(def, file, suffix, mode, prealfile) if (endp = strrchr(ends, '.')) { - if (!strcmp(endp, suffix)) + if (strcmp(endp, suffix)) { len = endp - name; if (len > sizeof namebuf - 1) len = sizeof namebuf - 1; (void) strncpy(namebuf, name, len); namebuf[len] = '\0'; name = namebuf; + locsuffix = suffix; } + else + locsuffix = NULL; } + else + locsuffix = suffix; /* Try once as-is, and if this fails, try stripping any leading */ /* path information in case cell is in a read-only directory (mode */ /* "read" only, and if def is non-NULL). */ - if ((rfile = PaOpen(name, mode, suffix, Path, CellLibPath, prealfile)) != NULL) + if ((rfile = PaOpen(name, mode, locsuffix, Path, CellLibPath, prealfile)) != NULL) return rfile; if (def) @@ -634,7 +641,7 @@ lefWriteMacro(def, f, scale, hide) { bool propfound; char *propvalue, *class = NULL; - Label *lab; + Label *lab, *tlab; Rect boundary, labr; SearchContext scx; CellDef *lefFlatDef; @@ -772,6 +779,20 @@ lefWriteMacro(def, f, scale, hide) else boundary = def->cd_bbox; + /* If a bounding box has been declared with the FIXED_BBOX property */ + /* then it takes precedence over def->cd_bbox. */ + + if (def->cd_flags & CDFIXEDBBOX) + { + char *propvalue; + bool found; + + propvalue = (char *)DBPropGet(def, "FIXED_BBOX", &found); + if (found) + sscanf(propvalue, "%d %d %d %d", &boundary.r_xbot, + &boundary.r_ybot, &boundary.r_xtop, &boundary.r_ytop); + } + /* Write position and size information */ fprintf(f, " ORIGIN %.4f %.4f ;\n", @@ -927,7 +948,18 @@ lefWriteMacro(def, f, scale, hide) SelectClear(); if (hide) + { SelectChunk(&scx, lab->lab_type, 0, NULL, FALSE); + + /* Note that a sticky label could be placed over multiple */ + /* tile types, which would cause SelectChunk to fail. So */ + /* always paint the label type into the label area in */ + /* SelectDef. */ + + pNum = DBPlane(lab->lab_type); + DBPaintPlane(SelectDef->cd_planes[pNum], &lab->lab_rect, + DBStdPaintTbl(lab->lab_type, pNum), (PaintUndoInfo *) NULL); + } else SelectNet(&scx, lab->lab_type, 0, NULL, FALSE); @@ -964,15 +996,21 @@ lefWriteMacro(def, f, scale, hide) if (maxport >= 0) { - /* Sanity check to see if port number is a duplicate */ - for (lab = lab->lab_next; lab != NULL; lab = lab->lab_next) + /* Sanity check to see if port number is a duplicate. ONLY */ + /* flag this if the other index has a different text, as it */ + /* is perfectly legal to have multiple ports with the same */ + /* name and index. */ + + for (tlab = lab->lab_next; tlab != NULL; tlab = tlab->lab_next) { - if (lab->lab_flags & PORT_DIR_MASK) - if ((lab->lab_flags & PORT_NUM_MASK) == idx) - { - TxError("Port index %d is used more than once\n", idx); - idx--; - } + if (tlab->lab_flags & PORT_DIR_MASK) + if ((tlab->lab_flags & PORT_NUM_MASK) == idx) + if (strcmp(lab->lab_text, lab->lab_text)) + { + TxError("Index %d is used for ports \"%s\" and \"%s\"\n", + idx, lab->lab_text, tlab->lab_text); + idx--; + } } } else @@ -1030,6 +1068,7 @@ lefWriteMacro(def, f, scale, hide) scx.scx_area = labr; SelectClear(); SelectChunk(&scx, lab->lab_type, 0, &carea, FALSE); + if (GEO_RECTNULL(&carea)) carea = lab->lab_rect; lspace = DRCGetDefaultLayerSpacing(lab->lab_type, lab->lab_type); carea.r_xbot -= lspace; carea.r_ybot -= lspace; @@ -1094,10 +1133,12 @@ lefWriteMacro(def, f, scale, hide) */ void -LefWriteAll(rootUse, writeTopCell, lefTech) +LefWriteAll(rootUse, writeTopCell, lefTech, lefHide, recurse) CellUse *rootUse; bool writeTopCell; bool lefTech; + bool lefHide; + bool recurse; { CellDef *def, *rootdef; FILE *f; @@ -1116,8 +1157,12 @@ LefWriteAll(rootUse, writeTopCell, lefTech) (void) DBCellSrDefs(0, lefDefInitFunc, (ClientData) 0); /* Recursively visit all defs in the tree and push on stack */ + /* If "recurse" is false, then only the children of the root use */ + /* are pushed (this is the default behavior). */ lefDefStack = StackNew(100); - (void) lefDefPushFunc(rootUse); + if (writeTopCell) + lefDefPushFunc(rootUse, (bool *)NULL); + DBCellEnum(rootUse->cu_def, lefDefPushFunc, (ClientData)&recurse); /* Open the file for output */ @@ -1146,8 +1191,7 @@ LefWriteAll(rootUse, writeTopCell, lefTech) { def->cd_client = (ClientData) 0; if (!SigInterruptPending) - if ((writeTopCell == TRUE) || (def != rootdef)) - lefWriteMacro(def, f, scale); + lefWriteMacro(def, f, scale, lefHide); } /* End the LEF file */ @@ -1178,8 +1222,9 @@ lefDefInitFunc(def) */ int -lefDefPushFunc(use) +lefDefPushFunc(use, recurse) CellUse *use; + bool *recurse; { CellDef *def = use->cu_def; @@ -1188,7 +1233,8 @@ lefDefPushFunc(use) def->cd_client = (ClientData) 1; StackPush((ClientData) def, lefDefStack); - (void) DBCellEnum(def, lefDefPushFunc, (ClientData) 0); + if (recurse && (*recurse)) + (void) DBCellEnum(def, lefDefPushFunc, (ClientData)recurse); return (0); } 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 1f8a857b..62a5815b 100644 --- a/magic/Makefile +++ b/magic/Makefile @@ -29,8 +29,8 @@ EXTRA_LIBS = ${MAGICDIR}/bplane/libbplane.o \ ${MAGICDIR}/utils/libutils.o \ ${MAIN_EXTRA_LIBS} -BITMAPS = up.xbm down.xbm left.xbm right.xbm zoom.xbm lock.xbm -DEST_XBM = $(BITMAPS:%=$(DESTDIR)${TCLDIR}/bitmaps/%) +BITMAPS = up.gif down.gif left.gif right.gif zoom.gif lock.xbm +DEST_XBM = $(BITMAPS:%=$(DESTDIR)${INSTALL_TCLDIR}/bitmaps/%) DFLAGS += -DMAGIC_DATE="\"`date`\"" -DCAD_DIR="${LIBDIR}" LIBS += ${GR_LIBS} ${READLINE_LIBS} -lm ${LD_EXTRA_LIBS} \ @@ -49,32 +49,32 @@ tclmagic${SHDLIB_EXT}: ${EXTRA_LIBS} -lc ${LIBS} ${LIB_SPECS} ${LDFLAGS} proto.magicrc: proto.magicrc.in - ${SCPP} ${GR_DFLAGS} ${DFLAGS} proto.magicrc.in > proto.magicrc + ${MCPP} ${GR_DFLAGS} ${DFLAGS} proto.magicrc.in > proto.magicrc -install: $(DESTDIR)${BINDIR}/${MODULE}${EXEEXT} $(DESTDIR)${SYSDIR}/.magicrc \ - $(DESTDIR)${SYSDIR}/magicps.pro +install: $(DESTDIR)${INSTALL_BINDIR}/${MODULE}${EXEEXT} $(DESTDIR)${INSTALL_SYSDIR}/.magicrc \ + $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro -install-tcl: $(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT} $(DESTDIR)${SYSDIR}/.magicrc \ - $(DESTDIR)${SYSDIR}/.initrc $(DESTDIR)${SYSDIR}/magicps.pro ${DEST_XBM} +install-tcl: $(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT} $(DESTDIR)${INSTALL_SYSDIR}/.magicrc \ + $(DESTDIR)${INSTALL_SYSDIR}/.initrc $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro ${DEST_XBM} -$(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT}: tclmagic${SHDLIB_EXT} - ${RM} $(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT} - ${CP} tclmagic${SHDLIB_EXT} $(DESTDIR)${TCLDIR}/tclmagic${SHDLIB_EXT} +$(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT}: tclmagic${SHDLIB_EXT} + ${RM} $(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT} + ${CP} tclmagic${SHDLIB_EXT} $(DESTDIR)${INSTALL_TCLDIR}/tclmagic${SHDLIB_EXT} -$(DESTDIR)${TCLDIR}/bitmaps/%: bitmaps/% - ${RM} $(DESTDIR)${TCLDIR}/bitmaps/$* - ${CP} bitmaps/$* $(DESTDIR)${TCLDIR}/bitmaps/$* +$(DESTDIR)${INSTALL_TCLDIR}/bitmaps/%: bitmaps/% + ${RM} $(DESTDIR)${INSTALL_TCLDIR}/bitmaps/$* + ${CP} bitmaps/$* $(DESTDIR)${INSTALL_TCLDIR}/bitmaps/$* -$(DESTDIR)${SYSDIR}/.magicrc: proto.magicrc - ${RM} $(DESTDIR)${SYSDIR}/.magicrc - ${CP} proto.magicrc $(DESTDIR)${SYSDIR}/.magicrc +$(DESTDIR)${INSTALL_SYSDIR}/.magicrc: proto.magicrc + ${RM} $(DESTDIR)${INSTALL_SYSDIR}/.magicrc + ${CP} proto.magicrc $(DESTDIR)${INSTALL_SYSDIR}/.magicrc -$(DESTDIR)${SYSDIR}/.initrc: proto.initrc - ${RM} $(DESTDIR)${SYSDIR}/.initrc - ${CP} proto.initrc $(DESTDIR)${SYSDIR}/.initrc +$(DESTDIR)${INSTALL_SYSDIR}/.initrc: proto.initrc + ${RM} $(DESTDIR)${INSTALL_SYSDIR}/.initrc + ${CP} proto.initrc $(DESTDIR)${INSTALL_SYSDIR}/.initrc -$(DESTDIR)${SYSDIR}/magicps.pro: magicps.pro - ${RM} $(DESTDIR)${SYSDIR}/magicps.pro - ${CP} magicps.pro $(DESTDIR)${SYSDIR}/magicps.pro +$(DESTDIR)${INSTALL_SYSDIR}/magicps.pro: magicps.pro + ${RM} $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro + ${CP} magicps.pro $(DESTDIR)${INSTALL_SYSDIR}/magicps.pro include ${MAGICDIR}/rules.mak diff --git a/magic/bitmaps/down.gif b/magic/bitmaps/down.gif new file mode 100644 index 00000000..7962f6f5 Binary files /dev/null and b/magic/bitmaps/down.gif differ diff --git a/magic/bitmaps/left.gif b/magic/bitmaps/left.gif new file mode 100644 index 00000000..85b7e28c Binary files /dev/null and b/magic/bitmaps/left.gif differ diff --git a/magic/bitmaps/right.gif b/magic/bitmaps/right.gif new file mode 100644 index 00000000..11853ba8 Binary files /dev/null and b/magic/bitmaps/right.gif differ diff --git a/magic/bitmaps/up.gif b/magic/bitmaps/up.gif new file mode 100644 index 00000000..7f46b82a Binary files /dev/null and b/magic/bitmaps/up.gif differ diff --git a/magic/bitmaps/zoom.gif b/magic/bitmaps/zoom.gif new file mode 100644 index 00000000..a05342d4 Binary files /dev/null and b/magic/bitmaps/zoom.gif differ 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/resis/Depend b/resis/Depend index 3ceed50d..afdbda71 100644 --- a/resis/Depend +++ b/resis/Depend @@ -21,7 +21,7 @@ ResMakeRes.o: ResMakeRes.c ../utils/magic.h ../utils/geometry.h \ ../bplane/bplaneInt.h ../utils/malloc.h ../textio/textio.h \ ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ ../windows/windows.h ../dbwind/dbwind.h ../utils/tech.h \ - ../textio/txcommands.h ../resis/resis.h + ../textio/txcommands.h ../resis/resis.h ../cif/CIFint.h ResSimple.o: ResSimple.c ../utils/magic.h ../utils/geometry.h \ ../utils/geofast.h ../tiles/tile.h ../utils/hash.h ../utils/heap.h \ ../database/database.h ../bplane/bplane.h ../bplane/bpOpaque.h \ diff --git a/resis/ResBasic.c b/resis/ResBasic.c index 24721e10..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. * * *-------------------------------------------------------------------------- @@ -139,6 +139,7 @@ ResEachTile(tile, startpoint) bool merged; tElement *tcell; tileJunk *tstructs= (tileJunk *)(tile->ti_client); + ExtDevice *devptr; ResTileCount++; @@ -165,24 +166,24 @@ ResEachTile(tile, startpoint) resNodeIsPort(resptr, x, y, tile); } - if TTMaskHasType(&(ExtCurStyle->exts_transMask), t1) + if TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t1) { /* - * The transistor is put in the center of the tile. This is fine - * for single tile transistors, but not as good for multiple ones. + * The device is put in the center of the tile. This is fine + * for single tile device, but not as good for multiple ones. */ - if (tstructs->tj_status & RES_TILE_TRAN) + if (tstructs->tj_status & RES_TILE_DEV) { - if (tstructs->transistorList->rt_gate == NULL) + if (tstructs->deviceList->rd_fet_gate == NULL) { int x = (LEFT(tile) + RIGHT(tile)) >> 1; int y = (TOP(tile) + BOTTOM(tile)) >> 1; resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); - tstructs->transistorList->rt_gate = resptr; + tstructs->deviceList->rd_fet_gate = resptr; tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement))); - tcell->te_thist = tstructs->transistorList; + tcell->te_thist = tstructs->deviceList; tcell->te_nextt = NULL; InitializeNode(resptr, x, y, RES_NODE_JUNCTION); @@ -219,7 +220,7 @@ ResEachTile(tile, startpoint) { (void)DBSrPaintArea((Tile *) NULL, ResUse->cu_def->cd_planes[pNum], - &tileArea, mask, resSubTranFunc, (ClientData) tile); + &tileArea, mask, resSubDevFunc, (ClientData) tile); } } } @@ -250,13 +251,14 @@ ResEachTile(tile, startpoint) for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp)) { t2 = TiGetRightType(tp); - if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1)) - /* found transistor */ + devptr = ExtCurStyle->exts_device[t2]; + if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) + /* found device */ { xj = LEFT(tile); yj = (TOP(tp) + BOTTOM(tp)) >> 1; - ResNewSDTransistor(tile, tp, xj, yj, RIGHTEDGE, &ResNodeQueue); + ResNewSDDevice(tile, tp, xj, yj, RIGHTEDGE, &ResNodeQueue); } if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2) /* tile is junction */ @@ -272,13 +274,14 @@ ResEachTile(tile, startpoint) for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp)) { t2 = TiGetLeftType(tp); - if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1)) - /* found transistor */ + devptr = ExtCurStyle->exts_device[t2]; + if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) + /* found device */ { xj = RIGHT(tile); yj = (TOP(tp)+BOTTOM(tp))>>1; - ResNewSDTransistor(tile, tp, xj, yj, LEFTEDGE, &ResNodeQueue); + ResNewSDDevice(tile, tp, xj, yj, LEFTEDGE, &ResNodeQueue); } if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1], t2) /* tile is junction */ @@ -294,13 +297,14 @@ ResEachTile(tile, startpoint) for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp)) { t2 = TiGetBottomType(tp); - if(TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) - /* found transistor */ + devptr = ExtCurStyle->exts_device[t2]; + if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) + /* found device */ { yj = TOP(tile); xj = (LEFT(tp)+RIGHT(tp))>>1; - ResNewSDTransistor(tile,tp,xj,yj,BOTTOMEDGE, &ResNodeQueue); + ResNewSDDevice(tile,tp,xj,yj,BOTTOMEDGE, &ResNodeQueue); } if TTMaskHasType(&ExtCurStyle->exts_nodeConn[t1],t2) /* tile is junction */ @@ -315,13 +319,14 @@ ResEachTile(tile, startpoint) for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp)) { t2 = TiGetTopType(tp); - if(TTMaskHasType(&(ExtCurStyle->exts_transMask), t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]), t1)) - /* found transistor */ + devptr = ExtCurStyle->exts_device[t2]; + if(TTMaskHasType(&(ExtCurStyle->exts_deviceMask), t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), t1)) + /* found device */ { yj = BOTTOM(tile); xj = (LEFT(tp) + RIGHT(tp)) >> 1; - ResNewSDTransistor(tile, tp, xj, yj, TOPEDGE, &ResNodeQueue); + ResNewSDDevice(tile, tp, xj, yj, TOPEDGE, &ResNodeQueue); } if TTMaskHasType(&(ExtCurStyle->exts_nodeConn[t1]), t2) /* tile is junction */ @@ -344,7 +349,7 @@ ResEachTile(tile, startpoint) /* *------------------------------------------------------------------------- * - * resSubTranFunc -- called when DBSrPaintArea finds a transistor within + * resSubDevFunc -- called when DBSrPaintArea finds a device within * a substrate area. * * Results: always returns 0 to keep search going. @@ -355,7 +360,7 @@ ResEachTile(tile, startpoint) */ int -resSubTranFunc(tile,tp) +resSubDevFunc(tile,tp) Tile *tile,*tp; @@ -365,13 +370,13 @@ resSubTranFunc(tile,tp) tElement *tcell; int x,y; - if (junk->transistorList->rt_subs== NULL) + if (junk->deviceList->rd_fet_subs == NULL) { resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode))); - junk->transistorList->rt_subs = resptr; - junk->tj_status |= RES_TILE_TRAN; + junk->deviceList->rd_fet_subs = resptr; + junk->tj_status |= RES_TILE_DEV; tcell = (tElement *) mallocMagic((unsigned)(sizeof(tElement))); - tcell->te_thist = junk->transistorList; + tcell->te_thist = junk->deviceList; tcell->te_nextt = NULL; x = (LEFT(tile)+RIGHT(tile))>>1; y = (TOP(tile)+BOTTOM(tile))>>1; 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 aea2ab4a..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; @@ -102,6 +102,7 @@ dbcConnectFuncDCS(tile, cx) SearchContext scx2; int pNum; CellDef *def; + ExtDevice *devptr; TiToRect(tile, &tileArea); srArea = &scx->scx_area; @@ -121,79 +122,83 @@ dbcConnectFuncDCS(tile, cx) for (tp = BL(tile); BOTTOM(tp) < TOP(tile); tp=RT(tp)) { t2 = TiGetType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + devptr = ExtCurStyle->exts_device[t2]; + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { - TiToRect(tp, &tranArea); - thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); - ResCalcPerimOverlap(thisTran,tp); - GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area); - thisTran->type = TiGetType(tp); - thisTran->nextTran = TransList; - TransList = thisTran; + TiToRect(tp, &devArea); + thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile))); + ResCalcPerimOverlap(thisDev,tp); + GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area); + thisDev->type = TiGetType(tp); + thisDev->nextDev = DevList; + DevList = thisDev; } } /*right*/ for (tp = TR(tile); TOP(tp) > BOTTOM(tile); tp=LB(tp)) { t2 = TiGetType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + devptr = ExtCurStyle->exts_device[t2]; + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { - TiToRect(tp, &tranArea); - thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); - GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area); - thisTran->type = TiGetType(tp); - thisTran->nextTran = TransList; - TransList = thisTran; - ResCalcPerimOverlap(thisTran,tp); + TiToRect(tp, &devArea); + thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile))); + GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area); + thisDev->type = TiGetType(tp); + thisDev->nextDev = DevList; + DevList = thisDev; + ResCalcPerimOverlap(thisDev,tp); } } /*top*/ for (tp = RT(tile); RIGHT(tp) > LEFT(tile); tp=BL(tp)) { t2 = TiGetType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + devptr = ExtCurStyle->exts_device[t2]; + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { - TiToRect(tp, &tranArea); - thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); - GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area); - thisTran->type = TiGetType(tp); - thisTran->nextTran = TransList; - TransList = thisTran; - ResCalcPerimOverlap(thisTran,tp); + TiToRect(tp, &devArea); + thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile))); + GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area); + thisDev->type = TiGetType(tp); + thisDev->nextDev = DevList; + DevList = thisDev; + ResCalcPerimOverlap(thisDev,tp); } } /*bottom */ for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp=TR(tp)) { t2 = TiGetType(tp); - if (TTMaskHasType(&(ExtCurStyle->exts_transMask),t2) && - TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[t2][0]),t1)) + devptr = ExtCurStyle->exts_device[t2]; + if (TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t2) && + TTMaskHasType(&(devptr->exts_deviceSDTypes[0]),t1)) { - TiToRect(tp, &tranArea); - thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); - GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area); - thisTran->type = TiGetType(tp); - thisTran->nextTran = TransList; - TransList = thisTran; - ResCalcPerimOverlap(thisTran,tp); + TiToRect(tp, &devArea); + thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile))); + GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area); + thisDev->type = TiGetType(tp); + thisDev->nextDev = DevList; + DevList = thisDev; + ResCalcPerimOverlap(thisDev,tp); } } } - else if TTMaskHasType(&(ExtCurStyle->exts_transMask),t1) + else if TTMaskHasType(&(ExtCurStyle->exts_deviceMask),t1) { - TiToRect(tile, &tranArea); - thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); - ResCalcPerimOverlap(thisTran,tile); - GeoTransRect(&scx->scx_trans, &tranArea, &thisTran->area); - thisTran->type = TiGetType(tile); - thisTran->nextTran = TransList; - TransList = thisTran; + TiToRect(tile, &devArea); + thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile))); + ResCalcPerimOverlap(thisDev,tile); + GeoTransRect(&scx->scx_trans, &devArea, &thisDev->area); + thisDev->type = TiGetType(tile); + thisDev->nextDev = DevList; + DevList = thisDev; } /* in some cases (primarily bipolar technology), we'll want to extract - transistors whose substrate terminals are part of the given region. + devices whose substrate terminals are part of the given region. The following does that check. (10-11-88) */ #ifdef ARIEL @@ -333,8 +338,8 @@ dbcConnectFuncDCS(tile, cx) */ void -ResCalcPerimOverlap(trans, tile) - ResTranTile *trans; +ResCalcPerimOverlap(dev, tile) + ResDevTile *dev; Tile *tile; { @@ -342,7 +347,7 @@ ResCalcPerimOverlap(trans, tile) int t1; int overlap; - trans->perim = (TOP(tile)-BOTTOM(tile)-LEFT(tile)+RIGHT(tile))<<1; + dev->perim = (TOP(tile)-BOTTOM(tile)-LEFT(tile)+RIGHT(tile))<<1; overlap =0; t1 = TiGetType(tile); @@ -386,7 +391,7 @@ ResCalcPerimOverlap(trans, tile) } } - trans->overlap = overlap; + dev->overlap = overlap; } @@ -399,7 +404,7 @@ ResCalcPerimOverlap(trans, tile) * dbcConnectFuncDCS. * * Results: - * Linked list of transistors. + * Linked list of devices. * * Side effects: * The contents of the result cell are modified. @@ -407,7 +412,7 @@ ResCalcPerimOverlap(trans, tile) * ---------------------------------------------------------------------------- */ -ResTranTile * +ResDevTile * DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) SearchContext *scx; TileTypeBitMask *mask; @@ -419,12 +424,13 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) { static int first = 1; struct conSrArg2 csa2; - int tran, pNum; - char *tran_name; + int dev, pNum; + char *dev_name; TileTypeBitMask *newmask; - ResTranTile *CurrentT; + ResDevTile *CurrentT; CellDef *def = destUse->cu_def; TileType newtype; + ExtDevice *devptr; csa2.csa2_use = destUse; csa2.csa2_xMask = xMask; @@ -441,21 +447,22 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) { TTMaskZero(&DiffTypeBitMask); TTMaskZero(&ResSubsTypeBitMask); - for (tran = TT_TECHDEPBASE; tran < TT_MAXTYPES; tran++) + for (dev = TT_TECHDEPBASE; dev < TT_MAXTYPES; dev++) { - tran_name = (ExtCurStyle->exts_transName)[tran]; - if ((tran_name != NULL) && (strcmp(tran_name, "None"))) + devptr = ExtCurStyle->exts_device[dev]; + if ((devptr != NULL) && ((dev_name = devptr->exts_deviceName) != NULL) + && (strcmp(dev_name, "None"))) { TTMaskSetMask(&DiffTypeBitMask, - &(ExtCurStyle->exts_transSDTypes[tran][0])); + &(devptr->exts_deviceSDTypes[0])); TTMaskSetMask(&ResSubsTypeBitMask, - &(ExtCurStyle->exts_transSubstrateTypes[tran])); + &(devptr->exts_deviceSubstrateTypes)); } } first = 0; } - TransList = NULL; + DevList = NULL; DBTreeSrTiles(scx, mask, xMask, dbcConnectFuncDCS, (ClientData) &csa2); while (csa2.csa2_top >= 0) { @@ -471,7 +478,7 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) } freeMagic((char *)csa2.csa2_list); - for (CurrentT = TransList; CurrentT != NULL; CurrentT=CurrentT->nextTran) + for (CurrentT = DevList; CurrentT != NULL; CurrentT=CurrentT->nextDev) { TileType t = CurrentT->type; TileType nt; @@ -489,7 +496,7 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) } DBReComputeBbox(def); - return(TransList); + return(DevList); } @@ -499,7 +506,7 @@ DBTreeCopyConnectDCS(scx, mask, xMask, connect, area, destUse) * * resSubSearchFunc -- * - * called when DBSrPaintArea finds a transistor within + * called when DBSrPaintArea finds a device within * a substrate area. * * Results: @@ -517,22 +524,24 @@ resSubSearchFunc(tile,cx) { - ResTranTile *thisTran; - Rect tranArea; + ResDevTile *thisDev; + Rect devArea; TileType t = TiGetType(tile); + ExtDevice *devptr; /* Right now, we're only going to extract substrate terminals for devices with only one diffusion terminal, principally bipolar devices. */ - if (ExtCurStyle->exts_transSDCount[t] >1) return 0; - TiToRect(tile, &tranArea); - thisTran = (ResTranTile *) mallocMagic((unsigned)(sizeof(ResTranTile))); - GeoTransRect(&cx->tc_scx->scx_trans, &tranArea, &thisTran->area); - thisTran->type = t; - thisTran->nextTran = TransList; - TransList = thisTran; - ResCalcPerimOverlap(thisTran,tile); + devptr = ExtCurStyle->exts_device[t] + if (devptr->exts_deviceSDCount >1) return 0; + TiToRect(tile, &devArea); + thisDev = (ResDevTile *) mallocMagic((unsigned)(sizeof(ResDevTile))); + GeoTransRect(&cx->tc_scx->scx_trans, &devArea, &thisDev->area); + thisDev->type = t; + thisDev->nextDev = DevList; + DevList = thisDev; + ResCalcPerimOverlap(thisDev,tile); return 0; } 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..2c736df2 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); } @@ -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/ResMain.c b/resis/ResMain.c index 1548be5e..18c03850 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,8 +52,8 @@ extern HashTable ResNodeTable; * * ResInitializeConn-- * - * Sets up mask by Source/Drain type of transistors. This is - * exts_transSDtypes turned inside out. + * Sets up mask by Source/Drain type of devices. This is + * exts_deviceSDtypes turned inside out. * * Results: none * @@ -65,24 +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++) { - tran_name = (ExtCurStyle->exts_transName)[tran]; - if ((tran_name != NULL) && (strcmp(tran_name, "None"))) + devptr = ExtCurStyle->exts_device[dev]; + if ((devptr != NULL) && ((dev_name = devptr->exts_deviceName) != NULL) + && (strcmp(dev_name, "None"))) { for (diff = TT_TECHDEPBASE; diff < TT_MAXTYPES; diff++) { - if TTMaskHasType(&(ExtCurStyle->exts_transSDTypes[tran][0]), diff) - TTMaskSetType(&ResConnectWithSD[diff],tran); + if TTMaskHasType(&(devptr->exts_deviceSDTypes[0]), diff) + TTMaskSetType(&ResConnectWithSD[diff],dev); - if TTMaskHasType(&(ExtCurStyle->exts_transSubstrateTypes[tran]),diff) - TTMaskSetType(&ResConnectWithSD[diff],tran); + if TTMaskHasType(&(devptr->exts_deviceSubstrateTypes),diff) + TTMaskSetType(&ResConnectWithSD[diff],dev); } } - TTMaskSetMask(&ResConnectWithSD[tran],&DBConnectTbl[tran]); + TTMaskSetMask(&ResConnectWithSD[dev],&DBConnectTbl[dev]); } } @@ -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); } @@ -571,7 +573,7 @@ ResExtractNet(startlist,goodies,cellname) { SearchContext scx; int pNum; - ResTranTile *TranTiles,*lasttile; + ResDevTile *DevTiles,*lasttile; TileTypeBitMask FirstTileMask; Point startpoint; ResFixPoint *fix; @@ -581,7 +583,7 @@ ResExtractNet(startlist,goodies,cellname) ResResList=NULL; ResNodeList=NULL; - ResTransList=NULL; + ResDevList=NULL; ResNodeQueue=NULL; ResContactList = NULL; ResOriginNode = NULL; @@ -630,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) && @@ -646,21 +648,26 @@ 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); - newtrantiles = DBTreeCopyConnectDCS(&scx, &FirstTileMask, 0, + // 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); - 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; } @@ -694,7 +701,7 @@ ResExtractNet(startlist,goodies,cellname) (void) DBSrPaintClient((Tile *) NULL,plane,rect, &DBAllButSpaceAndDRCBits, (ClientData) CLIENTDEFAULT, ResAddPlumbing, - (ClientData) &ResTransList); + (ClientData) &ResDevList); } /* Finish preprocessing. */ @@ -702,7 +709,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) @@ -754,7 +761,7 @@ ResCleanUpEverything() int pNum; resResistor *oldRes; - resTransistor *oldTran; + resDevice *oldDev; ResContactPoint *oldCon; /* check integrity of internal database. Free up lists. */ @@ -784,13 +791,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); } } @@ -804,7 +812,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 @@ -824,18 +832,43 @@ 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; + /* 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 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; GOTOPOINT(tile, &workingPoint); SourcePoint->p_x = workingPoint.p_x; SourcePoint->p_y = workingPoint.p_y; + if (TiGetTypeExact(tile) == goodies->rg_ttype) return tile; else @@ -859,7 +892,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; } @@ -868,37 +901,38 @@ 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); } 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_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); + TxError("Couldn't find device at %d %d\n", + goodies->rg_devloc->p_x, goodies->rg_devloc->p_y); return(NULL); } 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 +945,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 +958,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 +971,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))+ @@ -951,11 +985,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 @@ -963,8 +997,8 @@ FindStartTile(goodies, SourcePoint) *------------------------------------------------------------------------- */ -resTransistor * -ResGetTransistor(pt) +resDevice * +ResGetDevice(pt) Point *pt; { @@ -977,23 +1011,23 @@ 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; } - /*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); if (IsSplit(tile)) { - if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetLeftType(tile)) - || TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetRightType(tile))) - return(((tileJunk *)tile->ti_client)->transistorList); + if (TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetLeftType(tile)) + || TTMaskHasType(&ExtCurStyle->exts_deviceMask, TiGetRightType(tile))) + return(((tileJunk *)tile->ti_client)->deviceList); } - else if (TTMaskHasType(&ExtCurStyle->exts_transMask, TiGetType(tile))) + 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 1ff30a22..022f9ed1 100644 --- a/resis/ResMakeRes.c +++ b/resis/ResMakeRes.c @@ -24,9 +24,10 @@ 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(); +bool ResCalcNearDevice(); bool ResCalcNorthSouth(); bool ResCalcEastWest(); @@ -57,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) @@ -73,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) { @@ -443,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 @@ -459,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; @@ -484,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; } @@ -579,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; } @@ -650,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. */ @@ -679,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))) { @@ -720,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))) { @@ -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/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 0c93cfcd..49cc3db6 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. */ @@ -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); } } } @@ -97,32 +97,34 @@ 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; - subsName = ExtCurStyle->exts_transSubstrateName[t]; + t = devices->layout->rd_devtype; + devptr = ExtCurStyle->exts_device[t]; + subsName = devptr->exts_deviceSubstrateName; #ifdef MAGIC_WRAPPER /* Substrate variable name substitution */ @@ -133,29 +135,49 @@ ResPrintExtTran(outextfile, transistors) 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", - ExtCurStyle->exts_transName[t], - 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, - 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); + 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); + + 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, + devices->source->name, + devices->layout->rd_width, + devices->rs_sattr, + devices->drain->name, + devices->layout->rd_width, + devices->rs_dattr); } } } @@ -188,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. */ @@ -242,7 +264,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. * @@ -597,7 +619,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. * @@ -612,9 +634,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 fd7ce8bb..c64caa88 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 @@ -79,8 +79,8 @@ 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 */ -char RTRAN_NOATTR[1]={'0'}; +static float resscale=1.0; /* Scale factor */ +char RDEV_NOATTR[1]={'0'}; ResFixPoint *ResFixList; #define nodeinit(n)\ @@ -146,8 +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; + resscale = (float)atof(line[NODELAMBDA]); + if (resscale == 0.0) resscale = 1.0; } result=0; break; @@ -181,14 +181,16 @@ 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) { 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) @@ -225,6 +227,14 @@ ResReadNode(nodefile) HashEntry *entry; ResSimNode *node; char *cp; + float lambda; + + /* 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 = (float)ExtCurStyle->exts_unitsPerLambda; fp = PaOpen(nodefile,"r",".nodes",".", (char *) NULL, (char **) NULL); if (fp == NULL) @@ -237,13 +247,13 @@ 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); + 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])/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]) / 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]); @@ -310,29 +320,30 @@ 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; + float lambda; - 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); @@ -345,23 +356,25 @@ 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->status = FALSE; + device->nextDev = ResRDevList; + + 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); + + 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; @@ -385,18 +398,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); } @@ -415,35 +428,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; @@ -796,7 +809,7 @@ ResSimMerge(line) { ResSimNode *node; - tranPtr *ptr; + devPtr *ptr; if ((line[ALIASNAME][0] == '\0') || (line[REALNAME][0] == '\0')) { @@ -808,12 +821,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); } @@ -850,7 +863,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 a1c98d9e..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 */ -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 */ extern ResSimNode *ResOriginalNodes; /*Linked List of Nodes */ int resNodeNum; @@ -94,21 +92,20 @@ 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 +135,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 +144,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 +203,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 +445,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 +460,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 +719,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 +803,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 +821,7 @@ ResCheckSimNodes(celldef, resisdata) ResisData *resisdata; { ResSimNode *node; - tranPtr *ptr; + devPtr *ptr; float ftolerance, rctolerance, minRes, cumRes; int failed1=0; int failed3=0; @@ -870,13 +867,26 @@ 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. */ if (ResOptionsFlags & ResOpt_FastHenry) { - ResPrintReference(ResFHFile, ResTranList, celldef); + ResPrintReference(ResFHFile, ResRDevList, celldef); } for (node = ResOriginalNodes; node != NULL; node=node->nextnode) @@ -913,11 +923,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 +935,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 +946,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 +974,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,20 +995,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 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; @@ -1011,7 +1027,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. */ @@ -1046,20 +1062,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); } /* @@ -1126,21 +1142,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; @@ -1156,12 +1172,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); @@ -1169,11 +1185,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) { @@ -1181,8 +1197,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 @@ -1190,24 +1206,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 @@ -1217,9 +1233,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) { @@ -1238,10 +1254,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 { @@ -1250,8 +1266,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; } } @@ -1261,11 +1277,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) { @@ -1284,14 +1300,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 { @@ -1300,8 +1316,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 @@ -1319,27 +1335,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) { @@ -1352,24 +1368,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"); @@ -1381,59 +1397,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) { @@ -1460,7 +1476,7 @@ ResSortByGate(TranpointerList) else { last = working; - working = working->nextTran; + working = working->nextDev; continue; } if (localchange) @@ -1468,31 +1484,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; } } } @@ -1521,7 +1537,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 { @@ -1613,36 +1629,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 b4147523..f55b0845 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,10 +728,11 @@ ResCalculateChildCapacitance(me) { RCDelayStuff *myC; resElement *workingRes; - resTransistor *tran; + resDevice *dev; float childcap; tElement *tptr; int t; + ExtDevice *devptr; if (me->rn_client != (ClientData) NULL) /* we have a loop */ @@ -748,16 +749,17 @@ 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* - ExtCurStyle->exts_transGateCap[t]+ - (tran->rt_width+tran->rt_width)* - ExtCurStyle->exts_transSDCap[t]; + dev->rd_length* + dev->rd_width* + devptr->exts_deviceGateCap+ + (dev->rd_width+dev->rd_width)* + devptr->exts_deviceSDCap; } } @@ -915,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? */ @@ -952,26 +954,25 @@ ResDoSimplify(tolerance,rctol,goodies) { RCDelayStuff *rc = (RCDelayStuff *) ResNodeList->rn_client; + goodies->rg_nodecap = totalcap; + ResCalculateTDi(ResOriginNode,(resResistor *)NULL, + goodies->rg_bigdevres); if (rc != (RCDelayStuff *)NULL) - { - goodies->rg_nodecap = totalcap; - ResCalculateTDi(ResOriginNode,(resResistor *)NULL, - goodies->rg_bigtranres); - 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; - } + 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 { @@ -982,7 +983,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) @@ -1023,7 +1024,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; @@ -1087,8 +1088,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 5548f4e1..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,369 +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); - junk2 = resAddField(tile); - if (TTMaskHasType(&(ExtCurStyle->exts_transMask), 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(&(ExtCurStyle->exts_transSDTypes[loctype][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(&(ExtCurStyle->exts_transSDTypes[loctype][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(&(ExtCurStyle->exts_transSDTypes[loctype][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(&(ExtCurStyle->exts_transSDTypes[loctype][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); - 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(&(ExtCurStyle->exts_transSDTypes[t1][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(&(ExtCurStyle->exts_transSDTypes[t1][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(&(ExtCurStyle->exts_transSDTypes[t1][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(&(ExtCurStyle->exts_transSDTypes[t1][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); } /* @@ -536,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); @@ -577,7 +587,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,52 +604,52 @@ ResPreProcessTransistors(TileList, TransistorList, Def) tt = TiGetType(tile); tstruct = (tileJunk *) tile->ti_client; - if (!TTMaskHasType(&ExtCurStyle->exts_transMask, tt) || - tstruct->transistorList == NULL) + if (!TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt) || + 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..5eb2e1f6 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,25 @@ 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 rs_ttype; /* device type */ char *rs_gattr; /* Gate attributes, if any */ char *rs_sattr; char *rs_dattr; -} RTran; +} RDev; typedef struct ressimnode { @@ -327,7 +328,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 +342,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 +361,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 +373,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 +407,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 +438,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 +453,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,11 +567,10 @@ typedef struct capval /* Assorted Variables */ -extern RTran *ResTranList; +extern RDev *ResRDevList; extern REcell *ResBigEventList; extern int ResOptionsFlags; extern char *ResCurrentNode; -extern int Maxtnumber; extern ResSimNode *ResOriginalNodes; #ifdef ARIEL extern int ResMinEventTime; @@ -587,24 +587,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 +613,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 +649,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/scmos/Makefile b/scmos/Makefile index 647e1d79..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 \ @@ -54,37 +52,40 @@ 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 - $(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): @@ -96,8 +97,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/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/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 deleted file mode 100644 index 5213039d..00000000 --- a/scmos/test.out +++ /dev/null @@ -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/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/configure b/scripts/configure index 4cb2d8d7..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 @@ -640,6 +640,7 @@ gr_dflags gr_cflags rl_libs rl_defs +DIST_DIR cadinstall programs unused @@ -671,12 +672,11 @@ X_LIBS X_PRE_LIBS X_CFLAGS XMKMF +PYTHON3 CSH GCORE EGREP GREP -PYTHON3 -M4 RANLIB INSTALL_DATA INSTALL_SCRIPT @@ -747,6 +747,7 @@ ac_user_opts=' enable_option_checking with_gnu_ld with_x +with_distdir with_interpreter with_tcl with_tk @@ -1425,6 +1426,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 @@ -4035,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 @@ -5340,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. @@ -5431,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; } @@ -6136,6 +6090,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_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_DIR="\${exec_prefix}" + else + DIST_DIR=${withval} + fi + +fi + + # Check for libXi, which is required on some systems but not available on # others. use_libxi="" @@ -8072,7 +8044,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*) @@ -8259,6 +8231,7 @@ fi + ac_config_files="$ac_config_files defs.mak" @@ -9448,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" @@ -9460,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: " @@ -9476,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 b2070922..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 @@ -345,6 +341,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_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_DIR="\${exec_prefix}" + else + DIST_DIR=${withval} + fi +], ) + # Check for libXi, which is required on some systems but not available on # others. use_libxi="" @@ -1615,7 +1625,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*) @@ -1768,6 +1778,7 @@ AC_SUBST(modules) AC_SUBST(unused) AC_SUBST(programs) AC_SUBST(cadinstall) +AC_SUBST(DIST_DIR) AC_SUBST(rl_defs) AC_SUBST(rl_libs) @@ -1787,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) @@ -1824,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" @@ -1836,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: " @@ -1852,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 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} diff --git a/scripts/defs.mak.in b/scripts/defs.mak.in index 7338b375..0404e2ee 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_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 + MAIN_EXTRA_LIBS = @extra_libs@ LD_EXTRA_LIBS = @ld_extra_libs@ LD_SHARED = @ld_extra_objs@ @@ -50,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() diff --git a/sim/SimDBstuff.c b/sim/SimDBstuff.c index 67c09c8f..26d2e7c2 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, 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/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 ); } diff --git a/tcltk/Makefile b/tcltk/Makefile index ac45c270..efa12d00 100644 --- a/tcltk/Makefile +++ b/tcltk/Makefile @@ -18,12 +18,12 @@ TCL_FILES = \ console.tcl \ techbuilder.tcl \ cellmgr.tcl \ + drcmgr.tcl \ libmgr.tcl \ texthelper.tcl \ tools.tcl \ mazeroute.tcl \ strip_reflibs.tcl \ - drc.tcl \ toolkit.tcl \ toolkit_rev0.tcl \ bsitools.tcl \ @@ -31,29 +31,31 @@ 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 \ - -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 \ @@ -72,23 +74,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/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 new file mode 100644 index 00000000..3f46203e --- /dev/null +++ b/tcltk/drcmgr.tcl @@ -0,0 +1,300 @@ +#------------------------------------------------------ +# 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.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:" + 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) + +#--------------------------------------------------- +# 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/toolkit.tcl b/tcltk/toolkit.tcl index 7412277a..c62df42d 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 @@ -548,6 +570,14 @@ 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]] + } + if {$callback != {}} { set parameters [$callback $pname $parameters] } @@ -605,12 +635,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] @@ -628,6 +658,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 {ival 0}} { + + if [dict exists $parameters $pname] { + set value [dict get $parameters $pname] + } else { + set value $ival + } + + 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 --- # @@ -713,9 +775,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] } diff --git a/tcltk/wrapper.tcl b/tcltk/wrapper.tcl index cb1f1e73..b798b5ef 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. @@ -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.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.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.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.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.gif + 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 @@ -367,6 +384,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} @@ -533,6 +554,8 @@ set Opts(crosshair) 0 set Opts(hidelocked) 0 set Opts(hidespecial) 0 set Opts(toolbar) 0 +set Opts(scale) 1.0 +set Opts(toolscale) 1.0 set Opts(drc) 1 set Opts(autobuttontext) 1 @@ -625,7 +648,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] @@ -716,18 +739,22 @@ proc magic::toolupdate {win {yesno "yes"} {layerlist "none"}} { # Generate the toolbar images for a technology proc magic::maketoolimages {} { + global Opts + + # 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. - 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 } } @@ -892,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] @@ -918,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 @@ -1011,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 @@ -1018,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 @@ -1046,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" @@ -1119,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" @@ -1404,6 +1441,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\] \ 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 *); 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 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 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 */ 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 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); 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); } /*