From c8fa8625af56d74f35af6e1e7d6151db8d3951da Mon Sep 17 00:00:00 2001 From: shtaxxx Date: Wed, 21 Apr 2021 00:03:33 +0900 Subject: [PATCH 1/2] rc-1.8.6 --- veriloggen/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/veriloggen/VERSION b/veriloggen/VERSION index 8decb929..f263cd11 100644 --- a/veriloggen/VERSION +++ b/veriloggen/VERSION @@ -1 +1 @@ -1.8.5 +1.8.6 From 7502afc393dfad4d8f0a9e923f61ec883bb2aba6 Mon Sep 17 00:00:00 2001 From: shtaxxx Date: Wed, 21 Apr 2021 00:51:34 +0900 Subject: [PATCH 2/2] 1.8.7-rc --- .../Makefile | 29 +++ ..._multiport_memorymodel_split_read_write.py | 18 ++ ..._multiport_memorymodel_split_read_write.py | 220 ++++++++++++++++++ veriloggen/VERSION | 2 +- veriloggen/types/axi.py | 45 ++++ 5 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 tests/extension/thread_/multiport_memorymodel_split_read_write/Makefile create mode 100644 tests/extension/thread_/multiport_memorymodel_split_read_write/test_thread_multiport_memorymodel_split_read_write.py create mode 100644 tests/extension/thread_/multiport_memorymodel_split_read_write/thread_multiport_memorymodel_split_read_write.py diff --git a/tests/extension/thread_/multiport_memorymodel_split_read_write/Makefile b/tests/extension/thread_/multiport_memorymodel_split_read_write/Makefile new file mode 100644 index 00000000..13c4fb29 --- /dev/null +++ b/tests/extension/thread_/multiport_memorymodel_split_read_write/Makefile @@ -0,0 +1,29 @@ +TARGET=$(shell ls *.py | grep -v test | grep -v parsetab.py) +ARGS= + +PYTHON=python3 +#PYTHON=python +#OPT=-m pdb +#OPT=-m cProfile -s time +#OPT=-m cProfile -o profile.rslt + +.PHONY: all +all: test + +.PHONY: run +run: + $(PYTHON) $(OPT) $(TARGET) $(ARGS) + +.PHONY: test +test: + $(PYTHON) -m pytest -vv + +.PHONY: check +check: + $(PYTHON) $(OPT) $(TARGET) $(ARGS) > tmp.v + iverilog -tnull -Wall tmp.v + rm -f tmp.v + +.PHONY: clean +clean: + rm -rf *.pyc __pycache__ parsetab.py .cache *.out *.png *.dot tmp.v uut.vcd diff --git a/tests/extension/thread_/multiport_memorymodel_split_read_write/test_thread_multiport_memorymodel_split_read_write.py b/tests/extension/thread_/multiport_memorymodel_split_read_write/test_thread_multiport_memorymodel_split_read_write.py new file mode 100644 index 00000000..30a324c5 --- /dev/null +++ b/tests/extension/thread_/multiport_memorymodel_split_read_write/test_thread_multiport_memorymodel_split_read_write.py @@ -0,0 +1,18 @@ +from __future__ import absolute_import +from __future__ import print_function + +import os +import veriloggen +import thread_multiport_memorymodel_split_read_write + + +def test(request): + veriloggen.reset() + + simtype = request.config.getoption('--sim') + + rslt = thread_multiport_memorymodel_split_read_write.run(filename=None, simtype=simtype, + outputfile=os.path.splitext(os.path.basename(__file__))[0] + '.out') + + verify_rslt = rslt.splitlines()[-1] + assert(verify_rslt == '# verify: PASSED') diff --git a/tests/extension/thread_/multiport_memorymodel_split_read_write/thread_multiport_memorymodel_split_read_write.py b/tests/extension/thread_/multiport_memorymodel_split_read_write/thread_multiport_memorymodel_split_read_write.py new file mode 100644 index 00000000..3df95e1d --- /dev/null +++ b/tests/extension/thread_/multiport_memorymodel_split_read_write/thread_multiport_memorymodel_split_read_write.py @@ -0,0 +1,220 @@ +from __future__ import absolute_import +from __future__ import print_function +import sys +import os + +# the next line can be removed after installation +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname( + os.path.dirname(os.path.dirname(os.path.abspath(__file__))))))) + +from veriloggen import * +import veriloggen.thread as vthread +import veriloggen.types.axi as axi + + +def mkLed(): + m = Module('blinkled') + clk = m.Input('CLK') + rst = m.Input('RST') + + datawidth = 32 + addrwidth = 10 + + # With async DMA, set enable_async = True + myaxi = vthread.AXIM(m, 'myaxi', clk, rst, datawidth, enable_async=True) + # If RAM is simultaneously accesseed with DMA, numports must be 2 or more. + myram = vthread.RAM(m, 'myram', clk, rst, datawidth, addrwidth, numports=2) + + saxi = vthread.AXISLiteRegister(m, 'saxi', clk, rst, datawidth) + + all_ok = m.TmpReg(initval=0) + + def blink(size): + # wait start + saxi.wait_flag(0, value=1, resetvalue=0) + # reset done + saxi.write(1, 0) + + all_ok.value = True + + for i in range(4): + print('# iter %d start' % i) + # Test for 4KB boundary check + offset = i * 1024 * 16 + (myaxi.boundary_size - 4) + body(size, offset) + print('# iter %d end' % i) + + if all_ok: + print('# verify (local): PASSED') + else: + print('# verify (local): FAILED') + + # result + saxi.write(2, all_ok) + + # done + saxi.write_flag(1, 1, resetvalue=0) + + def body(size, offset): + # write + for i in range(size): + wdata = i + 100 + myram.write(i, wdata) + + w_laddr = 0 + w_gaddr = offset + # If RAM is simultaneously accesseed with DMA, different port must be + # used. + myaxi.dma_write_async(myram, w_laddr, w_gaddr, size, port=1) + print('dma_write_async: [%d] -> [%d]' % (w_laddr, w_gaddr)) + + # write + for i in range(size): + wdata = i + 1000 + myram.write(i + size, wdata) + + myaxi.dma_wait_write() + print('dma_wait_write : [%d] -> [%d]' % (w_laddr, w_gaddr)) + + w_laddr = size + w_gaddr = (size + size) * 4 + offset + myaxi.dma_write_async(myram, w_laddr, w_gaddr, size, port=1) + print('dma_write_async: [%d] -> [%d]' % (w_laddr, w_gaddr)) + + # read + r_laddr = 0 + r_gaddr = offset + myaxi.dma_read_async(myram, r_laddr, r_gaddr, size, port=0) + print('dma_read_async : [%d] <- [%d]' % (r_laddr, r_gaddr)) + + for sleep in range(size): + pass + + myaxi.dma_wait_write() + print('dma_wait_write : [%d] -> [%d]' % (w_laddr, w_gaddr)) + + myaxi.dma_wait_read() + print('dma_wait_read : [%d] <- [%d]' % (r_laddr, r_gaddr)) + + for i in range(size): + rdata = myram.read(i) + if vthread.verilog.NotEql(rdata, i + 100): + print('rdata[%d] = %d' % (i, rdata)) + all_ok.value = False + + # read + r_laddr = 0 + r_gaddr = (size + size) * 4 + offset + myaxi.dma_read(myram, r_laddr, r_gaddr, size, port=0) + print('dma_read : [%d] <- [%d]' % (r_laddr, r_gaddr)) + + for sleep in range(size): + pass + + for i in range(size): + rdata = myram.read(i) + if vthread.verilog.NotEql(rdata, i + 1000): + print('rdata[%d] = %d' % (i, rdata)) + all_ok.value = False + + th = vthread.Thread(m, 'th_blink', clk, rst, blink) + fsm = th.start(32) + + return m + + +def mkTest(memimg_name=None): + m = Module('test') + + # target instance + led = mkLed() + + # copy paras and ports + params = m.copy_params(led) + ports = m.copy_sim_ports(led) + + clk = ports['CLK'] + rst = ports['RST'] + + memory = axi.AxiMultiportMemoryModel(m, 'memory', clk, rst, numports=2, + memimg_name=memimg_name) + + r_ports, w_ports = axi.split_read_write(m, ports, 'myaxi') + + memory.connect(0, r_ports, 'r_myaxi') + memory.connect(1, w_ports, 'w_myaxi') + + # AXI-Slave controller + _saxi = vthread.AXIMLite(m, '_saxi', clk, rst, noio=True) + _saxi.connect(ports, 'saxi') + + def ctrl(): + for i in range(100): + pass + + for i in range(16): + # byte addressing + v = memory.read(i * 4) + print('read: mem[%d] -> %x' % (i, v)) + v = v + 1024 + # byte addressing + memory.write(i * 4, v) + print('write: mem[%d] <- %x' % (i, v)) + + awaddr = 0 + _saxi.write(awaddr, 1) + + araddr = 4 + v = _saxi.read(araddr) + while v == 0: + v = _saxi.read(araddr) + + araddr = 8 + v = _saxi.read(araddr) + if v: + print('# verify: PASSED') + else: + print('# verify: FAILED') + + th = vthread.Thread(m, 'th_ctrl', clk, rst, ctrl) + fsm = th.start() + + uut = m.Instance(led, 'uut', + params=m.connect_params(led), + ports=m.connect_ports(led)) + + # simulation.setup_waveform(m, uut) + simulation.setup_clock(m, clk, hperiod=5) + init = simulation.setup_reset(m, rst, m.make_reset(), period=100) + + init.add( + Delay(1000000), + Systask('finish'), + ) + + return m + + +def run(filename='tmp.v', simtype='iverilog', outputfile=None): + + if outputfile is None: + outputfile = os.path.splitext(os.path.basename(__file__))[0] + '.out' + + memimg_name = 'memimg_' + outputfile + + test = mkTest(memimg_name=memimg_name) + + if filename is not None: + test.to_verilog(filename) + + sim = simulation.Simulator(test, sim=simtype) + rslt = sim.run(outputfile=outputfile) + lines = rslt.splitlines() + if simtype == 'verilator' and lines[-1].startswith('-'): + rslt = '\n'.join(lines[:-1]) + return rslt + + +if __name__ == '__main__': + rslt = run(filename='tmp.v') + print(rslt) diff --git a/veriloggen/VERSION b/veriloggen/VERSION index f263cd11..88d3ee79 100644 --- a/veriloggen/VERSION +++ b/veriloggen/VERSION @@ -1 +1 @@ -1.8.6 +1.8.7 diff --git a/veriloggen/types/axi.py b/veriloggen/types/axi.py index 2f235fec..b8819b54 100644 --- a/veriloggen/types/axi.py +++ b/veriloggen/types/axi.py @@ -3831,3 +3831,48 @@ def align(src, num_align_words): offset += res return ret + + +def split_read_write(m, ports, prefix, + read_prefix='r_', write_prefix='w_'): + + # Read (AR, R) + r_ports = {} + for name, port in ports.items(): + r_name = read_prefix + port.name + + if name.startswith(prefix + '_ar') or name.startswith(prefix + '_r'): + if isinstance(port, vtypes.Reg): + r_port = m.RegLike(port, name=r_name) + port.connect(r_port) + else: + r_port = m.WireLike(port, name=r_name) + r_port.connect(port) + else: + r_port = m.WireLike(port, name=r_name) + if isinstance(port, vtypes.Wire): + r_port.assign(0) + + r_ports[r_name] = r_port + + # Write (AW, W, B) + w_ports = {} + for name, port in ports.items(): + w_name = write_prefix + port.name + + if (name.startswith(prefix + '_aw') or + name.startswith(prefix + '_w') or name.startswith(prefix + '_b')): + if isinstance(port, vtypes.Reg): + w_port = m.RegLike(port, name=w_name) + port.connect(w_port) + else: + w_port = m.WireLike(port, name=w_name) + w_port.connect(port) + else: + w_port = m.WireLike(port, name=w_name) + if isinstance(port, vtypes.Wire): + w_port.assign(0) + + w_ports[w_name] = w_port + + return r_ports, w_ports