Skip to content

Commit 6372c5e

Browse files
committed
Merge branch 'feature_multicycle' into develop
2 parents 8b1aefa + b5e6609 commit 6372c5e

File tree

6 files changed

+389
-2
lines changed

6 files changed

+389
-2
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: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from __future__ import absolute_import
2+
from __future__ import print_function
3+
4+
import os
5+
import veriloggen
6+
import thread_stream_producer_consumer
7+
8+
9+
def test(request):
10+
veriloggen.reset()
11+
12+
simtype = request.config.getoption('--sim')
13+
14+
rslt = thread_stream_producer_consumer.run(filename=None, simtype=simtype,
15+
outputfile=os.path.splitext(os.path.basename(__file__))[0] + '.out')
16+
17+
verify_rslt = rslt.splitlines()[-1]
18+
assert(verify_rslt == '# verify: PASSED')
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
from __future__ import absolute_import
2+
from __future__ import print_function
3+
import sys
4+
import os
5+
6+
# the next line can be removed after installation
7+
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(
8+
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))))
9+
10+
from veriloggen import *
11+
import veriloggen.thread as vthread
12+
import veriloggen.types.axi as axi
13+
14+
15+
def mkLed():
16+
m = Module('blinkled')
17+
clk = m.Input('CLK')
18+
rst = m.Input('RST')
19+
20+
datawidth = 32
21+
addrwidth = 10
22+
myaxi = vthread.AXIM(m, 'myaxi', clk, rst, datawidth)
23+
ram_a = vthread.RAM(m, 'ram_a', clk, rst, datawidth, addrwidth)
24+
ram_b = vthread.RAM(m, 'ram_b', clk, rst, datawidth, addrwidth)
25+
26+
# argmax
27+
argmaxstrm = vthread.Stream(m, 'argmax_stream', clk, rst)
28+
29+
argmax_a = argmaxstrm.source('a')
30+
argmax_a_index = argmaxstrm.source('a_index')
31+
32+
current_index = argmaxstrm.Consumer(initval=0)
33+
current_max = argmaxstrm.Consumer(initval=-1 * 2 ** 31)
34+
35+
compare = current_max < argmax_a
36+
compare.latency = 0
37+
38+
next_index = argmaxstrm.Mux(compare, argmax_a_index, current_index)
39+
next_index.latency = 0
40+
41+
next_max = argmaxstrm.Mux(compare, argmax_a, current_max)
42+
next_max.latency = 0
43+
44+
argmaxstrm.Producer(current_index, next_index)
45+
out_index = next_index
46+
47+
argmaxstrm.Producer(current_max, next_max)
48+
49+
argmaxstrm.sink(out_index, 'index')
50+
51+
# main
52+
strm = vthread.Stream(m, 'mystream', clk, rst)
53+
54+
a = strm.source('a')
55+
size = strm.parameter('size')
56+
a_index = strm.Counter(size=size)
57+
58+
sub = strm.substream_multicycle(argmaxstrm)
59+
sub.to_source('a', a)
60+
sub.to_source('a_index', a_index)
61+
index = sub.from_sink('index')
62+
valid = a_index == size - 1
63+
64+
strm.sink(index, 'index', when=valid, when_name='vailid')
65+
66+
def comp_stream(size, offset):
67+
strm.set_source('a', ram_a, offset, size)
68+
strm.set_parameter('size', size)
69+
strm.set_sink('index', ram_b, offset, 1)
70+
strm.run()
71+
strm.join()
72+
73+
def comp_sequential(size, offset):
74+
index = 0
75+
_max = 0
76+
for i in range(size):
77+
a = ram_a.read(i + offset)
78+
if a > _max:
79+
index = i
80+
_max = a
81+
ram_b.write(offset, index)
82+
83+
def check(size, offset_stream, offset_seq):
84+
all_ok = True
85+
for i in range(size):
86+
st = ram_b.read(i + offset_stream)
87+
sq = ram_b.read(i + offset_seq)
88+
if vthread.verilog.NotEql(st, sq):
89+
all_ok = False
90+
if all_ok:
91+
print('# verify: PASSED')
92+
else:
93+
print('# verify: FAILED')
94+
95+
def comp(size):
96+
offset = 0
97+
myaxi.dma_read(ram_a, offset, 0, size)
98+
ram_a.write(offset + 3, -100)
99+
ram_a.write(offset + 7, 200)
100+
comp_stream(size, offset)
101+
myaxi.dma_write(ram_b, offset, 1024, 1)
102+
103+
offset = size
104+
myaxi.dma_read(ram_a, offset, 0, size)
105+
ram_a.write(offset + 3, -100)
106+
ram_a.write(offset + 7, 200)
107+
comp_sequential(size, offset)
108+
myaxi.dma_write(ram_b, offset, 1024 * 2, 1)
109+
110+
check(1, 0, offset)
111+
112+
vthread.finish()
113+
114+
th = vthread.Thread(m, 'th_comp', clk, rst, comp)
115+
fsm = th.start(32)
116+
117+
return m
118+
119+
120+
def mkTest(memimg_name=None):
121+
m = Module('test')
122+
123+
# target instance
124+
led = mkLed()
125+
126+
# copy paras and ports
127+
params = m.copy_params(led)
128+
ports = m.copy_sim_ports(led)
129+
130+
clk = ports['CLK']
131+
rst = ports['RST']
132+
133+
memory = axi.AxiMemoryModel(m, 'memory', clk, rst, memimg_name=memimg_name)
134+
memory.connect(ports, 'myaxi')
135+
136+
uut = m.Instance(led, 'uut',
137+
params=m.connect_params(led),
138+
ports=m.connect_ports(led))
139+
140+
# simulation.setup_waveform(m, uut)
141+
simulation.setup_clock(m, clk, hperiod=5)
142+
init = simulation.setup_reset(m, rst, m.make_reset(), period=100)
143+
144+
init.add(
145+
Delay(1000000),
146+
Systask('finish'),
147+
)
148+
149+
return m
150+
151+
152+
def run(filename='tmp.v', simtype='iverilog', outputfile=None):
153+
154+
if outputfile is None:
155+
outputfile = os.path.splitext(os.path.basename(__file__))[0] + '.out'
156+
157+
memimg_name = 'memimg_' + outputfile
158+
159+
test = mkTest(memimg_name=memimg_name)
160+
161+
if filename is not None:
162+
test.to_verilog(filename)
163+
164+
sim = simulation.Simulator(test, sim=simtype)
165+
rslt = sim.run(outputfile=outputfile)
166+
lines = rslt.splitlines()
167+
if simtype == 'verilator' and lines[-1].startswith('-'):
168+
rslt = '\n'.join(lines[:-1])
169+
return rslt
170+
171+
172+
if __name__ == '__main__':
173+
rslt = run(filename='tmp.v')
174+
print(rslt)

veriloggen/stream/graph.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,56 @@ def visit_ForwardSource(self, node):
342342
self._add_output(node, prev)
343343
return prev
344344

345+
def visit_Consumer(self, node):
346+
label = self._get_label(node)
347+
shape = self._get_shape(node)
348+
color = self._get_color(node)
349+
style = self._get_style(node)
350+
peripheries = self._get_peripheries(node)
351+
self.graph.add_node(node,
352+
label=label, shape=shape,
353+
color=color, style=style,
354+
peripheries=peripheries)
355+
356+
initval = self.visit(node.args[0])
357+
self.graph.add_edge(initval, node, label='initval')
358+
359+
if node.start_stage is not None:
360+
self._set_rank(node.start_stage + 1, node)
361+
362+
prev = self._add_gap(node, label)
363+
self._add_output(node, prev)
364+
return prev
365+
366+
def visit_Producer(self, node):
367+
label = self._get_label(node)
368+
shape = self._get_shape(node)
369+
color = self._get_color(node)
370+
style = self._get_style(node)
371+
peripheries = self._get_peripheries(node)
372+
self.graph.add_node(node,
373+
label=label, shape=shape,
374+
color=color, style=style,
375+
peripheries=peripheries)
376+
377+
dest = self.visit(node.dest)
378+
self.graph.add_edge(node, dest, label='dest')
379+
value = self.visit(node.args[0])
380+
self.graph.add_edge(value, node, label='value')
381+
if node.when_index > 0:
382+
when = self.visit(node.args[node.when_index])
383+
self.graph.add_edge(when, node, label='when')
384+
if node.reset_index > 0:
385+
reset = self.visit(node.args[node.reset_index])
386+
self.graph.add_edge(reset, node, label='reset')
387+
388+
if node.start_stage is not None:
389+
self._set_rank(node.start_stage + 1, node)
390+
391+
prev = self._add_gap(node, label)
392+
self._add_output(node, prev)
393+
return prev
394+
345395
def visit_ReadRAM(self, node):
346396
label = self._get_label(node)
347397
shape = self._get_shape(node)

0 commit comments

Comments
 (0)