-- 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. (672)\130b9B984b10B330b11B834b13B281b8B3285b9B378b16B314b16B1192b14B348b16B1267b15B661b9B204b14B1048b9B805v13V194b15B378b11B2219b4B2411b7B225v13V351b14B856b14B1742b14B529b13B535b11B609b5B