Multiple changes:
(1) Corrections to the R-C extraction code to better handle nodes
which have the recorded position at the corner of a split tile.
(2) Corrected "select area label" to prevent accidentally selecting
unexpanded instances in the area. Also corrects an issue with
not being able to select labels that are attached to "space".
(3) Changed the way that magic interprets the "sidewall" coefficient
so that it is entered into the tech file as the actual sidewall
coefficient instead of being half the value to correct for
magic's double counting of edges. The correction is instead
done when parsing the tech file. This measure was taken because
the open PDK values generated by "capiche" were not halving the
value, so I either change magic or I change all the tech files.
This commit is contained in:
parent
73620475d7
commit
51522d6889
|
|
@ -3057,6 +3057,13 @@ extSideBottom(tpfar, bp, esws)
|
|||
* amount of capacitance for an edge with tpnear on the close side
|
||||
* and tpfar on the remote side.
|
||||
*
|
||||
* Important! The sidewall coeffient is correct for the coupling between
|
||||
* edges, but both edges will be checked, causing a double-count, so each
|
||||
* edge should contribute half of the total. For a long time the sidewall
|
||||
* coefficient was claimed to need to be half the value, but the offset
|
||||
* makes it incorrect to halve the coefficient, and it is necessary to
|
||||
* halve the total sidewall capacitance when doing the calculations.
|
||||
*
|
||||
* Results:
|
||||
* Returns 0 always.
|
||||
*
|
||||
|
|
@ -3080,7 +3087,7 @@ extSideCommon(rinside, rfar, tpnear, tpfar, bdir, overlap, sep, extCoupleList)
|
|||
HashEntry *he;
|
||||
EdgeCap *e;
|
||||
CoupleKey ck;
|
||||
CapValue cap;
|
||||
CapValue cap, swcap;
|
||||
|
||||
/* Get the tile types of tpnear and tpfar */
|
||||
extGetBoundaryTypes2(bdir, tpnear, tpfar, &near, &far);
|
||||
|
|
@ -3092,11 +3099,10 @@ extSideCommon(rinside, rfar, tpnear, tpfar, bdir, overlap, sep, extCoupleList)
|
|||
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 + e->ec_offset);
|
||||
swcap = 0.5 * (e->ec_cap * overlap) / (sep + e->ec_offset);
|
||||
cap += swcap;
|
||||
if (CAP_DEBUG)
|
||||
extAdjustCouple(he,
|
||||
(e->ec_cap * overlap) / (sep + e->ec_offset),
|
||||
"sidewall");
|
||||
extAdjustCouple(he, swcap, "sidewall");
|
||||
}
|
||||
extSetCapValue(he, cap);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3291,6 +3291,18 @@ ExtTechLine(sectionName, argc, argv)
|
|||
return (TRUE);
|
||||
break;
|
||||
case SIDEWALL:
|
||||
|
||||
/* NOTE: Originally, the sidewall capacitance coefficient was
|
||||
* supposed to be the value that is appropriate to compute
|
||||
* half the total sidewall on each edge. The addition of "offset"
|
||||
* requires that the coefficient (and offset) should be values
|
||||
* yielding the total sidewall between two edges. Because each
|
||||
* edge is computed separately, the total capacitance is halved
|
||||
* when doing the calculation (see ExtCouple.c). Sidewall values
|
||||
* are correct for the open PDKs and presumably incorrect for the
|
||||
* original SCMOS tech files.
|
||||
*/
|
||||
|
||||
DBTechNoisyNameMask(argv[2], &types2);
|
||||
TTMaskSetMask(allExtractTypes, &types2);
|
||||
DBTechNoisyNameMask(argv[3], &near);
|
||||
|
|
|
|||
|
|
@ -911,19 +911,56 @@ resMakeDevFunc(tile, dinfo, cx)
|
|||
Rect devArea;
|
||||
TileType ttype;
|
||||
|
||||
/* To simplify processing, if a split tile does not have TT_SPACE
|
||||
* on either side, then only the left side is processed.
|
||||
*/
|
||||
if (IsSplit(tile))
|
||||
if (TiGetLeftType(tile) != TT_SPACE && TiGetRightType(tile) != TT_SPACE)
|
||||
if (dinfo & TT_SIDE)
|
||||
return 0;
|
||||
|
||||
TiToRect(tile, &devArea);
|
||||
GeoTransRect(&cx->tc_scx->scx_trans, &devArea, &thisDev->area);
|
||||
|
||||
/*
|
||||
* NOTE: The .ext file may record devices on a split tile when the lower
|
||||
* left corner is not the device. Because the location is only one unit
|
||||
* square, the area of the device will not be searched. Check for this
|
||||
* case and handle accordingly.
|
||||
*/
|
||||
if (IsSplit(tile))
|
||||
ttype = ((dinfo & TT_SIDE)) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
{
|
||||
TileType lefttype, righttype;
|
||||
bool devleft, devright;
|
||||
|
||||
lefttype = TiGetLeftType(tile);
|
||||
devleft = TTMaskHasType(&ExtCurStyle->exts_deviceMask, lefttype);
|
||||
if (!devleft)
|
||||
{
|
||||
righttype = TiGetRightType(tile);
|
||||
devright = TTMaskHasType(&ExtCurStyle->exts_deviceMask, righttype);
|
||||
if (devright)
|
||||
{
|
||||
int hheight, hwidth;
|
||||
|
||||
/* Find the tile half width and half height. If the width
|
||||
* or height is not an even integer, round up.
|
||||
*/
|
||||
hheight = (TOP(tile) - BOTTOM(tile));
|
||||
hwidth = (RIGHT(tile) - LEFT(tile));
|
||||
if (hheight & 1) hheight++;
|
||||
if (hwidth & 1) hwidth++;
|
||||
hheight >>= 1;
|
||||
hwidth >>= 1;
|
||||
|
||||
/* Use the type of the tile's right side */
|
||||
ttype = SplitRightType(tile);
|
||||
|
||||
/* Move the device area into the actual device location */
|
||||
thisDev->area.r_ll.p_x += hwidth;
|
||||
if (TiGetTypeExact(tile) & TT_DIRECTION)
|
||||
thisDev->area.r_ll.p_y += hheight;
|
||||
else
|
||||
thisDev->area.r_ur.p_y -= hheight;
|
||||
}
|
||||
else
|
||||
ttype = ((dinfo & TT_SIDE)) ? righttype : lefttype;
|
||||
}
|
||||
else
|
||||
ttype = ((dinfo & TT_SIDE)) ? righttype : lefttype;
|
||||
}
|
||||
else
|
||||
ttype = TiGetType(tile);
|
||||
|
||||
|
|
@ -985,14 +1022,6 @@ resExpandDevFunc(tile, dinfo, cx)
|
|||
int pNum;
|
||||
Rect area;
|
||||
|
||||
/* To simplify processing, if a split tile does not have TT_SPACE
|
||||
* on either side, then only the left side is processed.
|
||||
*/
|
||||
if (IsSplit(tile))
|
||||
if (TiGetLeftType(tile) != TT_SPACE && TiGetRightType(tile) != TT_SPACE)
|
||||
if (dinfo & TT_SIDE)
|
||||
return 0;
|
||||
|
||||
pNum = DBPlane(thisDev->type);
|
||||
if (devExtentsStack == NULL)
|
||||
devExtentsStack = StackNew(8);
|
||||
|
|
@ -1013,8 +1042,25 @@ resExpandDevFunc(tile, dinfo, cx)
|
|||
|
||||
if (IsSplit(tp))
|
||||
{
|
||||
TileType leftType;
|
||||
bool isDevType;
|
||||
|
||||
dinfo = TiGetTypeExact(tp);
|
||||
if (TiGetLeftType(tp) == TT_SPACE)
|
||||
|
||||
/* For split tiles, determine which side is the device.
|
||||
* Since some devices (e.g., diodes, MiM caps) may have contact
|
||||
* types that are part of the device, make sure to compare the
|
||||
* residue mask of the type, not the type itself.
|
||||
*/
|
||||
|
||||
leftType = TiGetLeftType(tp);
|
||||
if (DBIsContact(leftType))
|
||||
isDevType = (TTMaskHasType(DBResidueMask(leftType), thisDev->type)) ?
|
||||
TRUE : FALSE;
|
||||
else
|
||||
isDevType = (leftType == thisDev->type) ? TRUE : FALSE;
|
||||
|
||||
if (!isDevType)
|
||||
{
|
||||
dinfo |= TT_SIDE; /* Look at tile right side */
|
||||
sides |= IGNORE_LEFT;
|
||||
|
|
@ -1387,6 +1433,11 @@ ResExtractNet(node, resisdata, cellname)
|
|||
thisDev->nextDev = DevTiles;
|
||||
DevTiles = thisDev;
|
||||
|
||||
/* Because resMakeDevFunc() may adjust the area to contain the
|
||||
* device, copy thisDev->area back into scx.scx_area
|
||||
*/
|
||||
scx.scx_area = thisDev->area;
|
||||
|
||||
/* Paint the entire device into ResUse */
|
||||
TTMaskSetOnlyType(&tMask, thisDev->type);
|
||||
DBTreeSrTiles(&scx, &tMask, 0, resExpandDevFunc, (ClientData)thisDev);
|
||||
|
|
|
|||
|
|
@ -895,6 +895,7 @@ ResPreProcessDevices(TileList, DeviceList, Def, devNodeTable)
|
|||
resInfo *tstruct;
|
||||
TileType tt, residue;
|
||||
int pNum;
|
||||
bool isdev;
|
||||
|
||||
while (TileList != (ResDevTile *)NULL)
|
||||
{
|
||||
|
|
@ -925,12 +926,24 @@ ResPreProcessDevices(TileList, DeviceList, Def, devNodeTable)
|
|||
GOTOPOINT(tile, &(TileList->area.r_ll));
|
||||
PlaneSetHint(Def->cd_planes[pNum], tile);
|
||||
|
||||
tt = TiGetType(tile);
|
||||
tt = TiGetLeftType(tile);
|
||||
isdev = TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt);
|
||||
|
||||
if (IsSplit(tile) && !isdev)
|
||||
{
|
||||
/* Check the other side */
|
||||
tt = TiGetRightType(tile);
|
||||
isdev = TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt);
|
||||
}
|
||||
|
||||
/* Warning: Will probably need to deal with resInfo structs on split
|
||||
* tiles when both sides of the split tile are not TT_SPACE!
|
||||
*/
|
||||
tstruct = (resInfo *) TiGetClientPTR(tile);
|
||||
|
||||
if ((tstruct == (resInfo *)CLIENTDEFAULT) ||
|
||||
(tstruct->deviceList == NULL) ||
|
||||
!TTMaskHasType(&ExtCurStyle->exts_deviceMask, tt))
|
||||
(!isdev))
|
||||
{
|
||||
TxError("Bad Device Location at %d,%d\n",
|
||||
TileList->area.r_ll.p_x,
|
||||
|
|
|
|||
|
|
@ -470,14 +470,19 @@ SelectArea(scx, types, xMask, globmatch)
|
|||
|
||||
if (TTMaskHasType(types, L_LABEL))
|
||||
{
|
||||
TileTypeBitMask *maskptr;
|
||||
|
||||
TTMaskClearType(types, L_LABEL);
|
||||
if (TTMaskIsZero(types)) types = &DBAllButSpaceAndDRCBits;
|
||||
if (TTMaskIsZero(types))
|
||||
maskptr = &DBAllTypeBits;
|
||||
else
|
||||
maskptr = types;
|
||||
|
||||
if (globmatch != NULL)
|
||||
DBCellCopyGlobLabels(scx, types, xMask, SelectUse, &labelArea,
|
||||
DBCellCopyGlobLabels(scx, maskptr, xMask, SelectUse, &labelArea,
|
||||
globmatch);
|
||||
else
|
||||
DBCellCopyAllLabels(scx, types, xMask, SelectUse, &labelArea);
|
||||
DBCellCopyAllLabels(scx, maskptr, xMask, SelectUse, &labelArea);
|
||||
}
|
||||
|
||||
/* Select cell uses. */
|
||||
|
|
|
|||
Loading…
Reference in New Issue