From 46f3f448495cf02da20ffcf0663eb409e794dada Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 16 Oct 2019 09:17:58 -0400 Subject: [PATCH 1/4] Corrected EFArgs() so that "ext2spice run -help" works as advertised; e.g., "-h" or "-help" is now recognized as a valid option instead of printing a usage message by way of throwing an error. --- ext2spice/ext2spice.c | 25 +++++++++++++++---------- extflat/EFargs.c | 20 +++++++++++++++----- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 43ebabbe..8885bdce 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -1147,6 +1147,17 @@ spcmainArgs(pargc, pargv) char **argv = *pargv, *cp; int argc = *pargc; + char usage_text[] = "Usage: ext2spice " + "[-B] [-o spicefile] [-M|-m] [-y cap_digits] " + "[-J flat|hier]\n" + "[-f spice2|spice3|hspice|ngspice] [-M] [-m] " +#ifdef MAGIC_WRAPPER + "[file]\n"; +#else + "[-j device:sdRclass[/subRclass]/defaultSubstrate]\n" + "file\n\n or else see options to extcheck(1)\n"; +#endif + switch (argv[0][1]) { case 'd': @@ -1243,6 +1254,9 @@ spcmainArgs(pargc, pargv) break; } #endif /* MAGIC_WRAPPER */ + case 'h': /* -h or -help, as suggested by "ext2spice help" */ + TxPrintf(usage_text); + break; default: TxError("Unrecognized flag: %s\n", argv[0]); goto usage; @@ -1253,16 +1267,7 @@ spcmainArgs(pargc, pargv) return 0; usage: - TxError("Usage: ext2spice [-B] [-o spicefile] [-M|-m] [-y cap_digits] " - "[-J flat|hier]\n" - "[-f spice2|spice3|hspice|ngspice] [-M] [-m] " -#ifdef MAGIC_WRAPPER - "[file]\n" -#else - "[-j device:sdRclass[/subRclass]/defaultSubstrate]\n" - "file\n\n or else see options to extcheck(1)\n" -#endif - ); + TxError(usage_text); #ifdef MAGIC_WRAPPER return 1; diff --git a/extflat/EFargs.c b/extflat/EFargs.c index dd812dac..d94ebc16 100644 --- a/extflat/EFargs.c +++ b/extflat/EFargs.c @@ -160,6 +160,15 @@ EFArgs(argc, argv, err_result, argsProc, cdata) HierName *hierName; FILE *f; + char usage_text[] = + "Standard arguments: [-R] [-C] [-r rthresh] [-c cthresh] [-v]\n" + "[-p searchpath] [-s sym=value] [-S symfile] [-t trimchars]\n" +#ifdef MAGIC_WRAPPER + "[rootfile]\n"; +#else + "[-T techname] rootfile\n"; +#endif + if (err_result != NULL) *err_result = FALSE; /* Hash table of nodes we're going to watch if -N given */ @@ -270,6 +279,11 @@ EFArgs(argc, argv, err_result, argsProc, cdata) case 'z': efHNStats = TRUE; break; + case 'h': + if (argsProc != NULL) (*argsProc)(&argc, &argv, cdata); + TxPrintf(usage_text); + if (err_result != NULL) *err_result = TRUE; + return NULL; /*** Try a caller-supplied argument processing function ***/ default: @@ -312,19 +326,15 @@ EFArgs(argc, argv, err_result, argsProc, cdata) realIn[cp - inname] = '\0'; inname = realIn; } - return inname; usage: - TxError("Standard arguments: [-R] [-C] [-r rthresh] [-c cthresh] [-v]\n" - "[-p searchpath] [-s sym=value] [-S symfile] [-t trimchars]\n" + TxError(usage_text); #ifdef MAGIC_WRAPPER - "[rootfile]\n"); if (err_result != NULL) *err_result = TRUE; return NULL; #else - "[-T techname] rootfile\n"); exit (1); /*NOTREACHED*/ #endif From 0386752abb77cc565271c9bb4db7f97bfe5118d7 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 16 Oct 2019 10:14:44 -0400 Subject: [PATCH 2/4] Removed an error message from DRCcif.c; otherwise it raises an error whenever there are no DRC-CIF rules in the techfile. The same error will be raised anyway when reading the techfile if DRC-CIF rules are declared without a style being specified. --- drc/DRCcif.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drc/DRCcif.c b/drc/DRCcif.c index fa4f00c7..9031ea4c 100644 --- a/drc/DRCcif.c +++ b/drc/DRCcif.c @@ -504,10 +504,7 @@ drcCifCheck(arg) if (CIFCurStyle != drcCifStyle) { - if (drcNeedStyle == NULL) { - TxError("Error: No DRC CIF style declared!\n"); - return; - } + if (drcNeedStyle == NULL) return; CIFSaveStyle = CIFCurStyle; From 745afa900d41566352491d91f601921b1e41817c Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 16 Oct 2019 11:38:31 -0400 Subject: [PATCH 3/4] Corrected missing NULL initializer for device substrate name, which can result in a segfault when reloading a techfile. --- extract/ExtTech.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extract/ExtTech.c b/extract/ExtTech.c index d2b3ebbf..37259c54 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -2226,6 +2226,8 @@ ExtTechLine(sectionName, argc, argv) if (subsName != NULL) devptr->exts_deviceSubstrateName = StrDup((char **) NULL, subsName); + else + devptr->exts_deviceSubstrateName = (char *)NULL; devptr->exts_deviceSubstrateTypes = subsTypes; devptr->exts_deviceIdentifierTypes = idTypes; devptr->exts_deviceParams = (ParamList *) NULL; From b41c86980b0b37c756218f7c6832e8205107a076 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 16 Oct 2019 20:53:03 -0400 Subject: [PATCH 4/4] Corrected a mistake with the extension of the bloat-all CIF operator that broke the operator for the usual case of all types in the same plane. --- cif/CIFgen.c | 2 +- dbwind/DBWcommands.c | 5 +- extflat/Depend | 5 + extflat/EFantenna.c | 297 +++++++++++++++++++++++++++++++++++++++++++ extflat/Makefile | 2 +- extract/ExtTech.c | 22 +++- extract/extractInt.h | 3 + 7 files changed, 332 insertions(+), 4 deletions(-) create mode 100644 extflat/EFantenna.c diff --git a/cif/CIFgen.c b/cif/CIFgen.c index 7233d12f..ac85961a 100644 --- a/cif/CIFgen.c +++ b/cif/CIFgen.c @@ -945,7 +945,7 @@ cifBloatAllFunc(tile, bls) t = tile; type = TiGetType(tile); pNum = DBPlane(type); - pmask = CoincidentPlanes(&connect, pNum); + pmask = CoincidentPlanes(&connect, PlaneNumToMaskBit(pNum)); if (pmask == 0) { TiToRect(tile, &area); diff --git a/dbwind/DBWcommands.c b/dbwind/DBWcommands.c index 778e3735..7559b1f6 100644 --- a/dbwind/DBWcommands.c +++ b/dbwind/DBWcommands.c @@ -38,7 +38,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ * Standard DBWind command set */ -extern void CmdAddPath(), CmdArray(); +extern void CmdAddPath(), CmdAntennaCheck(), CmdArray(); extern void CmdBox(), CmdCellname(), CmdClockwise(); extern void CmdContact(), CmdCopy(), CmdCorner(); extern void CmdCrash(), CmdCrosshair(); @@ -222,6 +222,9 @@ DBWInitCommands() WindAddCommand(DBWclientID, "addpath [path] append to current search path", CmdAddPath, FALSE); + WindAddCommand(DBWclientID, + "antennacheck [path] check for antenna violations", + CmdAntennaCheck, FALSE); WindAddCommand(DBWclientID, "array xsize ysize OR\n" "array xlo xhi ylo yhi\n" diff --git a/extflat/Depend b/extflat/Depend index 86844587..a48cf3b8 100644 --- a/extflat/Depend +++ b/extflat/Depend @@ -28,3 +28,8 @@ EFsym.o: EFsym.c ../utils/magic.h ../utils/geometry.h ../utils/geofast.h \ EFvisit.o: EFvisit.c ../utils/magic.h ../utils/geometry.h \ ../utils/geofast.h ../utils/hash.h ../utils/malloc.h ../utils/utils.h \ ../extflat/extflat.h ../extflat/EFint.h ../extract/extract.h +EFantenna.o: EFantenna.c ../tcltk/tclmagic.h ../utils/magic.h \ + ../utils/geometry.h ../utils/hash.h ../utils/utils.h ../tiles/tile.h \ + ../database/database.h ../windows/windows.h ../textio/textio.h \ + ../dbwind/dbwind.h ../textio/txcommands.h ../extflat/extflat.h \ + ../extract/extract.h ../utils/malloc.h diff --git a/extflat/EFantenna.c b/extflat/EFantenna.c new file mode 100644 index 00000000..0048b3f9 --- /dev/null +++ b/extflat/EFantenna.c @@ -0,0 +1,297 @@ +/* + * EFantenna.c -- + * + * Program to flatten hierarchical .ext files and then execute an + * antenna violation check for every MOSFET device in the flattened + * design. + * + * Flattens the tree rooted at file.ext, reading in additional .ext + * files as specified by "use" lines in file.ext. + * + */ + +#include +#include /* for atof() */ +#include +#include + +#include "tcltk/tclmagic.h" +#include "utils/magic.h" +#include "utils/geometry.h" +#include "utils/hash.h" +#include "utils/utils.h" +#include "tiles/tile.h" +#ifdef MAGIC_WRAPPER +#include "database/database.h" +#include "windows/windows.h" +#include "textio/textio.h" +#include "dbwind/dbwind.h" /* for DBWclientID */ +#include "textio/txcommands.h" +#endif +#include "extflat/extflat.h" +#include "extract/extract.h" /* for extDevTable */ +#include "utils/malloc.h" + +/* Forward declarations */ +int antennacheckArgs(); +int antennacheckVisit(); + +typedef struct { + long visitMask:MAXDEVTYPES; +} nodeClient; + +typedef struct { + HierName *lastPrefix; + long visitMask:MAXDEVTYPES; +} nodeClientHier; + +#define NO_RESCLASS -1 + +#define markVisited(client, rclass) \ + { (client)->visitMask |= (1<visitMask = (long)0; } + +#define beenVisited(client, rclass) \ + ( (client)->visitMask & (1<efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClient))); \ + (( nodeClient *)(node)->efnode_client)->visitMask = (long) 0; \ +} + + +#define initNodeClientHier(node) \ +{ \ + (node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClientHier))); \ + ((nodeClientHier *) (node)->efnode_client)->visitMask = (long) 0; \ +} + + +/* + * ---------------------------------------------------------------------------- + * + * Main Tcl callback for command "magic::antennacheck" + * + * ---------------------------------------------------------------------------- + */ + +#define ANTENNACHECK_RUN 0 +#define ANTENNACHECK_HELP 1 + +void +CmdAntennaCheck(w, cmd) + MagWindow *w; + TxCommand *cmd; +{ + int i,flatFlags; + char *inName; + FILE *f; + + int option = ANTENNACHECK_RUN; + int value; + int argc = cmd->tx_argc; + char **argv = cmd->tx_argv; + char **msg; + bool err_result; + + short sd_rclass; + short sub_rclass; + char *devname; + char *subname; + int idx; + + static char *cmdAntennaCheckOption[] = { + "[run] [options] run antennacheck on current cell\n" + " use \"run -help\" to get standard options", + "help print help information", + NULL + }; + + if (cmd->tx_argc > 1) + { + option = Lookup(cmd->tx_argv[1], cmdAntennaCheckOption); + if (option < 0) option = ANTENNACHECK_RUN; + else argv++; + } + + switch (option) + { + case ANTENNACHECK_RUN: + goto runantennacheck; + break; + case ANTENNACHECK_HELP: +usage: + for (msg = &(cmdAntennaCheckOption[0]); *msg != NULL; msg++) + { + TxPrintf(" %s\n", *msg); + } + break; + } + return; + +runantennacheck: + + EFInit(); + EFCapThreshold = INFINITY; + EFResistThreshold = INFINITY; + + /* Process command line arguments */ + inName = EFArgs(argc, argv, &err_result, antennacheckArgs, (ClientData) NULL); + + if (err_result == TRUE) + { + EFDone(); + return /* TCL_ERROR */; + } + + if (inName == NULL) + { + /* Assume that we want to do exttospice on the currently loaded cell */ + + if (w == (MagWindow *) NULL) + windCheckOnlyWindow(&w, DBWclientID); + + if (w == (MagWindow *) NULL) + { + TxError("Point to a window or specify a cell name.\n"); + EFDone(); + return /* TCL_ERROR */; + } + inName = ((CellUse *) w->w_surfaceID)->cu_def->cd_name; + } + + /* + * Initializations specific to this program. + */ + + /* Read the hierarchical description of the input circuit */ + if (EFReadFile(inName, FALSE, FALSE, FALSE) == FALSE) + { + EFDone(); + return /* TCL_ERROR */; + } + + /* Convert the hierarchical description to a flat one */ + flatFlags = EF_FLATNODES; + EFFlatBuild(inName, flatFlags); + + EFVisitDevs(antennacheckVisit, (ClientData)NULL); + EFFlatDone(); + EFDone(); + + TxPrintf("antennacheck finished.\n"); +} + + +/* + * ---------------------------------------------------------------------------- + * + * antennacheckArgs -- + * + * Process those arguments that are specific to antennacheck. + * Assumes that *pargv[0][0] is '-', indicating a flag + * argument. + * + * Results: + * None. TCL version returns False if an error is encountered + * while parsing arguments, True otherwise. + * + * Side effects: + * After processing an argument, updates *pargc and *pargv + * to point to after the argument. + * + * May initialize various global variables based on the + * arguments given to us. + * + * Exits in the event of an improper argument. + * + * ---------------------------------------------------------------------------- + */ + +int +antennacheckArgs(pargc, pargv) + int *pargc; + char ***pargv; +{ + char **argv = *pargv, *cp; + int argc = *pargc; + + switch (argv[0][1]) + { + default: + TxError("Unrecognized flag: %s\n", argv[0]); + goto usage; + } + + *pargv = argv; + *pargc = argc; + return 0; + +usage: + TxError("Usage: antennacheck\n"); + return 1; +} + + + +/* + * ---------------------------------------------------------------------------- + * + * antennacheckVisit -- + * + * Procedure to check for antenna violations from a single device. + * Called by EFVisitDevs(). + * + * Results: + * Returns 0 always. + * + * Side effects: + * May tag other device records to avoid double-counting devices. + * Generates feedback entries if an antenna violation is found. + * + * ---------------------------------------------------------------------------- + */ + +int +antennacheckVisit(dev, hierName, scale, trans) + Dev *dev; /* Device being output */ + HierName *hierName; /* Hierarchical path down to this device */ + float scale; /* Scale transform for output */ + Transform *trans; /* Coordinate transform */ +{ + DevTerm *gate, *source, *drain; + int l, w; + Rect r; + + switch(dev->dev_class) + { + case DEV_FET: + case DEV_MOSFET: + GeoTransRect(trans, &dev->dev_rect, &r); + + /* Procedure: + * + * 1. If device is marked visited, return. + * 2. Mark device visited + * 3. Mark all connected devices visited + * 4. For each plane from metal1 up (determined by planeorder): + * a. Run SimTreeCopyConnect() + * b. Accumulate gate area of connected devices + * c. Accumulate metal area of connected devices + * d. Check against antenna ratio + * e. Generate feedback if in violation of antenna rule + * + * NOTE: SimTreeCopyConnect() is used cumulatively, so that + * additional searching only needs to be done for the additional + * layer being searched. This is the reason for using + * SimTreeCopyConnect() instead of DBTreeCopyConnect(). + */ + + /* To be completed */ + } + return 0; +} + diff --git a/extflat/Makefile b/extflat/Makefile index 4ec0e281..2794bb7e 100644 --- a/extflat/Makefile +++ b/extflat/Makefile @@ -5,7 +5,7 @@ MODULE = extflat MAGICDIR = .. SRCS = EFargs.c EFbuild.c EFdef.c EFerr.c EFflat.c EFhier.c EFname.c \ - EFread.c EFsym.c EFvisit.c + EFread.c EFsym.c EFvisit.c EFantenna.c include ${MAGICDIR}/defs.mak include ${MAGICDIR}/rules.mak diff --git a/extract/ExtTech.c b/extract/ExtTech.c index 37259c54..21ff4ce3 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -71,7 +71,7 @@ typedef enum AREAC, CONTACT, CSCALE, DEFAULTAREACAP, DEFAULTOVERLAP, DEFAULTPERIMETER, DEFAULTSIDEOVERLAP, DEFAULTSIDEWALL, - DEVICE, FET, FETRESIST, HEIGHT, LAMBDA, OVERC, + DEVICE, FET, FETRESIST, HEIGHT, ANTENNA, LAMBDA, OVERC, PERIMC, PLANEORDER, NOPLANEORDER, RESIST, RSCALE, SIDEHALO, SIDEOVERLAP, SIDEWALL, STEP, STYLE, SUBSTRATE, UNITS, VARIANT } Key; @@ -122,6 +122,9 @@ static keydesc keyTable[] = { "height", HEIGHT, 4, 4, "type height-above-subtrate thickness", + "antenna", ANTENNA, 3, 3, +"type antenna-ratio", + "lambda", LAMBDA, 2, 2, "units-per-lambda", @@ -1785,6 +1788,7 @@ ExtTechLine(sectionName, argc, argv) case FET: case FETRESIST: case HEIGHT: + case ANTENNA: case OVERC: case PERIMC: case RESIST: @@ -2305,6 +2309,22 @@ ExtTechLine(sectionName, argc, argv) } } break; + case ANTENNA: { + float antennaratio; + + if (!StrIsNumeric(argv[2])) + { + TechError("Layer antenna ratio %s must be numeric\n", argv[2]); + break; + } + antennaratio = (float)strtod(argv[2], NULL); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, t)) + { + ExtCurStyle->exts_antennaRatio[t] = antennaratio; + } + } + break; case UNITS: if (!strcmp(argv[1], "microns")) doConvert = TRUE; diff --git a/extract/extractInt.h b/extract/extractInt.h index 5e0064e1..bb30c425 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -656,6 +656,9 @@ typedef struct extstyle float exts_height[NT]; float exts_thick[NT]; + /* Antenna area ratio for each layer */ + float exts_antennaRatio[NT]; + /* * Capacitance to substrate for each tile type, in units of * attofarads per square lambda.