Skip to content

Commit

Permalink
Supporting the execution as software for veriloggen.thread methods. S…
Browse files Browse the repository at this point in the history
…ome intrinsic methods are also able to be executed as software.
  • Loading branch information
shtaxxx committed Aug 10, 2024
1 parent c47ce66 commit e9f2fd8
Show file tree
Hide file tree
Showing 22 changed files with 679 additions and 208 deletions.
3 changes: 2 additions & 1 deletion examples/thread_axi_slave_ipxact/thread_axi_slave_ipxact.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ def blink(size):
saxi.write(1, 0) # unset busy

th = vthread.Thread(m, 'th_blink', clk, rst, blink)
th.add_intrinsics(wait)
th.add_intrinsic(wait, 'wait')

fsm = th.start(16)

return m
Expand Down
29 changes: 29 additions & 0 deletions tests/extension/thread_/exec_as_sw/Makefile
Original file line number Diff line number Diff line change
@@ -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 *.vcd
18 changes: 18 additions & 0 deletions tests/extension/thread_/exec_as_sw/test_thread_exec_as_sw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from __future__ import absolute_import
from __future__ import print_function

import os
import veriloggen
import thread_exec_as_sw


def test(request):
veriloggen.reset()

simtype = request.config.getoption('--sim')

rslt = thread_exec_as_sw.run(filename=None, simtype=simtype,
outputfile=os.path.splitext(os.path.basename(__file__))[0] + '.out')

verify_rslt = [line for line in rslt.splitlines() if line.startswith('# verify:')][0]
assert(verify_rslt == '# verify: PASSED')
120 changes: 120 additions & 0 deletions tests/extension/thread_/exec_as_sw/thread_exec_as_sw.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
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


def mkLed():
m = Module('blinkled')
clk = m.Input('CLK')
rst = m.Input('RST')
led = m.OutputReg('LED', 8, initval=0)

datawidth = 32
addrwidth = 10
myram = vthread.RAM(m, 'myram', clk, rst, datawidth, addrwidth)

def blink(times):
all_ok = True

write_sum = 0
for i in range(times):
wdata = i
myram.write(i, wdata)
write_sum += wdata
print('wdata = %d' % wdata)

read_sum = 0
for i in range(times):
rdata = myram.read(i)
read_sum += rdata
print('rdata = %d' % rdata)
#if vthread.verilog.NotEql(rdata, i):
if rdata != i:
all_ok = False

print('read_sum = %d' % read_sum)

#if vthread.verilog.NotEql(read_sum, write_sum):
if read_sum != write_sum:
all_ok = False

led.value = 0
for i in range(times):
led.value += 1
print(led, i)

if all_ok and led == times:
print('# verify: PASSED')
else:
print('# verify: FAILED')

# as SW
print("as SW")
blink(100)

print("as HW")

# as HW
th = vthread.Thread(m, 'th_blink', clk, rst, blink)
fsm = th.start(100)

return m


def mkTest():
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']

uut = m.Instance(led, 'uut',
params=m.connect_params(led),
ports=m.connect_ports(led))

# vcd_name = os.path.splitext(os.path.basename(__file__))[0] + '.vcd'
# simulation.setup_waveform(m, uut, dumpfile=vcd_name)
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'

test = mkTest()

if filename is not None:
test.to_verilog(filename)

sim = simulation.Simulator(test, sim=simtype)
rslt = sim.run(outputfile=outputfile)

return rslt


if __name__ == '__main__':
rslt = run(filename='tmp.v')
print(rslt)
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ def blink(times):

th = vthread.Thread(m, 'th_blink', clk, rst, blink)

# add intrinsics
th.add_intrinsics(send, wait)
# add intrinsic functions
th.add_intrinsic(send, 'send')
th.add_intrinsic(wait, 'wait')

fsm = th.start(10)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ def blink(times):

th = vthread.Thread(m, 'th_blink', clk, rst, blink)

# add intrinsics
th.add_intrinsics(send, wait)
# add intrinsic functions
th.add_intrinsic(send, 'send')
th.add_intrinsic(wait, 'wait')

fsm = th.start(10)

Expand Down
14 changes: 10 additions & 4 deletions veriloggen/stream/stypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4421,7 +4421,7 @@ def _implement(self, m, seq, svalid=None, senable=None):


class FromExtern(_UnaryOperator):
__intrinsics__ = ('write')
__intrinsics__ = {'write': '_intrinsic_write'}
latency = 1

def __init__(self, right, width=None, point=None, signed=True, latency=1):
Expand Down Expand Up @@ -4458,13 +4458,16 @@ def _implement(self, m, seq, svalid=None, senable=None):
data = fx.FixedReg(m, self.name('data'), width, point, initval=0, signed=signed)
self.sig_data = data

def write(self, fsm, value):
def _intrinsic_write(self, fsm, value):
cond = fsm.here

self.seq.If(cond)(
self.sig_data(value)
)

def write(self, value):
raise NotImplementedError("only intrinsic method is implemented.")


class _LineBufferOut(_UnaryOperator):
latency = 1
Expand Down Expand Up @@ -4766,20 +4769,23 @@ def _implement(self, m, seq, svalid=None, senable=None):


class Reg(Predicate):
__intrinsics__ = ('write')
__intrinsics__ = {'write': '_intrinsic_write'}

def __init__(self, data, when=None):
Predicate.__init__(self, data, when)
self.graph_label = 'Reg'
self.graph_shape = 'box'

def write(self, fsm, value):
def _intrinsic_write(self, fsm, value):
cond = fsm.here

self.seq.If(cond)(
self.sig_data(value)
)

def write(self, value):
raise NotImplementedError("only intrinsic method is implemented.")


class ReadRAM(_SpecialOperator):
latency = 1
Expand Down
6 changes: 3 additions & 3 deletions veriloggen/thread/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@

from . import fixed

__intrinsics__ = []
__intrinsics__.extend(__ttypes_intrinsics__)
__intrinsics__.extend(__util_intrinsics__)
__intrinsics__ = {}
__intrinsics__.update(__ttypes_intrinsics__)
__intrinsics__.update(__util_intrinsics__)
55 changes: 37 additions & 18 deletions veriloggen/thread/axim.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,34 @@
class AXIM(axi.AxiMaster, _MutexFunction):
""" AXI Master Interface with DMA controller """

__intrinsics__ = ('read', 'write', 'write_fence',
'dma_read', 'dma_read_async',
'dma_write', 'dma_write_async',
'dma_read_bank', 'dma_read_bank_async',
'dma_write_bank', 'dma_write_bank_async',
'dma_read_block', 'dma_read_block_async',
'dma_write_block', 'dma_write_block_async',
'dma_read_packed', 'dma_read_packed_async',
'dma_write_packed', 'dma_write_packed_async',
'dma_read_bcast', 'dma_read_bcast_async',
'dma_wait_read', 'dma_wait_write',
'dma_wait_write_idle', 'dma_wait_write_response',
'dma_wait',
'set_global_base_addr',) + _MutexFunction.__intrinsics__
__intrinsics__ = {'read': 'read',
'write': 'write',
'write_fence': 'write_fence',
'dma_read': 'dma_read',
'dma_read_async': 'dma_read_async',
'dma_write': 'dma_write',
'dma_write_async': 'dma_write_async',
'dma_read_bank': 'dma_read_bank',
'dma_read_bank_async': 'dma_read_bank_async',
'dma_write_bank': 'dma_write_bank',
'dma_write_bank_async': 'dma_write_bank_async',
'dma_read_block': 'dma_read_block',
'dma_read_block_async': 'dma_read_block_async',
'dma_write_block': 'dma_write_block',
'dma_write_block_async': 'dma_write_block_async',
'dma_read_packed': 'dma_read_packed',
'dma_read_packed_async': 'dma_read_packed_async',
'dma_write_packed': 'dma_write_packed',
'dma_write_packed_async': 'dma_write_packed_async',
'dma_read_bcast': 'dma_read_bcast',
'dma_read_bcast_async': 'dma_read_bcast_async',
'dma_wait_read': 'dma_wait_read',
'dma_wait_write': 'dma_wait_write',
'dma_wait_write_idle': 'dma_wait_write_idle',
'dma_wait_write_response': 'dma_wait_write_response',
'dma_wait': 'dma_wait',
'set_global_base_addr': 'set_global_base_addr',
} | _MutexFunction.__intrinsics__

def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32,
waddr_id_width=0, wdata_id_width=0, wresp_id_width=0,
Expand Down Expand Up @@ -1709,7 +1723,8 @@ def unpack_write_req(self, v):


class AXIMVerify(AXIM):
__intrinsics__ = ('read_delayed', 'write_delayed') + AXIM.__intrinsics__
__intrinsics__ = {'read_delayed': 'read_delayed',
'write_delayed': 'write_delayed'} | AXIM.__intrinsics__

def read_delayed(self, fsm, global_addr, delay):
if self.use_global_base_addr:
Expand Down Expand Up @@ -1803,8 +1818,11 @@ def write_delayed(self, fsm, global_addr, value, delay):
class AXIMLite(axi.AxiLiteMaster, _MutexFunction):
""" AXI-Lite Master Interface """

__intrinsics__ = ('read', 'write', 'write_fence',
'set_global_base_addr',) + _MutexFunction.__intrinsics__
__intrinsics__ = {'read': 'read',
'write': 'write',
'write_fence': 'write_fence',
'set_global_base_addr': 'set_global_base_addr'
} | _MutexFunction.__intrinsics__

def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32,
waddr_cache_mode=axi.AxCACHE_NONCOHERENT, raddr_cache_mode=axi.AxCACHE_NONCOHERENT,
Expand Down Expand Up @@ -1897,7 +1915,8 @@ def set_global_base_addr(self, fsm, addr):


class AXIMLiteVerify(AXIMLite):
__intrinsics__ = ('read_delayed', 'write_delayed') + AXIMLite.__intrinsics__
__intrinsics__ = {'read_delayed': 'read_delayed',
'write_delayed': 'write_delayed'} | AXIMLite.__intrinsics__

def read_delayed(self, fsm, global_addr, delay):
if self.use_global_base_addr:
Expand Down
16 changes: 12 additions & 4 deletions veriloggen/thread/axis.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,12 @@ def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32,


class AXISRegister(AXIS):
__intrinsics__ = ('read', 'write', 'write_flag', 'wait',
'wait_flag') + _MutexFunction.__intrinsics__
__intrinsics__ = {'read': 'read',
'write': 'write',
'write_flag': 'write_flag',
'wait': 'wait',
'wait_flag': 'wait_flag',
} | _MutexFunction.__intrinsics__

def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32,
waddr_id_width=0, wdata_id_width=0, wresp_id_width=0,
Expand Down Expand Up @@ -242,8 +246,12 @@ def wait_flag(self, fsm, addr, value, resetvalue=0, polarity=True):


class AXISLiteRegister(AXISLite):
__intrinsics__ = ('read', 'write', 'write_flag', 'wait',
'wait_flag') + _MutexFunction.__intrinsics__
__intrinsics__ = {'read': 'read',
'write': 'write',
'write_flag': 'write_flag',
'wait': 'wait',
'wait_flag': 'wait_flag',
} | _MutexFunction.__intrinsics__

def __init__(self, m, name, clk, rst, datawidth=32, addrwidth=32,
noio=False, length=4, fsm_as_module=False):
Expand Down
Loading

0 comments on commit e9f2fd8

Please sign in to comment.