!****************************************************************** ! spec for external routine in this file %recordformat connf(%integer type,side,c,w,%string(4) layer) %routine %spec place pads ( %string(31) chipname ,cellname, %record(connf)%array %name ports, %integer n ) !****************************************************************** !-----------------------------------------------------------------! ! ! ! PLACE PADS: an ILAP routine to distribute pads around a design. ! ! ! ! George A. McCaskill 26th August 1982 ! ! "" Revised: 10th September 1982 ! ! "" Revisited: 22nd September 1982 ! !-----------------------------------------------------------------! !********************************************************************* %constant %string (2) blue ="M", metal ="M", nm="M" %constant %string (2) green ="D", diffusion="D", nd="D" %constant %string (2) red ="P", poly ="P", np="P" %constant %string (2) implant ="I", ni="I" %constant %string (2) glass ="G", ng="G" %constant %string (2) contact ="C", nc="C" %constant %string (2) buried ="B", nb="B" %constant %integer true = 0, false = 1 %external %routine %spec first cell number (%integer num) %external %routine %spec set lambda (%integer l) %external %routine %spec buried contacts %external %routine %spec butting contacts %external %string (2) %fn %spec contacts %external %integer %map %spec ILAP control %constant %integer no warnings = 1 %constant %integer monitor endsym = 2 %constant %integer give times = 4 %constant %integer merge cif = 8 %constant %integer design rule check = 16 %constant %integer circuit analysis = 32 %constant %integer give node list = 64 %constant %integer give tran list = 128 %constant %integer give node plot = 256 %external %routine %spec merge on %external %routine %spec merge off %external %routine %spec drc on %external %routine %spec drc off %external %routine %spec initialise %alias "INITIALISENMOS" (%string (255) s) %external %routine %spec finish %external %routine %spec give statistics %external %routine %spec end symbol %external %routine %spec symbol (%string (31) name) %external %routine %spec symbol spec (%string (31) name, %integer xl, yl, xu, yu) %external %routine %spec external symbol spec (%string (31) name, %integer number, %integer xl, yl, xu, yu) %external %routine %spec box %alias "ILAPBOX" (%integer xl, yl, xu, yu) %external %routine %spec polygon %alias "ILAPPOLYGON" (%real x, y) %external %routine %spec line %alias "ILAPLINE" (%real x, y) %external %routine %spec wirex (%integer x, y, l) %external %routine %spec wirey (%integer x, y, l) %external %routine %spec ETPX (%string (31) name, %integer x, y, l) %external %routine %spec ETPY (%string (31) name, %integer x, y, l) %external %routine %spec ETDX (%string (31) name, %integer x, y, l) %external %routine %spec ETDY (%string (31) name, %integer x, y, l) %external %routine %spec DTPX (%string (31) name, %integer x, y, l) %external %routine %spec DTPY (%string (31) name, %integer x, y, l) %external %routine %spec DTDX (%string (31) name, %integer x, y, l) %external %routine %spec DTDY (%string (31) name, %integer x, y, l) %external %routine %spec DTDBX (%string (31) name, %integer x, y, l) %external %routine %spec DTDBY (%string (31) name, %integer x, y, l) %external %routine %spec ax (%integer u) %external %routine %spec ay (%integer v) %external %routine %spec axy (%real x, y) %external %routine %spec dx (%integer u) %external %routine %spec dy (%integer v) %external %routine %spec dxy (%real x, y) %external %routine %spec layer (%string (4) colour) %external %string (4) %function %spec clayer %external %routine %spec width (%integer size) %external %integer %function %spec cwidth %external %routine %spec cifcomment (%string (255) s) %external %routine %spec user extension (%integer no, %string (255) s) %external %routine %spec draw (%string (31) name, %integer x, y) %external %routine %spec drawmx (%string (31) name, %integer x, y) %external %routine %spec drawmy (%string (31) name, %integer x, y) %external %routine %spec drawrot (%string (31) name, %integer x, y, rot) %external %routine %spec draw mx rot (%string (31) name, %integer x, y, rot) %external %routine %spec draw my rot (%string (31) name, %integer x, y, rot) %external %integer %function %spec SX (%string (31) name) %external %integer %function %spec SY (%string (31) name) %external %integer %function %spec LX (%string (31) name) %external %integer %function %spec LY (%string (31) name) %external %integer %function %spec symbol exists (%string (31) name) %external %routine %spec dm (%integer x, y) %external %routine %spec pm (%integer x, y) %external %routine %spec pdms (%integer x, y) %external %routine %spec pdmn (%integer x, y) %external %routine %spec pdmw (%integer x, y) %external %routine %spec pdme (%integer x, y) %external %routine %spec pdbn (%integer x, y) %external %routine %spec pdbs (%integer x, y) %external %routine %spec pdbe (%integer x, y) %external %routine %spec pdbw (%integer x, y) %external %routine %spec pdcn (%integer x, y) %external %routine %spec pdcs (%integer x, y) %external %routine %spec pdce (%integer x, y) %external %routine %spec pdcw (%integer x, y) %external %routine %spec pdbns (%integer x, y) %external %routine %spec pdbew (%integer x, y) %external %routine %spec tpla (%string (31) name, %string (127) file, %integer %name phi1y, phi2y, %integer %array %name inx, outx) %external %routine %spec epla (%string (31) name, %string (127) file, %integer %name phi1y, phi2y, %integer %array %name inx, outx) %external %routine %spec equate (%string (255) parm) %external %routine %spec table (%string (255) parm) %external %routine %spec rom (%string (31) name, %string (127) file, %integer %name phi1y, phi2y, %integer %array %name inx, outx) %external %routine %spec stack (%string (31) name, %integer bits, words, %integer %name controlx, controly, pushcony, popcony, phi1x, phi2x, phi3x, phi4x, %integer %array %name pushy, popy) %record %format port (%integer x, w) %external %integer %function %spec route (%string (31) name, %record (port) %array %name a, b, %integer n, %string (4) layer, %integer twid, tsep, sepn) %external %routine %spec croute (%string(31) name, %record(port)%arrayname a, b, %integer n, ya, xb, %string (4) lay, %integer twid, tsep) %external %routine %spec padvdd %external %routine %spec padgnd %external %routine %spec padin (%integername padinx) %external %routine %spec padout (%integername padoutx) %external %routine %spec padclout (%integername padcloutx, padcloutclx) %external %routine %spec padinout (%integername padinoutinx, padinoutoutx, padinoutenx) %external %routine %spec crest (%integer xsize, ysize) %external %routine %spec text %alias "ILAPTEXT" (%string (31) name, %string (255) text, %integer xsize, ysize) !********************************************************************** %external %routine %spec warn %alias "ILAPWARNING" ( %string(255) f ) %external %routine %spec fault %alias "ILAPDISASTER" (%string(255) f ) %external %routine %spec update mbb %alias "ILAPUPDATEMBB" ( %integer xl, xb, xr, xt ) %external %string (63) %fn %spec ITOS (%integer A, B) ! The following convention is adopted for 3 ! indicating position :- ! 4 directions 2 ! ! 1 ! ! For example , the ILAP symbol 'pad placed side3' is positioned 'on top' ! of the given cell. ! %constant %integer %array opposite (1:4) = 3,4,1,2 %constant %integer %array next (1:4) = 2,3,4,1 %constant %integer %array prev (1:4) = 4,1,2,3 %external %routine place pads ( %string(31) chipname ,cellname, %record(connf)%array %name ports, %integer n ) ! ! the cell's ports are ordered into 4 sides, with portf pointing into the ! sorted PORTS parameter. ! %record %format portf ( %integer start, finish ) %record %format cellf ( %integer %array offset (1:4), %record(portf)%array ports (1:4), %integer %array w (1:4), %integer dx , dy ) %record(cellf) cell { user's cell } ! ! The four pad blocks are represented as linked lists, the free list ! is assembled from a pool of exactly n pad items. ! %record %format padf ( %integer type, width, %record(padf)%name next ) ! %record(padf)%array free pads (1:n) %record(padf)%name fp { free pointer } ! The four pad blocks are accesed from the 'side' array ! %record %format sidef ( %record(padf)%name first, { pointer to pad list } %string(4) layer, { routing layer } %integer n, { number of pads } separation, { total routing size } ground rail, { height of rail } pushed, { side pushing flag } corner, { height at corner } px, { amount pushed to side } ed, em, { extra diffusion, metal } drouted, mrouted, { routing flags } height, { dimensions } width, metal width, { width of routing } x { displacement }) %record(sidef)%array side (1:4) { four sides of pads } ! Record for describing position and dimension of 'slots' ! ! a slot is an area between the power and ground rail available for ! pad placement. ! %record %format boxf ( %integer x, { length in x direction } y, { height in y direction } d, { direction of ground rail } g, { position of ground tab } son, { each slot can give rise to another } ax, { absolute x coordinate } ay { absolute y coordinate } ) ! %record(boxf)%array slots (1:10) ! %integer power { slot found for power pad } %integer ground { slot found for ground pad } %constant %integer gnd height = 96 %constant %integer pad width = 96 %constant %integer true = 1, false = 0 { numeric values of true { and false are significant { port types } { user specified } %constant %integer vdd port = 1 %constant %integer gnd port = 2 %constant %integer in port = 3 %constant %integer out port = 4 %constant %integer cloutout port = 5 %constant %integer cloutcl port = 6 %constant %integer inoutin port = 7 %constant %integer inoutout port = 8 %constant %integer inouten port = 9 { now for the pad types } { program generated } %constant %integer padint = 3 %constant %integer padoutt = 4 %constant %integer padcloutt = 5 %constant %integer padcloutmyt = 6 { padinout mirrored in Y } %constant %integer padinoutt = 7 %constant %integer padinoutmyt = 8 %constant %integer lvddt = 9 { long vdd link } %constant %integer lgndt = 10 %constant %integer svddt = 11 { short vdd link } %constant %integer sgndt = 12 %constant %integer cloutabst = 13 { mark pads with no geometry } %constant %integer cloutmyabst = 14 %constant %integer inoutabst = 15 %constant %integer inoutmyabst = 16 %constant %string(16) %array pads (3:16) = "padin", "padout", "padclout" (2), "padinout" (2), "pad placed lvdd", "pad placed lgnd", "pad placed svdd", "pad placed sgnd", "pseudo clout" (2), "pseudo inout" (2) %constant %record (PADF) %name nil = 0 %integer i { counter variable } %integer vdd { number of vdd requests } %integer gnd { number of gnd requests } ! Pad dimensions ! %integer padinx %integer padiny %integer padoutx %integer padouty %integer padcloutx %integer padcloutclx %integer padclouty %integer padinoutinx %integer padinoutoutx %integer padinoutenx %integer padinouty %integer contact height { butting or buried ? %integer clearance { clearance of cell from ground rail, { or pad block %integer ground pad placed %integer power pad placed !-----------------! ! Chip dimensions ! !-----------------! %integer x1,x2,x3,x4 { size of block n in x direction } %integer y1,y2,y3,y4 { size "" "" "" "" y "" } %integer xc1,xc2,xc3,xc4 %integer yc1,yc2,yc3,yc4 %integer oxc1,oxc2,oxc3,oxc4,oyc1,oyc2,oyc3,oyc4 { original dimensions } %integer %array d (1:4 ) ! ! side3 power rail ! | ! +--xc4-------+--------x3-------+----xc3--|+ ! | c4 y3 | c3 | ! s + +-------+-----------------+-------+ | ! i yc4 | | | yc3 s ! d | | d3 | | i ! e +----+ +-----------------+ +--+ d ! 4 | |-d4----| GEORGE'S |--d2---| | e ! y4 | | CELL ! | | y2 2 ! +-x4-+ +-----------------+ +--+ ! | | | | | ! | c1 | d1 | yc2 ! yc1 +-------+---------------.-+-------+c2| ! +------xc1---+--------x1-----.-+----xc2---+ ! . ! side1 . ! ground rail ! !------------------! ! Get pad from pool ! %integer %fn new %record(padf)%name tp tp == fp fp == fp_next tp_next == nil %result = addr(tp) %end !--------------------------------------------! ! useful function ! %integer %function max ( %integer a , b ) %result = a %if a >= b %result = b %end %integer %function min ( %integer a , b ) %result = a %if a <= b %result = b %end !-------------------------------------! ! error handler, terminates execution ! %routine error (%integer n , %string(255) m ) %string(255) f %switch e (1:13) -> e(n) e(1):f = "ports seperated by less than 3 lambda".m ;->ef e(2):f = "more than one VDD pad".m ;->ef e(3):f = "PLACEPADS can't cope with this cell".m ;->ef e(4):f = "layer must be METAL for ground or power pad".m ;->ef e(5):f = "METAL port width must be >= 8".m ;->ef e(6):f = "DIFFUSION port width must be >= 2".m ;->ef e(7):f = "missing PADCLOUT port".m ;->ef e(8):f = "missing PADINOUT port".m ;->ef e(9):f = "extra PADCLOUT out port".m ;->ef e(10):f = "extra PADCLOUT clock port".m ;->ef e(11):f = "extra PADINOUT in port".m ;->ef e(12):f = "extra PADINOUT out port".m ;->ef e(13):f = "extra PADINOUT enable port".m ef: warn("PLACE PADS - ".f) %end !--------------------------------! ! Check the user specified ports ! %routine check ports ( %record(connf)%array %name ports , %integer n ) %integer i %switch s(1:4) %routine cerror ( %integer what, who ) error(what,": on side".itos(ports(who)_side,0).", c = ". %c itos(ports(i)_c,1) ) %end %routine check unassigned ( %integer m ) %string(10) who,l %record(connf) p %integer i %on 6,8 %start { works with checks on only } %if eventinf>>8&15 = 8 %start fault("unassigned variable: ".who." field in port ".itos(m,0)." of the 'connf' array.") %finish %else %start fault("incorrect array bounds 'N' given to 'PORTS'") %finish %finish who = "" p = ports(m) who = "type" i = p_type who = "side" i = p_side who = "c" i = p_c who = "w" i = p_w who = "layer" l = p_layer %end %for i = 1,1,n %cycle check unassigned(i) fault("type field out of range on port ".itos(i,0)) %unless %c ( vdd port <= ports(i)_type <= inouten port ) fault("side field out of range on port ".itos(i,0)) %unless %c ( 1 <= ports(i)_side <= 4 ) vdd = vdd + 1 %if ports(i)_type = vdd port gnd = gnd + 1 %if ports(i)_type = gnd port cerror(2,i) %if vdd > 1 cerror(4,i) %if ( ports(i)_type < in port %or ports(i)_type = inoutin port ) %and ports(i)_layer # METAL cerror(5,i) %if ( ports(i)_type < in port %or ports(i)_type = inoutin port ) %and ports(i)_w < 8 cerror(6,i) %if ports(i)_type > gnd port %and ports(i)_type # inoutin port %and ports(i)_w < 2 %repeat %for i = 1,1,n %cycle -> s(ports(i)_side) s(1):s(3): ports(i)_c = ports(i)_c - cell_dx ; %continue s(2):s(4): ports(i)_c = ports(i)_c - cell_dy %repeat %end ! sort ports in order of displacement 'c' from start of side ! %routine sort ports ( %record(connf)%array %name a , %integer n ) %integer %function less than ( %record(connf) a,b ) %result = true %if a_side < b_side %or ( a_side = b_side %and a_c < b_c ) %result = false %end %routine sort ( %integer l, r) %integer i,j %record(connf) x,w i = l j = r x = a( (l+r)//2 ) %cycle i = i + 1 %while less than ( a(i), x ) = true { quicksort } j = j - 1 %while less than ( x, a(j) ) = true %if i <= j %start w = a(i) ; a(i) = a(j) ; a(j) = w i = i + 1 ; j = j - 1 %finish %repeat %until i > j sort ( l,j ) %if l < j sort ( i,r ) %if i < r %end sort(1,n) %end !---------------------------------------------------------! ! routine which assembles the pad 'side' array element 'd' ! %routine make side ( %integer d ) { d = north , east , south , west } %integer i,j { counters } %string(1) s { character of side } %integer dx ! Define some flags %integer output pad { flags are local to 'this side' } %integer input pad %integer gnd pad %integer vdd pad %integer inout pad %integer clout pad !------------------------------------------------------! ! another port spotted for this side ! %routine add to list ( %record(connf) port ) %switch s ( vdd port:inouten port ) j=j+1 -> s ( port_type ) s(vdd port):vdd pad = true ; %return s(gnd port):gnd pad = true ; %return s(in port):input pad = true ; %return s(out port):output pad = true ; %return s(cloutout port):s(cloutcl port): clout pad = true; %return s(inoutin port) :s(inoutout port):s(inouten port): inout pad = true %end !----------------------------------------! ! build up pad list from this sides ports ! %routine assemble pads ( %integer start, finish ) %record(padf)%name tp %integer i %constant %integer inoutin = 1 { flags for multiple port pads } %constant %integer inoutout = 2 %constant %integer inouten = 4 %constant %integer cloutout = 1 %constant %integer cloutcl = 2 %record(padf)%name inout padp { remember instantiation of } { inout pad } %integer inout %integer clock %integer clock first %integer inout first !-------------------------------------------! ! add appropriate pad ( if any ) to pad list ! %routine make pad ( %record(padf)%name pad , %record(connf)%name port, %integer %name width ) %switch p ( vdd port:inouten port ) { switch on port type } error(7," on side".s ) %if clock # 0 %and %not ( cloutout port <= port_type <= cloutcl port ) error(8," on side".s ) %if inout # 0 %and %not ( inoutin port <= port_type <= inouten port ) -> p ( port_type ) p(vdd port): %if ( output pad ! input pad ! %c clout pad ! inout pad = false ) %and n # vdd + gnd %start { n = total number of ports ( global )} pad_type = svddt { short power link } %finish %else %start pad_type = lvddt { long power link } %finish pad_width = 14 width = width + 14 %return p(gnd port): %if ( output pad ! input pad ! %c clout pad ! inout pad = false ) %and n # vdd + gnd %start pad_type = sgndt { short ground link } %finish %else %start pad_type = lgndt %finish pad_width = 8 width = width + 8 %return p(in port): pad_type = padint ; pad_width = pad width width = width + pad width %return p(out port): pad_type = padoutt ; pad_width = pad width width = width + pad width %return p(cloutout port): error(9," on side".s) %if clock&cloutout # 0 clock = clock!cloutout clock first = cloutout %if clock first = 0 -> check clout p(cloutcl port): error(10, " on side".s) %if clock&cloutcl # 0 clock first = cloutcl %if clock first = 0 clock = clock!cloutcl check clout: %if clock&cloutcl # 0 %and clock&cloutout # 0 %start %if clock first = cloutout %start pad_type = padcloutt %finish %else %start pad_type = padcloutmyt %finish pad_width = pad width width = width + pad width clock first = 0 ; clock = 0 %finish %else %start %if clock first = cloutout %then pad_type = cloutabst %c %else pad_type = cloutmyabst %finish %return p(inoutin port): error(11," on side".s) %if inout&inoutin # 0 inout = inout!inoutin -> check inout p(inoutout port): error(12," on side".s) %if inout&inoutout # 0 inout = inout!inoutout inout first = inoutout %if inout first = 0 -> check inout p(inouten port): error(13," on side".s) %if inout&inouten # 0 inout = inout!inouten inout first = inouten %if inout first = 0 check inout: %if port_type = inoutin port %start inout padp == pad %finish %else %start %if inout first = inoutout %then pad_type = inoutabst %c %else pad_type = inoutmyabst %finish %if inout&inoutin # 0 %and inout&inoutout # 0 %and inout&inouten # 0 %start %if inout first = inoutout %start inout padp_type = padinoutt %finish %else %start inout padp_type = padinoutmyt %finish inout padp_width = pad width width = width + pad width inout = 0 ; inout first = 0 %finish %end inout = 0 clock = 0 clock first = 0 inout first = 0 side(d)_width = 0 side(d)_first == nil %return %if start = 0 side(d)_first == record(new) tp == side(d)_first make pad ( tp, ports(start), side(d)_width ) %for i = start+1,1,finish %cycle tp_next == record(new) tp == tp_next make pad ( tp, ports(i), side(d)_width ) %repeat error(7," on side".s) %if clock # 0 { missing clockout port } error(8," on side".s) %if inout # 0 { missing inout port } %end !--------------------------------------------! ! work out routing requirements for this side ! %routine prepare routing ( %integer start, finish ) %record(port)%array ap ( 1:n ) %record(port)%array bp ( 1:n ) %integer a, h, m, i, x %integer pad centre %integer cell centre %integer ma, size, msize %integer carry on %integer inout count %integer which sep %integer wide route %record(port)%array map (1:n) %record(port)%array mbp (1:n) %record(padf)%name tp a = 0; h = 0; m = -1 pad centre = side(d)_width//2 ma = 0; size = 0; msize = 0 in out count = 0 wide route = vdd pad ! gnd pad cell centre = cell_w(d)//2 tp == side (d)_first !----------------------------------! ! Now find out the required offset ! !----------------------------------! %if pad centre > cell centre %start side(d)_x = 0 cell_offset(d) = pad centre - cell centre %finish %else %start side(d)_x = cell centre - pad centre cell_offset(d) = 0 %finish !----------------------! ! choose routing layer ! !----------------------! %if input pad ! clout pad ! inout pad ! vdd pad ! gnd pad = true %start side(d)_layer = DIFFUSION which sep = 3 %finish %else %start { i.e. only the output pad present } side(d)_layer = POLY which sep = 2 %finish %if wide route = true %start side(d)_metal width = 8 %finish %else %start side(d)_metal width = 4 %finish x = side(d)_x side(d)_mrouted = false ; side(d)_drouted = false %if start > 0 %start %for i = start,1,finish %cycle carry on = true ! First keep track of height of side %if tp_type < cloutabst %start { do we have 'real' pad ? } h = SY ( pads( tp_type) ) h = h + contact height %if padcloutt <= tp_type <= padinoutmyt h = h + contact height - 3 %if side(d)_layer = DIFFUSION %and tp_type = padoutt h = h + 1 %if side(d)_layer = POLY %and tp_type = padoutt m = h %if h > m %finish %else %start carry on = false tp_width = pad width %finish ! Now build up routing arrays for I/O ports %if ( in port <= ports(i)_type <= cloutcl port ) %or ( inoutout port <=ports(i)_type <= inouten port ) %start ! ! first generate B array ( the user's ports ) ! a = a + 1 bp(a)_x = ports(i)_c + cell_offset(d) + clearance bp(a)_w = 2 ! ! Now generate the A array ( pads ) ! %if tp_type = padint %start ap(a)_x = x + padinx %finish %else %if tp_type = padoutt %start ap(a)_x = x + padoutx %finish %else %if tp_type = padcloutt %or tp_type = padcloutmyt %or %c tp_type = cloutabst %or tp_type = cloutmyabst %start %if ports(i)_type = cloutout port %then ap(a)_x = x + padcloutx %c %else ap(a)_x = x + padcloutclx ap(a)_x = - ap(a)_x + pad width - 2 + 2*x %c %if tp_type = padcloutmyt %or tp_type = cloutmyabst ! ! just a bit of algebra to adjust for mirroring ^ ! %finish %else %if tp_type = inoutabst %or tp_type = inoutmyabst %start %if ports(i)_type = inoutout port %then ap(a)_x = x + padinoutoutx %c %else ap(a)_x = x + padinoutenx ap(a)_x = - ap(a)_x + pad width + 2*x - 2 %c %if tp_type = inoutmyabst inout count = inout count + 1 %finish ap(a)_w = 2 side(d)_drouted = true %finish %else %if ports(i)_type <= gnd port %or ports(i)_type = inoutin port %start ma = ma + 1 %if tp_type = svddt %or tp_type = lvddt %start map(ma)_x = x + 3 %finish %else %if tp_type = sgndt %or tp_type = lgndt %start map(ma)_x = x %finish %else %if tp_type = padinoutt %start map(ma)_x = x + padinoutinx inout count = inout count + 1 carry on = false %finish %else %if tp_type = padinoutmyt %start map(ma)_x = x + pad width - padinoutinx - side(d)_metal width carry on = false inout count = inout count + 1 %finish mbp(ma)_x = ports(i)_c + cell_offset(d) + clearance map(ma)_w = side(d)_metal width mbp(ma)_w = side(d)_metal width side(d)_mrouted = true %finish x = x + tp_width %if carry on = true x = x + tp_width %and inout count = 0 %if inout count = 3 tp_width = 0 %if tp_type >= cloutabst tp == tp_next %repeat %finish msize = route ( "pad placed vdd route".s, map,mbp,ma,METAL,side(d)_metal width,3,0 ) %c %if side(d)_mrouted = true size = route ( "pad placed route".s, ap,bp,a,side(d)_layer,2,which sep,0 ) %c %if side(d)_drouted = true side(d)_ed = 0 ; side(d)_em = 0 side(d)_mrouted = false %if msize <= 0 side(d)_drouted = false %if size <= 0 msize = 0 %if msize < 0 size = 0 %if size < 0 %if size < msize %start side(d)_ed = msize - size %finish %else %if msize < size %start side(d)_em = size - msize %finish side(d)_separation = max ( size, msize ) side(d)_height = m %end !--------------------------------------------------! ! Routine which calls the appropriate ILAP SYMBOLS ! %routine draw side ( %integer start, finish ) %integer i, x, e %integer extend outputs %integer extend clouts %integer extend inputs %integer extend metal %integer highest %record(padf)%name tp %routine draw pad ( %integer type, dx ) %switch p (padint:sgndt) %return %if type >= cloutabst %routine do contact ( %integer x, y ) %if side(d)_layer = POLY %start LAYER(POLY) BOX( dx + x -1, y, dx + x + 1, y+2 ) %if type = padoutt %finish %else %start %if contacts = buried %start PDCN ( dx + x, y ) %finish %else %start DRAW ( "pad placed scon" , dx + x-1, y - 2 ) LAYER ( DIFFUSION ) BOX ( dx + x + 1, y + 4 , dx + x + 3, y + 7 ) %finish %finish %end -> p(type) p(padint): DRAW("padin",dx,0) %if extend inputs = true %start LAYER ( DIFFUSION ) BOX ( dx + padinx , padiny, dx + padinx + 2 , highest ) %finish %return p(padoutt): DRAW("padout",dx,0) %if extend outputs = true %start LAYER ( DIFFUSION ) BOX ( dx + padoutx , padouty + 2, dx + padoutx+2, highest ) %finish do contact( padoutx + 1, padouty - 1 ) %return p(padcloutt): DRAW("padclout",dx,0) %if extend clouts = true %start LAYER ( DIFFUSION ) BOX( dx + padcloutclx, padclouty+contact height, dx + padcloutclx+2 , highest ) %finish LAYER ( DIFFUSION ) BOX ( dx + padcloutx, padclouty, dx +padcloutx+2, highest ) do contact( padcloutclx+1, padclouty+2 ) %return p(padcloutmyt): DRAWMX("padclout",dx+pad width,0) %if extend clouts = true %start LAYER ( DIFFUSION ) BOX ( dx + pad width - padcloutclx - 2, padclouty+contact height, dx + pad width - padcloutclx, highest ) %finish LAYER ( DIFFUSION ) BOX ( dx + pad width - padcloutx -2 , padclouty, dx + pad width - padcloutx, highest ) do contact( pad width - padcloutclx-1, padclouty+2 ) %return p(padinoutt): DRAW("padinout",dx,0) LAYER( METAL ) BOX ( dx + padinoutinx, padinouty, dx + padinoutinx + 4, highest ) do contact( padinoutoutx+1, padinouty+2 ) do contact( padinoutenx+1, padinouty+2 ) %return p(padinoutmyt): DRAWMX("padinout",dx+pad width,0) LAYER( METAL ) BOX ( dx + pad width - padinoutinx - 4, padinouty, dx + pad width - padinoutinx, highest ) do contact( pad width - padinoutoutx - 1, padinouty+2 ) do contact( pad width - padinoutenx - 1, padinouty+2 ) %return p(lvddt): DRAW("pad placed lvdd",dx,0) %return p(lgndt): DRAW("pad placed lgnd",dx,0) %return p(svddt): DRAW("pad placed svdd",dx,0) %return p(sgndt): DRAW("pad placed sgnd",dx,0) %end x = 0 dx = side(d)_x extend outputs = output pad & ( clout pad ! inout pad ) extend clouts = clout pad & inout pad extend inputs = input pad & ( gnd pad ! vdd pad ! %c output pad ! inout pad ! clout pad ) extend metal = ( vdd pad ! gnd pad ) & %c ( output pad ! inout pad ! clout pad ) highest = side(d)_height tp == side(d)_first %for i = start,1,finish %cycle draw pad( tp_type,dx + x ) %if extend metal = true %and ( lvddt <= tp_type <= sgndt ) %start LAYER ( METAL ) %if tp_type = svddt %or tp_type = lvddt %then e = 3 %else e = 0 BOX ( dx + e + x, gnd height, dx + e + 8 + x, highest ) %finish x = x + tp_width tp == tp_next %repeat %end ! Initialise MAKE SIDE s = tostring('0'+d) { character of side } output pad = false input pad = false gnd pad = false vdd pad = false inout pad = false clout pad = false !------------------------------! ! pull out ports for this side ! !------------------------------! j = 0 cell_ports(d)_start = 0 %for i = 1,1,n %cycle add to list ( ports(i) ) %if ports(i)_side = d cell_ports(d)_start = i %if j = 1 %and cell_ports(d)_start = 0 %repeat cell_ports(d)_finish = cell_ports(d)_start+j-1 ! { leave ports being to close to router. Watch ! Ports can conflict ! round corners ! } ! %if j > 1 %start ! ! %for i = 2,1,j %cycle ! error(1," between ports ".itos(i-1,0)." and ".itos(i,0)." of side".s ) %c ! %if cell_ports(d)_p(i)_c - cell_ports(d)_p(i-1)_c - %c ! cell_ports(d)_p(i-1)_w < 3 ! %repeat ! %finish assemble pads ( cell_ports(d)_start, cell_ports(d)_finish ) prepare routing ( cell_ports(d)_start, cell_ports(d)_finish ) %if j > 0 %start { we have some ports } %if input pad ! output pad ! clout pad ! inout pad = false %and %c n # vdd + gnd %then side(d)_ground rail = 8+8+8 %c %else side(d)_ground rail = gnd height SYMBOL ("pad placed side".s) draw side ( cell_ports(d)_start, cell_ports(d)_finish ) DRAW ( "pad placed route".s,0,side(d)_height ) %if side(d)_drouted = true DRAW ( "pad placed vdd route".s,0,side(d)_height ) %if side(d)_mrouted = true %if side(d)_x > 0 %start { add in power rail } LAYER( METAL ) BOX ( 0,0,side(d)_x, 8 ) BOX ( side(d)_x+side(d)_width, 0, side(d)_x+side(d)_x+side(d)_width, 8 ) %finish ENDSYMBOL side(d)_width = side(d)_width + 2 * side(d)_x side(d)_height = side(d)_height + side(d)_separation %finish %else %start SYMBOL ("pad placed side".s) side(d)_ground rail = 8+8+8 side(d)_height = 8+8+8 LAYER( METAL ) BOX ( 0,0,cell_w(d),8 ) BOX ( 0,8+8,cell_w(d),8+8+8 ) side(d)_width = cell_w(d) ENDSYMBOL %finish %end { of make side } !===============================================================! ! Now that we have dimensions of all four blocks we can do the ! ! final modifications, prior to assembly. ! !===============================================================! %routine extend routing ( %integer start, finish , w ) %integer i, dn, x %string (1) s %return %if start = 0 dn = d(w) s = to string (w + '0') SYMBOL ( "pad placed extra route".s ) %for i = start,1,finish %cycle x = ports(i)_c + cell_offset(w) %if ports(i)_type >= in port %and ports(i)_type # inoutin port %start LAYER ( side(w)_layer ) BOX ( x + clearance, -side(w)_ed, x + 2 + clearance, dn ) %c %if side(w)_ed > 0 %or dn > 0 %finish %else %start LAYER ( METAL ) BOX( x+clearance, -side(w)_em, x+side(w)_metal width+clearance, dn ) %c %if side(w)_em > 0 %or dn > 0 %finish !------------------------------! ! Now add contact if necessary ! !------------------------------! %if ports(i)_layer = POLY %start %if side(w)_layer = diffusion %start %if contacts = buried %start PDCS ( x+1+clearance, dn + clearance - 2 ) %finish %else %start DRAWMY("pad placed scon",x-1+clearance, dn + contact height ) %finish %finish %else %start LAYER(POLY) BOX( x + clearance, dn, x + 2 + clearance, dn + clearance ) %finish %finish %else %if ports(i)_layer = DIFFUSION %start %if side(w)_layer = diffusion %start LAYER(DIFFUSION) BOX( x + clearance, dn, x + 2 + clearance, dn + clearance ) %finish %else %start PDCN( x+1+clearance, dn + clearance - 3 ) %finish %finish %else %if ports(i)_layer = METAL %start %if ports(i)_type <= gnd port %or ports(i)_type = inout in port %start LAYER(METAL) BOX( x + clearance, dn, x + side(w)_metal width + clearance, dn + clearance ) %finish %else %start %if side(w)_layer = diffusion %start DM ( x+1+clearance, dn + clearance - 2 ) %finish %else %start PM ( x+1+clearance, dn + clearance - 2 ) %finish LAYER( side(w)_layer ) BOX( x + clearance, dn, x + 2 + clearance, dn + clearance - 4 ) %finish %finish %repeat ENDSYMBOL %end ! ! Now for the 'slot' routines ! !---------------------! ! Initialise slot 'a' ! %routine make slot ( %integer a, b, c, d, e, f, g ) slots(a)_x = b slots(a)_y = c slots(a)_d = d slots(a)_g = e slots(a)_ax = f slots(a)_ay = g slots(a)_son = 0 %end ! returns number of largest slot ! %integer %function largest slot %record(boxf) s %integer i %integer which %integer size which = 0 size = 0 %for i = 1,1,8 %cycle s = slots(i) %if ( s_d = 1 %or s_d = 3 ) %and s_y = gnd height %and s_x >= size %start size = s_x which = i %finish %else %if ( s_d = 2 %or s_d = 4 ) %and s_x = gnd height %and s_y >= size %start size = s_y which = i %finish %repeat warn("couldn't find slot") %if which = 0 %result = which %end !---------------------------------------------------! ! Draw pad in slot, n = 9 => power pad, 10 => ground ! %routine place pad ( %integer n ) %record(boxf)%name s %switch p (1:4), g (1:4) %routine fit ground tab (%integer p, g, x, y) ! ! This routine attaches the special ground symbol to the ground rail ! %return %if g = 0 LAYER ( METAL ) %if p = 3 %and g = 2 %start BOX( x+pad width-11, y + gnd height - 8, x + pad width - 8, y + gnd height ) %finish %else %if p = 3 %and g = 4 %start BOX( x+8, y+gnd height-8, x+11, y+gnd height ) %finish %else %if p = 1 %and g = 4 %start BOX( x+8, y, x+11, y+8) %finish %else %if p = 1 %and g = 2 %start BOX( x+pad width-11, y, x+pad width-8, y+8) %finish %end ! ! s_d indicates direction of ground rail ! s == slots (n) %if n = 9 %start { n = 9 => power pad } -> p (s_d) %finish fit ground tab ( s_d, s_g, s_ax, s_ay ) -> g (s_d) { n = 10 => ground } g(3): p(1):DRAW("pad placed padgnd", s_ax, s_ay); -> ep g(4): p(2):DRAWROT("pad placed padgnd", s_ax+gnd height, s_ay, 1); -> ep g(1): p(3):DRAWMY("pad placed padgnd", s_ax, s_ay+gnd height); -> ep g(2): p(4):DRAWMYROT("pad placed padgnd", s_ax, s_ay, 1) ep: %end !----------------------------------------------! ! we have a slot big enuff, copy into slot 9, or 10 ! %integer %function position pad ( %integer n ) %if power pad placed = false %start slots(9) = slots(n) power = n power pad placed = true %result = 9 %finish %else %if ground pad placed = false %start slots(10) = slots(n) ground = n ground pad placed = true %result = 10 %finish %result = 0 %end !---------------------------------------------------! ! try and fit in pad in slot 'n', if still pads left ! %routine fit pads in slot ( %record(boxf)%name s , %integer n ) %return %if power pad placed & ground pad placed = true %if ( s_d = 1 %or s_d = 3 ) %and s_y = gnd height %and s_x >= pad width %start s_son = position pad ( n ) s_x = s_x - pad width { update slot's coords ) s_ax = s_ax + pad width %return %if s_x < pad width slots(s_son)_son = position pad ( n ) ! no need to update, we have placed both pads ! %finish %else %if ( s_d = 2 %or s_d = 4 ) %and s_x = gnd height %and s_y >= pad width %start s_son = position pad ( n ) s_y = s_y - pad width s_ay = s_ay + pad width %return %if s_y < pad width slots(s_son)_son = position pad ( n ) %finish %end !------------------------------------------------------------! ! We have been forced to widen slot 'n' in order to fit a pad ! %routine update slots ( %integer n ) %constant %integer %array sopposite (1:8) = 6,5,8,7,2,1,4,3 %constant %integer right = 1, up = 2 %integer w %integer i %switch e (1:8) %record(boxf)%name s, o %routine move slots ( %integer who, where, how much ) %if where = up %start %while who # 0 %cycle slots(who)_ay = slots(who)_ay + how much who = slots(who)_son %repeat %finish %else %start %while who # 0 %cycle slots(who)_ax = slots(who)_ax + how much who = slots(who)_son %repeat %finish %end s == slots (n) o == slots (sopposite(n)) %if s_d = 1 %or s_d = 3 %start w = pad width - s_x s_x = pad width o_x = o_x + w %finish %else %start w = pad width - s_y s_y = pad width o_y = o_y + w %finish -> e(n) e(1):e(6): XC1 = XC1 + w ; d(4) = d(4) + w ; XC4 = XC4 + w move slots(i,right,w) %for i = 2,1,5 %return e(2):e(5): XC2 = XC2 + w ; d(2) = d(2) + w ; XC3 = XC3 + w move slots(i,right,w) %for i = 3,1,4 %return e(3):e(8): YC1 = YC1 + w ; d(1) = d(1) + w ; YC2 = YC2 + w move slots(i,up,w) %for i = 4,1,7 %return e(7):e(4): YC4 = YC4 + w ; d(3) = d(3) + w ; YC3 = YC3 + w move slots(i,up,w) %for i = 5,1,6 %end %routine position slots ! make slot parameters :- ! ! make slot ( number , x dimension , y dimension , ! direction of ground rail, direction of ground tab, ! x coordinate, y coordinate ) %if side(1)_pushed = false %start make slot ( 1, XC1 + side(1)_x, side(1)_ground rail, 3, 2, 0, 0 ) %finish %else %start make slot ( 1, side(1)_x,gnd height,3,0, OXC1,0 ) %finish %if side(1)_pushed = false %start make slot ( 2, XC2 + side(1)_x, side(1)_ground rail, 3, 4, XC1+X1-side(1)_x, 0 ) %finish %else %start make slot ( 2, side(1)_x, gnd height, 3, 0, XC1+X1-side(1)_x,0 ) %finish %if side(2)_pushed = false %start make slot ( 3, side(2)_ground rail, side(2)_x + YC2 - side(1)_ground rail, 4, 0, XC1+X1+XC2-side(2)_ground rail, side(1)_ground rail ) %finish %else %start make slot ( 3, gnd height, side(2)_x, 4, 0, XC1+X1+XC2-gnd height, OYC2 ) %finish %if side(2)_pushed = false %start make slot ( 4, side(2)_ground rail, YC3 + side(2)_x, 4, 4, XC4+X3+XC3-side(2)_ground rail, YC2+Y2-side(2)_x ) %finish %else %start make slot ( 4, gnd height, side(2)_x, 4, 0, XC4+X3+XC3-gnd height, YC2+Y2-side(2)_x ) %finish %if side(3)_pushed = false %start make slot ( 5, XC3 + side(3)_x - side(2)_ground rail, side(3)_ground rail, 1, 0, XC4+X3-side(3)_x, YC2+Y2+YC3-side(3)_ground rail ) %finish %else %start make slot( 5, side(3)_x, gnd height, 1, 0, XC4+X3-side(3)_x, YC2+Y2+YC3-gnd height ) %finish %if side(3)_pushed = false %start make slot ( 6, XC4 + side(3)_x, side(3)_ground rail, 1, 2, 0, YC1+Y4+YC4-side(3)_ground rail ) %finish %else %start make slot ( 6, side(3)_x, gnd height, 1, 0, OXC4, YC1+Y4+YC4-gnd height ) %finish %if side(4)_pushed = false %start make slot ( 7, side(4)_ground rail, YC4 + side(4)_x - side(3)_ground rail, 2, 0, 0, YC1+Y4-side(4)_x ) %finish %else %start make slot ( 7, gnd height, side(4)_x, 2, 0, 0, YC1+Y4-side(4)_x ) %finish %if side(4)_pushed = false %start make slot ( 8, side(4)_ground rail, YC1 - side(1)_ground rail + side(4)_x, 2, 0, 0, side(1)_ground rail ) %finish %else %start make slot ( 8, gnd height, side(4)_x, 2, 0, 0, OYC1 ) %finish %end !--------------------------------------------------------------------! ! this routine only used if pads have not been positioned without ! widening. ! %routine force final pads %integer s s = largest slot %return %if s = 0 update slots ( s ) fit pads in slot ( slots(s) , s ) force final pads %if power pad placed & ground pad placed = false %end !---------------------------------------------------------------! ! Routine which pushes the pad blocks into their final positions ! relative to each other. ! %routine fit %integer i,j,p %integer biggest %integer smallest %integer shift %integer pushed !-----------------------! ! Now define dimensions ! !-----------------------! d(1) = max(cell_offset(4),cell_offset(2)) d(2) = max(cell_offset(1),cell_offset(3)) d(3) = d(1) d(4) = d(2) ! Find pair of opposite sides with greatest area between the pads and ! the cell. ! %if side(1)_width*d(1)+side(3)_width*d(3) > %c side(2)_width*d(2)+side(4)_width*d(4) %then biggest = 1 %c %else biggest = 2 ! Find smaller of the other pair ! %if biggest = 1 %start %if cell_offset(4) > cell_offset(2) %then smallest = 2 %c %else smallest = 4 %finish %else %start %if cell_offset(3) > cell_offset(1) %then smallest = 1 %c %else smallest = 3 %finish ! Now push in the two big sides ! pushed = 0 %for i = 1,1,4 %cycle side(i)_pushed = false side(i)_corner = side(i)_ground rail side(i)_px = 0 %if side(i)_ground rail # 8+8+8 %and cell_ports(i)_start > 0 %and %c ( i = biggest %or i = opposite( biggest ))%start %if d(i) >= side(i)_height -24 %start d(i) = d(i) - side(i)_height + 24 d(prev(i)) = d(prev(i)) + 14 - pushed %c %if side(prev(i))_ground rail # 8+8+8 d(next(i)) = d(next(i)) + 14 - pushed %c %if side(next(i))_ground rail # 8+8+8 side(i)_pushed = true side(i)_corner = 8+8+8 side(i)_px = 14 pushed = 14 { width of ground link } %finish %else %start shift = side(i)_height-side(i)_ground rail %if d(i) < shift %then d(i) = 0 %c %else d(i) = d(i)-shift %if pushed # 14 %start %if cell_offset(prev(i)) > d(i)-3 %and side(prev(i))_ground rail # 8+8+8 %start d(prev(i))=d(prev(i))+3 { push out previous side } pushed = 3 %finish %if cell_offset(next(i)) > d(i)-3 %and side(next(i))_ground rail # 8+8+8 %start d(next(i))=d(next(i))+3 { push out next side } pushed = 3 %finish %finish %finish %finish %repeat ! Now push in smallest side, if possible ! %if cell_offset(smallest) < min( d(prev(smallest)),d(next(smallest))) %and cell_ports(smallest)_start > 0 %start shift = side(smallest)_height-side(smallest)_ground rail %if d(smallest) < shift %then d(smallest) = 0 %c %else d(smallest) = d(smallest)-shift %finish X1 = side(1)_width ; Y1 = side(1)_height X2 = side(2)_height ; Y2 = side(2)_width X3 = side(3)_width ; Y3 = side(3)_height X4 = side(4)_height ; Y4 = side(4)_width XC1 = X4 + d(4) - cell_offset(1) XC2 = X2 + d(2) - cell_offset(1) XC3 = X2 + d(2) - cell_offset(3) XC4 = X4 + d(4) - cell_offset(3) XC1 = XC1 + 1 %and XC3 = XC3 + 1 %if cell_w(1)&1 = 1 YC1 = Y1 + d(1) - cell_offset(4) YC2 = Y1 + d(1) - cell_offset(2) YC3 = Y3 + d(3) - cell_offset(2) YC4 = Y3 + d(3) - cell_offset(4) YC4 = YC4 + 1 %and YC3 = YC3 + 1 %if cell_w(2)&1 = 1 OXC1 = XC1 ; OXC2 = XC2 ; OXC3 = XC3 ; OXC4 = XC4 OYC1 = YC1 ; OYC2 = YC2 ; OYC3 = YC3 ; OYC4 = YC4 position slots fit pads in slot ( slots(j), j ) %for j = 1,1,8 force final pads %if power pad placed & ground pad placed = false extend routing ( cell_ports(j)_start, cell_ports(j)_finish, j ) %for j = 1,1,4 %end %routine add railing %integer old %integer dx old = ILAP CONTROL ILAP CONTROL = ILAP CONTROL ! 1 { suppress warnings } LAYER ( METAL ) { corner 1 } BOX ( 0, 0, XC1, 8 ) { first the power rail } BOX ( 0, 8, 8, YC1 ) BOX( side(4)_corner-8, side(1)_corner-8, OXC1-side(1)_px, side(1)_corner ) BOX( side(4)_corner-8, side(1)_corner, side(4)_corner, OYC1-side(4)_px ) %if side(1)_pushed = true %start DRAW( "ground link", OXC1-14, 0 ) DRAWMX( "ground link", XC1+X1+XC2-OXC2+14, 0 ) %finish %else %start BOX( OXC1-side(1)_px, side(1)_ground rail-8, OXC1, side(1)_ground rail ) BOX( XC1+X1+XC2-OXC2, side(1)_ground rail-8, XC1+X1+XC2-OXC2+side(1)_px, side(1)_ground rail ) %finish BOX( OXC1, side(1)_ground rail-8, { complete the ground rail } XC1+side(1)_x, side(1)_ground rail ) BOX( XC1+X1-side(1)_x, side(1)_ground rail-8, XC1+X1+XC2-OXC2, side(1)_ground rail ) { corner2 } BOX ( XC1+X1, 0, XC1+X1+XC2, 8 ) BOX ( XC1+X1+XC2-8, 8, XC1+X1+XC2, YC2 ) BOX ( XC1+X1+XC2-OXC2+side(1)_px, side(1)_corner-8, XC1+X1+XC2-side(2)_corner+8, side(1)_corner ) BOX ( XC1+X1+XC2-side(2)_corner, side(1)_corner, XC1+X1+XC2-side(2)_corner+8, OYC2-side(2)_px ) dx = XC1+X1+XC2 %if side(2)_pushed = true %start DRAWROT( "ground link", dx, OYC2-14, 1 ) DRAWMXROT( "ground link", dx, YC2+Y2+YC3-OYC3+14, 1 ) %finish %else %start BOX( dx-side(2)_ground rail, OYC2-side(2)_px, dx-side(2)_ground rail+8, OYC2 ) BOX( dx-side(2)_ground rail, YC2+Y2+YC3-OYC3, dx-side(2)_ground rail+8, YC2+Y2+YC3-OYC3+side(2)_px ) %finish BOX( dx-side(2)_ground rail, OYC2, dx-side(2)_ground rail+8, YC2+side(2)_x ) BOX( dx-side(2)_ground rail, YC2+Y2-side(2)_x, dx-side(2)_ground rail+8, YC2+Y2+YC3-OYC3 ) { corner 3 } BOX ( XC4+X3, YC2+Y2+YC3-8, XC4+X3+XC3, YC2+Y2+YC3 ) BOX ( XC4+X3+XC3-8, YC2+Y2, XC4+X3+XC3, YC2+Y2+YC3-8 ) BOX ( XC4+X3+XC3-side(2)_corner, YC2+Y2+YC3-OYC3+side(2)_px, XC4+X3+XC3-side(2)_corner+8, YC2+Y2+YC3-side(3)_corner ) BOX ( XC4+X3+XC3-OXC3+side(3)_px, YC2+Y2+YC3-side(3)_corner, XC4+X3+XC3-side(2)_corner+8, YC2+Y2+YC3-side(3)_corner+8 ) %if side(3)_pushed = true %start DRAWMY( "ground link", OXC4-14, YC1+Y4+YC4 ) DRAWROT( "ground link", XC4+X3+XC3-OXC3+14, YC1+Y4+YC4, 2 ) %finish %else %start BOX( OXC4-side(3)_px, YC1+Y4+YC4-side(3)_ground rail, OXC4, YC1+Y4+YC4-side(3)_ground rail+8 ) BOX( XC4+X3+XC3-OXC3, YC1+Y4+YC4-side(3)_ground rail, XC4+X3+XC3-OXC3+side(3)_px, YC1+Y4+YC4-side(3)_ground rail+8 ) %finish BOX( OXC4, YC1+Y4+YC4-side(3)_ground rail, XC4+side(3)_x, YC1+Y4+YC4-side(3)_ground rail+8 ) BOX( XC4+X3-side(3)_x, YC1+Y4+YC4-side(3)_ground rail, XC4+X3+XC3-OXC3, YC1+Y4+YC4-side(3)_ground rail+8 ) { corner 4 } BOX ( 0, YC1+Y4, 8, YC1+Y4+YC4 ) BOX ( 8, YC1+Y4+YC4-8, XC4, YC1+Y4+YC4 ) BOX ( side(4)_corner-8, YC1+Y4+YC4-side(3)_corner, OXC4-side(3)_px, YC1+Y4+YC4-side(3)_corner+8 ) BOX ( side(4)_corner-8, YC1+Y4+YC4-OYC4+side(4)_px, side(4)_corner, YC1+Y4+YC4-side(3)_corner ) %if side(4)_pushed = true %start DRAWMYROT( "ground link", 0, OYC1-14, 1) DRAWROT( "ground link", 0, YC1+Y4+YC4-OYC4+14, -1 ) %finish %else %start BOX( side(4)_ground rail-8, OYC1-side(4)_px, side(4)_ground rail, OYC1 ) BOX( side(4)_ground rail-8, YC1+Y4+YC4-OYC4, side(4)_ground rail, YC1+Y4+YC4-OYC4+side(4)_px ) %finish BOX( side(4)_ground rail-8, OYC1, side(4)_ground rail, YC1+side(4)_x ) BOX( side(4)_ground rail-8, YC1+Y4-side(4)_x, side(4)_ground rail, YC1+Y4+YC4-OYC4 ) ILAP CONTROL = old %end %routine initialise %integer i ! ! set up pad pool ! free pads(i)_next == free pads(i+1) %for i = 1,1,n-1 free pads(n)_next == nil fp == free pads(1) vdd = 0; gnd = 0 { Number of requests } ground pad placed = false power pad placed = false ! call pre-defined pads ! PADIN ( padinx ) ; PADOUT ( padoutx ) PADINOUT( padinoutinx, padinoutoutx, padinoutenx ) PADCLOUT( padcloutx, padcloutclx ) padouty = SY( "padout" ) padinouty = SY( "padinout" ) padclouty = SY( "padclout" ) padiny = gnd height !------------------------! ! Define special symbols ! !------------------------! SYMBOL("pad placed padgnd") LAYER( METAL ) BOX(11,88,85,96) BOX(24,24,72,72) BOX(64,72,72,88) BOX(24,72,32,88) LAYER( GLASS ) BOX(28,28,68,68) update mbb(0, 0, 96, 96 ) { make square bounding box } ENDSYMBOL SYMBOL ( "pad placed lvdd" ) LAYER ( METAL ) BOX ( 0, 0, 14, 8 ) BOX ( 3, 0, 11, gnd height + 3 ) ENDSYMBOL SYMBOL ( "pad placed lgnd" ) LAYER ( METAL ) BOX ( 0, 0, 8, 8 ) BOX ( 0, gnd height - 8 , 8 , gnd height + 3 ) ENDSYMBOL SYMBOL ( "pad placed svdd" ) LAYER ( METAL ) BOX ( 0, 0, 14, 8 ) BOX ( 3, 0, 8+3, 8+8+8+3 ) ENDSYMBOL SYMBOL ( "pad placed sgnd" ) LAYER ( METAL ) BOX (0, 0, 8, 8) BOX (0, 8+8, 8, 8+8+8+3 ) ENDSYMBOL SYMBOL ( "pad placed scon" ) LAYER ( METAL ) PM ( 2, 2 ) BOX ( 0, 4, 4, 5 ) DM ( 2, 7 ) ENDSYMBOL SYMBOL ( "ground link" ) LAYER( METAL ) BOX(0,0,14,8) BOX(0,16,11,24) BOX(3,24,11,gnd height) BOX(11,gnd height-8,14,gnd height) ENDSYMBOL %if contacts = buried %start contact height = 5 { PDCN } %finish %else %start contact height = SY("pad placed scon") %finish clearance = contact height cell_w(1) = SX ( cell name ) + 2 * clearance cell_w(2) = SY ( cell name ) + 2 * clearance cell_w(3) = cell_w(1) cell_w(4) = cell_w(2) cell_dx = LX ( cell name ) cell_dy = LY ( cell name ) %end !----------------! ! Main Program !--------------------------------------------------------! !----------------! initialise check ports ( ports, n ) sort ports ( ports, n ) make side(i) %for i = 1,1,4 fit SYMBOL ( chip name ) !---------------------------------! ! First draw in blocks + routing ! !---------------------------------! DRAWMYROT( "pad placed side4", 0, YC1, 1 ) DRAWMYROT( "pad placed extra route4", X4, YC1, 1) %c %if cell_ports(4)_start > 0 DRAW ( "pad placed side1",XC1, 0) DRAW ( "pad placed extra route1", XC1, Y1 ) %c %if cell_ports(1)_start > 0 DRAW ( cell name, X4+d(4) + clearance - cell_dx, Y1+d(1) + clearance - cell_dy ) DRAWMY ( "pad placed extra route3", XC4, Y1+d(1)+d(3)+cell_w(2) ) %c %if cell_ports(3)_start > 0 DRAWMY ( "pad placed side3", XC4, YC1+Y4+YC4 ) DRAWROT( "pad placed extra route2", X4+d(4)+d(2)+cell_w(1),YC2, 1 ) %c %if cell_ports(2)_start > 0 DRAWROT( "pad placed side2", X4+d(4)+d(2)+cell_w(1)+X2,YC2, 1) place pad ( 9 ) %if power pad placed = true place pad ( 10 ) %if ground pad placed = true add railing ENDSYMBOL %end ! Here ends Place Pads ! ! Maintenance Guide Available ! %end %of %file