! 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