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
30 from openpower
.decoder
.power_enums
import MSRSpec
33 msr_default
= MSRSpec(pr
=1, dr
=0, sf
=1) # 64 bit by default
38 def b(x
): # byte-reverse function
39 return int.from_bytes(x
.to_bytes(8, byteorder
='little'),
40 byteorder
='big', signed
=False)
45 # f.write(str(hex(cell))+"="+str(hex(mem[cell]))+"\n")
48 def mmu_lookup(dut
, addr
):
49 mmu
= dut
.submodules
.mmu
51 print("pi_ld", hex(addr
))
52 data
, _
, _
= yield from pi_ld(dut
.submodules
.ldst
.pi
, addr
, 4, msr
=msr_default
)
53 print("pi_ld done, data", hex(data
))
55 # original test code kept for reference
56 while not wbget.stop: # wait for dc_valid / err
57 print("waiting for mmu")
58 l_done = yield (mmu.l_out.done)
59 l_err = yield (mmu.l_out.err)
60 l_badtree = yield (mmu.l_out.badtree)
61 l_permerr = yield (mmu.l_out.perm_error)
62 l_rc_err = yield (mmu.l_out.rc_error)
63 l_segerr = yield (mmu.l_out.segerr)
64 l_invalid = yield (mmu.l_out.invalid)
65 if (l_done or l_err or l_badtree or
66 l_permerr or l_rc_err or l_segerr or l_invalid):
70 phys_addr
= yield mmu
.d_out
.addr
71 pte
= yield mmu
.d_out
.pte
72 l_done
= yield (mmu
.l_out
.done
)
73 l_err
= yield (mmu
.l_out
.err
)
74 l_badtree
= yield (mmu
.l_out
.badtree
)
75 print ("translated done %d err %d badtree %d addr %x pte %x" % \
76 (l_done
, l_err
, l_badtree
, phys_addr
, pte
))
78 yield mmu
.l_in
.valid
.eq(0)
84 mmu
= dut
.submodules
.mmu
85 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
88 # expecting this data to return
89 # 0x1000: 0xdeadbeef01234567,
90 # 0x1008: 0xfeedf00ff001a5a5
95 # TODO mmu_lookup using port interface
97 data
= yield from mmu_lookup(dut
, addr
)
98 assert data
== 0x1234567
100 data
= yield from mmu_lookup(dut
, addr
+8)
101 assert data
== 0xf001a5a5
102 #assert phys_addr == addr # happens to be the same (for this example)
104 data
= yield from mmu_lookup(dut
, addr
+4)
105 assert data
== 0xdeadbeef
107 data
= yield from mmu_lookup(dut
, addr
+8)
108 assert data
== 0xf001a5a5
110 yield from pi_st(dut
.submodules
.ldst
.pi
, addr
+4, 0x10015a5a, 4, msr
=msr_default
)
112 data
= yield from mmu_lookup(dut
, addr
+4)
113 assert data
== 0x10015a5a
124 pspec
= TestMemPspec(ldst_ifacetype
='mmu_cache_wb',
127 #disable_cache=True, # hmmm...
133 cmpi
= ConfigMemoryPortInterface(pspec
)
134 m
.submodules
.ldst
= ldst
= cmpi
.pi
135 m
.submodules
.mmu
= mmu
= MMU()
138 l_in
, l_out
= mmu
.l_in
, mmu
.l_out
139 d_in
, d_out
= dcache
.d_in
, dcache
.d_out
141 # link mmu and dcache together
142 m
.d
.comb
+= dcache
.m_in
.eq(mmu
.d_out
) # MMUToDCacheType
143 m
.d
.comb
+= mmu
.d_in
.eq(dcache
.m_out
) # DCacheToMMUType
145 # link ldst and MMU together
146 comb
+= l_in
.eq(ldst
.m_out
)
147 comb
+= ldst
.m_in
.eq(l_out
)
154 m
, cmpi
= setup_mmu()
156 # virtual "memory" to use for this test
158 mem
= {0x10000: # PARTITION_TABLE_2
159 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
160 b(0x800000000100000b),
162 0x30000: # RADIX_ROOT_PTE
163 # V = 1 L = 0 NLB = 0x400 NLS = 9
164 b(0x8000000000040009),
166 0x40000: # RADIX_SECOND_LEVEL
167 # V = 1 L = 1 SW = 0 RPN = 0
168 # R = 1 C = 1 ATT = 0 EAA 0x7
169 b(0xc000000000000183),
171 0x1000000: # PROCESS_TABLE_3
172 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
173 b(0x40000000000300ad),
176 0x1000: 0xdeadbeef01234567,
177 0x1008: 0xfeedf00ff001a5a5
185 sim
.add_sync_process(wrap(ldst_sim(m
)))
186 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
187 with sim
.write_vcd('test_ldst_pi.vcd'):
191 def ldst_sim_misalign(dut
):
192 mmu
= dut
.submodules
.mmu
195 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
198 data
, _
, _
= yield from pi_ld(dut
.submodules
.ldst
.pi
, 0x1007, 8, msr_default
)
199 print ("misalign ld data", data
)
205 def test_misalign_mmu():
207 m
, cmpi
= setup_mmu()
209 # virtual "memory" to use for this test
211 mem
= {0x10000: # PARTITION_TABLE_2
212 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
213 b(0x800000000100000b),
215 0x30000: # RADIX_ROOT_PTE
216 # V = 1 L = 0 NLB = 0x400 NLS = 9
217 b(0x8000000000040009),
219 0x40000: # RADIX_SECOND_LEVEL
220 # V = 1 L = 1 SW = 0 RPN = 0
221 # R = 1 C = 1 ATT = 0 EAA 0x7
222 b(0xc000000000000183),
224 0x1000000: # PROCESS_TABLE_3
225 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
226 b(0x40000000000300ad),
229 0x1000: 0xdeadbeef01234567,
230 0x1008: 0xfeedf00ff001a5a5
238 sim
.add_sync_process(wrap(ldst_sim_misalign(m
)))
239 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
240 with sim
.write_vcd('test_ldst_pi_misalign.vcd'):
244 def ldst_sim_radixmiss(dut
):
245 mmu
= dut
.submodules
.mmu
248 yield mmu
.rin
.prtbl
.eq(1<<40) # set process table
251 data
, _
, _
= yield from pi_ld(dut
.submodules
.ldst
.pi
,
252 0x10000000, 8, msr
=msr_default
)
253 print ("radixmiss ld data", data
)
258 def ldst_sim_dcache_regression(dut
):
259 mmu
= dut
.submodules
.mmu
262 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
266 data
, _
, _
= yield from pi_ld(dut
.submodules
.ldst
.pi
, addr
, 8, msr
=msr_default
)
267 print ("=== dcache_regression ld data", data
)
268 assert(data
== 0xdeadbeef01234567)
273 def ldst_sim_dcache_random(dut
):
274 mmu
= dut
.submodules
.mmu
275 pi
= dut
.submodules
.ldst
.pi
278 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
284 addr
= randint(0, memsize
-1)
285 data
= randint(0, (1<<64)-1)
289 yield from pi_st(pi
, addr
, data
, 8, msr
=msr_default
)
292 ld_data
, _
, _
= yield from pi_ld(pi
, addr
, 8, msr
=msr_default
)
295 print ("dcache_random values", hex(addr
), hex(data
), hex(ld_data
), eq
)
296 assert(data
==ld_data
) ## investigate why this fails -- really seldom
301 def ldst_sim_dcache_first(dut
): # this test is likely to fail
302 mmu
= dut
.submodules
.mmu
303 pi
= dut
.submodules
.ldst
.pi
306 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
311 data
= 0x8c5a3e460d71f0b4
313 # known to fail without bugfix in src/soc/fu/ldst/loadstore.py
314 yield from pi_st(pi
, addr
, data
, 8, msr
=msr_default
)
317 ld_data
, _
, _
= yield from pi_ld(pi
, addr
, 8, msr
=msr_default
)
320 print ("dcache_first ld data", hex(data
), hex(ld_data
))
322 assert(data
==ld_data
)
327 def test_radixmiss_mmu():
329 m
, cmpi
= setup_mmu()
331 # virtual "memory" to use for this test
333 mem
= {0x10000: # PARTITION_TABLE_2
334 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
335 b(0x800000000100000b),
337 0x30000: # RADIX_ROOT_PTE
338 # V = 1 L = 0 NLB = 0x400 NLS = 9
339 b(0x8000000000040009),
341 0x40000: # RADIX_SECOND_LEVEL
342 # V = 1 L = 1 SW = 0 RPN = 0
343 # R = 1 C = 1 ATT = 0 EAA 0x7
344 b(0xc000000000000183),
346 0x1000000: # PROCESS_TABLE_3
347 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
348 b(0x40000000000300ad),
351 0x1000: 0xdeadbeef01234567,
352 0x1008: 0xfeedf00ff001a5a5
360 sim
.add_sync_process(wrap(ldst_sim_radixmiss(m
)))
361 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
362 with sim
.write_vcd('test_ldst_pi_radix_miss.vcd'):
365 def test_dcache_regression():
367 m
, cmpi
= setup_mmu()
369 # dcache_load at addr 0
371 0x10000: # PARTITION_TABLE_2
372 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
373 b(0x800000000100000b),
375 0x30000: # RADIX_ROOT_PTE
376 # V = 1 L = 0 NLB = 0x400 NLS = 9
377 b(0x8000000000040009),
379 0x40000: # RADIX_SECOND_LEVEL
380 # V = 1 L = 1 SW = 0 RPN = 0
381 # R = 1 C = 1 ATT = 0 EAA 0x7
382 b(0xc000000000000183),
384 0x1000000: # PROCESS_TABLE_3
385 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
386 b(0x40000000000300ad),
389 0x10000: 0xdeadbeef01234567,
390 0x10008: 0xfeedf00ff001a5a5
397 sim
.add_sync_process(wrap(ldst_sim_dcache_regression(m
)))
398 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
399 with sim
.write_vcd('test_ldst_pi_radix_miss.vcd'):
402 def test_dcache_random():
404 m
, cmpi
= setup_mmu()
406 # dcache_load at addr 0
408 0x10000: # PARTITION_TABLE_2
409 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
410 b(0x800000000100000b),
412 0x30000: # RADIX_ROOT_PTE
413 # V = 1 L = 0 NLB = 0x400 NLS = 9
414 b(0x8000000000040009),
416 0x40000: # RADIX_SECOND_LEVEL
417 # V = 1 L = 1 SW = 0 RPN = 0
418 # R = 1 C = 1 ATT = 0 EAA 0x7
419 b(0xc000000000000183),
421 0x1000000: # PROCESS_TABLE_3
422 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
423 b(0x40000000000300ad),
430 sim
.add_sync_process(wrap(ldst_sim_dcache_random(m
)))
431 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
432 with sim
.write_vcd('test_ldst_pi_random.vcd'):
435 def ldst_sim_dcache_random2(dut
, mem
):
436 mmu
= dut
.submodules
.mmu
437 pi
= dut
.submodules
.ldst
.pi
440 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
446 ## random values from a failed test
447 #[0x100e0,0xf553b658ba7e1f51,0,0], ## 1
448 #[0x10150,0x12c95a730df1cee7,0,0], ## 2
449 #[0x10080,0x5a921ae06674cd81,0,0], ## 3
450 #[0x100f8,0x4fea5eab80090fa5,0,0], ## 4
451 #[0x10080,0xd481432d17a340be,0,0], ## 5
452 #[0x10060,0x8553fcf29526fb32,0,0], ## 6
453 [0x101d0,0x327c967c8be30ded,0,0], ## 7
454 [0x101e0,0x8f15d8d05d25b151,1,0] ## 8
455 #uncommenting line 7 will cause the original test not to fail
466 print("== write: wb_get")
468 for i
in range(0,c1
):
469 print("before_pi_st")
472 yield from pi_st(pi
, addr
, data
, 8, msr
=msr_default
)
475 for i
in range(0,c2
):
476 print("before_pi_ld")
479 print("== read: wb_get")
480 ld_data
, _
, _
= yield from pi_ld(pi
, addr
, 8, msr
=msr_default
)
482 #dumpmem(mem,"/tmp/dumpmem"+str(c)+".txt")
486 print ("dcache_random values", hex(addr
), hex(data
), hex(ld_data
), eq
)
487 assert(data
==ld_data
) ## investigate why this fails -- really seldom
492 def test_dcache_random2():
494 m
, cmpi
= setup_mmu()
496 # dcache_load at addr 0
498 0x10000: # PARTITION_TABLE_2
499 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
500 b(0x800000000100000b),
502 0x30000: # RADIX_ROOT_PTE
503 # V = 1 L = 0 NLB = 0x400 NLS = 9
504 b(0x8000000000040009),
506 0x40000: # RADIX_SECOND_LEVEL
507 # V = 1 L = 1 SW = 0 RPN = 0
508 # R = 1 C = 1 ATT = 0 EAA 0x7
509 b(0xc000000000000183),
511 0x1000000: # PROCESS_TABLE_3
512 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
513 b(0x40000000000300ad),
515 ###0x101e0:0x8f15d8d05d25b152 ## flush cache -- then check again
522 sim
.add_sync_process(wrap(ldst_sim_dcache_random2(m
, mem
)))
523 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
524 with sim
.write_vcd('test_ldst_pi_random2.vcd'):
527 def test_dcache_first():
529 m
, cmpi
= setup_mmu()
531 # dcache_load at addr 0
533 0x10000: # PARTITION_TABLE_2
534 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
535 b(0x800000000100000b),
537 0x30000: # RADIX_ROOT_PTE
538 # V = 1 L = 0 NLB = 0x400 NLS = 9
539 b(0x8000000000040009),
541 0x40000: # RADIX_SECOND_LEVEL
542 # V = 1 L = 1 SW = 0 RPN = 0
543 # R = 1 C = 1 ATT = 0 EAA 0x7
544 b(0xc000000000000183),
546 0x1000000: # PROCESS_TABLE_3
547 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
548 b(0x40000000000300ad),
555 sim
.add_sync_process(wrap(ldst_sim_dcache_first(m
)))
556 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
557 with sim
.write_vcd('test_ldst_pi_first.vcd'):
560 if __name__
== '__main__':
564 ### tests taken from src/soc/experiment/test/test_dcache.py
565 test_dcache_regression()
567 test_dcache_random() #sometimes fails
568 test_dcache_random2() #reproduce error