! TOBEPI: Convert a design from ESDL to BEPI format, by taking an ESDL ! ".BIC" file (that has preferably been through the interactive route ! vetting program VZAP), and generating from that the three data files ! (".CPL", ".NET", ".PAG") required by BEPI programs ONE to FIVE or the ! single program SWRAP which replaces these. ! RWT November 1985 revised August 1986 %begin %include "inc:util.imp" !Reminder of ESDL data format: !ESDL -> ^S [0:eic,1:fic,2:cic,3:bic] UNIT* !UNIT -> ^U [1:spec,2:unit,3:chip,4:board,5:pack] HEAD UNIT* ! ^J nsubs HEAD* {^N{^A netname nfans {subno tno}*}+}* ! ^E !HEAD -> ^H0 nin nout nio nt label name ! {^T tno<<2+[0:dup,1:out,2:in,3:inout] pinname signalname}* ! {^P [1:at,2:on,3:pack,4:subpack,5:delay,6:value,7:size,8:place] parm}* ! ^G !In particular for .BIC files we have: ! ^S3^U4 HEAD(label=circuitname,name=boardname,p7(size)) ^Jn ! {HEAD(label=uselessPACKnumber,name=chipname,p1(ATslotname), ! p2(ONpackname),p7(size),p8(place(x:y)))}n ! {^N{^A ...}+}* ^E ! pinnames in ^T lists take the form x:y/pinname %recordformatspec pinf %recordformatspec netf %recordformat chipf(%record(chipf)%name next,%record(pinf)%name pins, %integer label,name,on,at,wide,high,x,y) %recordformat pinf(%record(pinf)%name nextinchip,nextinnet, %record(chipf)%name chip,%record(netf)%name net, %integer tno,flags,pin,signal,index,x,y) %recordformat netf(%record(netf)%name nextnet,nextsubnet,net, %record(pinf)%name pins, %integer signal,index) %constinteger pat=1,pon=2,psize=7,pplace=8 %integer sym; !Current I-code symbol %string(255)s; !Current I-code string %integer si; !Signal name index, normally -1, but for !a signal A<17>, si would be 17 and s A %constinteger hashmask=63 %recordformat hashf(%record(hashf)%name next,%string(255)s) %record(hashf)%namearray hashtab(0:hashmask) %record(netf)%name nets; !List of nets in main circuit %record(chipf)%name chips; !List of chips in main circuit, of which !the first is the main circuit itself. %integer width,height %string(255)file="" %constinteger xflip=1<<31,yflip=1<<30,xyswap=1<<29 %integer bools = xflip,xoffset=0,yoffset=0 %integerfn codestring ! Returns a code value which uniquely identifies ! global string S, which is entered in a dictionary. ! This consists of a primary hash table with simple ! unsorted linked lists hanging off each entry. ! The actual number returned is the address of the string. %record(hashf)%name h %integer value=0,i %result = 0 %if length(s)=0 %for i = 1,1,length(s) %cycle value = value<<1+(charno(s,i)!32) %repeat value = value&hashmask h == hashtab(value) %cycle %if h==nil %start; !Tag new entry onto (end of) list h == record(heapget(5+length(s))) h_s = s; h_next == hashtab(value) hashtab(value) == h %result = addr(h_s) %finish %result = addr(h_s) %if h_s=s h == h_next %repeat %end %string(255)%fn hashstring(%integer tag) ! Re-constitutes a hash-coded string %result = "" %if tag=0 %result = string(tag) %end %string(255)%fn indexstring(%integer i) ! Re-constitutes index part of a signal name %string(255)s %result = "" %if i<0 s = itos(i,0) %result = "<".s.">" %end %record(*)%map reverse(%record(*)%name list) ! Reverses an arbitrary singly linked list, provided ! the first field in the record is used for linking. %recordformat f(%record(f)%name next) %record(f)%name head,tail,temp head == list; tail == nil; %result == nil %if list==nil %cycle temp==head; head==temp_next; temp_next==tail; tail==temp %repeatuntil head==nil %result==tail %end ! ESDL I-code input procedures %routine readsym ! Read significant character and store in global SYM. ! NB newlines are not significant but spaces are. readsymbol(sym) %until sym#nl %returnunless sym='^' readsymbol(sym); sym=sym+'^'<<8 %end %routine verify(%integer want) ! Ensure global SYM corresponds to WANT %routine p(%integer x) printsymbol(x>>8) %unless x>>8=0 printsymbol(x) %end %returnif sym=want printstring("Got "); p(sym) printstring(" when expecting "); p(want) newline; %stop %end %routine readstring ! Read string and store in global S and SI (if of form signal) %owninteger dotted=0 %integer indexed=0 %integer len,i si = -1 read(len); readsym; verify(':') length(s) = len %for i=1,1,len %cycle readsym indexed = i %if indexed=0 %and sym='<' charno(s,i) = sym %repeat %if indexed#0 %start length(s) = indexed-1 si = 0 %cycle indexed = indexed+1; i = charno(s,indexed)-'0' %exitunless 0<=i<=9 si = si*10+i %repeat %finish %end %integerfn getnum ! Extract a possibly signed decimal number off the front of global ! string S, which is shortened by the number plus its terminator. %integer n=0,sign=0,pos=1 %while pos<=length(s) %cycle sym = charno(s,pos); pos = pos+1 %if sym='-' %start sign = 1 %finishelseif '0'<=sym<='9' %start n = n*10-'0'+sym %finishelseexit %repeat s = substring(s,pos,length(s)) %result = n %if sign=0 %result=-n %end %predicate contains(%string(*)%name s,%integer k) ! Does string S contain character K? %integer i %for i = 1,1,length(s) %cycle %trueif charno(s,i)=k %repeat %false %end %record(chipf)%map readchips ! Read {^H0 ... ^G}* %integer i %record(chipf)%name chead,ctail %record(pinf)%name phead,ptail ctail == nil readsym %while sym='^H' %cycle readsym; verify('0') chead == new(chead); chead = 0 chead_next == ctail; ctail == chead read(i); read(i); read(i); read(i) {ni,no,nio,nt} readstring; chead_label = codestring readstring; chead_name = codestring ptail == nil; readsym %while sym='^T' %cycle read(i) %if i&3#0 %start; !In,Out,or InOut phead == new(phead); phead = 0; phead_chip == chead phead_nextinchip == ptail; ptail == phead phead_tno = i>>2; phead_flags = i&3 readstring %if contains(s,':') %start phead_x = getnum; verify(':'); phead_y = getnum %finish phead_pin = codestring readstring; phead_signal = codestring; phead_index = si %else; !Dummy pin readstring; readstring %finish readsym %repeat chead_pins == reverse(phead) %while sym='^P' %cycle read(i); readstring %if i=pon %start chead_on = codestring %finishelseif i=pat %start chead_at = codestring %finishelseif i=psize %start chead_wide = getnum; verify(':') chead_high = getnum %finishelseif i=pplace %start chead_x = getnum; verify(':') chead_y = getnum %finish readsym %repeat verify('^G') readsym %repeat %result == chead %end %record(netf)%map readnets ! Read {^N {subnet}*}* %record(netf)%name head,tail %record(netf)%map readsubnets ! Read {^A subnetname pairs {chip pin}*}* %record(netf)%name head,tail %record(pinf)%name p,term %record(chipf)%name sub %integer nfans,subno,tno tail == nil %while sym='^A' %cycle head == new(head); head = 0 head_nextsubnet == tail; tail == head readstring; head_signal = codestring; head_index = si read(nfans); p == nil %while nfans>0 %cycle nfans = nfans-1; read(subno); read(tno) sub == chips ! Scan component list (by position) sub == sub_next %and subno = subno-1 %while subno>0 term == sub_pins ! Scan component's pin list (by pin number value) term == term_nextinchip %while term##nil %and term_tno#tno %if term==nil %start printstring("Terminal "); write(tno,0) printstring(" not found in component ") printstring(hashstring(sub_name)) printstring(" at "); printstring(hashstring(sub_at)); newline %elseif term_flags&4=0; !All is well: not been here before term_flags = term_flags!4; term_net == head term_nextinnet == p; p == term %finishelseunless term_net==head %start; !Confusion printstring("Terminal"); write(term_tno,1) printstring(", pin ".hashstring(term_pin)) space; printstring(hashstring(term_signal)) printstring(" of ".hashstring(term_chip_label)); space printstring(hashstring(term_chip_name)." at ") printstring(hashstring(term_chip_at)); newline printstring("is already connected to ") printstring(hashstring(term_net_signal)) printstring(indexstring(term_net_index)) printstring(", cannot also connect to ".s) printstring(indexstring(si)); newline %finish %repeat head_pins == p readsym %repeat head == tail %cycle tail_net == head; tail == tail_nextsubnet %repeatuntil tail==nil %result == head %end tail == nil %while sym='^N' %cycle readsym; head == readsubnets head_nextnet == tail; tail == head %repeat %result == head %end %routine xy(%integer x,y,p,q) %integer t x = width-x %if bools&xflip#0 y = height-y %if bools&yflip#0 %if bools&xyswap#0 %start t = x; x = y; y = t %finish write(x-xoffset,p); printsymbol('0') write(y-yoffset,q); printsymbol('0') %end %routine warn(%integer d,%string(19)type) %returnif d<=0 printstring("Warning: "); printstring(type) printstring(" names exceed recommended maximum length by") write(d,1); printstring(" characters"); newline %end %routine produce cpl file %record(chipf)%name c %integer i,maxcn=0,maxpn=0 %string(255)chipname %routine putcpl %record(pinf)%name p %string(255)pinname maxcn = length(chipname) %if length(chipname)>maxcn p == c_pins %while p##nil %cycle pinname = hashstring(p_pin) maxpn = length(pinname) %if length(pinname)>maxpn printstring(chipname); spaces(10-length(chipname)-length(pinname)) space; printstring(pinname); xy(p_x,p_y,6,6); newline p == p_nextinchip %repeat %end printstring("Writing .CPL file") openoutput(1,file.".CPL"); selectoutput(1) c == chips; chipname = "EDGE"; putcpl c == chips_next %while c##nil %cycle chipname = hashstring(c_at) putcpl c == c_next %repeat closeoutput; selectoutput(0); newline warn(maxcn-5,"component") warn(maxpn-5,"pin") %end %routine produce net files %record(netf)%name m,n %record(pinf)%name p %string(255)signame,pinname,chipname %integer maxsn=0,i printstring("Writing .NET and .PAG files") openoutput(2,file.".PAG") openoutput(1,file.".NET"); selectoutput(1) m == nets %while m##nil %cycle n == m; m == m_nextnet signame = hashstring(n_signal) %if n_index>=0 %start signame = signame."<".itos(n_index,0).">" %finish maxsn = length(signame) %if length(signame)>maxsn %if charno(signame,1)='.' %then selectoutput(2) %else selectoutput(1) %cycle p == n_pins; i = 0 %while p##nil %cycle printstring(signame) pinname = hashstring(p_pin) %if p_chip==chips %then chipname = "EDGE" %elsestart chipname = hashstring(p_chip_at) %finish space; spaces(14-length(signame)-length(chipname)) printstring(chipname."-".pinname) newline p == p_nextinnet %repeat n == n_nextsubnet %repeatuntil n==nil %repeat selectoutput(2); closeoutput selectoutput(1); closeoutput selectoutput(0); newline warn(maxsn-9,"signal") %end ! Acquire Parameters define param("Filename",file,pamnodefault) define int param("XOffset",xoffset,pamnewgroup) define int param("YOffset",yoffset,0) define boolean params("Xflip,Yflip,XYswap",bools,pamnewgroup) processparameters(cliparam) toupper(file) ! Initialise, Read BIC file hashtab(sym) == nil %for sym = 0,1,hashmask printstring("Reading .BIC file") openinput(1,file.".BIC"); selectinput(1) readsym; verify('^S'); readsym; verify('3') readsym; verify('^U'); readsym; verify('4') chips == readchips width = chips_wide; height = chips_high verify('^J'); read(sym) chips_next == reverse(readchips) nets == readnets verify('^E') closeinput; newline ! Produce output files produce cpl file produce net files %endofprogram