-- ChipReticleImpl2.mesa -- Auxiliary functions to support reticle production. -- last modified by E. McCreight, November 23, 1982 1:40 PM -- written by E. McCreight, May 19, 1982 3:32 PM DIRECTORY ChipFeature, ChipNetDefs, ChipReticle, ChipUserInt, CoordRectPQ, FeaturePST, InlineDefs, ppdddefs, ppddefs, ppdefs, ReticleBandFormat, SegmentDefs, StreamDefs, StringDefs; ChipReticleImpl2: PROGRAM IMPORTS ChipFeature, ChipNetDefs, ChipReticle, ChipUserInt, CoordRectPQ, FeaturePST, InlineDefs, ppdddefs, ppddefs, ppdefs, StreamDefs, StringDefs EXPORTS ChipReticle SHARES ChipReticle = BEGIN OPEN StreamDefs, StringDefs, ppdddefs, ppddefs, ppdefs, ChipUserInt, ChipNetDefs, ChipReticle, FeaturePST, CoordRectPQ; InitMaskStates: PUBLIC PROCEDURE[] = BEGIN hasPad, hasNBuriedContact, hasMetal2, hasCMOS, hasNDepletion: BOOLEAN _ FALSE; UnmarkList: PROC[lp: listPtr] = BEGIN FOR p: listPtr _ lp, p.nxt WHILE p#NIL DO UnmarkObject[p.ob]; ENDLOOP; END; UnmarkObject: PROC[ob: obPtr] = BEGIN ob.marked _ FALSE; WITH dob: ob SELECT FROM cell => UnmarkList[dob.ptr]; ENDCASE => NULL; END; ScanListForLayers: PROC [lp: listPtr] = BEGIN FOR p: listPtr _ lp, p.nxt WHILE p#NIL DO ScanObjectForLayers[p.ob]; ENDLOOP; END; ScanObjectForLayers: PROC [ob: obPtr] = BEGIN IF NOT ob.marked THEN BEGIN ob.marked _ TRUE; WITH dob: ob SELECT FROM rect, wire => SELECT ob.l FROM imp => hasNDepletion _ TRUE; met2, cut2 => hasMetal2 _ TRUE; pdif, nwel => hasCMOS _ TRUE; bur => hasNBuriedContact _ TRUE; ovg => hasPad _ TRUE; ENDCASE => NULL; cont => SELECT dob.typ FROM burr => hasNBuriedContact _ TRUE; nwell, mPDif => hasCMOS _ TRUE; mmPDif => hasMetal2 _ hasCMOS _ TRUE; mmDif, mmPol, mmButt => hasMetal2 _ TRUE; ENDCASE => NULL; xstr => BEGIN IF dob.impl OR dob.pullup THEN hasNDepletion _ TRUE; IF dob.l = pdif THEN hasCMOS _ TRUE; END; cell => ScanListForLayers[dob.ptr]; ENDCASE => NULL; END; END; UnmarkList[masterList]; ScanListForLayers[masterList]; FOR mask: Masks IN Masks DO state: ReticleStatePtr _ @maskStates[mask]; state^ _ [ mask: mask, block: uz.NEW[CoordRectBlock], slice: NewFeaturePST[featureZ], cover: NewFeaturePST[featureZ], inReticleSet: (SELECT mask FROM pad => hasPad AND NOT HeSaysYes[IF hasMetal2 THEN "Merge pad mask with via mask?"L ELSE "Merge pad mask with cut mask?"L], nBuriedContact => hasNBuriedContact, via, metal2 => hasMetal2, nWell, nImplant, pImplant => hasCMOS, nDepletion => hasNDepletion, thinOx, poly, cut, metal => TRUE, ENDCASE => FALSE), fieldPolarity: (SELECT mask FROM thinOx, poly, metal, metal2 => transparent, ENDCASE => opaque) ]; ENDLOOP; SetStretches[]; Explain["Set non-standard stretches now if you wish."]; END; -- of InitMaskStates FinishMask: PUBLIC PROCEDURE[state: ReticleStatePtr, mask: Masks, showMasks: BOOLEAN, screenClip: CoordRect] = BEGIN OPEN ReticleBandFormat; deltaY: DeltaY = LAST[DeltaY]; BandBlock: TYPE = CARDINAL[0..100]; overflowRects: ARRAY BandBlock OF CARDINAL _ ALL[0]; overflowBandsInDeltaY: BandBlock = 1+ ((deltaY-2)/herald.bandHeight); ScaleToReticle: PROCEDURE[x: Coord] RETURNS[ReticleUnit] = INLINE {RETURN[InlineDefs.LowHalf[x/coordsPerReticle]]}; NextYMin: PROCEDURE[y: ReticleUnit] = BEGIN WHILE thisBand+herald.bandHeight<=y DO IF overflowRects[0]>0 THEN FOR b: BandBlock IN (0..overflowBandsInDeltaY) DO overflowRects[b-1] _ overflowRects[b]; ENDLOOP; overflowRects[overflowBandsInDeltaY-1] _ 0; thisBand _ thisBand+herald.bandHeight; [] _ WriteBlock[stream: reticleFile, address: @endObject, words: SIZE[EndObject]]; ENDLOOP; END; ClaimBands: PROCEDURE[y1, y2: ReticleUnit] RETURNS[midY: ReticleUnit] = BEGIN -- We would like to have this rectangle cover the interval from -- [y1..y2). Unfortunately two conditions could prevent this. -- The first is that that interval could be larger than DeltaY. -- The second is that we are only allowed to carry 1000 -- rectangles from one band to the next. b: BandBlock _ 0; NextYMin[y1]; y2 _ MIN[y2, y1+deltaY]; FOR midY _ thisBand+herald.bandHeight, midY+herald.bandHeight WHILE midY RecoverOriginalMasterList[]; IF showMasks THEN BEGIN p1: Point _ ScalePointToChipmonk[[x: screenClip.x1, y: screenClip.y1]]; p2: Point _ ScalePointToChipmonk[[x: screenClip.x2, y: screenClip.y2]]; masterList _ makeList[ p: makeCell[sx: p2.x-p1.x, sy: p2.y-p1.y, cnt: 0, ptr: NIL], x: p1.x, y: p1.y, o: 0, refl: 0]; masterList.selected _ TRUE; END; FOR i: LONG INTEGER DECREASING IN [0..state.rectCount) DO r: CoordRect; IF ((i+1) MOD RectsPerBlock)=0 THEN BEGIN block: CoordRectBlock; IF reticleRectFile=NIL THEN reticleRectFile _ NewWordStream[ TempFileName[name, mask], ReadWrite]; SetPosition[stream: reticleRectFile, pos: (i/RectsPerBlock)*2*SIZE[CoordRectBlock]]; -- pos is in bytes, first byte is 0 [] _ ReadBlock[stream: reticleRectFile, address: @block, words: SIZE[CoordRectBlock]]; state.block^ _ block; END; r _ state.block[InlineDefs.LowHalf[i MOD RectsPerBlock]]; WHILE CoordRectPQSize[pending]>0 AND r.x2<=CoordRectPQMin[pending].x2 DO WriteRect[ExtractCoordRectPQ[pending]]; ENDLOOP; WriteRect[r]; IF showMasks THEN WriteRectOnScreen[r]; ENDLOOP; WHILE CoordRectPQSize[pending]>0 DO WriteRect[ExtractCoordRectPQ[pending]]; ENDLOOP; IF showMasks THEN BEGIN dChange _ TRUE; Explain[levelNames[mask], "(clipped mask)"L]; END; END; RecoverOriginalMasterList[]; NextYMin[maxReticle.y]; [] _ WriteBlock[stream: reticleFile, address: @endObject, words: SIZE[EndObject]]; TruncateDiskStream[reticleFile]; IF reticleRectFile#NIL THEN BEGIN reticleRectFile.reset[reticleRectFile]; -- free up its disk space TruncateDiskStream[reticleRectFile]; reticleRectFile _ NIL; END; pending _ DestroyCoordRectPQ[pending]; END; -- of FinishMask WriteCoordRect: PUBLIC PROCEDURE[mask: Masks, r: CoordRect] = BEGIN -- called in order of increasing r.x2 state: ReticleStatePtr _ @maskStates[mask]; IF state.inReticleSet AND r.x10 AND r.x2 StartTransparentFeature[state: state, x: f.cover.x1, y: [f.cover.y1, f.cover.y2]]; ENDCASE => -- complemented polarity region StartOpaqueFeature[state: state, x: f.cover.x1, y: [f.cover.y1, f.cover.y2]]; END; END; InsertFeaturePST[p: state.slice, item: f]; END; -- of NoteFeature ForgetFeature: PUBLIC PROCEDURE[state: ReticleStatePtr, f: FeaturePtr] = BEGIN DeleteFeaturePST[p: state.slice, item: f]; IF NOT state.inReticleSet THEN RETURN; -- There are the same two possibilities here. IF state.fieldPolarity=opaque THEN FinishTransparentFeature[state: state, x: f.cover.x2, y: [f.cover.y1, f.cover.y2]] ELSE BEGIN CheckDesignBoundary[state: state, x: f.cover.x2]; SELECT TRUE FROM NOT state.designAreaStarted, state.designAreaFinished, f.cover.y2<=state.fieldRect.y1, state.fieldRect.y2<=f.cover.y1 => FinishTransparentFeature[state: state, x: f.cover.x2, y: [f.cover.y1, f.cover.y2]]; ENDCASE => -- complemented polarity region FinishOpaqueFeature[state: state, x: f.cover.x2, y: [f.cover.y1, f.cover.y2]]; END; END; -- of ForgetFeature CheckDesignBoundary: PROCEDURE[state: ReticleStatePtr, x: Coord] = BEGIN -- only for fieldPolarity=transparent IF state.fieldRect.x1<=x AND NOT state.designAreaStarted THEN BEGIN -- start complemented polarity region StartTransparentFeature[state: state, x: state.fieldRect.x1, y: [state.fieldRect.y1, state.fieldRect.y2]]; state.designAreaStarted _ TRUE; END; IF state.fieldRect.x2 minField.min _ int.max; int.max=y.max => minField.max _ int.min; ENDCASE => NULL; END; -- of ReduceField ClassifyFeaturePSTInterval[p: p, int: y, covered: ReduceField, gap: ReticleNullGap]; RETURN[minField]; END; -- of MinField TerminateCover: PROCEDURE[p: FeaturePSTHandle, x: Coord, y: Interval, mask: Masks] RETURNS[Interval] = BEGIN TouchedFeatureList: TYPE = LONG POINTER TO TouchedFeature _ NIL; TouchedFeature: TYPE = RECORD[ next: TouchedFeatureList, f: FeaturePtr]; list: TouchedFeatureList _ NIL; int: Interval _ y; TouchFeature: PROCEDURE[item: FeaturePtr] = BEGIN list _ uz.NEW[TouchedFeature _ [next: list, f: item]]; int _ [MIN[int.min, item.cover.y1], MAX[int.max, item.cover.y2]]; END; -- of TouchFeature SearchFeaturePST[p: p, int: y, touch: TouchFeature]; WHILE list#NIL DO t: TouchedFeatureList _ list.next; WriteCoordRect[mask: mask, r: [x1: list.f.cover.x1, x2: x, y1: list.f.cover.y1, y2: list.f.cover.y2]]; DeleteFeaturePST[p: p, item: list.f]; list.f _ ChipFeature.DestroyFeature[list.f]; uz.FREE[@list]; list _ t; ENDLOOP; RETURN[int]; END; -- of TerminateCover ReticleNullCover: PROCEDURE[int: Interval, repItem: FeaturePtr] = {NULL}; ReticleNullGap: PROCEDURE[int: Interval] = {NULL}; END. -- of ChipReticleImpl2