{ Note the whole basic problem is that we use separate colour names for { the grid array and the framestore. always keep this in mind...} { slightly amended to not draw anything. should therefore always be followed} { by a call to refresh } ! The numbering in grid seems to be thus ! 1 = red/poly 2 = green/diff 4= blue/metal 8= diffusion ! 64 " " " mkd 128 " " " mkd I may thus use (at risk) 32 and 16 %external %routine readilap(%string(31) file, %record (point fm) start, %record (array fm) %array %name grid(-frames:xrlim+frames), %record (conf) %array %name con (1:200), %integer %name con ptr) %routinespec read line %routinespec readsym(%integername n) %routinespec fault(%string(63) s) %integerfnspec getname(%integername name) %integerfnspec checklit(%integer sym) %integerfnspec checksep %integerfnspec getsexpr(%string(*)%name s) %integerfnspec getexpr(%integername e) %routinespec startwort(%integer type,x,y,l) %routinespec xleg(%integer l) %routinespec yleg(%integer l) %routinespec endwort %routinespec subsw(%integer x,y,p) %routinespec subst(%record(point fm) pt,%integer path,other,imp,p) %routinespec box(%integer layer,xl,yb,xr,yt) %routinespec contact(%integer type,x,y) %constinteger namessize=100 %ownstring(31)%array names(1:namessize)= %c "symbol","endsymbol","etpx","etpy","etdx","etdy", "dtpx","dtpy","dtdx","dtdy","dtdbx","dtdby", "wirex","wirey","dx","dy","layer","width", "pm","dm","pdbn","pdbe","pdbs","pdbw", "pdbns","pdbew","pdcn","pdce","pdcs","pdcw", "box","vddwirex","vddwirey","gndwirex","gndwirey","poly", "diffusion","metal",""(*) %constinteger ilapprocs=35,etpx=3,dtpx=7,dtdbx=11,dtdby=12,wirex=13, %c dy=16,pm=19,poly=36,diffusion=37,metal=38,implant=39,bu=12 %constinteger xdir=1,ydir=2,gndwirey=35 %constbytearray xydir(etpx:gndwirey)=xdir,ydir,xdir,ydir, xdir,ydir,xdir,ydir,xdir,ydir,xdir,ydir,xdir,ydir, 0(15),xdir,ydir,xdir,ydir %constbytearray tranp(etpx:dtdby)=poly,poly,diffusion,diffusion, poly,poly,diffusion,diffusion,diffusion,diffusion %switch ilapname(1:ilapprocs) %owninteger namesend=39 {ilapproces+layer names} %constbytearray defaultwidth(poly:metal)=2,2,3 %constinteger tsize=255 %bytearray t(0:tsize) %constinteger legs=100 %integerarray legx,legy(1:legs) %constinteger true=1,false=0 %integer tp,name,x,y,l,w,curlay,curwid,wort,wortx,worty,worttype, %c faulty,legp,lege,xx,yy,i %string(255) s,lines,stri %record(point fm) zero = 0 %conststring(1) snl=" " %byte language %on %event 1,2,3,4,5,6,7,8,9 %start select output(2) clear line printstring(event_message);newline close output select output(0) print string ("** Event "); write(event_event,-1); print symbol (',') write (event_sub,1); spaces(2); printstring(event_message); newline faulty=true ->endfile %unless (event_event = 9 %and event_sub=3) %or event_event=3 %return %finish open input(2,file) select input(2) print symbol (13) toupper(file) %if file -> s.(".PAS") %then language = pascal %else language = imp printstring("Reading ".lap(language)." from ".file.", Planting at ") write(start_x,3);write(start_y,3) newline wort=false faulty=false open output(2,"ted.lis") select output(2) print string("Input from file: ".file." ") curlay=0 ; curwid=0 tp=0 ; t(tp)=nl {to trigger first read line} next:{read next line if necessary} %if t(tp)=nl %then read line %if getname(name)=false %then fault("unknown statement") %and ->next %if name<=ilapprocs %then ->ilapname(name) fault("unknown procedure") ->next ilapname(1):{symbol} %if checklit('(')=false %then ->error %if getsexpr(s)=false %then ->error %if lines -> s.(encstring(language)).symbol name %start;%finish %if symbol name -> symbol name .(encstring(language)).s %start;%finish %if checklit(')')=false %then ->error %if checksep=false %then ->error ->next ilapname(2):{endsymbol} %if checksep=false %then ->error endwort endfile:{from event trap} select input (2) close input select output(2) %if faulty=true %then printstring("File error") %else printstring("File OK") newline close output select output(0) %if faulty=true %then printstring("Data file corrupt") %else printstring("OK") newline %return ilapname(3):{etpx} ilapname(4):{etpy} ilapname(5):{etdx} ilapname(6):{etdy} ilapname(7):{dtpx} ilapname(8):{dtpy} ilapname(9):{dtdx} ilapname(10):{dtdy} ilapname(11):{dtdbx} ilapname(12):{dtdby} %if checklit('(')=false %then ->error %if getsexpr(s)=false %then ->error %if checklit(',')=false %then ->error %if getexpr(x)=false %then ->error %if checklit(',')=false %then ->error %if getexpr(y)=false %then ->error %if checklit(',')=false %then ->error %if getexpr(l)=false %then ->error %if l=0 %then fault("zero length transistor") %and ->next %if checklit(')')=false %then ->error %if checksep=false %then ->error startwort(name,x,y,l) ->next ilapname(32):{Vdd wire x} ilapname(33):{Vdd wire y} name = name - 32 + 13 -> ilapname(14) ilapname(34):{Gnd wire x} ilapname(35):{Gnd wire y} name = name - 34 + 13 ilapname(13):{wirex} ilapname(14):{wirey} %if checklit('(')=false %then ->error %if getexpr(x)=false %then ->error %if checklit(',')=false %then ->error %if getexpr(y)=false %then ->error %if checklit(',')=false %then ->error %if getexpr(l)=false %then ->error %if l=0 %then fault("zero length wire") %and ->next %if checklit(')')=false %then ->error %if checksep=false %then ->error %if curlay=0 %then fault("no layer specified for wire") %and ->next startwort(name,x,y,l) ->next ilapname(15):{dx} ilapname(16):{dy} %if checklit('(')=false %then ->error %if getexpr(l)=false %then ->error %if checklit(')')=false %then ->error %if checksep=false %then ->error %if wort=false %then fault("dx/y out of context") %and ->next %if xydir(name)=xdir %then xleg(l) %else yleg(l) ->next ilapname(17):{layer} %if checklit('(')=false %then ->error %if getname(name)=false %then ->error %unless poly<=name<=metal %then fault("unknown layer") %and ->next %if checklit(')')=false %then ->error %if checksep=false %then ->error endwort curlay=name curwid=defaultwidth(curlay) ->next ilapname(18):{width} %if checklit('(')=false %then ->error %if getexpr(w)=false %then ->error %if w<=0 %then fault("invalid width") %and ->next %if checklit(')')=false %then ->error %if checksep=false %then ->error endwort curwid=w ->next ilapname(19):{pm} ilapname(20):{dm} ilapname(21):{pdbn} ilapname(22):{pdbe} ilapname(23):{pdbs} ilapname(24):{pdbw} ilapname(25):{pdbns} ilapname(26):{pdbew} ilapname(27):{pdcn} ilapname(28):{pdce} ilapname(29):{pdcs} ilapname(30):{pdcw} %if checklit('(')=false %then ->error %if getexpr(x)=false %then ->error %if checklit(',')=false %then ->error %if getexpr(y)=false %then ->error %if checklit(')')=false %then ->error %if checksep=false %then ->error contact(name-pm,x,y) ->next ilapname(31):{box} %if checklit('(')=false %then ->error %if getexpr(x)=false %then ->error %if checklit(',')=false %then ->error %if getexpr(y)=false %then ->error %if checklit(',')=false %then ->error %if getexpr(xx)=false %then ->error %if checklit(',')=false %then ->error %if getexpr(yy)=false %then ->error %if checklit(')')=false %then ->error %if checksep=false %then ->error %if x>=xx %or y>=yy %then fault("box inside out") %and ->next endwort box(curlay,x,y,xx,yy) ->next error:fault("invalid statement") ->next !--------------------------------------------------------------------------- %routine read line %integer i,tpp tpp=0 line s = "" %cycle readsym(i) %if i=' ' %then %continue %if i='{' %then %start readsym(i) %until i='}' %or i=nl %if i='}' %then readsym(i) %finish %if tpp>tsize %then fault("statement too long") %and %return t(tpp)=i ; tpp=tpp+1 %if i=nl %then %start %if tpp=1 %or t(0)='!' %then tpp=0 %and %continue %if tpp>=2 %and t(tpp-1)='c' %and t(tpp-2)='%' %then %c tpp=tpp-2 %and %continue %exit %finish %repeat tp=0 %end !----------------------------------------------------------------------- %routine readsym(%integername n) read symbol(n) ; print symbol(n) lines = lines.tostring(n) %if 'A'<=n<='Z' %then n=n-'A'+'a' %end !----------------------------------------------------------------------- %routine fault(%string(63) s) %integer tpp tpp=0 print symbol(t(tpp)) %and tpp=tpp+1 %until t(tpp-1)=nl spaces(tp) ; print string("^".snl.s.snl) tp=tp+1 %while t(tp)#';' %and t(tp)#nl %if t(tp)=';' %then tp=tp+1 faulty=true %end !-------------------------------------------------------------------------- %integerfn getname(%integername name) %string(255) s %unless 'a'<=t(tp)<='z' %then %result=false s=tostring(t(tp)) ; tp=tp+1 %while 'a'<=t(tp)<='z' %or '0'<=t(tp)<='9' %cycle s=s.tostring(t(tp)) ; tp=tp+1 %repeat {find name in dictionary} %for name=1,1,namesend-1 %cycle %if s=names(name) %then %result=true %repeat {insert name if not already in dictionary} %if namesend=namessize %then fault("too many names") %and %result=false names(namesend)=s name=namesend namesend=namesend+1 %result=true %end !-------------------------------------------------------------------------- %integerfn checklit(%integer sym) %if t(tp)=sym %then tp=tp+1 %and %result=true %result=false %end !------------------------------------------------------------------------- %integerfn checksep %if t(tp)=';' %then tp=tp+1 %and %result=true %if t(tp)=nl %then %result=true %result=false %end !-------------------------------------------------------------------------- %integerfn getsexpr(%string(*)%name s) %integer i,tpi {string literal only as yet} s="" %if checklit(encchar(language))=false %then %result=false tpi=tp %cycle i=t(tp) ; tp=tp+1 %if i=nl %then tp=tpi %and %result=false %if i#encchar(language) %then s=s.tostring(i) %and %continue i=t(tp) %if i#encchar(language) %then %result=true s=s.encstring(language) tp=tp+1 %repeat %end !-------------------------------------------------------------------------- %integerfn getexpr(%integername e) %integer i,tpi,sign {constants only as yet} tpi=tp i=t(tp) ; tp=tp+1 sign=1 %if i='+' %or i='-' %then %start %if i='-' %then sign=-1 i=t(tp) ; tp=tp+1 %finish %unless '0'<=i<='9' %then tp=tpi %and %result=false e=i-'0' %cycle i=t(tp) %unless '0'<=i<='9' %then e=sign*e %and %result=true tp=tp+1 e=10*e+i-'0' %repeat %end !-------------------------------------------------------------------------- %routine startwort(%integer type,x,y,l) endwort wort=true worttype=type wortx=x ; worty=y legp=1 %if xydir(worttype)=xdir %then xleg(l) %else yleg(l) %end !---------------------------------------------------------------------- %routine xleg(%integer l) %if l=0 %then %return %if legp>1 %and legy(legp-1)=0 %then legx(legp-1)=legx(legp-1)+l %else %start %if legp>legs %then fault("too many dx/y legs") %and %return legx(legp)=l legy(legp)=0 legp=legp+1 %finish %end !---------------------------------------------------------------------- %routine yleg(%integer l) %if l=0 %then %return %if legp>1 %and legx(legp-1)=0 %then legy(legp-1)=legy(legp-1)+l %else %start %if legp>legs %then fault("too many dx/y legs") %and %return legy(legp)=l legx(legp)=0 legp=legp+1 %finish %end !----------------------------------------------------------------------- %routine endwort %integer l,path,other,imp,pathlim,otherlim,implim %record(point fm) pt %if wort=false %then %return lege=legp-1 %if etpx<=worttype<=dtdby %then %start {transistors} path=tranp(worttype) %if path=poly %then other=diffusion %else other=poly %if worttype>=dtpx %then imp=true %else imp=false %if xydir(worttype)=xdir %then %start %if worttype=dtdbx %then contact(bu,wortx,worty+1) l=legx(1) pathlim=wortx+l ; otherlim=pathlim %if l>0 %then %start {east} implim=pathlim+2 %if lege=1 %then pathlim=implim %else otherlim=implim box(path,wortx-2,worty,pathlim,worty+2) box(other,wortx,worty-2,otherlim,worty+4) %if imp=true %then box(implant,wortx-2,worty-2,implim,worty+4) pt_x=wortx+l-2 pt_y=worty %if lege>1 %then subst(pt,path,other,imp,2) %finish %else %start {west} implim=pathlim-2 %if lege=1 %then pathlim=implim %else otherlim=implim box(path,pathlim,worty,wortx+2,worty+2) box(other,otherlim,worty-2,wortx,worty+4) %if imp=true %then box(implant,implim,worty-2,wortx+2,worty+4) pt_x=wortx+l pt_y=worty %if lege>1 %then subst(pt,path,other,imp,2 ) %finish %finish %else %start {ydir=true} %if worttype=dtdby %then contact(bu,wortx+1,worty) l=legy(1) pathlim=worty+l ; otherlim=pathlim %if l>0 %then %start {north} implim=pathlim+2 %if lege=1 %then pathlim=implim %else otherlim=implim box(path,wortx,worty-2,wortx+2,pathlim) box(other,wortx-2,worty,wortx+4,otherlim) %if imp=true %then box(implant,wortx-2,worty-2,wortx+4,implim) pt_x=wortx pt_y=worty+l-2 %if lege>1 %then subst(pt,path,other,imp,2) %finish %else %start {south} implim=pathlim-2 %if lege=1 %then pathlim=implim %else otherlim=implim box(path,wortx,pathlim,wortx+2,worty+2) box(other,wortx-2,otherlim,wortx+4,worty) %if imp=true %then box(implant,wortx-2,implim,wortx+4,worty+2) pt_x=wortx pt_y=worty+l %if lege>1 %then subst(pt,path,other,imp,2) %finish %finish %finish %else %start {wires} %if worttype=wirex %then %start l=legx(1) %if l>0 %then %start {east} box(curlay,wortx,worty,wortx+l,worty+curwid) %if lege>1 %then subsw(wortx+l-curwid,worty,2) %finish %else %start {west} box(curlay,wortx+l,worty,wortx,worty+curwid) %if lege>1 %then subsw(wortx+l,worty,2) %finish %finish %else %start {wirey} l=legy(1) %if l>0 %then %start {north} box(curlay,wortx,worty,wortx+curwid,worty+l) %if lege>1 %then subsw(wortx,worty+l-curwid,2) %finish %else %start {south} box(curlay,wortx,worty+l,wortx+curwid,worty) %if lege>1 %then subsw(wortx,worty+l,2) %finish %finish %finish wort=false %end !---------------------------------------------------------------------- %routine subsw(%integer x,y,p) %integer l %if legx(p)=0 %then %start l=legy(p) %if l>0 %then box(curlay,x,y+curwid,x+curwid,y+curwid+l) %c %else box(curlay,x,y+l,x+curwid,y) %if lege>p %then subsw(x,y+l,p+1) %finish %else %start l=legx(p) %if l>0 %then box(curlay,x+curwid,y,x+curwid+l,y+curwid) %c %else box(curlay,x+l,y,x,y+curwid) %if lege>p %then subsw(x+l,y,p+1) %finish %end !---------------------------------------------------------------------- %routine subst(%record (point fm) pt,%integer path,other,imp,p) %integer l,pathlim,otherlim,implim %integer x, y x = pt_x { APM only takes five params } y = pt_y %if legx(p)=0 %then %start l=legy(p) %if l>0 %then %start {north} pathlim=y+2+l ; otherlim=pathlim ; implim=pathlim+2 %if lege=p %then pathlim=implim %else otherlim=implim box(path,x,y+2,x+2,pathlim) box(other,x-2,y+4,x+4,otherlim) %if imp=true %then box(implant,x-2,y+4,x+4,implim) pt_y=y+l pt_x = x %if lege>p %then subst(pt,path,other,imp,p+1) %finish %else %start {south} pathlim=y+l ; otherlim=pathlim ; implim=pathlim-2 %if lege=p %then pathlim=implim %else otherlim=implim box(path,x,pathlim,x+2,y) box(other,x-2,otherlim,x+4,y-2) %if imp=true %then box(implant,x-2,implim,x+4,y-2) pt_y=y+l pt_x = x %if lege>p %then subst(pt,path,other,imp,p+1) %finish %finish %else %start l=legx(p) %if l>0 %then %start {east} pathlim=x+l+2 ; otherlim=pathlim ; implim=pathlim+2 %if lege=p %then pathlim=implim %else otherlim=implim box(path,x+2,y,pathlim,y+2) box(other,x+4,y-2,otherlim,y+4) %if imp=true %then box(implant,x+4,y-2,implim,y+4) pt_x=x+l pt_y=y %if lege>p %then subst(pt,path,other,imp,p+1) %finish %else %start {west} pathlim=x+l ; otherlim=pathlim ; implim=pathlim-2 %if lege=p %then pathlim=implim %else otherlim=implim box(path,pathlim,y,x,y+2) box(other,otherlim,y-2,x-2,y+4) %if imp=true %then box(implant,implim,y-2,x-2,y+4) pt_x=x+l pt_y = y %if lege>p %then subst(pt,path,other,imp,p+1) %finish %finish %end !---------------------------------------------------------------------- %routine contact( %integer type,x,y) ! two fold use. first of all increments the contact count and sets it up ! secondly it draws it %integer i,j,ii,jj ! p d pd pd pd pd pd pd pd pd pd pd b ! sizes of the contacts m m bn be bs bw bns bew cn ce cs cw u %constant %byte %array xl(0:12) = 2,2,2, 2, 2, 3, 2, 3, 2, 2, 2, 3, 2 %constant %byte %array xr(0:12) = 1,1,1, 2, 1, 1, 1, 2, 1, 2, 1, 1, 1 %constant %byte %array yb(0:12) = 2,2,2, 2, 3, 2, 3, 2, 2, 2, 3, 2, 2 %constant %byte %array yt(0:12) = 1,1,2, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1 x = x + start_x y = y + start_Y %return %if x < 0 %or x > xrlim %or y < 0 %or y > yt lim %if x + xr(type) > maximum x %then maximum x = x + xr(type) %if y + yt(type) > maximum y %then maximum y = y + yt(type) %if x - xl(type) < minimum x %then minimum x = x - xl(type) %if y - yb(type) < minimum y %then minimum y = y - yb(type) %for i = x-xl(type),1,x+xr(type) %cycle %for j = y-yb(type),1,y+yt(type) %cycle %return %if grid(i)_y(j) & 32 # 0 %repeat %repeat %for i = x-xl(type),1,x+xr(type) %cycle %for j = y-yb(type),1,y+yt(type) %cycle grid(i)_y(j) = grid(i)_y(j) ! 32 %repeat %repeat con(con ptr)_t = type con(con ptr)_x = x con(con ptr)_y = y con ptr = con ptr + 1 %if con ptr > 200 %start printstring("too many contacts") %finish %end !---------------------------------------------------------------------- %routine box(%integer layer,xl,yb,xr,yt) %const %byte %array grid col(poly:implant) = 1,2,4,8 %integer i,j,ii,jj xl = xl + start_x xr = xr + start_x yb = yb + start_y yt = yt + start_y ! forget it if totaly of the edge of the screen %return %if xr < 0 %or xl > xr lim %or yt < 0 %or yb > yt lim xl = -frames %if xl < -frames xr = xr lim %if xr > xr lim yt = yt lim %if yt > yt lim yb = -frames %if yb < -frames %if xr > maximum x %then maximum x = xr %if yt > maximum y %then maximum y = yt %if xl < minimum x %then minimum x = xl %if yb < minimum y %then minimum y = yb %if xl>=xr %or yb>=yt %then %return {addition of = nb } %for i = xl,1,xr-1 %cycle %for j = yb,1,yt-1 %cycle grid(i)_y(j) = grid(i)_y(j) ! grid col(layer) %repeat %repeat %end !---------------------------------------------------------------------- %end %endoffile