Merge branch 'master' into magic-8.2
This commit is contained in:
commit
56c1829610
|
|
@ -1596,7 +1596,7 @@ esMakePorts(hc, cdata)
|
|||
|
||||
// Find the cell for the instance
|
||||
portdef = NULL;
|
||||
he = HashFind(&updef->def_uses, portname);
|
||||
he = HashLookOnly(&updef->def_uses, portname);
|
||||
if (he != NULL)
|
||||
{
|
||||
use = (Use *)HashGetValue(he);
|
||||
|
|
@ -1686,7 +1686,7 @@ esMakePorts(hc, cdata)
|
|||
|
||||
// Find the cell for the instance
|
||||
portdef = NULL;
|
||||
he = HashFind(&updef->def_uses, portname);
|
||||
he = HashLookOnly(&updef->def_uses, portname);
|
||||
if (he != NULL)
|
||||
{
|
||||
use = (Use *)HashGetValue(he);
|
||||
|
|
|
|||
|
|
@ -32,4 +32,5 @@ EFantenna.o: EFantenna.c ../tcltk/tclmagic.h ../utils/magic.h \
|
|||
../utils/geometry.h ../utils/hash.h ../utils/utils.h ../tiles/tile.h \
|
||||
../database/database.h ../windows/windows.h ../textio/textio.h \
|
||||
../dbwind/dbwind.h ../textio/txcommands.h ../extflat/extflat.h \
|
||||
../extract/extract.h ../utils/malloc.h
|
||||
../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \
|
||||
../utils/malloc.h
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@
|
|||
#include "textio/txcommands.h"
|
||||
#endif
|
||||
#include "extflat/extflat.h"
|
||||
#include "extract/extract.h" /* for extDevTable */
|
||||
#include "extract/extract.h"
|
||||
#include "extract/extractInt.h"
|
||||
#include "utils/malloc.h"
|
||||
|
||||
/* Forward declarations */
|
||||
|
|
@ -103,6 +104,8 @@ CmdAntennaCheck(w, cmd)
|
|||
char *subname;
|
||||
int idx;
|
||||
|
||||
CellUse *editUse;
|
||||
|
||||
static char *cmdAntennaCheckOption[] = {
|
||||
"[run] [options] run antennacheck on current cell\n"
|
||||
" use \"run -help\" to get standard options",
|
||||
|
|
@ -134,6 +137,13 @@ usage:
|
|||
|
||||
runantennacheck:
|
||||
|
||||
if (ExtCurStyle->exts_planeOrderStatus == noPlaneOrder)
|
||||
{
|
||||
TxError("No planeorder specified for this process: "
|
||||
"Cannot run antenna checks!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
EFInit();
|
||||
EFCapThreshold = INFINITY;
|
||||
EFResistThreshold = INFINITY;
|
||||
|
|
@ -162,6 +172,7 @@ runantennacheck:
|
|||
}
|
||||
inName = ((CellUse *) w->w_surfaceID)->cu_def->cd_name;
|
||||
}
|
||||
editUse = (CellUse *)w->w_surfaceID;
|
||||
|
||||
/*
|
||||
* Initializations specific to this program.
|
||||
|
|
@ -178,7 +189,7 @@ runantennacheck:
|
|||
flatFlags = EF_FLATNODES;
|
||||
EFFlatBuild(inName, flatFlags);
|
||||
|
||||
EFVisitDevs(antennacheckVisit, (ClientData)NULL);
|
||||
EFVisitDevs(antennacheckVisit, (ClientData)editUse);
|
||||
EFFlatDone();
|
||||
EFDone();
|
||||
|
||||
|
|
@ -234,9 +245,30 @@ usage:
|
|||
TxError("Usage: antennacheck\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* AntennaGetNode --
|
||||
*
|
||||
* function to find a node given its hierarchical prefix and suffix
|
||||
*
|
||||
* Results:
|
||||
* a pointer to the node struct or NULL
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
EFNode *
|
||||
AntennaGetNode(prefix, suffix)
|
||||
HierName *prefix;
|
||||
HierName *suffix;
|
||||
{
|
||||
HashEntry *he;
|
||||
|
||||
he = EFHNConcatLook(prefix, suffix, "output");
|
||||
return(((EFNodeName *) HashGetValue(he))->efnn_node);
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
@ -256,15 +288,30 @@ usage:
|
|||
*/
|
||||
|
||||
int
|
||||
antennacheckVisit(dev, hierName, scale, trans)
|
||||
antennacheckVisit(dev, hierName, scale, trans, editUse)
|
||||
Dev *dev; /* Device being output */
|
||||
HierName *hierName; /* Hierarchical path down to this device */
|
||||
float scale; /* Scale transform for output */
|
||||
Transform *trans; /* Coordinate transform */
|
||||
CellUse *editUse; /* ClientData is edit cell use */
|
||||
{
|
||||
DevTerm *gate, *source, *drain;
|
||||
int l, w;
|
||||
DevTerm *gate;
|
||||
int pos, pNum, pNum2, pmax, p, i, j, gatearea, diffarea, total;
|
||||
double difftotal;
|
||||
int *antennaarea;
|
||||
Rect r;
|
||||
EFNode *gnode;
|
||||
SearchContext scx;
|
||||
TileTypeBitMask gatemask;
|
||||
|
||||
extern CellDef *extPathDef; /* see extract/ExtLength.c */
|
||||
extern CellUse *extPathUse; /* see extract/ExtLength.c */
|
||||
|
||||
extern int areaAccumFunc(), antennaAccumFunc();
|
||||
|
||||
antennaarea = (int *)mallocMagic(DBNumTypes * sizeof(int));
|
||||
|
||||
for (i = 0; i < DBNumTypes; i++) antennaarea[i] = 0;
|
||||
|
||||
switch(dev->dev_class)
|
||||
{
|
||||
|
|
@ -274,24 +321,176 @@ antennacheckVisit(dev, hierName, scale, trans)
|
|||
|
||||
/* Procedure:
|
||||
*
|
||||
* 1. If device is marked visited, return.
|
||||
* 2. Mark device visited
|
||||
* 3. Mark all connected devices visited
|
||||
* 4. For each plane from metal1 up (determined by planeorder):
|
||||
* a. Run SimTreeCopyConnect()
|
||||
* 1. If device gate node is marked visited, return.
|
||||
* 2. Mark device gate node visited
|
||||
* 3. For each plane from metal1 up (determined by planeorder):
|
||||
* a. Run DBTreeCopyConnect()
|
||||
* b. Accumulate gate area of connected devices
|
||||
* c. Accumulate metal area of connected devices
|
||||
* d. Check against antenna ratio
|
||||
* e. Generate feedback if in violation of antenna rule
|
||||
* c. Accumulate diffusion area of connected devices
|
||||
* d. Accumulate metal area of connected devices
|
||||
* e. Check against antenna ratio(s)
|
||||
* f. Generate feedback if in violation of antenna rule
|
||||
*
|
||||
* NOTE: SimTreeCopyConnect() is used cumulatively, so that
|
||||
* NOTE: DBTreeCopyConnect() is used cumulatively, so that
|
||||
* additional searching only needs to be done for the additional
|
||||
* layer being searched. This is the reason for using
|
||||
* SimTreeCopyConnect() instead of DBTreeCopyConnect().
|
||||
* layer being searched.
|
||||
*/
|
||||
|
||||
/* To be completed */
|
||||
gate = &dev->dev_terms[0];
|
||||
|
||||
gnode = AntennaGetNode(hierName, gate->dterm_node->efnode_name->efnn_hier);
|
||||
if (beenVisited((nodeClient *)gnode->efnode_client, 0))
|
||||
return 0;
|
||||
else
|
||||
markVisited((nodeClient *)gnode->efnode_client, 0);
|
||||
|
||||
/* Find the plane of the gate type */
|
||||
pNum = DBPlane(dev->dev_type);
|
||||
pos = ExtCurStyle->exts_planeOrder[pNum];
|
||||
pmax = ++pos;
|
||||
|
||||
/* Find the highest plane in the technology */
|
||||
for (p = PL_TECHDEPBASE; p < DBNumPlanes; p++)
|
||||
if (ExtCurStyle->exts_planeOrder[p] > pmax)
|
||||
pmax = ExtCurStyle->exts_planeOrder[p];
|
||||
|
||||
/* Use the cellDef reserved for extraction */
|
||||
DBCellClearDef(extPathDef);
|
||||
scx.scx_use = editUse;
|
||||
scx.scx_trans = GeoIdentityTransform;
|
||||
|
||||
/* gatemask is a mask of all gate types for MOSFET devices */
|
||||
|
||||
TTMaskZero(&gatemask);
|
||||
for (i = 0; i < DBNumTypes; i++)
|
||||
{
|
||||
ExtDevice *ed;
|
||||
char devclass;
|
||||
|
||||
if (ExtCurStyle->exts_device[i] != NULL)
|
||||
{
|
||||
for (ed = ExtCurStyle->exts_device[i]; ed; ed = ed->exts_next)
|
||||
{
|
||||
devclass = ed->exts_deviceClass;
|
||||
switch (devclass)
|
||||
{
|
||||
case DEV_MOSFET:
|
||||
case DEV_FET:
|
||||
case DEV_ASYMMETRIC:
|
||||
case DEV_MSUBCKT:
|
||||
TTMaskSetType(&gatemask, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (; pos <= pmax; pos++)
|
||||
{
|
||||
/* Modify DBConnectTbl to limit connectivity to the plane */
|
||||
/* of the antenna check and below */
|
||||
|
||||
/* To be completed */
|
||||
|
||||
DBTreeCopyConnect(&scx, &DBConnectTbl[dev->dev_type], 0,
|
||||
DBConnectTbl, &TiPlaneRect, extPathUse);
|
||||
|
||||
/* Search plane of gate type and accumulate all (new) gate area */
|
||||
DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[pNum],
|
||||
&TiPlaneRect, &gatemask, areaAccumFunc, (ClientData)&gatearea);
|
||||
|
||||
/* Search planes of tie type and accumulate all (new) tiedown areas */
|
||||
for (p = 0; p < DBNumPlanes; p++)
|
||||
DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[p],
|
||||
&TiPlaneRect, &ExtCurStyle->exts_antennaTieTypes,
|
||||
areaAccumFunc, (ClientData)&diffarea);
|
||||
|
||||
/* Search metal planes and accumulate all (new) antenna areas */
|
||||
for (p = 0; p < DBNumPlanes; p++)
|
||||
{
|
||||
if (ExtCurStyle->exts_planeOrder[p] == pos)
|
||||
{
|
||||
pNum2 = p;
|
||||
}
|
||||
if (ExtCurStyle->exts_planeOrder[p] <= pos)
|
||||
DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[p],
|
||||
&TiPlaneRect, &DBAllButSpaceAndDRCBits,
|
||||
antennaAccumFunc, (ClientData)&antennaarea);
|
||||
}
|
||||
|
||||
/* To be elaborated. . . this encodes only one of several */
|
||||
/* methods of calculating antenna violations. */
|
||||
|
||||
if (diffarea == 0)
|
||||
{
|
||||
difftotal = 0.0;
|
||||
for (i = 0; i < DBNumTypes; i++)
|
||||
difftotal += antennaarea[i] / ExtCurStyle->exts_antennaRatio[i];
|
||||
|
||||
if (difftotal > gatearea)
|
||||
TxError("Antenna violation detected at plane %s "
|
||||
"(violation to be elaborated)",
|
||||
DBPlaneLongNameTbl[pNum2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* areaAccumFunc --
|
||||
*
|
||||
* Accumulate the total tile area searched
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
areaAccumFunc(tile, totalarea)
|
||||
Tile *tile;
|
||||
int *totalarea;
|
||||
{
|
||||
Rect rect;
|
||||
int area;
|
||||
|
||||
TiToRect(tile, &rect);
|
||||
|
||||
area += (rect.r_xtop - rect.r_xbot) * (rect.r_ytop - rect.r_ybot);
|
||||
|
||||
*totalarea += area;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* antennaAccumFunc --
|
||||
*
|
||||
* Accumulate the total tile area searched, keeping an individual
|
||||
* count for each tile type.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
antennaAccumFunc(tile, typeareas)
|
||||
Tile *tile;
|
||||
int **typeareas;
|
||||
{
|
||||
Rect rect;
|
||||
int area;
|
||||
int type;
|
||||
|
||||
type = TiGetType(tile);
|
||||
|
||||
TiToRect(tile, &rect);
|
||||
|
||||
area += (rect.r_xtop - rect.r_xbot) * (rect.r_ytop - rect.r_ybot);
|
||||
|
||||
*typeareas[type] += area;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ efBuildNode(def, isSubsnode, nodeName, nodeCap, x, y, layerName, av, ac)
|
|||
HashSetValue(he, (char *) newname);
|
||||
|
||||
/* New node itself */
|
||||
size = sizeof (EFNode) + (efNumResistClasses - 1) * sizeof (PerimArea);
|
||||
size = sizeof (EFNode) + (efNumResistClasses - 1) * sizeof (EFPerimArea);
|
||||
newnode = (EFNode *) mallocMagic((unsigned)(size));
|
||||
newnode->efnode_flags = (isSubsnode == TRUE) ? EF_SUBS_NODE : 0;
|
||||
newnode->efnode_cap = nodeCap;
|
||||
|
|
@ -1182,7 +1182,7 @@ efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac)
|
|||
int n;
|
||||
Connection *conn;
|
||||
unsigned size = sizeof (Connection)
|
||||
+ (efNumResistClasses - 1) * sizeof (PerimArea);
|
||||
+ (efNumResistClasses - 1) * sizeof (EFPerimArea);
|
||||
|
||||
conn = (Connection *) mallocMagic((unsigned)(size));
|
||||
|
||||
|
|
|
|||
|
|
@ -430,7 +430,7 @@ efAddNodes(hc, stdcell)
|
|||
bool is_subcircuit = (def->def_flags & DEF_SUBCIRCUIT) ? TRUE : FALSE;
|
||||
|
||||
scale = def->def_scale;
|
||||
size = sizeof (EFNode) + (efNumResistClasses-1) * sizeof (PerimArea);
|
||||
size = sizeof (EFNode) + (efNumResistClasses-1) * sizeof (EFPerimArea);
|
||||
|
||||
for (node = (EFNode *) def->def_firstn.efnode_next;
|
||||
node != &def->def_firstn;
|
||||
|
|
@ -467,10 +467,10 @@ efAddNodes(hc, stdcell)
|
|||
newnode->efnode_type = node->efnode_type;
|
||||
if (!stdcell)
|
||||
bcopy((char *) node->efnode_pa, (char *) newnode->efnode_pa,
|
||||
efNumResistClasses * sizeof (PerimArea));
|
||||
efNumResistClasses * sizeof (EFPerimArea));
|
||||
else
|
||||
bzero((char *) newnode->efnode_pa,
|
||||
efNumResistClasses * sizeof (PerimArea));
|
||||
efNumResistClasses * sizeof (EFPerimArea));
|
||||
GeoTransRect(&hc->hc_trans, &node->efnode_loc, &newnode->efnode_loc);
|
||||
|
||||
/* Scale the result by "scale" --- hopefully we end up with an integer */
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ typedef struct
|
|||
{
|
||||
int pa_area;
|
||||
int pa_perim;
|
||||
} PerimArea;
|
||||
} EFPerimArea;
|
||||
|
||||
typedef struct efnhdr
|
||||
{
|
||||
|
|
@ -219,7 +219,7 @@ typedef struct efnode
|
|||
*/
|
||||
EFAttr *efnode_attrs; /* Node attribute list */
|
||||
ClientData efnode_client; /* For hire */
|
||||
PerimArea efnode_pa[1]; /* Dummy; each node actually has
|
||||
EFPerimArea efnode_pa[1]; /* Dummy; each node actually has
|
||||
* efNumResistClasses array elements
|
||||
* allocated to it.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ typedef enum
|
|||
AREAC, CONTACT, CSCALE,
|
||||
DEFAULTAREACAP, DEFAULTOVERLAP, DEFAULTPERIMETER, DEFAULTSIDEOVERLAP,
|
||||
DEFAULTSIDEWALL,
|
||||
DEVICE, FET, FETRESIST, HEIGHT, ANTENNA, LAMBDA, OVERC,
|
||||
DEVICE, FET, FETRESIST, HEIGHT, ANTENNA, TIEDOWN, LAMBDA, OVERC,
|
||||
PERIMC, PLANEORDER, NOPLANEORDER, RESIST, RSCALE, SIDEHALO, SIDEOVERLAP,
|
||||
SIDEWALL, STEP, STYLE, SUBSTRATE, UNITS, VARIANT
|
||||
} Key;
|
||||
|
|
@ -125,6 +125,9 @@ static keydesc keyTable[] = {
|
|||
"antenna", ANTENNA, 3, 3,
|
||||
"type antenna-ratio",
|
||||
|
||||
"tiedown", TIEDOWN, 2, 2,
|
||||
"types",
|
||||
|
||||
"lambda", LAMBDA, 2, 2,
|
||||
"units-per-lambda",
|
||||
|
||||
|
|
@ -665,14 +668,17 @@ extTechStyleInit(style)
|
|||
style->exts_numResistClasses = 0;
|
||||
|
||||
style->exts_planeOrderStatus = needPlaneOrder ;
|
||||
TTMaskZero(&style->exts_antennaTieTypes);
|
||||
|
||||
for (r = 0; r < DBNumTypes; r++)
|
||||
{
|
||||
style->exts_antennaRatio[r] = 0;
|
||||
style->exts_resistByResistClass[r] = 0;
|
||||
TTMaskZero(&style->exts_typesByResistClass[r]);
|
||||
style->exts_typesResistChanged[r] = DBAllButSpaceAndDRCBits;
|
||||
TTMaskSetType(&style->exts_typesResistChanged[r], TT_SPACE);
|
||||
style->exts_typeToResistClass[r] = -1;
|
||||
|
||||
}
|
||||
doConvert = FALSE;
|
||||
|
||||
|
|
@ -1789,6 +1795,7 @@ ExtTechLine(sectionName, argc, argv)
|
|||
case FETRESIST:
|
||||
case HEIGHT:
|
||||
case ANTENNA:
|
||||
case TIEDOWN:
|
||||
case OVERC:
|
||||
case PERIMC:
|
||||
case RESIST:
|
||||
|
|
@ -2325,6 +2332,9 @@ ExtTechLine(sectionName, argc, argv)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case TIEDOWN:
|
||||
TTMaskSetMask(&ExtCurStyle->exts_antennaTieTypes, &types1);
|
||||
break;
|
||||
case UNITS:
|
||||
if (!strcmp(argv[1], "microns"))
|
||||
doConvert = TRUE;
|
||||
|
|
|
|||
|
|
@ -659,6 +659,9 @@ typedef struct extstyle
|
|||
/* Antenna area ratio for each layer */
|
||||
float exts_antennaRatio[NT];
|
||||
|
||||
/* Mask of types that tie down antennas */
|
||||
TileTypeBitMask exts_antennaTieTypes;
|
||||
|
||||
/*
|
||||
* Capacitance to substrate for each tile type, in units of
|
||||
* attofarads per square lambda.
|
||||
|
|
|
|||
Loading…
Reference in New Issue