-- File CIFCIF.mesa -- Output module for CIF 2.0 -- Written by Martin Newell, March 1981 -- Last updated: June 12, 1981 3:26 PM DIRECTORY AuxIntDefs: FROM "AuxIntDefs" USING [IExpand, IGetRootID, IGetFirstSymbol, IGetNextSymbol, IStop], AuxOutputDefs: FROM "AuxOutputDefs", CIFDevicesDefs: FROM "CIFDevicesDefs" USING [DeviceDescriptor, DeviceDescriptorRecord, RegisterDevice, MaxLENGTHLayerArray], CIFUtilitiesDefs: FROM "CIFUtilitiesDefs" USING [Rectangle, SetClipRectangle, DrawClipRectangle, GetDisplayContext], Graphics: FROM "Graphics" USING [DisplayContext, PopContext, PushContext, Scale], InlineDefs: FROM "InlineDefs" USING [LowHalf], IntStorageDefs: FROM "IntStorageDefs" USING [ObjectName, NilObjectName], IntTransDefs: FROM "IntTransDefs" USING [Transform, TransformRecord], IODefs: FROM "IODefs" USING [CR, SP, NUL, WriteLine, WriteString, WriteChar, GetOutputStream, SetOutputStream, WriteDecimal], JaMFnsDefs: FROM "JaMFnsDefs" USING [PopString, GetJaMBreak, SetJaMBreak, PopBoolean], ParserTypeDefs: FROM "ParserTypeDefs" USING [Point, Path, RemovePoint], Real: FROM "Real" USING [Fix, WriteReal], StreamDefs: FROM "StreamDefs" USING [StreamHandle, NewByteStream, Write, Append], StringDefs: FROM "StringDefs" USING[AppendChar, AppendString, AppendLongDecimal], SystemDefs: FROM "SystemDefs" USING [AllocateHeapNode, FreeHeapNode]; CIFCIF: PROGRAM IMPORTS AuxIntDefs, CIFDevicesDefs, CIFUtilitiesDefs, Graphics, InlineDefs, IODefs, JaMFnsDefs, ParserTypeDefs, Real, StreamDefs, StringDefs, SystemDefs EXPORTS AuxOutputDefs = BEGIN OPEN AuxIntDefs, AuxOutputDefs, CIFDevicesDefs, CIFUtilitiesDefs, Graphics, InlineDefs, IntStorageDefs, IntTransDefs, IODefs, JaMFnsDefs, ParserTypeDefs, Real, StreamDefs, StringDefs, SystemDefs; -- CIF procedures CIFDeviceRecord: DeviceDescriptorRecord _ [ next: NIL, name: "cif", deviceSelect: CIFSelect, deviceDrawFrame: CIFDrawFrame, deviceSetScale: CIFSetScale, deviceSetClipRegion: CIFSetClipRegion, deviceOutput: CIFOutput, deviceLayer: CIFLayer, deviceLoadLayer: CIFLoadLayer, deviceRectangle: CIFRectangle, deviceStartPoly: CIFStartPoly, devicePolyVertex: CIFPolyVertex, deviceEndPoly: CIFEndPoly, deviceText: CIFText ]; --the following types are copied from CIFOutput UserObjectType: TYPE = {User9, User94, other}; UserObject: TYPE = POINTER TO UserObjectRecord; UserObjectRecord: TYPE = RECORD[ SELECT type: UserObjectType FROM User9 => [ --Symbol name name: PACKED ARRAY [0..0) OF CHARACTER], User94 => [ --Named point x: REAL, y: REAL, name: PACKED ARRAY [0..0) OF CHARACTER], ENDCASE]; CIFSelect: PROCEDURE RETURNS[BOOLEAN] = BEGIN RETURN[TRUE]; END; CIFDrawFrame: PROCEDURE = BEGIN DrawClipRectangle[]; END; CIFSetScale: PROCEDURE [factor: REAL] = BEGIN dc: DisplayContext _ GetDisplayContext[]; PopContext[dc]; PushContext[dc]; Scale[dc, [factor,factor]]; END; CIFSetClipRegion: PROCEDURE [rt: Rectangle] = BEGIN SetClipRectangle[rt]; END; CIFOutput: PROCEDURE = --expects (boolean is true for ALL symbols, false for REFERENCED only) BEGIN symbol: ObjectName; cifNum: CARDINAL; fileName: STRING _ [100]; allSymbols: BOOLEAN; PopString[fileName]; allSymbols _ PopBoolean[]; IF ~DotinName[fileName] THEN AppendString[fileName,".cif"]; Aborted _ FALSE; InitDict[256]; IF allSymbols THEN --get handle on all symbols, even if not referenced { FOR s:ObjectName _ IGetFirstSymbol[],IGetNextSymbol[] UNTIL s=NilObjectName DO { u: STRING _ [100]; [] _ Lookup[s]; }; ENDLOOP; }; --provoke initial entries in dictionary ScanningTopLevel _ TRUE; IExpand[IGetRootID[]]; IF Aborted THEN { Abort[]; RETURN; }; ScanningTopLevel _ FALSE; --output symbols DoHeader[fileName]; [symbol,cifNum] _ GetNonProcessedEntry[]; UNTIL cifNum=0 DO DoSymbolHeader[symbol]; IExpand[symbol]; IF Aborted THEN { Abort[]; RETURN; }; DoSymbolTrailer[symbol]; [symbol,cifNum] _ GetNonProcessedEntry[]; ENDLOOP; --output mainline CIFStream.put[CIFStream,CR]; IExpand[IGetRootID[]]; IF Aborted THEN { Abort[]; RETURN; }; DoTrailer[]; FreeDict[]; END; Abort: PROCEDURE[] = BEGIN save: StreamHandle _ GetOutputStream[]; SetOutputStream[CIFStream]; WriteLine["***Aborted***"]; SetOutputStream[save]; WriteLine["***Aborted***"]; DoTrailer[]; FreeDict[]; END; DoHeader: PROCEDURE[fileName: STRING] = BEGIN save: StreamHandle _ GetOutputStream[]; CIFStream _ NewByteStream[fileName, Write+Append]; SetOutputStream[CIFStream]; WriteString["(File: "]; WriteString[fileName]; WriteLine[". Created by CIFCIF);"]; SetOutputStream[save]; CurrentLayer _ 32000; --i.e. not set END; DoTrailer: PROCEDURE = BEGIN save: StreamHandle _ GetOutputStream[]; SetOutputStream[CIFStream]; WriteLine["End"]; SetOutputStream[save]; CIFStream.destroy[CIFStream]; CIFStream _ NIL; END; DoSymbolHeader: PROCEDURE [symbol: ObjectName] = BEGIN save: StreamHandle _ GetOutputStream[]; SetOutputStream[CIFStream]; WriteChar[CR]; WriteString["DS "]; WriteDecimal[Lookup[symbol]]; WriteLine[";"]; SaveLayer _ CurrentLayer; CurrentLayer _ 32000; SetOutputStream[save]; END; DoSymbolTrailer: PROCEDURE[symbol: ObjectName] = BEGIN save: StreamHandle _ GetOutputStream[]; SetOutputStream[CIFStream]; WriteLine["DF;"]; SetOutputStream[save]; CurrentLayer _ SaveLayer; END; CIFLayer: PROCEDURE [layer: CARDINAL] = BEGIN END; CIFLoadLayer: PROCEDURE[layer:CARDINAL, v0,v1,v2,v3: CARDINAL] = BEGIN END; CIFRectangle: PROCEDURE [r: Rectangle] = BEGIN END; CIFStartPoly: PROCEDURE [x,y: REAL] = BEGIN END; CIFPolyVertex: PROCEDURE [x,y: REAL] = BEGIN END; CIFEndPoly: PROCEDURE = BEGIN END; CIFText: PROCEDURE[text: STRING, x,y: REAL] = BEGIN END; --Procedures that export AuxOutputDefs-- AuxWire: PUBLIC PROCEDURE [layerName: CARDINAL, width: LONG CARDINAL, a: ParserTypeDefs.Path] = BEGIN save: StreamHandle _ GetOutputStream[]; gotone: BOOLEAN; p: Point; IF ScanningTopLevel THEN RETURN; IF a.length=0 THEN RETURN; SetOutputStream[CIFStream]; SetLayer[layerName]; WriteString["W "]; WriteLongDecimal[width]; [gotone,p] _ RemovePoint[a]; WHILE gotone DO WriteChar[SP]; WriteLongDecimal[p.x]; WriteChar[SP]; WriteLongDecimal[p.y]; [gotone,p] _ RemovePoint[a]; ENDLOOP; WriteLine[";"]; SetOutputStream[save]; END; AuxFlash: PUBLIC PROCEDURE [layerName: CARDINAL, diameter: LONG CARDINAL, center: ParserTypeDefs.Point] = BEGIN save: StreamHandle _ GetOutputStream[]; IF ScanningTopLevel THEN RETURN; SetOutputStream[CIFStream]; SetLayer[layerName]; WriteString["R "]; WriteLongDecimal[diameter]; WriteChar[SP]; WriteLongDecimal[center.x]; WriteChar[SP]; WriteLongDecimal[center.y]; WriteLine[";"]; SetOutputStream[save]; END; AuxPolygon: PUBLIC PROCEDURE [layerName: CARDINAL, a: ParserTypeDefs.Path] = BEGIN save: StreamHandle _ GetOutputStream[]; gotone: BOOLEAN; p: Point; IF ScanningTopLevel THEN RETURN; IF a.length=0 THEN RETURN; SetOutputStream[CIFStream]; SetLayer[layerName]; WriteString["P"]; [gotone,p] _ RemovePoint[a]; WHILE gotone DO WriteChar[SP]; WriteLongDecimal[p.x]; WriteChar[SP]; WriteLongDecimal[p.y]; [gotone,p] _ RemovePoint[a]; ENDLOOP; WriteLine[";"]; SetOutputStream[save]; END; AuxBox: PUBLIC PROCEDURE [layerName: CARDINAL, length, width: LONG CARDINAL, center: ParserTypeDefs.Point, xRotation, yRotation: LONG INTEGER] = BEGIN save: StreamHandle _ GetOutputStream[]; IF GetJaMBreak[] THEN { IStop[]; SetJaMBreak[FALSE]; Aborted _ TRUE; RETURN; }; IF ScanningTopLevel THEN RETURN; SetOutputStream[CIFStream]; SetLayer[layerName]; WriteString["B "]; WriteLongDecimal[length]; WriteChar[SP]; WriteLongDecimal[width]; WriteChar[SP]; WriteLongDecimal[center.x]; WriteChar[SP]; WriteLongDecimal[center.y]; IF yRotation#0 OR xRotation<0 THEN { WriteChar[SP]; WriteLongDecimal[xRotation]; WriteChar[SP]; WriteLongDecimal[yRotation]; }; WriteLine[";"]; SetOutputStream[save]; END; AuxUserObject: PUBLIC PROCEDURE [layerName: CARDINAL, size: CARDINAL, data: POINTER TO UNSPECIFIED] = BEGIN userObject: UserObject _ data; save: StreamHandle _ GetOutputStream[]; IF ScanningTopLevel THEN RETURN; WITH userObject SELECT FROM User9 => { string: STRING _ [100]; i,stringlength: INTEGER; SetOutputStream[CIFStream]; stringlength _ (size-SIZE[User9 UserObjectRecord])*2; FOR i IN [0..stringlength) DO AppendChar[string,IF name[i]=SP THEN '* ELSE name[i]]; ENDLOOP; IF stringlength>0 AND name[stringlength-1]=NUL THEN string.length _ string.length - 1; WriteString["9 "]; WriteString[string]; WriteLine[";"]; SetOutputStream[save]; }; User94 => { string: STRING _ [100]; i,stringlength: INTEGER; SetOutputStream[CIFStream]; stringlength _ (size-SIZE[User94 UserObjectRecord])*2; FOR i IN [0..stringlength) DO AppendChar[string,IF name[i]=SP THEN '* ELSE name[i]]; ENDLOOP; IF stringlength>0 AND name[stringlength-1]=NUL THEN string.length _ string.length - 1; WriteString["94 "]; WriteString[string]; WriteChar[SP]; WriteFloat[x]; WriteChar[SP]; WriteFloat[y]; WriteLine[";"]; SetOutputStream[save]; }; ENDCASE => WriteLine["unknown user object"]; END; AuxCall: PUBLIC PROCEDURE [symbol: ObjectName, cifNumber: LONG CARDINAL, transform: Transform] = BEGIN save: StreamHandle _ GetOutputStream[]; t: TransformRecord; c,s: REAL; Rx,Ry: LONG INTEGER; cifNum: INTEGER _ Lookup[symbol]; --need to do this always IF ScanningTopLevel THEN RETURN; SetOutputStream[CIFStream]; WriteString["C "]; WriteLongDecimal[cifNum]; t _ transform^; --Check and output Mirror IF (t.a11*t.a22-t.a21*t.a12)<0 THEN --determinant negative - need mirror { t.a11 _ -t.a11; t.a12 _ -t.a12; WriteString[" MX"]; }; --check and output Rotate c _ t.a11/t.a33; s _ t.a12/t.a33; IF s#0 OR c<0 THEN { SELECT TRUE FROM c=s => Rx _ Ry _ 1; c=0 => {Rx _ 0; Ry _ IF s<0 THEN -1 ELSE 1; }; s=0 => {Ry _ 0; Rx _ IF c<0 THEN -1 ELSE 1; }; ENDCASE => { f: REAL _ ABS[BigCIFInteger/c]; f _ MIN[f,ABS[BigCIFInteger/s]]; Rx _ Fix[c*f]; Ry _ Fix[s*f]; }; WriteString[" R "]; WriteLongDecimal[Rx]; WriteChar[SP]; WriteLongDecimal[Ry]; }; --Check and output translation IF t.a31#0 OR t.a32#0 THEN { WriteString[" T "]; WriteLongDecimal[Fix[t.a31/t.a33]]; WriteChar[SP]; WriteLongDecimal[Fix[t.a32/t.a33]]; }; WriteLine[";"]; SetOutputStream[save]; END; BigCIFInteger: LONG INTEGER _ 20000000B; --2^22 SetLayer: PUBLIC PROCEDURE [layerName: CARDINAL] = BEGIN IF CurrentLayer#layerName THEN { save: StreamHandle _ GetOutputStream[]; SetOutputStream[CIFStream]; WriteString["L N"]; WriteChar[LayerChar[layerName]]; WriteString["; "]; SetOutputStream[save]; CurrentLayer _ layerName; }; END; --Dictionary DictEntry: TYPE = POINTER TO DictEntryRecord; DictEntryRecord: TYPE = RECORD [ next: DictEntry, --global list in order in which entries are made ovflow: DictEntry, --overflow list from entry in hash table key: ObjectName, --internal ID of symbol value: CARDINAL --generated CIF symbol # for output ]; DictHead: DictEntry; DictTail: DictEntry; HTable: DESCRIPTOR FOR ARRAY OF DictEntry; LastProcessedEntry: DictEntry; --points to last processed entry Value: CARDINAL; InitDict: PROCEDURE[hashlength: CARDINAL] = BEGIN i: CARDINAL; DictHead _ NIL; DictTail _ NIL; HTable _ DESCRIPTOR[AllocateHeapNode[hashlength*SIZE[DictEntry]],hashlength]; FOR i IN [0..hashlength) DO HTable[i] _ NIL; ENDLOOP; LastProcessedEntry _ NIL; Value _ 0; END; Lookup: PROCEDURE[key: ObjectName] RETURNS[CARDINAL] = --Return value associated with key. If key not found then --allocate a new entry with generated value, and return the value. BEGIN de: DictEntry; h: CARDINAL; [de,h] _ Where[key]; IF de=NIL THEN { de _ AllocateHeapNode[SIZE[DictEntryRecord]]; de^ _ [ next: NIL, ovflow: HTable[h], key: key, value: (Value_Value+1)]; HTable[h] _ de; IF DictTail=NIL THEN DictHead _ DictTail _ de ELSE { DictTail.next _ de; DictTail _ de; }; }; RETURN[de.value]; END; GetNonProcessedEntry: PROCEDURE RETURNS[key: ObjectName, value: CARDINAL] = --Step LastProcessedEntry and return its key and value, if any BEGIN IF LastProcessedEntry=NIL THEN LastProcessedEntry _ DictHead ELSE LastProcessedEntry _ LastProcessedEntry.next; IF LastProcessedEntry=NIL THEN RETURN[NilObjectName,0] ELSE RETURN[LastProcessedEntry.key, LastProcessedEntry.value]; END; FreeDict: PROCEDURE = BEGIN de,nextde: DictEntry; FOR de _ DictHead, nextde UNTIL de=NIL DO nextde _ de.next; FreeHeapNode[de]; ENDLOOP; FreeHeapNode[BASE[HTable]]; END; Where: PROCEDURE[key: ObjectName] RETURNS[de: DictEntry, h: CARDINAL] = --h is result of hashing name BEGIN h _ Hash[key, LENGTH[HTable]]; FOR de _ HTable[h], de.ovflow UNTIL de=NIL OR key=de.key DO --nothing-- ENDLOOP; END; Hash: PROCEDURE[key: ObjectName, range: CARDINAL] RETURNS[h: CARDINAL] = --h is result of hashing name into [0..range) BEGIN i: CARDINAL _ LowHalf[key]; RETURN[i MOD range]; END; --Utilities WriteLongDecimal: PROCEDURE[n: LONG INTEGER] = BEGIN s: STRING _ [50]; AppendLongDecimal[s,n]; WriteString[s]; END; WriteFloat: PROCEDURE[r: REAL] = BEGIN WriteReal[WriteChar,r]; END; DotinName: PROCEDURE[name: STRING] RETURNS[BOOLEAN] = BEGIN FOR i:CARDINAL IN [0..name.length) DO IF name[i]='. THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; END; --CIF parameters ScanningTopLevel: BOOLEAN; CIFStream: StreamHandle _ NIL; SaveLayer: CARDINAL; CurrentLayer: CARDINAL; Aborted: BOOLEAN; LayerChar: ARRAY [0..MaxLENGTHLayerArray) OF CHARACTER _ ALL['X]; LayerChar[0] _ 'I; --implant LayerChar[1] _ 'D; --diffusion LayerChar[2] _ 'P; --poly LayerChar[3] _ 'C; --contact LayerChar[4] _ 'M; --metal LayerChar[5] _ 'B; --buried LayerChar[6] _ 'G; --glass LayerChar[7] _ 'X; --undef --set up context RegisterDevice[@CIFDeviceRecord]; END. (635)\130b9B1223b6B916b14B33b10B38b16B231b9B60b12B50b11B150b16B67b9B1147b5B209b8B316b9B190b14B276b15B188b8B46b12B67b12B43b12B40b13B40b10B28b7B95b7B540b8B415b10B492b6B720b13B1249b7B1249b8B785b8B273b6B536b20B369b8B173b5B228b4B193b16B106b10B62b9B