mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-08-22 14:17:43 +02:00
Overhauled the extresist code (again), this time to (1) correct for
a long-standing error (introduced with the "extresist geometry" option) that can cause nets not to be extracted (due to the first record not having extraction data, which was itself a long-standing error in the code but which was not fixed correctly); (2) handle "device mosfet" type transistors (previously only handled the old "fet" type extraction devices); and (3) correct for the res.ext file having a different scalefactor relative to the .ext file. The latter item was solved by forcing all input to scale like ExtCurStyle->exts_unitsPerLambda, locally correcting all input as needed. Note that extresist still needs to handle other extraction devices (e.g., resistors and capacitors) but those will require additional handling in the routines which analyze the current path to determine how to break up wires into paths.
This commit is contained in:
+141
-35
@@ -122,55 +122,161 @@ cifPaintFunc(tile, table)
|
||||
* Always returns 0 to keep the search alive.
|
||||
*
|
||||
* Side effects:
|
||||
* Scales the tile by cifScale, then expands its area by the
|
||||
* remainder of the distance to meet the minimum dimension, as
|
||||
* defined by the grid distance (growDistance) in the current
|
||||
* CIFOp, then paints this area into cifNewPlane using the table
|
||||
* passed as parameter.
|
||||
* May paint into cifNewPlane
|
||||
*
|
||||
* Algorithm (based on maximum horizontal stripes rule):
|
||||
* Scan top and bottom boundaries from left to right. For any
|
||||
* distance (including distance zero) sharing the same type (0 or 1)
|
||||
* on both the tile top and bottom, find the diagonal length. If
|
||||
* less than co_distance, then expand this area and paint.
|
||||
* NOTE: This algorithm does not cover a number of geometry cases
|
||||
* and needs to be reworked. It should be restricted to cases of
|
||||
* layers that have "rect_only" DRC rules. Since the rule is usually
|
||||
* needed for implants on FET gates to maintain the implant width for
|
||||
* small gates, the "rect_only" requirement is not particularly
|
||||
* constraining.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
cifGrowMinFunc(tile, plane)
|
||||
cifGrowMinFunc(tile, table)
|
||||
Tile *tile;
|
||||
Plane *plane;
|
||||
PaintResultType *table; /* Table to be used for painting. */
|
||||
{
|
||||
Rect area, *maxr;
|
||||
int locDist, width, height;
|
||||
TileTypeBitMask mask;
|
||||
TileType type;
|
||||
Rect area, parea;
|
||||
int locDist, width, height, h;
|
||||
TileType type, tptype;
|
||||
Tile *tp, *tp2;
|
||||
|
||||
TiToRect(tile, &area);
|
||||
type = TiGetType(tile);
|
||||
|
||||
TTMaskZero(&mask);
|
||||
TTMaskSetType(&mask, type);
|
||||
area.r_xbot *= cifScale;
|
||||
area.r_xtop *= cifScale;
|
||||
area.r_ybot *= cifScale;
|
||||
area.r_ytop *= cifScale;
|
||||
|
||||
maxr = FindMaxRectangle2(&area, tile, plane, &mask);
|
||||
if (maxr == NULL) return 0; /* Should not happen */
|
||||
parea = area;
|
||||
|
||||
maxr->r_xbot *= cifScale;
|
||||
maxr->r_xtop *= cifScale;
|
||||
maxr->r_ybot *= cifScale;
|
||||
maxr->r_ytop *= cifScale;
|
||||
|
||||
width = maxr->r_xtop - maxr->r_xbot;
|
||||
height = maxr->r_ytop - maxr->r_ybot;
|
||||
locDist = (growDistance - width) / 2;
|
||||
if (locDist > 0)
|
||||
/* Check whole tile for minimum width */
|
||||
width = area.r_xtop - area.r_xbot;
|
||||
if (width < growDistance)
|
||||
{
|
||||
maxr->r_xbot -= locDist;
|
||||
maxr->r_xtop += locDist;
|
||||
}
|
||||
locDist = (growDistance - width) / 2;
|
||||
area.r_xbot -= locDist;
|
||||
area.r_xtop += locDist;
|
||||
|
||||
locDist = (growDistance - height) / 2;
|
||||
if (locDist > 0)
|
||||
/* If there is another tile on top or bottom, and the height is */
|
||||
/* less than minimum, then extend height in the direction of */
|
||||
/* the bordering tile. Otherwise, if the height is less than */
|
||||
/* minimum, then grow halfway in both directions. */
|
||||
|
||||
height = area.r_ytop - area.r_ybot;
|
||||
if (height < growDistance)
|
||||
{
|
||||
bool freeTop, freeBot;
|
||||
|
||||
freeTop = freeBot = TRUE;
|
||||
|
||||
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
|
||||
if (TiGetTopType(tp) == TiGetBottomType(tile))
|
||||
{
|
||||
freeBot = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
for (tp2 = RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2))
|
||||
if (TiGetBottomType(tp2) == TiGetTopType(tile))
|
||||
{
|
||||
freeTop = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* In the following, value h ensures that the euclidean */
|
||||
/* distance between inside corners of the layer */
|
||||
/* satisfies growDistance. */
|
||||
|
||||
if (freeTop == TRUE && freeBot == FALSE)
|
||||
{
|
||||
locDist = (growDistance - height) / 2;
|
||||
h = (int)sqrt((double)(growDistance * growDistance) -
|
||||
0.25 * (double)((growDistance + width) *
|
||||
(growDistance + width)) + 0.5);
|
||||
area.r_ybot -= h;
|
||||
}
|
||||
else if (freeTop == FALSE && freeBot == TRUE)
|
||||
{
|
||||
h = (int)sqrt((double)(growDistance * growDistance) -
|
||||
0.25 * (double)((growDistance + width) *
|
||||
(growDistance + width)) + 0.5);
|
||||
area.r_ytop += h;
|
||||
}
|
||||
else {
|
||||
locDist = (growDistance - height) / 2;
|
||||
area.r_ybot -= locDist;
|
||||
area.r_ytop += locDist;
|
||||
}
|
||||
}
|
||||
}
|
||||
DBPaintPlane(cifPlane, &area, table, (PaintUndoInfo *) NULL);
|
||||
|
||||
area = parea;
|
||||
|
||||
/* Scan bottom from left to right */
|
||||
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
|
||||
{
|
||||
maxr->r_ybot -= locDist;
|
||||
maxr->r_ytop += locDist;
|
||||
}
|
||||
tptype = TiGetTopType(tp);
|
||||
/* Scan top from right to left across range of tp */
|
||||
for (tp2 = RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2))
|
||||
if (TiGetBottomType(tp2) == tptype)
|
||||
{
|
||||
/* Set range to length of overlap */
|
||||
if ((LEFT(tp2) <= RIGHT(tp)) && (LEFT(tp2) >= LEFT(tp)))
|
||||
{
|
||||
area.r_xbot = LEFT(tp2) < LEFT(tile) ? LEFT(tile) : LEFT(tp2);
|
||||
area.r_xtop = RIGHT(tp) > RIGHT(tile) ? RIGHT(tile) : RIGHT(tp);
|
||||
}
|
||||
else if ((RIGHT(tp2) >= LEFT(tp)) && (RIGHT(tp2) <= RIGHT(tp)))
|
||||
{
|
||||
area.r_xbot = LEFT(tp) < LEFT(tile) ? LEFT(tile) : LEFT(tp);
|
||||
area.r_xtop = RIGHT(tp2) > RIGHT(tile) ? RIGHT(tile) : RIGHT(tp2);
|
||||
}
|
||||
else continue;
|
||||
|
||||
DBPaintPlane(cifPlane, maxr, CIFPaintTable, (PaintUndoInfo *) NULL);
|
||||
area.r_xbot *= cifScale;
|
||||
area.r_xtop *= cifScale;
|
||||
|
||||
/* Does area violate minimum width requirement? */
|
||||
width = area.r_xtop - area.r_xbot;
|
||||
height = area.r_ytop - area.r_ybot;
|
||||
|
||||
/* Manhattan requirement (to-do: Euclidean) */
|
||||
if (width < growDistance)
|
||||
{
|
||||
locDist = (growDistance - width) / 2;
|
||||
parea.r_xbot = area.r_xbot - locDist;
|
||||
parea.r_xtop = area.r_xtop + locDist;
|
||||
}
|
||||
else
|
||||
{
|
||||
parea.r_xbot = area.r_xbot;
|
||||
parea.r_xtop = area.r_xtop;
|
||||
}
|
||||
if (height < growDistance)
|
||||
{
|
||||
locDist = (growDistance - height) / 2;
|
||||
parea.r_ybot = area.r_ybot - locDist;
|
||||
parea.r_ytop = area.r_ytop + locDist;
|
||||
}
|
||||
else
|
||||
{
|
||||
parea.r_ybot = area.r_ybot;
|
||||
parea.r_ytop = area.r_ytop;
|
||||
}
|
||||
if ((width < growDistance) || (height < growDistance))
|
||||
DBPaintPlane(cifPlane, &parea, table, (PaintUndoInfo *) NULL);
|
||||
}
|
||||
}
|
||||
|
||||
CIFTileOps += 1;
|
||||
return 0;
|
||||
@@ -3199,7 +3305,7 @@ CIFGenLayer(op, area, cellDef, temps, clientdata)
|
||||
cifPlane = nextPlane;
|
||||
cifScale = 1;
|
||||
(void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect,
|
||||
&CIFSolidBits, cifGrowMinFunc, (ClientData)curPlane);
|
||||
&CIFSolidBits, cifGrowMinFunc, (ClientData)CIFPaintTable);
|
||||
temp = curPlane;
|
||||
curPlane = nextPlane;
|
||||
nextPlane = temp;
|
||||
|
||||
+3980
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user