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
31 msr_default
= MSRSpec(pr
=1, dr
=0, sf
=1) # 64 bit by default
36 def b(x
): # byte-reverse function
37 return int.from_bytes(x
.to_bytes(8, byteorder
='little'),
38 byteorder
='big', signed
=False)
43 # f.write(str(hex(cell))+"="+str(hex(mem[cell]))+"\n")
46 def mmu_lookup(dut
, addr
):
47 mmu
= dut
.submodules
.mmu
49 print("pi_ld", hex(addr
))
50 data
, _
, _
= yield from pi_ld(dut
.submodules
.ldst
.pi
, addr
, 4, msr
=msr_default
)
51 print("pi_ld done, data", hex(data
))
53 # original test code kept for reference
54 while not wbget.stop: # wait for dc_valid / err
55 print("waiting for mmu")
56 l_done = yield (mmu.l_out.done)
57 l_err = yield (mmu.l_out.err)
58 l_badtree = yield (mmu.l_out.badtree)
59 l_permerr = yield (mmu.l_out.perm_error)
60 l_rc_err = yield (mmu.l_out.rc_error)
61 l_segerr = yield (mmu.l_out.segerr)
62 l_invalid = yield (mmu.l_out.invalid)
63 if (l_done or l_err or l_badtree or
64 l_permerr or l_rc_err or l_segerr or l_invalid):
68 phys_addr
= yield mmu
.d_out
.addr
69 pte
= yield mmu
.d_out
.pte
70 l_done
= yield (mmu
.l_out
.done
)
71 l_err
= yield (mmu
.l_out
.err
)
72 l_badtree
= yield (mmu
.l_out
.badtree
)
73 print ("translated done %d err %d badtree %d addr %x pte %x" % \
74 (l_done
, l_err
, l_badtree
, phys_addr
, pte
))
76 yield mmu
.l_in
.valid
.eq(0)
82 mmu
= dut
.submodules
.mmu
83 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
86 # expecting this data to return
87 # 0x1000: 0xdeadbeef01234567,
88 # 0x1008: 0xfeedf00ff001a5a5
93 # TODO mmu_lookup using port interface
95 data
= yield from mmu_lookup(dut
, addr
)
96 assert data
== 0x1234567
98 data
= yield from mmu_lookup(dut
, addr
+8)
99 assert data
== 0xf001a5a5
100 #assert phys_addr == addr # happens to be the same (for this example)
102 data
= yield from mmu_lookup(dut
, addr
+4)
103 assert data
== 0xdeadbeef
105 data
= yield from mmu_lookup(dut
, addr
+8)
106 assert data
== 0xf001a5a5
108 yield from pi_st(dut
.submodules
.ldst
.pi
, addr
+4, 0x10015a5a, 4, msr
=msr_default
)
110 data
= yield from mmu_lookup(dut
, addr
+4)
111 assert data
== 0x10015a5a
122 pspec
= TestMemPspec(ldst_ifacetype
='mmu_cache_wb',
125 #disable_cache=True, # hmmm...
131 cmpi
= ConfigMemoryPortInterface(pspec
)
132 m
.submodules
.ldst
= ldst
= cmpi
.pi
133 m
.submodules
.mmu
= mmu
= MMU()
136 l_in
, l_out
= mmu
.l_in
, mmu
.l_out
137 d_in
, d_out
= dcache
.d_in
, dcache
.d_out
139 # link mmu and dcache together
140 m
.d
.comb
+= dcache
.m_in
.eq(mmu
.d_out
) # MMUToDCacheType
141 m
.d
.comb
+= mmu
.d_in
.eq(dcache
.m_out
) # DCacheToMMUType
143 # link ldst and MMU together
144 comb
+= l_in
.eq(ldst
.m_out
)
145 comb
+= ldst
.m_in
.eq(l_out
)
152 m
, cmpi
= setup_mmu()
154 # virtual "memory" to use for this test
156 mem
= {0x10000: # PARTITION_TABLE_2
157 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
158 b(0x800000000100000b),
160 0x30000: # RADIX_ROOT_PTE
161 # V = 1 L = 0 NLB = 0x400 NLS = 9
162 b(0x8000000000040009),
164 0x40000: # RADIX_SECOND_LEVEL
165 # V = 1 L = 1 SW = 0 RPN = 0
166 # R = 1 C = 1 ATT = 0 EAA 0x7
167 b(0xc000000000000183),
169 0x1000000: # PROCESS_TABLE_3
170 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
171 b(0x40000000000300ad),
174 0x1000: 0xdeadbeef01234567,
175 0x1008: 0xfeedf00ff001a5a5
183 sim
.add_sync_process(wrap(ldst_sim(m
)))
184 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
185 with sim
.write_vcd('test_ldst_pi.vcd'):
189 def ldst_sim_misalign(dut
):
190 mmu
= dut
.submodules
.mmu
193 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
196 data
, _
, _
= yield from pi_ld(dut
.submodules
.ldst
.pi
, 0x1007, 8, msr_default
)
197 print ("misalign ld data", data
)
203 def test_misalign_mmu():
205 m
, cmpi
= setup_mmu()
207 # virtual "memory" to use for this test
209 mem
= {0x10000: # PARTITION_TABLE_2
210 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
211 b(0x800000000100000b),
213 0x30000: # RADIX_ROOT_PTE
214 # V = 1 L = 0 NLB = 0x400 NLS = 9
215 b(0x8000000000040009),
217 0x40000: # RADIX_SECOND_LEVEL
218 # V = 1 L = 1 SW = 0 RPN = 0
219 # R = 1 C = 1 ATT = 0 EAA 0x7
220 b(0xc000000000000183),
222 0x1000000: # PROCESS_TABLE_3
223 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
224 b(0x40000000000300ad),
227 0x1000: 0xdeadbeef01234567,
228 0x1008: 0xfeedf00ff001a5a5
236 sim
.add_sync_process(wrap(ldst_sim_misalign(m
)))
237 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
238 with sim
.write_vcd('test_ldst_pi_misalign.vcd'):
242 def ldst_sim_radixmiss(dut
):
243 mmu
= dut
.submodules
.mmu
246 yield mmu
.rin
.prtbl
.eq(1<<40) # set process table
249 data
, _
, _
= yield from pi_ld(dut
.submodules
.ldst
.pi
,
250 0x10000000, 8, msr
=msr_default
)
251 print ("radixmiss ld data", data
)
256 def ldst_sim_dcache_regression(dut
):
257 mmu
= dut
.submodules
.mmu
260 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
264 data
, _
, _
= yield from pi_ld(dut
.submodules
.ldst
.pi
, addr
, 8, msr
=msr_default
)
265 print ("=== dcache_regression ld data", data
)
266 assert(data
== 0xdeadbeef01234567)
271 def ldst_sim_dcache_random(dut
):
272 mmu
= dut
.submodules
.mmu
273 pi
= dut
.submodules
.ldst
.pi
276 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
282 addr
= randint(0, memsize
-1)
283 data
= randint(0, (1<<64)-1)
287 yield from pi_st(pi
, addr
, data
, 8, msr
=msr_default
)
290 ld_data
, _
, _
= yield from pi_ld(pi
, addr
, 8, msr
=msr_default
)
293 print ("dcache_random values", hex(addr
), hex(data
), hex(ld_data
), eq
)
294 assert(data
==ld_data
) ## investigate why this fails -- really seldom
299 def ldst_sim_dcache_first(dut
): # this test is likely to fail
300 mmu
= dut
.submodules
.mmu
301 pi
= dut
.submodules
.ldst
.pi
304 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
309 data
= 0x8c5a3e460d71f0b4
311 # known to fail without bugfix in src/soc/fu/ldst/loadstore.py
312 yield from pi_st(pi
, addr
, data
, 8, msr
=msr_default
)
315 ld_data
, _
, _
= yield from pi_ld(pi
, addr
, 8, msr
=msr_default
)
318 print ("dcache_first ld data", hex(data
), hex(ld_data
))
320 assert(data
==ld_data
)
325 def test_radixmiss_mmu():
327 m
, cmpi
= setup_mmu()
329 # virtual "memory" to use for this test
331 mem
= {0x10000: # PARTITION_TABLE_2
332 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
333 b(0x800000000100000b),
335 0x30000: # RADIX_ROOT_PTE
336 # V = 1 L = 0 NLB = 0x400 NLS = 9
337 b(0x8000000000040009),
339 0x40000: # RADIX_SECOND_LEVEL
340 # V = 1 L = 1 SW = 0 RPN = 0
341 # R = 1 C = 1 ATT = 0 EAA 0x7
342 b(0xc000000000000183),
344 0x1000000: # PROCESS_TABLE_3
345 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
346 b(0x40000000000300ad),
349 0x1000: 0xdeadbeef01234567,
350 0x1008: 0xfeedf00ff001a5a5
358 sim
.add_sync_process(wrap(ldst_sim_radixmiss(m
)))
359 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
360 with sim
.write_vcd('test_ldst_pi_radix_miss.vcd'):
363 def test_dcache_regression():
365 m
, cmpi
= setup_mmu()
367 # dcache_load at addr 0
369 0x10000: # PARTITION_TABLE_2
370 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
371 b(0x800000000100000b),
373 0x30000: # RADIX_ROOT_PTE
374 # V = 1 L = 0 NLB = 0x400 NLS = 9
375 b(0x8000000000040009),
377 0x40000: # RADIX_SECOND_LEVEL
378 # V = 1 L = 1 SW = 0 RPN = 0
379 # R = 1 C = 1 ATT = 0 EAA 0x7
380 b(0xc000000000000183),
382 0x1000000: # PROCESS_TABLE_3
383 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
384 b(0x40000000000300ad),
387 0x10000: 0xdeadbeef01234567,
388 0x10008: 0xfeedf00ff001a5a5
395 sim
.add_sync_process(wrap(ldst_sim_dcache_regression(m
)))
396 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
397 with sim
.write_vcd('test_ldst_pi_radix_miss.vcd'):
400 def test_dcache_random():
402 m
, cmpi
= setup_mmu()
404 # dcache_load at addr 0
406 0x10000: # PARTITION_TABLE_2
407 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
408 b(0x800000000100000b),
410 0x30000: # RADIX_ROOT_PTE
411 # V = 1 L = 0 NLB = 0x400 NLS = 9
412 b(0x8000000000040009),
414 0x40000: # RADIX_SECOND_LEVEL
415 # V = 1 L = 1 SW = 0 RPN = 0
416 # R = 1 C = 1 ATT = 0 EAA 0x7
417 b(0xc000000000000183),
419 0x1000000: # PROCESS_TABLE_3
420 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
421 b(0x40000000000300ad),
428 sim
.add_sync_process(wrap(ldst_sim_dcache_random(m
)))
429 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
430 with sim
.write_vcd('test_ldst_pi_random.vcd'):
433 def ldst_sim_dcache_random2(dut
, mem
):
434 mmu
= dut
.submodules
.mmu
435 pi
= dut
.submodules
.ldst
.pi
438 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
444 ## random values from a failed test
445 #[0x100e0,0xf553b658ba7e1f51,0,0], ## 1
446 #[0x10150,0x12c95a730df1cee7,0,0], ## 2
447 #[0x10080,0x5a921ae06674cd81,0,0], ## 3
448 #[0x100f8,0x4fea5eab80090fa5,0,0], ## 4
449 #[0x10080,0xd481432d17a340be,0,0], ## 5
450 #[0x10060,0x8553fcf29526fb32,0,0], ## 6
451 [0x101d0,0x327c967c8be30ded,0,0], ## 7
452 [0x101e0,0x8f15d8d05d25b151,1,0] ## 8
453 #uncommenting line 7 will cause the original test not to fail
464 print("== write: wb_get")
466 for i
in range(0,c1
):
467 print("before_pi_st")
470 yield from pi_st(pi
, addr
, data
, 8, msr
=msr_default
)
473 for i
in range(0,c2
):
474 print("before_pi_ld")
477 print("== read: wb_get")
478 ld_data
, _
, _
= yield from pi_ld(pi
, addr
, 8, msr
=msr_default
)
480 #dumpmem(mem,"/tmp/dumpmem"+str(c)+".txt")
484 print ("dcache_random values", hex(addr
), hex(data
), hex(ld_data
), eq
)
485 assert(data
==ld_data
) ## investigate why this fails -- really seldom
490 def test_dcache_random2():
492 m
, cmpi
= setup_mmu()
494 # dcache_load at addr 0
496 0x10000: # PARTITION_TABLE_2
497 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
498 b(0x800000000100000b),
500 0x30000: # RADIX_ROOT_PTE
501 # V = 1 L = 0 NLB = 0x400 NLS = 9
502 b(0x8000000000040009),
504 0x40000: # RADIX_SECOND_LEVEL
505 # V = 1 L = 1 SW = 0 RPN = 0
506 # R = 1 C = 1 ATT = 0 EAA 0x7
507 b(0xc000000000000183),
509 0x1000000: # PROCESS_TABLE_3
510 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
511 b(0x40000000000300ad),
513 ###0x101e0:0x8f15d8d05d25b152 ## flush cache -- then check again
520 sim
.add_sync_process(wrap(ldst_sim_dcache_random2(m
, mem
)))
521 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
522 with sim
.write_vcd('test_ldst_pi_random2.vcd'):
525 def test_dcache_first():
527 m
, cmpi
= setup_mmu()
529 # dcache_load at addr 0
531 0x10000: # PARTITION_TABLE_2
532 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
533 b(0x800000000100000b),
535 0x30000: # RADIX_ROOT_PTE
536 # V = 1 L = 0 NLB = 0x400 NLS = 9
537 b(0x8000000000040009),
539 0x40000: # RADIX_SECOND_LEVEL
540 # V = 1 L = 1 SW = 0 RPN = 0
541 # R = 1 C = 1 ATT = 0 EAA 0x7
542 b(0xc000000000000183),
544 0x1000000: # PROCESS_TABLE_3
545 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
546 b(0x40000000000300ad),
553 sim
.add_sync_process(wrap(ldst_sim_dcache_first(m
)))
554 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
555 with sim
.write_vcd('test_ldst_pi_first.vcd'):
558 if __name__
== '__main__':
562 ### tests taken from src/soc/experiment/test/test_dcache.py
563 test_dcache_regression()
565 test_dcache_random() #sometimes fails
566 test_dcache_random2() #reproduce error