-- ChipDRCImpl.mesa -- last modified by E. McCreight, January 30, 1984 6:16 PM -- written by E. McCreight, April 14, 1982 10:25 AM DIRECTORY ChipDRC, ChipFeature, ChipNetDefs, ChipWire, LeftFeaturePQ, FeaturePST, ppdefs, RightFeaturePQ, StreamDefs; ChipDRCImpl: PROGRAM IMPORTS ChipDRC, ChipFeature, ChipNetDefs, ChipWire, LeftFeaturePQ, FeaturePST, RightFeaturePQ EXPORTS ChipDRC SHARES ChipDRC = BEGIN OPEN ppdefs, ChipNetDefs, FeaturePST, LeftFeaturePQ, RightFeaturePQ, ChipWire, ChipDRC; drcSwathWidth: PUBLIC Coord; doingDRC: PUBLIC BOOLEAN _ FALSE; polyGateOverlap, minTransistorDiffusionWidth, depletionOverlap: PUBLIC locNum; minSize, closestUnconnected: PUBLIC ARRAY ExtractLevel OF Coord; drcSwath: PUBLIC ChipWire.SlicePtr; -- drcSwathWidth wide drcSwathFeatures: PUBLIC RightFeaturePQHandle; -- the features in the slice but abandoned by ExtractNets SetupDRC: PUBLIC PROCEDURE[check: BOOLEAN] = BEGIN IF (doingDRC _ check) THEN BEGIN SetDRCParams[]; holdViolations _ NOT HeSetsParamsAndSaysYes[ "Should I tell you about errors as I find them?"]; drcSwath _ ChipWire.NewSlice[]; drcSwathFeatures _ NewRightFeaturePQ[uz]; END; END; -- of SetupDRC FinishDRC: PUBLIC PROCEDURE[root: CellCallPtr] = BEGIN IF doingDRC THEN BEGIN PurgeSwath[LAST[Coord]]; drcSwath _ ChipWire.DestroySlice[drcSwath]; drcSwathFeatures _ DestroyRightFeaturePQ[drcSwathFeatures]; END; CheckTerminalConnections[root]; EnumerateViolations[]; END; -- of FinishDRC LeftEdges: PUBLIC PROCEDURE[pq: LeftFeaturePQHandle] = BEGIN EnterSwath: PROCEDURE[f: FeaturePtr] = BEGIN rLev: ExtractLevel; IF InverseRequiredLevel[f.lev]=unknown THEN InsertFeaturePST[p: drcSwath[f.lev], item: f]; IF (rLev _ RequiredLevel[f.lev])#unknown THEN NoteCover[lev: rLev, c: f.cover]; END; CheckLeftEdge: PROCEDURE[f: FeaturePtr] = BEGIN lev, rLev, fLev: ExtractLevel; ForbiddenHere: PROCEDURE[item: FeaturePtr] = BEGIN p: Point; IF NOT HaveSharedArea[f.cover, item.cover] THEN RETURN; p _ RefCoordPt[SharedArea[f.cover, item.cover]]; IF f.net=NIL OR item.net=NIL THEN NoteViolation[[place: p, info: coverageForbidden[lev: lev]]] ELSE -- it's a violation only if they're not the same IF (f.net _ CanonNet[f.net])# (item.net _ CanonNet[item.net]) THEN BEGIN id: NormalNetIdPtr = GetNormalNetId[@f.net]; id.violations _ uz.NEW[ViolationList _ [ next: id.violations, v: [place: p, info: coverageForbiddenIfNetsDiffer[lev: lev, n1: RefCanonNet[item.net], n2: RefCanonNet[f.net]]]]]; END; END; IF (rLev _ InverseRequiredLevel[f.lev])#unknown THEN EnsureCoverage[lev: rLev, xNow: f.cover.x1, r: f.cover, NoCoverage: CoverageFailed]; lev _ f.lev; IF (fLev _ ForbiddenLevel[f.lev])#unknown THEN SearchFeaturePST[p: drcSwath[fLev], int: [f.cover.y1, f.cover.y2], touch: ForbiddenHere] ELSE IF (lev _ InverseForbiddenLevel[f.lev])#unknown THEN SearchFeaturePST[p: drcSwath[lev], int: [f.cover.y1, f.cover.y2], touch: ForbiddenHere]; IF closestUnconnected[f.lev]>0 THEN NeighborCheck[f: f, inLevel: f.lev, dist: closestUnconnected[f.lev]]; SELECT f.lev FROM bur => BEGIN NeighborCheck[f: f, inLevel: nGate, dist: (3*Lambda)/2]; NeighborCheck[f: f, inLevel: pGate, dist: (3*Lambda)/2]; END; nPlus => NeighborCheck[f: f, inLevel: pwelCont, dist: 3*Lambda]; pPlus => NeighborCheck[f: f, inLevel: nwelCont, dist: 3*Lambda]; pwelCont => NeighborCheck[f: f, inLevel: nPlus, dist: 3*Lambda]; nwelCont => NeighborCheck[f: f, inLevel: pPlus, dist: 3*Lambda]; ENDCASE => NULL; IF 00 AND RightFeaturePQMin[drcSwathFeatures].cover.x2 IF oldF.cover.x1 NULL; oldF _ ChipFeature.DestroyFeature[oldF]; ENDLOOP; END; -- of PurgeSwath -- Size checking ensures that connected -- features on the same layer are drawn -- so that a square of size minSize can be moved -- around every interior boundary of -- the connected region without getting stuck. -- Ramshaw and I spent a lunch brainstorming, -- and we decided that this -- is equivalent to every connected region's -- containing a square of size minSize on the interior of -- every corner. -- Corner are designated as {n, s}{e, w}{C, E}. -- (In Chipmonk's co-ordinate system, y increases -- southward and x increases eastward). -- For example, a nwC corner is a corner whose northwest -- quadrant is covered and all others are empty. A seE corner -- is a corner whose southeast quadrant is empty and all others -- are covered. There are eight of these designators, and -- a corner is completely determined by a point and a designator. LeftEdgeSizeCheck: PROCEDURE[f: FeaturePtr, minSize: Coord] = BEGIN LeftMinSizeViolation: PROCEDURE[lev: ExtractLevel, r: CoordRect] RETURNS[continue: BOOLEAN] = BEGIN MinSizeViolation[f: f, r: r]; continue _ TRUE; END; r: CoordRect = f.cover; IF r.x1=r.x2 OR r.y1=r.y2 THEN RETURN; -- r is a point or a line. -- Such features correspond to required areas, whose absence -- is detected in other ways. -- r is known to be a non-empty area IF r.y2 -- [x: r.x2, y: r.y1] could be a swC corner IF (r.y2 -- [x: r.x2, y: rightCover.max-1] is a seE corner EnsureCoverage[lev: f.lev, xNow: r.x2+1, r: [x1: r.x2-minSize, y1: rightCover.max-minSize, x2: r.x2, y2: rightCover.max], NoCoverage: RightMinSizeViolation]; ENDCASE => NULL; SELECT nextCover FROM <=r.y1 => NULL; -- [x: r.x2, y: nextCover] is a neE corner EnsureCoverage[lev: f.lev, xNow: r.x2+1, r: [x1: r.x2-minSize, y1: nextCover, x2: r.x2, y2: nextCover+minSize], NoCoverage: RightMinSizeViolation]; ENDCASE => -- [x: r.x2, y: r.y2-1] could be a nwC corner IF (r.y2 IF did.couldBeLogo THEN {did.violations _ uz.NEW[ViolationList _ [ next: did.violations, v: v ]]; RETURN}; ENDCASE => NULL; END; NoteViolation[v]; END; -- of MinSizeViolation NeighborCheck: PROCEDURE[f: FeaturePtr, inLevel: ExtractLevel, dist: Coord] = BEGIN TooCloseViolation: PROCEDURE[neighbor: FeaturePtr] = BEGIN cnNeighbor: CanonNetPtr _ neighbor.net _ CanonNet[neighbor.net]; v: Violation _ [ place: RefCoordPt[[ x1: MIN[f.cover.x1, neighbor.cover.x2], x2: f.cover.x1, y1: MAX[f.cover.y1-dist, neighbor.cover.y1], y2: MIN[f.cover.y2+dist, neighbor.cover.y2]]], info: tooClose[lev1: f.lev, lev2: neighbor.lev, n1: (f.net _ RefCanonNet[f.net]), n2: RefCanonNet[cnNeighbor]]]; IF f.cover.x1<=cnNeighbor.id.final.r.x2 OR (GetNormalNetId[@f.net].couldBeLogo AND GetNormalNetId[@neighbor.net].couldBeLogo) THEN -- nets could still not be in error cnNeighbor.id.violations _ uz.NEW[ViolationList _ [next: cnNeighbor.id.violations, v: v]] ELSE NoteViolation[v]; END; -- of TooCloseViolation CheckNeighborDiffusion: PROCEDURE[item: FeaturePtr] = BEGIN cnitem: CanonNetPtr _ item.net _ CanonNet[item.net]; ASSERT[item.cover.x1<=f.cover.x1]; IF f#item AND f.cover.x1 CheckNeighborDiffusion, -- transistors interfere ENDCASE => CheckThisNeighbor) ]; END; -- of NeighborCheck maxNeedingCover: CARDINAL = 100; needCover, oldNeedCover: ARRAY[0..maxNeedingCover) OF CoordRect; numNeedingCover: [0..maxNeedingCover]; EnsureCoverage: PROCEDURE[lev: ExtractLevel, xNow: Coord, r: CoordRect, NoCoverage: PROCEDURE[lev: ExtractLevel, r: CoordRect] RETURNS[continue: BOOLEAN]] = BEGIN -- Any x-values less than xNow will certainly already be present -- in the swath. x-values greater than or equal to -- xNow might be present in -- the swath, but need not yet be present. NeedCoverFull: SIGNAL = CODE; ExtendCoverage: PROCEDURE[item: FeaturePtr] = BEGIN c: CoordRect _ item.cover; source: [0..maxNeedingCover); nextSink: [0..maxNeedingCover] _ 0; StillNeedCover: PROCEDURE[r: CoordRect] = INLINE BEGIN IF nextSink {NoteViolation[[place: RefCoordPt[r], info: cantCheck[]]]; GOTO Overflow}]; FOR i: [0..maxNeedingCover) IN [0..numNeedingCover) DO IF needCover[i].x1 NULL; END; -- of EnsureCoverage maxfListSize: CARDINAL = 100; fList: ARRAY [0..maxfListSize) OF FeaturePtr; NoteCover: PROCEDURE[lev: ExtractLevel, c: CoordRect] = BEGIN fListSize: [0..maxfListSize] _ 0; ListTouchedRequirements: PROCEDURE[item: FeaturePtr] = BEGIN IF item.cover.x1 nWellRequired, pWell => pWellRequired, nDepletion => nDepletionRequired, nBuriedContact => nBuriedContactRequired, nPlus => nPlusRequired, pPlus => pPlusRequired, nGate => nGateRequired, pGate => pGateRequired, poly => polyRequired, ENDCASE => unknown)]}; InverseRequiredLevel: PROCEDURE[lev: ExtractLevel] RETURNS[ExtractLevel] = {RETURN[(SELECT lev FROM nWellRequired => nWell, pWellRequired => pWell, nDepletionRequired => nDepletion, nBuriedContactRequired => nBuriedContact, nPlusRequired => nPlus, pPlusRequired => pPlus, nGateRequired => nGate, pGateRequired => pGate, polyRequired => poly, ENDCASE => unknown)]}; ForbiddenLevel: PROCEDURE[lev: ExtractLevel] RETURNS[ExtractLevel] = {RETURN[(SELECT lev FROM nWell => nWellForbidden, pWell => pWellForbidden, nDepletion => nDepletionForbidden, nBuriedContact => nBuriedContactForbidden, nPlus => nPlusForbidden, pPlus => pPlusForbidden, nGate => nGateForbidden, pGate => pGateForbidden, poly => polyForbidden, cut => cutForbidden, ENDCASE => unknown)]}; InverseForbiddenLevel: PROCEDURE[lev: ExtractLevel] RETURNS[ExtractLevel] = {RETURN[(SELECT lev FROM nWellForbidden => nWell, pWellForbidden => pWell, nDepletionForbidden => nDepletion, nBuriedContactForbidden => nBuriedContact, nPlusForbidden => nPlus, pPlusForbidden => pPlus, nGateForbidden => nGate, pGateForbidden => pGate, polyForbidden => poly, cutForbidden => cut, ENDCASE => unknown)]}; END. -- of ChipDRCImpl