-- ChipReticleImpl.mesa -- A package to write files to drive the ISL/ICL ReticleMaker. -- last modified by E. McCreight, November 23, 1982 12:22 PM -- written by E. McCreight, March 19, 1982 1:28 PM DIRECTORY CellInstPQ, ChipExpand, ChipFeature, ChipNetDefs, ChipOrient, ChipReticle, ChipUserInt, ChipWire, FeaturePST, LeftFeaturePQ, ppdefs, ppMainDefs, ReticleBandFormat, RightFeaturePQ, SegmentDefs, StringDefs; ChipReticleImpl: PROGRAM IMPORTS CellInstPQ, ChipExpand, ChipFeature, ChipNetDefs, ChipOrient, ChipReticle, ChipUserInt, ChipWire, FeaturePST, LeftFeaturePQ, ppdefs, ppMainDefs, RightFeaturePQ, StringDefs EXPORTS ChipReticle SHARES ChipReticle = BEGIN OPEN ppdefs, ChipUserInt, ChipNetDefs, FeaturePST, ChipOrient, ChipReticle, LeftFeaturePQ; makingReticles: PUBLIC BOOLEAN ← FALSE; maskStates: PUBLIC ARRAY Masks OF ReticleState; reticleName: PUBLIC STRING ← NIL; herald: PUBLIC ReticleBandFormat.HeraldObject; reticleSize, reticleCenter: PUBLIC CoordPoint; reticleDesign, alignedDesign: PUBLIC CoordRect; ExtractReticles: PUBLIC PROCEDURE[univLp: listPtr] = BEGIN OPEN CellInstPQ, LeftFeaturePQ, RightFeaturePQ; -- Scan proceeds from left to right. univ: CoordRect ← [ x1: LAST[Coord], x2: FIRST[Coord], y1: LAST[Coord], y2: FIRST[Coord]]; leftFq: LeftFeaturePQHandle; rightFq: RightFeaturePQHandle; cq, deadcq: CellInstPQHandle; rootC: CellCallPtr; c: InstancePtr; lp: listPtr; topItemCount: CARDINAL ← 0; showMasks: BOOLEAN ← FALSE; screenClip: CoordRect ← [0,0,0,0]; fineResolution: STRING ← NIL; Action: TYPE = {enterCellItem, enterFeature, exitFeature, exitCell, none}; delay: ARRAY Action OF Coord ← [ enterCellItem: ScaleFromChipmonk[0], enterFeature: ScaleFromChipmonk[featureDelay], exitFeature: ScaleFromChipmonk[featureDelay], exitCell: ScaleFromChipmonk[3*featureDelay], none: ScaleFromChipmonk[0]]; ToDecimal: PROCEDURE[s: STRING, default: INTEGER] RETURNS[result: INTEGER] = BEGIN IF s=NIL OR s.length=0 THEN GOTO UseDefault; result ← StringDefs.StringToDecimal[s: s ! StringDefs.InvalidNumber => GOTO UseDefault]; EXITS UseDefault => result ← default; END; SelectNext: PROCEDURE RETURNS [next: Action] = BEGIN x: Coord; next ← none; IF CellInstPQSize[cq]>0 THEN {next ← enterCellItem; x ← CellInstPQMin[cq].x}; IF LeftFeaturePQSize[leftFq]>0 AND (LeftFeaturePQMin[leftFq].cover.x1+delay[enterFeature]< x+delay[next] OR next=none) THEN BEGIN next ← enterFeature; x ← LeftFeaturePQMin[leftFq].cover.x1 END; IF RightFeaturePQSize[rightFq]>0 AND (RightFeaturePQMin[rightFq].cover.x2+delay[exitFeature]< x+delay[next] OR next=none) THEN BEGIN next ← exitFeature; x ← RightFeaturePQMin[rightFq].cover.x2 END; IF CellInstPQSize[deadcq]>0 AND (CellInstPQMin[deadcq].x+delay[exitCell]< x+delay[next] OR next=none) THEN {next ← exitCell; x ← CellInstPQMin[deadcq].x}; END; designSize: CoordPoint; IF univLp=NIL THEN RETURN; -- empty design makingReticles ← TRUE; reticleName ← ChipUserInt.RequestString["Prefix of reticle file names:"L]; IF reticleName=NIL OR reticleName.length=0 THEN reticleName ← newString[ppMainDefs.fileName]; reticleName ← ChipUserInt.FixExtension[reticleName, ""]; herald ← ReticleBandFormat.ReticleMakerHerald; herald.bandWidth ← 2*(herald.bandWidth/2); -- in case some silly interface writer thinks that the -- Alto can handle scan lines consisting of an -- odd number of words. Explain["Select an instance of every cell that is"L, "an ICL test structure in fine-resolution co-ordinates"L]; fineResolution ← RequestString[ "How many nanometers is a fine resolution lambda?"L, "(default is 500 nm)"L]; coordScale[absolute] ← ToDecimal[s: fineResolution, default: 500]/2; IF fineResolution#NIL THEN {FreeString[fineResolution]; fineResolution ← NIL}; FOR lpp: listPtr ← univLp, lpp.nxt WHILE lpp#NIL DO r: CoordRect ← univ; WITH ob: lpp.ob SELECT FROM cell => BEGIN c: ProtoPtr ← ChipExpand.MakeProto[ob: @ob, locNumScale: (IF lpp.selected THEN absolute ELSE lambdaRelative)]; univ ← [ x1: MIN[r.x1, ScaleFromChipmonk[lpp.lx]], x2: MAX[r.x2, ScaleFromChipmonk[lpp.lx]+ CoordSize[size: c.size, orient: lpp.idx].x], y1: MIN[r.y1, ScaleFromChipmonk[lpp.ly]], y2: MAX[r.y2, ScaleFromChipmonk[lpp.ly]+ CoordSize[size: c.size, orient: lpp.idx].y]]; END; ENDCASE => univ ← [ x1: MIN[r.x1, ScaleFromChipmonk[lpp.lx]], x2: MAX[r.x2, ScaleFromChipmonk[lpp.lx+ ob.size[Rot90[lpp.idx]]]], y1: MIN[r.y1, ScaleFromChipmonk[lpp.ly]], y2: MAX[r.y2, ScaleFromChipmonk[lpp.ly+ ob.size[1-Rot90[lpp.idx]]]]]; topItemCount ← topItemCount+1; ENDLOOP; rightFq ← NewRightFeaturePQ[uz]; leftFq ← NewLeftFeaturePQ[uz]; cq ← NewCellInstPQ[uz]; deadcq ← NewCellInstPQ[uz]; reticleSize ← [ x: coordsPerReticle*16*herald.bandWidth, y: coordsPerReticle*herald.bandCount*herald.bandHeight]; reticleCenter ← [x: reticleSize.x/2, y: reticleSize.y/2]; designSize ← [ x: univ.x2-univ.x1, y: univ.y2-univ.y1]; reticleDesign ← [ x1: reticleCenter.x-designSize.x/2, x2: (reticleCenter.x-designSize.x/2)+designSize.x, y1: reticleCenter.y-designSize.y/2, y2: (reticleCenter.y-designSize.y/2)+designSize.y]; deltaOrigin ← [ x: univ.x1-reticleDesign.x1, y: univ.y1-reticleDesign.y1]; InitMaskStates[]; CircumscribeAndBeyond[q: leftFq, design: reticleDesign]; rootC ← instanceZ.NEW[cell Instance ← [min: ScalePointFromChipmonk[[x: 0, y: 0]], proto: ChipExpand.MakeProto[ ob: uz.NEW[cell object ← [p: NIL, size: [ScaleToChipmonk[univ.x2-univ.x1], ScaleToChipmonk[univ.y2-univ.y1], ScaleToChipmonk[univ.x2-univ.x1]], refCnt: 1, l: snerd, -- if anybody uses this, he's in trouble returnable: FALSE, marked: FALSE, varpart: cell[cnt: topItemCount, ptr: univLp]]], name: "Design"], caller: [NIL, 0], nets: cell[] ]]; ColorOff[]; [] ← ChipExpand.ProtoSeq[rootC]; InsertCellInstPQ[p: cq, item: [reticleDesign.x1, [rootC, 0]]]; InsertCellInstPQ[p: deadcq, item: [reticleDesign.x2, [rootC, 0]]]; currentX ← FIRST[Coord]; DO SELECT SelectNext[] FROM enterCellItem => BEGIN -- enter a new item from a cell lps: ListPtrSeqPtr; globalR: CoordRect; cir: ItemRef; idx: CellIndex; cqi: CellInstPt ← ExtractCellInstPQ[cq]; [-- x: currentX, -- call: cir] ← cqi; [head: c, idx: idx] ← cir; lps ← c.proto.seq[orientToSortClass[c.orient]]; lp ← lps[idx]; IF notingMark THEN BEGIN globalR ← ItemInWorld[cir]; ChipFeature.NoteMark[globalR, "New cell at lp↑ contains mark."]; END; ChipExpand.MakeInstance[item: [c, idx], slice: NIL, futureFeatures: leftFq, presentFeatures: rightFq, cellQ: cq, deadCellQ: deadcq]; END; enterFeature => BEGIN f: FeaturePtr ← ExtractLeftFeaturePQ[leftFq]; IF f.cover.x1>=currentX THEN currentX ← f.cover.x1 ELSE DebugAtPoint[ScalePointToChipmonk[ [x: f.cover.x1, y: f.cover.y1]], "Scan went backward"L]; ChipFeature.BWCursor[world: [x: f.cover.x1, y: f.cover.y1]]; IF notingMark THEN ChipFeature.NoteMark[f.cover, "New feature at f↑ contains mark."L]; SELECT f.lev FROM unknown => -- codes text to appear on all reticles FOR mask: Masks IN Masks DO IF mask#unknown AND maskStates[mask].inReticleSet THEN [] ← NewReticleFeature[cover: f.cover, mask: mask, lq: leftFq]; ENDLOOP; pad => BEGIN NoteFeature[state: @maskStates[(SELECT TRUE FROM maskStates[pad].inReticleSet => pad, maskStates[via].inReticleSet => via, ENDCASE => cut)], f: f]; END; nWell => BEGIN NoteFeature[state: @maskStates[nWell], f: f]; CheckOverlapInDesign[p: maskStates[pWell].slice, f: f, problem: "Diffusion too close to well boundary"L]; END; pWell => BEGIN NoteFeature[state: @maskStates[pWell], f: f]; CheckOverlapInDesign[p: maskStates[nWell].slice, f: f, problem: "Diffusion too close to well boundary"L]; END; nImplant => BEGIN NoteFeature[state: @maskStates[nImplant], f: f]; CheckOverlapInDesign[p: maskStates[pImplant].slice, f: f, problem: "p/n diffusions too close"L]; END; pImplant => BEGIN NoteFeature[state: @maskStates[pImplant], f: f]; CheckOverlapInDesign[p: maskStates[nImplant].slice, f: f, problem: "p/n diffusions too close"L]; END; nPlus => NoteFeature[state: @maskStates[thinOx], f: f]; pPlus => NoteFeature[state: @maskStates[thinOx], f: f]; ENDCASE => NoteFeature[state: @maskStates[f.lev], f: f]; RightFeaturePQ.InsertRightFeaturePQ[rightFq, f]; END; exitFeature => BEGIN f: FeaturePtr ← ExtractRightFeaturePQ[rightFq]; IF f.cover.x2>=currentX THEN currentX ← f.cover.x2 ELSE DebugAtPoint[ScalePointToChipmonk[ [x: f.cover.x2, y: f.cover.y1]], "Scan went backward"L]; IF notingMark THEN ChipFeature.NoteMark[f.cover, "Old feature at f↑ contains mark."L]; SELECT f.lev FROM unknown => NULL; nPlus => ForgetFeature[state: @maskStates[thinOx], f: f]; pPlus => ForgetFeature[state: @maskStates[thinOx], f: f]; pad => ForgetFeature[state: @maskStates[(SELECT TRUE FROM maskStates[pad].inReticleSet => pad, maskStates[via].inReticleSet => via, ENDCASE => cut)], f: f]; ENDCASE => ForgetFeature[state: @maskStates[f.lev], f: f]; f ← ChipFeature.DestroyFeature[f]; END; exitCell => BEGIN globalR: CoordRect; cqi: CellInstPt ← ExtractCellInstPQ[deadcq]; [-- x: currentX, -- call: [head: c]] ← cqi; IF notingMark THEN BEGIN globalR ← IF c.caller.head#NIL THEN ItemInWorld[c.caller] ELSE [x1: rootC.min.x, y1: rootC.min.y, x2: rootC.min.x, y2: rootC.min.y]; ChipFeature.NoteMark[globalR, "Leaving cell at c↑ containing mark."]; END; ChipExpand.ExitInstance[c]; END; ENDCASE => EXIT; ENDLOOP; cq ← DestroyCellInstPQ[cq]; leftFq ← DestroyLeftFeaturePQ[leftFq]; rightFq ← DestroyRightFeaturePQ[rightFq]; IF (showMasks ← HeSetsParamsAndSaysYes["Shall I show masks on the screen?"L]) THEN BEGIN p1, p2: CoordPoint; Explain["Mark one corner of clip rectangle."L]; p1 ← ScalePointFromChipmonk[markPnt]; Explain["Now mark diagonally opposite corner."L]; p2 ← ScalePointFromChipmonk[markPnt]; screenClip ← [x1: MIN[p1.x, p2.x], y1: MIN[p1.y, p2.y], x2: MAX[p1.x, p2.x], y2: MAX[p1.y, p2.y]]; END; FOR mask: Masks IN Masks DO state: ReticleStatePtr ← @maskStates[mask]; IF state.inReticleSet AND state.rectCount>0 THEN FinishMask[state, mask, showMasks, screenClip]; uz.FREE[@state.block]; state.slice ← DestroyFeaturePST[state.slice]; state.cover ← DestroyFeaturePST[state.cover]; ENDLOOP; IF reticleName#NIL THEN {FreeString[reticleName]; reticleName ← NIL}; ColorOn[]; END; -- of ExtractReticles CheckOverlapInDesign: PROCEDURE[p: FeaturePSTHandle, f: FeaturePtr, problem: STRING] = BEGIN SayProblem: PROCEDURE[r: CoordRect] = {RemarkAtPoint[p: RefCoordPt[r], s: problem]}; IF reticleDesign.x1<=f.cover.x1 AND f.cover.x2<=reticleDesign.x2 AND reticleDesign.y1<=f.cover.y1 AND f.cover.y2<=reticleDesign.y2 THEN ChipWire.OverlapIsViolation[p: p, f: f, problem: SayProblem]; END; -- of CheckOverlapInDesign CoordBox: PUBLIC PROCEDURE[center, diameter: CoordPoint, offset: CoordPoint ← [0,0]] RETURNS[CoordRect] = BEGIN origin: CoordPoint ← [x: center.x+offset.x, y: center.y+offset.y]; RETURN[[x1: (2*origin.x-diameter.x)/2, x2: (2*origin.x+diameter.x)/2, y1: (2*origin.y-diameter.y)/2, y2: (2*origin.y+diameter.y)/2]]; END; -- of CoordBox NewReticleFeature: PUBLIC PROCEDURE[cover: CoordRect, mask: Masks, lq: LeftFeaturePQHandle ← NIL] RETURNS[FeaturePtr] = {RETURN[IF mask=unknown -- codes for all masks -- OR maskStates[mask].inReticleSet THEN ChipFeature.NewFeature[cover: cover, lev: mask, lq: lq] ELSE NIL]}; END. -- of ChipReticleImpl