-- File CIFDrcNMOS.mesa
-- Written by Dan Fitzpatrick and Martin Newell, August 1980
-- Last updated: November 5, 1981 7:11 PM
DIRECTORY
CIFIODefs: FROM "CIFIODefs" USING [WriteLongDecimal, PutReal, PutShort, PutLong],
CIFDrcErrorDefs: FROM "CIFDrcErrorDefs" USING [ErrorPass],
CIFDrcNewListDefs: FROM "CIFDrcNewListDefs" USING [InitList,InsertTrap,StepSwaths,GenSwath,GetSwath,GenLocal, GetLocal,SwathType,ListDescriptor],
CIFDrcNMOSDefs: FROM "CIFDrcNMOSDefs",
CIFDrcUtilsDefs: FROM "CIFDrcUtilsDefs" USING [InitUtils, Edge, Trapezoid, TrapType, CopyEdge, MakeEdge, MakeTrap, FreeEdge, FreeTrap, XatY, Tag, CopyTrap],
CIFUtilitiesDefs: FROM "CIFUtilitiesDefs" USING [MoveCursorTo],
IODefs: FROM "IODefs" USING [WriteString, WriteLine, WriteDecimal],
MergeDefs: FROM "MergeDefs" USING [InitMerge, FinishMerge, GenMergeValue, Merge, MergeValue],
-- MiscDefs: FROM "MiscDefs" USING [CallDebugger],
Real: FROM "Real" USING [Fix],
SegmentDefs: FROM "SegmentDefs" USING [Write, Append],
StreamDefs: FROM "StreamDefs" USING [DiskHandle, NewByteStream],
SystemDefs: FROM "SystemDefs" USING [AllocateHeapNode, FreeHeapNode];
CIFDrcNMOS: PROGRAM
IMPORTS CIFDrcErrorDefs, CIFDrcNewListDefs, CIFDrcUtilsDefs, CIFIODefs, CIFUtilitiesDefs, IODefs, MergeDefs, Real, StreamDefs, SystemDefs
EXPORTS CIFDrcNMOSDefs =
BEGIN OPEN CIFIODefs, CIFDrcErrorDefs, CIFDrcNewListDefs, CIFDrcUtilsDefs, CIFUtilitiesDefs, IODefs, MergeDefs, Real, SegmentDefs, StreamDefs, SystemDefs;
InitDrcNMOS: PUBLIC PROCEDURE [baseName:STRING, lamda: REAL, left,bottom,right,top:REAL] =
BEGIN
InitUtils[];
InitList[Fix[left],Fix[right+1]];
InitMerge["Merge.tmp$"];
-- Open Error File
BaseFileName ← baseName;
errorFile ← NewByteStream[Tag[BaseFileName,"tmp$"], Write+Append];
errorFile.reset[errorFile];
PutShort[ErrorPassword,errorFile];
Lamda ← lamda;
Seperation ← 3*lamda;
YNext ← YCurr ← YPrev ← YBot ← bottom;
diffList ← NIL;
xCursor ← (left+right)/2;
-- Set up layer dependent width and seperation rules
MinWidth[implant] ← 3*Lamda;
MinWidth[diff] ← 2*Lamda;
MinWidth[poly] ← 2*Lamda;
MinWidth[cut] ← 2*Lamda;
MinWidth[metal] ← 3*Lamda;
MinWidth[trans] ← Lamda;
MinSep[implant] ← 1;
MinSep[diff] ← 3*Lamda;
MinSep[poly] ← 2*Lamda;
MinSep[cut] ← 2*Lamda;
MinSep[metal] ← 3*Lamda;
MinSep[trans] ← 1;
END;
FinishDrcNMOS: PUBLIC PROCEDURE =
BEGIN
-- Release all the remaining trapezoids
StepSwaths[];StepSwaths[];StepSwaths[];
errorFile.destroy[errorFile];-- Close error file for writing
-- Finished scanning chip; procede to error output phase
ErrorPass[BaseFileName];
FinishMerge[];
END;
NewSwath: PUBLIC PROCEDURE [prev,curr: REAL] =
BEGIN
-- NewSwath is called just before sending trapezoids in a new 3 Lambda high swath
-- The 3 previous swaths have been saved.
-- trapezoids in the middle swath are checked, knowing a local area of 3 lambda
-- in each direction.
-- After this swath has been checked the trapezoids in the oldest swath is thrown away.
i: CARDINAL;
trap,next,diffTrap,polyTrap,transTrap,outside: Trapezoid;
polyList,list:ListDescriptor;
outside ← NIL;
IF prev < YNext THEN Break["repeating a swath"];
-- Put diffusion traps in list only after all the poly for this swath has entered
-- Breaking diffusion and creating transistors
DO
IF outside # NIL THEN {
diffTrap ← outside;
outside ← outside.front
}
ELSE IF diffList # NIL THEN {
diffTrap ← diffList;
diffList ← diffList.front;
}
ELSE EXIT;
FOR polyTrap ← GenLocal[diffTrap.minx,diffTrap.maxx,poly,@polyList],
GetLocal[@polyList] UNTIL polyTrap = NIL DO
IF polyTrap.type = mask THEN BEGIN
[transTrap,outside] ← Clip[diffTrap,polyTrap,outside];
IF transTrap # NIL THEN BEGIN
-- Make a transistor
-- create a sanctuary region of 1 Lambda about
-- it where diffusion and poly may overlap.
InsertTrap[transTrap,trans,top];
MakeOverlapTrap[transTrap.left,transTrap.right,transTrap.miny, transTrap.maxy,Lamda,diff,sanctuary];
EXIT;
END
ELSE BEGIN
diffTrap ← outside;
outside ← outside.front;-- Remove diffTrap from list
END;
END;
REPEAT
FINISHED => BEGIN
-- Insert diffusion only after all the transistors have been found
InsertTrap[diffTrap,diff,top];
END;
ENDLOOP;
ENDLOOP;
YCurr ← prev;
YNext ← curr;
IF YCurr - Seperation < YPrev THEN RETURN;-- do nothing; not a full swath
MoveCursorTo[xCursor,YCurr];
-- diffusion and transistor trapezoids are in place for top swath
-- propagate node numbers for top swath
FOR i IN [0..trans] DO
FOR trap ← GenSwath[i,top,@list],next UNTIL trap = NIL DO
next ← GetSwath[@list];
IF trap.type = mask AND trap.miny >= YPrev-1 THEN Propagate[trap,i];
IF trap.type = mask AND trap.number = NIL THEN Break["trap did not get node number"];
ENDLOOP;
ENDLOOP;
-- Propagate across layers when there is a contact cut
FOR trap ← GenSwath[cut,top,@list],GetSwath[@list] UNTIL trap = NIL DO
PropagateByCut[trap];
ENDLOOP;
-- now test design rules for middle swath
FOR i IN [0..trans] DO
FOR trap ← GenSwath[i,middle,@list],next UNTIL trap = NIL DO
next ← GetSwath[@list];
IF trap.miny = trap.maxy THEN LOOP;-- don’t worry about these guys
IF trap.type # mask OR YPrev <= trap.miny OR trap.maxy <= YBot THEN LOOP;
CheckBottomEdge[trap,i];
MakeMinWidthTrap[trap.left,trap.miny,trap.maxy,i];
MakeMinSepTrap[trap.right,trap.miny,trap.maxy,i,trap.number];
-- layer dependent rules follow
SELECT i FROM
poly => BEGIN
MakeOverlapTrap[trap.left,trap.right,trap.miny,trap.maxy,Lamda, diff,exclusion,trap.number];
END;
cut => BEGIN
MakeOverlapTrap[trap.left,trap.right,trap.miny,trap.maxy,Lamda, metal,inclusion];
END;
ENDCASE;
ENDLOOP;
ENDLOOP;
-- Remove trapezoids out of range of new swath
StepSwaths[];
YBot ← YPrev;YPrev ← YCurr;
END;
CheckTrap: PUBLIC PROCEDURE[left,right:Edge, start,end:REAL, layer:CARDINAL] =
BEGIN
trap:Trapezoid;
-- Create a trapezoid
trap ← MakeTrap[left,right,start,end,layer,mask];
IF trap = NIL THEN RETURN;
-- Hold off on diffusion till all the poly’s have been read in
IF layer = diff THEN {
trap.front ← diffList;
diffList ← trap;
RETURN;
};
InsertTrap[trap,layer,top];
END;
MakeMinWidthTrap:PUBLIC PROCEDURE [left:Edge, miny, maxy:REAL, layer:CARDINAL] =
BEGIN
trap: Trapezoid;
right: Edge;
right ← MakeEdge[XatY[left,miny]+MinWidth[layer],miny,XatY[left,maxy]+MinWidth[layer], maxy,FALSE];
trap ← MakeTrap[left,right,miny,maxy,layer,inclusion];
PlaceInclusion[trap,layer];
FreeEdge[right];
END;
CreateUpMinWidth:PROCEDURE [yloc,minx,maxx:REAL,roundLeft,roundRight:BOOLEAN, layer:CARDINAL] =
BEGIN
newTrap: Trapezoid;
left, right: Edge;
IF minx >= maxx THEN RETURN;-- ignore 0 width traps
left ← MakeEdge[minx,yloc,minx,yloc+MinWidth[layer],TRUE];
right ← MakeEdge[maxx,yloc,maxx,yloc+MinWidth[layer],FALSE];
newTrap ← MakeTrap[left,right,yloc,yloc+MinWidth[layer],layer,inclusion];
PlaceInclusion[newTrap,layer];
IF roundLeft THEN BEGIN-- left corner is rounded
leftCorner: Edge;
leftCorner ← MakeEdge[minx-MinWidth[layer],yloc,minx-MinWidth[layer], yloc+MinWidth[layer],TRUE];
left ← CopyEdge[left];
newTrap ← MakeTrap[leftCorner,left,yloc,yloc+MinWidth[layer],layer,inclusion];
PlaceInclusion[newTrap,layer];
FreeEdge[leftCorner];FreeEdge[left];
END;
IF roundRight THEN BEGIN-- right corner is rounded
rightCorner: Edge;
right ← CopyEdge[right];
rightCorner ← MakeEdge[maxx+MinWidth[layer],yloc,maxx+MinWidth[layer], yloc+MinWidth[layer], TRUE];
newTrap ← MakeTrap[right,rightCorner,yloc,yloc+MinWidth[layer],layer,inclusion];
PlaceInclusion[newTrap,layer];
FreeEdge[right];FreeEdge[rightCorner];
END;
FreeEdge[left];FreeEdge[right];
END;
MakeMinSepTrap:PUBLIC PROCEDURE [left:Edge,miny,maxy:REAL,layer:CARDINAL,number:MergeValue] =
BEGIN
trap: Trapezoid;
right: Edge;
right ← MakeEdge[XatY[left,miny]+MinSep[layer],miny,XatY[left,maxy]+MinSep[layer], maxy,FALSE];
trap ← MakeTrap[left,right,miny,maxy,layer,exclusion];
trap.number ← number;
PlaceExclusion[trap,layer];
FreeEdge[right];
END;
CreateDownMinSep:PROCEDURE [yloc,minx,maxx:REAL,strLeft,strRight:BOOLEAN,layer:CARDINAL, number:MergeValue] =
BEGIN
newTrap: Trapezoid;
left, right: Edge;
IF minx = maxx THEN RETURN;-- ignore 0 width traps
left ← MakeEdge[minx,yloc-MinSep[layer],minx,yloc,TRUE];
right ← MakeEdge[maxx,yloc-MinSep[layer],maxx,yloc,FALSE];
newTrap ← MakeTrap[left,right,yloc-MinSep[layer],yloc,layer,exclusion];
newTrap.number ← number;
PlaceExclusion[newTrap,layer];
IF NOT strLeft THEN BEGIN-- left corner is rounded
leftCorner: Edge;
leftCorner ← MakeEdge[minx-MinSep[layer],yloc-MinSep[layer],minx-MinSep[layer],yloc,TRUE];
left ← CopyEdge[left];
newTrap ← MakeTrap[leftCorner,left,yloc-MinSep[layer],yloc,layer,exclusion];
newTrap.number ← number;
PlaceExclusion[newTrap,layer];
FreeEdge[leftCorner];FreeEdge[left];
END;
IF NOT strRight THEN BEGIN-- right corner is rounded
rightCorner: Edge;
right ← CopyEdge[right];
rightCorner ← MakeEdge[maxx+MinSep[layer],yloc-MinSep[layer], maxx+MinSep[layer],yloc,TRUE];
newTrap ← MakeTrap[right,rightCorner,yloc-MinSep[layer],yloc,layer,exclusion];
newTrap.number ← number;
PlaceExclusion[newTrap,layer];
FreeEdge[right];FreeEdge[rightCorner];
END;
FreeEdge[left];FreeEdge[right];
END;
MakeOverlapTrap:PROCEDURE [left,right:Edge,miny,maxy,amount:REAL,layer:CARDINAL, type:TrapType, number:MergeValue ← NIL] =
BEGIN
newLeft,newRight: Edge;
trap: Trapezoid;
miny ← miny - amount;
maxy ← maxy + amount;
newLeft ← MakeEdge[XatY[left,miny]-amount,miny,XatY[left,maxy]-amount, maxy,TRUE];
newRight ← MakeEdge[XatY[right,miny]+amount,miny,XatY[right,maxy]+amount, maxy,FALSE];
trap ← MakeTrap[newLeft,newRight,miny,maxy,layer,type];
trap.number ← number;
FreeEdge[newLeft];FreeEdge[newRight];
SELECT type FROM
exclusion => PlaceExclusion[trap,layer];
inclusion => PlaceInclusion[trap,layer];
sanctuary => PlaceSanctuary[trap,layer];
ENDCASE;
END;
Intersect:PROCEDURE [trap1,trap2:Trapezoid] RETURNS[p: BOOLEAN] =
BEGIN
RETURN[NOT (trap1.maxy <= trap2.miny OR trap2.maxy <= trap1.miny OR
trap1.maxx <= trap2.minx OR trap2.maxx <= trap1.minx)];
END;
PropagateByCut:PROCEDURE [cut:Trapezoid] =
BEGIN
first,trap:Trapezoid;
list:ListDescriptor;
first ← NIL;
FOR trap ← GenLocal[cut.minx,cut.maxx,metal,@list],GetLocal[@list]
UNTIL trap = NIL OR first # NIL DO
IF trap.type = mask AND Intersect[cut,trap] THEN first ← trap;
ENDLOOP;
-- first should be the only metal over the cut; if not other checks will report an error
-- if first is nil there is no metal; return
IF first = NIL THEN RETURN;
-- now propagate first’s node number to any intersecting poly, diff, or transistor
FOR trap ← GenLocal[cut.minx,cut.maxx,poly,@list],GetLocal[@list]
UNTIL trap = NIL DO
IF trap.type = mask AND Intersect[cut,trap] THEN Combine[trap,first];
ENDLOOP;
FOR trap ← GenLocal[cut.minx,cut.maxx,diff,@list],GetLocal[@list]
UNTIL trap = NIL DO
IF trap.type = mask AND Intersect[cut,trap] THEN Combine[trap,first];
ENDLOOP;
FOR trap ← GenLocal[cut.minx,cut.maxx,trans,@list],GetLocal[@list]
UNTIL trap = NIL DO
IF trap.type = mask AND Intersect[cut,trap] THEN Combine[trap,first];
ENDLOOP;
END;
Propagate:PROCEDURE [trap: Trapezoid, layer:CARDINAL] =
BEGIN
-- propagate node numbers from below
-- also this procedure creates upward pointing inclusion boxes
ptr: Trapezoid;
list:ListDescriptor;
FOR ptr ← GenLocal[trap.minx,trap.maxx,layer,@list],GetLocal[@list]
UNTIL ptr = NIL DO-- check if we have seen all possible propagation traps
IF ptr.type = mask AND ptr.maxy = trap.miny THEN BEGIN
-- This depends on mask geometry entering list sorted on ascending maxy
-- and on no overlapping trapezoids
-- Same layer, both masks, one right under the other; check for propagation
IF XatY[trap.left,trap.miny] < XatY[ptr.right,trap.miny] AND
XatY[ptr.left,trap.miny] < XatY[trap.right,trap.miny] THEN Combine[trap,ptr];
END;
ENDLOOP;
IF trap.number = NIL THEN BEGIN
trap.number ← GenMergeValue[];
IF PrintMerge THEN BEGIN
WriteString["Merge "]; WriteLongDecimal[LOOPHOLE[trap.number]];
WriteString[" on "]; WriteDecimal[trap.layer];
WriteLine[""];
END;
END;
END;
CheckBottomEdge:PROCEDURE [trap: Trapezoid, layer:CARDINAL] =
BEGIN
-- this procedure creates upward pointing inclusion boxes
-- and downward pointing exclusion boxes
ptr: Trapezoid;
list:ListDescriptor;
Segment: TYPE = POINTER TO SegmentRecord;
SegmentRecord: TYPE = RECORD [
next: Segment,
left: REAL,
right: REAL,
lcorner: BOOLEAN,
rcorner: BOOLEAN,
active: BOOLEAN
];
MakeSegment: PROCEDURE [left,right:REAL,lcorner,rcorner:BOOLEAN, next:Segment] RETURNS [seg:Segment] =
BEGIN
-- IF left = right THEN CallDebugger["tried to make 0 sized segment"];
IF left + 0.01 > right THEN RETURN[next];-- floating pt error
seg ← AllocateHeapNode[SIZE[SegmentRecord]];
seg↑ ← [
next: next,
left: left,
right: right,
lcorner:lcorner,
rcorner:rcorner,
active:TRUE-- new segments are all active
];
END; -- of MakeSegment
-- want to find what part of this trapezoid has no geometry immediately
-- underneath it, the segment list indicates these parts
-- as far as we know now no geometry is underneath the trap
segList: Segment ← MakeSegment[trap.minx,trap.maxx,FALSE,FALSE,NIL];
next: Segment;
IF trap.type # mask THEN Break["trap has wrong type in Check Bottom Edge"];
FOR ptr ← GenLocal[trap.minx,trap.maxx,layer,@list],GetLocal[@list]
UNTIL ptr = NIL DO-- check if we have seen all possible propagation traps
IF ptr.type = mask AND ptr.maxy = trap.miny THEN {
-- This depends and on no overlapping trapezoids
-- Same layer, both masks, one right under the other; check for propagation
lSide: REAL ← XatY[ptr.left,trap.miny];
rSide: REAL ← XatY[ptr.right,trap.miny];
IF XatY[trap.left,trap.miny] < rSide AND
lSide < XatY[trap.right,trap.miny] THEN {
-- ptr is immediately underneath trap
FOR seg:Segment ← segList,next UNTIL seg=NIL DO
-- Find a segment which overlaps this trapezoid
next ← seg.next;
IF seg.active AND lSide < seg.right AND
seg.left < rSide THEN {
-- this segment intersects
IF seg.left < lSide THEN
segList←MakeSegment[seg.left,lSide,seg.lcorner,TRUE, segList];
IF rSide < seg.right THEN
segList←MakeSegment[rSide,seg.right,TRUE,seg.rcorner, segList];
seg.active ← FALSE;
}
ENDLOOP;
};
};
ENDLOOP;
FOR seg:Segment ← segList,next UNTIL seg=NIL DO
next ← seg.next;
IF seg.active THEN {
CreateUpMinWidth[trap.miny,seg.left,seg.right,seg.lcorner,
seg.rcorner,layer];
CreateDownMinSep[trap.miny,seg.left,seg.right,seg.lcorner,
seg.rcorner,layer,trap.number];
};
FreeHeapNode[seg];
ENDLOOP;
END;
Clip:PROCEDURE [trap,ptr,outsideList:Trapezoid] RETURNS[inside,outside:Trapezoid] =
BEGIN
-- clip trap against ptr, add all trapezoids found outside ptr to outsideList
-- return the inside trapezoid as inside
tempTrap: Trapezoid;
tempEdge:Edge;
IF trap.maxy <= ptr.miny OR ptr.maxy <= trap.miny OR
trap.maxx <= ptr.minx OR ptr.maxx <= trap.minx THEN BEGIN
trap.front ← outsideList;
RETURN[inside ← NIL,outside ← trap];
END;
-- ptr and trap must intersect; clip trap against ptr
inside ← trap; outside←outsideList;
IF inside.miny < ptr.miny THEN BEGIN --clip against miny plane
tempTrap ← MakeTrap[inside.left,inside.right,inside.miny,ptr.miny,inside.layer, inside.type];
tempTrap.number ← inside.number;
tempTrap.front ← outside; outside ← tempTrap;
tempTrap ← MakeTrap[inside.left,inside.right,ptr.miny,inside.maxy,inside.layer, inside.type];
tempTrap.number ← inside.number;
FreeTrap[inside];
inside ← tempTrap;
END;
IF ptr.maxy < inside.maxy THEN BEGIN --clip against maxy plane
tempTrap ← MakeTrap[inside.left,inside.right,ptr.maxy,inside.maxy,inside.layer, inside.type];
tempTrap.number ← inside.number;
tempTrap.front ← outside; outside ← tempTrap;
tempTrap ← MakeTrap[inside.left,inside.right,inside.miny,ptr.maxy,inside.layer, inside.type];
tempTrap.number ← inside.number;
FreeTrap[inside];
inside ← tempTrap;
END;
IF inside.minx < ptr.minx THEN BEGIN --clip against minx plane
tempEdge ← MakeEdge[ptr.minx,inside.miny,ptr.minx,inside.maxy,TRUE];
tempTrap ← MakeTrap[inside.left,tempEdge,inside.miny,inside.maxy,inside.layer, inside.type];
tempTrap.number ← inside.number;
tempTrap.front ← outside; outside ← tempTrap;
tempTrap ← MakeTrap[tempEdge,inside.right,inside.miny,inside.maxy,inside.layer, inside.type];
tempTrap.number ← inside.number;
FreeTrap[inside];
inside ← tempTrap;
FreeEdge[tempEdge];
END;
IF ptr.maxx < inside.maxx THEN BEGIN --clip against maxx plane
tempEdge ← MakeEdge[ptr.maxx,inside.miny,ptr.maxx,inside.maxy,TRUE];
tempTrap ← MakeTrap[tempEdge,inside.right,inside.miny,inside.maxy,inside.layer, inside.type];
tempTrap.number ← inside.number;
tempTrap.front ← outside; outside ← tempTrap;
tempTrap ← MakeTrap[inside.left,tempEdge,inside.miny,inside.maxy,inside.layer, inside.type];
tempTrap.number ← inside.number;
FreeTrap[inside];
inside ← tempTrap;
FreeEdge[tempEdge];
END;
END;
Combine:PROCEDURE [trap1,trap2: Trapezoid] =
BEGIN
-- trap1 and trap2 are electrically equivalent
-- make there node numbers equivalent
SELECT TRUE FROM
trap1.number = NIL AND trap2.number = NIL => trap1.number ← trap2.number ← GenMergeValue[];
trap1.number = NIL => trap1.number ← trap2.number;
trap2.number = NIL => trap2.number ← trap1.number;
ENDCASE => BEGIN
IF PrintMerge THEN BEGIN
WriteLongDecimal[LOOPHOLE[trap1.number]]; WriteString[" ← "];
WriteLongDecimal[LOOPHOLE[trap2.number]]; WriteLine[""];
END;
trap1.number ← Merge[trap1.number,trap2.number];
END;
END;
PlaceInclusion:PROCEDURE [trap:Trapezoid, layer:CARDINAL] =
BEGIN
ptr,inside,outsideList,next,temp,inclList: Trapezoid;
list:ListDescriptor;
IF trap = NIL THEN RETURN;
IF trap.type # inclusion THEN Break["non incl in place incl"];
trap.front ← NIL;
outsideList ← trap;
FOR ptr ← GenLocal[trap.minx,trap.maxx,layer,@list],GetLocal[@list]
UNTIL ptr = NIL OR outsideList = NIL DO
IF ptr.type = mask THEN BEGIN-- ptr is in local area and right type
inclList ← outsideList; outsideList ← NIL;
FOR temp ← inclList,inclList UNTIL temp = NIL DO
inclList ← temp.front;-- remove front elememt of exclList, call it temp
[inside,outsideList] ← Clip[temp,ptr,outsideList];
FreeTrap[inside];
ENDLOOP;
END;
ENDLOOP;
FOR trap ← outsideList,next UNTIL trap = NIL DO
next ← trap.front;
MinWidthError[trap];
FreeTrap[trap];
ENDLOOP;
END;
PlaceExclusion:PROCEDURE [trap:Trapezoid, layer:CARDINAL] =
BEGIN
minx,maxx:LONG INTEGER;
ptr,inside,outsideList,next,temp,exclList: Trapezoid;
list:ListDescriptor;
IF trap = NIL THEN RETURN;
IF trap.type # exclusion THEN Break["non excl in place excl"];
trap.front ← NIL;
minx ← trap.minx;
maxx ← trap.maxx;
outsideList ← trap;
-- Any part of an exclusion trap that lies in a sanctuary trap is thrown away
-- since separation rules do not apply there
FOR ptr ← GenLocal[minx,maxx,layer,@list],GetLocal[@list]
UNTIL ptr = NIL OR outsideList = NIL DO
IF ptr.type = sanctuary THEN BEGIN-- ptr is in local area and is a sanctuary
exclList ← outsideList; outsideList ← NIL;
FOR temp ← exclList,exclList UNTIL temp = NIL DO
exclList ← temp.front;-- remove front elememt of exclList, call it temp
[inside,outsideList] ← Clip[temp,ptr,outsideList];
FreeTrap[inside];-- remove all parts in santuary box
ENDLOOP;
LOOP;
END;
ENDLOOP;
-- Now find any intersection of exclusion and mask; mark as an error
FOR ptr ← GenLocal[minx,maxx,layer,@list],GetLocal[@list]
UNTIL ptr = NIL OR outsideList = NIL DO
IF ptr.type = mask THEN BEGIN-- ptr is in local area and is a mask
exclList ← outsideList; outsideList ← NIL;
FOR temp ← exclList,exclList UNTIL temp = NIL DO
exclList ← temp.front;-- remove front elememt of exclList, call it temp
[inside,outsideList] ← Clip[temp,ptr,outsideList];
IF inside # NIL THEN BEGIN
MinSepError[inside,inside.number,ptr.number];
FreeTrap[inside];
END;
ENDLOOP;
LOOP;
END;
ENDLOOP;
-- Free all the remaining exclusion trapezoids
FOR trap ← outsideList,next UNTIL trap = NIL DO
next ← trap.front;
FreeTrap[trap];
ENDLOOP;
END;
PlaceSanctuary:PROCEDURE [trap:Trapezoid, layer:CARDINAL] =
BEGIN
IF trap = NIL THEN RETURN;
IF trap.type # sanctuary THEN Break["non sanctuary in place sanctuary"];
IF trap.miny < YPrev THEN {-- this trap goes on bottom swath
InsertTrap[CopyTrap[trap],layer,bottom];
};
IF trap.miny < YCurr AND YPrev < trap.maxy THEN {
-- this trap goes on middle swath
InsertTrap[CopyTrap[trap],layer,middle];
};
IF YCurr < trap.maxy THEN {-- this trap goes on top swath
InsertTrap[CopyTrap[trap],layer,top];
};
FreeTrap[trap];
END;
MinWidthError: PROCEDURE[trap:Trapezoid] =
-- Write on error file this minimum width violation
BEGIN
PutShort[1,errorFile];
PutShort[trap.layer,errorFile];
PutReal[trap.miny,errorFile];
PutReal[trap.maxy,errorFile];
PutReal[XatY[trap.left,trap.miny],errorFile];
PutReal[XatY[trap.left,trap.maxy],errorFile];
PutReal[XatY[trap.right,trap.miny],errorFile];
PutReal[XatY[trap.right,trap.maxy],errorFile];
-- IF trap.miny = trap.maxy THEN CallDebugger["0 height error"];
-- IF trap.minx = trap.maxx THEN CallDebugger["0 width error"];
END;
MinSepError: PROCEDURE[trap:Trapezoid, num1,num2:MergeValue] =
-- Write on error file this minimum width violation
BEGIN
PutShort[2,errorFile];
PutShort[trap.layer,errorFile];
PutReal[trap.miny,errorFile];
PutReal[trap.maxy,errorFile];
PutReal[XatY[trap.left,trap.miny],errorFile];
PutReal[XatY[trap.left,trap.maxy],errorFile];
PutReal[XatY[trap.right,trap.miny],errorFile];
PutReal[XatY[trap.right,trap.maxy],errorFile];
PutLong[num1,errorFile];
PutLong[num2,errorFile];
-- IF trap.miny = trap.maxy THEN CallDebugger["0 height error"];
-- IF trap.minx = trap.maxx THEN CallDebugger["0 width error"];
END;
Break: PROCEDURE[s:STRING] =
BEGIN
-- Cause break; go into debugger
x: REAL ← 0;
WriteLine[s]; IF 10/x = 9 THEN WriteLine[s];
END;
NodeNumberCount: LONG CARDINAL ← LONG[0];
Seperation: REAL;
Lamda: REAL;
YBot, YPrev, YCurr, YNext: REAL;
xCursor: REAL;
MinWidth, MinSep: ARRAY[0..TotalLayerCount] OF REAL;
diffList: Trapezoid ← NIL;
errorFile: DiskHandle;
ErrorPassword:CARDINAL = 12346;
PrintMerge:BOOLEAN ← FALSE;
BaseFileName:STRING;
implant:CARDINAL = 0;
diff:CARDINAL = 1;
poly:CARDINAL = 2;
cut:CARDINAL = 3;
metal:CARDINAL = 4;
DiffPolySafety:CARDINAL = 5;
trans:CARDINAL = 6;
TotalLayerCount:CARDINAL = 7;
END.