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