-- 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