begin ; !Rom Finite State Machine Simulator
! Input:
! Number of inputs
! Input Names
! Number of Outputs
! Output Names
! Number of state bits
! { state : { = clone-state } { Output = expression }*
! { next-state-number expression }* ; }* .
! Expressions involve input names, 0, 1, and )(+.¬ and are
! terminated by a colon, thereby allowing them to extend
! over several lines.
! Output:
! A binary file for each byte the rom is wide.
! The state bits form the most significant part of both
! address and data, the input and output bits increase
! in significance, i.e. the first input bit is the least
! significant address bit, the last output bit is the most
! significant data bit (but less significant than the least
! significant state bit).
include "inc:util.imp"
string (31)file = cliparam
file = file.tostring('.')
openinput(1,file."fsm"); selectinput(1)
integer line=1, pend=-1, i
integer inputs, outputs, statebits
integer inbits, outbits, max
integer errorcount=0
routine error(string (255)s)
errorcount = errorcount+1
printstring(s." at line "); write(line,0); newline
selectoutput(0)
printstring(s." at line "); write(line,0); newline
selectoutput(1)
end
routine wbsym(integer x); !Write back symbol
pend = x
end
integerfn rsym; !Read symbol, skip comments, count lines
integer x
x = pend; pend = -1; result = x unless x<0
cycle
readsymbol(x); line = line+1 if x=nl
if x='{' start
cycle
readsymbol(x); line = line+1 if x=nl
repeatuntil x='}'
elseif x='|'
readsymbol(x) until x=nl
line = line+1
finishelseresult = x
repeat
end
integerfn sigsym; !Read significant symbol
integer x
x = rsym until ' '#x#nl
result = x
end
integerfn rdec; !Read decimal number
integer x=sigsym,n=0
unless '0'<=x<='9' start
error("Warning: decimal number expected")
result = 0
finish
cycle
exitunless '0'<=x<='9'
n = n*10-'0'+x
x = rsym
repeat
wbsym(x); result = n
end
routine rname(string (15)name s); !Read signal name or special symbol
integer x = sigsym
s = tostring(x)
returnunless 'A'<=x&95<='Z'
cycle
x = rsym
exitunless 'A'<=x&95<='Z' or '0'<=x<='9' or x=''''
s = s.tostring(x)
repeat
wbsym(x)
end
inputs = rdec
string (15)array in(0:inputs); !0 never used
rname(in(i)) for i=1,1,inputs
outputs = rdec
begin
string (15)array out(0:outputs); !0 never used
rname(out(i)) for i=1,1,outputs
statebits = rdec
inbits = statebits+inputs
outbits = statebits+outputs
if outbits>32 start
error("Rom too wide"); stop
finish
max = 1<<inbits-1
begin
integerarray a(0:max); ! ROM
integerarray e(0:max); ! Expression stack
constinteger maxstack=50
shortarray opd(1:maxstack); !Operand stack
shortarray opt(1:maxstack); !Operator stack
integer pd,pt
constbytearray op(0:6)='0','1',')','(','+','.','¬'
constinteger zero=0,one=1,right=2,left=3,or=4,and=5,not=6
integer inbits=0,outbits,sym
constinteger clear=0,set=1,complement=2
routine dostate(integer state)
integer low = state<<inputs, high = low+1<<inputs-1; !array bounds
routine expr
string (15)s
integer k
constinteger d=1,t=2
integer mode = d; !indicates whether expecting operanD or operaTor
routine m(integer x,y); !verify mode=x, then set to y
string (63)e
unless mode=x start
e = "Got "
if x=d start
e = e.tostring(k)
error(e." when expecting an operand")
else
error(e.s." when expecting an operator")
finish
finish
mode = y
end
routine dpush(integer x); !add to reverse polish list
{printstring("Dpush "); %if x>=0 %then printsymbol(op(x)) %else write(x,0); newline
returnif x=left
error("Expression too complex") if pd>=maxstack
pd = pd+1; opd(pd) = x
end
integerfn tpop; !off operator stack
{printstring("Tpop:")
result = 0 if pt<=0
pt = pt-1; result = opt(pt+1)
end
routine tpush(integer x); !onto operator stack
integer y
{printstring("Tpush "); %if x>=0 %then printsymbol(op(x)) %else write(x,0); newline
unless x=left start
while pt>0 and x<=opt(pt) cycle ; !flush high-prec ops
y = tpop; exitif x=right and y=left
dpush(y)
repeat
finish
returnif x=right
error("Expression too complex") if pt>=maxstack
pt = pt+1; opt(pt) = x
end
! Part 1 of EXPR: read expression and build reverse polish list
pd = 0; pt = 0; tpush(left); !Initial open bracket
cycle
rname(s); k = charno(s,1)
if k='(' start
m(d,d); tpush(left)
elseif k=')'
m(t,t); tpush(right)
if pt=0 start
error("Spurious ')'")
k = rsym until k=',' or k=';'; exit
finish
elseif k='+'
m(t,d); tpush(or)
elseif k='.'
m(t,d); tpush(and)
elseif k='¬'
m(d,d); tpush(not)
elseif k=',' or k=';'
wbsym(k) unless k=','
m(t,0); tpush(right)
unless pt=0 start
error("Premature ','")
exit
finish
exit
elseif k='0'
m(d,t); dpush(zero)
elseif k='1'
m(d,t); dpush(one)
else
m(d,t); k = inputs
while k>0 cycle
exitif in(k)=s; k = k-1
repeat
if k=0 start
error("Unknown operand ".s)
k = 0
finish
dpush(-k)
finish
repeat
! Part 2 of EXPR: evaluate expression just built
integer p=0
integer stackbit=1,nextbit,i
while p<pd cycle
nextbit = stackbit>>1
p = p+1; k = opd(p)
if k=one start
e(i) = e(i)!stackbit for i=low,1,high
stackbit = stackbit<<1
elseif k=zero
e(i) = e(i)&¬stackbit for i=low,1,high
stackbit = stackbit<<1
elseif k=not
e(i) = e(i)!!nextbit for i=low,1,high
elseif k=and
stackbit = nextbit; nextbit = nextbit>>1
for i=low,1,high cycle
e(i) = e(i)&¬nextbit if e(i)&stackbit=0
repeat
elseif k=or
stackbit = nextbit; nextbit = nextbit>>1
for i=low,1,high cycle
e(i) = e(i)!nextbit if e(i)&stackbit#0
repeat
else
k = 1<<(-1-k)
for i=low,1,high cycle
if i&k#0 start
e(i) = e(i)!stackbit
else
e(i) = e(i)&¬stackbit
finish
repeat
stackbit = stackbit<<1
finish
repeat
error("Bit lost") unless stackbit=2
e(i) = e(i)&1 for i=low,1,high
end
routine equals
integer x = sigsym
returnif x='='
wbsym(x)
error("Warning: '=' expected")
end
routine setoutput
string (15)o; rname(o)
integer k,i
equals
k = outputs
while k>0 cycle
exitif out(k)=o
k = k-1
repeat
error("Unknown output ".o) if k=0
k = 1<<(k-1)
expr
for i=low,1,high cycle
if e(i)=0 then a(i) = a(i)&¬k else a(i) = a(i)!k
repeat
end
routine nextstate
integer i,old,new,f=0
new = rdec; equals; expr
for i=low,1,high cycle
if e(i)#0 start
old = a(i)>>outputs
error("Ambiguous next state") and f=1 if old#state and f=0
a(i) = a(i)!!(old!!new)<<outputs
finish
repeat
end
! Main part of DOSTATE
integer k = sigsym,i
unless k=':' start
error("Warning: ':' expected")
finish
k = sigsym
if k='=' start ; !clone output configuration of another state
k = rdec
k = k<<inputs!!low
for i=low,1,high cycle
a(i) = a(i!!k)
repeat
k = sigsym
error("',' expected") unless k=','
finishelse wbsym(k)
k = 1<<outputs-1
a(i) = a(i)&k!state<<outputs for i=low,1,high
cycle
k = sigsym; wbsym(k)
if '0'<=k<='9' then nextstate c
elseif 'A'<=k&95<='Z' then setoutput c
elseexit
repeat
k = rsym
error("Warning: ';' expected") unless k=';'
end {dostate}
! Rest of main program
a(i) = 0 and e(i) = 0 for i=0,1,max
cycle
i = sigsym; exitif i='.'; wbsym(i)
dostate(rdec)
repeat
if errorcount#0 start
selectoutput(0); printstring("No output generated"); newline
stop
finish
! End of ROM building code, simulation follows.
routine feedback
inbits = inbits&(1<<inputs-1) ! outbits>>outputs<<inputs
end
routine list(integer mode)
string (15)signal
integer i
cycle
sym = rsym; exitif sym=nl
wbsym(sym); rname(signal)
i = inputs
while i>0 cycle
exitif in(i)=signal; i = i-1
repeat
if i=0 start
printstring("Unknown signal ".signal); newline
else
i = 1<<(i-1)
if mode=clear start
inbits = inbits&¬i
elseif mode=set
inbits = inbits!i
else
inbits = inbits!!i
finish
finish
repeat
end
routine show state
integer i
printstring("State:")
i = inputs+statebits
cycle
exitif i=inputs
i = i-1
space; printsymbol(inbits>>i&1+'0')
repeat
newline
printstring("Inputs:"); phex4(inbits)
while i>0 cycle
space; printstring(in(i)); printsymbol('=')
i = i-1
printsymbol(inbits>>i&1+'0')
repeat
newline
printstring("Next state:")
i = outputs+statebits
cycle
exitif i=outputs
i = i-1
space; printsymbol(outbits>>i&1+'0')
repeat
newline
printstring("Outputs:"); phex(outbits)
while i>0 cycle
space; printstring(out(i)); printsymbol('=')
i = i-1
printsymbol(outbits>>i&1+'0')
repeat
newline
end
selectinput(0); wbsym(-1)
cycle
sym = rsym
if sym=nl start {clock tick
!!phex(inbits); space; phex(a(inbits)); space
outbits = a(inbits)
!!phex(outbits); newline
show state
feedback
elseif sym='0'
list(clear)
elseif sym='1'
list(set)
else
wbsym(sym)
list(complement)
finish
repeat
end
end
endofprogram