diff options
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | calma/CalmaRdpt.c | 8 | ||||
-rw-r--r-- | cif/CIFrdtech.c | 4 | ||||
-rw-r--r-- | commands/CmdLQ.c | 12 | ||||
-rw-r--r-- | debian/changelog | 6 | ||||
-rw-r--r-- | drc/DRCbasic.c | 8 | ||||
-rw-r--r-- | ext2spice/ext2hier.c | 15 | ||||
-rw-r--r-- | ext2spice/ext2spice.c | 155 | ||||
-rw-r--r-- | ext2spice/ext2spice.h | 30 | ||||
-rw-r--r-- | extflat/Depend | 10 | ||||
-rw-r--r-- | extflat/EFantenna.c | 446 | ||||
-rw-r--r-- | extflat/EFbuild.c | 240 | ||||
-rw-r--r-- | extflat/EFdef.c | 22 | ||||
-rw-r--r-- | extflat/EFflat.c | 18 | ||||
-rw-r--r-- | extflat/EFhier.c | 6 | ||||
-rw-r--r-- | extflat/EFint.h | 2 | ||||
-rw-r--r-- | extflat/EFread.c | 3 | ||||
-rw-r--r-- | extflat/EFvisit.c | 8 | ||||
-rw-r--r-- | extract/ExtTech.c | 83 | ||||
-rw-r--r-- | extract/extract.h | 1 | ||||
-rw-r--r-- | extract/extractInt.h | 16 | ||||
-rw-r--r-- | lef/lefWrite.c | 32 | ||||
-rw-r--r-- | resis/ResReadSim.c | 42 |
23 files changed, 892 insertions, 277 deletions
@@ -1 +1 @@ -8.2.149 +8.2.157 diff --git a/calma/CalmaRdpt.c b/calma/CalmaRdpt.c index 61e6e87..f0edac7 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/cif/CIFrdtech.c b/cif/CIFrdtech.c index 297ad7b..3777df9 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/commands/CmdLQ.c b/commands/CmdLQ.c index 1225081..02c04b6 100644 --- a/commands/CmdLQ.c +++ b/commands/CmdLQ.c @@ -318,7 +318,7 @@ CmdLabel(w, cmd) * Implement the "load" command. * * Usage: - * load [name [scaled n [d]]] [-force] + * load [name [scaled n [d]]] [-force] [-nowindow] * * If name is supplied, then the window containing the point tool is * remapped so as to edit the cell with the given name. @@ -364,15 +364,16 @@ CmdLoad(w, cmd) locargc--; ignoreTech = TRUE; } - if (locargc >= 4 && !strncmp(cmd->tx_argv[2], "scale", 5) && + if ((locargc >= 4) && !strncmp(cmd->tx_argv[2], "scale", 5) && StrIsInt(cmd->tx_argv[3])) { n = atoi(cmd->tx_argv[3]); - if (cmd->tx_argc == 5 && StrIsInt(cmd->tx_argv[4])) + if ((locargc == 5) && StrIsInt(cmd->tx_argv[4])) d = atoi(cmd->tx_argv[4]); else if (locargc != 4) { - TxError("Usage: %s name scaled n [d]\n", cmd->tx_argv[0]); + TxError("Usage: %s name scaled n [d] [-force] [-nowindow]\n", + cmd->tx_argv[0]); return; } DBLambda[0] *= d; @@ -381,7 +382,8 @@ CmdLoad(w, cmd) } else if (!ignoreTech && !noWindow) { - TxError("Usage: %s [name [scaled n [d]]]\n", cmd->tx_argv[0]); + TxError("Usage: %s name [scaled n [d]] [-force] [-nowindow]\n", + cmd->tx_argv[0]); return; } } diff --git a/debian/changelog b/debian/changelog index d622aa0..7a92b94 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +magic (8.2.157+ds.1-1) unstable; urgency=low + + * New upstream release + + -- Ruben Undheim <ruben.undheim@gmail.com> Thu, 07 Nov 2019 21:14:45 +0100 + magic (8.2.149+ds.1-1) unstable; urgency=medium * Upload to unstable diff --git a/drc/DRCbasic.c b/drc/DRCbasic.c index a3d2cbb..78afd39 100644 --- a/drc/DRCbasic.c +++ b/drc/DRCbasic.c @@ -484,6 +484,7 @@ drcTile (tile, arg) int edgeX = LEFT(tile); firsttile = TRUE; + mrd = NULL; for (tpleft = BL(tile); BOTTOM(tpleft) < top; tpleft = RT(tpleft)) { /* Get the tile types to the left and right of the edge */ @@ -554,8 +555,6 @@ drcTile (tile, arg) mrd = drcCanonicalMaxwidth(tpleft, GEO_WEST, arg, cptr); else if (firsttile) mrd = drcCanonicalMaxwidth(tile, GEO_EAST, arg, cptr); - else - mrd = NULL; if (!trigpending || (DRCCurStyle->DRCFlags & DRC_FLAGS_WIDEWIDTH_NONINCLUSIVE)) cptr->drcc_dist--; @@ -610,7 +609,6 @@ drcTile (tile, arg) drcCheckMaxwidth(tile, arg, cptr); continue; } - else if (!triggered) mrd = NULL; if (cptr->drcc_flags & DRC_RECTSIZE) { @@ -870,6 +868,7 @@ checkbottom: /* Go right across bottom of tile */ firsttile = TRUE; + mrd = NULL; for (tpbot = LB(tile); LEFT(tpbot) < right; tpbot = TR(tpbot)) { /* Get the tile types to the top and bottom of the edge */ @@ -936,8 +935,6 @@ checkbottom: mrd = drcCanonicalMaxwidth(tpbot, GEO_SOUTH, arg, cptr); else if (firsttile) mrd = drcCanonicalMaxwidth(tile, GEO_NORTH, arg, cptr); - else - mrd = NULL; if (!trigpending || (DRCCurStyle->DRCFlags & DRC_FLAGS_WIDEWIDTH_NONINCLUSIVE)) cptr->drcc_dist--; @@ -992,7 +989,6 @@ checkbottom: if (trigpending) cptr = cptr->drcc_next; continue; } - else if (!triggered) mrd = NULL; result = 0; arg->dCD_radial = 0; diff --git a/ext2spice/ext2hier.c b/ext2spice/ext2hier.c index 07143cb..6f6fc55 100644 --- a/ext2spice/ext2hier.c +++ b/ext2spice/ext2hier.c @@ -1625,6 +1625,10 @@ esMakePorts(hc, cdata) { nn->efnn_node->efnode_flags |= EF_PORT; nn->efnn_port = -1; // Will be sorted later + + // Diagnostic + // TxPrintf("Port connection in %s from net %s to net %s (%s)\n", + // def->def_name, locname, name, portname); } } @@ -1634,9 +1638,6 @@ esMakePorts(hc, cdata) updef = portdef; } - // Diagnostic - // TxPrintf("Connection in %s to net %s (%s)\n", def->def_name, - // name, portname); } } @@ -1656,7 +1657,7 @@ esMakePorts(hc, cdata) // In particular, this keeps parasitics out of the netlist for // LVS purposes if "cthresh" is set to "infinite". - if (fabs((double)conn->conn_cap) < EFCapThreshold) continue; + if (fabs((double)conn->conn_cap / 1000) < EFCapThreshold) continue; portname = name; updef = def; @@ -1771,7 +1772,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) { @@ -1883,6 +1885,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 8885bdc..65eb732 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -264,7 +264,8 @@ CmdExtToSpice(w, cmd) "extresist [on|off] incorporate information from extresist", "resistor tee [on|off] model resistor capacitance as a T-network", "scale [on|off] use .option card for scaling", - "subcircuits [on|off] standard cells become subcircuit calls", + "subcircuits [top|descend] [on|off|auto]\n" + " standard cells become subcircuit calls", "hierarchy [on|off] output hierarchical spice for LVS", "blackbox [on|off] output abstract views as black-box entries", "renumber [on|off] on = number instances X1, X2, etc.\n" @@ -1371,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 */ @@ -1466,35 +1468,54 @@ 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) + TxError("No port connection on port %d; need to resolve.\n", portidx); + else + { + if (tchars > 80) + { + fprintf(esSpiceF, "\n+"); + tchars = 1; + } + tchars += spcdevOutNode(hierName, nodeName->efnn_hier, + "subcircuit", esSpiceF); + } + } + freeMagic(nodeList); + /* Look for all implicit substrate connections that are */ /* declared as local node names, and put them last. */ @@ -1614,7 +1635,7 @@ topVisit(def, doStub) Def *def; bool doStub; { - EFNode *snode; + EFNode *snode, *basenode; EFNodeName *sname, *nodeName; HashSearch hs; HashEntry *he; @@ -1667,7 +1688,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) { @@ -1675,11 +1698,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 @@ -1713,7 +1737,7 @@ topVisit(def, doStub) fprintf(esSpiceF, "\n+"); tchars = 1; } - pname = nodeSpiceName(snode->efnode_name->efnn_hier); + pname = nodeSpiceName(snode->efnode_name->efnn_hier, NULL); fprintf(esSpiceF, " %s", pname); tchars += strlen(pname) + 1; break; @@ -2095,6 +2119,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; +} + /* * ---------------------------------------------------------------------------- * @@ -2720,7 +2794,8 @@ FILE *outf; /* Canonical name */ nn = (EFNodeName *) HashGetValue(he); if (outf) - fprintf(outf, "%s", nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier)); + fprintf(outf, "%s", nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier, + NULL)); /* Mark node as visited */ if ((nodeClient *)nn->efnn_node->efnode_client == (ClientData)NULL) @@ -2931,7 +3006,7 @@ spcdevOutNode(prefix, suffix, name, outf) return 0; } nn = (EFNodeName *) HashGetValue(he); - nname = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier); + nname = nodeSpiceName(nn->efnn_node->efnode_name->efnn_hier, NULL); fprintf(outf, " %s", nname); /* Mark node as visited */ @@ -2977,8 +3052,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; } @@ -3013,8 +3088,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; } @@ -3049,7 +3124,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; } @@ -3099,7 +3174,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]; @@ -3144,7 +3219,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", @@ -3167,23 +3242,27 @@ nodeVisitDebug(node, res, cap) * * Side effects: * Allocates nodeClients for the node. + * Returns the node in the "rnode" pointer, if non-NULL. * * ---------------------------------------------------------------------------- */ static char esTempName[MAX_STR_SIZE]; -char *nodeSpiceName(hname) +char *nodeSpiceName(hname, rnode) HierName *hname; + EFNode **rnode; { EFNodeName *nn; HashEntry *he; EFNode *node; + if (rnode) *rnode = (EFNode *)NULL; he = EFHNLook(hname, (char *) NULL, "nodeName"); if ( he == NULL ) return "errGnd!"; nn = (EFNodeName *) HashGetValue(he); node = nn->efnn_node; + if (rnode) *rnode = node; if ( (nodeClient *) (node->efnode_client) == NULL ) { initNodeClient(node); diff --git a/ext2spice/ext2spice.h b/ext2spice/ext2spice.h index 4247d61..065650d 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 c2c8968..f4e4058 100644 --- a/extflat/Depend +++ b/extflat/Depend @@ -29,8 +29,8 @@ EFvisit.o: EFvisit.c ../utils/magic.h ../utils/geometry.h \ ../utils/geofast.h ../utils/hash.h ../utils/malloc.h ../utils/utils.h \ ../extflat/extflat.h ../extflat/EFint.h ../extract/extract.h EFantenna.o: EFantenna.c ../tcltk/tclmagic.h ../utils/magic.h \ - ../utils/geometry.h ../utils/hash.h ../utils/utils.h ../tiles/tile.h \ - ../database/database.h ../windows/windows.h ../textio/textio.h \ - ../dbwind/dbwind.h ../textio/txcommands.h ../extflat/extflat.h \ - ../extract/extract.h ../extract/extractInt.h ../extract/extDebugInt.h \ - ../utils/malloc.h + ../utils/geometry.h ../utils/hash.h ../utils/utils.h ../utils/styles.h \ + ../tiles/tile.h ../database/database.h ../windows/windows.h \ + ../textio/textio.h ../dbwind/dbwind.h ../textio/txcommands.h \ + ../extflat/extflat.h ../extract/extract.h ../extract/extractInt.h \ + ../extract/extDebugInt.h ../utils/malloc.h diff --git a/extflat/EFantenna.c b/extflat/EFantenna.c index 4bbbd1c..470edfe 100644 --- a/extflat/EFantenna.c +++ b/extflat/EFantenna.c @@ -14,18 +14,20 @@ #include <stdlib.h> /* for atof() */ #include <string.h> #include <ctype.h> +#include <math.h> /* for INFINITY */ #include "tcltk/tclmagic.h" #include "utils/magic.h" #include "utils/geometry.h" #include "utils/hash.h" #include "utils/utils.h" +#include "utils/styles.h" #include "tiles/tile.h" #ifdef MAGIC_WRAPPER #include "database/database.h" #include "windows/windows.h" #include "textio/textio.h" -#include "dbwind/dbwind.h" /* for DBWclientID */ +#include "dbwind/dbwind.h" #include "textio/txcommands.h" #endif #include "extflat/extflat.h" @@ -70,6 +72,34 @@ typedef struct { ((nodeClientHier *) (node)->efnode_client)->visitMask = (long) 0; \ } +/* Diagnostic */ +int efGates; +static int efAntennaDebug = FALSE; + +/* The extract file is designed to be independent of the magic database, */ +/* but that means that the device types do not match magic database types. */ +/* A lookup table is needed to cross-reference the device types. */ + +TileType *EFDeviceTypes; + +typedef struct _aas { + int *accum; /* Pointer to array of accumulated areas per type */ + int pNum; /* Plane of check */ + Rect r; /* Holds any one visited rectangle */ + CellDef *def; /* CellDef for adding feedback */ +} AntennaAccumStruct; + +typedef struct _gdas { + int accum; /* Accumulated area of all gates/diff */ + Rect r; /* Holds any one visited rectangle */ + CellDef *def; /* CellDef for adding feedback */ +} GateDiffAccumStruct; + +typedef struct _ams { + int pNum; /* Plane of check */ + CellDef *def; /* CellDef for adding feedback */ +} AntennaMarkStruct; + /* * ---------------------------------------------------------------------------- @@ -80,16 +110,18 @@ typedef struct { */ #define ANTENNACHECK_RUN 0 -#define ANTENNACHECK_HELP 1 +#define ANTENNACHECK_DEBUG 1 +#define ANTENNACHECK_HELP 2 void CmdAntennaCheck(w, cmd) MagWindow *w; TxCommand *cmd; { - int i,flatFlags; + int i, flatFlags; char *inName; FILE *f; + TileType t; int option = ANTENNACHECK_RUN; int value; @@ -109,6 +141,7 @@ CmdAntennaCheck(w, cmd) static char *cmdAntennaCheckOption[] = { "[run] [options] run antennacheck on current cell\n" " use \"run -help\" to get standard options", + "debug print detailed information about each error", "help print help information", NULL }; @@ -125,6 +158,9 @@ CmdAntennaCheck(w, cmd) case ANTENNACHECK_RUN: goto runantennacheck; break; + case ANTENNACHECK_DEBUG: + efAntennaDebug = TRUE; + break; case ANTENNACHECK_HELP: usage: for (msg = &(cmdAntennaCheckOption[0]); *msg != NULL; msg++) @@ -179,6 +215,7 @@ runantennacheck: */ /* Read the hierarchical description of the input circuit */ + TxPrintf("Reading extract file.\n"); if (EFReadFile(inName, FALSE, FALSE, FALSE) == FALSE) { EFDone(); @@ -187,13 +224,24 @@ runantennacheck: /* Convert the hierarchical description to a flat one */ flatFlags = EF_FLATNODES; + TxPrintf("Building flattened netlist.\n"); EFFlatBuild(inName, flatFlags); + /* Build device lookup table */ + EFDeviceTypes = (TileType *)mallocMagic(MAXDEVTYPES * sizeof(TileType)); + for (i = 0; i < MAXDEVTYPES; i++) + if (EFDevTypes[i]) + EFDeviceTypes[i] = extGetDevType(EFDevTypes[i]); + + efGates = 0; + TxPrintf("Running antenna checks.\n"); EFVisitDevs(antennacheckVisit, (ClientData)editUse); EFFlatDone(); EFDone(); TxPrintf("antennacheck finished.\n"); + freeMagic(EFDeviceTypes); + efAntennaDebug = FALSE; } @@ -296,28 +344,30 @@ antennacheckVisit(dev, hierName, scale, trans, editUse) CellUse *editUse; /* ClientData is edit cell use */ { DevTerm *gate; + TileType t, conType; int pos, pNum, pNum2, pmax, p, i, j, gatearea, diffarea, total; - double difftotal; + double anttotal; + float saveRatio; int *antennaarea; - Rect r; + Rect r, gaterect; EFNode *gnode; SearchContext scx; - TileTypeBitMask gatemask; + TileTypeBitMask gatemask, saveConMask; + bool antennaError; extern CellDef *extPathDef; /* see extract/ExtLength.c */ extern CellUse *extPathUse; /* see extract/ExtLength.c */ - extern int areaAccumFunc(), antennaAccumFunc(); + extern int areaAccumFunc(), antennaAccumFunc(), areaMarkFunc(); antennaarea = (int *)mallocMagic(DBNumTypes * sizeof(int)); - for (i = 0; i < DBNumTypes; i++) antennaarea[i] = 0; - switch(dev->dev_class) { case DEV_FET: case DEV_MOSFET: - GeoTransRect(trans, &dev->dev_rect, &r); + case DEV_MSUBCKT: + case DEV_ASYMMETRIC: /* Procedure: * @@ -336,16 +386,23 @@ antennacheckVisit(dev, hierName, scale, trans, editUse) * layer being searched. */ + GeoTransRect(trans, &dev->dev_rect, &r); gate = &dev->dev_terms[0]; - gnode = AntennaGetNode(hierName, gate->dterm_node->efnode_name->efnn_hier); + if (gnode->efnode_client == (ClientData) NULL) + initNodeClient(gnode); if (beenVisited((nodeClient *)gnode->efnode_client, 0)) return 0; else markVisited((nodeClient *)gnode->efnode_client, 0); + /* Diagnostic stuff */ + efGates++; + if (efGates % 100 == 0) TxPrintf(" %d gates analyzed.\n", efGates); + /* Find the plane of the gate type */ - pNum = DBPlane(dev->dev_type); + t = EFDeviceTypes[dev->dev_type]; + pNum = DBPlane(t); pos = ExtCurStyle->exts_planeOrder[pNum]; pmax = ++pos; @@ -354,10 +411,15 @@ antennacheckVisit(dev, hierName, scale, trans, editUse) if (ExtCurStyle->exts_planeOrder[p] > pmax) pmax = ExtCurStyle->exts_planeOrder[p]; + /* Create the yank cell if it doesn't already exist */ + if (extPathDef == (CellDef *) NULL) + DBNewYank("__PATHYANK__", &extPathUse, &extPathDef); + /* Use the cellDef reserved for extraction */ - DBCellClearDef(extPathDef); + /* DBCellClearDef(extPathDef); */ /* See below */ scx.scx_use = editUse; scx.scx_trans = GeoIdentityTransform; + scx.scx_area = r; /* gatemask is a mask of all gate types for MOSFET devices */ @@ -387,80 +449,227 @@ antennacheckVisit(dev, hierName, scale, trans, editUse) for (; pos <= pmax; pos++) { + GateDiffAccumStruct gdas; + AntennaAccumStruct aas; + AntennaMarkStruct ams; + + /* Find the plane of pos */ + + for (p = 0; p < DBNumPlanes; p++) + if (ExtCurStyle->exts_planeOrder[p] == pos) + pNum2 = p; + + /* Find the tiletype which is a contact and whose base is pNum2 */ + /* (NOTE: Need to extend to all such contacts, as there may be */ + /* more than one.) (Also should find these types up top, not */ + /* within the loop.) */ + /* Modify DBConnectTbl to limit connectivity to the plane */ /* of the antenna check and below */ - /* To be completed */ + conType = -1; + for (i = 0; i < DBNumTypes; i++) + if (DBIsContact(i) && DBPlane(i) == pNum2) + { + conType = i; + TTMaskZero(&saveConMask); + TTMaskSetMask(&saveConMask, &DBConnectTbl[i]); + TTMaskZero(&DBConnectTbl[i]); + for (j = 0; j < DBNumTypes; j++) + if (TTMaskHasType(&saveConMask, j) && + (DBPlane(j) <= pNum2)) + TTMaskSetType(&DBConnectTbl[i], j); + break; + } - DBTreeCopyConnect(&scx, &DBConnectTbl[dev->dev_type], 0, - DBConnectTbl, &TiPlaneRect, extPathUse); + for (i = 0; i < DBNumTypes; i++) antennaarea[i] = 0; + gatearea = 0; + diffarea = 0; - /* 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); + /* 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 type and accumulate all (new) tiedown areas */ + /* Search planes of tie types and accumulate all tiedown areas */ + gdas.accum = 0; for (p = 0; p < DBNumPlanes; p++) DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[p], &TiPlaneRect, &ExtCurStyle->exts_antennaTieTypes, - areaAccumFunc, (ClientData)&diffarea); + areaAccumFunc, (ClientData)&gdas); + diffarea = gdas.accum; + + /* Search 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 (new) antenna areas */ + /* Search metal planes and accumulate all antenna areas */ for (p = 0; p < DBNumPlanes; p++) { - if (ExtCurStyle->exts_planeOrder[p] == pos) - { - pNum2 = p; - } + if (ExtCurStyle->exts_antennaModel & ANTENNAMODEL_PARTIAL) + if (p != pNum2) continue; + + aas.pNum = p; + aas.accum = &antennaarea[0]; if (ExtCurStyle->exts_planeOrder[p] <= pos) DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[p], &TiPlaneRect, &DBAllButSpaceAndDRCBits, - antennaAccumFunc, (ClientData)&antennaarea); + antennaAccumFunc, (ClientData)&aas); } - /* To be elaborated. . . this encodes only one of several */ - /* methods of calculating antenna violations. */ - + antennaError = FALSE; if (diffarea == 0) { - difftotal = 0.0; + anttotal = 0.0; + saveRatio = 0.0; + for (i = 0; i < DBNumTypes; i++) + { + 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++) - difftotal += antennaarea[i] / ExtCurStyle->exts_antennaRatio[i]; + if (ExtCurStyle->exts_antennaRatio[i].ratioDiff != INFINITY) + { + if (ExtCurStyle->exts_antennaRatio[i].ratioDiff > 0) + anttotal += (double)antennaarea[i] / + (double)ExtCurStyle->exts_antennaRatio[i].ratioDiff; + if (ExtCurStyle->exts_antennaRatio[i].ratioDiff > saveRatio) + saveRatio = ExtCurStyle->exts_antennaRatio[i].ratioDiff; + } + + if (anttotal > (double)gatearea) + { + antennaError = TRUE; + if (efAntennaDebug == TRUE) + { + TxError("Antenna violation detected at plane %s\n", + DBPlaneLongNameTbl[pNum2]); + TxError("Effective antenna ratio %g > limit %g\n", + saveRatio * (float)anttotal / (float)gatearea, + saveRatio); + TxError("Gate rect (%d %d) to (%d %d)\n", + gdas.r.r_xbot, gdas.r.r_ybot, + gdas.r.r_xtop, gdas.r.r_ytop); + TxError("Antenna rect (%d %d) to (%d %d)\n", + aas.r.r_xbot, aas.r.r_ybot, + aas.r.r_xtop, aas.r.r_ytop); + } + } + } + + if (antennaError) + { + /* Search plane of gate type and mark all gate areas */ + ams.def = editUse->cu_def; + ams.pNum = pNum2; + DBSrPaintArea((Tile *)NULL, extPathUse->cu_def->cd_planes[pNum], + &TiPlaneRect, &gatemask, areaMarkFunc, (ClientData)&ams); + + /* Search metal planes and accumulate all antenna areas */ + for (p = 0; p < DBNumPlanes; p++) + { + if (ExtCurStyle->exts_antennaModel & ANTENNAMODEL_PARTIAL) + if (p != pNum2) continue; - if (difftotal > gatearea) - TxError("Antenna violation detected at plane %s " - "(violation to be elaborated)", - DBPlaneLongNameTbl[pNum2]); + 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; } /* * ---------------------------------------------------------------------------- * - * areaAccumFunc -- + * areaMarkFunc -- * - * Accumulate the total tile area searched + * Mark the tile areas searched with feedback entries * * ---------------------------------------------------------------------------- */ int -areaAccumFunc(tile, totalarea) +areaMarkFunc(tile, ams) Tile *tile; - int *totalarea; + AntennaMarkStruct *ams; { Rect rect; - int area; + 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; +} - area += (rect.r_xtop - rect.r_xbot) * (rect.r_ytop - rect.r_ybot); +/* + * ---------------------------------------------------------------------------- + * + * areaAccumFunc -- + * + * Accumulate the total tile area searched + * + * ---------------------------------------------------------------------------- + */ - *totalarea += area; +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; } @@ -470,27 +679,164 @@ areaAccumFunc(tile, totalarea) * antennaAccumFunc -- * * Accumulate the total tile area searched, keeping an individual - * count for each tile type. + * count for each tile type. If the antenna model is SIDEWALL, then + * calculate the area of the tile sidewall (tile perimeter * layer + * thickness), rather than the drawn tile area. * * ---------------------------------------------------------------------------- */ int -antennaAccumFunc(tile, typeareas) +antennaAccumFunc(tile, aaptr) Tile *tile; - int **typeareas; + AntennaAccumStruct *aaptr; { - Rect rect; + Rect *rect = &(aaptr->r); int area; int type; + int *typeareas = aaptr->accum; + int plane = aaptr->pNum; + float thick; type = TiGetType(tile); - TiToRect(tile, &rect); + TiToRect(tile, rect); + + if (ExtCurStyle->exts_antennaModel & 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 + { + /* 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. */ - area += (rect.r_xtop - rect.r_xbot) * (rect.r_ytop - rect.r_ybot); + if (DBIsContact(type)) + { + TileType ttype; + TileTypeBitMask sMask; - *typeareas[type] += area; + 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/EFbuild.c b/extflat/EFbuild.c index dd2c700..6999f1a 100644 --- a/extflat/EFbuild.c +++ b/extflat/EFbuild.c @@ -591,23 +591,28 @@ efBuildDevice(def, class, type, r, argc, argv) Rect *r; /* Coordinates of 1x1 rectangle entirely inside device */ int argc; /* Size of argv */ char *argv[]; /* Tokens for the rest of the dev line. - * The first depend on the type of device. The rest - * are taken in groups of 3, one for each terminal. - * Each group of 3 consists of the node name to which - * the terminal connects, the length of the terminal, - * and an attribute list (or the token 0). + * Starts with the last two position values, used to + * hash the device record. The next arguments depend + * on the type of device. The rest are taken in groups + * of 3, one for each terminal. Each group of 3 consists + * of the node name to which the terminal connects, the + * length of the terminal, and an attribute list (or the + * token 0). */ { int n, nterminals, pn; + HashEntry *he; DevTerm *term; Dev *newdev, devtmp; DevParam *newparm, *devp, *sparm; char ptype, *pptr, **av; + char devhash[24]; int argstart = 1; /* start of terminal list in argv[] */ bool hasModel = strcmp(type, "None") ? TRUE : FALSE; int area, perim; /* Total area, perimeter of primary type (i.e., channel) */ + newdev = (Dev *)NULL; devtmp.dev_subsnode = NULL; devtmp.dev_cap = 0.0; devtmp.dev_res = 0.0; @@ -713,7 +718,6 @@ efBuildDevice(def, class, type, r, argc, argv) } /* Check for optional substrate node */ - switch (class) { case DEV_RES: @@ -743,93 +747,149 @@ efBuildDevice(def, class, type, r, argc, argv) nterminals = (argc - argstart) / 3; - newdev = (Dev *) mallocMagic((unsigned) DevSize(nterminals)); - newdev->dev_subsnode = devtmp.dev_subsnode; - newdev->dev_cap = devtmp.dev_cap; - newdev->dev_res = devtmp.dev_res; - newdev->dev_area = devtmp.dev_area; - newdev->dev_perim = devtmp.dev_perim; - newdev->dev_length = devtmp.dev_length; - newdev->dev_width = devtmp.dev_width; - newdev->dev_params = devtmp.dev_params; - - newdev->dev_nterm = nterminals; - newdev->dev_rect = *r; - newdev->dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, type); - newdev->dev_class = class; + /* Determine if this device has been seen before */ + + sprintf(devhash, "%dx%d", r->r_xbot, r->r_ybot); + he = HashFind(&def->def_devs, devhash); + newdev = (Dev *)HashGetValue(he); + if (newdev) + { + /* Duplicate device. Duplicates will only appear in res.ext files + * where a device has nodes changed. Merge all properties of the + * original device with nodes from the new device. Keep the + * original device and discard the new one. + * + * Check that the device is actually the same device type and number + * of terminals. If not, throw an error and abandon the new device. + */ + + if ((newdev->dev_class != class) || + (strcmp(EFDevTypes[newdev->dev_type], type))) + { + TxError("Device %s %s at (%d, %d) overlaps incompatible device %s %s!\n", + extDevTable[class], type, r->r_xbot, r->r_ybot, + extDevTable[newdev->dev_class], EFDevTypes[newdev->dev_type]); + return 0; + } + else if (newdev->dev_nterm != nterminals) + { + TxError("Device %s %s at (%d, %d) overlaps device with incompatible" + " number of terminals (%d vs. %d)!\n", + extDevTable[class], type, r->r_xbot, r->r_ybot, nterminals, + newdev->dev_nterm); + return 0; + } + } + else + { + newdev = (Dev *) mallocMagic((unsigned) DevSize(nterminals)); + + /* Add this dev to the hash table for def */ + HashSetValue(he, (ClientData)newdev); + + newdev->dev_cap = devtmp.dev_cap; + newdev->dev_res = devtmp.dev_res; + newdev->dev_area = devtmp.dev_area; + newdev->dev_perim = devtmp.dev_perim; + newdev->dev_length = devtmp.dev_length; + newdev->dev_width = devtmp.dev_width; + newdev->dev_params = devtmp.dev_params; + + newdev->dev_nterm = nterminals; + newdev->dev_rect = *r; + newdev->dev_type = efBuildAddStr(EFDevTypes, &EFDevNumTypes, MAXDEVTYPES, type); + newdev->dev_class = class; + switch (class) + { + case DEV_FET: /* old-style "fet" record */ + newdev->dev_area = atoi(argv[0]); + newdev->dev_perim = atoi(argv[1]); + break; + case DEV_MOSFET: /* new-style "device mosfet" record */ + case DEV_ASYMMETRIC: + case DEV_BJT: + newdev->dev_length = atoi(argv[0]); + newdev->dev_width = atoi(argv[1]); + break; + case DEV_RES: + if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1])) + { + newdev->dev_length = atoi(argv[0]); + newdev->dev_width = atoi(argv[1]); + } + else if (StrIsNumeric(argv[0])) + { + newdev->dev_res = (float)atof(argv[0]); + } + else + { + if (hasModel) + { + efReadError("Error: expected L and W, got %s %s\n", argv[0], + argv[1]); + newdev->dev_length = 0; + newdev->dev_width = 0; + } + else + { + efReadError("Error: expected resistance value, got %s\n", + argv[0]); + newdev->dev_res = 0.0; + } + } + break; + case DEV_CAP: + case DEV_CAPREV: + if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1])) + { + newdev->dev_length = atoi(argv[0]); + newdev->dev_width = atoi(argv[1]); + } + else if (StrIsNumeric(argv[0])) + { + newdev->dev_cap = (float)atof(argv[0]); + } + else + { + if (hasModel) + { + efReadError("Error: expected L and W, got %s %s\n", argv[0], + argv[1]); + newdev->dev_length = 0; + newdev->dev_width = 0; + } + else + { + efReadError("Error: expected capacitance value, got %s\n", + argv[0]); + newdev->dev_cap = 0.0; + } + } + break; + } + } + + newdev->dev_subsnode = devtmp.dev_subsnode; switch (class) { case DEV_FET: /* old-style "fet" record */ - newdev->dev_area = atoi(argv[0]); - newdev->dev_perim = atoi(argv[1]); newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); break; case DEV_MOSFET: /* new-style "device mosfet" record */ case DEV_ASYMMETRIC: case DEV_BJT: - newdev->dev_length = atoi(argv[0]); - newdev->dev_width = atoi(argv[1]); - /* "None" in the place of the substrate name means substrate is ignored */ if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0)) newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); break; case DEV_RES: - if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1])) - { - newdev->dev_length = atoi(argv[0]); - newdev->dev_width = atoi(argv[1]); - } - else if (StrIsNumeric(argv[0])) - { - newdev->dev_res = (float)atof(argv[0]); - } - else - { - if (hasModel) - { - efReadError("Error: expected L and W, got %s %s\n", argv[0], - argv[1]); - newdev->dev_length = 0; - newdev->dev_width = 0; - } - else - { - efReadError("Error: expected resistance value, got %s\n", argv[0]); - newdev->dev_res = 0.0; - } - } if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0)) newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); break; case DEV_CAP: case DEV_CAPREV: - if (hasModel && StrIsInt(argv[0]) && StrIsInt(argv[1])) - { - newdev->dev_length = atoi(argv[0]); - newdev->dev_width = atoi(argv[1]); - } - else if (StrIsNumeric(argv[0])) - { - newdev->dev_cap = (float)atof(argv[0]); - } - else - { - if (hasModel) - { - efReadError("Error: expected L and W, got %s %s\n", argv[0], - argv[1]); - newdev->dev_length = 0; - newdev->dev_width = 0; - } - else - { - efReadError("Error: expected capacitance value, got %s\n", argv[0]); - newdev->dev_cap = 0.0; - } - } if ((argstart == 3) && (strncmp(argv[2], "None", 4) != 0)) newdev->dev_subsnode = efBuildDevNode(def, argv[2], TRUE); @@ -859,10 +919,6 @@ efBuildDevice(def, class, type, r, argc, argv) #undef TERM_PERIM #undef TERM_ATTRS - /* Add this dev to the list for def */ - newdev->dev_next = def->def_devs; - def->def_devs = newdev; - return 0; } @@ -1696,6 +1752,36 @@ efFreeUseTable(table) } } +/* + * ---------------------------------------------------------------------------- + * + * efFreeDevTable -- + * + * Free the device records allocated for each entry in the device hash table, + * the memory allocated by the device, leaving the hash entry null. + * + * ---------------------------------------------------------------------------- + */ + +void +efFreeDevTable(table) + HashTable *table; +{ + Dev *dev; + HashSearch hs; + HashEntry *he; + int n; + + HashStartSearch(&hs); + while (he = HashNext(table, &hs)) + { + dev = (Dev *)HashGetValue(he); + for (n = 0; n < (int)dev->dev_nterm; n++) + if (dev->dev_terms[n].dterm_attrs) + freeMagic((char *) dev->dev_terms[n].dterm_attrs); + freeMagic((char *) dev); + } +} /* * ---------------------------------------------------------------------------- diff --git a/extflat/EFdef.c b/extflat/EFdef.c index 0ef549f..e0b7c30 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 9725def..bd02d9c 100644 --- a/extflat/EFflat.c +++ b/extflat/EFflat.c @@ -205,7 +205,7 @@ EFFlatBuildOneLevel(def, flags) if (usecount > 0) efHierSrUses(&efFlatContext, efFlatNodesDeviceless, (ClientData)&usecount); - if ((usecount == 0) && (efFlatRootUse.use_def->def_devs == NULL)) + if ((usecount == 0) && (HashGetNumEntries(&efFlatRootUse.use_def->def_devs) == 0)) efFlatRootUse.use_def->def_flags |= DEF_NODEVICES; /* Record all local nodes */ @@ -372,7 +372,7 @@ efFlatNodesDeviceless(hc, cdata) if (newcount > 0) efHierSrUses(hc, efFlatNodesDeviceless, (ClientData)&newcount); - if ((hc->hc_use->use_def->def_devs == NULL) && (newcount == 0)) + if ((HashGetNumEntries(&hc->hc_use->use_def->def_devs) == 0) && (newcount == 0)) { /* Add all our own nodes to the table */ efAddNodes(hc, TRUE); @@ -527,6 +527,7 @@ efAddNodes(hc, stdcell) HashSetValue(he, (char *) newname); newname->efnn_node = newnode; newname->efnn_hier = hierName; + newname->efnn_port = -1; if (newnode->efnode_name) { newname->efnn_next = newnode->efnode_name->efnn_next; @@ -1018,14 +1019,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 2b38443..cef6bd5 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 9c38052..a9cbf2c 100644 --- a/extflat/EFint.h +++ b/extflat/EFint.h @@ -156,6 +156,7 @@ typedef struct def HashTable def_nodes; /* Map names into EFNodeNames */ HashTable def_dists; /* Map pairs of names into Distances */ HashTable def_uses; /* Hash children of this def by name */ + HashTable def_devs; /* Devices (hash by position) */ EFNode def_firstn; /* Head of circular list of nodes */ /* The following are all NULL-terminated lists */ @@ -163,7 +164,6 @@ typedef struct def Connection *def_conns; /* Hierarchical connections/adjustments */ Connection *def_caps; /* Two-terminal capacitors */ Connection *def_resistors; /* Two-terminal resistors */ - Dev *def_devs; /* Devices */ Kill *def_kills; /* Used to modify hierarchical structure * using information present only in the * parent, e.g, to kill an old node and diff --git a/extflat/EFread.c b/extflat/EFread.c index b57477f..c590129 100644 --- a/extflat/EFread.c +++ b/extflat/EFread.c @@ -356,8 +356,7 @@ readfile: r.r_xtop = atoi(argv[5]); r.r_ytop = atoi(argv[6]); - if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7, - &argv[7]) != 0) + if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7, &argv[7]) != 0) { efReadError("Incomplete terminal description for device\n"); continue; diff --git a/extflat/EFvisit.c b/extflat/EFvisit.c index 8d802ed..35de676 100644 --- a/extflat/EFvisit.c +++ b/extflat/EFvisit.c @@ -300,6 +300,8 @@ efVisitDevs(hc, ca) Dev *dev; float scale; Transform t; + HashSearch hs; + HashEntry *he; if (def->def_flags & DEF_SUBCIRCUIT) return 0; @@ -311,15 +313,17 @@ efVisitDevs(hc, ca) t = hc->hc_trans; /* Visit our own devices */ - for (dev = def->def_devs; dev; dev = dev->dev_next) + + HashStartSearch(&hs); + while (he = HashNext(&def->def_devs, &hs)) { + dev = (Dev *)HashGetValue(he); if (efDevKilled(dev, hc->hc_hierName)) continue; if ((*ca->ca_proc)(dev, hc->hc_hierName, scale, &t, ca->ca_cdata)) return 1; } - return 0; } diff --git a/extract/ExtTech.c b/extract/ExtTech.c index 94b74c7..96e3d4c 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -71,7 +71,7 @@ typedef enum AREAC, CONTACT, CSCALE, DEFAULTAREACAP, DEFAULTOVERLAP, DEFAULTPERIMETER, DEFAULTSIDEOVERLAP, DEFAULTSIDEWALL, - DEVICE, FET, FETRESIST, HEIGHT, ANTENNA, TIEDOWN, LAMBDA, OVERC, + DEVICE, FET, FETRESIST, HEIGHT, ANTENNA, MODEL, TIEDOWN, LAMBDA, OVERC, PERIMC, PLANEORDER, NOPLANEORDER, RESIST, RSCALE, SIDEHALO, SIDEOVERLAP, SIDEWALL, STEP, STYLE, SUBSTRATE, UNITS, VARIANT } Key; @@ -122,9 +122,12 @@ static keydesc keyTable[] = { "height", HEIGHT, 4, 4, "type height-above-subtrate thickness", - "antenna", ANTENNA, 3, 3, + "antenna", ANTENNA, 4, 4, "type antenna-ratio", + "model", MODEL, 3, 3, +"partial-cumulative area-sidewall", + "tiedown", TIEDOWN, 2, 2, "types", @@ -376,6 +379,35 @@ ExtGetDevInfo(idx, devnameptr, sd_rclassptr, sub_rclassptr, subnameptr) #endif /* MAGIC_WRAPPER */ +/* + * ---------------------------------------------------------------------------- + * + * extGetDevType -- + * + * Given an extraction model device name (devname), return the associated + * magic tiletype for the device. + * + * Results: + * Tile type that represents the device "devname" in the magic database. + * + * ---------------------------------------------------------------------------- + */ + +TileType +extGetDevType(devname) + char *devname; +{ + TileType t; + ExtDevice *devptr; + + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + for (devptr = ExtCurStyle->exts_device[t]; devptr; devptr = devptr->exts_next) + if (!strcmp(devptr->exts_deviceName, devname)) + return t; + + return -1; +} + #ifdef THREE_D /* @@ -672,7 +704,8 @@ extTechStyleInit(style) for (r = 0; r < DBNumTypes; r++) { - style->exts_antennaRatio[r] = 0; + style->exts_antennaRatio[r].ratioGate = 0.0; + style->exts_antennaRatio[r].ratioDiff = 0.0; style->exts_resistByResistClass[r] = 0; TTMaskZero(&style->exts_typesByResistClass[r]); style->exts_typesResistChanged[r] = DBAllButSpaceAndDRCBits; @@ -2321,17 +2354,53 @@ ExtTechLine(sectionName, argc, argv) if (!StrIsNumeric(argv[2])) { - TechError("Layer antenna ratio %s must be numeric\n", argv[2]); + TechError("Gate layer antenna ratio %s must be numeric\n", argv[2]); break; } antennaratio = (float)strtod(argv[2], NULL); for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) if (TTMaskHasType(&types1, t)) { - ExtCurStyle->exts_antennaRatio[t] = antennaratio; + ExtCurStyle->exts_antennaRatio[t].ratioGate = antennaratio; + } + + if (!StrIsNumeric(argv[3])) + { + if (!strcasecmp(argv[3], "none")) + antennaratio = INFINITY; + else + { + TechError("Diff layer antenna ratio %s must be numeric\n", argv[3]); + break; + } + } + else + antennaratio = (float)strtod(argv[3], NULL); + for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) + if (TTMaskHasType(&types1, t)) + { + ExtCurStyle->exts_antennaRatio[t].ratioDiff = antennaratio; } } break; + case MODEL: + if (!strcmp(argv[1], "partial")) + ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_PARTIAL; + else if (!strcmp(argv[1], "cumulative")) + ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_CUMULATIVE; + else + TxError("Unknown antenna model \"%s\": Use \"partial\" or " + "\"cumulative\""); + + if (!strcmp(argv[2], "area")) + ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_AREA; + else if (!strcmp(argv[2], "sidewall")) + ExtCurStyle->exts_antennaModel |= ANTENNAMODEL_SIDEWALL; + else + TxError("Unknown antenna model \"%s\": Use \"area\" or " + "\"sidewall\""); + break; + case TIEDOWN: TTMaskSetMask(&ExtCurStyle->exts_antennaTieTypes, &types1); break; @@ -2973,6 +3042,10 @@ zinit: ec = ec->ec_next) ec->ec_cap *= 0.5; } + + /* Layer thickness and height are in microns, but are floating-point */ + style->exts_thick[r] /= dscale; + style->exts_height[r] /= dscale; } /* side halo and step size are also in microns */ diff --git a/extract/extract.h b/extract/extract.h index b63c4ac..82e143d 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 44b7f7e..7e9c7a2 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -48,6 +48,17 @@ typedef int ResValue; /* Warning: in some places resistances are stored * as ints. This is here for documentation only. */ +typedef struct { + float ratioGate; + float ratioDiff; +} RatioValues; + +/* Antenna models */ +#define ANTENNAMODEL_PARTIAL 0x01 +#define ANTENNAMODEL_CUMULATIVE 0x02 +#define ANTENNAMODEL_AREA 0x04 +#define ANTENNAMODEL_SIDEWALL 0x08 + /* ------------------------ Parameter lists --------------------------- */ /* These lists keep track of what parameter names subcircuit definitions @@ -656,8 +667,10 @@ typedef struct extstyle float exts_height[NT]; float exts_thick[NT]; + char exts_antennaModel; + /* Antenna area ratio for each layer */ - float exts_antennaRatio[NT]; + RatioValues exts_antennaRatio[NT]; /* Mask of types that tie down antennas */ TileTypeBitMask exts_antennaTieTypes; @@ -1060,6 +1073,7 @@ extern NodeRegion *extBasic(); extern NodeRegion *extFindNodes(); extern ExtTree *extHierNewOne(); extern int extNbrPushFunc(); +extern TileType extGetDevType(); /* --------------------- Miscellaneous globals ------------------------ */ diff --git a/lef/lefWrite.c b/lef/lefWrite.c index 30859c1..8e2106c 100644 --- a/lef/lefWrite.c +++ b/lef/lefWrite.c @@ -83,6 +83,7 @@ lefFileOpen(def, file, suffix, mode, prealfile) */ { char namebuf[512], *name, *endp, *ends; + char *locsuffix; int len; FILE *rfile; @@ -115,14 +116,19 @@ lefFileOpen(def, file, suffix, mode, prealfile) (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 +640,7 @@ lefWriteMacro(def, f, scale, hide) { bool propfound; char *propvalue, *class = NULL; - Label *lab; + Label *lab, *tlab; Rect boundary, labr; SearchContext scx; CellDef *lefFlatDef; @@ -964,15 +970,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 diff --git a/resis/ResReadSim.c b/resis/ResReadSim.c index 6d9dad1..4a447aa 100644 --- a/resis/ResReadSim.c +++ b/resis/ResReadSim.c @@ -79,7 +79,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ ResSimNode *ResInitializeNode(); ResSimNode *ResOriginalNodes; /*Linked List of Nodes */ -static float lambda=1.0; /* Scale factor */ +static float resscale=1.0; /* Scale factor */ char RDEV_NOATTR[1]={'0'}; ResFixPoint *ResFixList; @@ -146,12 +146,8 @@ ResReadSim(simfile,fetproc,capproc,resproc,attrproc,mergeproc) case '|': if (strcmp(line[NODEUNITS],"units:") == 0) { - lambda = (float)atof(line[NODELAMBDA]); - if (lambda == 0.0) lambda = 1.0; - /* NOTE: units is derived from EFScale */ - /* which needs a factor of 100 conversion */ - /* to database units. */ - lambda *= 100.0; + resscale = (float)atof(line[NODELAMBDA]); + if (resscale == 0.0) resscale = 1.0; } result=0; break; @@ -231,6 +227,14 @@ ResReadNode(nodefile) HashEntry *entry; ResSimNode *node; char *cp; + float lambda; + + /* NOTE: Units from the .sim file or the .nodes file are in centimicrons + * when multiplied by resscale (units from the .sim file 1st line). + * multiply resscale by the extract scale (exts_unitsPerLambda) used to + * generate .ext dimensions originally, to get back to database units. + */ + lambda = resscale * (float)ExtCurStyle->exts_unitsPerLambda; fp = PaOpen(nodefile,"r",".nodes",".", (char *) NULL, (char **) NULL); if (fp == NULL) @@ -243,17 +247,13 @@ ResReadNode(nodefile) entry = HashFind(&ResNodeTable,line[NODENODENAME]); node = ResInitializeNode(entry); - /* NOTE: Fixed 10/15/2019. No scalefactor is passed to EFNodeVisit() - * so there is no scaling by lambda. Values are in centimicrons always, - * and factor of 100 is required to get database units. - */ - node->location.p_x = (int)((float)atof(line[NODENODEX]) / 100.0); - node->location.p_y = (int)((float)atof(line[NODENODEY]) / 100.0); + node->location.p_x = (int)((float)atof(line[NODENODEX]) / lambda); + node->location.p_y = (int)((float)atof(line[NODENODEY]) / lambda); #ifdef ARIEL - node->rs_bbox.r_xbot = (int)((float)atof(line[NODE_BBOX_LL_X]) / 100.0); - node->rs_bbox.r_ybot = (int)((float)atof(line[NODE_BBOX_LL_Y]) / 100.0); - node->rs_bbox.r_xtop = (int)((float)atof(line[NODE_BBOX_UR_X]) / 100.0); - node->rs_bbox.r_ytop = (int)((float)atof(line[NODE_BBOX_UR_Y]) / 100.0); + node->rs_bbox.r_xbot = (int)((float)atof(line[NODE_BBOX_LL_X]) / lambda); + node->rs_bbox.r_ybot = (int)((float)atof(line[NODE_BBOX_LL_Y]) / lambda); + node->rs_bbox.r_xtop = (int)((float)atof(line[NODE_BBOX_UR_X]) / lambda); + node->rs_bbox.r_ytop = (int)((float)atof(line[NODE_BBOX_UR_Y]) / lambda); #endif if (cp = strchr(line[NODETYPE], ';')) *cp = '\0'; node->type = DBTechNameType(line[NODETYPE]); @@ -340,6 +340,7 @@ ResSimDevice(line,rpersquare,ttype) int rvalue,i,j,k; char *newattr,tmpattr[MAXTOKEN]; static int nowarning = TRUE; + float lambda; device = (RDev *) mallocMagic((unsigned) (sizeof(RDev))); if ((line[RDEV_WIDTH][0] == '\0') || (line[RDEV_LENGTH][0] == '\0')) @@ -360,8 +361,11 @@ ResSimDevice(line,rpersquare,ttype) device->tnumber = ++Maxtnumber; device->status = FALSE; device->nextDev = ResRDevList; - device->location.p_x = atoi(line[RDEV_DEVX]); - device->location.p_y = atoi(line[RDEV_DEVY]); + + lambda = resscale * (float)ExtCurStyle->exts_unitsPerLambda; + device->location.p_x = (int)((float)atof(line[RDEV_DEVX]) / lambda); + device->location.p_y = (int)((float)atof(line[RDEV_DEVY]) / lambda); + device->rs_gattr=RDEV_NOATTR; device->rs_sattr=RDEV_NOATTR; device->rs_dattr=RDEV_NOATTR; |