! ILAP PLA generator

%include "nmos.inc"
%external %string (255) %fn %spec ItoS (%integer I, P)

{#######################################################################}
{#                                                                     #}
{#     This program is part of the ILAP library, and was written in    #}
{#  The Department of Computer Science at the University of Edinburgh  #}
{#      (James Clerk Maxwell Building, Kings Buildings, Edinburgh)     #}
{#                                                                     #}
{#  This software is available free to other educational establisments #}
{#  but the University of Edinburgh, retains all commercial rights.    #}
{#  It is a condition of having this software is that the sources are  #}
{#  not passed on to any other site, and that Edinburgh University is  #}
{#  given credit in any re-implementations of any of the algorithms    #}
{#  used, or articles published which refer to the software.           #}
{#                                                                     #}
{#  There is no formal support for this software, but any bugs should  #}
{#  be reported to Gordon Hughes or David Rees at the above address,   #}
{#  and these are likely to be fixed in a future release.              #}
{#                                                                     #}
{#######################################################################}

%own %integer LAST INS = 0, LAST OUTS = 0

%external %routine pla data size %alias "ILAP_PLA_DATA_SIZE" (%integer %name IN, OUT)
   ! Specify the number of data lines for the last PLA produced
   IN = LAST INS
   OUT = LAST OUTS
%end

%external %routine pla %alias "ILAP_PLA" (%string (31) name,
   %integer mode,
   %integer %array %name ispec, %integerarrayname  ospec,
   %integer ins,outs,feeds,prods,
   %integerarrayname and,
   %integerarrayname or,
   %integername phi1y,phi2y,
   %integerarrayname inx,
   %integerarrayname outx)
%integer infs,outfs          {ins & outs plus feeds}
%byte %array inspec (1:ins+feeds)
%byte %array outspec (1:outs+feeds)
%routinespec define plain
%integer plainmaxy,plainphi1y,plainvddy,plaingndy, plax, play
%routinespec define plaout
%integer plaoutmaxy,plaoutphi2y,plaoutvddy,plaoutgndy
%routinespec define pdp (%string (31) %name name,%integer n,x,type)
%routinespec define stretched pdp (%string (31) %name name,%integer n,x)
%routinespec define pup (%string (31) %name name,%integer l)
%routinespec define extended pup (%string (31)  %name name,%integer l)
%routinespec define plarout(%integer i) {mixed output cell. Right output}
%routinespec define plalout   {mixed output cell. left is output}
%integer plapupmaxy
%integer plainxb,plainyb      {bases of input buffers}
%integer plainxtb,plainytb    {bases of top input buffers}
%integer plaoutxb,plaoutyb    {bases of output buffers}
%integer plaoutxtb,plaoutytb  {top bases of output buffers}
%integer plainmaxx,plaoutmaxx {max x coord}
%integer orpdpyb              {base for beginning of OR metal lines}
%integer andpdpyb             {y-base of and-plane poly/diff/poly lines}
%integer orpdpxb              {x-base of or-plane poly/diff/poly lines}
%integer orpupyb              {y-base of or-plane pull-up pairs}
%integer eprods,eoutfs        {prods and outfs evened up}
%integer output displacement  {displacement of or plane from mininmum position}
%string (31) andpdpt,andpdpb,orpdp {for poly/diff/poly symbol names}
%string (31) andpup,orpup     {for pullup+metal symbol names}
%string (31) extpup           {for mixed outputs}
%integer top outputs present, top inputs present, bottom inputs present
%constinteger extragnd=8, out=right
%integer curx,cury,andp,orp,andt,ort,i,j,k,l
%string (31) tran
%integerarray outRA(1:feeds+outs+1)
%integerarray inRA(0:ins+feeds)
%integer ch, stage

  %on 6,8 %start
      %if event_event=6 %start
          disaster ("The arrays in your program are too small for the size of table being used")
      %else
          %if stage=1 %start
              disaster ("Input side specifications not all assigned for symbol """.name."""")
          %finish %else %if stage=2 %start
              disaster ("Output side specifications not all assigned for symbol """.name."""")
          %finish %else %if stage=3 %start
              disaster ("Input coordinates not all assigned for symbol """.name."""")
          %finish %else %if stage=4 %start
              disaster ("Output coordinates not all assigned for symbol """.name."""")
          %else
              disaster ("Unassigned variable during generation of symbol """.name."""")
          %finish
      %finish
  %finish

  disaster ("Table for pla """.name.""" has only inputs") %if feeds=outs=0
  disaster ("Table for pla """.name.""" has only outputs") %if feeds=ins=0
  last ins = ins
  last outs = outs
  stage = 0         { to monitor progress through the routine }
  infs=ins+feeds    {total no. of inputs}
  outfs=outs+feeds  {total no. of outputs}
  %if mode&(\(top inputs!mixedinputs!topoutputs!mixedoutputs!stretch))#0 %start
      warning ("Invalid PLA generator mode (".ItoS(mode,0).") for symbol """.name."""")
      mode = 0
  %finish
  top inputs present = false
  bottom inputs present = false
  top outputs present = false
  {swop in the input and output specifications (ie whether top or bottom)}
  {into new arrays, and include feed backs in the arrays}
  %if ins>0 %start
      %if mode&top inputs#0 %start
          inspec (i) = top %for i=1,1,ins
          top inputs present = true
      %finish %else %if mode&mixed inputs=0 %start
          inspec (i) = bottom %for i=1,1,ins
          bottom inputs present = true
      %else
          stage = 1
          %for i=1,1,ins %cycle
             %if bottom#ispec(i)#top %start
                 warning ("Invalid position for input ".itos(i,0)." of symbol """.name."""")
                 ispec(i) = bottom
             %finish
             inspec(i) = ispec(i)
             bottom inputs present = true %if inspec(i)=bottom
             top inputs present = true %if inspec(i)=top
          %repeat
      %finish
  %finish
  inspec(i)=bottom %for i=ins+1,1,ins+feeds
  outspec(i)=bottom %for i=1,1,feeds
  %if outs>0 %start
      %if mode&top outputs#0 %start
          outspec (i+feeds) = top %for i=1,1,outs
          top outputs present = true
      %finish %else %if mode&mixed outputs=0 %start
          outspec (i+feeds) = bottom %for i=1,1,outs
      %else
          stage = 2
          %for i=1,1,outs %cycle
             %if bottom#ospec(i)#top %start
                 warning ("Invalid position for output ".itos(i,0)." of symbol """.name."""")
                 ospec(i) = bottom
             %finish
             outspec(i+feeds) = ospec(i)
             top outputs present = true %if ospec(i)=top
          %repeat
      %finish
  %finish
  stage = 3
  define plain
  define plaout
  plapupmaxy=25
  plainxb=plapupmaxy
  plainyb=plaoutmaxy-plainmaxy-8
  %if feeds>1 %then plainyb=plainyb+5*(feeds-1)
  {check I/O spacing specifications if stretching}
  curx=plainxb+5
  %if mode&stretch inputs=0 %start
      inx(i)=0 %for i=1,1,ins
  %finish
  %if mode&stretch outputs=0 %start
      outx(i)=0 %for i=1,1,outs
  %finish
  %if ins>0 %and 0 < inx(1) < curx %start
    j=inx(1)        {1st input too far over to left}
    warning ("Symbol """.name.""" input 1 too far left, all inputs moved right")
    inx(1) = curx
    inx(i)=inx(i)+inx(1)-j %for i=2,1,ins
  %finish
  %for i=1,1,ins %cycle
    %if inx(i)<=0 %then inx(i)=curx
    %if i>1 %start
     %if inx(i)-inx(i-1) < plainmaxx %start
       inx(i) = inx(i-1)+plainmaxx
       warning ("Symbol """.name.""" input ".ItoS(i,0)." too far left, moved to ".ItoS(inx(i),0))
     %finish
    %finish
    curx=inx(i)+plainmaxx
  %repeat
{for ease of programming later, put input coords into another array}
{with the feed back coords inserted at the right hand end of the array}
 %if ins>0 %start
     inRA(i)=inx(i) %for i=1,1,ins
 %finish
 %if feeds>0 %start
     %for I=1,1,feeds %cycle
          %if i=1 %and ins=0 %start
              inRA(0)=curx { to keep the clock line happy }
              inRA(1)=curx
          %else
              inRA(i+ins)=inRA(i+ins-1)+plainmaxx
          %finish
     %repeat
 %finish
{check spacing between last input & 1st output, taking into consideration}
{feed backs}
  curx=curx+(feeds*plainmaxx)+(feeds*plaoutmaxx)+10 {feeds spacing}
  %if feeds>7 %then curx=curx+((feeds//extragnd)*9)
  Stage = 4
  %if outs>0 %and 0 < outx(1) < curx %start
    j=outx(1)   {1st output too far to left}
    warning ("Symbol """.name.""" output 1 too far left, all outputs moved right")
    outx(1) = curx
    outx(i)=outx(i)+outx(1)-j %for i=2,1,outs
  %else
    output displacement = 0
  %finish
  j=extragnd-feeds
  %for i=1,1,outs %cycle
    %if j=0 %start
      j=extragnd
      %if 7<=outx(i-1)-outx(i-2) <= 11 %then curx=outx(i-2)+23    %c
              %else curx=outx(i-2)+(outx(i-1)-outx(i-2))-11+23
    %finish
    %if outx(i) <= 0 %then outx(i)=curx
    %if i>1 %start
     %if outx(i) < curx  %start
         outx(i) = curx
         warning ("Symbol """.name.""" output ".ItoS(i,0)." too far left, moved to ".ItoS(outx(i),0))
     %finish
    %else
     output displacement = outx(1)-curx
    %finish
    curx=outx(i)+plaoutmaxx
    j=j-1
  %repeat
  Stage = 5
{for ease of programming later, shift outputs into a new  array and introduce}
{to the left the positions of the feed backs}
  %if outs>0 %start
      outRA(feeds+i)=outx(i) %for i=outs,-1,1
  %finish
  %if feeds>0 %start
      %for i=feeds,-1,1 %cycle
         %if i=feeds %and outs=0 %then outRA(i)=curx-7 %else outRA(i)=outRA(i+1)-7
      %repeat
  %finish
  eprods=(prods+1) & (\1)  {even up no of products}
  j=(eprods-1)//extragnd  {no of xtra gnd lines required}
  i=7*eprods+(9*j)
  define pdp(andpdpt,i,eprods,top)
  define pdp(andpdpb,i,eprods,bottom)
  define pup(andpup,inRA(infs)-plainxb+5)
  eoutfs=(outfs+1)&(\1)
  %if eoutfs # outfs %start {ie odd no of functions}
    outRA(eoutfs)=outRA(outfs)+7
  %finish
  i=outRA(eoutfs)-outRA(1)+8+output displacement
  j=(eoutfs-1)//extragnd
  %if mode&stretch#0 %then define stretched pdp(orpdp,i,eoutfs) %c
                     %else define pdp(orpdp,i,eoutfs,out)
  i=7*eprods+9*((eprods-1)//extragnd)-4
  define pup(orpup,i)
  %if top outputs present=true %start
    define plarout(i) 
    define plalout
    define extended pup (extpup,i)
  %finish

{start to define the main pla symbol}
  symbol(name)
  plainxb=plapupmaxy
  plainyb=plaoutmaxy-plainmaxy-8
  %if feeds>1 %then plainyb=plainyb+5*(feeds-1)
  andpdpyb=plainyb+plainmaxy

{draw input buffers and poly/diff/poly lines}
  %if bottom inputs present=true %or feeds>0 %start
    %for i=1,1,infs %cycle  {lets find bottom inputs}
     %if inspec(i)=bottom %or i>ins {ie feedback} %start
      draw ("plain",inRA(i)-5,plainyb)
      draw(andpdpb,inRA(i)-5,andpdpyb)
     %finish
    %repeat
  %finish
  orpdpxb=inRA(infs)+16
layer(poly)   {draw clock line phi1}
  box(0,plainyb+plainphi1y,9,plainyb+plainphi1y+2)
  %if feeds>0 %start
    box(9,plainyb+plainphi1y,inRA(ins)+9,plainyb+plainphi1y+2)
   layer(metal)  {in buffer VDD line}
    box(4,plainyb+plainvddy,inRA(infs),plainyb+plainvddy+4)
    %if %not bottom inputs present=true %start {GND input buffers}
      box(inRA(ins)+9,plainyb+plaingndy,orpdpxb,plainyb+plaingndy+4)
    %else
      %for i=1,1,ins %cycle
        %if inspec(i)=bottom %then %exit
      %repeat
      box(inRA(i)+9,plainyb+plaingndy,orpdpxb,plainyb+plaingndy+4)
    %finish
  %finish %else %if bottom inputs present=true %start
    %for i=ins,-1,1 %cycle
      %if inspec(i)=bottom %then %exit
    %repeat  {clock line phi 1}
    box(9,plainyb+plainphi1y,inRA(i)-5,plainyb+plainphi1y+2)
   layer(metal)  {in buffer VDD line}
    box(4,plainyb+plainvddy,inRA(i)-3,plainyb+plainvddy+4)
    %for i=1,1,ins %cycle
      %if inspec(i)=bottom %then %exit
    %repeat  {in buffer GND line}
    box(inRA(i)+9,plainyb+plaingndy,orpdpxb,plainyb+plaingndy+4)
  %finish
layer(metal)
  box(plainxb+7,andpdpyb,orpdpxb,andpdpyb+4) {bottom gnd line for pdp lines}

{draw and-plane pull-up pairs and metal lines}
  cury=andpdpyb+7
  j=extragnd
  %for i=2,2,eprods %cycle
    %if j=0 %then %start    {extra gnd line required}
      layer(metal)
        box(plainxb+7,cury+2,orpdpxb,cury+6)
      cury=cury+9
      j=extragnd
    %finish
    drawrot(andpup,plainxb,cury,1)
    %if top inputs present=true %start
      dm(orpdpxb-9,cury+3); pm(orpdpxb-5,cury+3)
      dm(orpdpxb-9,cury+10); pm(orpdpxb-5,cury+10)
    %else
      dm(orpdpxb-9,cury+3) ; pm(orpdpxb-5,cury+3)
      dm(orpdpxb-9,cury+10) ; pm(orpdpxb-5,cury+10)
    %finish
    drawrot(orpdp,orpdpxb,cury+11,-1)
    layer(poly)
      box(orpdpxb-3,cury+1,orpdpxb,cury+3)
      box(orpdpxb-3,cury+9,orpdpxb,cury+11)
    cury=cury+14
    j=j-2
  %repeat
  layer(metal)
    box(plainxb+7,cury+2,orpdpxb,cury+6)  {top gnd line in AND plane}
    box(orpdpxb,andpdpyb+8+plaoutgndy-plaoutmaxy,orpdpxb+4,cury+6)
    plainxtb=plainxb     {GND line between AND and OR plane}
    plainytb=cury+6

{ draw top input buffers }
 %if top inputs present=true %start
   plainytb=plainytb+plainmaxy
   %for i=1,1,ins %cycle
    %if inspec(i)=top %start
      draw my("plain",inRA(i)-5,plainytb)
      draw(andpdpt,inRA(i)-5,andpdpyb)
    %finish
   %repeat
 layer(poly)      {wire phi1 up top}
   box(7,plainyb+plainphi1y+2,11,plainyb+plainvddy+7)
   pm(9,plainyb+plainvddy+9)
   box(7,plainytb-plainvddy-7,11,plainytb-plainphi1y)
 layer(metal)
   box(7,plainyb+plainvddy+7,11,plainytb-plainvddy-7)
   pm(9,plainytb-plainvddy-9)
   %for i=ins,-1,1 %cycle
     %if inspec(i)=top %then %exit  {got top input}
   %repeat
 layer(poly)
   box(11,plainytb-plainphi1y-2,inRA(i)-5,plainytb-plainphi1y)
   play=plainytb
   layer(metal)  {top input VDD line}
     %if %not top outputs present=true %then                              %c
       box(4,plainytb-plainvddy-4,orpdpxb,plainytb-plainvddy) %c
       %else box(4,plainytb-plainvddy-4,inRA(i)-3,plainytb-plainvddy)
     %if top outputs present=true %then         %c
       box(4,plainytb-1,orpdpxb,plainytb+3) {VDD for top outputs}
 %finish

{draw or-plane pull-up pairs and metal lines}
  plaoutxb=orpdpxb+6
  orpupyb=cury-3
  plaoutytb=orpupyb+plaoutmaxy  {set top OR plane base}
  plaoutyb=andpdpyb+8-plaoutmaxy
  orpdpyb=plaoutyb+plaoutmaxy
  j=extragnd
  %for i=2,2,eoutfs %cycle
    %if j=0 %then %start
    layer(metal)
      box(outRA(i-3)+15,plaoutyb+plaoutgndy+4,outRA(i-3)+19,orpupyb-3)
      j=extragnd
    %finish
    %if i>outfs %start   {ie redundant output}
      %if outspec(i-1)=top %start
        draw MY("plaout",outRA(i-1)-2,plaoutytb)
        draw MY(extpup,outRA(i-1)-1,plaoutyb+plaoutmaxy)
      %else
        draw("plaout",outRA(i-1)-2,plaoutyb)
        %if top outputs present=true %then draw(extpup,outRA(i-1)-1,plaoutytb-plaoutmaxy)    %c
                                     %else draw(orpup,outRA(i-1)-1,orpupyb)
      %finish
    %finish %else %if outspec(i-1)=top %start
      %if outspec(i)=top %start
        draw MY("plaout",outRA(i-1)-2,plaoutytb)
        draw MY(extpup,outRA(i-1)-1,plaoutyb+plaoutmaxy)
      %else
        draw("plamr",outRA(i-1)-2,plaoutyb)
        draw MY("plaml",outRA(i-1)-2,plaoutytb)
      %finish
    %else
      %if outspec(i)=top %start
        draw("plaml",outRA(i-1)-2,plaoutyb)
        draw MY("plamr",outRA(i-1)-2,plaoutytb)
      %else  {both bottom}
        draw("plaout",outRA(i-1)-2,plaoutyb)
        %if top outputs present=true %then draw(extpup,outRA(i-1)-1,plaoutytb-plaoutmaxy)    %c
                         %else draw(orpup,outRA(i-1)-1,orpupyb)
      %finish
    %finish
    j=j-2
  %repeat
  %if top outputs present=true %then plax=outRA(eoutfs)+18     %c
    %else plax=outRA(eoutfs)+11
  %if %not top outputs present=true %start
    %if %not top inputs present=true %then play=orpupyb+plapupmaxy
  %else 
    play=plaoutytb
  %finish
  layer(poly)   {draw clock line phi2 right across}
    box(outRA(1)-2,plaoutyb+plaoutphi2y,plax,plaoutyb+plaoutphi2y+2)
 {wire clock PHI2 up top if necessary and right across}
  %if top outputs present=true %start
      box(outRA(1)-2,plaoutytb-plaoutphi2y-2,plax-11,plaoutytb-plaoutphi2y)
    layer(metal)
      box(plax-11,plaoutyb+plaoutphi2y+6,plax-7,plaoutytb-plaoutphi2y-4)
      pm(plax-9,plaoutyb+plaoutphi2y+4)
      pm(plax-9,plaoutytb-plaoutphi2y-2)
  %finish

{draw metal gnd and vdd lines}
 layer(metal)    {GND lines first}
   %if top outputs present=true %start
     %if top inputs present=true %then                                         %c
       box(orpdpxb,plainytb-plainmaxy,orpdpxb+4,plainytb-plaingndy)
                                     {vert. GND between AND and OR}
   %finish
   %if bottom inputs present=true %or feeds>0 %then        %c
     box(orpdpxb-4,plainyb+plaingndy+4,orpdpxb,plaoutyb+plaoutgndy+4) 
                                    {vert. GND for bottom AND reg}
   box(orpdpxb+4,plaoutyb+plaoutgndy,plax-4,plaoutyb+plaoutgndy+4) 
                                 {GND for bottom out reg}
   box(plax-4,0,plax,play)       {vert. right-most GND line}
   %if top outputs present=true %start  {top output GND line}
     box(orpdpxb+4,plaoutytb-plaoutgndy-4,plax-4,plaoutytb-plaoutgndy)
     %if top inputs present=true %then  {top input GND line}                       %c
      box(plainxtb+14,plainytb-plaingndy-4,orpdpxb,plainytb-plaingndy)
                                 {top GND line for inputs buffers}
   %else
     box(plainxtb,plainytb-plaingndy-4,plax-4,plainytb-plaingndy) %if top inputs present=true
   %finish    {Now VDD lines}
    box(4,plainyb-4,orpdpxb,plainyb)         {lower horiz. VDD line}
    box(orpdpxb-4,plainyb,orpdpxb,plaoutyb+plaoutvddy+4) {wee addition}
                                             {VDD for output buffers}
    box(orpdpxb,plaoutyb+plaoutvddy,plax-12,plaoutyb+plaoutvddy+4)
    box(0,0,4,play)            {left-most VDD line}
    %if %not top inputs present=true %start
      %if top outputs present=true %start   {top outputs VDD line}
        box(4,play-plaoutvddy-4,plax-11,play-plaoutvddy)
      %else; box(4,play-4,plax-11,play)  {pull-ups VDD line}
      %finish
    %else  {top input VDD line}
      %if top outputs present=true %start
        box(orpdpxb+4,play-plaoutvddy-4,plax-11,play-plaoutvddy)
        box(orpdpxb,play-plaoutvddy-4,orpdpxb+4,plainytb+3)
      %else       {top input VDD line}
        box(orpdpxb-3,plainytb-plainvddy-4,orpdpxb,plainytb-plainvddy)
        box(orpdpxb,orpupyb+plapupmaxy-4,orpdpxb+4,plainytb-plainvddy)
        box(orpdpxb+4,orpupyb+plapupmaxy-4,plax-11,orpupyb+plapupmaxy)
      %finish
    %finish
  phi1y=plainyb+plainphi1y
  phi2y=plaoutyb+plaoutphi2y

{work out positions of inputs and outputs}
  layer(diffusion)
    %for i=1,1,ins %cycle
      %if inspec(i)=bottom %and plainyb#0 %start
        box(inRA(i),0,inRA(i)+2,plainyb)
      %else
        %if top outputs present=true %then box(inRA(i),plainytb,inRA(i)+2,play)
      %finish
    %repeat
  %for i=feeds+1,1,outfs %cycle
    %if outspec(i)=bottom %start
      %if plaoutyb#0 %start
       %if i&1=1 %start
        box(outRA(i),0,outRA(i)+2,plaoutyb)
       %else
        %if outRA(i-1) < outRA(i)-7 %start {ie stretching}
         box(outRA(i),0,outRA(i)+2,plaoutyb)
         box(outRA(i-1)+9,plaoutyb,outRA(i)+2,plaoutyb+2)
        %else
         box(outRA(i),0,outRA(i)+2,plaoutyb)
        %finish
       %finish
      %finish %else %if i&1#1 %start {ie r.h.s. output}
       %if outRA(i-1) < outRA(i)-7 %start
        box(outRA(i-1)+9,plaoutyb,outRA(i)+2,plaoutyb+2)
       %finish
      %finish
    %else     {ie outputs out top}
     %if i&1#1 %start
       %if outRA(i-1) < outRA(i)-9 %start
         box(outRA(i-1)+9,plaoutytb-2,outRA(i)+2,plaoutytb)
       %finish
     %finish
    %finish
   %repeat

{draw feedbacks}
  %if feeds>0 %then %start
    layer(diffusion)
      box(inRA(infs),plaoutyb,outRA(1),plaoutyb+2)
      box(inRA(infs),plaoutyb+2,inRA(infs)+2,plainyb)
    %if feeds>1 %then %start
      %for i=2,1,feeds %cycle
        box(outRA(i),plaoutyb-5*(i-1)+2,outRA(i)+2,plaoutyb)
        box(inRA(infs-i+1)+2,plaoutyb-5*(i-1),
            outRA(i)+2,plaoutyb-5*(i-1)+2)
        box(inRA(infs-i+1),plaoutyb-5*(i-1),
            inRA(infs-i+1)+2,plainyb)
      %repeat
    %finish
  %finish

{program the and-plane}
  andp=1
  andt=1
  cury=andpdpyb+8
  j=extragnd
  %for i=1,1,prods %cycle
    %if j=0 %then cury=cury+9 %and j=extragnd
    %for k=1,1,infs %cycle
      %if and(andp)#0 %then %start
        tran="and".itos(andt,0)
        andt=andt+1
        %if and(andp)<0 %then %start {transistor in lhs track}
          etpy(tran,inRA(k)-4,cury,4)
          %if (k>1 %and and(andp-1)<=0) %then dm(inRA(k)-7,cury+2)
          %if k=1 %and inRA(1)>plainxb+6 %then dm(inRA(1)-7,cury+2)
          %if k>1 %and and(andp-1)>0 %start
            %if inRA(k-1)+9<inRA(k)-6 %start {ie stretching}
              layer(diffusion)
                box(inRA(k-1)+9,cury,inRA(k)-6,cury+4)
            %finish
          %finish
        %finish %else %start
          etpy(tran,inRA(k)+2,cury,4)
          %if k<infs %then dm(inRA(k)+7,cury+2)
        %finish
      %finish
      andp=andp+1
    %repeat
    cury=cury+7
    j=j-1
  %repeat

{program the or-plane}
  orp=1
  ort=1
  %for i=1,1,outfs %cycle
    l=extragnd
    cury=andpdpyb+8
    %for k=1,1,prods %cycle
      %if l=0 %then cury=cury+9 %and l=extragnd
      %if or(orp)>0 %then %start
        tran="or".itos(ort,0)
        ort=ort+1
        %if k&1#0 %then %start
         %if i&1=1 %start {l.h.s. of pair}
          etpx(tran,outRA(i),cury+1,4)
          %if k>1 %and (or(orp-1)<=0 %or l=extragnd) %c
            %then dm(outRA(i)+2,cury-2)
         %else
          etpx(tran,outRA(i-1)+7,cury+1,4)
          %if k>1 %and (or(orp-1)<=0 %or l=extragnd) %then  %c
            dm(outRA(i-1)+9,cury-2)
         %finish
        %finish %else %start
         %if i&1=1 %start
          etpx(tran,outRA(i),cury+7,4)
          %if k<prods %then dm(outRA(i)+2,cury+12)
         %else
          etpx(tran,outRA(i-1)+7,cury+7,4)
          %if k<prods %then dm(outRA(i-1)+9,cury+12)
         %finish
        %finish
      %finish
      %if k&1=0 %then cury=cury+14
      orp=orp+1
      l=l-1
    %repeat
  %repeat

  endsymbol
  %return
{******************************************************************************
%routine define plain
   {define input inverter and drivers}
   %const %string (7) name = "Pla in"
   %if symbol exists(name)#true %start
       symbol(name)
          etpx("plainphi1",5,2,2)
          etpx("plainpdb",5,14,5) ; dy(3)
          dtdby("plainpub",2,20,7)
          etpy("plainpdt",8,39,8)
          dtdby("plainput",2,38,-5)
          layer(poly)
            box(0,2,3,4) ; box(9,2,14,4) ; box(2,10,4,16)
            box(6,25,10,27) ; box(8,27,10,37)
            box(0,42,2,50) ; box(8,49,10,50)
          layer(diffusion)
            box(5,6,7,9) ; box(2,17,6,19)
            box(4,39,6,41) ; box(11,16,13,47)
          layer(metal)
            box(13,9,14,13)
          pdce(3,8) ; dm(11,11) ; dm(4,30) ; pdcs(3,43)
       endsymbol
   %finish
   plainmaxy = 50
   plainphi1y = 2
   plainvddy = 28
   plaingndy = 9
   plainmaxx = 14
%end
!----------------------------------------------------------------------
%routine define plaout
   {define output inverter pair}
   %const %string (7) name = "Pla out"
   %if symbol exists(name)#true %start
       symbol(name)
          dtdby("plaoutpur",5,36,-7);   dx(2);   dy(-2)
          etpx("plaoutpdr",6,40,4)
          dtdby("plaoutpul",2,23,-9);   dx(2)
          etpy("plaoutpdl",3,46,4)
          etpx("plaoutphi2l",3,59,2)
          etpx("plaoutphi2r",10,59,2)
          pdcs(3,3);   pdcs(10,3);   dm(7,9);   dm(8,45)
          pdcn(4,54);   pdcn(11,54);   dm(4,64);   dm(11,64)
          layer(poly)
             box(10,5,12,33);   box(1,5,3,12);   box(11,40,13,52)
             wirex(0,59,8)  { Clock line }
          layer(diffusion)
             box(7,11,9,25);   box(0,24,4,26);   box(0,26,2,50)
             box(7,46,10,50);   box(5,37,10,39)
       endsymbol
   %finish
   plaoutmaxy = 66
   plaoutphi2y = 59
   plaoutvddy = 7
   plaoutgndy = 43
   plaoutmaxx = 7
%end
!------------------------------------------------------------------------------
%routine define pdp(%string (31) %name name,%integer height,x,type)
   {define symbol for poly/diffusion/poly lines}
   %integer m,i,a,b,xg

   %string (7) %fn Side (%integer type)
      %const %string (7) %array Sides (1:4) = "bottom", "right", "top", "left"
      %result = "?" %unless 1<=type<=4
      %result = Sides(type)
   %end

   name = "Pla pdp ".side(type)." ".itos(height,0)
   name = name." TO" %if top outputs present = true %and type=out
   %if symbol exists(name)=true %then %return
   xg=(x-1)//extragnd
   symbol(name)
     layer(diffusion)
       dm(5,i*(7*extragnd+9)+2) %for i=0,1,xg
       %if type=out %start
         %if top outputs present=true %then i=16 %else i=9
       %else
         i=11
       %finish
     dm(5, height+i);  box (4,4,6,height+i-2)
     layer(poly)
       m=x
       a=0;   b=0   {l.h.s. poly track}
       %cycle
         %if type=bottom %or b>0 %or type=out %start
           box(a,b,a+2,b+5)
           box(a,b+5,a+3,b+7)
         %finish
         b=b+7;  a=a+1
         %if m>extragnd %start
           box(a,b,a+2,b+7*extragnd+1); b=b+7*extragnd-1; a=a-1
           box(a,b,a+2,b+3); b=b+3
         %finish %else %start
           box(a,b,a+2,b+7*m)
           %exit
         %finish
         m=m-extragnd
       %repeat
       %if type=top %start
         box(0,height+6,3,height+8)
         box(0,height+8,2,height+13)
       %finish
       m=x
       a=8;  b=0
       %cycle    {r.h.s. poly track}
         %if type=bottom %or b>0 %or type=out %start
           box(a,b,a+2,b+5)
           box(a-1,b+5,a+2,b+7)
         %finish
         b=b+7;  a=a-1
         %if m>extragnd %start
           box(a,b,a+2,b+7*extragnd+1); b=b+7*extragnd-1; a=a+1
           box(a,b,a+2,b+3); b=b+3
         %finish %else %start
           box(a,b,a+2,b+7*m)
           %exit
         %finish
         m=m-extragnd
       %repeat
       %if type=top %start
         box(7,height+6,10,height+8)
         box(8,height+8,10,height+13)
       %finish
   endsymbol
%end
!------------------------------------------------------------------------------
%routine define stretched pdp(%string (31) %name name,%integer height,x)
   %integer i,a,b,xg,outxbase

   name = "Pla spdp ".itos(height,0)
   name = name." TO" %if top outputs present = true
   %if symbol exists(name)=true %then %return
   outxbase=inRA(infs)+16
   xg=(x-1)//extragnd
   symbol(name)
     layer(diffusion)
       dm(5,2)
       %if xg>0 %start
         dm(5,outRA(i*8-1)+17-outxbase) %for i=1,1,xg
       %finish
       %if top outputs present=true %then i=16 %else i=9
       dm (5, height+i);  box (4,4,6,height+i-2)
     layer(poly)
       a=0; b=0
       %for i=0,1,xg %cycle
         box(a,b,a+2,b+5)
         box(a,b+5,a+3,b+7)
         b=b+7; a=a+1
         %if i#xg %start
           box(a,b,a+2,outRA((i+1)*8-1)+14-outxbase)
           b=outRA((i+1)*8-1)+12-outxbase
           a=a-1
           box(a,b,a+2,b+3)
           b=b+3
         %else
           box(a,b,a+2,height+5)
         %finish
       %repeat
       a=8; b=0
       %for i=0,1,xg %cycle
         box(a,b,a+2,b+5)
         box(a-1,b+5,a+2,b+7)
         b=b+7; a=a-1
         %if i#xg %start
           box(a,b,a+2,outRA((i+1)*8-1)+14-outxbase)
           a=a+1;
           b=outRA((i+1)*8-1)+12-outxbase
           box(a,b,a+2,b+3); b=b+3
         %else
           box(a,b,a+2,height+5)
         %finish
       %repeat
   endsymbol
%end
!-------------------------------------------------------------------------------
%routine define pup(%string (31) %name name,%integer l)
   {define symbol for pullups and metal lines from them}
   name = "Pla pup ".itos(l,0)
   %if symbol exists(name)=true %then %return
   symbol(name)
     dtdby("plapuppul",2,6,7)
     dtdby("plapuppur",9,15,7)
     layer(diffusion)
       dm(3,2) ; box(2,15,4,21) ; dm(4,23)
       box(6,23,11,25) ; box(9,4,11,13) ; dm(10,2)
     layer(metal)
       box(1,-l,5,0) ; box(8,-l,12,0)
   endsymbol
%end
!-------------------------------------------------------------------------------
%routine define extended pup (%string (31) %name name,%integer l)
   {define extended pull-up suitable for mixed outputs}
   name = "Pla xpup ".itos(l,0)
   %if symbol exists(name)=true %then %return
   symbol(name)
      dtdby(name."l",3,46,7)
      dtdby(name."r",8,34,7)
      dm(3,11);  dm(10,11);  dm(4,57)
      dm(3,2);  dm(10,2)
      layer(diffusion)
        box(3,13,5,44);  box(6,57,10,59);  box(8,43,10,57)
        box(8,13,10,32)
      layer(poly)
        box(-1,5,14,7)
      layer(metal)
        box(1,4,5,9);  box(8,4,12,9)
        box(1,-l,5,0);  box(8,-l,12,0)
   endsymbol
%end
{-----------------------------------------------------------------------------}
%routine define plalout  {output l.h.s. with pull-up r.h.s. of cell}
   %const %string(7) name = "Pla ml"   {ie mixed output, with left output}
   %if symbol exists(name)=true %then %return
   symbol(name)
      dtdby(name."inv",3,23,-9); dx(2)
      etpx(name."phl",3,59,2)
      etpx(name."l",3,40,2)
      dtdby(name."pup",8,29,7)
      pdcs(3,3);  dm(10,9);  dm(3,45)
      pdcn(4,54);  dm(4,64);  dm(11,56)
      dm(11,64)
      layer(poly)
        box(1,5,3,12);  box(0,59,1,61);  box(7,59,14,61)
        box(6,40,8,50);  box(4,48,6,52)
      layer(diffusion)
        box(8,11,10,27);  box(3,25,5,38)
        box(8,37,11,39);  box(9,39,11,54)
      layer(metal)
        box(9,58,13,62)
   endsymbol
%end
{------------------------------------------------------------------------------}
%routine define plarout(%integer l)  {output r.h.s. , pull-up l.h.s. of cell}
   %const %string(7) name = "Pla mr"
   %if symbol exists(name)=true %then %return
   symbol(name)
      dtdby(name."inv",9,23,-9);  dx(-2)
      etpx(name."phl",9,59,2)
      etpx(name."l",9,40,2)
      dtdby(name."pup",4,29,7)
      pdcs(10,3); dm(5,9); dm(10,45)
      pdcn(10,54); dm(11,64);  dm(4,56)
      dm(4,64)
      layer(poly)
         box(10,5,12,12);  box(13,59,14,61)
         box(0,59,7,61);  box(5,40,7,50)
         box(7,48,9,50);  box(9,48,11,52)
      layer(diffusion)
         box(3,11,5,26);  box(3,26,6,28)
         box(9,25,11,38);  box(2,37,6,39);  box(2,39,4,54)
      layer(metal)
         box(2,58,6,62)
         box(2,66,6,l+66); box(9,66,13,l+66)
   endsymbol
%end
{------------------------------------------------------------------------------}
%end
%endoffile
