Skip to content

Commit 7d7b071

Browse files
committed
dataflow_matmul_bram is added.
1 parent a46345f commit 7d7b071

File tree

3 files changed

+357
-0
lines changed

3 files changed

+357
-0
lines changed
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: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
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 mkBram(datawidth=32, addrwidth=10, numports=2):
29+
m = Module('BRAM%d' % numports)
30+
31+
clk = m.Input('CLK')
32+
rst = m.Input('RST')
33+
ports = []
34+
for i in range(numports):
35+
addr = m.Input('ADDR%d' % i, addrwidth)
36+
din = m.Input('DIN%d' % i, datawidth)
37+
we = m.Input('WE%d' % i)
38+
dout = m.Output('DOUT%d' % i, datawidth)
39+
delay_addr = m.Reg('delay_ADDR%d' % i, addrwidth)
40+
ports.append( (addr, din, we, dout, delay_addr) )
41+
42+
mem = m.Reg('mem', datawidth, length=2**addrwidth)
43+
44+
for i in range(numports):
45+
addr, din ,we, dout, delay_addr = ports[i]
46+
m.Always(Posedge(clk))(
47+
If(we)(
48+
mem[addr](din)
49+
),
50+
delay_addr(addr)
51+
)
52+
m.Assign(dout(mem[delay_addr]))
53+
54+
return m
55+
56+
def mkMatmulBram(n=16, datawidth=32):
57+
m = Module('Matmul')
58+
59+
clk = m.Input('CLK')
60+
rst = m.Input('RST')
61+
62+
addrwidth = int(math.log(n, 2)) * 2
63+
64+
bram = mkBram(datawidth, addrwidth)
65+
66+
ext_ports = []
67+
for i in range(3):
68+
addr = m.Input('bram_addr%d' % i, addrwidth)
69+
din = m.Input('bram_din%d' % i, datawidth)
70+
we = m.Input('bram_we%d' % i)
71+
dout = m.Output('bram_dout%d' % i, datawidth)
72+
ext_ports.append( [addr, din, we, dout] )
73+
74+
int_ports = []
75+
for i in range(3):
76+
addr = m.Wire('_addr%d' % i, addrwidth)
77+
din = m.Wire('_din%d' % i, datawidth)
78+
we = m.Wire('_we%d' % i)
79+
dout = m.Wire('_dout%d' % i, datawidth)
80+
int_ports.append( [addr, din, we, dout] )
81+
82+
for i in range(3):
83+
ports = [ clk, rst ] + ext_ports[i] + int_ports[i]
84+
m.Instance(bram, 'inst_bram%d' % i, ports=ports)
85+
86+
xaddr = m.Reg('xaddr', addrwidth, initval=0)
87+
xdin = m.Wire('xdin', datawidth)
88+
89+
yaddr = m.Reg('yaddr', addrwidth, initval=0)
90+
ydin = m.Wire('ydin', datawidth)
91+
92+
zaddr = m.Reg('zaddr', addrwidth, initval=0)
93+
zdout = m.Reg('zdout', datawidth, initval=0)
94+
zwe = m.Reg('zwe')
95+
96+
addr, din, we, dout = int_ports[0] # x
97+
m.Assign( addr(xaddr) )
98+
m.Assign( we(0) )
99+
m.Assign( xdin(dout) )
100+
101+
addr, din, we, dout = int_ports[1] # y
102+
m.Assign( addr(yaddr) )
103+
m.Assign( we(0) )
104+
m.Assign( ydin(dout) )
105+
106+
addr, din, we, dout = int_ports[2] # z
107+
m.Assign( addr(zaddr) )
108+
m.Assign( din(zdout) )
109+
m.Assign( we(zwe) )
110+
111+
# External Control
112+
start = m.Input('start')
113+
busy = m.OutputReg('busy', initval=0)
114+
115+
# MADD Instance
116+
madd = mkMadd()
117+
118+
ivalid = m.Reg('ivalid', initval=0)
119+
odata = m.Wire('odata', datawidth)
120+
ovalid = m.Wire('ovalid')
121+
vreset = m.Reg('vreset', initval=0)
122+
123+
m.Instance(madd, 'madd',
124+
ports=[ ('CLK', clk), ('RST', rst),
125+
('xd', xdin), ('xv', ivalid), ('yd', ydin), ('yv', ivalid),
126+
('zd', odata), ('zv', ovalid), ('vreset_data', 0), ('vreset', vreset) ])
127+
128+
read_count = m.TmpReg(32, initval=0)
129+
sum_value = m.TmpReg(datawidth, initval=0)
130+
sum_count = m.TmpReg(32, initval=0)
131+
132+
# main FSM
133+
fsm = FSM(m, 'fsm', clk, rst)
134+
135+
init = fsm.current()
136+
137+
# initial values
138+
fsm.add( xaddr(0-1), yaddr(0-1), zaddr(0-1), zwe(0),
139+
busy(0), vreset(1), ivalid(0),
140+
read_count(0), sum_value(0), sum_count(0) )
141+
142+
# start
143+
fsm.add( busy(1), vreset(0), cond=start )
144+
fsm.goto_next(cond=start)
145+
146+
comp = fsm.current()
147+
148+
# read data
149+
fsm.add( xaddr.inc(), yaddr.inc(), cond=read_count<n )
150+
fsm.add( ivalid(0), delay=1 )
151+
fsm.add( ivalid(1), delay=1, cond=read_count<n )
152+
fsm.add( read_count.inc(), cond=read_count<n )
153+
154+
# comp data
155+
fsm.add( sum_count.inc(), cond=ovalid )
156+
fsm.add( sum_value(odata), cond=ovalid )
157+
158+
# dump
159+
#fsm.add( Systask('display', 'xaddr=%10d yaddr=%10d', xaddr, yaddr) )
160+
#fsm.add( Systask('display', 'xdin =%10d ydin =%10d', xdin, ydin), delay=1 )
161+
#fsm.add( Systask('display', 'count=%10d odata=%10d', sum_count, odata), cond=ovalid )
162+
163+
fsm.goto_next(cond=sum_count==n)
164+
165+
# write data
166+
fsm.add( zaddr.inc() )
167+
fsm.add( zdout(sum_value), zwe(1) )
168+
fsm.add( zwe(0), delay=1 )
169+
170+
# set up for next
171+
fsm.add( yaddr(0-1), cond=yaddr==n*n-1 )
172+
fsm.add( xaddr(xaddr-n), cond=yaddr<n*n-1)
173+
fsm.add( read_count(0), sum_count(0) )
174+
175+
# reset pipeline
176+
fsm.add( vreset(1) )
177+
fsm.add( vreset(0), delay=1 )
178+
179+
done = (zaddr == n * n - 2)
180+
fsm.goto(comp, cond=Not(done))
181+
fsm.goto(init, cond=done)
182+
183+
fsm.make_always()
184+
185+
return m
186+
187+
def mkTest(n=16, datawidth=32):
188+
189+
m = Module('test')
190+
191+
addrwidth = int(math.log(n, 2)) * 2
192+
193+
# target instance
194+
main = mkMatmulBram(n, datawidth)
195+
196+
params = m.copy_params(main)
197+
ports = m.copy_sim_ports(main)
198+
199+
clk = ports['CLK']
200+
rst = ports['RST']
201+
202+
start = ports['start']
203+
busy = ports['busy']
204+
205+
uut = m.Instance(main, 'uut',
206+
params=m.connect_params(main),
207+
ports=m.connect_ports(main))
208+
209+
reset_done = m.Reg('reset_done', initval=0)
210+
reset_stmt = []
211+
reset_stmt.append( reset_done(0) )
212+
reset_stmt.append( start(0) )
213+
214+
for i in range(3):
215+
addr = ports['bram_addr%d' % i]
216+
din = ports['bram_din%d' % i]
217+
we = ports['bram_we%d' % i]
218+
dout = ports['bram_dout%d' % i]
219+
reset_stmt.append(addr(0))
220+
reset_stmt.append(din(0))
221+
reset_stmt.append(we(0))
222+
223+
simulation.setup_waveform(m, uut)
224+
simulation.setup_clock(m, clk, hperiod=5)
225+
init = simulation.setup_reset(m, rst, reset_stmt, period=100)
226+
227+
nclk = simulation.next_clock
228+
229+
init.add(
230+
Delay(1000),
231+
reset_done(1),
232+
nclk(clk),
233+
Delay(100000),
234+
Systask('finish'),
235+
)
236+
237+
fsm = FSM(m, 'fsm', clk, rst)
238+
239+
fsm.goto_next(cond=reset_done)
240+
241+
for i in range(3):
242+
addr = ports['bram_addr%d' % i]
243+
fsm.add( addr(-1) )
244+
245+
fsm.goto_next()
246+
247+
for i in range(3):
248+
addr = ports['bram_addr%d' % i]
249+
din = ports['bram_din%d' % i]
250+
we = ports['bram_we%d' % i]
251+
dout = ports['bram_dout%d' % i]
252+
next_addr = (addr+1) % (n*n)
253+
fsm.add( addr.inc() )
254+
#fsm.add( din(Mux(next_addr%n==next_addr/n, 1, 0)) )
255+
if i == 0:
256+
fsm.add( din(next_addr) )
257+
else:
258+
fsm.add( din(Mux(next_addr%n==next_addr/n, 1, 0)) )
259+
fsm.add( we(1) )
260+
fsm.add( we(0), cond=AndList(we, addr==2**addrwidth-1) )
261+
262+
fsm.goto_next(cond=AndList(we, ports['bram_addr0']==2**addrwidth-1))
263+
264+
fsm.goto_next(cond=Not(busy))
265+
266+
fsm.add( start(1) )
267+
fsm.add( start(0), delay=1 )
268+
fsm.goto_next()
269+
270+
fsm.goto_next(cond=busy)
271+
272+
fsm.goto_next(cond=Not(busy))
273+
274+
fsm.add( Systask('finish') )
275+
276+
fsm.make_always()
277+
278+
m.Always(Posedge(clk))(
279+
If(Scope(uut, 'zwe'))(
280+
Systask('display', 'zaddr=%10d zdout=%10d', Scope(uut, 'zaddr'), Scope(uut, 'zdout')),
281+
# If(AndList(Scope(uut, 'zaddr') % n == Scope(uut, 'zaddr') / n, Scope(uut, 'zdout') != 1))(
282+
# Systask('display', '## wrong')
283+
# ),
284+
# If(AndList(Scope(uut, 'zaddr') % n != Scope(uut, 'zaddr') / n, Scope(uut, 'zdout') != 0))(
285+
# Systask('display', '## wrong')
286+
# )
287+
If(Scope(uut, 'zaddr') != Scope(uut, 'zdout'))(
288+
Systask('display', '## wrong result')
289+
),
290+
)
291+
)
292+
293+
return m
294+
295+
if __name__ == '__main__':
296+
n = 16
297+
test = mkTest(n)
298+
verilog = test.to_verilog('tmp.v')
299+
#print(verilog)
300+
301+
# run simulator (Icarus Verilog)
302+
sim = simulation.Simulator(test)
303+
rslt = sim.run()
304+
print(rslt)
305+
306+
# only target RTL
307+
#main = mkMatmulBram(n)
308+
#verilog = main.to_verilog('tmp.v')
309+
#print(verilog)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from __future__ import absolute_import
2+
from __future__ import print_function
3+
import dataflow_matmul_bram
4+
5+
expected_verilog = """
6+
"""
7+
8+
def test():
9+
test_module = dataflow_matmul_bram.mkTest()
10+
code = test_module.to_verilog()
11+
12+
from pyverilog.vparser.parser import VerilogParser
13+
from pyverilog.ast_code_generator.codegen import ASTCodeGenerator
14+
parser = VerilogParser()
15+
expected_ast = parser.parse(expected_verilog)
16+
codegen = ASTCodeGenerator()
17+
expected_code = codegen.visit(expected_ast)
18+
19+
assert(expected_code == code)

0 commit comments

Comments
 (0)