! NEW ILAP PLA generator (no stretching)
! DJR 9/12/85

{#######################################################################}
{#                                                                     #}
{#     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 Ken Chisholm or David Rees at the above address,    #}
{#  and these are likely to be fixed in a future release.              #}
{#                                                                     #}
{#######################################################################}

%include "ilap:nmos.inc"

%externalstring(255)%fnspec itos(%integer i,n)

%external %routine npla %alias "ILAP_NPLA" ( %string(31) name,
     %integer mode,
     %integer %array %name ispec,
     %integer %array %name ospec,
     %integer ins, outs, feeds, prods,
     %integer %array %name and,
     %integer %array %name or,
     %integer %name phi1y, phi2y,
     %integer %array %name inx,
     %integer %array %name outx )

%integer plainx,plaoutx,plaphi1y,plaphi2y,curx,cury,andp,orp,nor,xag,xog
%integer eprods,orbasex,basey,i,j,p,plaoutlx,plaoutrx,plarx,phi2x,tphi2y
%integer lasttopin,lastbottomin,firsttopout,firstbottomout,tops,topy
%constinteger xgp=8,ppitch=7,ipitch=14,opitch=8
%integerarray infeedx,outfeedx(1:feeds+1)   {to avoid inside-out array}
%integerarray iispec(1:ins+feeds),oospec(1:feeds+outs)

{  print string("Warning : New top/bottom PLA generator in operation 
{Report any problems to DJR ASAP
{")

  lasttopin=0
  lastbottomin=0
  %if mode&topinputs#0 %then %start
    iispec(i)=top %for i=1,1,ins
    lasttopin=ins
  %finish %else %c
  %if mode&mixed inputs#0 %then %start
    %for i=1,1,ins %cycle
      iispec(i)=ispec(i)
      %if iispec(i)=top %then lasttopin=i
      %if iispec(i)=bottom %then lastbottomin=i
    %repeat
  %finish %else %start
    iispec(i)=bottom %for i=1,1,ins
    lastbottomin=ins
  %finish
  %if feeds>0 %then %start
    iispec(i)=bottom %for i=ins+1,1,ins+feeds
    lastbottomin=ins+feeds
  %finish

  firsttopout=feeds+outs+1    {i.e. none yet}
  firstbottomout=feeds+outs+1
  %if mode&topoutputs#0 %then %start
    oospec(i)=top %for i=feeds+outs,-1,feeds+1
    firsttopout=feeds+1
  %finish %else %c
  %if mode&mixed outputs#0 %then %start
    %for i=feeds+outs,-1,feeds+1 %cycle
      oospec(i)=ospec(i-feeds)
      %if oospec(i)=top %then firsttopout=i
      %if oospec(i)=bottom %then firstbottomout=i
    %repeat
  %finish %else %start
    oospec(i)=bottom %for i=feeds+outs,-1,feeds+1
    firstbottomout=feeds+1
  %finish
  %if feeds>0 %then %start
    oospec(i)=bottom %for i=1,1,feeds
    firstbottomout=1
  %finish
  %if lasttopin>0 %or firsttopout<feeds+outs+1 %then tops=true %else tops=false

  %if symbol exists("nplain")=true %then ->skip  {all symbols assumed defined}
  %include "nplasyms"
skip:
  plainx=6
  plaphi1y=3
  plaoutx=1
  plaphi2y=60
  plaoutlx=7        {rhs limit of metal in plaoutl}
  plaoutrx=1        {  ditto for plaoutr }

  symbol(name)

    %if feeds>0 %then basey=5*feeds-4 %else basey=0

    curx=0
    cury=basey

    eprods=((prods+1)//2)*2    {make an even no. of product terms}

    {generate and-plane}
    draw("nplabl",curx,cury)
    %if lastbottomin>0 %then %start    {bottom inputs present}
      phi1y=cury+plaphi1y
      layer(poly)
      wirex(0,phi1y,sx("nplabl"))
    %finish
    curx=curx+sx("nplabl")
    %for i=1,1,ins+feeds %cycle
      %if iispec(i)=bottom %then draw("nplain",curx,cury) %else %start
        %if i<=lastbottomin %then draw("nplaint",curx,cury) %c
           %else draw("nplaints",curx,cury)    {leave out phi1 line if poss.}
      %finish
      %if i<=ins %then inx(i)=curx+plainx %c
                 %else infeedx(ins+feeds+1-i)=curx+plainx
      curx=curx+ipitch
    %repeat
    draw ("nplabc",curx,cury)
    cury=cury+sy("nplain")-1    {to overlap}
    andp=1
    xag=0
    %for p=1,1,eprods %cycle
      curx=sy("nplapu00")
      %if p=1 %then drawrot("nplapu00",curx,cury,1) %c
              %else drawrot("nplapu".itos(xag,0),curx,cury,1)
      curx=curx-4    {to overlap}
      %for i=1,1,ins+feeds %cycle
        %if p>prods %then nor=0 %else nor=and(andp) %and andp=andp+1
        %if nor<0 %then draw("nplaanor0",curx,cury) %else %c
        %if nor=0 %then draw("nplaanorx",curx,cury) %else %c
                        draw("nplaanor1",curx,cury)
        curx=curx+ipitch
      %repeat
      %if p&1#0 %then draw("nplac",curx,cury)    {for each pair of product terms}
      cury=cury+ppitch
      xag=xag+1
      %if xag=xgp %and p#eprods %then %start
        xag=0
        curx=sy("nplapu00")-2
        %for i=1,1,ins+feeds %cycle
          draw("nplaaxg",curx,cury)
          curx=curx+ipitch
        %repeat
        draw("nplaaxgr",curx,cury)
        cury=cury+sy("nplaaxg")-1    {to overlap}
      %finish
    %repeat
    orbasex=curx+sx("nplac")-1
    curx=0
    %if tops=false %then %start
      draw("nplatl",curx,cury)
      curx=curx+sx("nplatl")
      %for i=1,1,ins+feeds %cycle
        draw("nplat",curx,cury)
        curx=curx+ipitch
      %repeat
      draw("nplatc",curx,cury)
    %finish %else %start
      draw("nplatlt",curx,cury)
      cury=cury+sy("nplain")
      %if lasttopin>0 %then %start
        %if lastbottomin=0 %then %start    {no bottom inputs}
          phi1y=cury-plaphi1y-2
          layer(poly)
          wirex(0,phi1y,sx("nplatlt"))
        %finish %else %start           {bring phi1y line up from bottom}
          layer(poly)
          wirey(9,phi1y+2,36)
          pm(10,phi1y+40)
          layer(metal) ; width(3)
          wirey(8,phi1y+42,cury-plaphi1y-42-phi1y-42)
          pm(10,cury-plaphi1y-40)
          layer(poly)
          wirey(9,cury-plaphi1y-38,38)
          dx(sx("nplatlt")-11)
        %finish
      %finish
      curx=curx+sx("nplatlt")
      %for i=1,1,ins+feeds %cycle
        %if iispec(i)=top %then drawmy("nplain",curx,cury) %else %start
          %if i<=lasttopin %then drawmy("nplaint",curx,cury) %c
                           %else drawmy("nplaints",curx,cury)
        %finish
        curx=curx+ipitch
      %repeat
      cury=cury-sy("nplain")
      draw("nplatct",curx,cury)
    %finish

    {generate or-plane}
    curx=orbasex-4
    cury=basey
    xog=0
    %for i=1,1,feeds+outs %cycle    {generate output buffers}
      %if oospec(i)=bottom %then %start
        %if i=1 %then draw("nplaoutl0",curx,cury) %else %start
          %if i&1#0 %then draw("nplaoutl",curx,cury) %c
                    %else draw("nplaoutr",curx,cury)
        %finish
      %finish %else %start
        %if i=1 %then draw("nplaouttl0",curx,cury) %else %start
          %if i&1#0 %then draw("nplaouttl",curx,cury) %c
                    %else draw("nplaouttr",curx,cury)
        %finish
      %finish
      %if i<=feeds %then outfeedx(i)=curx+plaoutx %c
                   %else outx(i-feeds)=curx+plaoutx
      %if i&1#0 %then plarx=curx+plaoutlx+3 %else plarx=curx+plaoutrx+3
      curx=curx+opitch
      xog=xog+1
      %if xog=xgp %and i#feeds+outs %then curx=curx+1 %and xog=0
    %repeat
    orp=1
    xog=0
    curx=orbasex
    %for i=1,1,feeds+outs %cycle
      cury=basey+sy("nplaoutl")-3    {to overlap}
      %if oospec(i)=bottom %then %start
        %if xog=0 %then draw("nplaoutp0",curx,cury) %c
                  %else draw("nplaoutp",curx,cury)
      %finish %else %start
        %if firstbottomout<=i %then %start
          %if xog=0 %then draw("nplaoutpt0",curx,cury) %c
                    %else draw("nplaoutpt",curx,cury)
        %finish %else %start    {can omit phi2 line}
          %if xog=0 %then draw("nplaoutpts0",curx,cury) %c
                    %else draw("nplaoutpts",curx,cury)
        %finish
      %finish
      cury=cury+sy("nplaoutp")-4    {to overlap}
      xag=0
      %for p=1,2,eprods-1 %cycle    {generate in pairs}
        j=or(orp)
        orp=orp+1
        j=or(orp)<<1!j %and orp=orp+1 %unless p=eprods-1 %and prods#eprods
        draw("nplaonor".itos(j,0),curx,cury)
        cury=cury+2*ppitch
        xag=xag+2
        %if xag=xgp %and p#eprods-1 %then %start
          xag=0
          cury=cury+4           {to avoid overlap}
          layer(metal); width(4);
          wirey(curx+2,cury,5);
          cury=cury+5
        %finish
      %repeat
      %if tops=false %then %start    {no top outputs}
        %if i=1 %then draw("nplapu00",curx,cury) %c
                %else draw("nplapu".itos(xog,0),curx,cury)
      %finish %else %start
        cury=cury+sy("nplaoutp")
        %if oospec(i)=top %then %start
          %if xog=0 %then drawmy("nplaoutp0",curx,cury) %c
                    %else drawmy("nplaoutp",curx,cury)
        %finish %else %start
          %if firsttopout<=i %then %start
            %if xog=0 %then drawmy("nplaoutpt0",curx,cury) %c
                      %else drawmy("nplaoutpt",curx,cury)
          %finish %else %start    {can omit phi2 line}
            %if xog=0 %then drawmy("nplaoutpts0",curx,cury) %c
                      %else drawmy("nplaoutpts",curx,cury)
          %finish
        %finish
        topy=cury+sy("nplaoutl")-2
      %finish
      curx=curx+ppitch
      xog=xog+1
      %if xog=xgp %and i#feeds+outs %then %start
        xog=0
        cury=basey+sy("nplaoutl")-5
        %if i>=firstbottomout %then layer(poly) %and wirex(curx,cury+9,9)
        layer(metal); width(4);
        wirey(curx+3,cury,14);
        cury=cury+14
        xag=0
        %for p=1,2,eprods-1 %cycle
          draw("nplaoxg",curx,cury)
          cury=cury+2*ppitch
          xag=xag+2
          %if xag=xgp %and p#eprods-1 %then %start  {to match and-plane extra gnd}
            xag=0
            layer(metal); width(4);
            wirey(curx+3,cury,9);
            cury=cury+9
          %finish
        %repeat
        %if tops=true %then %start
          %if i>=firsttopout %then layer(poly) %and wirex(curx,cury+3,9)
          layer(metal) ; width(4)
          wirey(curx+3,cury,14)
        %finish
        curx=curx+sx("nplaoxg")-1
      %finish
    %repeat
    phi2x=curx
    %if firstbottomout<=feeds+outs %and firsttopout<=feeds+outs %then %start
      %if plarx<curx+9 %then plarx=curx+9    {to leave room for phi2 line}
    %finish %else %start
      %if plarx<curx+2 %then plarx=curx+2
    %finish
    %if tops=true %then %start    {add top outputs etc.}
      curx=orbasex-4
      cury=topy-1
      xog=0
      %for i=1,1,feeds+outs %cycle    {generate output buffers}
        %if oospec(i)=top %then %start
          %if i=1 %then drawmy("nplaoutl0",curx,cury) %else %start
            %if i&1#0 %then drawmy("nplaoutl",curx,cury) %c
                      %else drawmy("nplaoutr",curx,cury)
          %finish
          layer(diffusion)    {add extra bit of diff to reach the top}
          wirey(curx+plaoutx,cury,1)
        %finish %else %start
          %if i=1 %then drawmy("nplaouttl0",curx,cury) %else %start
            %if i&1#0 %then drawmy("nplaouttl",curx,cury) %c
                      %else drawmy("nplaouttr",curx,cury)
          %finish
        %finish
        curx=curx+opitch
        xog=xog+1
        %if xog=xgp %and i#feeds+outs %then curx=curx+1 %and xog=0
      %repeat
    %finish
    cury=basey
    curx=plarx
    draw("nplabr",curx,cury)
    %if firstbottomout<=feeds+outs %then %start
      phi2y=cury+plaphi2y
      layer(poly)
      wirex(phi2x,phi2y,plarx+4-phi2x)
    %finish
    cury=cury+sy("nplabr")
    xag=0
    %for p=1,2,eprods-1 %cycle
      draw("nplar",curx,cury)
      cury=cury+2*ppitch
      xag=xag+2
      %if xag=xgp %and p#eprods-1 %then %start
        xag=0
        layer(metal); width(4);
        wirey(curx,cury,9);
        cury=cury+9
      %finish
    %repeat
    %if tops=true %then %start 
      draw("nplatr",curx,cury)
      %if firsttopout<=feeds+outs %then %start    {phi2 line needed at top}
        tphi2y=topy-1-plaphi2y-2
        %if firstbottomout>feeds+outs %then %start  {no phi2 needed at bottom}
          phi2y=tphi2y
          layer(poly)
          wirex(phi2x,phi2y,plarx+4-phi2x)
        %finish %else %start
          pm(phi2x+4,phi2y+1)
          layer(metal) ; width(3)
          wirey(phi2x+3,phi2y+3,tphi2y-1-phi2y-3)
          pm(phi2x+4,tphi2y+1)
          layer(poly)
          wirex(phi2x,tphi2y,2)
        %finish
      %finish
    %finish %else %start
      layer(metal); width(4)
      wirey(curx,cury,20)
    %finish

    %if feeds>0 %then %start
      {generate feedbacks and diffusion stubs etc.}
      layer(metal) ; width(4)
        wirey(0,0,basey)
        wirey(plarx,0,basey)
      layer(diffusion)
      %for i=1,1,ins %cycle
        %if iispec(i)=bottom %then wirey(inx(i),0,basey)
      %repeat
      wirex(infeedx(1),basey-1,outfeedx(1)-infeedx(1)+2)
      j=6
      %for i=2,1,feeds %cycle
        wirey(infeedx(i),basey,-j)
        dx(outfeedx(i)-infeedx(i))
        dy(j-2)
        j=j+5
      %repeat
      %for i=1,1,outs %cycle
        %if oospec(feeds+i)=bottom %then wirey(outx(i),0,basey)
    %repeat
  %finish

  endsymbol
%end
%endoffile
