1 """MMU PortInterface Test
3 quite basic, goes directly to the MMU to assert signals (does not
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 from openpower
.test
.wb_get
import wb_get
14 from openpower
.test
import wb_get
as wbget
17 from nmigen
.back
.pysim
import Simulator
, Delay
, Settle
19 from nmigen
.sim
.cxxsim
import Simulator
, Delay
, Settle
20 from nmutil
.util
import wrap
22 from soc
.config
.test
.test_pi2ls
import pi_ld
, pi_st
, pi_ldst
23 from soc
.config
.test
.test_loadstore
import TestMemPspec
24 from soc
.config
.loadstore
import ConfigMemoryPortInterface
26 from soc
.fu
.ldst
.loadstore
import LoadStore1
27 from soc
.experiment
.mmu
import MMU
29 from nmigen
.compat
.sim
import run_simulation
34 def b(x
): # byte-reverse function
35 return int.from_bytes(x
.to_bytes(8, byteorder
='little'),
36 byteorder
='big', signed
=False)
41 # f.write(str(hex(cell))+"="+str(hex(mem[cell]))+"\n")
44 def mmu_lookup(dut
, addr
):
45 mmu
= dut
.submodules
.mmu
47 print("pi_ld", hex(addr
))
48 data
, _
, _
= yield from pi_ld(dut
.submodules
.ldst
.pi
, addr
, 4, msr_pr
=1)
49 print("pi_ld done, data", hex(data
))
51 # original test code kept for reference
52 while not wbget.stop: # wait for dc_valid / err
53 print("waiting for mmu")
54 l_done = yield (mmu.l_out.done)
55 l_err = yield (mmu.l_out.err)
56 l_badtree = yield (mmu.l_out.badtree)
57 l_permerr = yield (mmu.l_out.perm_error)
58 l_rc_err = yield (mmu.l_out.rc_error)
59 l_segerr = yield (mmu.l_out.segerr)
60 l_invalid = yield (mmu.l_out.invalid)
61 if (l_done or l_err or l_badtree or
62 l_permerr or l_rc_err or l_segerr or l_invalid):
66 phys_addr
= yield mmu
.d_out
.addr
67 pte
= yield mmu
.d_out
.pte
68 l_done
= yield (mmu
.l_out
.done
)
69 l_err
= yield (mmu
.l_out
.err
)
70 l_badtree
= yield (mmu
.l_out
.badtree
)
71 print ("translated done %d err %d badtree %d addr %x pte %x" % \
72 (l_done
, l_err
, l_badtree
, phys_addr
, pte
))
74 yield mmu
.l_in
.valid
.eq(0)
80 mmu
= dut
.submodules
.mmu
81 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
84 # expecting this data to return
85 # 0x1000: 0xdeadbeef01234567,
86 # 0x1008: 0xfeedf00ff001a5a5
91 # TODO mmu_lookup using port interface
93 data
= yield from mmu_lookup(dut
, addr
)
94 assert data
== 0x1234567
96 data
= yield from mmu_lookup(dut
, addr
+8)
97 assert data
== 0xf001a5a5
98 #assert phys_addr == addr # happens to be the same (for this example)
100 data
= yield from mmu_lookup(dut
, addr
+4)
101 assert data
== 0xdeadbeef
103 data
= yield from mmu_lookup(dut
, addr
+8)
104 assert data
== 0xf001a5a5
106 yield from pi_st(dut
.submodules
.ldst
.pi
, addr
+4, 0x10015a5a, 4, msr_pr
=1)
108 data
= yield from mmu_lookup(dut
, addr
+4)
109 assert data
== 0x10015a5a
120 pspec
= TestMemPspec(ldst_ifacetype
='mmu_cache_wb',
123 #disable_cache=True, # hmmm...
129 cmpi
= ConfigMemoryPortInterface(pspec
)
130 m
.submodules
.ldst
= ldst
= cmpi
.pi
131 m
.submodules
.mmu
= mmu
= MMU()
134 l_in
, l_out
= mmu
.l_in
, mmu
.l_out
135 d_in
, d_out
= dcache
.d_in
, dcache
.d_out
137 # link mmu and dcache together
138 m
.d
.comb
+= dcache
.m_in
.eq(mmu
.d_out
) # MMUToDCacheType
139 m
.d
.comb
+= mmu
.d_in
.eq(dcache
.m_out
) # DCacheToMMUType
141 # link ldst and MMU together
142 comb
+= l_in
.eq(ldst
.m_out
)
143 comb
+= ldst
.m_in
.eq(l_out
)
150 m
, cmpi
= setup_mmu()
152 # virtual "memory" to use for this test
154 mem
= {0x10000: # PARTITION_TABLE_2
155 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
156 b(0x800000000100000b),
158 0x30000: # RADIX_ROOT_PTE
159 # V = 1 L = 0 NLB = 0x400 NLS = 9
160 b(0x8000000000040009),
162 0x40000: # RADIX_SECOND_LEVEL
163 # V = 1 L = 1 SW = 0 RPN = 0
164 # R = 1 C = 1 ATT = 0 EAA 0x7
165 b(0xc000000000000183),
167 0x1000000: # PROCESS_TABLE_3
168 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
169 b(0x40000000000300ad),
172 0x1000: 0xdeadbeef01234567,
173 0x1008: 0xfeedf00ff001a5a5
181 sim
.add_sync_process(wrap(ldst_sim(m
)))
182 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
183 with sim
.write_vcd('test_ldst_pi.vcd'):
187 def ldst_sim_misalign(dut
):
188 mmu
= dut
.submodules
.mmu
191 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
194 data
, _
, _
= yield from pi_ld(dut
.submodules
.ldst
.pi
, 0x1007, 8, msr_pr
=1)
195 print ("misalign ld data", data
)
201 def test_misalign_mmu():
203 m
, cmpi
= setup_mmu()
205 # virtual "memory" to use for this test
207 mem
= {0x10000: # PARTITION_TABLE_2
208 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
209 b(0x800000000100000b),
211 0x30000: # RADIX_ROOT_PTE
212 # V = 1 L = 0 NLB = 0x400 NLS = 9
213 b(0x8000000000040009),
215 0x40000: # RADIX_SECOND_LEVEL
216 # V = 1 L = 1 SW = 0 RPN = 0
217 # R = 1 C = 1 ATT = 0 EAA 0x7
218 b(0xc000000000000183),
220 0x1000000: # PROCESS_TABLE_3
221 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
222 b(0x40000000000300ad),
225 0x1000: 0xdeadbeef01234567,
226 0x1008: 0xfeedf00ff001a5a5
234 sim
.add_sync_process(wrap(ldst_sim_misalign(m
)))
235 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
236 with sim
.write_vcd('test_ldst_pi_misalign.vcd'):
240 def ldst_sim_radixmiss(dut
):
241 mmu
= dut
.submodules
.mmu
244 yield mmu
.rin
.prtbl
.eq(1<<40) # set process table
247 data
, _
, _
= yield from pi_ld(dut
.submodules
.ldst
.pi
,
248 0x10000000, 8, msr_pr
=1)
249 print ("radixmiss ld data", data
)
254 def ldst_sim_dcache_regression(dut
):
255 mmu
= dut
.submodules
.mmu
258 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
262 data
, _
, _
= yield from pi_ld(dut
.submodules
.ldst
.pi
, addr
, 8, msr_pr
=1)
263 print ("=== dcache_regression ld data", data
)
264 assert(data
== 0xdeadbeef01234567)
269 def ldst_sim_dcache_random(dut
):
270 mmu
= dut
.submodules
.mmu
271 pi
= dut
.submodules
.ldst
.pi
274 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
280 addr
= randint(0, memsize
-1)
281 data
= randint(0, (1<<64)-1)
285 yield from pi_st(pi
, addr
, data
, 8, msr_pr
=1)
288 ld_data
, _
, _
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
291 print ("dcache_random values", hex(addr
), hex(data
), hex(ld_data
), eq
)
292 assert(data
==ld_data
) ## investigate why this fails -- really seldom
297 def ldst_sim_dcache_first(dut
): # this test is likely to fail
298 mmu
= dut
.submodules
.mmu
299 pi
= dut
.submodules
.ldst
.pi
302 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
307 data
= 0x8c5a3e460d71f0b4
309 # known to fail without bugfix in src/soc/fu/ldst/loadstore.py
310 yield from pi_st(pi
, addr
, data
, 8, msr_pr
=1)
313 ld_data
, _
, _
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
316 print ("dcache_first ld data", hex(data
), hex(ld_data
))
318 assert(data
==ld_data
)
323 def test_radixmiss_mmu():
325 m
, cmpi
= setup_mmu()
327 # virtual "memory" to use for this test
329 mem
= {0x10000: # PARTITION_TABLE_2
330 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
331 b(0x800000000100000b),
333 0x30000: # RADIX_ROOT_PTE
334 # V = 1 L = 0 NLB = 0x400 NLS = 9
335 b(0x8000000000040009),
337 0x40000: # RADIX_SECOND_LEVEL
338 # V = 1 L = 1 SW = 0 RPN = 0
339 # R = 1 C = 1 ATT = 0 EAA 0x7
340 b(0xc000000000000183),
342 0x1000000: # PROCESS_TABLE_3
343 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
344 b(0x40000000000300ad),
347 0x1000: 0xdeadbeef01234567,
348 0x1008: 0xfeedf00ff001a5a5
356 sim
.add_sync_process(wrap(ldst_sim_radixmiss(m
)))
357 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
358 with sim
.write_vcd('test_ldst_pi_radix_miss.vcd'):
361 def test_dcache_regression():
363 m
, cmpi
= setup_mmu()
365 # dcache_load at addr 0
367 0x10000: # PARTITION_TABLE_2
368 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
369 b(0x800000000100000b),
371 0x30000: # RADIX_ROOT_PTE
372 # V = 1 L = 0 NLB = 0x400 NLS = 9
373 b(0x8000000000040009),
375 0x40000: # RADIX_SECOND_LEVEL
376 # V = 1 L = 1 SW = 0 RPN = 0
377 # R = 1 C = 1 ATT = 0 EAA 0x7
378 b(0xc000000000000183),
380 0x1000000: # PROCESS_TABLE_3
381 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
382 b(0x40000000000300ad),
385 0x10000: 0xdeadbeef01234567,
386 0x10008: 0xfeedf00ff001a5a5
393 sim
.add_sync_process(wrap(ldst_sim_dcache_regression(m
)))
394 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
395 with sim
.write_vcd('test_ldst_pi_radix_miss.vcd'):
398 def test_dcache_random():
400 m
, cmpi
= setup_mmu()
402 # dcache_load at addr 0
404 0x10000: # PARTITION_TABLE_2
405 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
406 b(0x800000000100000b),
408 0x30000: # RADIX_ROOT_PTE
409 # V = 1 L = 0 NLB = 0x400 NLS = 9
410 b(0x8000000000040009),
412 0x40000: # RADIX_SECOND_LEVEL
413 # V = 1 L = 1 SW = 0 RPN = 0
414 # R = 1 C = 1 ATT = 0 EAA 0x7
415 b(0xc000000000000183),
417 0x1000000: # PROCESS_TABLE_3
418 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
419 b(0x40000000000300ad),
426 sim
.add_sync_process(wrap(ldst_sim_dcache_random(m
)))
427 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
428 with sim
.write_vcd('test_ldst_pi_random.vcd'):
431 def ldst_sim_dcache_random2(dut
, mem
):
432 mmu
= dut
.submodules
.mmu
433 pi
= dut
.submodules
.ldst
.pi
436 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
442 ## random values from a failed test
443 #[0x100e0,0xf553b658ba7e1f51,0,0], ## 1
444 #[0x10150,0x12c95a730df1cee7,0,0], ## 2
445 #[0x10080,0x5a921ae06674cd81,0,0], ## 3
446 #[0x100f8,0x4fea5eab80090fa5,0,0], ## 4
447 #[0x10080,0xd481432d17a340be,0,0], ## 5
448 #[0x10060,0x8553fcf29526fb32,0,0], ## 6
449 [0x101d0,0x327c967c8be30ded,0,0], ## 7
450 [0x101e0,0x8f15d8d05d25b151,1,0] ## 8
451 #uncommenting line 7 will cause the original test not to fail
462 print("== write: wb_get")
464 for i
in range(0,c1
):
465 print("before_pi_st")
468 yield from pi_st(pi
, addr
, data
, 8, msr_pr
=1)
471 for i
in range(0,c2
):
472 print("before_pi_ld")
475 print("== read: wb_get")
476 ld_data
, _
, _
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
478 #dumpmem(mem,"/tmp/dumpmem"+str(c)+".txt")
482 print ("dcache_random values", hex(addr
), hex(data
), hex(ld_data
), eq
)
483 assert(data
==ld_data
) ## investigate why this fails -- really seldom
488 def test_dcache_random2():
490 m
, cmpi
= setup_mmu()
492 # dcache_load at addr 0
494 0x10000: # PARTITION_TABLE_2
495 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
496 b(0x800000000100000b),
498 0x30000: # RADIX_ROOT_PTE
499 # V = 1 L = 0 NLB = 0x400 NLS = 9
500 b(0x8000000000040009),
502 0x40000: # RADIX_SECOND_LEVEL
503 # V = 1 L = 1 SW = 0 RPN = 0
504 # R = 1 C = 1 ATT = 0 EAA 0x7
505 b(0xc000000000000183),
507 0x1000000: # PROCESS_TABLE_3
508 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
509 b(0x40000000000300ad),
511 ###0x101e0:0x8f15d8d05d25b152 ## flush cache -- then check again
518 sim
.add_sync_process(wrap(ldst_sim_dcache_random2(m
, mem
)))
519 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
520 with sim
.write_vcd('test_ldst_pi_random2.vcd'):
523 def test_dcache_first():
525 m
, cmpi
= setup_mmu()
527 # dcache_load at addr 0
529 0x10000: # PARTITION_TABLE_2
530 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
531 b(0x800000000100000b),
533 0x30000: # RADIX_ROOT_PTE
534 # V = 1 L = 0 NLB = 0x400 NLS = 9
535 b(0x8000000000040009),
537 0x40000: # RADIX_SECOND_LEVEL
538 # V = 1 L = 1 SW = 0 RPN = 0
539 # R = 1 C = 1 ATT = 0 EAA 0x7
540 b(0xc000000000000183),
542 0x1000000: # PROCESS_TABLE_3
543 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
544 b(0x40000000000300ad),
551 sim
.add_sync_process(wrap(ldst_sim_dcache_first(m
)))
552 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
553 with sim
.write_vcd('test_ldst_pi_first.vcd'):
556 if __name__
== '__main__':
560 ### tests taken from src/soc/experiment/test/test_dcache.py
561 test_dcache_regression()
563 test_dcache_random() #sometimes fails
564 test_dcache_random2() #reproduce error