1 from nmigen
import Signal
, Module
, Record
2 from nmigen
.back
.pysim
import Simulator
, Delay
3 from nmigen
.compat
.sim
import run_simulation
, Settle
4 from nmutil
.formaltest
import FHDLTestCase
5 from nmigen
.cli
import rtlil
7 from soc
.experiment
.pi2ls
import Pi2LSUI
8 from soc
.experiment
.lsmem
import TestMemLoadStoreUnit
9 from soc
.experiment
.pimem
import TestMemoryPortInterface
11 def wait_busy(port
, no
=False):
13 busy
= yield port
.pi
.busy_o
14 print("busy", no
, busy
)
22 addr_ok
= yield port
.pi
.addr_ok_o
23 print("addrok", addr_ok
)
31 ldok
= yield port
.pi
.ld
.ok
38 def l0_cache_st(dut
, addr
, data
, datalen
):
39 if isinstance(dut
.pi
, Record
):
44 # have to wait until not busy
45 yield from wait_busy(port1
, no
=False) # wait until not busy
47 # set up a ST on the port. address first:
48 yield port1
.pi
.is_st_i
.eq(1) # indicate ST
49 yield port1
.pi
.data_len
.eq(datalen
) # ST length (1/2/4/8)
51 yield port1
.pi
.addr
.data
.eq(addr
) # set address
52 yield port1
.pi
.addr
.ok
.eq(1) # set ok
54 yield from wait_addr(port1
) # wait until addr ok
55 # yield # not needed, just for checking
56 # yield # not needed, just for checking
57 # assert "ST" for one cycle (required by the API)
58 yield port1
.pi
.st
.data
.eq(data
)
59 yield port1
.pi
.st
.ok
.eq(1)
61 yield port1
.pi
.st
.ok
.eq(0)
63 # can go straight to reset.
64 yield port1
.pi
.is_st_i
.eq(0) # end
65 yield port1
.pi
.addr
.ok
.eq(0) # set !ok
66 # yield from wait_busy(port1, False) # wait until not busy
69 def l0_cache_ld(dut
, addr
, datalen
, expected
):
71 if isinstance(dut
.pi
, Record
):
76 # have to wait until not busy
77 yield from wait_busy(port1
, no
=False) # wait until not busy
79 # set up a LD on the port. address first:
80 yield port1
.pi
.is_ld_i
.eq(1) # indicate LD
81 yield port1
.pi
.data_len
.eq(datalen
) # LD length (1/2/4/8)
83 yield port1
.pi
.addr
.data
.eq(addr
) # set address
84 yield port1
.pi
.addr
.ok
.eq(1) # set ok
86 yield from wait_addr(port1
) # wait until addr ok
88 yield from wait_ldok(port1
) # wait until ld ok
89 data
= yield port1
.pi
.ld
.data
92 yield port1
.pi
.is_ld_i
.eq(0) # end
93 yield port1
.pi
.addr
.ok
.eq(0) # set !ok
94 # yield from wait_busy(port1, no=False) # wait until not busy
99 def l0_cache_ldst(arg
, dut
):
105 yield from l0_cache_st(dut
, 0x2, data
, 2)
106 yield from l0_cache_st(dut
, 0x4, data2
, 2)
107 result
= yield from l0_cache_ld(dut
, 0x2, 2, data
)
108 result2
= yield from l0_cache_ld(dut
, 0x4, 2, data2
)
109 arg
.assertEqual(data
, result
, "data %x != %x" % (result
, data
))
110 arg
.assertEqual(data2
, result2
, "data2 %x != %x" % (result2
, data2
))
114 class TestPIMem(unittest
.TestCase
):
116 def test_pi_mem(self
):
118 dut
= TestMemoryPortInterface(regwid
=64)
119 #vl = rtlil.convert(dut, ports=dut.ports())
120 #with open("test_basic_l0_cache.il", "w") as f:
123 run_simulation(dut
, {"sync": l0_cache_ldst(self
, dut
)},
124 vcd_name
='test_pi_mem_basic.vcd')
126 def test_pi2ls(self
):
130 m
.submodules
.dut
= dut
= Pi2LSUI("mem", regwid
=regwid
, addrwid
=addrwid
)
131 m
.submodules
.lsmem
= lsmem
= TestMemLoadStoreUnit(addr_wid
=addrwid
,
136 m
.d
.comb
+= [lsmem
.x_addr_i
.eq(dut
.lsui
.x_addr_i
),
137 lsmem
.x_mask_i
.eq(dut
.lsui
.x_mask_i
),
138 lsmem
.x_ld_i
.eq(dut
.lsui
.x_ld_i
),
139 lsmem
.x_st_i
.eq(dut
.lsui
.x_st_i
),
140 lsmem
.x_st_data_i
.eq(dut
.lsui
.x_st_data_i
),
141 lsmem
.x_stall_i
.eq(dut
.lsui
.x_stall_i
),
142 lsmem
.x_valid_i
.eq(dut
.lsui
.x_valid_i
),
143 lsmem
.m_stall_i
.eq(dut
.lsui
.m_stall_i
),
144 lsmem
.m_valid_i
.eq(dut
.lsui
.m_valid_i
)]
146 m
.d
.comb
+= [dut
.lsui
.x_busy_o
.eq(lsmem
.x_busy_o
),
147 dut
.lsui
.m_busy_o
.eq(lsmem
.m_busy_o
),
148 dut
.lsui
.m_ld_data_o
.eq(lsmem
.m_ld_data_o
),
149 dut
.lsui
.m_load_err_o
.eq(lsmem
.m_load_err_o
),
150 dut
.lsui
.m_store_err_o
.eq(lsmem
.m_store_err_o
),
151 dut
.lsui
.m_badaddr_o
.eq(lsmem
.m_badaddr_o
)]
153 run_simulation(m
, {"sync": l0_cache_ldst(self
, dut
)},
154 vcd_name
='test_pi2ls.vcd')
156 if __name__
== '__main__':
157 unittest
.main(exit
=False)