test_ldst_pi.py: add dcache regression and random test from test_dcache.py
[soc.git] / src / soc / experiment / test / test_ldst_pi.py
1 """MMU PortInterface Test
2
3 quite basic, goes directly to the MMU to assert signals (does not
4 yet use PortInterface)
5 """
6
7 from nmigen import (C, Module, Signal, Elaboratable, Mux, Cat, Repl, Signal)
8 from nmigen.cli import main
9 from nmigen.cli import rtlil
10 from nmutil.mask import Mask, masked
11 from nmutil.util import Display
12 from random import randint, seed
13
14 if True:
15 from nmigen.back.pysim import Simulator, Delay, Settle
16 else:
17 from nmigen.sim.cxxsim import Simulator, Delay, Settle
18 from nmutil.util import wrap
19
20 from soc.config.test.test_pi2ls import pi_ld, pi_st, pi_ldst
21 from soc.config.test.test_loadstore import TestMemPspec
22 from soc.config.loadstore import ConfigMemoryPortInterface
23
24 from soc.fu.ldst.loadstore import LoadStore1
25 from soc.experiment.mmu import MMU
26
27 from nmigen.compat.sim import run_simulation
28
29
30 stop = False
31
32 def b(x): # byte-reverse function
33 return int.from_bytes(x.to_bytes(8, byteorder='little'),
34 byteorder='big', signed=False)
35
36 def wb_get(wb, mem):
37 """simulator process for getting memory load requests
38 """
39
40 global stop
41
42 while not stop:
43 while True: # wait for dc_valid
44 if stop:
45 return
46 cyc = yield (wb.cyc)
47 stb = yield (wb.stb)
48 if cyc and stb:
49 break
50 yield
51 addr = (yield wb.adr) << 3
52 if addr not in mem:
53 print (" WB LOOKUP NO entry @ %x, returning zero" % (addr))
54
55 # read or write?
56 we = (yield wb.we)
57 if we:
58 store = (yield wb.dat_w)
59 sel = (yield wb.sel)
60 data = mem.get(addr, 0)
61 # note we assume 8-bit sel, here
62 res = 0
63 for i in range(8):
64 mask = 0xff << (i*8)
65 if sel & (1<<i):
66 res |= store & mask
67 else:
68 res |= data & mask
69 mem[addr] = res
70 print (" DCACHE set %x mask %x data %x" % (addr, sel, res))
71 else:
72 data = mem.get(addr, 0)
73 yield wb.dat_r.eq(data)
74 print (" DCACHE get %x data %x" % (addr, data))
75
76 yield wb.ack.eq(1)
77 yield
78 yield wb.ack.eq(0)
79 yield
80
81
82 def mmu_lookup(dut, addr):
83 mmu = dut.submodules.mmu
84 global stop
85
86 print("pi_ld", hex(addr))
87 data = yield from pi_ld(dut.submodules.ldst.pi, addr, 4, msr_pr=1)
88 print("pi_ld done, data", hex(data))
89 """
90 # original test code kept for reference
91 while not stop: # wait for dc_valid / err
92 print("waiting for mmu")
93 l_done = yield (mmu.l_out.done)
94 l_err = yield (mmu.l_out.err)
95 l_badtree = yield (mmu.l_out.badtree)
96 l_permerr = yield (mmu.l_out.perm_error)
97 l_rc_err = yield (mmu.l_out.rc_error)
98 l_segerr = yield (mmu.l_out.segerr)
99 l_invalid = yield (mmu.l_out.invalid)
100 if (l_done or l_err or l_badtree or
101 l_permerr or l_rc_err or l_segerr or l_invalid):
102 break
103 yield
104 """
105 phys_addr = yield mmu.d_out.addr
106 pte = yield mmu.d_out.pte
107 l_done = yield (mmu.l_out.done)
108 l_err = yield (mmu.l_out.err)
109 l_badtree = yield (mmu.l_out.badtree)
110 print ("translated done %d err %d badtree %d addr %x pte %x" % \
111 (l_done, l_err, l_badtree, phys_addr, pte))
112 yield
113 yield mmu.l_in.valid.eq(0)
114
115 return data
116
117
118 def ldst_sim(dut):
119 mmu = dut.submodules.mmu
120 global stop
121 yield mmu.rin.prtbl.eq(0x1000000) # set process table
122 yield
123
124 # expecting this data to return
125 # 0x1000: 0xdeadbeef01234567,
126 # 0x1008: 0xfeedf00ff001a5a5
127
128 addr = 0x1000
129 print("pi_ld")
130
131 # TODO mmu_lookup using port interface
132 # set inputs
133 data = yield from mmu_lookup(dut, addr)
134 assert data == 0x1234567
135
136 data = yield from mmu_lookup(dut, addr+8)
137 assert data == 0xf001a5a5
138 #assert phys_addr == addr # happens to be the same (for this example)
139
140 data = yield from mmu_lookup(dut, addr+4)
141 assert data == 0xdeadbeef
142
143 data = yield from mmu_lookup(dut, addr+8)
144 assert data == 0xf001a5a5
145
146 yield from pi_st(dut.submodules.ldst.pi, addr+4, 0x10015a5a, 4, msr_pr=1)
147
148 data = yield from mmu_lookup(dut, addr+4)
149 assert data == 0x10015a5a
150
151 yield
152 yield
153
154 stop = True
155
156 def setup_mmu():
157
158 pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
159 imem_ifacetype='',
160 addr_wid=48,
161 #disable_cache=True, # hmmm...
162 mask_wid=8,
163 reg_wid=64)
164
165 m = Module()
166 comb = m.d.comb
167 cmpi = ConfigMemoryPortInterface(pspec)
168 m.submodules.ldst = ldst = cmpi.pi
169 m.submodules.mmu = mmu = MMU()
170 dcache = ldst.dcache
171
172 l_in, l_out = mmu.l_in, mmu.l_out
173 d_in, d_out = dcache.d_in, dcache.d_out
174 wb_out, wb_in = dcache.wb_out, dcache.wb_in
175
176 # link mmu and dcache together
177 m.d.comb += dcache.m_in.eq(mmu.d_out) # MMUToDCacheType
178 m.d.comb += mmu.d_in.eq(dcache.m_out) # DCacheToMMUType
179
180 # link ldst and MMU together
181 comb += l_in.eq(ldst.m_out)
182 comb += ldst.m_in.eq(l_out)
183
184 return m, cmpi
185
186
187 def test_mmu():
188
189 m, cmpi = setup_mmu()
190
191 # virtual "memory" to use for this test
192
193 mem = {0x10000: # PARTITION_TABLE_2
194 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
195 b(0x800000000100000b),
196
197 0x30000: # RADIX_ROOT_PTE
198 # V = 1 L = 0 NLB = 0x400 NLS = 9
199 b(0x8000000000040009),
200
201 0x40000: # RADIX_SECOND_LEVEL
202 # V = 1 L = 1 SW = 0 RPN = 0
203 # R = 1 C = 1 ATT = 0 EAA 0x7
204 b(0xc000000000000183),
205
206 0x1000000: # PROCESS_TABLE_3
207 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
208 b(0x40000000000300ad),
209
210 # data to return
211 0x1000: 0xdeadbeef01234567,
212 0x1008: 0xfeedf00ff001a5a5
213 }
214
215
216 # nmigen Simulation
217 sim = Simulator(m)
218 sim.add_clock(1e-6)
219
220 sim.add_sync_process(wrap(ldst_sim(m)))
221 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
222 with sim.write_vcd('test_ldst_pi.vcd'):
223 sim.run()
224
225
226 def ldst_sim_misalign(dut):
227 mmu = dut.submodules.mmu
228 global stop
229 stop = False
230
231 yield mmu.rin.prtbl.eq(0x1000000) # set process table
232 yield
233
234 data = yield from pi_ld(dut.submodules.ldst.pi, 0x1007, 8, msr_pr=1)
235 print ("misalign ld data", hex(data))
236
237 yield
238 stop = True
239
240
241 def test_misalign_mmu():
242
243 m, cmpi = setup_mmu()
244
245 # virtual "memory" to use for this test
246
247 mem = {0x10000: # PARTITION_TABLE_2
248 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
249 b(0x800000000100000b),
250
251 0x30000: # RADIX_ROOT_PTE
252 # V = 1 L = 0 NLB = 0x400 NLS = 9
253 b(0x8000000000040009),
254
255 0x40000: # RADIX_SECOND_LEVEL
256 # V = 1 L = 1 SW = 0 RPN = 0
257 # R = 1 C = 1 ATT = 0 EAA 0x7
258 b(0xc000000000000183),
259
260 0x1000000: # PROCESS_TABLE_3
261 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
262 b(0x40000000000300ad),
263
264 # data to return
265 0x1000: 0xdeadbeef01234567,
266 0x1008: 0xfeedf00ff001a5a5
267 }
268
269
270 # nmigen Simulation
271 sim = Simulator(m)
272 sim.add_clock(1e-6)
273
274 sim.add_sync_process(wrap(ldst_sim_misalign(m)))
275 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
276 with sim.write_vcd('test_ldst_pi_misalign.vcd'):
277 sim.run()
278
279
280 def ldst_sim_radixmiss(dut):
281 mmu = dut.submodules.mmu
282 global stop
283 stop = False
284
285 yield mmu.rin.prtbl.eq(1<<40) # set process table
286 yield
287
288 data = yield from pi_ld(dut.submodules.ldst.pi, 0x10000000, 8, msr_pr=1)
289 print ("radixmiss ld data", hex(data))
290
291 yield
292 stop = True
293
294 def ldst_sim_dcache_regression(dut):
295 mmu = dut.submodules.mmu
296 global stop
297 stop = False
298
299 yield mmu.rin.prtbl.eq(1<<40) # set process table
300 yield
301
302 data = yield from pi_ld(dut.submodules.ldst.pi, 0, 8, msr_pr=1)
303 print ("dcache_regression ld data", hex(data))
304 # FIXME: this is 0 but should be 0xFFFFFFFFFFFFFFFF
305
306 yield
307 stop = True
308
309 def ldst_sim_dcache_random(dut):
310 mmu = dut.submodules.mmu
311 pi = dut.submodules.ldst.pi
312 global stop
313 stop = False
314
315 yield mmu.rin.prtbl.eq(1<<40) # set process table
316 yield
317
318 memsize = 256
319
320 for i in range(1024):
321 addr = randint(0, memsize-1)
322 data = randint(0, (1<<64)-1)
323 addr *= 8
324
325 yield from pi_st(pi, addr, data, 8, msr_pr=1)
326 yield
327
328 ld_data = yield from pi_ld(pi, addr, 8, msr_pr=1)
329
330 print ("dcache_random random ld data", hex(data), hex(read))
331 print ("addr",addr)
332
333 yield
334 stop = True
335
336 def test_radixmiss_mmu():
337
338 m, cmpi = setup_mmu()
339
340 # virtual "memory" to use for this test
341
342 mem = {0x10000: # PARTITION_TABLE_2
343 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
344 b(0x800000000100000b),
345
346 0x30000: # RADIX_ROOT_PTE
347 # V = 1 L = 0 NLB = 0x400 NLS = 9
348 b(0x8000000000040009),
349
350 0x40000: # RADIX_SECOND_LEVEL
351 # V = 1 L = 1 SW = 0 RPN = 0
352 # R = 1 C = 1 ATT = 0 EAA 0x7
353 b(0xc000000000000183),
354
355 0x1000000: # PROCESS_TABLE_3
356 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
357 b(0x40000000000300ad),
358
359 # data to return
360 0x1000: 0xdeadbeef01234567,
361 0x1008: 0xfeedf00ff001a5a5
362 }
363
364
365 # nmigen Simulation
366 sim = Simulator(m)
367 sim.add_clock(1e-6)
368
369 sim.add_sync_process(wrap(ldst_sim_radixmiss(m)))
370 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
371 with sim.write_vcd('test_ldst_pi_radix_miss.vcd'):
372 sim.run()
373
374 def test_dcache_regression():
375
376 m, cmpi = setup_mmu()
377
378 # dcache_load at addr 0
379 mem = {
380 0: 0xFFFFFFFFFFFFFFFF
381 }
382
383 # nmigen Simulation
384 sim = Simulator(m)
385 sim.add_clock(1e-6)
386
387 sim.add_sync_process(wrap(ldst_sim_dcache_regression(m)))
388 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
389 with sim.write_vcd('test_ldst_pi_radix_miss.vcd'):
390 sim.run()
391
392 def test_dcache_random():
393
394 m, cmpi = setup_mmu()
395
396 # dcache_load at addr 0
397 mem = {
398 }
399
400 # nmigen Simulation
401 sim = Simulator(m)
402 sim.add_clock(1e-6)
403
404 sim.add_sync_process(wrap(ldst_sim_dcache_random(m)))
405 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
406 with sim.write_vcd('test_ldst_pi_radix_miss.vcd'):
407 sim.run()
408
409 if __name__ == '__main__':
410 test_mmu()
411 test_misalign_mmu()
412 test_radixmiss_mmu()
413 ### tests taken from src/soc/experiment/test/test_dcache.py
414 test_dcache_regression()
415 #FIXME test_dcache_random()
416 #TODO test_dcache()