Skip to content

Commit c72c355

Browse files
committed
stream.read_RAM with when condition.
1 parent 3398ae9 commit c72c355

File tree

5 files changed

+227
-10
lines changed

5 files changed

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

veriloggen/stream/stypes.py

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3169,11 +3169,17 @@ def _implement(self, m, seq, svalid=None, senable=None):
31693169
self.sig_data = data
31703170

31713171

3172-
class ReadRAM(_BinaryOperator):
3172+
class ReadRAM(_SpecialOperator):
31733173
latency = 3
31743174

3175-
def __init__(self, addr, reset, width=None, point=None, signed=True, ram_name=None):
3176-
_BinaryOperator.__init__(self, addr, reset)
3175+
def __init__(self, addr, reset, when=None,
3176+
width=None, point=None, signed=True, ram_name=None):
3177+
3178+
args = [addr, reset]
3179+
if when is not None:
3180+
args.append(when)
3181+
3182+
_SpecialOperator.__init__(self, *args)
31773183

31783184
if width is not None:
31793185
self.width = width
@@ -3191,6 +3197,9 @@ def _implement(self, m, seq, svalid=None, senable=None):
31913197
raise ValueError("Latency mismatch '%d' < '%s'" %
31923198
(self.latency, 2))
31933199

3200+
if len(self.args) == 3 and self.latency == 2:
3201+
raise ValueError('Output register is required for when option')
3202+
31943203
if senable is not None:
31953204
raise NotImplementedError('senable is not supported.')
31963205

@@ -3206,29 +3215,40 @@ def _implement(self, m, seq, svalid=None, senable=None):
32063215
elif self.latency == 3:
32073216
data = m.Reg(self.name('data'), datawidth, initval=0, signed=signed)
32083217
self.sig_data = data
3209-
seq(data(rdata), cond=senable)
3218+
when_cond = self.args[2].sig_data if len(self.args) == 3 else None
3219+
if when_cond is not None:
3220+
when_cond = seq.Prev(when_cond, 2)
3221+
enable = _and_vars(senable, when_cond)
3222+
seq(data(rdata), cond=enable)
32103223

32113224
else:
32123225
prev_data = None
32133226

3227+
when_cond_base = self.args[2].sig_data if len(self.args) == 3 else None
3228+
32143229
for i in range(self.latency - 2):
32153230
data = m.Reg(self.name('data_d%d' % i), datawidth,
32163231
initval=0, signed=signed)
3232+
if when_cond_base is not None:
3233+
when_cond = seq.Prev(when_cond, i + 2)
3234+
else:
3235+
when_cond = None
3236+
enable = _and_vars(senable, when_cond)
32173237
if i == 0:
3218-
seq(data(rdata), cond=senable)
3238+
seq(data(rdata), cond=enable)
32193239
else:
3220-
seq(data(prev_data), cond=senable)
3240+
seq(data(prev_data), cond=enable)
32213241
prev_data = data
32223242

32233243
self.sig_data = data
32243244

32253245
@property
32263246
def addr(self):
3227-
return self.left.sig_data
3247+
return self.args[0].sig_data
32283248

32293249
@property
32303250
def enable(self):
3231-
return vtypes.Not(self.right.sig_data)
3251+
return vtypes.Not(self.args[1].sig_data)
32323252

32333253

32343254
def make_condition(*cond, **kwargs):

veriloggen/thread/stream.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,9 @@ def substream(self, substrm):
336336
self.substreams.append(sub)
337337
return sub
338338

339-
def read_RAM(self, name, addr, datawidth=None, point=0, signed=True):
339+
def read_RAM(self, name, addr, when=None,
340+
datawidth=None, point=0, signed=True):
341+
340342
if self.stream_synthesized:
341343
raise ValueError(
342344
'cannot modify the stream because already synthesized')
@@ -356,7 +358,8 @@ def read_RAM(self, name, addr, datawidth=None, point=0, signed=True):
356358
if datawidth is None:
357359
datawidth = self.datawidth
358360

359-
var = self.ReadRAM(addr, width=datawidth, point=point, signed=signed, ram_name=name)
361+
var = self.ReadRAM(addr, when=when,
362+
width=datawidth, point=point, signed=signed, ram_name=name)
360363

361364
self.read_rams[name] = var
362365
self.var_id_map[_id] = var

0 commit comments

Comments
 (0)