From c001de3d9dc3425339f1a229822162d23d045c88 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Sat, 28 May 2022 10:33:21 -0400 Subject: [PATCH] (1) Corrected an error in generating GDS_FILE properties when reading GDS files, caused by an unneeded change to pass both the "original" filename and the actual filename when handling compressed files---The original filename is unneeded. (2) Implemented several new methods for parasitic extraction. The first is an option offset value to apply to sidewall calculations. This handles issues where actual wire separation is different from drawn wire separation, which can be significant for the 1/d calculation of sidewall coupling. The second method is to use the recently-added fringe halo to compute the coupling of the fringe capacitance to nearby wires. Prior to this change, all fringe capacitance was applied to surfaces directly under a wire edge as if the fringe capacitance did not extend outward from the edge. Now the capacitance is properly pro-rated for the position of any overlapped shape inside the fringing field. Finally, the third method added is a new search algorithm for finding the nearest shapes along the length of a boundary. This is used for sidewall coupling and fringe shielding, where the nearest shape dominates the coupling, and any shapes behind are shielded and may (to first order) be ignored. Previously, the entire halo was searched without regard to shapes shielding other shapes behind, and a recent correction added an ad-hoc search for blocking shapes that was inefficient and not always correct. The new method is both efficient and accurate. --- VERSION | 2 +- calma/CalmaRdcl.c | 7 +- calma/CalmaRead.c | 7 +- commands/CmdCD.c | 2 +- extract/ExtCouple.c | 740 +++++++++++++++++++++++++++++++++---------- extract/ExtTech.c | 64 +++- extract/extract.h | 9 +- extract/extractInt.h | 1 + 8 files changed, 631 insertions(+), 201 deletions(-) diff --git a/VERSION b/VERSION index 8957483b..619b7fd5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.305 +8.3.306 diff --git a/calma/CalmaRdcl.c b/calma/CalmaRdcl.c index 3ca1d61c..0d64c40f 100644 --- a/calma/CalmaRdcl.c +++ b/calma/CalmaRdcl.c @@ -294,11 +294,8 @@ calmaExact() */ bool -calmaParseStructure(filename, origname) +calmaParseStructure(filename) char *filename; /* Name of the GDS file read */ - char *origname; /* Original name of the GDS file - * (used with compressed files) - */ { static int structs[] = { CALMA_STRCLASS, CALMA_STRTYPE, -1 }; int nbytes, rtype, nsrefs, osrefs, npaths; @@ -449,7 +446,7 @@ calmaParseStructure(filename, origname) /* Substitute variable for PDK path or ~ for home directory */ /* the same way that cell references are handled in .mag files. */ - DBPathSubstitute(origname, cstring, cifReadCellDef); + DBPathSubstitute(filename, cstring, cifReadCellDef); fncopy = StrDup(NULL, cstring); sprintf(fpcopy, "%"DLONG_PREFIX"d", (dlong) filepos); DBPropPut(cifReadCellDef, "GDS_START", (ClientData)fpcopy); diff --git a/calma/CalmaRead.c b/calma/CalmaRead.c index ea8597e0..caea2def 100644 --- a/calma/CalmaRead.c +++ b/calma/CalmaRead.c @@ -152,12 +152,9 @@ int calmaElementIgnore[] = { CALMA_ELFLAGS, CALMA_PLEX, -1 }; */ void -CalmaReadFile(file, filename, origname) +CalmaReadFile(file, filename) FILETYPE file; /* File from which to read Calma */ char *filename; /* The real name of the file read */ - char *origname; /* Original name of file read (used for - * compressed files) - */ { int k, version; char *libname = NULL; @@ -237,7 +234,7 @@ CalmaReadFile(file, filename, origname) if (!calmaParseUnits()) goto done; /* Main body of GDS-II input */ - while (calmaParseStructure(filename, origname)) + while (calmaParseStructure(filename)) if (SigInterruptPending) goto done; (void) calmaSkipExact(CALMA_ENDLIB); diff --git a/commands/CmdCD.c b/commands/CmdCD.c index 920d9095..edd6a019 100644 --- a/commands/CmdCD.c +++ b/commands/CmdCD.c @@ -927,7 +927,7 @@ CmdCalma(w, cmd) cmd->tx_argv[2], cmd->tx_argv[2], cmd->tx_argv[2]); return; } - CalmaReadFile(f, namep, cmd->tx_argv[2]); + CalmaReadFile(f, namep); (void) FCLOSE(f); return; } diff --git a/extract/ExtCouple.c b/extract/ExtCouple.c index 40c60840..04038f71 100644 --- a/extract/ExtCouple.c +++ b/extract/ExtCouple.c @@ -52,9 +52,10 @@ 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(); void extSideCommon(); -int extShieldLeft(), extShieldRight(), extShieldBottom(), extShieldTop(); /* Structure to pass on to the coupling and sidewall capacitance */ /* routines to include the current cell definition and the current */ @@ -81,17 +82,10 @@ typedef struct _esws { Boundary *bp; int plane_of_boundary; int plane_checked; + int fringe_halo; float shieldfrac; } extSidewallStruct; -/* Structure to pass the value for fringe shielding */ - -typedef struct _efss { - Boundary *bp; - float shieldfrac; // Fraction of fringe capacitance shielded -} extFringeShieldStruct; - - /* --------------------- Debugging stuff ---------------------- */ #define CAP_DEBUG FALSE @@ -540,6 +534,8 @@ extAddOverlap(tbelow, ecpls) return (0); } +/* Simple overlap. The area of overlap is subtracted from ov->o_area */ + int extSubtractOverlap(tile, ov) Tile *tile; @@ -557,6 +553,11 @@ extSubtractOverlap(tile, ov) return (0); } +/* Recursive shielding overlap check. If the tile shields, */ +/* then the area of overlap is subtracted from ov->o_area. If */ +/* not, then this routine is called recursively on the next */ +/* shielding plane. */ + int extSubtractOverlap2(tile, ov) Tile *tile; @@ -679,11 +680,11 @@ extAddCouple(bp, ecs) TileType tin = TiGetType(bp->b_inside), tout = TiGetType(bp->b_outside); int pNum; PlaneMask pMask; - int (*proc)(); Boundary bpCopy; Rect r, ovr; CellDef *def = ecs->def; extSidewallStruct esws; + int distFringe; /* Revert any edge contacts to their residues */ if (DBIsContact(tin)) @@ -713,78 +714,98 @@ extAddCouple(bp, ecs) } r = ovr = bp->b_segment; + /* If considering fringe capacitance to be distributed over */ + /* a halo surrounding the edge of a shape, then set the */ + /* fringe distance to the halo value. Otherwise, the */ + /* fringe cap is (unrealistically) assumed to couple only */ + /* to shapes that are directly below the edge. */ + + distFringe = (ExtOptions & EXT_DOFRINGEHALO) ? + ExtCurStyle->exts_fringeShieldHalo : 1; + switch (bp->b_direction) { case BD_LEFT: /* Along left */ - r.r_xbot -= ExtCurStyle->exts_sideCoupleHalo ; - ovr.r_xbot -= 1; - proc = extSideLeft; + r.r_xbot -= ExtCurStyle->exts_sideCoupleHalo; + ovr.r_xbot -= distFringe; + if (extCoupleList) + extWalkLeft(&r, + &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], + extSideLeft, bp, (ClientData)NULL); break; case BD_RIGHT: /* Along right */ - r.r_xtop += ExtCurStyle->exts_sideCoupleHalo ; - ovr.r_xtop += 1; - proc = extSideRight; + r.r_xtop += ExtCurStyle->exts_sideCoupleHalo; + ovr.r_xtop += distFringe; + if (extCoupleList) + extWalkRight(&r, + &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], + extSideRight, bp, (ClientData)NULL); break; case BD_TOP: /* Along top */ - r.r_ytop += ExtCurStyle->exts_sideCoupleHalo ; - ovr.r_ytop += 1; - proc = extSideTop; + r.r_ytop += ExtCurStyle->exts_sideCoupleHalo; + ovr.r_ytop += distFringe; + if (extCoupleList) + extWalkTop(&r, + &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], + extSideTop, bp, (ClientData)NULL); break; case BD_BOTTOM: /* Along bottom */ - r.r_ybot -= ExtCurStyle->exts_sideCoupleHalo ; - ovr.r_ybot -= 1; - proc = extSideBottom; + r.r_ybot -= ExtCurStyle->exts_sideCoupleHalo; + ovr.r_ybot -= distFringe; + if (extCoupleList) + extWalkBottom(&r, + &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], + extSideBottom, bp, (ClientData)NULL); break; } - if (extCoupleList) - { - (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[ecs->plane], - &r, &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], - proc, (ClientData) bp); - } + /* Additional calculations for the significant shielding effect of */ + /* nearby shapes on fringe capacitance. */ - if (extCoupleList && extOverlapList && (ExtCurStyle->exts_fringeShieldHalo > 0)) + if (extCoupleList && extOverlapList && (ExtCurStyle->exts_fringeShieldHalo > 0) + && (ExtOptions & EXT_DOCOUPLING)) { - extFringeShieldStruct efss; + float shieldFrac; NodeRegion *rbp; + shieldFrac = 0.0; + /* Resize r for fringe shield calculation */ + /* and find fringe shielding amount */ switch (bp->b_direction) { case BD_LEFT: /* Along left */ r.r_xbot += ExtCurStyle->exts_sideCoupleHalo ; r.r_xbot -= ExtCurStyle->exts_fringeShieldHalo ; - proc = extShieldLeft; + 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 ; - proc = extShieldRight; + 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 ; - proc = extShieldTop; + 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 ; - proc = extShieldBottom; + extWalkBottom(&r, + &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], + extShieldBottom, bp, (ClientData) &shieldFrac); break; } - /* Find fringe shielding amount */ - - efss.bp = bp; - efss.shieldfrac = 0.0; - - (void) DBSrPaintArea((Tile *) NULL, def->cd_planes[ecs->plane], - &r, &ExtCurStyle->exts_sideCoupleOtherEdges[tin][tout], - proc, (ClientData) &efss); - - esws.shieldfrac = efss.shieldfrac; + 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. @@ -816,6 +837,7 @@ extAddCouple(bp, ecs) esws.bp = bp; esws.plane_of_boundary = ecs->plane; + esws.fringe_halo = distFringe; for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) if (PlaneMaskHasPlane(pMask, pNum)) @@ -862,10 +884,19 @@ extSideOverlap(tp, esws) struct overlap ov; HashEntry *he; EdgeCap *e; - int length, areaAccountedFor; + int length, areaAccountedFor, areaTotal; + double cfrac, afrac; CapValue cap; CoupleKey ck; + /* Nothing to do for space tiles, so just return. */ + /* (TO DO: Make sure TT_SPACE is removed from all exts_sideOverlapOtherTypes */ + tb = TiGetType(tp); + if (tb == TT_SPACE) return (0); + + /* If shapes belong to the same node then there is no coupling. */ + if (rtp == rbp) return (0); + if (bp->b_segment.r_xtop == bp->b_segment.r_xbot) { length = MIN(bp->b_segment.r_ytop, TOP(tp)) @@ -879,16 +910,12 @@ extSideOverlap(tp, esws) TITORECT(tp, &ov.o_clip); GEOCLIP(&ov.o_clip, &extSideOverlapSearchArea); - ov.o_area = length; + areaTotal = length * esws->fringe_halo; areaAccountedFor = 0; - ASSERT(length == GEO_WIDTH(&ov.o_clip) * GEO_HEIGHT(&ov.o_clip), + + ASSERT(areaTotal == GEO_WIDTH(&ov.o_clip) * GEO_HEIGHT(&ov.o_clip), "extSideOverlap"); ta = TiGetType(bp->b_inside); - tb = TiGetType(tp); - - /* Avoid doing the code below if we're just going to return without */ - /* changing anything. */ - if ((tb == TT_SPACE) && (rtp == rbp)) return (0); /* Revert any contacts to their residues */ if (DBIsContact(ta)) @@ -896,6 +923,49 @@ extSideOverlap(tp, esws) if (DBIsContact(tb)) tb = DBPlaneToResidue(tb, esws->plane_checked); + /* 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) + { + 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); + 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; + 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); + 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; + 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); + + /* "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; + } + else + cfrac = 1.0; /* For simplified perimeter cap calculation */ + /* Apply each rule, incorporating shielding into the edge length. */ cap = (CapValue) 0; for (e = extOverlapList; e; e = e->ec_next) @@ -910,7 +980,7 @@ extSideOverlap(tp, esws) * each other part of the way? */ int pNum; - ov.o_area = length; + ov.o_area = areaTotal; ov.o_pmask = ExtCurStyle->exts_sideOverlapShieldPlanes[ta][tb]; if (ov.o_pmask) { @@ -918,7 +988,7 @@ extSideOverlap(tp, esws) for (pNum = PL_TECHDEPBASE; pNum < DBNumPlanes; pNum++) { /* Each call to DBSrPaintArea has an opportunity to - * subtract from the area (really length 'cause width=1. + * subtract from the area (really length 'cause width=1). */ if (!PlaneMaskHasPlane(ov.o_pmask, pNum)) continue; ov.o_pmask &= ~(PlaneNumToMaskBit(pNum)); @@ -939,7 +1009,17 @@ extSideOverlap(tp, esws) } } if (rtp != rbp) - cap += e->ec_cap * ov.o_area * (1.0 - esws->shieldfrac); + { + if (esws->fringe_halo == 1) + { + cap += e->ec_cap * ov.o_area * (1.0 - esws->shieldfrac); + } + else /* (perimeter cap distributed over halo) */ + { + afrac = (double)ov.o_area / (double)areaTotal; + cap += e->ec_cap * length * afrac * cfrac * (1.0 - esws->shieldfrac); + } + } areaAccountedFor += ov.o_area; } } @@ -966,9 +1046,15 @@ extSideOverlap(tp, esws) if (DBIsContact(outtype)) outtype = DBPlaneToResidue(outtype, esws->plane_of_boundary); - subcap = (ExtCurStyle->exts_perimCap[ta][outtype] * + afrac = (double)areaAccountedFor / (double)areaTotal; + if (esws->fringe_halo == 1) + 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)); rbp->nreg_cap -= subcap; /* Ignore residual error at ~zero zeptoFarads. Probably */ /* there should be better handling of round-off here. */ @@ -1003,14 +1089,398 @@ extSideOverlap(tp, esws) return (0); } -/* NOTE --- - * A non-rigorous check is made in the four routines below to see if there - * is intervening material between the boundary and tfar. To be rigorous - * without invoking a secondary area search, need to supply a routine that - * specifically walks out in one direction to the nearest matching tile - * and does not look beyond. +/* + * ---------------------------------------------------------------------------- + * + * extWalkTop --- + * + * Search in the area 'area' above the boundary 'bp' for coupling tiles of + * types in 'mask', starting from the right corner above the boundary and + * sweeping left. If a coupling tile is found, process it, clipping the + * boundary to the width of the tile if needed. Then recursively call + * extWalkTop on the areas to the left and right sides of the tile with + * boundaries reduced to the width of those areas. This way the edge + * boundary is subdivided into lengths occupied by the nearest neighbor. + * + * Return value: + * Return 1 if func() returned 1, otherwise return 0. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- */ +int +extWalkTop(area, mask, func, bp, clientData) + Rect *area; + TileTypeBitMask *mask; + int (*func)(); + Boundary *bp; + ClientData clientData; +{ + Tile *tile, *tp; + TileType ttype; + Boundary bloc; + Rect aloc; + + tile = RT(bp->b_outside); /* Tile above tile on top of the boundary */ + while (BOTTOM(tile) < area->r_ytop) + { + while (LEFT(tile) >= area->r_xtop) tile = BL(tile); /* Walk back to area */ + tp = tile; + while (RIGHT(tp) > area->r_xbot) + { + if (IsSplit(tp)) + ttype = (SplitSide(tp)) ? SplitRightType(tp) : SplitLeftType(tp); + else + ttype = TiGetTypeExact(tp); + + if (TTMaskHasType(mask, ttype)) + { + bool lookLeft, lookRight; + + bloc = *bp; /* Copy boundary to bc, then adjust boundary */ + + lookLeft = (LEFT(tp) > bp->b_segment.r_xbot) ? TRUE : FALSE; + lookRight = (RIGHT(tp) < bp->b_segment.r_xtop) ? TRUE : FALSE; + + if (lookLeft) + bloc.b_segment.r_xbot = LEFT(tp); + if (lookRight) + bloc.b_segment.r_xtop = RIGHT(tp); + + if (func(tp, &bloc, clientData) != 0) return 1; + + /* Recurse on tile left side */ + if (lookLeft) + { + aloc = *area; + aloc.r_xtop = bloc.b_segment.r_xbot; + bloc.b_segment.r_xbot = bp->b_segment.r_xbot; + bloc.b_segment.r_xtop = aloc.r_xtop; + if (extWalkTop(&aloc, mask, func, &bloc, clientData) != 0) + return 1; + } + + /* Recurse on tile right side */ + if (lookRight) + { + aloc = *area; + aloc.r_xbot = bloc.b_segment.r_xtop; + bloc.b_segment.r_xtop = bp->b_segment.r_xtop; + bloc.b_segment.r_xbot = aloc.r_xbot; + if (extWalkTop(&aloc, mask, func, &bloc, clientData) != 0) + return 1; + } + + /* Once a coupling tile is found, it blocks any */ + /* 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; +} + +/* + * ---------------------------------------------------------------------------- + * + * extWalkBottom --- + * + * Search in the area 'area' below the boundary 'bp' for coupling tiles of + * types in 'mask', starting from the left corner below the boundary and + * sweeping right. If a coupling tile is found, process it, clipping the + * boundary to the width of the tile if needed. Then recursively call + * extWalkBottom on the areas to the left and right sides of the tile with + * boundaries reduced to the width of those areas. This way the edge + * boundary is subdivided into lengths occupied by the nearest neighbor. + * + * Return value: + * Return 1 if func() returned 1, otherwise return 0. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +extWalkBottom(area, mask, func, bp, clientData) + Rect *area; + TileTypeBitMask *mask; + int (*func)(); + Boundary *bp; + ClientData clientData; +{ + Tile *tile, *tp; + TileType ttype; + Boundary bloc; + Rect aloc; + + tile = LB(bp->b_outside); /* Tile below tile on bottom of the boundary */ + while (TOP(tile) > area->r_ybot) + { + while (RIGHT(tile) <= area->r_xbot) tile = TR(tile); /* Walk back to area */ + tp = tile; + while (LEFT(tp) < area->r_xtop) + { + if (IsSplit(tp)) + ttype = (SplitSide(tp)) ? SplitRightType(tp) : SplitLeftType(tp); + else + ttype = TiGetTypeExact(tp); + + if (TTMaskHasType(mask, ttype)) + { + bool lookLeft, lookRight; + + bloc = *bp; /* Copy boundary to bc, then adjust boundary */ + + lookLeft = (LEFT(tp) > bp->b_segment.r_xbot) ? TRUE : FALSE; + lookRight = (RIGHT(tp) < bp->b_segment.r_xtop) ? TRUE : FALSE; + + if (lookLeft) + bloc.b_segment.r_xbot = LEFT(tp); + if (lookRight) + bloc.b_segment.r_xtop = RIGHT(tp); + + if (func(tp, &bloc, clientData) != 0) return 1; + + /* Recurse on tile left side */ + if (lookLeft) + { + aloc = *area; + aloc.r_xtop = bloc.b_segment.r_xbot; + bloc.b_segment.r_xbot = bp->b_segment.r_xbot; + bloc.b_segment.r_xtop = aloc.r_xtop; + if (extWalkBottom(&aloc, mask, func, &bloc, clientData) != 0) + return 1; + } + + /* Recurse on tile right side */ + if (lookRight) + { + aloc = *area; + aloc.r_xbot = bloc.b_segment.r_xtop; + bloc.b_segment.r_xtop = bp->b_segment.r_xtop; + bloc.b_segment.r_xbot = aloc.r_xbot; + if (extWalkBottom(&aloc, mask, func, &bloc, clientData) != 0) + return 1; + } + + /* Once a coupling tile is found, it blocks any */ + /* 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; +} + +/* + * ---------------------------------------------------------------------------- + * + * extWalkRight --- + * + * Search in the area 'area' to the right of the boundary 'bp' for coupling + * tiles of types in 'mask', starting from the top corner to the right of the + * boundary and sweeping downward. If a coupling tile is found, process it, + * clipping the boundary to the height of the tile if needed. Then recursively + * call extWalkRight on the areas above and below the tile with boundaries + * reduced to the height of those areas. This way the edge boundary is + * subdivided into lengths occupied by the nearest neighbor. + * + * Return value: + * Return 1 if func() returned 1, otherwise return 0. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +extWalkRight(area, mask, func, bp, clientData) + Rect *area; + TileTypeBitMask *mask; + int (*func)(); + Boundary *bp; + ClientData clientData; +{ + Tile *tile, *tp; + TileType ttype; + Boundary bloc; + Rect aloc; + + tile = TR(bp->b_outside); /* Tile to the right of tile to right of the boundary */ + while (LEFT(tile) < area->r_xtop) + { + while (BOTTOM(tile) >= area->r_ytop) tile = LB(tile); /* Walk back to area */ + tp = tile; + while (TOP(tp) > area->r_ybot) + { + if (IsSplit(tp)) + ttype = (SplitSide(tp)) ? SplitRightType(tp) : SplitLeftType(tp); + else + ttype = TiGetTypeExact(tp); + + if (TTMaskHasType(mask, ttype)) + { + bool lookDown, lookUp; + + bloc = *bp; /* Copy boundary to bc, then adjust boundary */ + + lookDown = (BOTTOM(tp) > bp->b_segment.r_ybot) ? TRUE : FALSE; + lookUp = (TOP(tp) < bp->b_segment.r_ytop) ? TRUE : FALSE; + + if (lookDown) + bloc.b_segment.r_ybot = BOTTOM(tp); + if (lookUp) + bloc.b_segment.r_ytop = TOP(tp); + + if (func(tp, &bloc, clientData) != 0) return 1; + + /* Recurse on tile bottom side */ + if (lookDown) + { + aloc = *area; + aloc.r_ytop = bloc.b_segment.r_ybot; + bloc.b_segment.r_ybot = bp->b_segment.r_ybot; + bloc.b_segment.r_ytop = aloc.r_ytop; + if (extWalkRight(&aloc, mask, func, &bloc, clientData) != 0) + return 1; + } + + /* Recurse on tile top side */ + if (lookUp) + { + aloc = *area; + aloc.r_ybot = bloc.b_segment.r_ytop; + bloc.b_segment.r_ytop = bp->b_segment.r_ytop; + bloc.b_segment.r_ybot = aloc.r_ybot; + if (extWalkRight(&aloc, mask, func, &bloc, clientData) != 0) + return 1; + } + + /* Once a coupling tile is found, it blocks any */ + /* 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; +} + +/* + * ---------------------------------------------------------------------------- + * + * extWalkLeft --- + * + * Search in the area 'area' to the left of the boundary 'bp' for coupling + * tiles of types in 'mask', starting from the bottom corner to the left of the + * boundary and sweeping upward. If a coupling tile is found, process it, + * clipping the boundary to the height of the tile if needed. Then recursively + * call extWalkLeft on the areas above and below the tile with boundaries + * reduced to the height of those areas. This way the edge boundary is + * subdivided into lengths occupied by the nearest neighbor. + * + * Return value: + * Return 1 if func() returned 1, otherwise return 0. + * + * Side effects: + * None. + * + * ---------------------------------------------------------------------------- + */ + +int +extWalkLeft(area, mask, func, bp, clientData) + Rect *area; + TileTypeBitMask *mask; + int (*func)(); + Boundary *bp; + ClientData clientData; +{ + Tile *tile, *tp; + TileType ttype; + Boundary bloc; + Rect aloc; + + tile = BL(bp->b_outside); /* Tile to the left of tile to left of the boundary */ + while (RIGHT(tile) > area->r_xbot) + { + while (TOP(tile) <= area->r_ybot) tile = RT(tile); /* Walk back to area */ + tp = tile; + while (BOTTOM(tp) < area->r_ytop) + { + if (IsSplit(tp)) + ttype = (SplitSide(tp)) ? SplitRightType(tp) : SplitLeftType(tp); + else + ttype = TiGetTypeExact(tp); + + if (TTMaskHasType(mask, ttype)) + { + bool lookDown, lookUp; + + bloc = *bp; /* Copy boundary to bc, then adjust boundary */ + + lookDown = (BOTTOM(tp) > bp->b_segment.r_ybot) ? TRUE : FALSE; + lookUp = (TOP(tp) < bp->b_segment.r_ytop) ? TRUE : FALSE; + + if (lookDown) + bloc.b_segment.r_ybot = BOTTOM(tp); + if (lookUp) + bloc.b_segment.r_ytop = TOP(tp); + + if (func(tp, &bloc, clientData) != 0) return 1; + + /* Recurse on tile bottom side */ + if (lookDown) + { + aloc = *area; + aloc.r_ytop = bloc.b_segment.r_ybot; + bloc.b_segment.r_ybot = bp->b_segment.r_ybot; + bloc.b_segment.r_ytop = aloc.r_ytop; + if (extWalkRight(&aloc, mask, func, &bloc, clientData) != 0) + return 1; + } + + /* Recurse on tile top side */ + if (lookUp) + { + aloc = *area; + aloc.r_ybot = bloc.b_segment.r_ytop; + bloc.b_segment.r_ytop = bp->b_segment.r_ytop; + bloc.b_segment.r_ybot = aloc.r_ybot; + if (extWalkRight(&aloc, mask, func, &bloc, clientData) != 0) + return 1; + } + + /* Once a coupling tile is found, it blocks any */ + /* 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; +} + /* * ---------------------------------------------------------------------------- * @@ -1039,9 +1509,10 @@ extSideOverlap(tp, esws) */ int -extSideLeft(tpfar, bp) +extSideLeft(tpfar, bp, clientData) Tile *tpfar; Boundary *bp; + ClientData clientData; /* Unused */ { NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar); @@ -1057,27 +1528,7 @@ extSideLeft(tpfar, bp) { 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 shielding shapes exist in between. */ - - 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) - extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); - } + extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); } } @@ -1107,9 +1558,10 @@ extSideLeft(tpfar, bp) */ int -extSideRight(tpfar, bp) +extSideRight(tpfar, bp, clientData) Tile *tpfar; Boundary *bp; + ClientData clientData; /* Unused */ { NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar); @@ -1125,27 +1577,7 @@ extSideRight(tpfar, bp) { 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 shielding shapes exist in between. */ - - 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) - extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); - } + extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); } } @@ -1175,9 +1607,10 @@ extSideRight(tpfar, bp) */ int -extSideTop(tpfar, bp) +extSideTop(tpfar, bp, clientData) Tile *tpfar; Boundary *bp; + ClientData clientData; /* Unused */ { NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar); @@ -1193,27 +1626,7 @@ extSideTop(tpfar, bp) { 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 shielding shapes exist in between. */ - - 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) - extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); - } + extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); } } @@ -1243,9 +1656,10 @@ extSideTop(tpfar, bp) */ int -extSideBottom(tpfar, bp) +extSideBottom(tpfar, bp, clientData) Tile *tpfar; Boundary *bp; + ClientData clientData; /* Unused */ { NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); NodeRegion *rfar = (NodeRegion *) extGetRegion(tpfar); @@ -1261,27 +1675,7 @@ extSideBottom(tpfar, bp) { 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 shielding shapes exist in between. */ - - 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) - extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); - } + extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep); } } @@ -1332,9 +1726,11 @@ extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep) cap = extGetCapValue(he); for (e = extCoupleList; e; e = e->ec_next) if (TTMaskHasType(&e->ec_near, near) && TTMaskHasType(&e->ec_far, far)) { - cap += (e->ec_cap * overlap) / sep; + cap += (e->ec_cap * overlap) / (sep + e->ec_offset); if (CAP_DEBUG) - extAdjustCouple(he, (e->ec_cap * overlap) / sep, "sidewall"); + extAdjustCouple(he, + (e->ec_cap * overlap) / (sep + e->ec_offset), + "sidewall"); } extSetCapValue(he, cap); } @@ -1355,17 +1751,17 @@ extSideCommon(rinside, rfar, tpnear, tpfar, overlap, sep) * Returns 0 always. * * Side effects: - * Updates efss->shieldfrac + * Updates data pointed to by shieldFrac * * ---------------------------------------------------------------------------- */ int -extShieldLeft(tpfar, efss) +extShieldLeft(tpfar, bp, shieldFrac) Tile *tpfar; - extFringeShieldStruct *efss; + Boundary *bp; + float *shieldFrac; { - Boundary *bp = efss->bp; NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); Tile *tpnear; float fshield; /* fraction shielded for this segment */ @@ -1405,7 +1801,7 @@ extShieldLeft(tpfar, efss) (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); - efss->shieldfrac = fshield * frac + efss->shieldfrac * (1.0 - frac); + *shieldFrac = fshield * frac + (*shieldFrac) * (1.0 - frac); } } } @@ -1428,17 +1824,17 @@ extShieldLeft(tpfar, efss) * Returns 0 always. * * Side effects: - * Updates efss->shieldfrac + * Updates data pointed to by shieldFrac * * ---------------------------------------------------------------------------- */ int -extShieldRight(tpfar, efss) +extShieldRight(tpfar, bp, shieldFrac) Tile *tpfar; - extFringeShieldStruct *efss; + Boundary *bp; + float *shieldFrac; { - Boundary *bp = efss->bp; NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); Tile *tpnear; float fshield; /* fraction shielded for this segment */ @@ -1478,7 +1874,7 @@ extShieldRight(tpfar, efss) (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); - efss->shieldfrac = fshield * frac + efss->shieldfrac * (1.0 - frac); + *shieldFrac = fshield * frac + (*shieldFrac) * (1.0 - frac); } } } @@ -1501,17 +1897,17 @@ extShieldRight(tpfar, efss) * Returns 0 always. * * Side effects: - * Updates efss->shieldfrac + * Updates data pointed to by shieldFrac * * ---------------------------------------------------------------------------- */ int -extShieldTop(tpfar, efss) +extShieldTop(tpfar, bp, shieldFrac) Tile *tpfar; - extFringeShieldStruct *efss; + Boundary *bp; + float *shieldFrac; { - Boundary *bp = efss->bp; NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); Tile *tpnear; float fshield; /* fraction shielded for this segment */ @@ -1551,7 +1947,7 @@ extShieldTop(tpfar, efss) (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); - efss->shieldfrac = fshield * frac + efss->shieldfrac * (1.0 - frac); + *shieldFrac = fshield * frac + (*shieldFrac) * (1.0 - frac); } } } @@ -1574,17 +1970,17 @@ extShieldTop(tpfar, efss) * Returns 0 always. * * Side effects: - * Updates efss->shieldfrac + * Updates data pointed to by shieldFrac * * ---------------------------------------------------------------------------- */ int -extShieldBottom(tpfar, efss) +extShieldBottom(tpfar, bp, shieldFrac) Tile *tpfar; - extFringeShieldStruct *efss; + Boundary *bp; + float *shieldFrac; { - Boundary *bp = efss->bp; NodeRegion *rinside = (NodeRegion *) extGetRegion(bp->b_inside); Tile *tpnear; float fshield; /* fraction shielded for this segment */ @@ -1624,7 +2020,7 @@ extShieldBottom(tpfar, efss) (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); - efss->shieldfrac = fshield * frac + efss->shieldfrac * (1.0 - frac); + *shieldFrac = fshield * frac + (*shieldFrac) * (1.0 - frac); } } } diff --git a/extract/ExtTech.c b/extract/ExtTech.c index 37bb26ce..2cb4d85f 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -111,8 +111,8 @@ static keydesc keyTable[] = { "defaultsideoverlap", DEFAULTSIDEOVERLAP, 6, 6, "types plane othertypes otherplane capacitance", - "defaultsidewall", DEFAULTSIDEWALL, 4, 4, -"types plane capacitance", + "defaultsidewall", DEFAULTSIDEWALL, 4, 5, +"types plane capacitance [offset]", "device", DEVICE, 4, 10, "device dev-type types options...", @@ -164,8 +164,8 @@ static keydesc keyTable[] = { "sideoverlap", SIDEOVERLAP, 5, 6, "intypes outtypes ovtypes capacitance [shieldtypes]", - "sidewall", SIDEWALL, 6, 6, -"intypes outtypes neartypes fartypes capacitance", + "sidewall", SIDEWALL, 6, 7, +"intypes outtypes neartypes fartypes capacitance [offset]", "step", STEP, 2, 2, "size", @@ -1374,6 +1374,7 @@ ExtTechSimplePerimCap(argc, argv) PlaneNumToMaskBit(plane2); cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap))); cnew->ec_cap = capVal; + cnew->ec_offset = 0; /* No offsets on perimeter caps */ cnew->ec_far = shields; /* Types that shield */ cnew->ec_near = subtypes; /* Types we create cap with */ if (plane2 != -1) @@ -1408,7 +1409,8 @@ ExtTechSimplePerimCap(argc, argv) */ void -ExtTechSimpleSidewallCap(argv) +ExtTechSimpleSidewallCap(argc, argv) + int argc; char *argv[]; { /* Like ExtTechLine, but with near = types2 and far = types1 */ @@ -1417,6 +1419,8 @@ ExtTechSimpleSidewallCap(argv) TileTypeBitMask types1, types2; CapValue capVal; EdgeCap *cnew; + int offset; + double doffset; int plane; DBTechNoisyNameMask(argv[1], &types1); @@ -1424,6 +1428,17 @@ ExtTechSimpleSidewallCap(argv) plane = DBTechNoisyNamePlane(argv[2]); capVal = aToCap(argv[3]); + if (argc == 5) + { + /* Save a value of 1000 * the offset, which will be converted + * appropriately to magic units like exts->sideCoupleHalo. + */ + sscanf(argv[4], "%lg", &doffset); + offset = (int)(0.5 + doffset * 1000.0); + } + else + offset = 0; + // Like perimeter cap, treat only space and space-like types // TTMaskCom2(&types2, &types1); TTMaskZero(&types2); @@ -1449,6 +1464,7 @@ ExtTechSimpleSidewallCap(argv) TTMaskSetMask(&ExtCurStyle->exts_sideCoupleOtherEdges[s][t], &types1); cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap))); cnew->ec_cap = capVal; + cnew->ec_offset = offset; cnew->ec_near = types2; cnew->ec_far = types1; cnew->ec_next = ExtCurStyle->exts_sideCoupleCap[s][t]; @@ -1679,6 +1695,7 @@ ExtTechSimpleSideOverlapCap(argv) PlaneNumToMaskBit(plane2); cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap))); cnew->ec_cap = capVal; + cnew->ec_offset = 0; /* No offsets on overlap caps */ cnew->ec_far = shields; /* Types that shield */ cnew->ec_near = ov; /* Types we create cap with */ cnew->ec_pmask = PlaneNumToMaskBit(plane2); @@ -1846,7 +1863,9 @@ ExtTechLine(sectionName, argc, argv) ParamList *subcktParams, *newParam; ExtDevice *devptr; int refcnt; + int offset; double dhalo; + double doffset; bool bad; if (argc < 1) @@ -2215,7 +2234,7 @@ ExtTechLine(sectionName, argc, argv) ExtTechSimpleSideOverlapCap(argv); break; case DEFAULTSIDEWALL: - ExtTechSimpleSidewallCap(argv); + ExtTechSimpleSidewallCap(argc, argv); break; case DEVICE: @@ -2896,6 +2915,7 @@ ExtTechLine(sectionName, argc, argv) ExtCurStyle->exts_sideOverlapOtherPlanes[s][t] |= pov; cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap))); cnew->ec_cap = capVal; + cnew->ec_offset = 0; /* No offsets on overlap caps */ cnew->ec_far = shield; /* Really types that shield */ cnew->ec_near = ov; /* Really types we create cap with */ cnew->ec_pmask = pov; @@ -2945,6 +2965,13 @@ ExtTechLine(sectionName, argc, argv) if (TTMaskHasType(&types1, TT_SPACE)) TechError("Can't have space on inside of edge [ignored]\n"); capVal = aToCap(argv[5]); + if (argc == 7) + { + sscanf(argv[6], "%lg", &doffset); + offset = (int)(0.5 + doffset * 1000.0); + } + else + offset = 0; for (s = TT_TECHDEPBASE; s < DBNumTypes; s++) { if (!TTMaskHasType(&types1, s)) @@ -2959,6 +2986,7 @@ ExtTechLine(sectionName, argc, argv) TTMaskSetMask(&ExtCurStyle->exts_sideCoupleOtherEdges[s][t], &far); cnew = (EdgeCap *) mallocMagic((unsigned) (sizeof (EdgeCap))); cnew->ec_cap = capVal; + cnew->ec_offset = offset; cnew->ec_near = near; cnew->ec_far = far; cnew->ec_next = ExtCurStyle->exts_sideCoupleCap[s][t]; @@ -3451,11 +3479,20 @@ zinit: // the value needs to be divided by 2 (the factor of // 2 is made up by the fact that the sidewall is // independently accumulated on each plate of the - // capacitor) + // capacitor). ALSO: ec_offset was multiplied up by + // 1000 so that micron distances could be saved as + // integer values, so that factor needs to be divided out. for (ec = style->exts_sideCoupleCap[r][s]; ec != NULL; ec = ec->ec_next) + { ec->ec_cap *= 0.5; + if (ec->ec_offset > 0) + { + ec->ec_offset = (int)(((float)ec->ec_offset / dscale) + 0.5); + ec->ec_offset /= 1000; + } + } } /* Layer thickness and height are in microns, but are floating-point */ @@ -3548,12 +3585,13 @@ ExtTechScale(scalen, scaled) // per distance, the distance is referred to a separation // distance in the same units, so the cap never scales. - // for (ec = style->exts_sideCoupleCap[i][j]; ec != NULL; - // ec = ec->ec_next) - // { - // ec->ec_cap *= scalen; - // ec->ec_cap /= scaled; - // } + for (ec = style->exts_sideCoupleCap[i][j]; ec != NULL; + ec = ec->ec_next) + { + // ec->ec_cap *= scalen; + // ec->ec_cap /= scaled; + DBScaleValue(&(ec->ec_offset), scaled, scalen); + } for (ec = style->exts_sideOverlapCap[i][j]; ec != NULL; ec = ec->ec_next) { diff --git a/extract/extract.h b/extract/extract.h index e1e06cac..c9c9f87b 100644 --- a/extract/extract.h +++ b/extract/extract.h @@ -67,10 +67,11 @@ extern char *extDevTable[]; #define EXT_DOCOUPLING 0x004 /* Extract coupling capacitance */ #define EXT_DORESISTANCE 0x008 /* Extract resistance */ #define EXT_DOLENGTH 0x010 /* Extract pathlengths */ -#define EXT_DOALL 0x01f /* ALL OF THE ABOVE */ -#define EXT_DOLOCAL 0x020 /* Write to local directory only */ -#define EXT_DOLABELCHECK 0x040 /* Check for connections by label */ -#define EXT_DOALIASES 0x080 /* Output all node aliases */ +#define EXT_DOFRINGEHALO 0x020 /* Distributed fringe capacitance */ +#define EXT_DOALL 0x03f /* ALL OF THE ABOVE */ +#define EXT_DOLOCAL 0x040 /* Write to local directory only */ +#define EXT_DOLABELCHECK 0x080 /* Check for connections by label */ +#define EXT_DOALIASES 0x100 /* Output all node aliases */ extern int ExtOptions; /* Bitmask of above */ diff --git a/extract/extractInt.h b/extract/extractInt.h index 5819fce0..93ffad73 100644 --- a/extract/extractInt.h +++ b/extract/extractInt.h @@ -442,6 +442,7 @@ typedef struct edgecap { struct edgecap *ec_next; /* Next edge capacitance rule in list */ CapValue ec_cap; /* Capacitance (attofarads) */ + int ec_offset; /* Offset to apply to separation */ TileTypeBitMask ec_near; /* Types closest to causing edge, or in * the case of sideOverlaps, the * types we are overlapping.