Skip to content

Commit a46345f

Browse files
committed
dataflow_matmul
1 parent fd80f74 commit a46345f

File tree

3 files changed

+848
-0
lines changed

3 files changed

+848
-0
lines changed

examples/dataflow_matmul/Makefile

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
TARGET=$(shell ls *.py | grep -v test | grep -v parsetab.py)
2+
ARGS=
3+
4+
PYTHON=python3
5+
#PYTHON=python
6+
#OPT=-m pdb
7+
#OPT=-m cProfile -s time
8+
#OPT=-m cProfile -o profile.rslt
9+
10+
.PHONY: all
11+
all: test
12+
13+
.PHONY: run
14+
run:
15+
$(PYTHON) $(OPT) $(TARGET) $(ARGS)
16+
17+
.PHONY: test
18+
test:
19+
$(PYTHON) -m pytest -vv
20+
21+
.PHONY: check
22+
check:
23+
$(PYTHON) $(OPT) $(TARGET) $(ARGS) > tmp.v
24+
iverilog -tnull -Wall tmp.v
25+
rm -f tmp.v
26+
27+
.PHONY: clean
28+
clean:
29+
rm -rf *.pyc __pycache__ parsetab.py .cache *.out *.png *.dot tmp.v uut.vcd
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
from __future__ import absolute_import
2+
from __future__ import print_function
3+
import sys
4+
import os
5+
import math
6+
7+
# the next line can be removed after installation
8+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
9+
10+
from veriloggen import *
11+
import veriloggen.dataflow as dataflow
12+
13+
def mkMadd():
14+
x = dataflow.Variable('xd', valid='xv', signed=True)
15+
y = dataflow.Variable('yd', valid='yv', signed=True)
16+
vreset = dataflow.Variable('vreset_data', valid='vreset')
17+
18+
xy = x * y
19+
20+
z = dataflow.Iadd(xy, signed=True, initval=0, reset=vreset)
21+
22+
z.output('zd', valid='zv')
23+
df = dataflow.Dataflow(z)
24+
m = df.to_module('madd')
25+
26+
return m
27+
28+
def mkMatmul(n=16, datawidth=32):
29+
m = Module('Matmul')
30+
31+
clk = m.Input('CLK')
32+
rst = m.Input('RST')
33+
34+
# BRAM I/F
35+
addrwidth = int(math.log(n, 2)) * 2
36+
37+
xaddr = m.OutputReg('xaddr', addrwidth, initval=0)
38+
xdin = m.Input('xdin', datawidth)
39+
40+
yaddr = m.OutputReg('yaddr', addrwidth, initval=0)
41+
ydin = m.Input('ydin', datawidth)
42+
43+
zaddr = m.OutputReg('zaddr', addrwidth, initval=0)
44+
zdout = m.OutputReg('zdout', datawidth, initval=0)
45+
zwe = m.OutputReg('zwe')
46+
47+
# External Control
48+
start = m.Input('start')
49+
busy = m.OutputReg('busy', initval=0)
50+
51+
# MADD Instance
52+
madd = mkMadd()
53+
54+
ivalid = m.Reg('ivalid', initval=0)
55+
odata = m.Wire('odata', datawidth)
56+
ovalid = m.Wire('ovalid')
57+
vreset = m.Reg('vreset', initval=0)
58+
59+
m.Instance(madd, 'madd',
60+
ports=[ ('CLK', clk), ('RST', rst),
61+
('xd', xdin), ('xv', ivalid), ('yd', ydin), ('yv', ivalid),
62+
('zd', odata), ('zv', ovalid), ('vreset_data', 0), ('vreset', vreset) ])
63+
64+
read_count = m.TmpReg(32, initval=0)
65+
sum_value = m.TmpReg(datawidth, initval=0)
66+
sum_count = m.TmpReg(32, initval=0)
67+
68+
# main FSM
69+
fsm = FSM(m, 'fsm', clk, rst)
70+
71+
init = fsm.current()
72+
73+
# initial values
74+
fsm.add( xaddr(0-1), yaddr(0-1), zaddr(0-1), zwe(0),
75+
busy(0), vreset(1), ivalid(0),
76+
read_count(0), sum_value(0), sum_count(0) )
77+
78+
# start
79+
fsm.add( busy(1), vreset(0), cond=start )
80+
fsm.goto_next(cond=start)
81+
82+
comp = fsm.current()
83+
84+
# read data
85+
fsm.add( xaddr.inc(), yaddr.inc(), cond=read_count<n )
86+
fsm.add( ivalid(0), delay=1 )
87+
fsm.add( ivalid(1), delay=1, cond=read_count<n )
88+
fsm.add( read_count.inc(), cond=read_count<n )
89+
90+
# comp data
91+
fsm.add( sum_count.inc(), cond=ovalid )
92+
fsm.add( sum_value(odata), cond=ovalid )
93+
94+
# dump
95+
#fsm.add( Systask('display', 'xaddr=%10d yaddr=%10d', xaddr, yaddr) )
96+
#fsm.add( Systask('display', 'xdin =%10d ydin =%10d', xdin, ydin), delay=1 )
97+
#fsm.add( Systask('display', 'count=%10d odata=%10d', sum_count, odata), cond=ovalid )
98+
99+
fsm.goto_next(cond=sum_count==n)
100+
101+
# write data
102+
fsm.add( zaddr.inc() )
103+
fsm.add( zdout(sum_value), zwe(1) )
104+
fsm.add( zwe(0), delay=1 )
105+
106+
# set up for next
107+
fsm.add( yaddr(0-1), cond=yaddr==n*n-1 )
108+
fsm.add( xaddr(xaddr-n), cond=yaddr<n*n-1)
109+
fsm.add( read_count(0), sum_count(0) )
110+
111+
# reset pipeline
112+
fsm.add( vreset(1) )
113+
fsm.add( vreset(0), delay=1 )
114+
115+
done = (zaddr == n * n - 2)
116+
fsm.goto(comp, cond=Not(done))
117+
fsm.goto(init, cond=done)
118+
119+
fsm.make_always()
120+
121+
return m
122+
123+
def mkTest(n=16, datawidth=32):
124+
125+
m = Module('test')
126+
127+
# target instance
128+
main = mkMatmul(n, datawidth)
129+
130+
params = m.copy_params(main)
131+
ports = m.copy_sim_ports(main)
132+
133+
clk = ports['CLK']
134+
rst = ports['RST']
135+
136+
xaddr = ports['xaddr']
137+
xdin = ports['xdin']
138+
139+
yaddr = ports['yaddr']
140+
ydin = ports['ydin']
141+
142+
zaddr = ports['zaddr']
143+
zdout = ports['zdout']
144+
zwe = ports['zwe']
145+
146+
start = ports['start']
147+
busy = ports['busy']
148+
149+
uut = m.Instance(main, 'uut',
150+
params=m.connect_params(main),
151+
ports=m.connect_ports(main))
152+
153+
reset_done = m.Reg('reset_done', initval=0)
154+
reset_stmt = []
155+
reset_stmt.append( reset_done(0) )
156+
reset_stmt.append( start(0) )
157+
reset_stmt.append( xdin(0) )
158+
reset_stmt.append( ydin(0) )
159+
160+
simulation.setup_waveform(m, uut)
161+
simulation.setup_clock(m, clk, hperiod=5)
162+
init = simulation.setup_reset(m, rst, reset_stmt, period=100)
163+
164+
nclk = simulation.next_clock
165+
166+
init.add(
167+
Delay(1000),
168+
reset_done(1),
169+
nclk(clk),
170+
Delay(100000),
171+
Systask('finish'),
172+
)
173+
174+
fsm = FSM(m, 'fsm', clk, rst)
175+
176+
fsm.goto_next(cond=reset_done)
177+
178+
fsm.goto_next(cond=Not(busy))
179+
180+
fsm.add( start(1) )
181+
fsm.add( start(0), delay=1 )
182+
#fsm.add( xdin(Mux(xaddr % n == xaddr / n, 1, 0)) )
183+
fsm.add( xdin(xaddr) )
184+
fsm.add( ydin(Mux(yaddr % n == yaddr / n, 1, 0)) )
185+
fsm.goto_next()
186+
187+
#fsm.add( xdin(Mux(xaddr % n == xaddr / n, 1, 0)) )
188+
fsm.add( xdin(xaddr) )
189+
fsm.add( ydin(Mux(yaddr % n == yaddr / n, 1, 0)) )
190+
fsm.goto_next(cond=busy)
191+
192+
#fsm.add( xdin(Mux(xaddr % n == xaddr / n, 1, 0)) )
193+
fsm.add( xdin(xaddr) )
194+
fsm.add( ydin(Mux(yaddr % n == yaddr / n, 1, 0)) )
195+
fsm.goto_next(cond=Not(busy))
196+
197+
fsm.add( Systask('finish') )
198+
199+
fsm.make_always()
200+
201+
m.Always(Posedge(clk))(
202+
If(zwe)(
203+
Systask('display', 'zaddr=%10d zdout=%10d', zaddr, zdout),
204+
#If(AndList(zaddr % n == zaddr / n, zdout != 1))(
205+
# Systask('display', '## wrong')
206+
#),
207+
#If(AndList(zaddr % n != zaddr / n, zdout != 0))(
208+
# Systask('display', '## wrong')
209+
#)
210+
If(zaddr != zdout)(
211+
Systask('display', '## wrong result')
212+
),
213+
)
214+
)
215+
216+
return m
217+
218+
if __name__ == '__main__':
219+
n = 16
220+
test = mkTest(n)
221+
verilog = test.to_verilog('tmp.v')
222+
#print(verilog)
223+
224+
# run simulator (Icarus Verilog)
225+
sim = simulation.Simulator(test)
226+
rslt = sim.run()
227+
print(rslt)
228+
229+
# only target RTL
230+
#main = mkMatmul(n)
231+
#verilog = main.to_verilog('tmp.v')
232+
#print(verilog)

0 commit comments

Comments
 (0)