Skip to content

Commit 9ffb388

Browse files
committed
sink immediate and stream with no sink size
1 parent 5e2c3c7 commit 9ffb388

File tree

4 files changed

+278
-6
lines changed

4 files changed

+278
-6
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_no_sink_size
7+
8+
9+
def test(request):
10+
veriloggen.reset()
11+
12+
simtype = request.config.getoption('--sim')
13+
14+
rslt = thread_stream_no_sink_size.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: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
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+
ram_c = vthread.RAM(m, 'ram_c', clk, rst, datawidth, addrwidth)
26+
27+
strm = vthread.Stream(m, 'mystream', clk, rst)
28+
a = strm.source('a')
29+
b = strm.source('b')
30+
c = a + b
31+
v = strm.Ands(c > 140, c < 150)
32+
cnt = strm.ReduceAdd(v)
33+
strm.sink(c, 'c', when=v, when_name='v')
34+
strm.sink(cnt, 'cnt')
35+
36+
def comp_stream(size, offset):
37+
strm.set_source('a', ram_a, offset, size)
38+
strm.set_source('b', ram_b, offset, size)
39+
strm.set_sink('c', ram_c, offset, 0) # max_size
40+
strm.set_sink_immediate('cnt', 0) # max_size
41+
strm.run()
42+
strm.join()
43+
cnt = strm.read_sink('cnt')
44+
print('# num of counted: %d' % cnt)
45+
return cnt
46+
47+
def comp_sequential(size, offset):
48+
sum = 0
49+
addr = 0
50+
for i in range(size):
51+
a = ram_a.read(i + offset)
52+
b = ram_b.read(i + offset)
53+
c = a + b
54+
if c > 140 and c < 150:
55+
ram_c.write(addr + offset, c)
56+
addr += 1
57+
print('# num of counted: %d' % addr)
58+
return addr
59+
60+
def check(size, offset_stream, offset_seq):
61+
all_ok = True
62+
for i in range(size):
63+
st = ram_c.read(i + offset_stream)
64+
sq = ram_c.read(i + offset_seq)
65+
if vthread.verilog.NotEql(st, sq):
66+
all_ok = False
67+
if all_ok:
68+
print('# verify: PASSED')
69+
else:
70+
print('# verify: FAILED')
71+
72+
def comp(size):
73+
# stream
74+
offset = 0
75+
myaxi.dma_read(ram_a, offset, 0, size)
76+
myaxi.dma_read(ram_b, offset, 512, size)
77+
cnt = comp_stream(size, offset)
78+
myaxi.dma_write(ram_c, offset, 1024, cnt)
79+
80+
# sequential
81+
offset = size
82+
myaxi.dma_read(ram_a, offset, 0, size)
83+
myaxi.dma_read(ram_b, offset, 512, size)
84+
cnt = comp_sequential(size, offset)
85+
myaxi.dma_write(ram_c, offset, 1024 * 2, cnt)
86+
87+
# verification
88+
check(cnt, 0, offset)
89+
90+
vthread.finish()
91+
92+
th = vthread.Thread(m, 'th_comp', clk, rst, comp)
93+
fsm = th.start(32)
94+
95+
return m
96+
97+
98+
def mkTest(memimg_name=None):
99+
m = Module('test')
100+
101+
# target instance
102+
led = mkLed()
103+
104+
# copy paras and ports
105+
params = m.copy_params(led)
106+
ports = m.copy_sim_ports(led)
107+
108+
clk = ports['CLK']
109+
rst = ports['RST']
110+
111+
memory = axi.AxiMemoryModel(m, 'memory', clk, rst, memimg_name=memimg_name)
112+
memory.connect(ports, 'myaxi')
113+
114+
uut = m.Instance(led, 'uut',
115+
params=m.connect_params(led),
116+
ports=m.connect_ports(led))
117+
118+
# simulation.setup_waveform(m, uut)
119+
simulation.setup_clock(m, clk, hperiod=5)
120+
init = simulation.setup_reset(m, rst, m.make_reset(), period=100)
121+
122+
init.add(
123+
Delay(1000000),
124+
Systask('finish'),
125+
)
126+
127+
return m
128+
129+
130+
def run(filename='tmp.v', simtype='iverilog', outputfile=None):
131+
132+
if outputfile is None:
133+
outputfile = os.path.splitext(os.path.basename(__file__))[0] + '.out'
134+
135+
memimg_name = 'memimg_' + outputfile
136+
137+
test = mkTest(memimg_name=memimg_name)
138+
139+
if filename is not None:
140+
test.to_verilog(filename)
141+
142+
sim = simulation.Simulator(test, sim=simtype)
143+
rslt = sim.run(outputfile=outputfile)
144+
lines = rslt.splitlines()
145+
if simtype == 'verilator' and lines[-1].startswith('-'):
146+
rslt = '\n'.join(lines[:-1])
147+
return rslt
148+
149+
150+
if __name__ == '__main__':
151+
rslt = run(filename='tmp.v')
152+
print(rslt)

veriloggen/thread/stream.py

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ class Stream(BaseStream):
4040
__intrinsics__ = ('set_source', 'set_source_pattern', 'set_source_multidim',
4141
'set_source_multipattern', 'set_source_empty',
4242
'set_sink', 'set_sink_pattern', 'set_sink_multidim',
43-
'set_sink_multipattern',
43+
'set_sink_multipattern', 'set_sink_immediate',
4444
'set_sink_empty', 'set_constant',
45+
'read_sink',
4546
'run', 'join', 'done',
4647
'source_join', 'source_done',
4748
'sink_join', 'sink_done')
@@ -76,8 +77,8 @@ def __init__(self, m, name, clk, rst,
7677
self.start = self.module.Reg(
7778
'_'.join(['', self.name, 'start']), initval=0)
7879

79-
self.end_flag = self.module.Reg(
80-
'_'.join(['', self.name, 'end_flag']), initval=0)
80+
self.term_sink = self.module.Reg(
81+
'_'.join(['', self.name, 'term_sink']), initval=0)
8182

8283
self.source_busy = self.module.Reg(
8384
'_'.join(['', self.name, 'source_busy']), initval=0)
@@ -785,6 +786,47 @@ def set_sink_multipattern(self, fsm, name, ram, offsets, patterns, port=0):
785786

786787
fsm.goto_next()
787788

789+
def set_sink_immediate(self, fsm, name, size):
790+
""" intrinsic method to set a sink stream as an immediate variable """
791+
792+
if not self.stream_synthesized:
793+
self._implement_stream()
794+
795+
if isinstance(name, str):
796+
var = self.var_name_map[name]
797+
elif isinstance(name, vtypes.Str):
798+
name = name.value
799+
var = self.var_name_map[name]
800+
elif isinstance(name, int):
801+
var = self.var_id_map[name]
802+
elif isinstance(name, vtypes.Int):
803+
name = name.value
804+
var = self.var_id_map[name]
805+
else:
806+
raise TypeError('Unsupported index name')
807+
808+
if name not in self.sinks:
809+
raise NameError("No such stream '%s'" % name)
810+
811+
set_cond = self._set_flag(fsm)
812+
start_delay = self._write_delay() - 1
813+
814+
self.seq.If(set_cond).Delay(start_delay).EagerVal()(
815+
var.sink_mode(mode_normal),
816+
var.sink_size(size)
817+
)
818+
819+
set_cond = self.seq.Prev(set_cond, start_delay)
820+
821+
ram_sel = var.sink_ram_sel
822+
self.seq.If(set_cond)(
823+
ram_sel(0) # '0' is reserved for empty
824+
)
825+
826+
self._synthesize_set_sink(var, name)
827+
828+
fsm.goto_next()
829+
788830
def set_sink_empty(self, fsm, name):
789831
""" intrinsic method to assign RAM property to a sink stream """
790832

@@ -853,6 +895,32 @@ def set_constant(self, fsm, name, value):
853895

854896
fsm.goto_next()
855897

898+
def read_sink(self, fsm, name):
899+
""" intrinsic method to read the last output of a sink stream """
900+
901+
if not self.stream_synthesized:
902+
self._implement_stream()
903+
904+
if isinstance(name, str):
905+
var = self.var_name_map[name]
906+
elif isinstance(name, vtypes.Str):
907+
name = name.value
908+
var = self.var_name_map[name]
909+
elif isinstance(name, int):
910+
var = self.var_id_map[name]
911+
elif isinstance(name, vtypes.Int):
912+
name = name.value
913+
var = self.var_id_map[name]
914+
else:
915+
raise TypeError('Unsupported index name')
916+
917+
if name not in self.sinks:
918+
raise NameError("No such stream '%s'" % name)
919+
920+
fsm.goto_next()
921+
922+
return var.sink_ram_wdata
923+
856924
def run(self, fsm):
857925
# entry point
858926
self.fsm._set_index(0)
@@ -1004,11 +1072,13 @@ def run(self, fsm):
10041072
self.sink_wait_count.inc()
10051073
)
10061074

1075+
pipeline_depth = self.pipeline_depth()
1076+
10071077
self.fsm.seq(
1008-
self.end_flag(0)
1078+
self.term_sink(0)
10091079
)
1010-
self.fsm.seq.If(self.seq.Prev(end_cond, num_wdelay))(
1011-
self.end_flag(1)
1080+
self.fsm.seq.If(self.seq.Prev(end_cond, pipeline_depth))(
1081+
self.term_sink(1)
10121082
)
10131083

10141084
self.fsm.goto_init()
@@ -1490,6 +1560,7 @@ def _synthesize_set_sink(self, var, name):
14901560
)
14911561

14921562
var.sink_fsm.If(wcond, var.sink_count == 1).goto_init()
1563+
var.sink_fsm.If(self.term_sink).goto_init()
14931564

14941565
def _make_sink_pattern_vars(self, var, name):
14951566
if var.sink_pat_cur_offsets is not None:
@@ -1614,6 +1685,7 @@ def _synthesize_set_sink_pattern(self, var, name):
16141685
fin_cond = upcond
16151686

16161687
var.sink_pat_fsm.If(fin_cond).goto_init()
1688+
var.sink_pat_fsm.If(self.term_sink).goto_init()
16171689

16181690
def _make_sink_multipattern_vars(self, var, name):
16191691
if var.sink_multipat_cur_offsets is not None:
@@ -1801,6 +1873,7 @@ def _synthesize_set_sink_multipattern(self, var, name):
18011873

18021874
var.sink_multipat_fsm.If(fin_cond,
18031875
var.sink_multipat_num_patterns == 0).goto_init()
1876+
var.sink_multipat_fsm.If(self.term_sink).goto_init()
18041877

18051878
def _set_flag(self, fsm, prefix='_set_flag'):
18061879
flag = self.module.TmpReg(initval=0, prefix=prefix)

0 commit comments

Comments
 (0)