diff --git a/VERSION b/VERSION index a8daa452..922558bc 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.363 +8.3.364 diff --git a/calma/CalmaRdpt.c b/calma/CalmaRdpt.c index b24d18de..6a462ed7 100644 --- a/calma/CalmaRdpt.c +++ b/calma/CalmaRdpt.c @@ -283,7 +283,7 @@ calmaElementBoundary() /* Convert the polygon to rectangles. */ - rp = CIFPolyToRects(pathheadp, plane, CIFPaintTable, (PaintUndoInfo *)NULL); + rp = CIFPolyToRects(pathheadp, plane, CIFPaintTable, (PaintUndoInfo *)NULL, TRUE); CIFFreePath(pathheadp); /* If the input layer is designated for ports by a "label" */ diff --git a/cif/CIFrdpoly.c b/cif/CIFrdpoly.c index 20377b47..3202e68f 100644 --- a/cif/CIFrdpoly.c +++ b/cif/CIFrdpoly.c @@ -29,6 +29,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "database/database.h" #include "cif/CIFint.h" #include "cif/CIFread.h" +#include "calma/calma.h" #include "utils/malloc.h" #define HEDGE 0 /* Horizontal edge */ @@ -222,11 +223,12 @@ cifCross(edge, dir, ybot, ytop) */ LinkedRect * -CIFPolyToRects(path, plane, resultTbl, ui) +CIFPolyToRects(path, plane, resultTbl, ui, isCalma) CIFPath *path; /* Path describing a polygon. */ Plane *plane; /* Plane to draw on */ PaintResultType *resultTbl; PaintUndoInfo *ui; + bool isCalma; /* TRUE for Calma, FALSE for CIF */ { int npts = 0, n, *dir, curr, wrapno; int xbot, xtop, ybot, ytop; @@ -240,6 +242,9 @@ CIFPolyToRects(path, plane, resultTbl, ui) if ((tail->cifp_x != path->cifp_x) || (tail->cifp_y != path->cifp_y)) { + if (isCalma) + CalmaReadError("Boundary is not closed.\n" ); + p = (CIFPath *) mallocMagic ((unsigned) sizeof (CIFPath)); p->cifp_x = path->cifp_x; p->cifp_y = path->cifp_y; diff --git a/cif/CIFrdpt.c b/cif/CIFrdpt.c index e39b49f1..d05bedf1 100644 --- a/cif/CIFrdpt.c +++ b/cif/CIFrdpt.c @@ -481,7 +481,7 @@ CIFPaintWirePath(pathheadp, width, endcap, plane, ptable, ui) /* Slow draw for non-Manhattan paths: */ /* Break the area up into triangles and rectangles */ - rectp = CIFPolyToRects(polypath, plane, ptable, ui); + rectp = CIFPolyToRects(polypath, plane, ptable, ui, FALSE); CIFFreePath(polypath); for (; rectp != NULL ; rectp = rectp->r_next) @@ -583,7 +583,7 @@ PaintPolygon(pointlist, number, plane, ptable, ui, keep) cifpath = newpath; } - rectlist = CIFPolyToRects(cifpath, plane, ptable, ui); + rectlist = CIFPolyToRects(cifpath, plane, ptable, ui, FALSE); CIFFreePath(cifpath); for (rectp = rectlist; rectp != NULL ; rectp = rectp->r_next) @@ -807,7 +807,7 @@ CIFParsePoly() /* Convert the polygon to rectangles. */ rectp = CIFPolyToRects(pathheadp, cifReadPlane, CIFPaintTable, - (PaintUndoInfo *)NULL); + (PaintUndoInfo *)NULL, FALSE); CIFFreePath(pathheadp); if (rectp == NULL) { diff --git a/commands/CmdCD.c b/commands/CmdCD.c index 830bb9c9..822e8de8 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -2907,7 +2907,7 @@ CmdCorner(w, cmd) ui.pu_pNum = pNum; rectp = CIFPolyToRects(cmdPathList.pathlist->pathhead, plane, - resultTbl, &ui); + resultTbl, &ui, FALSE); for (; rectp != NULL; rectp = rectp->r_next) { DBPaintPlane(plane, &rectp->r_r, resultTbl, &ui); diff --git a/commands/CmdE.c b/commands/CmdE.c index 32e13ff7..6f9f7912 100644 --- a/commands/CmdE.c +++ b/commands/CmdE.c @@ -42,6 +42,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "drc/drc.h" #include "textio/txcommands.h" #include "extract/extract.h" +#include "extract/extractInt.h" #include "select/select.h" /* C99 compat */ @@ -860,14 +861,15 @@ cmdExpandFunc(use, windowMask) #define EXTALL 0 #define EXTCELL 1 #define EXTDO 2 -#define EXTHELP 3 -#define EXTLENGTH 4 -#define EXTNO 5 -#define EXTPARENTS 6 -#define EXTSHOWPARENTS 7 -#define EXTSTYLE 8 -#define EXTUNIQUE 9 -#define EXTWARN 10 +#define EXTHALO 3 +#define EXTHELP 4 +#define EXTLENGTH 5 +#define EXTNO 6 +#define EXTPARENTS 7 +#define EXTSHOWPARENTS 8 +#define EXTSTYLE 9 +#define EXTUNIQUE 10 +#define EXTWARN 11 #define WARNALL 0 #define WARNDUP 1 @@ -900,6 +902,7 @@ CmdExtract(w, cmd) { char **msg, *namep, *arg; int option, warn, len, n, all; + int dist; bool no; CellUse *selectedUse; CellDef *selectedDef; @@ -953,6 +956,7 @@ CmdExtract(w, cmd) "all extract root cell and all its children", "cell name extract selected cell into file \"name\"", "do [option] enable extractor option", + "halo [value] print or set the sidewall halo distance", "help print this help information", "length [option] control pathlength extraction information", "no [option] disable extractor option", @@ -1060,6 +1064,36 @@ CmdExtract(w, cmd) ExtractOneCell(selectedUse->cu_def, namep, FALSE); return; + case EXTHALO: + if (ExtCurStyle == NULL) + { + TxError("No extraction style set.\n"); + return; + } + else if (argc == 2) + { +#ifdef MAGIC_WRAPPER + Tcl_Obj *tobj; + tobj = Tcl_NewIntObj(ExtCurStyle->exts_sideCoupleHalo); + Tcl_SetObjResult(magicinterp, tobj); +#else + TxPrintf("Side overlap halo is %d\n", ExtCurStyle->exts_sideCoupleHalo); +#endif + return; + } + else if (argc != 3) goto wrongNumArgs; + + /* argv[2] is a halo distance */ + dist = cmdParseCoord(w, argv[2], TRUE, TRUE); + if (dist <= 0) + { + TxError("Bad halo distance. Halo must be strictly positive."); + return; + } + else + ExtCurStyle->exts_sideCoupleHalo = dist; + break; + case EXTPARENTS: selectedUse = CmdGetSelectedCell((Transform *) NULL); if (selectedUse == NULL) diff --git a/ext2spice/ext2spice.c b/ext2spice/ext2spice.c index 143d1e86..6d2e6033 100644 --- a/ext2spice/ext2spice.c +++ b/ext2spice/ext2spice.c @@ -1093,7 +1093,7 @@ runexttospice: TTMaskZero(&initMask); if (!esDistrJunct) - TTMaskCom(&initMask); + TTMaskSetType(&initMask, efNumResistClasses); if (esMergeDevsA || esMergeDevsC) { @@ -1271,7 +1271,7 @@ main(argc, argv) TTMaskZero(&initMask); if (!esDistrJunct) - TTMaskCom(&initMask); + TTMaskSetType(&initMask, efNumResistClasses); if ( esMergeDevsA || esMergeDevsC ) { EFVisitDevs(devMergeVisit, (ClientData) NULL); diff --git a/extract/ExtCouple.c b/extract/ExtCouple.c index c17d068c..3f6b1745 100644 --- a/extract/ExtCouple.c +++ b/extract/ExtCouple.c @@ -22,7 +22,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #endif /* not lint */ #include -#include /* For sin() */ +#include /* For atan() */ #include "utils/magic.h" #include "utils/geometry.h" @@ -41,10 +41,6 @@ HashTable *extCoupleHashPtr; /* Clipping area for coupling searches */ Rect *extCoupleSearchArea; -/* Current list of sidewall capacitance rules */ -EdgeCap *extCoupleList; -EdgeCap *extOverlapList; - /* Def being processed */ CellDef *extOverlapDef; @@ -52,9 +48,8 @@ CellDef *extOverlapDef; int extBasicOverlap(), extBasicCouple(); int extAddOverlap(), extAddCouple(); int extSideLeft(), extSideRight(), extSideBottom(), extSideTop(); -int extShieldLeft(), extShieldRight(), extShieldBottom(), extShieldTop(); int extWalkLeft(), extWalkRight(), extWalkBottom(), extWalkTop(); -int extSideOverlap(); +int extSideOverlap(), extFindOverlap(); void extSideCommon(); /* Structure to pass on to the coupling and sidewall capacitance */ @@ -80,10 +75,13 @@ typedef struct _ecpls { typedef struct _esws { Boundary *bp; - int plane_of_boundary; - int plane_checked; - int fringe_halo; - float shieldfrac; + int plane_of_boundary; + int plane_checked; + bool fringe_halo; + Rect *area; + EdgeCap *extCoupleList; /* List of sidewall capacitance rules */ + EdgeCap *extOverlapList; /* List of overlap capacitance rules */ + CellDef *def; } extSidewallStruct; /* --------------------- Debugging stuff ---------------------- */ @@ -142,15 +140,6 @@ void extAdjustCouple(he, c, str) * hash table. (We may want to deduct the perimeter capacitance * to substrate?). * - * and a mitigating effect: - * - * Sidewall - * shield. When another shape on the same plane is in the proximity of - * a sidewall edge, then the other shape partially shields the - * fringe (sidewall overlap) capacitance. The amount of shielding - * is modeled by an ellipse between the fringe effect distance - * exts_fringeShieldHalo (no shielding) and zero (full shielding). - * * Requires that ExtFindRegions has been run on 'def' to label all its * tiles with NodeRegions. Also requires that the HashTable 'table' * has been initialized by the caller. @@ -670,8 +659,6 @@ extBasicCouple(tile, ecs) * ---------------------------------------------------------------------------- */ -Rect extSideOverlapSearchArea; - int extAddCouple(bp, ecs) Boundary *bp; /* Boundary being considered */ @@ -682,7 +669,6 @@ extAddCouple(bp, ecs) PlaneMask pMask; Boundary bpCopy; Rect r, ovr; - CellDef *def = ecs->def; extSidewallStruct esws; int distFringe; @@ -692,11 +678,13 @@ extAddCouple(bp, ecs) if (DBIsContact(tout)) tout = DBPlaneToResidue(tout, ecs->plane); - extCoupleList = ExtCurStyle->exts_sideCoupleCap[tin][tout]; - extOverlapList = ExtCurStyle->exts_sideOverlapCap[tin][tout]; - if (extCoupleList == NULL && extOverlapList == NULL) + esws.extCoupleList = ExtCurStyle->exts_sideCoupleCap[tin][tout]; + esws.extOverlapList = ExtCurStyle->exts_sideOverlapCap[tin][tout]; + if ((esws.extCoupleList == NULL) && (esws.extOverlapList == NULL)) return (0); + esws.def = ecs->def; + /* * Clip the edge of interest to the area where we're searching * for coupling capacitance, if such an area has been specified. @@ -719,138 +707,169 @@ extAddCouple(bp, ecs) /* fringe cap is (unrealistically) assumed to couple only */ /* to shapes that are directly below the edge. */ + esws.fringe_halo = (ExtOptions & EXT_DOFRINGEHALO) ? + ((ExtCurStyle->exts_sideCoupleHalo == 0) ? FALSE : TRUE) + : FALSE; + distFringe = (ExtOptions & EXT_DOFRINGEHALO) ? - ExtCurStyle->exts_fringeShieldHalo : 1; + ExtCurStyle->exts_sideCoupleHalo : 1; if (distFringe == 0) distFringe = 1; + esws.bp = bp; + esws.plane_of_boundary = ecs->plane; + esws.area = &ovr; + switch (bp->b_direction) { case BD_LEFT: /* Along left */ r.r_xbot -= ExtCurStyle->exts_sideCoupleHalo; ovr.r_xbot -= distFringe; - if (extCoupleList) - extWalkLeft(&r, + extWalkLeft(&r, &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], - extSideLeft, bp, (ClientData)NULL); + extSideLeft, bp, (ClientData)&esws); break; case BD_RIGHT: /* Along right */ r.r_xtop += ExtCurStyle->exts_sideCoupleHalo; ovr.r_xtop += distFringe; - if (extCoupleList) - extWalkRight(&r, + extWalkRight(&r, &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], - extSideRight, bp, (ClientData)NULL); + extSideRight, bp, (ClientData)&esws); break; case BD_TOP: /* Along top */ r.r_ytop += ExtCurStyle->exts_sideCoupleHalo; ovr.r_ytop += distFringe; - if (extCoupleList) - extWalkTop(&r, + extWalkTop(&r, &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], - extSideTop, bp, (ClientData)NULL); + extSideTop, bp, (ClientData)&esws); break; case BD_BOTTOM: /* Along bottom */ r.r_ybot -= ExtCurStyle->exts_sideCoupleHalo; ovr.r_ybot -= distFringe; - if (extCoupleList) - extWalkBottom(&r, + extWalkBottom(&r, &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], - extSideBottom, bp, (ClientData)NULL); + extSideBottom, bp, (ClientData)&esws); + break; + } + return (0); +} + +/* + * ---------------------------------------------------------------------------- + * + * extRemoveSubcap -- + * + * A nearby shape blocks parasitic fringe capacitance from a layer boundary + * to substrate, and so all parasitic fringe capacitance from the layer's + * region to substrate that is blocked must be removed from the total + * substrate capacitance for that region. + * + * ---------------------------------------------------------------------------- + */ + +void +extRemoveSubcap(bp, clip, esws) + Boundary *bp; /* Boundary with fringe capacitance */ + Rect *clip; /* Area not being blocked */ + extSidewallStruct *esws; /* Overlapping edge and plane information */ +{ + int dnear, length; + double snear, cfrac; + NodeRegion *rbp; + TileType ta, tb; + float mult; + CapValue subcap; + + if (!esws->fringe_halo) return; + + ta = TiGetType(bp->b_inside); + tb = TiGetType(bp->b_outside); + rbp = (NodeRegion *)extGetRegion(bp->b_inside); + + if (bp->b_segment.r_xtop == bp->b_segment.r_xbot) + length = bp->b_segment.r_ytop - bp->b_segment.r_ybot; + else + length = bp->b_segment.r_xtop - bp->b_segment.r_xbot; + + switch (bp->b_direction) + { + case BD_LEFT: /* Tile tp is to the left of the boundary */ + dnear = bp->b_segment.r_xbot - clip->r_xbot; + break; + case BD_RIGHT: /* Tile tp is to the right of the boundary */ + dnear = clip->r_xtop - bp->b_segment.r_xtop; + break; + case BD_BOTTOM: /* Tile tp is below the boundary */ + dnear = bp->b_segment.r_ybot - clip->r_ybot; + break; + case BD_TOP: /* Tile tp is above the boundary */ + dnear = clip->r_ytop - bp->b_segment.r_ytop; break; } - /* Additional calculations for the significant shielding effect of */ - /* nearby shapes on fringe capacitance. */ + if (dnear < 0) dnear = 0; /* Don't count underlap */ + mult = ExtCurStyle->exts_overlapMult[ta][0]; + snear = 0.6366 * atan(mult * dnear); - if (extCoupleList && extOverlapList && (ExtCurStyle->exts_fringeShieldHalo > 0) - && (ExtOptions & EXT_DOCOUPLING)) - { - float shieldFrac; - NodeRegion *rbp; + /* "snear" is the fractional portion of the fringe cap seen by */ + /* the substrate, so (1.0 - snear) is the part that is blocked. */ - shieldFrac = 0.0; + subcap = ExtCurStyle->exts_perimCap[ta][tb] * (1.0 - snear) * length; + rbp->nreg_cap -= subcap; +} - /* Resize r for fringe shield calculation */ - /* and find fringe shielding amount */ +/* + * ---------------------------------------------------------------------------- + * + * extFindOverlap -- + * + * Callback function for extWalkTop/Bottom/Right/Left to find the + * side overlap (fringe) capacitance from a material edge (held in + * esws->bp) and all layers in planes below to which its fringe + * capacitance may couple. The area to search will have been reduced + * by any nearby layers on the same plane that shield the fringe + * capacitance. + * + * Results: + * Returns 0 to keep extWalk*() going. + * + * Side effects: + * See side effects of the called function extSideOverlap() + * + * ---------------------------------------------------------------------------- + */ - switch (bp->b_direction) + +int +extFindOverlap(tp, area, esws) + Tile *tp; /* Overlapped tile */ + Rect *area; /* Area to check for coupling */ + extSidewallStruct *esws; /* Overlapping edge and plane information */ +{ + PlaneMask pMask; + int pNum; + Rect *rsave; + Boundary *bp = esws->bp; + TileType tin = TiGetType(bp->b_inside); + TileType tout = TiGetType(bp->b_outside); + + pMask = ExtCurStyle->exts_sideOverlapOtherPlanes[tin][tout]; + extOverlapDef = esws->def; + + /* Replace esws->area with area */ + rsave = esws->area; + esws->area = area; + + for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) + if (PlaneMaskHasPlane(pMask, pNum)) { - case BD_LEFT: /* Along left */ - r.r_xbot += ExtCurStyle->exts_sideCoupleHalo ; - r.r_xbot -= ExtCurStyle->exts_fringeShieldHalo ; - extWalkLeft(&r, - &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], - extShieldLeft, bp, (ClientData) &shieldFrac); - break; - case BD_RIGHT: /* Along right */ - r.r_xtop -= ExtCurStyle->exts_sideCoupleHalo ; - r.r_xtop += ExtCurStyle->exts_fringeShieldHalo ; - extWalkRight(&r, - &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], - extShieldRight, bp, (ClientData) &shieldFrac); - break; - case BD_TOP: /* Along top */ - r.r_ytop -= ExtCurStyle->exts_sideCoupleHalo ; - r.r_ytop += ExtCurStyle->exts_fringeShieldHalo ; - extWalkTop(&r, - &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], - extShieldTop, bp, (ClientData) &shieldFrac); - break; - case BD_BOTTOM: /* Along bottom */ - r.r_ybot += ExtCurStyle->exts_sideCoupleHalo ; - r.r_ybot -= ExtCurStyle->exts_fringeShieldHalo ; - extWalkBottom(&r, - &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], - extShieldBottom, bp, (ClientData) &shieldFrac); - break; + esws->plane_checked = pNum; + (void) DBSrPaintArea((Tile *) NULL, esws->def->cd_planes[pNum], + area, &ExtCurStyle->exts_sideOverlapOtherTypes[tin][tout], + extSideOverlap, (ClientData)esws); } - - esws.shieldfrac = shieldFrac; - - /* Remove the part of the capacitance to substrate that came from - * the sidewall overlap and that was shielded by the nearby shape. - */ - if (esws.shieldfrac > 0.0) - { - int length; - CapValue subcap; - - if (bp->b_segment.r_xtop == bp->b_segment.r_xbot) - length = bp->b_segment.r_ytop - bp->b_segment.r_ybot; - else - length = bp->b_segment.r_xtop - bp->b_segment.r_xbot; - - subcap = ExtCurStyle->exts_perimCap[tin][tout] * length * esws.shieldfrac; - - rbp = (NodeRegion *) extGetRegion(bp->b_inside); - rbp->nreg_cap -= subcap; - } - } - else - esws.shieldfrac = 0.0; - - if (extOverlapList) - { - pMask = ExtCurStyle->exts_sideOverlapOtherPlanes[tin][tout]; - extSideOverlapSearchArea = ovr; - extOverlapDef = def; - - esws.bp = bp; - esws.plane_of_boundary = ecs->plane; - esws.fringe_halo = distFringe; - - for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) - if (PlaneMaskHasPlane(pMask, pNum)) - { - esws.plane_checked = pNum; - (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[pNum], - &ovr, &ExtCurStyle->exts_sideOverlapOtherTypes[tin][tout], - extSideOverlap, (ClientData) &esws); - } - } - - return (0); + esws->area = rsave; + return 0; } /* @@ -886,7 +905,7 @@ extSideOverlap(tp, esws) HashEntry *he; EdgeCap *e; int length, areaAccountedFor, areaTotal; - double cfrac, afrac; + double cfrac, sfrac, afrac, mult; CapValue cap; CoupleKey ck; @@ -907,12 +926,10 @@ extSideOverlap(tp, esws) } TITORECT(tp, &ov.o_clip); - GEOCLIP(&ov.o_clip, &extSideOverlapSearchArea); - areaTotal = length * esws->fringe_halo; + GEOCLIP(&ov.o_clip, esws->area); + areaTotal = GEO_WIDTH(&ov.o_clip) * GEO_HEIGHT(&ov.o_clip); areaAccountedFor = 0; - ASSERT(areaTotal == GEO_WIDTH(&ov.o_clip) * GEO_HEIGHT(&ov.o_clip), - "extSideOverlap"); ta = TiGetType(bp->b_inside); /* Revert any contacts to their residues */ @@ -923,50 +940,58 @@ extSideOverlap(tp, esws) /* Find the fraction of the fringe cap seen by tile tp (depends */ /* on the tile width and distance from the boundary) */ - if (esws->fringe_halo > 1) + if (esws->fringe_halo) { int dfar, dnear; - double ffar, fnear; double sfar, snear; switch (bp->b_direction) { case BD_LEFT: /* Tile tp is to the left of the boundary */ - dfar = bp->b_segment.r_ll.p_x - LEFT(tp); - dnear = bp->b_segment.r_ll.p_x - RIGHT(tp); + dfar = bp->b_segment.r_ll.p_x - ov.o_clip.r_xbot; + dnear = bp->b_segment.r_ll.p_x - ov.o_clip.r_xtop; break; case BD_RIGHT: /* Tile tp is to the right of the boundary */ - dfar = RIGHT(tp) - bp->b_segment.r_ur.p_x; - dnear = LEFT(tp) - bp->b_segment.r_ur.p_x; + dfar = ov.o_clip.r_xtop - bp->b_segment.r_ur.p_x; + dnear = ov.o_clip.r_xbot - bp->b_segment.r_ur.p_x; break; case BD_BOTTOM: /* Tile tp is below the boundary */ - dfar = bp->b_segment.r_ll.p_y - BOTTOM(tp); - dnear = bp->b_segment.r_ll.p_y - TOP(tp); + dfar = bp->b_segment.r_ll.p_y - ov.o_clip.r_ybot; + dnear = bp->b_segment.r_ll.p_y - ov.o_clip.r_ytop; break; case BD_TOP: /* Tile tp is above the boundary */ - dfar = TOP(tp) - bp->b_segment.r_ur.p_y; - dnear = BOTTOM(tp) - bp->b_segment.r_ur.p_y; + dfar = ov.o_clip.r_ytop - bp->b_segment.r_ur.p_y; + dnear = ov.o_clip.r_ybot - bp->b_segment.r_ur.p_y; break; } - if (dnear < 0) dnear = 0; /* Do not count underlap */ - if (dfar > esws->fringe_halo) dfar = esws->fringe_halo; - ffar = (double)dfar / (double)esws->fringe_halo; - fnear = (double)dnear / (double)esws->fringe_halo; - sfar = sin(1.5708 * ffar); - snear = sin(1.5708 * fnear); + if (dnear < 0) dnear = 0; /* Don't count underlap */ + mult = ExtCurStyle->exts_overlapMult[ta][tb]; + sfar = 0.6366 * atan(mult * dfar); + snear = 0.6366 * atan(mult * dnear); /* "cfrac" is the fractional portion of the fringe cap seen by */ /* tile tp along its length. This is independent of the */ /* portion of the boundary length that tile tp occupies. */ cfrac = sfar - snear; + + /* The fringe portion extracted from the substrate will be */ + /* different than the portion added to the coupling layer. */ + + mult = ExtCurStyle->exts_overlapMult[ta][0]; + sfar = 0.6366 * atan(mult * dfar); + snear = 0.6366 * atan(mult * dnear); + sfrac = sfar - snear; } else + { cfrac = 1.0; /* For simplified perimeter cap calculation */ + sfrac = 1.0; + } /* Apply each rule, incorporating shielding into the edge length. */ cap = (CapValue) 0; - for (e = extOverlapList; e; e = e->ec_next) + for (e = esws->extOverlapList; e; e = e->ec_next) { /* Only apply rules for the plane in which they are declared */ if (!PlaneMaskHasPlane(e->ec_pmask, esws->plane_checked)) continue; @@ -1008,14 +1033,14 @@ extSideOverlap(tp, esws) } if (rtp != rbp) { - if (esws->fringe_halo == 1) + if (!esws->fringe_halo) { - cap += e->ec_cap * ov.o_area * (1.0 - esws->shieldfrac); + cap += e->ec_cap * ov.o_area; } else /* (perimeter cap distributed over halo) */ { afrac = (double)ov.o_area / (double)areaTotal; - cap += e->ec_cap * length * afrac * cfrac * (1.0 - esws->shieldfrac); + cap += e->ec_cap * length * afrac * cfrac; } } areaAccountedFor += ov.o_area; @@ -1045,14 +1070,12 @@ extSideOverlap(tp, esws) outtype = DBPlaneToResidue(outtype, esws->plane_of_boundary); afrac = (double)areaAccountedFor / (double)areaTotal; - if (esws->fringe_halo == 1) + if (!esws->fringe_halo) subcap = (ExtCurStyle->exts_perimCap[ta][outtype] * - (1.0 - esws->shieldfrac) * MIN(areaAccountedFor, length)); else /* Fringe capacitance distributed over halo */ subcap = (ExtCurStyle->exts_perimCap[ta][outtype] * - (1.0 - esws->shieldfrac) * cfrac * length * - MIN(afrac, 1.0)); + sfrac * length * MIN(afrac, 1.0)); rbp->nreg_cap -= subcap; /* Ignore residual error at ~zero zeptoFarads. Probably */ /* there should be better handling of round-off here. */ @@ -1148,8 +1171,15 @@ extWalkTop(area, mask, func, bp, clientData) if (lookRight) bloc.b_segment.r_xtop = RIGHT(tp); + /* Call sidewall coupling calculation function */ if (func(tp, &bloc, clientData) != 0) return 1; + /* Clip coupling area and call fringe coupling calculation function */ + aloc = *area; + aloc.r_ytop = BOTTOM(tp); + if (extFindOverlap(bp->b_outside, &aloc, clientData) != 0) return 1; + extRemoveSubcap(bp, &aloc, clientData); + /* Recurse on tile left side */ if (lookLeft) { @@ -1176,13 +1206,18 @@ extWalkTop(area, mask, func, bp, clientData) /* coupling to tiles behind it, so return. */ return 0; } + /* Continue to walk left until out of bounds */ tp = BL(tp); } /* Continue to walk up from right edge */ tile = RT(tile); } - return 0; + + /* Any length which does not couple to anything in the */ + /* same plane is still checked for coupling to anything */ + /* below it. */ + return extFindOverlap(bp->b_outside, area, clientData); } /* @@ -1246,8 +1281,15 @@ extWalkBottom(area, mask, func, bp, clientData) if (lookRight) bloc.b_segment.r_xtop = RIGHT(tp); + /* Call sidewall coupling calculation function */ if (func(tp, &bloc, clientData) != 0) return 1; + /* Clip coupling area and call fringe coupling calculation function */ + aloc = *area; + aloc.r_ybot = TOP(tp); + if (extFindOverlap(bp->b_outside, &aloc, clientData) != 0) return 1; + extRemoveSubcap(bp, &aloc, clientData); + /* Recurse on tile left side */ if (lookLeft) { @@ -1274,13 +1316,18 @@ extWalkBottom(area, mask, func, bp, clientData) /* coupling to tiles behind it, so return. */ return 0; } + /* Continue to walk right until out of bounds */ tp = TR(tp); } /* Continue to walk down from left edge */ tile = LB(tile); } - return 0; + + /* Any length which does not couple to anything in the */ + /* same plane is still checked for coupling to anything */ + /* below it. */ + return extFindOverlap(bp->b_outside, area, clientData); } /* @@ -1344,8 +1391,15 @@ extWalkRight(area, mask, func, bp, clientData) if (lookUp) bloc.b_segment.r_ytop = TOP(tp); + /* Call sidewall coupling calculation function */ if (func(tp, &bloc, clientData) != 0) return 1; + /* Clip coupling area and call fringe coupling calculation function */ + aloc = *area; + aloc.r_xtop = LEFT(tp); + if (extFindOverlap(bp->b_outside, &aloc, clientData) != 0) return 1; + extRemoveSubcap(bp, &aloc, clientData); + /* Recurse on tile bottom side */ if (lookDown) { @@ -1372,13 +1426,18 @@ extWalkRight(area, mask, func, bp, clientData) /* coupling to tiles behind it, so return. */ return 0; } + /* Continue to walk down until out of bounds */ tp = LB(tp); } /* Continue to walk right from top edge */ tile = TR(tile); } - return 0; + + /* Any length which does not couple to anything in the */ + /* same plane is still checked for coupling to anything */ + /* below it. */ + return extFindOverlap(bp->b_outside, area, clientData); } /* @@ -1442,8 +1501,15 @@ extWalkLeft(area, mask, func, bp, clientData) if (lookUp) bloc.b_segment.r_ytop = TOP(tp); + /* Call sidewall coupling calculation function */ if (func(tp, &bloc, clientData) != 0) return 1; + /* Clip coupling area and call fringe coupling calculation function */ + aloc = *area; + aloc.r_xbot = RIGHT(tp); + if (extFindOverlap(bp->b_outside, &aloc, clientData) != 0) return 1; + extRemoveSubcap(bp, &aloc, clientData); + /* Recurse on tile bottom side */ if (lookDown) { @@ -1470,13 +1536,18 @@ extWalkLeft(area, mask, func, bp, clientData) /* coupling to tiles behind it, so return. */ return 0; } + /* Continue to walk up until out of bounds */ tp = RT(tp); } /* Continue to walk left from top edge */ tile = BL(tile); } - return 0; + + /* Any length which does not couple to anything in the */ + /* same plane is still checked for coupling to anything */ + /* below it. */ + return extFindOverlap(bp->b_outside, area, clientData); } /* @@ -1507,10 +1578,10 @@ extWalkLeft(area, mask, func, bp, clientData) */ int -extSideLeft(tpfar, bp, clientData) +extSideLeft(tpfar, bp, esws) Tile *tpfar; Boundary *bp; - ClientData clientData; /* Unused */ + extSidewallStruct *esws; { NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar); @@ -1526,7 +1597,8 @@ extSideLeft(tpfar, bp, clientData) { int overlap = MIN(TOP(tpnear), start) - MAX(BOTTOM(tpnear), limit); if (overlap > 0) - extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); + extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep, + esws->extCoupleList); } } @@ -1556,10 +1628,10 @@ extSideLeft(tpfar, bp, clientData) */ int -extSideRight(tpfar, bp, clientData) +extSideRight(tpfar, bp, esws) Tile *tpfar; Boundary *bp; - ClientData clientData; /* Unused */ + extSidewallStruct *esws; { NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar); @@ -1575,7 +1647,8 @@ extSideRight(tpfar, bp, clientData) { int overlap = MIN(TOP(tpnear), limit) - MAX(BOTTOM(tpnear), start); if (overlap > 0) - extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); + extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep, + esws->extCoupleList); } } @@ -1605,10 +1678,10 @@ extSideRight(tpfar, bp, clientData) */ int -extSideTop(tpfar, bp, clientData) +extSideTop(tpfar, bp, esws) Tile *tpfar; Boundary *bp; - ClientData clientData; /* Unused */ + extSidewallStruct *esws; { NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar); @@ -1624,7 +1697,8 @@ extSideTop(tpfar, bp, clientData) { int overlap = MIN(RIGHT(tpnear), limit) - MAX(LEFT(tpnear), start); if (overlap > 0) - extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); + extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep, + esws->extCoupleList); } } @@ -1654,10 +1728,10 @@ extSideTop(tpfar, bp, clientData) */ int -extSideBottom(tpfar, bp, clientData) +extSideBottom(tpfar, bp, esws) Tile *tpfar; Boundary *bp; - ClientData clientData; /* Unused */ + extSidewallStruct *esws; { NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar); @@ -1673,7 +1747,8 @@ extSideBottom(tpfar, bp, clientData) { int overlap = MIN(RIGHT(tpnear), start) - MAX(LEFT(tpnear), limit); if (overlap > 0) - extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); + extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep, + esws->extCoupleList); } } @@ -1704,12 +1779,13 @@ extSideBottom(tpfar, bp, clientData) */ void -extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep) +extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep, extCoupleList) NodeRegion *rinside, *rfar; /* Both must be valid */ Tile *tpnear, *tpfar; /* Tiles on near and far side of edge */ int overlap, sep; /* Overlap of this edge with original one, * and distance between the two. */ + EdgeCap *extCoupleList; /* List of sidewall capacitance rules */ { TileType near = TiGetType(tpnear), far = TiGetType(tpfar); HashEntry *he; @@ -1733,295 +1809,3 @@ extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep) extSetCapValue(he, cap); } -/* - * ---------------------------------------------------------------------------- - * - * extShieldLeft -- - * - * Searching to the left of the boundary 'bp', we found the tile - * 'tpfar' which may lie on the far side of an edge to which the - * edge bp->b_inside | bp->b_outside shields the fringing capacitance. - * - * Walk along the right-hand side of 'tpfar' searching for such edges, - * and recording the amount of shielding in the passed structure. - * - * Results: - * Returns 0 always. - * - * Side effects: - * Updates data pointed to by shieldFrac - * - * ---------------------------------------------------------------------------- - */ - -int -extShieldLeft(tpfar, bp, shieldFrac) - Tile *tpfar; - Boundary *bp; - float *shieldFrac; -{ - NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); - Tile *tpnear; - float fshield; /* fraction shielded for this segment */ - float frac; /* ratio of segment to boundary length */ - - int sep = bp->b_segment.r_xbot - RIGHT(tpfar); - int limit = MAX(bp->b_segment.r_ybot, BOTTOM(tpfar)); - int start = MIN(bp->b_segment.r_ytop, TOP(tpfar)); - float halo = (float)ExtCurStyle->exts_fringeShieldHalo; - float fsep = (float)sep; - - for (tpnear = TR(tpfar); TOP(tpnear) > limit; tpnear = LB(tpnear)) - { - int overlap = MIN(TOP(tpnear), start) - MAX(BOTTOM(tpnear), limit); - if (overlap > 0) - { - Tile *tptest = tpnear; - Point p; - NodeRegion *rnear; - - /* Walk back from edge to original boundary, checking */ - /* that no shapes are shielding the shield. . . */ - - p.p_y = (start + limit) / 2; - p.p_x = RIGHT(tpnear) + 1; - while (p.p_x < bp->b_segment.r_xbot) - { - GOTOPOINT(tptest, &p); - rnear = (NodeRegion *)extGetRegion(tptest); - if ((rnear != (NodeRegion *)extUnInit) && (rnear != rinside)) - break; - p.p_x = RIGHT(tptest) + 1; - } - if (p.p_x > bp->b_segment.r_xbot) - { - frac = (float)(start - limit) / - (float)(bp->b_segment.r_ytop - bp->b_segment.r_ybot); - /* Use sin() approximation for shielding effect */ - fshield = 1.0 - sin(1.571 * fsep / halo); - *shieldFrac = fshield * frac + (*shieldFrac) * (1.0 - frac); - } - } - } - return (0); -} - -/* - * ---------------------------------------------------------------------------- - * - * extShieldRight -- - * - * Searching to the right of the boundary 'bp', we found the tile - * 'tpfar' which may lie on the far side of an edge to which the - * edge bp->b_inside | bp->b_outside shields the fringing capacitance. - * - * Walk along the left-hand side of 'tpfar' searching for such edges, - * and recording the amount of shielding in the passed structure. - * - * Results: - * Returns 0 always. - * - * Side effects: - * Updates data pointed to by shieldFrac - * - * ---------------------------------------------------------------------------- - */ - -int -extShieldRight(tpfar, bp, shieldFrac) - Tile *tpfar; - Boundary *bp; - float *shieldFrac; -{ - NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); - Tile *tpnear; - float fshield; /* fraction shielded for this segment */ - float frac; /* ratio of segment to boundary length */ - - int sep = LEFT(tpfar) - bp->b_segment.r_xtop; - int limit = MIN(bp->b_segment.r_ytop, TOP(tpfar)); - int start = MAX(bp->b_segment.r_ybot, BOTTOM(tpfar)); - float halo = (float)ExtCurStyle->exts_fringeShieldHalo; - float fsep = (float)sep; - - for (tpnear = BL(tpfar); BOTTOM(tpnear) < limit; tpnear = RT(tpnear)) - { - int overlap = MIN(TOP(tpnear), limit) - MAX(BOTTOM(tpnear), start); - if (overlap > 0) - { - Tile *tptest = tpnear; - Point p; - NodeRegion *rnear; - - /* Walk back from edge to original boundary, checking */ - /* that no shapes are shielding the shield. . . */ - - p.p_y = (start + limit) / 2; - p.p_x = LEFT(tpnear) - 1; - while (p.p_x > bp->b_segment.r_xtop) - { - GOTOPOINT(tptest, &p); - rnear = (NodeRegion *)extGetRegion(tptest); - if ((rnear != (NodeRegion *)extUnInit) && (rnear != rinside)) - break; - p.p_x = LEFT(tptest) - 1; - } - if (p.p_x < bp->b_segment.r_xtop) - { - frac = (float)(limit - start) / - (float)(bp->b_segment.r_ytop - bp->b_segment.r_ybot); - /* Use sin() approximation for shielding effect */ - fshield = 1.0 - sin(1.571 * fsep / halo); - *shieldFrac = fshield * frac + (*shieldFrac) * (1.0 - frac); - } - } - } - return (0); -} - -/* - * ---------------------------------------------------------------------------- - * - * extShieldTop -- - * - * Searching to the top of the boundary 'bp', we found the tile - * 'tpfar' which may lie on the far side of an edge to which the - * edge bp->b_inside | bp->b_outside shields the fringing capacitance. - * - * Walk along the bottom side of 'tpfar' searching for such edges, - * and recording the amount of shielding in the passed structure. - * - * Results: - * Returns 0 always. - * - * Side effects: - * Updates data pointed to by shieldFrac - * - * ---------------------------------------------------------------------------- - */ - -int -extShieldTop(tpfar, bp, shieldFrac) - Tile *tpfar; - Boundary *bp; - float *shieldFrac; -{ - NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); - Tile *tpnear; - float fshield; /* fraction shielded for this segment */ - float frac; /* ratio of segment to boundary length */ - - int sep = BOTTOM(tpfar) - bp->b_segment.r_ytop; - int limit = MIN(bp->b_segment.r_xtop, RIGHT(tpfar)); - int start = MAX(bp->b_segment.r_xbot, LEFT(tpfar)); - float halo = (float)ExtCurStyle->exts_fringeShieldHalo; - float fsep = (float)sep; - - for (tpnear = LB(tpfar); LEFT(tpnear) < limit; tpnear = TR(tpnear)) - { - int overlap = MIN(RIGHT(tpnear), limit) - MAX(LEFT(tpnear), start); - if (overlap > 0) - { - Tile *tptest = tpnear; - Point p; - NodeRegion *rnear; - - /* Walk back from edge to original boundary, checking */ - /* that no shapes are shielding the shield. . . */ - - p.p_x = (start + limit) / 2; - p.p_y = BOTTOM(tpnear) - 1; - while (p.p_y > bp->b_segment.r_ytop) - { - GOTOPOINT(tptest, &p); - rnear = (NodeRegion *)extGetRegion(tptest); - if ((rnear != (NodeRegion *)extUnInit) && (rnear != rinside)) - break; - p.p_y = BOTTOM(tptest) - 1; - } - if (p.p_y < bp->b_segment.r_ytop) - { - frac = (float)(limit - start) / - (float)(bp->b_segment.r_xtop - bp->b_segment.r_xbot); - /* Use sin() approximation for shielding effect */ - fshield = 1.0 - sin(1.571 * fsep / halo); - *shieldFrac = fshield * frac + (*shieldFrac) * (1.0 - frac); - } - } - } - return (0); -} - -/* - * ---------------------------------------------------------------------------- - * - * extShieldBottom -- - * - * Searching to the bottom of the boundary 'bp', we found the tile - * 'tpfar' which may lie on the far side of an edge to which the - * edge bp->b_inside | bp->b_outside shields the fringing capacitance. - * - * Walk along the top side of 'tpfar' searching for such - * and recording the amount of shielding in the passed structure. - * - * Results: - * Returns 0 always. - * - * Side effects: - * Updates data pointed to by shieldFrac - * - * ---------------------------------------------------------------------------- - */ - -int -extShieldBottom(tpfar, bp, shieldFrac) - Tile *tpfar; - Boundary *bp; - float *shieldFrac; -{ - NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); - Tile *tpnear; - float fshield; /* fraction shielded for this segment */ - float frac; /* ratio of segment to boundary length */ - - int sep = bp->b_segment.r_ybot - TOP(tpfar); - int limit = MAX(bp->b_segment.r_xbot, LEFT(tpfar)); - int start = MIN(bp->b_segment.r_xtop, RIGHT(tpfar)); - float halo = (float)ExtCurStyle->exts_fringeShieldHalo; - float fsep = (float)sep; - - for (tpnear = RT(tpfar); RIGHT(tpnear) > limit; tpnear = BL(tpnear)) - { - int overlap = MIN(RIGHT(tpnear), start) - MAX(LEFT(tpnear), limit); - if (overlap > 0) - { - Tile *tptest = tpnear; - Point p; - NodeRegion *rnear; - - /* Walk back from edge to original boundary, checking */ - /* that no shapes are shielding the shield. . . */ - - p.p_x = (start + limit) / 2; - p.p_y = TOP(tpnear) + 1; - while (p.p_y < bp->b_segment.r_ybot) - { - GOTOPOINT(tptest, &p); - rnear = (NodeRegion *)extGetRegion(tptest); - if ((rnear != (NodeRegion *)extUnInit) && (rnear != rinside)) - break; - p.p_y = TOP(tptest) + 1; - } - if (p.p_y > bp->b_segment.r_ybot) - { - frac = (float)(start - limit) / - (float)(bp->b_segment.r_xtop - bp->b_segment.r_xbot); - /* Use sin() approximation for shielding effect */ - fshield = 1.0 - sin(1.571 * fsep / halo); - *shieldFrac = fshield * frac + (*shieldFrac) * (1.0 - frac); - } - } - } - return (0); -} - diff --git a/extract/ExtTech.c b/extract/ExtTech.c index 4578ee74..1f32fb3f 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -62,6 +62,12 @@ void extTechFinalStyle(); void ExtLoadStyle(); void ExtTechScale(int, int); +/* This is a placeholder value; it may be approximately + * constant across processes, or it may need to be set + * per process. + */ +#define FRINGE_MULT 0.02 + /* * Table used for parsing the extract section of a .tech file * Each line in the extract section is of a type determined by @@ -767,6 +773,7 @@ extTechStyleInit(style) style->exts_sideOverlapCap[r][s] = (EdgeCap *) NULL; style->exts_perimCap[r][s] = (CapValue) 0; style->exts_overlapCap[r][s] = (CapValue) 0; + style->exts_overlapMult[r][s] = (float) 0; TTMaskZero(&style->exts_overlapShieldTypes[r][s]); style->exts_overlapShieldPlanes[r][s] = 0; @@ -815,7 +822,6 @@ extTechStyleInit(style) } style->exts_sideCoupleHalo = 0; - style->exts_fringeShieldHalo = 0; style->exts_stepSize = 100; style->exts_unitsPerLambda = 100.0; style->exts_resistScale = 1000; @@ -1064,6 +1070,7 @@ ExtTechSimpleAreaCap(argc, argv) TileType s, t; TileTypeBitMask types, subtypes, shields; CapValue capVal; + float multVal; int plane1, plane2, plane3, pnum1, pnum2, pnum3; PlaneMask pshield; @@ -1096,7 +1103,11 @@ ExtTechSimpleAreaCap(argc, argv) /* Part 1: Area cap */ for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) if (TTMaskHasType(&types, t)) + { ExtCurStyle->exts_areaCap[t] = capVal; + ExtCurStyle->exts_overlapMult[t][0] = (float) capVal * FRINGE_MULT; + ExtCurStyle->exts_overlapMult[0][t] = (float) capVal * FRINGE_MULT; + } if ((plane2 == -1) && (ExtCurStyle->exts_globSubstratePlane == -1)) return; else if (plane1 == plane2) return; /* shouldn't happen */ @@ -1182,6 +1193,8 @@ ExtTechSimpleAreaCap(argc, argv) continue; /* redundant overlap */ ExtCurStyle->exts_overlapCap[s][t] = capVal; + ExtCurStyle->exts_overlapMult[s][t] = (float)capVal * FRINGE_MULT; + ExtCurStyle->exts_overlapMult[t][s] = (float)capVal * FRINGE_MULT; ExtCurStyle->exts_overlapPlanes |= PlaneNumToMaskBit(plane1); if (plane2 != -1) ExtCurStyle->exts_overlapOtherPlanes[s] |= PlaneNumToMaskBit(plane2); @@ -1561,6 +1574,8 @@ ExtTechSimpleOverlapCap(argv) continue; /* redundant overlap */ ExtCurStyle->exts_overlapCap[s][t] = capVal; + ExtCurStyle->exts_overlapMult[s][t] = (float)capVal * FRINGE_MULT; + ExtCurStyle->exts_overlapMult[t][s] = (float)capVal * FRINGE_MULT; ExtCurStyle->exts_overlapPlanes |= PlaneNumToMaskBit(plane1); ExtCurStyle->exts_overlapOtherPlanes[s] |= PlaneNumToMaskBit(plane2); TTMaskSetType(&ExtCurStyle->exts_overlapTypes[plane1], s); @@ -2109,7 +2124,11 @@ ExtTechLine(sectionName, argc, argv) capVal = aToCap(argv[2]); for (t = TT_TECHDEPBASE; t < DBNumTypes; t++) if (TTMaskHasType(&types1, t)) + { ExtCurStyle->exts_areaCap[t] = capVal; + ExtCurStyle->exts_overlapMult[t][0] = (float) capVal * FRINGE_MULT; + ExtCurStyle->exts_overlapMult[0][t] = (float) capVal * FRINGE_MULT; + } break; case CONTACT: /* Contact size, border, spacing deprecated (now taken from */ @@ -2825,6 +2844,8 @@ ExtTechLine(sectionName, argc, argv) continue; } ExtCurStyle->exts_overlapCap[s][t] = capVal; + ExtCurStyle->exts_overlapMult[s][t] = (float)capVal * FRINGE_MULT; + ExtCurStyle->exts_overlapMult[t][s] = (float)capVal * FRINGE_MULT; ExtCurStyle->exts_overlapPlanes |= PlaneNumToMaskBit(p1); ExtCurStyle->exts_overlapOtherPlanes[s] |= PlaneNumToMaskBit(p2); @@ -3012,11 +3033,7 @@ ExtTechLine(sectionName, argc, argv) ExtCurStyle->exts_sideCoupleHalo = (int)dhalo; break; case FRINGESHIELDHALO: - /* Allow floating-point and increase by factor of 1000 */ - /* to accommodate "units microns". */ - sscanf(argv[1], "%lg", &dhalo); - dhalo *= (double)1000.0; - ExtCurStyle->exts_fringeShieldHalo = (int)dhalo; + /* This is deprecated. . . Ignore */ break; case PERIMC: DBTechNoisyNameMask(argv[2], &types2); @@ -3471,6 +3488,7 @@ zinit: style->exts_perimCap[r][s] *= scalefac; style->exts_overlapCap[r][s] *= sqfac; + style->exts_overlapMult[r][s] *= scalefac; for (ec = style->exts_sideOverlapCap[r][s]; ec != NULL; ec = ec->ec_next) ec->ec_cap *= scalefac; @@ -3512,8 +3530,6 @@ zinit: style->exts_sideCoupleHalo = (int)(((float)style->exts_sideCoupleHalo / dscale) + 0.5); - style->exts_fringeShieldHalo = (int)(((float)style->exts_fringeShieldHalo - / dscale) + 0.5); style->exts_stepSize = (int)(((float)style->exts_stepSize / dscale) + 0.5); } @@ -3530,7 +3546,6 @@ zinit: /* needed, so normalize it back to lambda units. */ style->exts_sideCoupleHalo /= 1000; - style->exts_fringeShieldHalo /= 1000; } /* @@ -3559,7 +3574,6 @@ ExtTechScale(scalen, scaled) style->exts_unitsPerLambda = style->exts_unitsPerLambda * (float)scalen / (float)scaled; DBScaleValue(&style->exts_sideCoupleHalo, scaled, scalen); - DBScaleValue(&style->exts_fringeShieldHalo, scaled, scalen); DBScaleValue(&style->exts_stepSize, scaled, scalen); for (i = 0; i < DBNumTypes; i++) @@ -3591,6 +3605,8 @@ ExtTechScale(scalen, scaled) style->exts_perimCap[i][j] /= scaled; style->exts_overlapCap[i][j] *= sqn; style->exts_overlapCap[i][j] /= sqd; /* Typo fixed in 7.2.57 */ + style->exts_overlapMult[i][j] *= scalen; + style->exts_overlapMult[i][j] /= scaled; // Do not scale sidewall cap, for while the value is // per distance, the distance is referred to a separation diff --git a/extract/extractInt.h b/extract/extractInt.h index 32f0839b..b5f54f1b 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -726,6 +726,15 @@ typedef struct extstyle */ CapValue exts_overlapCap[NT][NT]; + /* + * exts_overlapMult is needed for modeling fringe shielding and + * partial fringing, whose models have multiplier coefficients + * that are proportional to area capacitance referred to some + * constant length (so that it scales with the internal grid, + * not with the internal grid squared). + */ + float exts_overlapMult[NT][NT]; + /* Specifies an ordering of the planes, so we can determine which * tile is above another one. This is used only when determining * if we should subtract capacitance to substrate for overlap and @@ -780,19 +789,13 @@ typedef struct extstyle * This value determines how much extra gets yanked when * computing hierarchical adjustments, so should be kept * small to insure reasonable performance. + * + * To be done: Set this as a per-plane value with a + * corresponding method in the tech file to declare the value + * for each plane separately. */ int exts_sideCoupleHalo; - /* - * Search out a distance exts_fringeShieldHalo from each edge - * for types on the same plane that partially shield fringe - * capacitance. The shielding is modeled as an ellipse equation - * and the shield halo should be approximately 10x the distance - * where half the fringe capacitance is shielded. If not specified, - * then it is set to be equal to exts_sideCoupleHalo. - */ - int exts_fringeShieldHalo; - /* * Sidewall-overlap coupling capacitance. * This is between an edge on one plane and a type on another plane