fix up test_loadstore1.py
[soc.git] / src / soc / experiment / test / test_loadstore1.py
1 from nmigen import (C, Module, Signal, Elaboratable, Mux, Cat, Repl, Signal)
2 from nmigen.cli import main
3 from nmigen.cli import rtlil
4 from nmutil.mask import Mask, masked
5 from nmutil.util import Display
6 from random import randint, seed
7 from nmigen.sim import Simulator, Delay, Settle
8 from nmutil.util import wrap
9
10 from soc.config.test.test_pi2ls import pi_ld, pi_st, pi_ldst, wait_busy
11 #from soc.config.test.test_pi2ls import pi_st_debug
12 from soc.config.test.test_loadstore import TestMemPspec
13 from soc.config.loadstore import ConfigMemoryPortInterface
14
15 from soc.fu.ldst.loadstore import LoadStore1
16 from soc.experiment.mmu import MMU
17 from soc.experiment.test import pagetables
18
19 from nmigen.compat.sim import run_simulation
20 from random import random
21
22 stop = False
23
24 def wb_get(wb, mem):
25 """simulator process for getting memory load requests
26 """
27
28 global stop
29 assert (stop==False)
30
31 while not stop:
32 while True: # wait for dc_valid
33 if stop:
34 return
35 cyc = yield (wb.cyc)
36 stb = yield (wb.stb)
37 if cyc and stb:
38 break
39 yield
40 addr = (yield wb.adr) << 3
41 if addr not in mem:
42 print (" WB LOOKUP NO entry @ %x, returning zero" % (addr))
43
44 # read or write?
45 we = (yield wb.we)
46 if we:
47 store = (yield wb.dat_w)
48 sel = (yield wb.sel)
49 data = mem.get(addr, 0)
50 # note we assume 8-bit sel, here
51 res = 0
52 for i in range(8):
53 mask = 0xff << (i*8)
54 if sel & (1<<i):
55 res |= store & mask
56 else:
57 res |= data & mask
58 mem[addr] = res
59 print (" DCACHE set %x mask %x data %x" % (addr, sel, res))
60 else:
61 data = mem.get(addr, 0)
62 yield wb.dat_r.eq(data)
63 print (" DCACHE get %x data %x" % (addr, data))
64
65 yield wb.ack.eq(1)
66 yield
67 yield wb.ack.eq(0)
68 yield
69
70 def setup_mmu():
71
72 global stop
73 stop = False
74
75 pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
76 imem_ifacetype='',
77 addr_wid=48,
78 #disable_cache=True, # hmmm...
79 mask_wid=8,
80 reg_wid=64)
81
82 m = Module()
83 comb = m.d.comb
84 cmpi = ConfigMemoryPortInterface(pspec)
85 m.submodules.ldst = ldst = cmpi.pi
86 m.submodules.mmu = mmu = MMU()
87 dcache = ldst.dcache
88
89 l_in, l_out = mmu.l_in, mmu.l_out
90 d_in, d_out = dcache.d_in, dcache.d_out
91 wb_out, wb_in = dcache.wb_out, dcache.wb_in
92
93 # link mmu and dcache together
94 m.d.comb += dcache.m_in.eq(mmu.d_out) # MMUToDCacheType
95 m.d.comb += mmu.d_in.eq(dcache.m_out) # DCacheToMMUType
96
97 # link ldst and MMU together
98 comb += l_in.eq(ldst.m_out)
99 comb += ldst.m_in.eq(l_out)
100
101 return m, cmpi
102
103 test_exceptions = True
104 test_dcbz = True
105 test_random = True
106
107 def _test_loadstore1_invalid(dut, mem):
108 mmu = dut.submodules.mmu
109 pi = dut.submodules.ldst.pi
110 global stop
111 stop = False
112
113 print("=== test invalid ===")
114
115 addr = 0
116 ld_data, exctype, exc, dar_o = yield from pi_ld(pi, addr, 8, msr_pr=1)
117 print("ld_data", ld_data, exctype, exc)
118 assert (exctype == "slow")
119 invalid = exc.invalid
120 assert (invalid == 1)
121
122 print("=== test invalid done ===")
123
124 stop = True
125
126
127 def _test_loadstore1(dut, mem):
128 mmu = dut.submodules.mmu
129 pi = dut.submodules.ldst.pi
130 global stop
131 stop = False
132
133 yield mmu.rin.prtbl.eq(0x1000000) # set process table
134 yield
135
136 addr = 0x100e0
137 data = 0xf553b658ba7e1f51
138
139 if test_dcbz:
140 yield from pi_st(pi, addr, data, 8, msr_pr=1)
141 yield
142
143 ld_data, exctype, exc, dar_o = yield from pi_ld(pi, addr, 8, msr_pr=1)
144 assert ld_data == 0xf553b658ba7e1f51
145 assert exctype is None
146
147 ld_data, exctype, exc, dar_o = yield from pi_ld(pi, addr, 8, msr_pr=1)
148 assert ld_data == 0xf553b658ba7e1f51
149 assert exctype is None
150
151 print("do_dcbz ===============")
152 yield from pi_st(pi, addr, data, 8, msr_pr=1, is_dcbz=1)
153 print("done_dcbz ===============")
154 yield
155
156 ld_data, exctype, exc, dar_o = yield from pi_ld(pi, addr, 8, msr_pr=1)
157 print("ld_data after dcbz")
158 print(ld_data)
159 assert ld_data == 0
160 assert exctype is None
161
162 if test_exceptions:
163 print("=== alignment error (ld) ===")
164 addr = 0xFF100e0FF
165 ld_data, exctype, exc, dar = yield from pi_ld(pi, addr, 8, msr_pr=1)
166 if exc:
167 alignment = exc.alignment
168 happened = exc.happened
169 else:
170 alignment = 0
171 happened = 0
172 assert (happened == 1)
173 assert (alignment == 1)
174 assert (dar == addr)
175 assert (exctype == "fast")
176 yield from wait_busy(pi, debug="pi_ld_E_alignment_error")
177 # wait is only needed in case of in exception here
178 print("=== alignment error test passed (ld) ===")
179
180 # take some cycles in between so that gtkwave separates out
181 # signals
182 yield
183 yield
184 yield
185 yield
186
187 print("=== alignment error (st) ===")
188 addr = 0xFF100e0FF
189 exctype, exc, dar_o = yield from pi_st(pi, addr,0, 8, msr_pr=1)
190 if exc:
191 alignment = exc.alignment
192 happened = exc.happened
193 else:
194 alignment = 0
195 happened = 0
196 assert (happened == 1)
197 assert (alignment==1)
198 assert (dar==addr)
199 assert (exctype == "fast")
200 #???? yield from wait_busy(pi, debug="pi_st_E_alignment_error")
201 # wait is only needed in case of in exception here
202 print("=== alignment error test passed (st) ===")
203 yield #FIXME hangs
204
205 if True:
206 print("=== no alignment error (ld) ===")
207 addr = 0x100e0
208 ld_data, exctype, exc, dar_o = yield from pi_ld(pi, addr, 8, msr_pr=1)
209 print("ld_data", ld_data, exctype, exc)
210 if exc:
211 alignment = exc.alignment
212 happened = exc.happened
213 else:
214 alignment = 0
215 happened = 0
216 assert (happened == 0)
217 assert (alignment == 0)
218 print("=== no alignment error done (ld) ===")
219
220 if test_random:
221 addrs = [0x456920,0xa7a180,0x299420,0x1d9d60]
222
223 for addr in addrs:
224 print("== RANDOM addr ==",hex(addr))
225 ld_data, exctype, exc, dar_o = \
226 yield from pi_ld(pi, addr, 8, msr_pr=1)
227 print("ld_data[RANDOM]",ld_data,exc,addr)
228 assert (exctype == None)
229
230 for addr in addrs:
231 print("== RANDOM addr ==",hex(addr))
232 exc = yield from pi_st(pi, addr,0xFF*addr, 8, msr_pr=1)
233 assert (exctype == None)
234
235 # readback written data and compare
236 for addr in addrs:
237 print("== RANDOM addr ==",hex(addr))
238 ld_data, exctype, exc, dar_o = \
239 yield from pi_ld(pi, addr, 8, msr_pr=1)
240 print("ld_data[RANDOM_READBACK]",ld_data,exc,addr)
241 assert (exctype == None)
242 assert (ld_data == 0xFF*addr)
243
244 print("== RANDOM addr done ==")
245
246 stop = True
247
248 def test_loadstore1():
249
250 m, cmpi = setup_mmu()
251
252 mem = pagetables.test1
253
254 # nmigen Simulation
255 sim = Simulator(m)
256 sim.add_clock(1e-6)
257
258 sim.add_sync_process(wrap(_test_loadstore1(m, mem)))
259 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
260 with sim.write_vcd('test_loadstore1.vcd'):
261 sim.run()
262
263 def test_loadstore1_invalid():
264
265 m, cmpi = setup_mmu()
266
267 mem = {}
268
269 # nmigen Simulation
270 sim = Simulator(m)
271 sim.add_clock(1e-6)
272
273 sim.add_sync_process(wrap(_test_loadstore1_invalid(m, mem)))
274 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
275 with sim.write_vcd('test_loadstore1_invalid.vcd'):
276 sim.run()
277
278 if __name__ == '__main__':
279 test_loadstore1()
280 test_loadstore1_invalid()