Skip to content

Commit 9f11af9

Browse files
committed
Merge branch 'feature_stream_split' into develop
2 parents 69143e2 + 0727017 commit 9f11af9

File tree

4 files changed

+278
-0
lines changed

4 files changed

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

veriloggen/stream/stypes.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,6 +1497,83 @@ def eval(self):
14971497
return Slice(var, msb, lsb)
14981498

14991499

1500+
def Split(data, width=None, point=None, signed=None, num_chunks=None):
1501+
"""
1502+
Split the given data into multiple chunks
1503+
1504+
Parameters
1505+
----------
1506+
data : _Numeric
1507+
Input data
1508+
1509+
width : int
1510+
Data width of separated chunks (default: same as input data)
1511+
1512+
point : int
1513+
Fixed-point position of separated chunks (default: same as input data)
1514+
1515+
signed : bool
1516+
Sign (default: same as input data)
1517+
1518+
num_chunks: int
1519+
The number of separated chunks (default: (input data width) / width)
1520+
1521+
Returns
1522+
-------
1523+
chunks : list
1524+
A list of separated chunks
1525+
1526+
For the consistency with Cat operator, the order of chunks is higher-bit first.
1527+
If data is a 32-bit value, and width is 8, returned list of chunks will be
1528+
chunks = [data[31:24], data[23:16], data[15:8], data[7:0]]
1529+
"""
1530+
1531+
data = _to_constant(data)
1532+
1533+
if width is None and num_chunks is None:
1534+
raise ValueError('width or num_chunks must be specified.')
1535+
1536+
if width is not None and num_chunks is not None:
1537+
raise ValueError('Either of width or num_chunks must be specified.')
1538+
1539+
if width is None:
1540+
width = int(ceil(data.bit_length() / num_chunks))
1541+
elif num_chunks is None:
1542+
num_chunks = int(ceil(data.bit_length() / width))
1543+
1544+
if point is None:
1545+
point = data.get_point()
1546+
1547+
if signed is None:
1548+
signed = data.get_signed()
1549+
1550+
total_width = width * num_chunks
1551+
ret = []
1552+
for i in range(0, total_width, width):
1553+
if i + width > data.bit_length():
1554+
if signed:
1555+
sign = data[-1]
1556+
sign.latency = 0
1557+
pad = Repeat(sign, total_width - data.bit_length())
1558+
pad.latency = 0
1559+
else:
1560+
pad = Int(0, signed=False)
1561+
pad.width = total_width - data.bit_length()
1562+
1563+
slc = Slice(data, data.bit_length() - 1, i)
1564+
slc.latency = 0
1565+
v = Cat(pad, slc)
1566+
v.latency = 0
1567+
else:
1568+
v = Slice(data, i + width - 1, i)
1569+
v.latency = 0
1570+
1571+
ret.append(Cast(v, width, point, signed))
1572+
1573+
ret.reverse()
1574+
return ret
1575+
1576+
15001577
class Cat(_SpecialOperator):
15011578

15021579
def __init__(self, *vars):

0 commit comments

Comments
 (0)