fix TestMemLoadStoreUnit, it required a FSM to monitor write
[soc.git] / src / soc / config / test / test_pi2ls.py
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
6 import unittest
7 from soc.config.test.test_loadstore import TestMemPspec
8 from soc.config.loadstore import ConfigMemoryPortInterface
9
10
11 def wait_busy(port, no=False):
12 while True:
13 busy = yield port.pi.busy_o
14 print("busy", no, busy)
15 if bool(busy) == no:
16 break
17 yield
18
19
20 def wait_addr(port):
21 while True:
22 addr_ok = yield port.pi.addr_ok_o
23 print("addrok", addr_ok)
24 if addr_ok:
25 break
26 yield
27
28
29 def wait_ldok(port):
30 while True:
31 ldok = yield port.pi.ld.ok
32 print("ldok", ldok)
33 if ldok:
34 break
35 yield
36
37
38 def l0_cache_st(dut, addr, data, datalen):
39 if isinstance(dut.pi, Record):
40 port1 = dut
41 else:
42 port1 = dut.pi
43
44 # have to wait until not busy
45 yield from wait_busy(port1, no=False) # wait until not busy
46
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)
50
51 yield port1.pi.addr.data.eq(addr) # set address
52 yield port1.pi.addr.ok.eq(1) # set ok
53 yield Settle()
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)
60 yield
61 yield port1.pi.st.ok.eq(0)
62 yield from wait_busy(port1, True) # wait while busy
63
64 # can go straight to reset.
65 yield port1.pi.is_st_i.eq(0) # end
66 yield port1.pi.addr.ok.eq(0) # set !ok
67
68
69 def l0_cache_ld(dut, addr, datalen):
70
71 if isinstance(dut.pi, Record):
72 port1 = dut
73 else:
74 port1 = dut.pi
75
76 # have to wait until not busy
77 yield from wait_busy(port1, no=False) # wait until not busy
78
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)
82
83 yield port1.pi.addr.data.eq(addr) # set address
84 yield port1.pi.addr.ok.eq(1) # set ok
85 yield Settle()
86 yield from wait_addr(port1) # wait until addr ok
87 yield
88 yield from wait_ldok(port1) # wait until ld ok
89 data = yield port1.pi.ld.data
90
91 # cleanup
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 while not busy
95
96 return data
97
98
99 def l0_cache_ldst(arg, dut):
100
101 # do two half-word stores at consecutive addresses, then two loads
102 addr1 = 0x04
103 addr2 = addr1 + 0x2
104 data = 0xbeef
105 data2 = 0xf00f
106 #data = 0x4
107 yield from l0_cache_st(dut, addr1, data, 2)
108 yield from l0_cache_st(dut, addr2, data2, 2)
109 result = yield from l0_cache_ld(dut, addr1, 2)
110 result2 = yield from l0_cache_ld(dut, addr2, 2)
111 arg.assertEqual(data, result, "data %x != %x" % (result, data))
112 arg.assertEqual(data2, result2, "data2 %x != %x" % (result2, data2))
113
114 # now load both in a 32-bit load to make sure they're really consecutive
115 data3 = data | (data2 << 16)
116 result3 = yield from l0_cache_ld(dut, addr1, 4)
117 arg.assertEqual(data3, result3, "data3 %x != %x" % (result3, data3))
118
119
120 def tst_config_pi(testcls, ifacetype):
121 """set up a configureable memory test of type ifacetype
122 """
123 dut = Module()
124 pspec = TestMemPspec(ldst_ifacetype=ifacetype,
125 addr_wid=48,
126 mask_wid=8,
127 reg_wid=64)
128 cmpi = ConfigMemoryPortInterface(pspec)
129 dut.submodules.pi = cmpi.pi
130 if hasattr(cmpi, 'lsmem'): # hmmm not happy about this
131 dut.submodules.lsmem = cmpi.lsmem.lsi
132 vl = rtlil.convert(dut, ports=[])#dut.ports())
133 with open("test_pi_%s.il" % ifacetype, "w") as f:
134 f.write(vl)
135
136 run_simulation(dut, {"sync": l0_cache_ldst(testcls, cmpi.pi)},
137 vcd_name='test_pi_%s.vcd' % ifacetype)
138
139
140 class TestPIMem(unittest.TestCase):
141
142 def test_pi_mem(self):
143 tst_config_pi(self, 'testpi')
144
145 def test_pi2ls(self):
146 tst_config_pi(self, 'testmem')
147
148 def test_pi2ls_bare_wb(self):
149 tst_config_pi(self, 'test_bare_wb')
150
151
152 if __name__ == '__main__':
153 unittest.main(exit=False)
154