-- PROGRAM SifGuts -- Updated to Mesa 6.0 - January 27, 1981 11:36 AM -- Last edited - February 5, 1981 1:31 PM DIRECTORY IODefs: FROM "iodefs", Real : FROM "Real" USING [Fix], RealFns : FROM "RealFns" USING [SqRt], StreamDefs: FROM "streamdefs", SystemDefs: FROM "systemdefs", SifGutsDefs : FROM "SifGutsDefs", SifOutputDefs : FROM "SifOutputDefs" USING [PutLayer, PutBox, PutName, PutCall, PutComment, PutDefStart, PutDefFinish, PutEnd, PutError], StringDefs: FROM "stringdefs"; SifGuts : PROGRAM IMPORTS IODefs, Real, RealFns, SifOutputDefs, StreamDefs, StringDefs, SystemDefs EXPORTS SifGutsDefs = BEGIN OPEN IODefs, Real, RealFns, SifGutsDefs, SifOutputDefs, StreamDefs, StringDefs, SystemDefs; debugging: BOOLEAN _ FALSE; FatalError: BOOLEAN _ FALSE; InDefs: BOOLEAN _ FALSE; -- Must be set whenever defining a symbol A: LONG INTEGER; B: LONG INTEGER; Password : CARDINAL = 172635B; -- Icarus's legal password StartDefNbr, FinishDefNbr: INTEGER; fin: StreamHandle; Nlayers: INTEGER = 8; -- need some layer names for layer changes to CIF LayerNames: ARRAY [0..Nlayers) OF STRING = [ "NI", -- implant is ICARUS layer 0 "ND", -- diffusion "NP", -- polysilicon "NC", -- contact cut "NM", -- metal "NB", -- buried contact "NG", -- overglassing "NX" -- extra ]; getstring : PROCEDURE[f:StreamHandle, s:STRING] = BEGIN -- gets a BCPL string from the given file -- returns it in s StrHead: TYPE = MACHINE DEPENDENT RECORD [length: [0..255], chr2: CHARACTER]; TwoByte: TYPE = MACHINE DEPENDENT RECORD [chr1,chr2: CHARACTER]; bh: StrHead; tb: TwoByte; j : INTEGER; bh_f.get[f]; s.length_bh.length; s[0]_bh.chr2; FOR j IN [1..bh.length/2] DO tb_f.get[f]; s[2*j-1]_tb.chr1; s[2*j]_tb.chr2; ENDLOOP; RETURN END; Sgn: PROCEDURE[x: INTEGER] RETURNS[i: INTEGER] = BEGIN -- -1,0,1 if < , = , > 0 RETURN [IF x = 0 THEN 0 ELSE IF x < 0 THEN -1 ELSE 1] END; Scale: PROCEDURE [x: LONG INTEGER] RETURNS [y: LONG INTEGER] = -- Convert from icarus to CIF units (always round up) -- This procedure should only be used for lengths -- ScalePoint should be used to convert points BEGIN y _ 2*x; END; ScaleFl: PROCEDURE [x: REAL] RETURNS [y: LONG INTEGER] = -- Convert from icarus to CIF units (always round up) -- This procedure accepts floating point numbers for conversion BEGIN y _ Fix[(2*x) + NearOne]; END; --ScalePoint: PROCEDURE [x,y: REAL] RETURNS [s: Point] = -- Converts a point in icarus units to CIF units --BEGIN -- s.x _ Fix[(x*ScaleFactorMul)/ScaleFactorDiv]; -- s.y _ Fix[(y*ScaleFactorMul)/ScaleFactorDiv]; -- END; DeBlank : PROCEDURE[s:STRING] = -- Convert all blanks in string s into stars BEGIN i: CARDINAL; FOR i IN [0..s.length) DO IF s.text[i] = ' OR s.text[i] ='; OR s.text[i] = CR OR s.text[i] = TAB THEN s.text[i] _ '*; ENDLOOP; END; MakeSymbolCall : PROCEDURE[callNo:INTEGER,mirx,miry:BOOLEAN, rot:Point, xorigin,yorigin, xdisp,ydisp: LONG INTEGER, xcount,ycount:INTEGER] = BEGIN i,j: INTEGER; xpos,ypos: LONG INTEGER; IF xcount <= 1 OR ycount <= 1 THEN BEGIN -- No need to create new definition since array is linear xpos _ xorigin; FOR i IN [1..xcount] DO ypos _ yorigin; FOR j IN [1..ycount] DO PutCall[callNo, mirx, miry, rot, Point[xpos,-(ypos)]]; ypos _ ypos + ydisp; ENDLOOP; xpos _ xpos + xdisp; ENDLOOP; END ELSE BEGIN -- To cut down on number of calls to the symbol introduce -- a new symbol which contains a linear array in y -- this can be called several times changing the x position MakeArraySymbol[FinishDefNbr, callNo, mirx, miry, rot, yorigin, ydisp, ycount]; xpos _ xorigin; FOR i IN [1..xcount] DO PutCall[FinishDefNbr, FALSE, FALSE, Point[LONG[1],LONG[0]], Point[xpos,LONG[0]]]; xpos _ xpos + xdisp; ENDLOOP; FinishDefNbr _ FinishDefNbr + 1; END; END; MakeArraySymbol : PROCEDURE[symblNo,callNo:INTEGER,mirx,miry:BOOLEAN, rot:Point, yorigin, ydisp: LONG INTEGER, ycount:INTEGER] = BEGIN i: INTEGER; ypos: LONG INTEGER; IF InDefs THEN BEGIN -- Store information and create symbol later cell: ArraySymbolHoldingCell _ AllocateCell[]; cell.symblNo _ symblNo; cell.callNo _ callNo; cell.mirx _ mirx; cell.miry _ miry; cell.rot _ rot; cell.yorigin _ yorigin; cell.ydisp _ ydisp; cell.ycount _ ycount; cell.next _ CellList; CellList _ cell; END ELSE BEGIN -- Not in definitions, cannot delay output symbol any longer -- since it would create an illegal forward reference InDefs _ TRUE; PutDefStart[symblNo,A,B,""]; ypos _ yorigin; FOR i IN [1..ycount] DO PutCall[callNo,mirx,miry,rot,Point[LONG[0],-(ypos)]]; ypos _ ypos + ydisp; ENDLOOP; PutDefFinish[]; InDefs _ FALSE; END; END; AllocateCell : PROCEDURE RETURNS[ArraySymbolHoldingCell] = BEGIN RETURN[AllocateHeapNode[SIZE[ArraySymbolHoldingCellRecord]]]; END; FreeCell : PROCEDURE [cell:ArraySymbolHoldingCell] = BEGIN FreeHeapNode[cell]; END; ItemOutput : PROCEDURE = -- prints out pertinent info on items -- notice also that this routine does the scaling!!! BEGIN -- ICARUS form iteminfotype : TYPE = MACHINE DEPENDENT RECORD[ disappear : [0..1], type : [0..7], layer : [0..15], state : [0..7], w : [0..31] ]; mirrot: TYPE = MACHINE DEPENDENT RECORD[mir,rot: [0..255]]; sqrt2f: CARDINAL = 27146; -- .414... x 2^16 info: iteminfotype; xmin,ymin,xmax,ymax,xdif: INTEGER; nx,ny,dx,dy,origx,origy,def: INTEGER; mr: mirrot; distmp: LONG INTEGER; s: STRING _ [255]; -- for throwing away text p: Point; -- get the common part of an item info_fin.get[fin]; -- all sorts of strange fields there xmin_fin.get[fin]; ymin_fin.get[fin]; xmax_fin.get[fin]; ymax_fin.get[fin]; BEGIN OPEN info; -- ****** handle all the cases that ICARUS might give ****** -- notice that we must go into the TEXT code segment (type=2) -- and the INSTANCE code segment (type=4) even if we aren't -- outputting, because the representations of those items in -- the file are larger than the LINE and BOX representations -- ****** ****** SELECT type FROM -- LINE (45-degree type) ITEM 0 => BEGIN -- Line type object, convert into a box angle: Point; IF w = 0 THEN RETURN; IF xmin = xmax OR ymin = ymax THEN RETURN; -- don't do zero-length ones IF layer < Nlayers THEN PutLayer[LayerNames[layer]] ELSE BEGIN FatalError _ TRUE; PutError["Illegal layer number encountered"]; END; xdif _ ABS[xmax-xmin]; -- we take advantage of fact that lines must be -- 45 deg. or -45 distmp _ ScaleFl[SqrtOf2*xdif]; p _ [(LONG[xmax]+LONG[xmin]), -(LONG[ymax]+LONG[ymin])]; IF Sgn[xmax-xmin] # Sgn[ymax-ymin] THEN angle _ [LONG[1],LONG[1]] ELSE angle _ [LONG[1],LONG[-1]]; PutBox[distmp, Scale[w], p, angle]; END; -- BOX (rectangular, 0-degree rotation) ITEM 1 => BEGIN -- Box type object IF xmin = xmax OR ymin = ymax THEN RETURN; -- don't do zero-length ones IF layer < Nlayers THEN PutLayer[LayerNames[layer]] ELSE BEGIN FatalError _ TRUE; PutError["Illegal layer number encountered"]; END; -- these must be scaled to 10x or something PutBox[Scale[ABS[xmax-xmin]], Scale[ABS[ymax-ymin]], [(LONG[xmax]+LONG[xmin]), -(LONG[ymax]+LONG[ymin])], Point[LONG[1],LONG[0]] ]; END; -- TEXT (BCPL string) ITEM 2 => BEGIN getstring[fin,s]; DeBlank[s]; --Remove all blanks from string s, blanks must not appear in names PutName[Scale[xmin],Scale[-(ymin)],s]; END; -- SYMBOL INSTANCE 4 => BEGIN -- symbol instance .. do a call angle: Point _ [LONG[1],LONG[0]]; rot:INTEGER; nx_fin.get[fin]; ny_fin.get[fin]; dx_fin.get[fin]; dy_fin.get[fin]; origx_fin.get[fin]; origy_fin.get[fin]; mr_fin.get[fin]; def _ fin.get[fin] + StartDefNbr - 1; rot _ mr.rot MOD 4; IF rot = 1 THEN angle _ [LONG[0],LONG[-1]] ELSE IF rot = 2 THEN angle _ [LONG[-1],LONG[0]] ELSE IF rot = 3 THEN angle _ [LONG[0],LONG[1]]; MakeSymbolCall[def, mr.mir/2=1, (mr.mir MOD 2)=1, angle, Scale[origx], Scale[origy], Scale[dx], Scale[dy], nx, ny]; END; ENDCASE => BEGIN FatalError _ TRUE; PutError["Found Weird Type Thing"]; END; END; -- of the open clause RETURN END; -- of ItemOutput DoDefs: PROCEDURE [Ndefs: INTEGER] = BEGIN nv,j,k,Defnum: INTEGER; defname: STRING _ [255]; tempString: STRING _ [255]; FOR Defnum IN [StartDefNbr..StartDefNbr+Ndefs) DO -- throw away extra information given with symbol definition FOR j IN [1..5] DO -- throw away the bounding box nv_fin.get[fin]; ENDLOOP; --nv is number of vertices in the def (we dont care, do we?) FOR j IN [1..2*nv] DO k_fin.get[fin] ENDLOOP; -- throw them away -- extract important information, the name and the items getstring[fin,defname]; -- the thing has a name nv_fin.get[fin]; -- number of items in this definition -- start the definition, and output CIF for each item DefineSymbol[Defnum,A,B,defname]; FOR j IN [1..nv] DO ItemOutput[] ENDLOOP; DefineFinish[]; ENDLOOP; -- end of definitions loop END; DefineSymbol: PROCEDURE [N: INTEGER, A,B: LONG INTEGER, name: STRING] = BEGIN InDefs _ TRUE; PutDefStart[N,A,B,name]; END; DefineFinish: PROCEDURE = BEGIN cell: ArraySymbolHoldingCell; PutDefFinish[]; InDefs _ FALSE; -- Check if any arrays caused need for new symbol to be created FOR cell _ CellList, CellList UNTIL cell = NIL DO CellList _ cell.next; MakeArraySymbol[cell.symblNo,cell.callNo,cell.mirx,cell.miry, cell.rot,cell.yorigin,cell.ydisp,cell.ycount]; FreeCell[cell]; ENDLOOP; END; SetScale: PROCEDURE[mul,div: LONG INTEGER] = -- Set global scale factors to mul & div BEGIN A _ mul; B _ 2*div; END; IcToCif: PUBLIC PROCEDURE[inputFileName: STRING, mul,div: LONG INTEGER, StartDefNumber: INTEGER] RETURNS[error:BOOLEAN, Ndefs: INTEGER] = BEGIN s: STRING _ [255]; Top: INTEGER; SetScale[mul,div]; IF debugging THEN WriteLine["Initializing."]; StartDefNbr _ StartDefNumber; -- open that file fin_NewWordStream[inputFileName, Read]; IF fin.get[fin] # Password THEN BEGIN s.length _ 0; StringDefs.AppendString[s, inputFileName]; StringDefs.AppendString[s, " is not an Icarus file"]; PutError[s]; RETURN[error_TRUE, Ndefs_0]; END; s.length _ 0; StringDefs.AppendString[s, "Created by Sif from "]; StringDefs.AppendString[s, inputFileName]; PutComment[s]; Ndefs_fin.get[fin]; --get the number of definitions to follow FinishDefNbr _ StartDefNbr + Ndefs; -- do the symbol defs IF debugging THEN WriteLine["Starting on Definitions."]; DoDefs[Ndefs]; -- Put top level instances in symbol 'Top' Top _ FinishDefNbr; FinishDefNbr _ FinishDefNbr + 1; IF debugging THEN WriteLine["Starting on Items."]; DefineSymbol[Top,A,B,""]; WHILE NOT fin.endof[fin] DO ItemOutput[]; ENDLOOP; DefineFinish[]; -- One call format PutCall[Top,FALSE,FALSE,[LONG[1],LONG[0]],[LONG[0],LONG[0]]]; PutEnd[]; fin.destroy[fin]; RETURN[error_FatalError, Ndefs_FinishDefNbr-StartDefNbr]; END; ArraySymbolHoldingCell:TYPE = POINTER TO ArraySymbolHoldingCellRecord; ArraySymbolHoldingCellRecord:TYPE = RECORD [ next: ArraySymbolHoldingCell, symblNo,callNo:INTEGER, mirx,miry:BOOLEAN, rot:Point, yorigin,ydisp:LONG INTEGER, ycount:INTEGER ]; CellList: ArraySymbolHoldingCell _ NIL; (1792)\500b7B1316b3B142b5B237b7B213b12B96b2B6b2B48b2B48b2B8b7B231b14B990b15B869b12B123b8B80b10B3329b6B821b12B116b12B378b8B113b7B one: REAL _ 1; two: REAL _ 2; half:REAL _ one/two; SqrtOf2: REAL _ SqRt[two]; NearThousand: REAL _ 999; NearOne: REAL _ NearThousand/1000; END.