mark test_pi2ls.py as broken
[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 from openpower.exceptions import LDSTExceptionTuple
10
11
12 def wait_busy(port, no=False, debug=None):
13 cnt = 0
14 while True:
15 busy = yield port.busy_o
16 print("busy", no, busy, cnt, debug)
17 if bool(busy) == no:
18 break
19 yield
20 cnt += 1
21
22
23 def wait_addr(port,debug=None):
24 cnt = 0
25 while True:
26 addr_ok = yield port.addr_ok_o
27 exc_happened = yield port.exc_o.happened
28 print("addrok", addr_ok,cnt,debug,exc_happened)
29 if addr_ok or exc_happened:
30 break
31 yield
32 cnt += 1
33
34
35 def wait_ldok(port):
36 cnt = 0
37 while True:
38 ldok = yield port.ld.ok
39 exc_happened = yield port.exc_o.happened
40 print("ldok", ldok, "exception", exc_happened, "count", cnt)
41 cnt += 1
42 if ldok or exc_happened:
43 break
44 yield
45
46
47 def pi_st(port1, addr, data, datalen, msr, is_dcbz=0):
48
49 # have to wait until not busy
50 yield from wait_busy(port1,debug="pi_st_A") # wait while busy
51
52 # set up a ST on the port. address first:
53 yield port1.is_dcbz_i.eq(is_dcbz) # reset dcbz too
54 yield port1.is_st_i.eq(1) # indicate ST
55 yield port1.data_len.eq(datalen) # ST length (1/2/4/8)
56 yield port1.priv_mode.eq(~msr.pr)
57 yield port1.virt_mode.eq(msr.dr)
58 yield port1.mode_32bit.eq(~msr.sf)
59
60 yield port1.addr.data.eq(addr) # set address
61 yield port1.addr.ok.eq(1) # set ok
62 yield Settle()
63
64 # must check exception even before waiting for address.
65 # XXX TODO: wait_addr should check for exception
66 exc_info = yield from get_exception_info(port1.exc_o)
67 exc_happened = exc_info.happened
68 if exc_happened:
69 print("print fast ST exception happened")
70 yield # MUST wait for one clock cycle before de-asserting these
71 yield port1.is_st_i.eq(0) # end
72 yield port1.addr.ok.eq(0) # set !ok
73 yield port1.is_dcbz_i.eq(0) # reset dcbz too
74 return "fast", exc_info
75
76 yield from wait_addr(port1) # wait until addr ok
77
78 exc_info = yield from get_exception_info(port1.exc_o)
79 exc_happened = exc_info.happened
80 if exc_happened:
81 print("print fast ST exception happened")
82 yield # MUST wait for one clock cycle before de-asserting these
83 yield port1.is_st_i.eq(0) # end
84 yield port1.addr.ok.eq(0) # set !ok
85 yield port1.is_dcbz_i.eq(0) # reset dcbz too
86 return "fast", exc_info
87
88
89 # yield # not needed, just for checking
90 # yield # not needed, just for checking
91 # assert "ST" for one cycle (required by the API)
92 yield port1.st.data.eq(data)
93 yield port1.st.ok.eq(1)
94 yield
95 yield port1.st.ok.eq(0)
96 exc_info = yield from get_exception_info(port1.exc_o)
97 exc_happened = exc_info.happened
98 if exc_happened:
99 print("print fast ST exception happened")
100 yield # MUST wait for one clock cycle before de-asserting these
101 yield port1.is_st_i.eq(0) # end
102 yield port1.addr.ok.eq(0) # set !ok
103 yield port1.is_dcbz_i.eq(0) # reset dcbz too
104 return "fast", exc_info
105
106 yield from wait_busy(port1,debug="pi_st_E") # wait while busy
107 exc_info = yield from get_exception_info(port1.exc_o)
108 exc_happened = exc_info.happened
109 if exc_happened:
110 yield # needed if mmu/dache is used
111 yield port1.is_st_i.eq(0) # end
112 yield port1.addr.ok.eq(0) # set !ok
113 yield port1.is_dcbz_i.eq(0) # reset dcbz too
114 yield # needed if mmu/dache is used
115 return "slow", exc_info
116
117 # can go straight to reset.
118 yield port1.is_st_i.eq(0) # end
119 yield port1.addr.ok.eq(0) # set !ok
120 yield port1.is_dcbz_i.eq(0) # reset dcbz too
121 yield # needed if mmu/dache is used
122
123 return None, None
124
125 def get_exception_info(exc_o):
126 attrs = []
127 for fname in LDSTExceptionTuple._fields:
128 attr = getattr(exc_o, fname)
129 val = yield attr
130 attrs.append(val)
131 return LDSTExceptionTuple(*attrs)
132
133
134 # copy of pi_st removed
135
136 def pi_ld(port1, addr, datalen, msr):
137
138 # have to wait until not busy
139 yield from wait_busy(port1,debug="pi_ld_A") # wait while busy
140
141 # set up a LD on the port. address first:
142 yield port1.is_ld_i.eq(1) # indicate LD
143 yield port1.data_len.eq(datalen) # LD length (1/2/4/8)
144 yield port1.priv_mode.eq(~msr.pr)
145 yield port1.virt_mode.eq(msr.dr)
146 yield port1.mode_32bit.eq(~msr.sf)
147
148 yield port1.addr.data.eq(addr) # set address
149 yield port1.addr.ok.eq(1) # set ok
150 yield Settle()
151 yield from wait_addr(port1) # wait until addr ok
152 exc_info = yield from get_exception_info(port1.exc_o)
153 exc_happened = exc_info.happened
154 if exc_happened:
155 print("print fast LD exception happened")
156 yield # MUST wait for one clock cycle before de-asserting these
157 yield port1.is_ld_i.eq(0) # end
158 yield port1.addr.ok.eq(0) # set !ok
159 return None, "fast", exc_info
160
161 yield
162 yield from wait_ldok(port1) # wait until ld ok
163 data = yield port1.ld.data
164 exc_info = yield from get_exception_info(port1.exc_o)
165 exc_happened = yield port1.exc_o.happened
166 exc_happened = exc_info.happened
167
168 # cleanup
169 yield port1.is_ld_i.eq(0) # end
170 yield port1.addr.ok.eq(0) # set !ok
171 if exc_happened:
172 return None, "slow", exc_info
173
174 yield from wait_busy(port1, debug="pi_ld_E") # wait while busy
175
176 exc_info = yield from get_exception_info(port1.exc_o)
177 exc_happened = exc_info.happened
178 if exc_happened:
179 return None, "slow", exc_info
180
181 return data, None, None
182
183
184 def pi_ldst(arg, dut, msr):
185
186 # do two half-word stores at consecutive addresses, then two loads
187 addr1 = 0x04
188 addr2 = addr1 + 0x2
189 data = 0xbeef
190 data2 = 0xf00f
191 #data = 0x4
192 assert(yield from pi_st(dut, addr1, data, 2, msr) is None)
193 assert(yield from pi_st(dut, addr2, data2, 2, msr) is None)
194 result, exc = yield from pi_ld(dut, addr1, 2, msr)
195 result2, exc2 = yield from pi_ld(dut, addr2, 2, msr)
196 assert(exc is None)
197 assert(exc2 is None)
198 arg.assertEqual(data, result, "data %x != %x" % (result, data))
199 arg.assertEqual(data2, result2, "data2 %x != %x" % (result2, data2))
200
201 # now load both in a 32-bit load to make sure they're really consecutive
202 data3 = data | (data2 << 16)
203 result3, exc3 = yield from pi_ld(dut, addr1, 4, msr)
204 assert(exc3 is None)
205 arg.assertEqual(data3, result3, "data3 %x != %x" % (result3, data3))
206
207
208 def tst_config_pi(testcls, ifacetype):
209 """set up a configureable memory test of type ifacetype
210 """
211 dut = Module()
212 pspec = TestMemPspec(ldst_ifacetype=ifacetype,
213 imem_ifacetype='',
214 addr_wid=64,
215 mask_wid=8,
216 reg_wid=64)
217 cmpi = ConfigMemoryPortInterface(pspec)
218 dut.submodules.pi = cmpi.pi
219 if hasattr(cmpi, 'lsmem'): # hmmm not happy about this
220 dut.submodules.lsmem = cmpi.lsmem.lsi
221 vl = rtlil.convert(dut, ports=[]) # dut.ports())
222 with open("test_pi_%s.il" % ifacetype, "w") as f:
223 f.write(vl)
224
225 run_simulation(dut, {"sync": pi_ldst(testcls, cmpi.pi.pi)},
226 vcd_name='test_pi_%s.vcd' % ifacetype)
227
228
229 # FIXME: TypeError: pi_ldst() missing 1 required positional argument: 'msr'
230 @unittest.skip('broken')
231 class TestPIMem(unittest.TestCase):
232 def test_pi_mem(self):
233 tst_config_pi(self, 'testpi')
234
235 def test_pi2ls(self):
236 tst_config_pi(self, 'testmem')
237
238 def test_pi2ls_bare_wb(self):
239 tst_config_pi(self, 'test_bare_wb')
240
241
242 if __name__ == '__main__':
243 unittest.main()