! ILAP design rule checker

%include "nmos.inc"
%include "arrays.inc"
%external%routine%spec delete (%string(255) filename)
!%external%integer%fn%spec in stream
!%external%integer%fn%spec out stream
!%external%string(127)%fn%spec infilename
!%external%string(127)%fn%spec outfilename
!%const %string (1) snl = "
!"

{#########################################################################}
{#                                                                       #}
{#      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 DRC CONTROL = -1

%external %integer %map ILAP DRC CONTROL %alias "ILAP_DRC_CONTROL"
   %result == DRC CONTROL
%end

%record%format nodef (%short Player, Dlayer, Tlayer, Mlayer)

!%external%routine%spec analyse circuit %alias "ILAP__ANALYSE_CIRCUIT" (%record(nodef)%array(2)%name nodes,
!   %integer xmax, ymax, maxnum, %integer%array%name C, old Acount, old Lcount, old Bcount)

%external %routine check %alias "ILAP__CHECK" (%string(31) s, %byte%array(2)%name data, %c
    %short%array(2)%name tranids, %integer xmax, ymax, xorigin, yorigin)

    %record (nodef) %array nodes (0:xmax, 0:ymax)
    %record (nodef) %name left, current, bottom
    %short LDP, LM, LBC, BDP, BM, BBC, CDP, CM, CBC
    %short%array errors (0:xmax,0:ymax)
    %constinteger LARGE = 255
    %integer%array C, Acount, Lcount, Bcount (1:LARGE)
    %constinteger MAXERRS=15
    %conststring(60)%array message(0:MAXERRS) = %c
        "DIFFUSION spacing error ",
        "POLY spacing error ",
        "METAL spacing error ",
        "ION IMPLANT error ",
        "BURIED CONTACT error ",
        "CONTACT spacing error ",
        "Warning - Spurious transistor ",
        "Error in CONTACT ",
        "DIFFUSION width error ",
        "POLY width error ",
        "METAL width error ",
        "CONTACT to DIFFUSION too close to transistor ",
        "Insufficient overlap of transistor ",
        "CONTACT width error ",
        "Warning - Coincident METAL and POLY edges ",
        "Error in TRANSISTOR "
    %conststring(17) OK="  No errors found"
    %conststring(9) sperrfile = "$ERRS.TMP"
    %conststring(10) tranfile = "$TRANS.TMP"
    %constinteger NV=64, Tbit=128
    %constinteger end=2_111
    %constbyte widconst=8, main layer=39
    %constinteger DIFF=0, POLY=1, METAL=2, CONTACT=5
    %constinteger IMPLANT=3, BURIED=4
    %constinteger SPURTRAN=6, CONERR=7, CONTRAN=11, TRANOVERLAP=12
    %constinteger MP=14, TRANERR=15
    %constinteger SPACING=1, WIDTH=2, WIDTH AND SPACING=3
    %constinteger NOT REQUIRED=0, REQUIRED=1, NO=0
    %constinteger vertical=1, horizontal=2
    %integer POLYCHECK, DIFF2CHECK, DIFF3CHECK, METALCHECK
    %integer CONTACTCHECK, CTCHECK, TOCHECK, BCHECK, BURIEDCHECK
    %integer CONVALIDCHECK, IMPLANTOVERLAPCHECK, IMPLANTSPACINGCHECK
    %integer POLYDIFFTRANCHECK, MPCHECK, SPURTRANCHECK
    %constinteger noDTIerr=16_7FB6, noNV=16_BF
    %constshortinteger DSmask=1, DWmask=256, PWmask=512
    %constinteger conmask=16_80, impmask=8, bmask=16_10
    %constbyte PPPP=4_2222, PPTD=4_2231, PPTT=4_2233, PTDD=4_2311
    %constbyte PTTP=4_2322, DDDD=4_1111, DDDT=4_1113, DDTP=4_1132
    %constbyte DDTT=4_1133, DTPP=4_1322, DTTT=4_1333, TDDD=4_3111
    %constbyte TTPP=4_3322, TTDD=4_3311, TTTD=4_3331, TTTT=4_3333
    %constbyte PPPT=4_2223, TPPP=4_3222
    %constbyte DP=2_11, CC=2_11, MMMM=2_1111, BBBB=2_1111
    %constbyte OIIO=6, OOI=1, OIO=2, IOO=4
    %constbyte IOOO=8, OIOO=4, OOIO=2, OOOI=1
    %const%byte PandD=3, BandC=48, M=4, onlyD=1, noDorP=0, onlyB=16
    %integer%array errcount(0:MAXERRS)
    %byte row1P, row2P, row3P, row4P
    %byte row1D, row2D, row3D, row4D
    %byte row1M, row2M, row3M, row4M
    %byte row1C, row2C, row3C, row4C
    %byte row1B, row2B, row3B, row4B
    %byte row1I, row2I, row3I, row4I
    %byte P1, P2, P3, D1, D2, D3, M1, M2, M3, C1, C2, C3, B1, B2, B3
    %byte bt1, bt2, bt3, bt4, old bt1, old bt2, old bt3, old bt4
    %integer outsperrs, insperrs, trans, stream, x, y, nodenum, ex, ey
    %integer elayer, boxsize, comp, last, implanted
    %routine%spec follow connectivity


    %routine find streams
        %integer stream, old

!        old = outstream
!        %for stream = 15, -1, 0 %cycle
!            select output (stream)
!            %if outfilename = "NL:" %then outsperrs = stream %and %exit
!        %repeat
!        %for stream = 14, -1, 0 %cycle
!            select output (stream)
!            %if outfilename = "NL:" %then trans = stream %and %exit
!        %repeat
!        Disaster ("DRC fails - output streams are all used") %if stream = 0
!        select output (old)
!        old = instream
!        %for stream = 15, -1, 0 %cycle
!            select input (stream)
!            %if infilename = "NL:" %then insperrs = stream %and %exit
!        %repeat
!        Disaster ("DRC fails - input streams are all used") %if stream = 0
!        select input (old)
insperrs=2; outsperrs=2; trans = 1
    %end


    %routine initialise
        %integer xx,yy

        find streams
        %for xx=0,1,xmax %cycle
            %for yy=0,1,ymax %cycle
                errors(xx,yy) <- 0
                nodes(xx,yy) = 0
            %repeat
        %repeat
        %for xx=0,1,maxerrs %cycle
            errcount(xx)=0
        %repeat
        %for xx=1,1,LARGE %cycle
            C(xx) = 0
        %repeat
        nodenum = 0
        POLYCHECK = DRC CONTROL & width and spacing
        DIFF2CHECK = (DRC CONTROL >> 2) & width and spacing
        DIFF3CHECK = DIFF2CHECK & spacing
        METALCHECK = (DRC CONTROL >> 4) & width and spacing
        CONTACTCHECK = (DRC CONTROL >> 6) & width and spacing
        CTCHECK = (DRC CONTROL >> 9) & spacing
        TOCHECK = (DRC CONTROL >> 11) & width
        BCHECK = (DRC CONTROL >> 14) & spacing
        CONVALIDCHECK = (DRC CONTROL >> 8) & 1
        IMPLANTOVERLAPCHECK = (DRC CONTROL >> 10) & 1
        IMPLANTSPACINGCHECK = (DRC CONTROL >> 11) & 1
        POLYDIFFTRANCHECK = (DRC CONTROL >> 13) & 1
        BURIEDCHECK = (DRC CONTROL >> 15) & 1
        MPCHECK = 0 {(DRC CONTROL >> 16) & 1   { until futher notice!
        SPURTRANCHECK = (DRC CONTROL >> 17) & 1
    %end


    %routine get new row (%integer xx,yy)
        bt1 = data(xx-3,yy)
        bt2 = data(xx-2,yy)
        bt3 = data(xx-1,yy)
        bt4 = data(xx,yy)
    %end


    %integer%fn get row (%integer layer)
        %result=(((((((bt1 >> layer) & 1) << 1) ! ((bt2 >> layer) & 1)) << 1) %c
                ! ((bt3 >> layer) & 1)) << 1) ! ((bt4 >> layer) & 1)
    %end


    %routine keep old row
        old bt1 = bt1;  old bt2 = bt2
        old bt3 = bt3;  old bt4 = bt4
    %end


    %routine connect first row
        BDP = 0;  BM = 0;  BBC = 0
        bottom == nil

        LDP = 0;  CDP = bt1 & PandD
        LM  = 0;  CM  = bt1 & M
        LBC = 0;  CBC = bt1 & BandC
        left == nil
        current == nodes (0,0)
        implanted = (bt1 >> IMPLANT) & 1
        follow connectivity

        LDP = CDP;  CDP = bt2 & PandD
        LM  = CM;   CM  = bt2 & M
        LBC = CBC;  CBC = bt2 & BandC
        left == current
        current == nodes (1,0)
        implanted = (bt2 >> IMPLANT) & 1
        follow connectivity

        LDP = CDP;  CDP = bt3 & PandD
        LM  = CM;   CM  = bt3 & M
        LBC = CBC;  CBC = bt3 & BandC
        left == current
        current == nodes (2,0)
        implanted = (bt3 >> IMPLANT) & 1
        follow connectivity

        LDP = CDP;  CDP = bt4 & PandD
        LM  = CM;   CM  = bt4 & M
        LBC = CBC;  CBC = bt4 & BandC
        left == current
        current == nodes (3,0)
        implanted = (bt4 >> IMPLANT) & 1
        follow connectivity
    %end


    %routine connect row (%integer xx, yy)
        %if yy = 0 %start
            BDP = 0;  BM = 0;  BBC = 0
            bottom == nil
        %finish %else %start
            BDP = CDP;  BM = CM;  BBC = CBC
            bottom == current
        %finish
        LDP = bt3 & PandD;  CDP = bt4 & PandD
        LM  = bt3 & M;      CM  = bt4 & M
        LBC = bt3 & BandC;  CBC = bt4 & BandC
        left == nodes (xx-1, yy)
        current == nodes (xx, yy)
        implanted = (bt4 >> IMPLANT) & 1
        follow connectivity
    %end


    %routine connect first col (%integer xx, yy)
        LDP = 0;  BDP = old bt1 & PandD;  CDP = bt1 & PandD
        LM  = 0;  BM  = old bt1 & M;      CM  = bt1 & M
        LBC = 0;  BBC = old bt1 & BandC;  CBC = bt1 & BandC
        left == nil
        current == nodes (xx-3, yy)
        bottom == nodes (xx-3, yy-1)
        implanted = (bt1 >> IMPLANT) & 1
        follow connectivity

        LDP = CDP;  BDP = old bt2 & PandD;  CDP = bt2 & PandD
        LM  = CM;   BM  = old bt2 & M;      CM  = bt2 & M
        LBC = CBC;  BBC = old bt2 & BandC;  CBC = bt2 & BandC
        left == current
        current == nodes (xx-2, yy)
        bottom == nodes (xx-2, yy-1)
        implanted = (bt2 >> IMPLANT) & 1
        follow connectivity

        LDP = CDP;  BDP = old bt3 & PandD;  CDP = bt3 & PandD
        LM  = CM;   BM  = old bt3 & M;      CM  = bt3 & M
        LBC = CBC;  BBC = old bt3 & BandC;  CBC = bt3 & BandC
        left == current
        current == nodes (xx-1, yy)
        bottom == nodes (xx-1, yy-1)
        implanted = (bt3 >> IMPLANT) & 1
        follow connectivity

        LDP = CDP;  BDP = old bt4 & PandD;  CDP = bt4 & PandD
        LM  = CM;   BM  = old bt4 & M;      CM  = bt4 & M
        LBC = CBC;  BBC = old bt4 & BandC;  CBC = bt4 & BandC
        left == current
        current == nodes (xx, yy)
        bottom == nodes (xx, yy-1)
        implanted = (bt4 >> IMPLANT) & 1
        follow connectivity
    %end


    %routine connect
        LDP = bt3 & PandD;  BDP = CDP;  CDP = bt4 & PandD
        LM  = bt3 & M;      BM  = CM;   CM  = bt4 & M
        LBC = bt3 & BandC;  BBC = CBC;  CBC = bt4 & BandC
        left == nodes (x-1, y)
        bottom == current
        current == nodes (x, y)
        implanted = (bt4 >> IMPLANT) & 1
        follow connectivity
    %end


    %routine initialise windows (%integer xx)
        get new row (xx,0)
        row4P = get row (POLY);      row4D = get row (DIFF)
        row4M = get row (METAL);     row4C = get row (CONTACT)
        row4B = get row (BURIED);    row4I = get row (IMPLANT)
        %if xx=3 %then connect first row %else connect row (xx,0)

        keep old row
        get new row (xx,1)
        row3P = get row (POLY);     row3D = get row (DIFF)
        row3M = get row (METAL);    row3C = get row (CONTACT)
        row3B = get row (BURIED);   row3I = get row (IMPLANT)
        %if xx=3 %then connect first col (xx,1) %else connect row (xx,1)

        keep old row
        get new row (xx,2)
        row2P = get row (POLY);     row2D = get row (DIFF)
        row2M = get row (METAL);    row2C = get row (CONTACT)
        row2B = get row (BURIED);   row2I = get row (IMPLANT)
        %if xx=3 %then connect first col (xx,2) %else connect row (xx,2)

        keep old row
        get new row (xx,3)
        row1P = get row (POLY);     row1D = get row (DIFF)
        row1M = get row (METAL);    row1C = get row (CONTACT)
        row1B = get row (BURIED);   row1I = get row (IMPLANT)
        %if xx=3 %then connect first col (xx,3) %else connect row (xx,3)
    %end


    %routine move window
        row4P = row3P;              row4D = row3D
        row3P = row2P;              row3D = row2D
        row2P = row1P;              row2D = row1D
        row1P = get row (POLY);     row1D = get row (DIFF)

        row4M = row3M;              row4C = row3C
        row3M = row2M;              row3C = row2C
        row2M = row1M;              row2C = row1C
        row1M = get row (METAL);    row1C = get row (CONTACT)

        row4B = row3B;              row4I = row3I
        row3B = row2B;              row3I = row2I
        row2B = row1B;              row2I = row1I
        row1B = get row (BURIED);   row1I = get row (IMPLANT)
    %end


    %routine error (%integer err,xx,yy)
        errors(xx,yy) <- errors(xx,yy) ! (1 << err)
        data(xx,yy)=data(xx,yy) ! NV
        errcount(err)=errcount(err)+1
    %end


    %routine errors in centre (%integer mask,err,xx,yy)
        %if errors(xx-2,yy-2) & mask = 0 %then error(err,xx-2,yy-2)
        %if errors(xx-1,yy-2) & mask = 0 %then error(err,xx-1,yy-2)
        %if errors(xx-2,yy-1) & mask = 0 %then error(err,xx-2,yy-1)
        %if errors(xx-1,yy-1) & mask = 0 %then error(err,xx-1,yy-1)
    %end


    %routine get rid of sperrs
        %integer out,in, ex, ey
        %short comp, N, I, elayer, boxsize
        %string(127) inf

        out=outstream
        select output (outsperrs)
        printstring ("0"); newline; !to finish off file output
        close output
        select output (out)
        in=instream
        open input (insperrs,sperrfile)
        select input (insperrs)
        %cycle
            read (comp)
            %exit %if comp=0; !end of file
            read (N); read (ex); read (ey)
            read (elayer); read (boxsize)
            I = C(N)
            %cycle
                %exit %if I = comp %or I = 0
                I = C(I)
            %repeat %until I=N
            %if I=N %or I=0 %start; !real error, numbers not merged
                %if boxsize=3 %start; !3*3 spacing error
                    %if (1 << elayer) & errors(ex,ey) = 0 %then %c
                        error (elayer, ex, ey)
                %finish %else %start; ! 4*4 spacing error
                    %if (1 << elayer) & (errors(ex-1,ey-1) %c
                       ! errors(ex-1,ey-2) ! errors(ex-2,ey-2) %c
                                           ! errors(ex-2,ey-1)) = 0 %start
                        error (elayer, ex-1, ey-1)
                        error (elayer, ex-1, ey-2)
                        error (elayer, ex-2, ey-2)
                        error (elayer, ex-2, ey-1)
                    %finish
                %finish
            %finish
        %repeat
!        inf = infilename
        close input
!        delete (inf)
        select input (in)
    %end



    %routine process errors
      %integer i,j,k,x,y,xx,yy,ylim,sum,mask
        select output (0)
        sum=0
        %for I=0,1,MAXERRS %cycle
            sum = sum + errcount(I)
        %repeat
        %if sum=0 %then printstring(OK.snl) %and %return
        %for x=0,1,xmax %cycle    ;! find lower left
          %for y=0,1,ymax %cycle
            %if errors(x,y)#0 %start; !have an error
              %for I = 0,1,MAXERRS %cycle
                mask = 1 << I
                %if errors(x,y) & mask # 0 %start
                  ylim=ymax
                  %for yy=y,1,ymax %cycle    ;! find top left
                    %if errors(x,yy)&mask=0 %start
                      ylim=yy-1
                      %exit
                    %finish
                  %repeat
                  %for xx=x+1,1,xmax %cycle
                    %if errors(xx,y)&mask=0 %start
                      xx=xx-1
                      %exit
                    %finish
                    %for yy=y+1,1,ylim %cycle
                      %if errors(xx,yy)&mask=0 %start
                        %if yy-y>=xx-x %start
                          ylim=yy-1
                          %exit
                        %finish %else %start
                          xx=xx-1
                          ->boxout
                        %finish
                      %finish
                    %repeat
                  %repeat
boxout:
                  spaces(2)
                  printstring(message(I))
                  %if y=ylim %and x=xx %start;  !single lambda box
                    printstring("at")
                    write(x+xorigin,3); write(y+yorigin,3)
                  %finish %else %start
                    print string("llx=") ; write(x+xorigin,0); spaces(2)
                    print string(" lly=") ; write(y+yorigin,0); spaces(2)
                    print string(" urx=") ; write(xx+xorigin+1,0); spaces(2)
                    print string(" ury=") ; write(ylim+yorigin+1,0)
                  %finish
                  newline
                  %for j=x,1,xx %cycle
                    %for k=y,1,ylim %cycle
                      errors(j,k) <- errors(j,k)&(\mask)
                      sum=sum-1
                    %repeat
                  %repeat
                  %return %if sum=0
                  %exit %if errors(x,y) = 0
                %finish
              %repeat
            %finish
          %repeat
        %repeat
    %end


    %routine check sperrs (%short N)
        %short I
        %integer out

        %if comp = 0 %start;  !1st 1 in box perimeter
            comp = N
        %finish %else %start
            %if N # last %and N # comp %start; !not same as comparator or 
                I = C(N);                      !last 1 in perimeter
                %cycle
                    %exit %if I = 0
                    %return %if I = comp; !numbers are merged
                    I = C(I)
                %repeat %until I = N
                out = outstream
                select output (outsperrs)
                write (comp,0); spaces(2)
                write (N,0);    spaces(2)
                write (ex,0);   spaces(2)
                write (ey,0);   spaces(2)
                write (elayer,0);  spaces(2)
                write (boxsize,0); newline
                select output (out)
            %finish
        %finish
        last = N
    %end


    %routine check ws2 (%byte r1,r2,r3,%integer layer,check,xx,yy)
        %byte c

        c = (r2 >> 1) & 1; !0 for spacing and 1 for width check
        %return %if check & (c+1) = not required
        %if (tbox((r1 << 3) ! r2 ) >> r3) & 1 = 0 %start
            %if c = 0 %start; !spacing error - could be spurious
                comp=0; last=0; boxsize=3
                ex=xx;  ey=yy;  elayer=layer
                %if layer=POLY %start
                    %if r1 & IOO # 0 %then %c
                        check sperrs (nodes(xx-1,yy+1)_Player)
                    %if r1 & OIO # 0 %then %c
                        check sperrs (nodes(xx,yy+1)_Player)
                    %if r1 & OOI # 0 %then %c
                        check sperrs (nodes(xx+1,yy+1)_Player)
                    %if r2 & OOI # 0 %then %c
                        check sperrs (nodes(xx+1,yy)_Player)
                    %if r3 & OOI # 0 %then %c
                        check sperrs (nodes(xx+1,yy-1)_Player)
                    %if r3 & OIO # 0 %then %c
                        check sperrs (nodes(xx,yy-1)_Player)
                    %if r3 & IOO # 0 %then %c
                        check sperrs (nodes(xx-1,yy-1)_Player)
                    %if r2 & IOO # 0 %then %c
                        check sperrs (nodes(xx-1,yy)_Player)
                    %return
                %finish%else%if layer = DIFF %start
                    %if r1 & IOO # 0 %then %c
                        check sperrs (nodes(xx-1,yy+1)_Dlayer)
                    %if r1 & OIO # 0 %then %c
                        check sperrs (nodes(xx,yy+1)_Dlayer)
                    %if r1 & OOI # 0 %then %c
                        check sperrs (nodes(xx+1,yy+1)_Dlayer)
                    %if r2 & OOI # 0 %then %c
                        check sperrs (nodes(xx+1,yy)_Dlayer)
                    %if r3 & OOI # 0 %then %c
                        check sperrs (nodes(xx+1,yy-1)_Dlayer)
                    %if r3 & OIO # 0 %then %c
                        check sperrs (nodes(xx,yy-1)_Dlayer)
                    %if r3 & IOO # 0 %then %c
                        check sperrs (nodes(xx-1,yy-1)_Dlayer)
                    %if r2 & IOO # 0 %then %c
                        check sperrs (nodes(xx-1,yy)_Dlayer)
                    %return
                %finish%else%if layer=METAL %start
                    %if r1 & IOO # 0 %then %c
                        check sperrs (nodes(xx-1,yy+1)_Mlayer)
                    %if r1 & OIO # 0 %then %c
                        check sperrs (nodes(xx,yy+1)_Mlayer)
                    %if r1 & OOI # 0 %then %c
                        check sperrs (nodes(xx+1,yy+1)_Mlayer)
                    %if r2 & OOI # 0 %then %c
                        check sperrs (nodes(xx+1,yy)_Mlayer)
                    %if r3 & OOI # 0 %then %c
                        check sperrs (nodes(xx+1,yy-1)_Mlayer)
                    %if r3 & OIO # 0 %then %c
                        check sperrs (nodes(xx,yy-1)_Mlayer)
                    %if r3 & IOO # 0 %then %c
                        check sperrs (nodes(xx-1,yy-1)_Mlayer)
                    %if r2 & IOO # 0 %then %c
                        check sperrs (nodes(xx-1,yy)_Mlayer)
                    %return
                %finish
            %finish
            %if (1 << layer) & main layer # 0 %start
                error(layer + (widconst * c),xx,yy)
            %finish %else %start
                error(layer,xx,yy)
            %finish
        %finish
    %end


    %routine check ws3 (%byte r1,r2,r3,r4, %integer layer,check)
        %byte c, err

        c = (r2 >> 1) & 1; !0 for spacing or 1 for width check
        %return %if c # (r2 >> 2) & 1 %or r2 & OIIO # r3 & OIIO
        %return %if check & (c+1) = not required
        %if (fbox((((r1 << 4) ! r2) << 4) ! r3) >> r4) & 1 = 0 %start
            err=layer + (widconst * c)
            %return %if ((errors(x-2,y-2) ! errors(x-2,y-1) ! %c
                errors(x-1,y-1) ! errors(x-1,y-2)) >> err) & 1 # 0
            %if c = 0 %start; !spacing error - could be spurious
                comp=0; last=0; boxsize=4
                ex=x;   ey=y;   elayer=layer
                %if layer=DIFF %start; !no 4*4 check for POLY
                    %if r1 & IOOO # 0 %then %c
                        check sperrs (nodes(x-3,y)_Dlayer)
                    %if r1 & OIOO # 0 %then %c
                        check sperrs (nodes(x-2,y)_Dlayer)
                    %if r1 & OOIO # 0 %then %c
                        check sperrs (nodes(x-1,y)_Dlayer)
                    %if r1 & OOOI # 0 %then %c
                        check sperrs (nodes(x,y)_Dlayer)
                    %if r2 & OOOI # 0 %then %c
                        check sperrs (nodes(x,y-1)_Dlayer)
                    %if r3 & OOOI # 0 %then %c
                        check sperrs (nodes(x,y-2)_Dlayer)
                    %if r4 & OOOI # 0 %then %c
                        check sperrs (nodes(x,y-3)_Dlayer)
                    %if r4 & OOIO # 0 %then %c
                        check sperrs (nodes(x-1,y-3)_Dlayer)
                    %if r4 & OIOO # 0 %then %c
                        check sperrs (nodes(x-2,y-3)_Dlayer)
                    %if r4 & IOOO # 0 %then %c
                        check sperrs (nodes(x-3,y-3)_Dlayer)
                    %if r3 & IOOO # 0 %then %c
                        check sperrs (nodes(x-3,y-2)_Dlayer)
                    %if r2 & IOOO # 0 %then %c
                        check sperrs (nodes(x-3,y-1)_Dlayer)
                    %return
                %finish%else%if layer=METAL %start
                    %if r1 & IOOO # 0 %then %c
                        check sperrs (nodes(x-3,y)_Mlayer)
                    %if r1 & OIOO # 0 %then %c
                        check sperrs (nodes(x-2,y)_Mlayer)
                    %if r1 & OOIO # 0 %then %c
                        check sperrs (nodes(x-1,y)_Mlayer)
                    %if r1 & OOOI # 0 %then %c
                        check sperrs (nodes(x,y)_Mlayer)
                    %if r2 & OOOI # 0 %then %c
                        check sperrs (nodes(x,y-1)_Mlayer)
                    %if r3 & OOOI # 0 %then %c
                        check sperrs (nodes(x,y-2)_Mlayer)
                    %if r4 & OOOI # 0 %then %c
                        check sperrs (nodes(x,y-3)_Mlayer)
                    %if r4 & OOIO # 0 %then %c
                        check sperrs (nodes(x-1,y-3)_Mlayer)
                    %if r4 & OIOO # 0 %then %c
                        check sperrs (nodes(x-2,y-3)_Mlayer)
                    %if r4 & IOOO # 0 %then %c
                        check sperrs (nodes(x-3,y-3)_Mlayer)
                    %if r3 & IOOO # 0 %then %c
                        check sperrs (nodes(x-3,y-2)_Mlayer)
                    %if r2 & IOOO # 0 %then %c
                        check sperrs (nodes(x-3,y-1)_Mlayer)
                    %return
                %finish
            %finish
            error(err,x-2,y-2)
            error(err,x-2,y-1)
            error(err,x-1,y-1)
            error(err,x-1,y-2)
        %finish
    %end


    %routine check contacts
        %integer r1,r2,r3,r4

        %routine noerr (%integer x1,y1,x2,y2)
            %short%name e1, e2
              e1 == errors(x1,y1)
              e2 == errors(x2,y2)
              %if e1 & DSmask # 0 %then %c
                         errcount(DIFF) = errcount(DIFF) - 1
              %if e2 & DSmask # 0 %then %c
                         errcount(DIFF) = errcount(DIFF) - 1
              %if e1 & impmask # 0 %then %c
                         errcount(IMPLANT) = errcount(IMPLANT) - 1
              %if e2 & impmask # 0 %then %c
                         errcount(IMPLANT) = errcount(IMPLANT) - 1
              data(x1,y1) = data(x1,y1) & noNV
              data(x2,y2) = data(x2,y2) & noNV
              e1 <- e1 & noDTIerr
              e2 <- e2 & noDTIerr
        %end

        %if %not (row1M=MMMM %and row2M=MMMM %and row3M=MMMM %c
            %and row4M=MMMM) %then errors in centre (conmask,CONERR,x,y)

        r1=((((((data(x-3,y) & DP) << 2) ! (data(x-2,y) & DP)) %c
             << 2) ! (data(x-1,y) & DP)) << 2) ! (data(x,y) & DP)
        r2=((((((data(x-3,y-1) & DP) << 2) ! (data(x-2,y-1) & DP)) %c
             << 2) ! (data(x-1,y-1) & DP)) << 2) ! (data(x,y-1) & DP)
        r3=((((((data(x-3,y-2) & DP) << 2) ! (data(x-2,y-2) & DP)) %c
             << 2) ! (data(x-1,y-2) & DP)) << 2) ! (data(x,y-2) & DP)
        r4=((((((data(x-3,y-3) & DP) << 2) ! (data(x-2,y-3) & DP)) %c
             << 2) ! (data(x-1,y-3) & DP)) << 2) ! (data(x,y-3) & DP)

        %if r1=DDDD %start
            %if r2=DDDD %start
                %if r3=DDDD %start
                    %return %if (r4=DDDD)
                    %if (r4=TTTT) %then noerr(x-3,y-3,x,y-3) %and %return
                %finish%else%if r3=TTTT %start
                    %return %if (r4=PPPP) %or (r4=TTPP) %c
                            %or (r4=PPTT) %or (r4=PTTP) %c
                            %or (r4=PPPT) %or (r4=TPPP)
                %finish
            %finish%else%if r2=TTTT %start
                %return %if (r3=PPPP) %and (r4=PPPP)
                %return %if (r3=TTPP) %and (r4=TTPP)
                %return %if (r3=PPTT) %and (r4=PPTT)
                %return %if (r3=PTTP) %and (r4=PTTP)
                %return %if (r3=PPPT) %and (r4=PPPT)
                %return %if (r3=TPPP) %and (r4=TPPP)
            %finish
        %finish%else%if r1=PPPP %start
            %if r2=PPPP %start
                %return %if (r3=PPPP) %and (r4=PPPP)
                %return %if (r3=TTTT) %and (r4=DDDD)
            %finish
            %return %if (r2=TTTT) %and (r3=DDDD) %and (r4=DDDD)
        %finish%else%if r1=DDTP %start
            %if r2=DDTP %start
                %return %if (r3=DDTP) %and ((r4=DDTP) %or (r4=DDTT))
                %return %if (r3=DDTT) %and (r4=DDTT)
            %finish
            %return %if (r2=DDTT) %and (r3=DDTT) %and (r4=DDTP)
        %finish%else%if r1=PTDD %start
            %if r2=PTDD %start
                %return %if (r3=PTDD) %and ((r4=PTDD) %or (r4=TTDD))
                %return %if (r3=TTDD) %and (r4=TTDD)
            %finish
            %return %if (r2=TTDD) %and (r3=TTDD) %and (r4=PTDD)
        %finish%else%if r1=DTPP %start
            %if r2=DTPP %start
                %return %if (r3=DTPP) %and ((r4=DTPP) %or (r4=DTTT))
                %return %if (r3=DTTT) %and (r4=DTTT)
            %finish
            %return %if (r2=DTTT) %and (r3=DTTT) %and (r4=DTPP)
        %finish%else%if r1=PPTD %start
            %if r2=PPTD %start
                %return %if (r3=PPTD) %and ((r4=PPTD) %or (r4=TTTD))
                %return %if (r3=TTTD) %and (r4=TTTD)
            %finish
            %return %if (r2=TTTD) %and (r3=TTTD) %and (r4=PPTD)
        %finish%else%if r1=PPTT %start
            %return %if (r2=TTTT) %and (r3=DDDD) %and (r4=DDDD)
            %return %if (r2=PPTT) %and (r3=TTTT) %and (r4=DDDD)
        %finish%else%if r1=TTPP %start
            %return %if (r2=TTTT) %and (r3=DDDD) %and (r4=DDDD)
            %return %if (r2=TTPP) %and (r3=TTTT) %and (r4=DDDD)
        %finish%else%if r1=PTTP %start
            %return %if (r2=TTTT) %and (r3=DDDD) %and (r4=DDDD)
            %return %if (r2=PTTP) %and (r3=TTTT) %and (r4=DDDD)
        %finish
        %if (r1=DDDT) %and (r2=DDDT) %and (r3=DDDT) %and (r4=DDDT) %c
                      %then noerr(x,y,x,y-3) %and %return
        %if (r1=TDDD) %and (r2=TDDD) %and (r3=TDDD) %and (r4=TDDD) %c
                      %then noerr(x-3,y,x-3,y-3) %and %return
        %if (r1=TTTT) %and (r2=DDDD) %and (r3=DDDD) %and (r4=DDDD) %c
                      %then noerr(x-3,y,x,y) %and %return
        %if (r1=TTDD) %start
            %return %if (r2=TTDD) %and (r3=PTDD) %and (r4=PTDD)
            %return %if (r2=PTDD) %and (r3=PTDD) %and (r4=PTDD)
        %finish%else%if (r1=DDTT) %start
           %return %if (r2=DDTT) %and (r3=DDTP) %and (r4=DDTP)
           %return %if (r2=DDTP) %and (r3=DDTP) %and (r4=DDTP)
        %finish%else%if (r1=TTTD) %start
            %return %if (r2=TTTD) %and (r3=PPTD) %and (r4=PPTD)
            %return %if (r2=PPTD) %and (r3=PPTD) %and (r4=PPTD)
        %finish%else%if (r1=DTTT) %start
            %return %if (r2=DTTT) %and (r3=DTPP) %and (r4=DTPP)
            %return %if (r2=DTPP) %and (r3=DTPP) %and (r4=DTPP)
        %finish%else%if (r1=PPPT) %start
            %return %if (r2=PPPT) %and (r3=TTTT) %and (r4=DDDD)
            %return %if (r2=TTTT) %and (r3=DDDD) %and (r4=DDDD)
        %finish%else%if (r1=TPPP) %start
            %return %if (r2=TPPP) %and (r3=TTTT) %and (r4=DDDD)
            %return %if (r2=TTTT) %and (r3=DDDD) %and (r4=DDDD)
        %finish
        %return %if (row1B & row2B & row3B & row4B)=BBBB;  !CMOS check

{}printstring("<<")
        errors in centre (conmask,conerr,x,y)
{}printstring(">>")
    %end;  !of contact cut checks


    %routine check implants
        %constbyte IIII=15
        %byte NBC2, NBC3, T1, T2, T3, T4, IT1, IT2, IT3, IT4

          !! know that I is already in window !!

        NBC2 <- \ (row2B ! row2C)
        NBC3 <- \ (row3B ! row3C)

        T1 = (row2P & row2D & NBC2) & OIOO
        T2 = (row2P & row2D & NBC2) & OOIO
        T3 = (row3P & row3D & NBC3) & OIOO
        T4 = (row3P & row3D & NBC3) & OOIO

        %if T1 # 0 %or T2 # 0 %or T3 # 0 %or T4 # 0 %start; !T in centre
            IT1 = T1 & row2I
            IT2 = T2 & row2I
            IT3 = T3 & row3I
            IT4 = T4 & row3I
            %if IT1 # 0 %or IT2 # 0 %or IT3 # 0 %or IT4 # 0 %start; !centre IT
                %return %if IMPLANTOVERLAPCHECK = not required %c
                        %or row1I & row2I & row3I & row4I = IIII
            %finish %else %start; !I in window, T and not I in centre
                %return %if IMPLANTSPACINGCHECK = not required
            %finish
            errors in centre (impmask, IMPLANT, x, y)
        %finish
    %end


    %routine check MP edges (%byte r1P,r2P,r3P,r1M,r2M,r3M, %integer xx,yy)
        %return %if (r2P ! r2M) & OIO = 0
        %if r2M & OIO # 0 %start;  !M in centre
            %if r2P & OIO # 0 %start;  !MP in centre
                %if (r1M ! r1P) & OIO = 0 %or (r2M ! r2P) & IOO = 0 %c
                  %or (r2M ! r2P) & OOI = 0 %or (r3M ! r3P) & OIO = 0 %c
                  %then error (MP,xx,yy)
            %finish %else %start;  !M and not P in centre
                %if (\r1M & r1P) & OIO # 0 %or (\r2M & r2P) # 0 %c
                  %or (\r3M & r3P) & OIO # 0 %then error (MP,xx,yy)
            %finish
        %finish %else %start; !P and not M in centre
            %if (\r1P & r1M) & OIO # 0 %or (\r2P & r2M # 0) %c
              %or (\r3P & r3M) & OIO # 0 %then error (MP,xx,yy)
        %finish
    %end


    %routine check buried contact
        %return %if ((row2P & row2D) & (row3P & row3D)) & OIIO # OIIO; !no PD
        %return %if (data(x-2,y-1) ! data(x-1,y-1) %c
                   ! data(x-2,y-2) ! data(x-1,y-2)) & Tbit # 0
        %return %if (row2B  & row3B ) & OIIO # OIIO; !not all B in centre
        %if (row1B & row2B & row3B & row4B) # BBBB %c
            %then errors in centre (bmask,BURIED,x,y)
    %end


    %routine check tran(%byte r1P,r2P,r3P,r1D,r2D,r3D,%integer xx,yy)
        %byte n,s,e,w,nw1,nw2,nw3

        %routine check (%byte r1,r2,r3)
            %if r1 & OIO # 0 %or r2 # 0 %or r3 & OIO # 0 %c
                %then error(tranerr,xx,yy) %and %return
            %if r1 & OOI # 0 %start
                %if n=0 %and e=0 %then error(tranerr,xx,yy) %c
                                 %and %return
            %finish
            %if r1 & IOO # 0 %start
                %if n=0 %and w=0 %then error(tranerr,xx,yy) %c
                                 %and %return
            %finish
            %if r3 & IOO # 0 %start
                %if w=0 %and s=0 %then error(tranerr,xx,yy) %c
                                 %and %return
            %finish
            %if r3 & OOI # 0 %start
                %if e=0 %and s=0 %then error(tranerr,xx,yy) %c
                                 %and %return
            %finish
        %end

        nw2=(r2P ! r2D)
        %return %if nw2 & OIO = 0
        nw1=(r1P ! r1D)
        nw3=(r3P ! r3D)
        n=nw1 & OIO;    s=nw3 & OIO
        e=nw2 & OOI;    w=nw2 & IOO
        %if r2P & OIO # 0 %start; !P in centre
            %if r2D & OIO # 0 %start; !T in centre
                %if n=0 %or s=0 %or e=0 %or w=0 %c
                    %then error(tranerr,xx,yy)
            %finish %else %start;  !no D in centre
                check(\r1P & r1D,\r2P & r2D,\r3P & r3D)
            %finish
        %finish %else %start
            check(\r1D & r1P,\r2D & r2P,\r3D & r3P)
        %finish
    %end


    %routine check spurtrans (%byte DP, T, xx, yy)
        %return %if DP = 0; !no D and P present
        %return %if T#0 ;  !T set
        error(SPURTRAN, xx, yy)
    %end


    %routine check 3 by 3 window (%integer xx, yy)
        %byte Ppresent, Dpresent, Mpresent, Cpresent, Bpresent

        Ppresent = P1 ! P2 ! P3;   Dpresent = D1 ! D2 ! D3
        Mpresent = M1 ! M2 ! M3;   Cpresent = C1 ! C2 ! C3
        Bpresent = B1 ! B2 ! B3

        %if POLYCHECK # not required %and Ppresent # no %then %c
            check ws2 (P1, P2, P3, POLY, POLYCHECK, xx, yy)
        %if DIFF2CHECK # not required %and Dpresent # no %then %c
            check ws2 (D1, D2, D3, DIFF, DIFF2CHECK, xx, yy)
        %if METALCHECK # not required %and Mpresent # no %then %c
            check ws2 (M1, M2, M3, METAL, METALCHECK, xx, yy)
        %if CONTACTCHECK # not required %and Cpresent # no %then %c
            check ws2 (C1, C2, C3, CONTACT, CONTACTCHECK, xx, yy)
        %if BCHECK # not required %and Bpresent # no %then %c
            check ws2 (B1, B2, B3, BURIED, BCHECK, x, yy)
        %if CTCHECK # not required %and Cpresent # no %and %c
            Ppresent # no %then check ws2 (P1 ! C1, P2 ! C2, P3 ! C3,
                                             CONTRAN, CTCHECK, xx, yy)
        %if TOCHECK # not required %and Ppresent # no %and %c
            Dpresent # no %and B2 & OIO = 0 %start
            %if errors (xx,yy) & PWmask = 0 %then %c
                check ws2 (\D1 & P1, \D2 & P2, \D3 & P3, TRANOVERLAP,
                                                      TOCHECK, xx, yy)
            %if errors (xx,yy) & DWmask = 0 %then %c
                check ws2 (\P1 & D1, \P2 & D2, \P3 & D3, TRANOVERLAP,
                                                      TOCHECK, xx, yy)
        %finish
        %if POLYDIFFTRANCHECK = required %and Ppresent # no %and %c
            Dpresent # no %then check tran (P1, P2, P3, D1, D2, D3, xx, yy)
        %if MPCHECK = required %and Cpresent = no %and Ppresent # no %c
            %and Mpresent # no %then check MP edges (P1, P2, P3,
                                                     M1, M2, M3, xx, yy)
        %if SPURTRANCHECK = required %and Dpresent # no %and %c
            Ppresent # no %and (C2 ! B2) & OIO = 0 %then %c
            check spurtrans ((P2 & D2) & OIO, data(xx,yy) & Tbit, xx, yy)
    %end


    %routine check 4 by 4 window
        %byte Dpresent, Mpresent, Ipresent, Bpresent

        Dpresent = row1D ! row2D ! row3D ! row4D
        Mpresent = row1M ! row2M ! row3M ! row4M
        Bpresent = row1B ! row2B ! row3B ! row4B
        Ipresent = row1I ! row2I ! row3I ! row4I

        %if DIFF3CHECK # not required %and Dpresent # no %then %c
            check ws3 (row1D, row2D, row3D, row4D, DIFF, DIFF3CHECK)
        %if METALCHECK # not required %and Mpresent # no %then %c
            check ws3 (row1M, row2M, row3M, row4M, METAL, METALCHECK)
        %if (IMPLANTOVERLAPCHECK = required %or %c
             IMPLANTSPACINGCHECK = required) %and Ipresent # no %then %c
             check implants
        %if BURIEDCHECK = required %and Bpresent # no %then %c
            check buried contact
        %if CONVALIDCHECK = required %and %c
            ((row2C & row3C) >> 1) & CC = CC %then check contacts
    %end


    %routine do first column checks
        P1 = row1P >> 1;  D1 = row1D >> 1;  B1 = row1B >> 1
        P2 = row2P >> 1;  D2 = row2D >> 1;  B2 = row2B >> 1
        P3 = row3P >> 1;  D3 = row3D >> 1;  B3 = row3B >> 1

        M1 = row1M >> 1;  C1 = row1C >> 1
        M2 = row2M >> 1;  C2 = row2C >> 1
        M3 = row3M >> 1;  C3 = row3C >> 1

        check 3 by 3 window (1, y-1)
    %end


    %routine do first window checks
        P1 = row2P >> 1;  D1 = row2D >> 1;  B1 = row2B >> 1
        P2 = row3P >> 1;  D2 = row3D >> 1;  B2 = row3B >> 1
        P3 = row4P >> 1;  D3 = row4D >> 1;  B3 = row4B >> 1

        M1 = row2M >> 1;  C1 = row2C >> 1
        M2 = row3M >> 1;  C2 = row3C >> 1
        M3 = row4M >> 1;  C3 = row4C >> 1

        check 3 by 3 window (1,1)
    %end


    %routine do first row checks
        P1 = row2P & end;  D1 = row2D & end;  B1 = row2B & end
        P2 = row3P & end;  D2 = row3D & end;  B2 = row3B & end
        P3 = row4P & end;  D3 = row4D & end;  B3 = row4B & end

        M1 = row2M & end;  C1 = row2C & end
        M2 = row3M & end;  C2 = row3C & end
        M3 = row4M & end;  C3 = row4C & end

        check 3 by 3 window (x-1, 1)
    %end


    %routine do centre window checks
        P1 = row1P & end;  D1 = row1D & end;  B1 = row1B & end
        P2 = row2P & end;  D2 = row2D & end;  B2 = row2B & end
        P3 = row3P & end;  D3 = row3D & end;  B3 = row3B & end

        M1 = row1M & end;  C1 = row1C & end
        M2 = row2M & end;  C2 = row2C & end
        M3 = row3M & end;  C3 = row3C & end

        check 3 by 3 window (x-1, y-1)
        check 4 by 4 window
    %end


    %routine record transistor (%short T, D, P, direction)
        %integer out
        out=outstream
        select output (trans)
        write (T,0); spaces(2)
        write (D,0); spaces(2)
        write (P,0); spaces(2)
        write (implanted,0); spaces(2)
        write (direction,0); newline
        select output (out)
    %end


    %routine follow connectivity
        %routine %spec merge (%integer A, B)
        %short L, B

        %routine nodesearch (%integer LL, BB, %short%name Lp, Cp, Bp)
            %if LL=0 %and BB=0 %start; !assign new number
                nodenum = nodenum + 1
                disaster ("DRC fails - too many nodes in cell") %if nodenum > large
                Cp = nodenum
                Acount (nodenum) = 1
                Lcount (nodenum) = 1
                Bcount (nodenum) = 1
                %return
            %finish%else%if LL=0 %start; !BB # 0
                Cp = Bp
                Lcount (Cp) = Lcount (Cp) + 1
            %finish %else %start; !LL # 0
                Cp = Lp
                %if BB # 0 %start
                    %if Lp # Bp %then merge (Lp, Bp); !single layer
                %finish %else %start; !merge 
                    Bcount (Cp) = Bcount (Cp) + 1
                %finish
            %finish 
            Acount (Cp) = Acount (Cp) + 1
        %end

        %routine transearch;  !to be expanded
            %if (LDP # PandD %or LBC # 0) %c
                     %and (BDP # PandD %or BBC # 0) %start
                nodenum = nodenum + 1
                current_Tlayer = nodenum
                Acount (nodenum) = 1
                Lcount (nodenum) = 1
                Bcount (nodenum) = 1
                %return
            %finish%else%if (LDP # PandD %or LBC # 0) %start
                current_Tlayer = bottom_Tlayer
                Lcount (current_Tlayer) = Lcount (current_Tlayer) + 1
            %finish %else %start
                current_Tlayer = left_Tlayer
                %if (BDP = PandD) %and (BBC = 0) %start
                    %if (left_Tlayer # bottom_Tlayer) %then %c
                        merge (left_Tlayer,bottom_Tlayer)
                %finish %else %start
                    Bcount (current_Tlayer) = Bcount (current_Tlayer) + 1
                %finish
            %finish
            Acount (current_Tlayer) = Acount (current_Tlayer) + 1
        %end

        %routine merge (%integer A, B)
          %short join

            %integer %fn already connected (%short N1,N2)
                join = N1
                %cycle
                    %result = true %if C(join) = N2
                    %exit %if C(join) = N1
                    join = C(join)
                %repeat
                %result = false
            %end

            %return %if A=0 %or B=0
            %if C(A)=0 %and C(B)=0 %start
                C(A)=B;  C(B)=A
                %return
            %finish
            %if C(A)=0 %start
                C(A) = B
            %finish %else %start
                %if already connected (A,B)=true %then %return
                C(join) = B
            %finish
            %if C(B)=0 %start
                C(B) = A
            %finish %else %start
                %if already connected (B,A)#true %then C(join) = A
            %finish
        %end

        !! main part !!

%option "-noass"
        %if CM # 0 %then nodesearch (LM, BM, left_Mlayer, current_Mlayer,
                                                          bottom_Mlayer)
                                    !! metal in current pixel
        %return %if CDP = noDorP
        %if CDP = onlyD %start;  !no P in current pixel
            %if LBC = 0 %then L = \(LDP >> 1) & (LDP & 1) %c
                        %else L = (LDP & 1)
            %if BBC = 0 %then B = \(BDP >> 1) & (BDP & 1) %c
                        %else B = (BDP & 1)
            nodesearch (L, B, left_Dlayer, current_Dlayer,
                                             bottom_Dlayer)
!            %if ILAP CONTROL & CIRCUIT ANALYSIS # 0 %start
!                %if LDP = PandD %and LBC = 0 %then %c
!                    record transistor (left_Tlayer, current_Dlayer,
!                                                left_Player, horizontal)
!                %if BDP = PandD %and BBC = 0 %then %c
!                    record transistor (bottom_Tlayer, current_Dlayer,
!                                                bottom_Player, vertical)
!            %finish
        %finish %else %start;  !P present
            nodesearch (LDP >> 1, BDP >> 1, left_Player, current_Player,
                                                        bottom_Player)
            %if CDP = PandD %start
                %if CBC = 0 %start
                    transearch
!                    %if ILAP CONTROL & CIRCUIT ANALYSIS # 0 %start
!                        %if LDP = onlyD %then %c
!                          record transistor (current_Tlayer, left_Dlayer,
!                                             current_Player, horizontal)
!                        %if BDP = only D %then %c
!                          record transistor (current_Tlayer, bottom_Dlayer,
!                                                 current_Player, vertical)
!                    %finish
                %finish %else %start
                    current_Dlayer = current_Player
                    %if left_Player # bottom_Dlayer %then %c
                        merge (left_Player, bottom_Dlayer)
                    %if left_Dlayer # bottom_Player %then %c
                        merge (left_Dlayer, bottom_Player)
                %finish
            %finish
        %finish
        %return %if CBC = 0 %or CBC = onlyB %or LBC # 0 %or BBC # 0
        %if CDP = onlyD %then merge (current_Mlayer, current_Dlayer) %c
                        %else merge (current_Mlayer, current_Player)
    %end




   !!!!main program!!!!

    stream=outstream
    select output (0)

    initialise
    newline
    printstring("Checking symbol ".s);newline
    Disaster ("DRC fails - Symbol too small for checking") %if xmax<3 %or ymax<3

    open output (outsperrs, sperrfile)
!    open output (trans, tranfile) %if ILAP control & Circuit Analysis # 0

    x=3;   y=3
    initialise windows (x)
    do first window checks
    do first column checks
    do first row checks
    do centre window checks
    %for y=4,1,ymax %cycle
        keep old row
        get new row (x,y)
        move window
        connect first col (x,y)
        do first column checks
        do centre window checks
    %repeat
    %for x=4,1,xmax %cycle
        y=3
        initialise windows (x)
        do first row checks
        do centre window checks
        %for y=4,1,ymax %cycle
            get new row (x,y)
            move window
            connect
            do centre window checks
        %repeat
    %repeat
    get rid of sperrs
    process errors

    select output (trans)
    printstring("0"); newline
    close output

!    %if ILAP CONTROL & CIRCUIT ANALYSIS # 0 %then %c
!      analyse circuit (nodes, xmax, ymax, nodenum, C, Acount, Lcount, Bcount)

    select output (stream)

%end

%end%of%file
