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.
This commit is contained in:
parent
745afa900d
commit
b41c86980b
|
|
@ -945,7 +945,7 @@ cifBloatAllFunc(tile, bls)
|
||||||
t = tile;
|
t = tile;
|
||||||
type = TiGetType(tile);
|
type = TiGetType(tile);
|
||||||
pNum = DBPlane(type);
|
pNum = DBPlane(type);
|
||||||
pmask = CoincidentPlanes(&connect, pNum);
|
pmask = CoincidentPlanes(&connect, PlaneNumToMaskBit(pNum));
|
||||||
if (pmask == 0)
|
if (pmask == 0)
|
||||||
{
|
{
|
||||||
TiToRect(tile, &area);
|
TiToRect(tile, &area);
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
|
||||||
* Standard DBWind command set
|
* Standard DBWind command set
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern void CmdAddPath(), CmdArray();
|
extern void CmdAddPath(), CmdAntennaCheck(), CmdArray();
|
||||||
extern void CmdBox(), CmdCellname(), CmdClockwise();
|
extern void CmdBox(), CmdCellname(), CmdClockwise();
|
||||||
extern void CmdContact(), CmdCopy(), CmdCorner();
|
extern void CmdContact(), CmdCopy(), CmdCorner();
|
||||||
extern void CmdCrash(), CmdCrosshair();
|
extern void CmdCrash(), CmdCrosshair();
|
||||||
|
|
@ -222,6 +222,9 @@ DBWInitCommands()
|
||||||
WindAddCommand(DBWclientID,
|
WindAddCommand(DBWclientID,
|
||||||
"addpath [path] append to current search path",
|
"addpath [path] append to current search path",
|
||||||
CmdAddPath, FALSE);
|
CmdAddPath, FALSE);
|
||||||
|
WindAddCommand(DBWclientID,
|
||||||
|
"antennacheck [path] check for antenna violations",
|
||||||
|
CmdAntennaCheck, FALSE);
|
||||||
WindAddCommand(DBWclientID,
|
WindAddCommand(DBWclientID,
|
||||||
"array xsize ysize OR\n"
|
"array xsize ysize OR\n"
|
||||||
"array xlo xhi ylo yhi\n"
|
"array xlo xhi ylo yhi\n"
|
||||||
|
|
|
||||||
|
|
@ -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 \
|
EFvisit.o: EFvisit.c ../utils/magic.h ../utils/geometry.h \
|
||||||
../utils/geofast.h ../utils/hash.h ../utils/malloc.h ../utils/utils.h \
|
../utils/geofast.h ../utils/hash.h ../utils/malloc.h ../utils/utils.h \
|
||||||
../extflat/extflat.h ../extflat/EFint.h ../extract/extract.h
|
../extflat/extflat.h ../extflat/EFint.h ../extract/extract.h
|
||||||
|
EFantenna.o: EFantenna.c ../tcltk/tclmagic.h ../utils/magic.h \
|
||||||
|
../utils/geometry.h ../utils/hash.h ../utils/utils.h ../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
|
||||||
|
|
|
||||||
|
|
@ -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 <stdio.h>
|
||||||
|
#include <stdlib.h> /* for atof() */
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#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<<rclass); }
|
||||||
|
|
||||||
|
#define clearVisited(client) \
|
||||||
|
{ (client)->visitMask = (long)0; }
|
||||||
|
|
||||||
|
#define beenVisited(client, rclass) \
|
||||||
|
( (client)->visitMask & (1<<rclass))
|
||||||
|
|
||||||
|
#define initNodeClient(node) \
|
||||||
|
{ \
|
||||||
|
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClient))); \
|
||||||
|
(( nodeClient *)(node)->efnode_client)->visitMask = (long) 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define initNodeClientHier(node) \
|
||||||
|
{ \
|
||||||
|
(node)->efnode_client = (ClientData) mallocMagic((unsigned) (sizeof(nodeClientHier))); \
|
||||||
|
((nodeClientHier *) (node)->efnode_client)->visitMask = (long) 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
MODULE = extflat
|
MODULE = extflat
|
||||||
MAGICDIR = ..
|
MAGICDIR = ..
|
||||||
SRCS = EFargs.c EFbuild.c EFdef.c EFerr.c EFflat.c EFhier.c EFname.c \
|
SRCS = EFargs.c EFbuild.c EFdef.c EFerr.c EFflat.c EFhier.c EFname.c \
|
||||||
EFread.c EFsym.c EFvisit.c
|
EFread.c EFsym.c EFvisit.c EFantenna.c
|
||||||
|
|
||||||
include ${MAGICDIR}/defs.mak
|
include ${MAGICDIR}/defs.mak
|
||||||
include ${MAGICDIR}/rules.mak
|
include ${MAGICDIR}/rules.mak
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ typedef enum
|
||||||
AREAC, CONTACT, CSCALE,
|
AREAC, CONTACT, CSCALE,
|
||||||
DEFAULTAREACAP, DEFAULTOVERLAP, DEFAULTPERIMETER, DEFAULTSIDEOVERLAP,
|
DEFAULTAREACAP, DEFAULTOVERLAP, DEFAULTPERIMETER, DEFAULTSIDEOVERLAP,
|
||||||
DEFAULTSIDEWALL,
|
DEFAULTSIDEWALL,
|
||||||
DEVICE, FET, FETRESIST, HEIGHT, LAMBDA, OVERC,
|
DEVICE, FET, FETRESIST, HEIGHT, ANTENNA, LAMBDA, OVERC,
|
||||||
PERIMC, PLANEORDER, NOPLANEORDER, RESIST, RSCALE, SIDEHALO, SIDEOVERLAP,
|
PERIMC, PLANEORDER, NOPLANEORDER, RESIST, RSCALE, SIDEHALO, SIDEOVERLAP,
|
||||||
SIDEWALL, STEP, STYLE, SUBSTRATE, UNITS, VARIANT
|
SIDEWALL, STEP, STYLE, SUBSTRATE, UNITS, VARIANT
|
||||||
} Key;
|
} Key;
|
||||||
|
|
@ -122,6 +122,9 @@ static keydesc keyTable[] = {
|
||||||
"height", HEIGHT, 4, 4,
|
"height", HEIGHT, 4, 4,
|
||||||
"type height-above-subtrate thickness",
|
"type height-above-subtrate thickness",
|
||||||
|
|
||||||
|
"antenna", ANTENNA, 3, 3,
|
||||||
|
"type antenna-ratio",
|
||||||
|
|
||||||
"lambda", LAMBDA, 2, 2,
|
"lambda", LAMBDA, 2, 2,
|
||||||
"units-per-lambda",
|
"units-per-lambda",
|
||||||
|
|
||||||
|
|
@ -1785,6 +1788,7 @@ ExtTechLine(sectionName, argc, argv)
|
||||||
case FET:
|
case FET:
|
||||||
case FETRESIST:
|
case FETRESIST:
|
||||||
case HEIGHT:
|
case HEIGHT:
|
||||||
|
case ANTENNA:
|
||||||
case OVERC:
|
case OVERC:
|
||||||
case PERIMC:
|
case PERIMC:
|
||||||
case RESIST:
|
case RESIST:
|
||||||
|
|
@ -2305,6 +2309,22 @@ ExtTechLine(sectionName, argc, argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case UNITS:
|
||||||
if (!strcmp(argv[1], "microns"))
|
if (!strcmp(argv[1], "microns"))
|
||||||
doConvert = TRUE;
|
doConvert = TRUE;
|
||||||
|
|
|
||||||
|
|
@ -656,6 +656,9 @@ typedef struct extstyle
|
||||||
float exts_height[NT];
|
float exts_height[NT];
|
||||||
float exts_thick[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
|
* Capacitance to substrate for each tile type, in units of
|
||||||
* attofarads per square lambda.
|
* attofarads per square lambda.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue