diff --git a/VERSION b/VERSION index d5c5d3b5..10ef81d4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.678 +8.3.679 diff --git a/extract/ExtCouple.c b/extract/ExtCouple.c index fd0f7223..53217cb2 100644 --- a/extract/ExtCouple.c +++ b/extract/ExtCouple.c @@ -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); } diff --git a/extract/ExtTech.c b/extract/ExtTech.c index 3de00911..112087e6 100644 --- a/extract/ExtTech.c +++ b/extract/ExtTech.c @@ -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); diff --git a/resis/ResMain.c b/resis/ResMain.c index 5c71b2a2..b5a3268a 100644 --- a/resis/ResMain.c +++ b/resis/ResMain.c @@ -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); diff --git a/resis/ResUtils.c b/resis/ResUtils.c index a0a70922..e8d9004a 100644 --- a/resis/ResUtils.c +++ b/resis/ResUtils.c @@ -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, diff --git a/select/selCreate.c b/select/selCreate.c index d7f40ba3..88b07082 100644 --- a/select/selCreate.c +++ b/select/selCreate.c @@ -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. */