-- File CIFExtControl.mesa
-- Written by Dan Fitzpatrick and Martin Newell, June 1980
-- Last updated: October 16, 1981 4:39 PM by DF

DIRECTORY

CIFControlDefs: FROM "CIFControlDefs" USING [DrawCIF],
CIFDevicesDefs: FROM "CIFDevicesDefs" USING [DeviceDescriptor, DeviceDescriptorRecord,
RegisterDevice, GetCIFOutDevice],
CIFExtNMOSDefs: FROM "CIFExtNMOSDefs" USING [InitNMOS, FinishNMOS, NameNMOS],
CIFExtNMOS2Defs: FROM "CIFExtNMOS2Defs" USING [undef],
CIFExtScanDefs: FROM "CIFExtScanDefs" USING [InitExtScan, ExtractorScanConvert, ExtractorMakeEdge, AddToEdgeList, Edge],
CIFExtUtilsDefs: FROM "CIFExtUtilsDefs" USING [SetExtLayer],
CIFOutputDefs: FROM "CIFOutputDefs" USING [SetSorting],
CIFUtilitiesDefs: FROM "CIFUtilitiesDefs" USING [Rectangle, TrapezoidBlock,
SetClipRectangle, GetClipRectangle, DrawClipRectangle,
SetDisplayContext, GetDisplayContext, MapRectangle, MoveCursorTo],
Graphics: FROM "Graphics" USING [DisplayContext, NewContext, PushContext,
PopContext, CopyContext, Scale],
IntDefs: FROM "IntDefs" USING[ILastBB],
JaMFnsDefs: FROM "JaMFnsDefs" USING [PopString],
Real: FROM "Real" USING [Fix],
StringDefs: FROM "StringDefs" USING [AppendChar, AppendString];

CIFExtControl: PROGRAM
IMPORTS CIFControlDefs, CIFDevicesDefs, CIFExtNMOSDefs, CIFExtScanDefs, CIFExtUtilsDefs, CIFOutputDefs, CIFUtilitiesDefs, Graphics, IntDefs, JaMFnsDefs, Real, StringDefs =

BEGIN OPEN CIFControlDefs, CIFDevicesDefs, CIFExtNMOS2Defs, CIFExtNMOSDefs, CIFExtScanDefs, CIFExtUtilsDefs, CIFOutputDefs, CIFUtilitiesDefs, Graphics, IntDefs, JaMFnsDefs, Real, StringDefs;


-- CIF Circuit Extractor procedures

ExtractorDeviceRecord: DeviceDescriptorRecord ← [
next:NIL,
name:"extractor",
deviceSelect: ExtractorSelect,
deviceDrawFrame: ExtractorDrawFrame,
deviceSetScale: ExtractorSetScale,
deviceSetClipRegion: ExtractorSetClipRegion,
deviceOutput: ExtractorOutput,
deviceLayer: ExtractorLayer,
deviceLoadLayer: ExtractorLoadLayer,
deviceRectangle: ExtractorRectangle,
deviceStartPoly: ExtractorStartPoly,
devicePolyVertex: ExtractorPolyVertex,
deviceEndPoly: ExtractorEndPoly,
deviceText: ExtractorText
];

ExtractorSelect: PROCEDURE RETURNS[BOOLEAN] =
BEGIN
--
ExtractorSetClipRegion[GetClipRectangle[]];
RETURN[TRUE];
END;

ExtractorDrawFrame: PROCEDURE =
BEGIN
DrawClipRectangle[];
END;

ExtractorSetScale: PROCEDURE [factor: REAL] =
BEGIN
dc: DisplayContext ← GetDisplayContext[];
PopContext[dc];
PushContext[dc];
Scale[dc, [factor,factor]];
END;

ExtractorSetClipRegion: PROCEDURE [rt: Rectangle] =
BEGIN
SetClipRectangle[rt];
END;

ExtractorOutput: PROCEDURE =
--expects <filename> (STRING)
BEGIN
fileName: STRING ← [100];
saveContext: DisplayContext ← GetDisplayContext[];
r: Rectangle ← GetClipRectangle[]; --clipping region in CIF units
etop: REAL;
PopString[fileName];
SetDisplayContext[extractorContext];
SetClipRectangle[r];
extractorClipRectangle ←
MapRectangle[r,extractorContext,identityContext];
etop ← extractorClipRectangle.ury;
xCursor ← (r.llx + r.urx)/2;
ExtractorStart[fileName];
DrawCIF[Fix[r.llx],Fix[r.urx],Fix[r.lly],Fix[r.ury]];
ExtractorEnd[etop];
SetDisplayContext[saveContext];
SetClipRectangle[r];
END;

ExtractorStart: PROCEDURE[fileName: STRING] =
BEGIN
--Initialize EdgeList and ActiveList
SetSorting[incy];
ExtractorCurrentLayer ← 32000; --i.e. not set
InitExtScan;
InitNMOS[fileName];
END;

ExtractorEnd: PROCEDURE [ymax: REAL] =
BEGIN
ExtractorScanConvert[ymax+1];
MoveCursorTo[xCursor,ymax];
FinishNMOS[];
END;

ExtractorLayer: PROCEDURE [layer: CARDINAL] =
--used to trigger scan conversion up to bottom of object about to be received
BEGIN
l,r,b,t: LONG INTEGER;
bottom: REAL;
rec: Rectangle;
[l,r,b,t] ← ILastBB[]; --in chip coordinates
--kludge - need bottom of current object in Extractor coords
rec ← MapRectangle[[l,b,r,t], extractorContext, identityContext];
bottom ← MIN[rec.lly,rec.ury]-1; -- -1 to be on safe side
ExtractorScanConvert[bottom];
ExtractorCurrentLayer ← layer;
MoveCursorTo[xCursor,bottom];
END;

ExtractorLoadLayer: PROCEDURE[layer:CARDINAL, v0,v1,v2,v3: CARDINAL] =
BEGIN
SetExtLayer[layer,v0,v1,v2,v3];
END;


ExtractorText: PROCEDURE[text: STRING, x,y: REAL --, layer:CARDINAL ← undef --] =
--x,y are in BaseContext
BEGIN
NameNMOS[text, x, y, undef];
END;

ExtractorTrapezoid: PROCEDURE [t:POINTER TO TrapezoidBlock] =
--make two edges of appropriate types
BEGIN OPEN t;
edge: Edge;
-- Only look at edges on implant,diffusion,poly,contact,metal,and buried
IF ExtractorCurrentLayer>5 THEN RETURN;
edge ← ExtractorMakeEdge[ExtractorCurrentLayer, xsleft,ystart,xeleft,yend,TRUE];
IF edge#NIL THEN AddToEdgeList[edge];
edge ← ExtractorMakeEdge[ExtractorCurrentLayer, xsright,ystart,xeright,yend,FALSE];
IF edge#NIL THEN AddToEdgeList[edge];
END;

ExtractorRectangle: PROCEDURE [r: Rectangle] =
--make two edges of appropriate types
BEGIN
edge: Edge;
IF ExtractorCurrentLayer>5 THEN RETURN;
edge ← ExtractorMakeEdge[ExtractorCurrentLayer,
r.llx,r.lly, r.llx,r.ury, TRUE];
IF edge#NIL THEN AddToEdgeList[edge];
edge ← ExtractorMakeEdge[ExtractorCurrentLayer,
r.urx,r.lly, r.urx,r.ury, FALSE];
IF edge#NIL THEN AddToEdgeList[edge];
END;

x0,y0: REAL;
xs,ys: REAL;

ExtractorStartPoly: PROCEDURE [x,y: REAL] =
BEGIN
x0 ← xs ← x;
y0 ← ys ← y;
END;

ExtractorPolyVertex: PROCEDURE [x,y: REAL] =
BEGIN
edge: Edge ← NIL;
IF ExtractorCurrentLayer>5 THEN RETURN;
SELECT TRUE FROM
y>ys=> edge ← ExtractorMakeEdge[ExtractorCurrentLayer, xs,ys, x,y,FALSE];
y<ys=> edge ← ExtractorMakeEdge[ExtractorCurrentLayer, x,y, xs,ys,TRUE];
ENDCASE;
IF edge#NIL THEN AddToEdgeList[edge];
xs ← x;
ys ← y;
END;

ExtractorEndPoly: PROCEDURE =
BEGIN
ExtractorPolyVertex[x0,y0];
END;

DefaultExtension: PROCEDURE[name,ext: STRING] RETURNS[STRING] =
--set extension if not already present
BEGIN
i: CARDINAL;
FOR i IN [0..name.length) DO
IF name[i]=’. THEN RETURN[name];
ENDLOOP;
AppendChar[name,’.];
AppendString[name,ext];
RETURN[name];
END;

--Extractor Parameters
extractorClipRectangle: Rectangle;
extractorContext: DisplayContext ← NewContext[GetCIFOutDevice[]];
identityContext: DisplayContext ← CopyContext[extractorContext];

ExtractorCurrentLayer: CARDINAL;
xCursor: REAL;

--set up context

RegisterDevice[@ExtractorDeviceRecord];

END.