!****************************************************************************** !****************************************************************************** ! specs in same order as in perqimports file %routine %spec buried contacts { pla & stacks with no burried contacts %routine %spec butting contacts %string (2) %fn %spec contacts %integer %map %spec ILAP control { This allows the control over ILAP %routine %spec warn %alias "ILAPWARNING" (%string(255) s) %routine %spec die %alias "ILAPDISASTER" (%string (255) s) %routine %spec update mbb %alias "ILAPUPDATEMBB" (%integer xl, yl, xu, yu) %routine %spec dump comment (%string (255) s) %routine %spec symbol (%string (31) name) %routine %spec external symbol spec (%string (31) name, %integer num, xl, yl, xu, yu) %routine %spec symbol spec (%string (31) name, %integer xl, yl, xu, yu) %routine %spec end symbol %routine %spec ax (%integer u) %routine %spec ay (%integer v) %routine %spec axy (%real x, y) %routine %spec dx (%integer u) %routine %spec dy (%integer v) %routine %spec dxy (%real dx, dy) %routine %spec wirex (%integer x, y, l) %routine %spec wirey (%integer x, y, l) %routine %spec box %alias "ILAPBOX" (%integer xl, yl, xu, yu) %routine %spec polygon %alias "ILAPPOLYGON" (%real x, y) %routine %spec line %alias "ILAPLINE" (%real x, y) %routine %spec ETPX (%string (31) name, %integer x, y, l) %routine %spec ETPY (%string (31) name, %integer x, y, l) %routine %spec ETDX (%string (31) name, %integer x, y, l) %routine %spec ETDY (%string (31) name, %integer x, y, l) %routine %spec DTPX (%string (31) name, %integer x, y, l) %routine %spec DTPY (%string (31) name, %integer x, y, l) %routine %spec DTDX (%string (31) name, %integer x, y, l) %routine %spec DTDY (%string (31) name, %integer x, y, l) %routine %spec DTDBX (%string (31) name, %integer x, y, l) %routine %spec DTDBY (%string (31) name, %integer x, y, l) %routine %spec layer (%string (4) colour) %string (4) %fn %spec C LAYER %routine %spec WIDTH (%integer W) %integer %fn %spec C WIDTH %routine %spec draw (%string (31) name, %integer x, y) %routine %spec draw mx (%string (31) name, %integer x, y) %routine %spec draw my (%string (31) name, %integer x, y) %routine %spec draw rot (%string (31) name, %integer x, y, rot) %routine %spec draw mx rot (%string (31) name, %integer x, y, rot) %routine %spec draw my rot (%string (31) name, %integer x, y, rot) %routine %spec cif comment (%string (255) s) %routine %spec user extension (%integer no, %string (255) s) %integer %fn %spec sx (%string (31) cell) %integer %fn %spec sy (%string (31) cell) %integer %fn %spec lx (%string (31) cell) %integer %fn %spec ly (%string (31) cell) %integer %fn %spec symbol exists (%string (31) name) %routine %spec set lambda (%integer L) %routine %spec first cell number (%integer I) %routine %spec MERGE ON %routine %spec MERGE OFF %routine %spec DRC ON %routine %spec DRC OFF %routine %spec SET ERROR STREAM (%integer I) %routine %spec SET CIF STREAM (%integer I) %routine %spec INITIALISE NMOS (%string (255) ofile) %routine %spec INITIALISE CMOS (%string (255) ofile) %routine %spec finish %routine %spec give statistics !****************************************************************************** !****************************************************************************** %own %string (31) VERSION = "Imp LAP Version 4.2Q 10-Feb-83" !****************************************************************************** !****************************************************************************** !*** *** !*** This is ILAP *** !*** or *** !*** Imp LAP *** !*** *** !****************************************************************************** !****************************************************************************** ! ! ! INTRODUCTION: ! ! ILAP is a series of external Imp77 procedures which allow the ! creation of syntactically correct CIF2.0 representations of integrated ! circuit layouts. By embedding a graphics capability into a high level ! language, the use of control structures and parameterised symbols is ! made available to the designer. ! ! ! DESCRIPTION: ! ! ILAP contains procedures to draw shapes on different mask layers and ! define symbols made of such shapes. The actual individual procedures ! are described below. However, it is important to note here that ILAP is ! very close to CIF 2.0, and that almost all procedure calls translate ! directly into CIF 2.. Consequently, where the results of certain ! constructions are not described the reader is referred to the definition ! of CIF2.0 given in Mead and Conway's "Introduction to VLSI Systems" ! (chapter 4, section 4.5). ! ! ! DIFFERENCES FROM CIF2.0: ! ! The major differences and restrictions of ILAP from CIF2.0 are summarised below. ! ! All primitive shapes and symbol calls should be in symbols. ! Boxes cannot be specified other than parallel to the axes. ! Symbols can only be rotated parallel to the axes. ! Symbol calls which specify rotation or mirroring are rotated or ! mirrored before translation. ! No symbol definition delete statement. ! ! ! ACCURACY: ! ! All units (i.e. widths, heights, lengths and displacements), are ! specified in terms of lambda. Lambda is the distance by which a ! geometrical feature on one layer may stray from another geometrical ! feature on the same layer or on another layer with all processing ! factors considered and an appropriate safety factor added. The design ! rules given in Mead and Conway are given in terms of lambda. Accuracy ! of all units is preserved to one tenth lambda. ! ! ! The next 20 lines are operating system dependent possibly %external %integer %fn %spec REM (%integer A, B) %const %string (1) snl = " " %own %integer cif stream = 1 {normally 3} %own %integer error stream = 0 %external %routine %spec prompt (%string (63) s) %external %string (63) %fn %spec itos (%integer n, s) %external %string (15) %fn %spec timestamp %external %routine %spec check (%string (31) s, %byte %array %name data, %short %array %name tran ids, %integer xmax, ymax, xorigin, yorigin) %external %routine %spec monitor %alias "ILAPMONITOR" (%string (255) s); ! Timings %external %byte %integer %fn %spec default technology !%system %routine %spec exit (%integer code) !******************************************************************************* ! specs for external routines in file IMPIOCPI %externalroutinespec openinput(%integer stream,%string(100) filename) %externalintegerfnspec instream %externalstring(100)%fnspec infilename(%integer stream) %externalroutinespec closeinput(%integer stream) %externalroutinespec openoutput(%integer stream,%string(100) filename) %externalintegerfnspec outstream %externalstring(100)%fnspec outfilename(%integer stream) %externalroutinespec closeoutput(%integer stream) !******************************************************************************* %const %integer true = 0, false = 1 %const %integer smallest = -16_7FFF { maximum bounding box size in lambda %const %integer largest = 16_7FFF { ditto %const %integer max symbols = 255 { Must be a power of 2 minus 1 for 'lookup' to work %const %integer max boxes = 1000 { Maximum boxes in a symbol %const %integer cifscale = 20 { All values are multiplied by this and the integer part taken %const %integer Polygon Type = 1, Line Type = 2 %const %integer ETPX type = 3, ETPY type = 4 %const %integer ETDX type = 5, ETDY type = 6 %const %integer DTPX type = 7, DTPY type = 8 %const %integer DTDX type = 9, DTDY type = 10 %const %integer DTDBX type = 11, DTDBY type = 12 %const %integer Wire type = 13 %const %integer Max type = 13 %const %integer up = 0, down = 1, left = 2, right = 3, none = 4 %const %integer Tr bit = 128 { Indicates that the layer number is part of a transistor %const %integer Tr layer = 7 %const %integer no tr bit = \ Tr bit %const %integer violations = 64 %const %integer max layer = 15 %own %integer last layer = 9 %own %integer last merged layer = 7 %const %integer diff layer = 0 %const %integer poly layer = 1 ! The following arrays are for Nmos. ! The Cmos initialisation changes NI to CW and NB to CS %own %byte %array layer mnemonics (0:max layer) = 'D', 'P', 'M', 'I', 'B', 'C', 'V', 'T', 'G', 'X', '?' (*) %own %string (15) %array layer names (0:max layer) = "diffusion", "polysilicon", "metal", "implant", "buried", "contact", "violations", "transistors", "glass", "NX", "undefined" (*) %own %integer %array widths (0:max layer) = 0(*) %own %integer %array default widths (0:max layer) = 2, 2, 3, 6, 4, 2, 0, 2, 40, 0 (*) %const %string (35) after init = " must be called before INITIALISE" %record %format symdef(%string(31) name, %integer number, geometry, calls, xl, yl, xu, yu, trans);! Symbol Table Entry format %own %record (symdef) %array symbol table(-1:max symbols) = 0(*) { Symbol Table %own %byte symbols speced = false %const %record (symdef) %name null symbol = 0 %own %record (symdef) %name current symbol { current symbol %own %record (symdef) %name call symbol { symbol currently being called %record %format boxf (%short lx, ly, ux, uy, %byte layer) %own %record (boxf) %array boxes (0:max boxes) %own %integer next box=0 %own %string(31) current transistor name { name of transistor %own %string (3) layer before transistor="" { restored after each transistor %own %byte technology = '?' { Type of MOS. %own %integer current point { index for path %own %integer current type { path type %own %integer current width { for Wires %own %integer init = false { Set TRUE after initialise called %own %integer statements { CIF statement count %own %integer warnings { Error report counter %own %integer current stream { Holds current stream selected by caller %own %integer initial symbol = 100 { Set to first CIF symbol number required can be set by users %own %integer seqno { Number of current symbol %own %integer wlx, wly, wux, wuy, wdir { Wire box bounds (also used for transistor gates)} %own %integer olx, oly, oux, ouy { Transistor overlap boxes } %own %string (3) gate layer, overlap layer %own %byte depletion transistor = false { type of tran being defined } %own %byte first transistor box = false %own %integer lambda = 300 { Number of 100ths of a micron in each unit distance %const %string (1) butting = "C", buried = "B" %own %string (1) contact type = "B" %external %routine buried contacts { pla & stacks with no buried contacts contact type=buried %end %external %routine butting contacts contact type = butting %end %external %string (2) %fn contacts %result = contact type %end %own %integer control = 0 %external %integer %map ILAP control { This allows the control over ILAP %result == control %end %const %integer no warnings = 1 { Suppress warning messages %const %integer monitor endsym = 2 { Gives a message on ENDSYM %const %integer give times = 4 { Monitor CPU use %const %integer merge = 8 { Produce merged CIF %const %integer design rule check = 16 { Turns on DRC %const %integer circuit analysis = 32 { Let Natalie loose on the design! %const %integer give node list = 64 { Ask for a list of nodes %const %integer give tran list = 128 { Ask for a list of transistors %const %integer give node plot = 256 { Ask for a plot of the extracted circuit. %own %integer current layer = -1, previous layer = -1 ! The significance of the layer integer is - ! <0 => no layer defined ! 0<= layer&noTRbit <=max layer => a known layer (from array) %string(63)%fn layer name(%integer cif name) cif name = cif name & no tr bit %result = layer names(cif name) %if 0<=cif name<=max layer %result = "undefined" %end %external %routine warn %alias "ILAPWARNING" (%string(255) s) !Outputs a warning message plus some additional information on an error !Also keeps a count of number of warnings %integer i %return %if control & no warnings # 0 i = out stream select output (error stream) print string ("Warning: ") print string (s) print string (" on layer ".layer name(current layer)) %if current layer>=0 print string (" in symbol ".current symbol_name) %if current symbol##null symbol newline select output (i) warnings = warnings + 1 %end %external %routine die %alias "ILAPDISASTER" (%string (255) s) ! Abort the program, after a disastrous error. select output (error stream) print string ("Disaster: ") print string (s) print string (" in symbol ".current symbol_name) %if current symbol##null symbol newline ! exit (16_10000000 + 42) %end %string (63) %fn W P or Tran (%integer current type) ! Returns a string with 'Transistor Polygon or Wire' ! Current point<1 is none or all %const %string (7) %array type(1:max type) = "Polygon", "Line", "ETPX", "ETPY", "ETDX", "ETDY", "DTPX", "DTPY", "DTDX", "DTDY", "DTDBX", "DTDBY", "Wire" %result = "Transistor, Polygon, or Wire" %if current point<1 %result = type(current type) %end %string (31) %fn at point (%integer x, y) %result = " at (X=".itos(x,0)." Y=".itos(y,0).")" %end %routine layer check ! check that user has specified a layer to output on warn ("Layer not defined") %if current layer<0 %end %routine warn outside symbol (%string (255) s, %integer x, y) ! warn a user that geometry of a call is outside a symbol warn (s." outside a symbol".at point(x,y)) %end %routine out num (%integer n) ! Outputs a number in the minimum digits space; write (n, 0) %end %routine initialise (%string (255) ofile) %string(255) s1,s2 %integer i, char %return %if init=true; !already initialised current stream = out stream select output (error stream) print string (version); newline %if ofile="" %start prompt ("File name:") read symbol (char) %until char > ' ' %cycle ofile = ofile.tostring(char) %if char#' ' read symbol (char) %repeat %until char < ' ' %finish %unless ofile->s1.(".").s2 %then ofile=ofile.".cif" open output (cif stream, ofile) init = true symbol table (i) = 0 %for i = -1, 1, max symbols current point = -1 current symbol == null symbol statements = 0 warnings = 0 %if initial symbol<0 %start warn("Initial symbol ".itos(initial symbol,0)." invalid") initial symbol = 100 %finish seqno = initial symbol - 1 technology = default technology %if technology = '?' widths(i)=default widths(i) %for i=0,1,max layer current layer = -1 select output (cif stream) dump comment ("CIF 2.0") dump comment ("File ".ofile) dump comment ("Produced ".timestamp." by ".version) dump comment ("Lambda =".itos(lambda,3)." hundredths of a micron") select output (current stream) %end %routine new layer (%string (4) colour) %integer new layer, i, current stream warn outside symbol("Set layer",0,0) %if current symbol==null symbol colour = to string (technology).colour %if length(colour) = 1 current layer = -1 %and %return %if colour = ""; ! Forget current layer %if length(colour)=2 %start new layer = -1 %for I = 0, 1, last layer %cycle new layer = i %if layer mnemonics(i)=charno(colour,2) %repeat new layer = new layer ! Tr bit %if new layer >=0 %and current transistor name # "" %if new layer = -1 %start ! Try to add it : DIE ("Too many layers used") %if last layer = max layer last layer = last layer + 1 layer mnemonics (last layer ) = charno (colour,2) layer names (last layer) = colour new layer = last layer %finish %return %if current layer=new layer current layer=new layer %finish %else %start current layer = max layer layer names (max layer) = colour %finish %if control < merge %or new layer & no tr bit > last merged layer %start current stream = out stream select output (cif stream) print symbol ('L'); space; print string (colour); print symbol (';') newline select output (current stream) statements = statements + 1 %finish %end %external %routine update mbb %alias "ILAPUPDATEMBB" (%integer xl, yl, xu, yu) ! Updates if necessary the minimum bounding box of the current symbol %return %if current symbol==null symbol current symbol_xl=xl %if xlcurrent symbol_xu current symbol_yu=yu %if yu>current symbol_yu %end %integerfn lookup(%string(31)name) !Finds the specified name in the Symbol Table or allocates a new entry !Names are converted to a canonical form (see fn CANONICAL below) !Returns entry -1 if the Symbol Table is full %integer val, i %string(31) %fn canonical(%string(31) name) !Returns parameter in a canonical form i.e. only upper case and spaces removed %string(31) canon name %integer i,char canon name = "" %for i = 1,1,length(name) %cycle char = charno(name,i) char = char-('a'-'A') %if 'a'<=char<'z'; !Lower case to Upper case canon name = canon name.tostring(char) %if char#' ';!Remove spaces %repeat %result = canon name %end name = canonical(name) val = 0 val = val+charno(name,i)<<(i-1) %for i=1,1,length(name) i = val&max symbols i = (i+1)&max symbols %until canonical(symbol table(i)_name)=name %orc symbol table(i)_number=0 %or i=val&max symbols %result = i %unless i=val&max symbols %result = -1 %end %const %integer choose sx = 0, choose sy = 1, choose lx = 2, choose ly = 3 %integer %fn get mbb (%string (31) cell, %integer which) %const %string (2) %array proc (0:3) = "SX", "SY", "LX", "LY" %record (symdef) %name entry %switch sw (0:3) initialise ("") %if init=false entry == symbol table (lookup(cell)) %if entry_number>0 %start %if entry_xu<=entry_xl %or entry_yu<=entry_yl %start warn (proc(which)." is undefined") %result = 0 %finish warn (proc(which)." is of the current symbol") %if entry==current symbol -> sw(which) sw (choose sx): %result = entry_xu - entry_xl sw (choose sy): %result = entry_yu - entry_yl sw (choose lx): %result = entry_xl sw (choose ly): %result = entry_yl %finish warn ("Symbol """.cell.""" not defined for ".proc(which)) %result = 0 %end %external %routine dump comment (%string (255) s) %integer current stream current stream = out stream select output (cif stream) print symbol ('('); print string (s); print string (");"); newline statements = statements + 1 select output (current stream) warn ("Comment contains brackets") %if s -> ("(") warn ("Comment extends across a line") %if s -> (snl) %end %routine dump (%string (15) start, %real x, y) ! Start dumping the code for either a polygon or a line current stream = out stream select output (cif stream) print string (start) wlx = int (x); wly = int (y) olx = wlx; oly = wly out num (int(x*cif scale)) out num (int(y*cif scale)) current point = 1 select output (current stream) %end %routine dump point (%real x, y) current stream = out stream select output (cif stream) out num (int(x*cif scale)) out num (int(y*cif scale)) wlx = int(x); wly = int(y) update mbb (olx, oly, wlx, wly) current point = current point + 1 newline %if current point & 7 = 0 select output (current stream) %end %routine dump box (%integer xl, yl, xu, yu) current stream = out stream select output (cif stream) print symbol ('B') outnum ((xu-xl)*cifscale) outnum ((yu-yl)*cifscale) outnum (int(((xu+xl)*cifscale)/2)) outnum (int(((yu+yl)*cifscale)/2)) print symbol (';') newline statements = statements+1 select output (current stream) %end %routine output box(%integer xl, yl, xu, yu) ! Saves a box given any diagonally opposite corners ! or outputs it if the layer is not to be saved. %record(boxf)%name box %integer i, l %if xu= merge %and 0<=l<=last merged layer %start %if next box<=max boxes %start box == boxes(next box) box_ly <- yl; box_lx <- xl; box_uy <- yu; box_ux <- xu; box_layer<-current layer next box = next box + 1 %finish %else die ("Too many boxes") %finish %else dump box (xl, yl, xu, yu) %end %routine output expanded box (%integer xl, yl, xu, yu, expand, direction, which box, last) ! Saves an expanded box given any diagonally opposite corners %integer i %if xu=yy-y %start xxlim=xx-1 %exit %finish %else %start yy=yy-1 ->boxout %finish %finish %repeat %repeat boxout: put box(x+originx,y+originy,xxlim+originx+1,yy+originy+1,p) %for j=y,1,yy %cycle %for i=x,1,xxlim %cycle pixel == bit map(i, j) pixel = pixel&(\mask) %repeat %repeat %finish %repeat %repeat %repeat %end %routine Transistor Polygon or Wire check ! Checks if a path of points is being produced if so outputs a set of boxes ! Minimum points for a line is 2 ! Minimum points for a polygon is 3 %switch type (1:max type) %integer i initialise("") %if init=false; !User has not called initialise do it for him %return %if current point<0; !Nothing happening %if current type=Polygon Type %and current point>2 %and (olx#wlx %or oly#wly) %start warn("Polygon not closed".at point(wlx, wly)) %finish i = current point current point = -1 %if (current type=Line type %and i=1) %or (current type=Polygon type %and i=2) %start warn("Incomplete ".W P or Tran(current type).at point(wlx, wly)) %return %finish -> type (current type) type (polygon type): type (line type): current stream = out stream select output (cif stream) Print symbol (';'); newline select output (current stream) statements = statements + 1 %return type (wire type): output box (wlx, wly, wux, wuy) %return type (ETPX type): type (ETPY type): type (ETDX type): type (ETDY type): type (DTPX type): type (DTPY type): type (DTDX type): type (DTDY type): type (DTDBX type): type (DTDBY type): new layer (overlap layer) output box (olx, oly, oux, ouy) ! Extend the gate in the direction that we last went in. %if wdir=up %start wuy = wuy + 2; ouy = ouy + 2 %finish %else %if wdir=down %start wly = wly - 2; oly = oly - 2 %finish %else %if wdir=right %start wux = wux + 2; oux = oux + 2 %finish %else %start { left } wlx = wlx - 2; olx = olx - 2 %finish do transistor implant %if depletion transistor = true new layer (gate layer) output box (wlx, wly, wux, wuy) current transistor name = "" depletion transistor = false new layer (layer before transistor) %end %integer %fn draw first (%string (31) name, %integer x, y) ! Checks if a symbol is defined if it is output first part of call ! Used in conjunction with drawlast %record (symdef)%name entry Transistor Polygon or Wire check entry == symbol table (lookup (name)) %if entry_number = 0 %start warn ("Call on undefined symbol ".name.at point(x,y)) %result = false %finish %else %start %if entry==current symbol %start warn ("Recursive call on symbol ".name.at point(x,y)) %result = false %finish %else %start %if current symbol##null symbol %start current symbol_calls = current symbol_calls + 1 current symbol_trans = current symbol_trans + entry_trans %finish %else warn outside symbol ("Call of ".name,x,y) current stream = out stream select output(cif stream) print symbol ('C') outnum (IMOD(entry_number)) call symbol == entry %result = true %finish %finish %end %string (3) %fn rotation (%integer %name ROT) ! return the rotation component and also normalise ROT to the range 0 to 3 %const %string (4) %array rotations (0:3) = "1 0", "0 1", "-1 0", "0 -1" rot = rem(rem(rot,4)+4,4); !normalise rotation %result = " R ".rotations(rot) %end %routine draw last (%string (15) transform, %integer x, y) ! Outputs final part of symbol call. ! first the transformation information, and then the translation to new x,y print string (transform) print string (" T") outnum (x*cifscale); outnum (y*cifscale); print symbol (';'); newline statements = statements + 1 select output (current stream) %end %routine shape check (%string (15) shape, %integer X, Y) Transistor Polygon or Wire check layer check %if current symbol##null symbol %start current symbol_geometry = current symbol_geometry+1 %finish %else warn outside symbol (shape, x, y) %end %routine check current symbol %integer cxl, cxu, cyl, cyu, cxd, cyd cxl = current symbol_xl cyl = current symbol_yl cxu = current symbol_xu cyu = current symbol_yu cxd = cxu-cxl-1 cxd = 3 %if cxd<3; ! 0:3 is minimum size that can be DRCed cyd = cyu-cyl-1 cyd = 3 %if cyd<3 %begin %integer i,j,x,y,bit,checks, yl, yu %record(boxf) %name box %byte %array bit map (0 : cxd, 0 : cyd) %short %array tran names (0 : cxd, 0 : cyd) %byte %name pixel %integer %fn extend (%short I) { I = I ! 16_FFFF0000 %if I&16_8000#0 ;! for EMAS only} %result = I %end %for i = 0, 1, cxd %cycle bit map(i,j) = 0 %for j = 0, 1, cyd %repeat checks = 0 %for i = 0, 1, next box-1 %cycle box == boxes(i) bit = 1<<(box_layer¬rbit) ! (box_layer&trbit) checks = checks ! bit yl = extend (box_ly) - cyl yu = extend (box_uy) - cyl - 1 %for x = extend (box_lx)-cxl, 1, extend (box_ux)-cxl-1 %cycle %for y = yl, 1, yu %cycle pixel == bit map(x,y) pixel = pixel ! bit %repeat %repeat %repeat %if control >= design rule check %start monitor ("Starting DRC") %if control & give times # 0 check (current symbol_name, bit map, tran names, cxd, cyd, cxl, cyl) %finish checks = checks ! violations; ! To ensure that they are drawn. monitor ("Start of Bit map to boxes") %if control & give times #0 bit map to boxes (bit map, cxd, cyd, cxl, cyl, checks) monitor ("End of Bit map to boxes ") %if control & give times # 0 next box = 0 %end %end !*** !*** !*** Everything before this point is internal to ILAP !*** Everything after this point is available externally !*** !*** %external %routine symbol (%string (31) name) %record (symdef) %name entry Transistor Polygon or Wire check %if current symbol##null symbol %start warn("Nested symbol definition ".name) endsymbol %finish entry == symbol table(lookup(name)) %if entry##symbol table (-1) %start %if entry_number>0 %then warn ("Multiply defined symbol ".name) seqno = seqno+1 %if entry_number = 0 { if it has not been spec'd } previous layer = current layer current layer = -1 current symbol == entry %if current symbol_number=0 %start ! Note that all fields have value 0 if not assigned. current symbol_number = seqno current symbol_name = name current symbol_xl = largest; current symbol_yl = largest current symbol_xu = smallest; current symbol_yu = smallest %finish %else current symbol_number = IMOD(current symbol_number) current stream = out stream select output (cif stream) print string ("DS") outnum (current symbol_number); outnum (lambda); outnum (cifscale); print symbol (';') user extension (9, name) statements = statements + 1 select output (current stream) %finish %else die ("Symbol Table Full adding ".name) monitor ("Start of symbol """.name."""") %if control & give times # 0 %end %external %routine external symbol spec (%string (31) name, %integer num, xl, yl, xu, yu) %string(255) line %record (symdef) %name entry Transistor Polygon or Wire check %if 0initial symbol+max symbols %start entry==symbol table(lookup(name)) %if entry##symbol table(-1) %start %if entry_number#0 %then warn ("External symbol ".name." conflicts with internal definition") entry_number=-num; entry_name=name entry_xl=xl; entry_yl=yl entry_xu=xu; entry_yu=yu warn ("Invalid MBB for external symbol ".name) %if xl>=xu %or yl>=yu line=name line = itos (yu * lambda,0).",".line line = itos (xu * lambda ,0).",".line line = itos (yl * lambda ,0).",".line line = itos (xl * lambda ,0).",".line line = itos (num, 0).",".line user extension (8, line) %finish %else die ("Symbol Table Full adding external symbol ".name) %finish %else warn ("External symbol ".name." number ".itos(num,0)." conflicts with internal numbers") %end %external %routine symbol spec (%string (31) name, %integer xl, yl, xu, yu) %record (symdef) %name entry Transistor Polygon or Wire check entry == symbol table(lookup(name)) %if entry##symbol table (-1) %start %if entry_number#0 %then warn ("Symbol ".name." conflicts with previous definition") seqno = seqno+1 previous layer = current layer current layer = - 1 entry_number = - seqno entry_name = name entry_xl = xl; entry_yl = yl entry_xu = xu; entry_yu = yu %finish %else die ("Symbol Table Full adding ".name) symbols speced = true %end %external %routine end symbol %integer i %string (255) diags Transistor Polygon or Wire check %if current symbol##null symbol %start %if control # 0 %start diags = "End of symbol """.current symbol_name."""" %if control & monitor end sym # 0 %start diags = diags.itos(current symbol_xl,1).itos(current symbol_yl,1) diags = diags.itos(current symbol_xu,1).itos(current symbol_yu,1) %finish monitor (diags) %if control & (monitor end sym ! give times) # 0 %finish current layer = previous layer widths(i)=default widths(i) %for i=0,1,max layer %if current symbol_geometry>0 %start check current symbol %if control >= merge %finish %else %start %if control >= design rule check %start current stream = out stream select output (0) newline print string ("No check of symbol ".current symbol_name) newline select output (current stream) %finish %finish current stream = out stream select output (cif stream) print string ("DF;"); newlines(2) statements = statements + 1 select output (current stream) %if current symbol_xl=largest %and current symbol_yl=largest %and %c current symbol_xu=smallest %and current symbol_yu=smallest %start warn ("No geometry") current symbol_xl=0; current symbol_yl=0 current symbol_xu=0; current symbol_yu=0 %finish current symbol == null symbol %finish %else warn ("Unmatched endsymbol") %end %external %routine ax (%integer u) %if polygon type # current type # line type %start %unless wlx0 %start wlx = wux; wux = wux + u; wdir = right %finish %else %start wux = wlx; wlx = wlx + u; wdir = left %finish olx = wlx; oux = wux; oly = wly - 2; ouy = wuy + 2 %finish %else warn ("DX of ".W P or Tran (current type)." is zero") %finish %else dump point (wlx+u, wly) %end %external %routine dy (%integer v) %if polygon type # current type # line type %start %if v#0 %start %if current type # wire type %start ! Transistor %if wdir=right %start oux = oux + 2 %finish %else %if wdir=left %start olx = olx - 2 %finish new layer (overlap layer) output box (olx, oly, oux, ouy) do transistor implant %if depletion transistor = true new layer (gate layer) %finish output box (wlx, wly, wux, wuy) %if up#wdir#down %start %if wdir=right %then wlx=wux-current width %else wux=wlx+current width %finish %if v>0 %start wly = wuy; wuy = wuy + v; wdir = up %finish %else %start wuy = wly; wly = wly + v; wdir = down %finish olx = wlx - 2; oux = wux + 2; oly = wly; ouy = wuy %finish %else warn ("DY of ".W P or Tran (current type)." is zero") %finish %else dump point (wlx, wly+v) %end %external %routine dxy (%real dx, dy) %unless polygon type # current type # line type %start dump point (wlx+dx, wly+dy) %finish %else warn ("Only polygons and lines may use the DXY construct") %end %external %routine wirex (%integer x, y, l) shape check ("Wirex", x, y) %return %if cwidth<=0 current type = wire type current width = cwidth current point = 0 %if l < 0 %start wlx = x + l; wux = x; wdir = left %finish %else %if l > 0 %start wlx = x; wux = x + l; wdir = right %finish %else %start warn ("Zero length Wirex".at point (x, y)) %finish wly = y; wuy = y + current width { Note the box is buffered and is output when a new one is to be buffered } %end %external %routine wirey (%integer x, y, l) shape check ("Wirey", x, y) %return %if cwidth<=0 current type = wire type current width = cwidth current point = 0 %if l < 0 %start wly = y + l; wuy = y; wdir = down %finish %else %if l > 0 %start wly = y; wuy = y + l; wdir = up %finish %else %start warn ("Zero length Wirey".at point(x,y)) %finish wlx = x; wux = x + current width { Note the box is buffered and is output when a new one is to be buffered } %end %external %routine box %alias "ILAPBOX" (%integer xl, yl, xu, yu) shape check ("Box", xl, yl) %if xl=2 %start %if l#0 %start layer before transistor = clayer current transistor name = name current type = Type current width = w current point = 0 gate layer = gate overlap layer = overlap depletion transistor = true %if DTPX type <= type <= DTDBY type first transistor box = true %if dir='X' %start %if l>0 %start wlx = x; wux = x + l; wdir = right %finish %else %start wlx = x + l; wux = x; wdir = left %finish wly = y; wuy = y + w olx = wlx; oux = wux; oly = wly - 2; ouy = wuy + 2 %if l>0 %then wlx=wlx-2 %else wux=wux+2 %finish %else %start %if l>0 %start wly = y; wuy = y + l; wdir = up %finish %else %start wly = y + l; wuy = y; wdir = down %finish wlx = x; wux = x + w olx = wlx - 2; oux = wux + 2; oly = wly; ouy = wuy %if l>0 %then wly=wly-2 %else wuy=wuy+2 %finish %if current symbol ## null symbol %then current symbol_trans = current symbol_trans + 1 %finish %else warn ("Zero length ".W P or Tran(type).at point(x,y)) %finish %else warn("Invalid ".W P or Tran(type)." width <2".at point(x,y)) %end %external %routine ETPX (%string (31) name, %integer x, y, l) start tran (name, x, y, l, widths(poly layer), 'X', ETPX type, "P", "D") %end %external %routine ETPY (%string (31) name, %integer x, y, l) start tran (name, x, y, l, widths(poly layer), 'Y', ETPY type, "P", "D") %end %external %routine ETDX (%string (31) name, %integer x, y, l) start tran (name, x, y, l, widths(diff layer), 'X', ETDX type, "D", "P") %end %external %routine ETDY (%string (31) name, %integer x, y, l) start tran (name, x, y, l, widths(diff layer), 'Y', ETDY type, "D", "P") %end %external %routine DTPX (%string (31) name, %integer x, y, l) start tran (name, x, y, l, widths(poly layer), 'X', DTPX type, "P", "D") %end %external %routine DTPY (%string (31) name, %integer x, y, l) start tran (name, x, y, l, widths(poly layer), 'Y', DTPY type, "P", "D") %end %external %routine DTDX (%string (31) name, %integer x, y, l) start tran (name, x, y, l, widths(diff layer), 'X', DTDX type, "D", "P") %end %external %routine DTDY (%string (31) name, %integer x, y, l) start tran (name, x, y, l, widths(diff layer), 'Y', DTDY type, "D", "P") %end %external %routine DTDBX (%string (31) name, %integer x, y, l) start tran (name, x, y, l, widths(diff layer), 'X', DTDBX type, "D", "P") new layer ("NB"); output box (x-2, y-1, x+2, y+widths(diff layer)+1) %end %external %routine DTDBY (%string (31) name, %integer x, y, l) start tran (name, x, y, l, widths(diff layer), 'Y', DTDBY type, "D", "P") new layer ("NB"); output box (x-1, y-2, x+widths(diff layer)+1, y+2) %end %external %routine layer (%string (4) colour) Transistor Polygon or Wire check new layer (colour) %end %external %string (4) %fn C LAYER ! returns the current layer %integer layer layer = current layer & no tr bit %result = to string (technology).to string (layer mnemonics (layer)) %if 0<=layer<=last layer %result = "" %end %external %routine WIDTH (%integer W) ! sets the width of Wires and transistors in the current layer %if w > 0 %start %if current layer >= 0 %start widths (current layer) = W %finish %else warn ("No layer is set") %finish %else warn ("Invalid setting for WIDTH (".itos(W,0).")") %end %external %integer %fn C WIDTH ! returns the current width %integer layer layer = current layer & no tr bit %result = widths (layer) %if 0 <= layer <= last layer %result = 2 %end %external %routine draw (%string (31) name, %integer x, y) %if drawfirst(name,x,y)=true %start draw last ("", x, y) update mbb (call symbol_xl+x, call symbol_yl+y, call symbol_xu+x, call symbol_yu+y) %finish %end %external %routine draw mx (%string (31) name, %integer x, y) %if drawfirst(name,x,y)=true %start draw last (" MX", x, y) update mbb (-call symbol_xu+x, call symbol_yl+y, -call symbol_xl+x, call symbol_yu+y) %finish %end %external %routine draw my (%string (31) name, %integer x, y) %if drawfirst(name,x,y)=true %start draw last (" MY", x, y) update mbb (call symbol_xl+x, -call symbol_yu+y, call symbol_xu+x, -call symbol_yl+y) %finish %end %external %routine draw rot (%string (31) name, %integer x, y, rot) %if drawfirst(name,x,y)=true %start draw last (rotation (rot), x, y) %if rot=0 %start; ! In first quadrant update mbb(call symbol_xl+x, call symbol_yl+y, call symbol_xu+x, call symbol_yu+y) %finish %else %if rot=2 %start; ! In third quadrant update mbb(-call symbol_xu+x,-call symbol_yu+y, -call symbol_xl+x,-call symbol_yl+y) %finish %else %if rot=1 %start; ! In Second quadrant update mbb(-call symbol_yu+x, call symbol_xl+y, -call symbol_yl+x, call symbol_xu+y) %finish %else %start; ! In Fourth quadrant update mbb(call symbol_yl+x,-call symbol_xu+y, call symbol_yu+x,-call symbol_xl+y) %finish %finish %end %external %routine draw mx rot (%string (31) name, %integer x, y, rot) %if drawfirst(name,x,y)=true %start draw last (" MX".rotation (rot), x, y) %if rot=0 %start update mbb(call symbol_xu+x, call symbol_yl+y, call symbol_xl+x, call symbol_yu+y) %finish %else %if rot=2 %start update mbb(-call symbol_yu+x,-call symbol_xu+y, -call symbol_yl+x,-call symbol_xl+y) %finish %else %if rot=1 %start update mbb(call symbol_xl+x, -call symbol_yl+y, call symbol_xu+x, -call symbol_yu+y) %finish %else %start update mbb(call symbol_yl+x,call symbol_xl+y, call symbol_yu+x,call symbol_xu+y) %finish %finish %end %external %routine draw my rot (%string (31) name, %integer x, y, rot) %if drawfirst(name,x,y)=true %start draw last (" MY".rotation (rot), x, y) %if rot=0 %start update mbb(call symbol_xl+x, call symbol_yu+y, call symbol_xu+x, call symbol_yl+y) %finish %else %if rot=2 %start update mbb (-call symbol_xu+x, call symbol_yl+y, -call symbol_xl+x, call symbol_yu+y) %finish %else %if rot=1 %start update mbb(call symbol_yl+x,call symbol_xl+y, call symbol_yu+x,call symbol_xu+y) %finish %else %start update mbb(call symbol_xl+x, -call symbol_yl+y, call symbol_xu+x, -call symbol_yu+y) %finish %finish %end %external %routine cif comment (%string (255) s) Transistor Polygon or Wire check dump comment (s) %end %external %routine user extension (%integer no, %string (255) s) %integer current stream Transistor Polygon or Wire check %if 0<=no<=9 %start warn ("User extension contains a ';' truncated before it") %if s->s.(";") current stream = out stream select output (cif stream) outnum (no); space; print string (s); print symbol (';'); newline statements = statements + 1 select output (current stream) %finish %else warn ("Invalid user extension ".itos(no,0)) %end %external %integer %fn sx (%string (31) cell) %result = get mbb (cell, choose sx) %end %external %integer %fn sy (%string (31) cell) %result = get mbb (cell, choose sy) %end %external %integer %fn lx (%string (31) cell) %result = get mbb (cell, choose lx) %end %external %integer %fn ly (%string (31) cell) %result = get mbb (cell, choose ly) %end %external %integer %fn symbol exists (%string (31) name) %record (symdef) %name entry initialise ("") %if init=false entry == symbol table (lookup(name)) %if entry_number=0 %then %result=false %else %result=true %end %external %routine set lambda (%integer L) warn ("Set Lambda".after init) %if init=true lambda = l %end %external %routine first cell number (%integer I) warn ("First cell number".after init) %if init=true warn ("First cell number must be positive") %and %return %if i<0 initial symbol = i %end %external %routine MERGE ON control = control ! merge %end %external %routine MERGE OFF control = control & (\merge) %end %external %routine DRC ON control = control ! design rule check %end %external %routine DRC OFF CONTROL = control & (\ design rule check) %end %external %routine SET ERROR STREAM (%integer I) warn ("Set error stream".after init) %if init=true ERROR stream = I %end %external %routine SET CIF STREAM (%integer I) warn ("Set CIF stream".after init) %if init=true CIF stream = I %end %external %routine INITIALISE NMOS (%string (255) ofile) technology = 'N' initialise (ofile) %end %external %routine INITIALISE CMOS (%string (255) ofile) technology = 'C' ! Change layers which are merged from their Nmos settings - layer mnemonics (3) = 'W'; layer names (3) = "well" layer mnemonics (4) = 'S'; layer names (4) = "substrate" initialise (ofile) %end %external %routine finish %record (symdef) %name entry %integer i Transistor Polygon or Wire check end symbol %and warn ("Endsymbol missing at FINISH") %if current symbol##null symbol ! Check for any un-satisfied symbol specs %if symbols speced = true %start %for i = 0, 1, max symbols %cycle entry == symbol table (i) warn ("Body of symbol """.entry_name.""" missing at FINISH") %if entry_number < 0 %repeat %finish current stream = out stream select output (cif stream) print symbol ('E'); newline close output(cif stream) select output (error stream) statements = statements+1 %if warnings>0 %start write (warnings, 0); print string (" Warning") print symbol ('s') %if warnings#1 print string (" issued."); newline %finish write(statements, 0) ; printstring(" CIF 2.0 statements output"); newline init = false select output (current stream) %end %external %routine give statistics %record (sym def) %name symbol %integer i print string (" Symbol Statistics"); newline print string (" Type Name symbol LLX LLY URX URY TR Count"); newline %for i=0,1,max symbols %cycle symbol == symbol table(i) %if symbol_number#0 %start %if symbol_geometry=0 %and symbol_calls=0 %start %if symbol_xu>symbol_xl %start print string (" External") %finish %else %start print string (" Empty") %finish %finish %else %if symbol_geometry=0 %and symbol_calls#0 %start print string ("Composition") %finish %else %if symbol_geometry#0 %and symbol_calls=0 %start print string (" Leaf Cell") %finish %else %if symbol_geometry#0 %and symbol_calls#0 %start print string ("***********") %finish spaces (31-8-length (symbol_name)) print string (symbol_name) write (symbol_number, 6) write (symbol_xl, 6) write (symbol_yl, 6) write (symbol_xu, 6) write (symbol_yu, 6) write (symbol_trans, 7) newline %finish %repeat %end %end %of %file