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
15 from nmigen
.back
.pysim
import Simulator
, Delay
, Settle
17 from nmigen
.sim
.cxxsim
import Simulator
, Delay
, Settle
18 from nmutil
.util
import wrap
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
24 from soc
.fu
.ldst
.loadstore
import LoadStore1
25 from soc
.experiment
.mmu
import MMU
27 from nmigen
.compat
.sim
import run_simulation
32 def b(x
): # byte-reverse function
33 return int.from_bytes(x
.to_bytes(8, byteorder
='little'),
34 byteorder
='big', signed
=False)
37 """simulator process for getting memory load requests
44 while True: # wait for dc_valid
52 addr
= (yield wb
.adr
) << 3
54 print (" WB LOOKUP NO entry @ %x, returning zero" % (addr
))
59 store
= (yield wb
.dat_w
)
61 data
= mem
.get(addr
, 0)
62 # note we assume 8-bit sel, here
71 print (" DCACHE set %x mask %x data %x" % (addr
, sel
, res
))
73 data
= mem
.get(addr
, 0)
74 yield wb
.dat_r
.eq(data
)
75 print (" DCACHE get %x data %x" % (addr
, data
))
83 def mmu_lookup(dut
, addr
):
84 mmu
= dut
.submodules
.mmu
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
))
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):
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
))
114 yield mmu
.l_in
.valid
.eq(0)
120 mmu
= dut
.submodules
.mmu
122 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
125 # expecting this data to return
126 # 0x1000: 0xdeadbeef01234567,
127 # 0x1008: 0xfeedf00ff001a5a5
132 # TODO mmu_lookup using port interface
134 data
= yield from mmu_lookup(dut
, addr
)
135 assert data
== 0x1234567
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)
141 data
= yield from mmu_lookup(dut
, addr
+4)
142 assert data
== 0xdeadbeef
144 data
= yield from mmu_lookup(dut
, addr
+8)
145 assert data
== 0xf001a5a5
147 yield from pi_st(dut
.submodules
.ldst
.pi
, addr
+4, 0x10015a5a, 4, msr_pr
=1)
149 data
= yield from mmu_lookup(dut
, addr
+4)
150 assert data
== 0x10015a5a
162 pspec
= TestMemPspec(ldst_ifacetype
='mmu_cache_wb',
165 #disable_cache=True, # hmmm...
171 cmpi
= ConfigMemoryPortInterface(pspec
)
172 m
.submodules
.ldst
= ldst
= cmpi
.pi
173 m
.submodules
.mmu
= mmu
= MMU()
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
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
184 # link ldst and MMU together
185 comb
+= l_in
.eq(ldst
.m_out
)
186 comb
+= ldst
.m_in
.eq(l_out
)
193 m
, cmpi
= setup_mmu()
195 # virtual "memory" to use for this test
197 mem
= {0x10000: # PARTITION_TABLE_2
198 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
199 b(0x800000000100000b),
201 0x30000: # RADIX_ROOT_PTE
202 # V = 1 L = 0 NLB = 0x400 NLS = 9
203 b(0x8000000000040009),
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),
210 0x1000000: # PROCESS_TABLE_3
211 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
212 b(0x40000000000300ad),
215 0x1000: 0xdeadbeef01234567,
216 0x1008: 0xfeedf00ff001a5a5
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'):
230 def ldst_sim_misalign(dut
):
231 mmu
= dut
.submodules
.mmu
235 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
238 data
= yield from pi_ld(dut
.submodules
.ldst
.pi
, 0x1007, 8, msr_pr
=1)
239 print ("misalign ld data", hex(data
))
245 def test_misalign_mmu():
247 m
, cmpi
= setup_mmu()
249 # virtual "memory" to use for this test
251 mem
= {0x10000: # PARTITION_TABLE_2
252 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
253 b(0x800000000100000b),
255 0x30000: # RADIX_ROOT_PTE
256 # V = 1 L = 0 NLB = 0x400 NLS = 9
257 b(0x8000000000040009),
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),
264 0x1000000: # PROCESS_TABLE_3
265 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
266 b(0x40000000000300ad),
269 0x1000: 0xdeadbeef01234567,
270 0x1008: 0xfeedf00ff001a5a5
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'):
284 def ldst_sim_radixmiss(dut
):
285 mmu
= dut
.submodules
.mmu
289 yield mmu
.rin
.prtbl
.eq(1<<40) # set process table
292 data
= yield from pi_ld(dut
.submodules
.ldst
.pi
, 0x10000000, 8, msr_pr
=1)
293 print ("radixmiss ld data", hex(data
))
298 def ldst_sim_dcache_regression(dut
):
299 mmu
= dut
.submodules
.mmu
303 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
307 data
= yield from pi_ld(dut
.submodules
.ldst
.pi
, addr
, 8, msr_pr
=1)
308 print ("=== dcache_regression ld data", hex(data
))
309 assert(data
== 0xdeadbeef01234567)
314 def ldst_sim_dcache_random2(dut
):
315 mmu
= dut
.submodules
.mmu
316 pi
= dut
.submodules
.ldst
.pi
320 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
326 ## random values from a failed test
327 [0x100e0,0xf553b658ba7e1f51],
328 [0x10150,0x12c95a730df1cee7],
329 [0x10080,0x5a921ae06674cd81],
330 [0x100f8,0x4fea5eab80090fa5],
331 [0x10080,0xd481432d17a340be],
332 [0x10060,0x8553fcf29526fb32],
333 # [0x101d0,0x327c967c8be30ded],
334 [0x101e0,0x8f15d8d05d25b151]
341 yield from pi_st(pi
, addr
, data
, 8, msr_pr
=1)
344 ld_data
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
346 print ("dcache_random values", hex(addr
), hex(data
), hex(ld_data
), data
==ld_data
)
347 assert(data
==ld_data
) ## investigate why this fails -- really seldom
352 def ldst_sim_dcache_random(dut
):
353 mmu
= dut
.submodules
.mmu
354 pi
= dut
.submodules
.ldst
.pi
358 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
364 addr
= randint(0, memsize
-1)
365 data
= randint(0, (1<<64)-1)
369 yield from pi_st(pi
, addr
, data
, 8, msr_pr
=1)
372 ld_data
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
374 print ("dcache_random values", hex(addr
), hex(data
), hex(ld_data
), data
==ld_data
)
375 assert(data
==ld_data
) ## investigate why this fails -- really seldom
380 def ldst_sim_dcache_first(dut
): # this test is likely to fail
381 mmu
= dut
.submodules
.mmu
382 pi
= dut
.submodules
.ldst
.pi
386 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
391 data
= 0x8c5a3e460d71f0b4
393 # known to fail without bugfix in src/soc/fu/ldst/loadstore.py
394 yield from pi_st(pi
, addr
, data
, 8, msr_pr
=1)
397 ld_data
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
400 print ("dcache_first ld data", hex(data
), hex(ld_data
))
402 assert(data
==ld_data
)
407 def test_radixmiss_mmu():
409 m
, cmpi
= setup_mmu()
411 # virtual "memory" to use for this test
413 mem
= {0x10000: # PARTITION_TABLE_2
414 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
415 b(0x800000000100000b),
417 0x30000: # RADIX_ROOT_PTE
418 # V = 1 L = 0 NLB = 0x400 NLS = 9
419 b(0x8000000000040009),
421 0x40000: # RADIX_SECOND_LEVEL
422 # V = 1 L = 1 SW = 0 RPN = 0
423 # R = 1 C = 1 ATT = 0 EAA 0x7
424 b(0xc000000000000183),
426 0x1000000: # PROCESS_TABLE_3
427 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
428 b(0x40000000000300ad),
431 0x1000: 0xdeadbeef01234567,
432 0x1008: 0xfeedf00ff001a5a5
440 sim
.add_sync_process(wrap(ldst_sim_radixmiss(m
)))
441 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
442 with sim
.write_vcd('test_ldst_pi_radix_miss.vcd'):
445 def test_dcache_regression():
447 m
, cmpi
= setup_mmu()
449 # dcache_load at addr 0
451 0x10000: # PARTITION_TABLE_2
452 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
453 b(0x800000000100000b),
455 0x30000: # RADIX_ROOT_PTE
456 # V = 1 L = 0 NLB = 0x400 NLS = 9
457 b(0x8000000000040009),
459 0x40000: # RADIX_SECOND_LEVEL
460 # V = 1 L = 1 SW = 0 RPN = 0
461 # R = 1 C = 1 ATT = 0 EAA 0x7
462 b(0xc000000000000183),
464 0x1000000: # PROCESS_TABLE_3
465 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
466 b(0x40000000000300ad),
469 0x10000: 0xdeadbeef01234567,
470 0x10008: 0xfeedf00ff001a5a5
477 sim
.add_sync_process(wrap(ldst_sim_dcache_regression(m
)))
478 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
479 with sim
.write_vcd('test_ldst_pi_radix_miss.vcd'):
482 def test_dcache_random():
484 m
, cmpi
= setup_mmu()
486 # dcache_load at addr 0
488 0x10000: # PARTITION_TABLE_2
489 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
490 b(0x800000000100000b),
492 0x30000: # RADIX_ROOT_PTE
493 # V = 1 L = 0 NLB = 0x400 NLS = 9
494 b(0x8000000000040009),
496 0x40000: # RADIX_SECOND_LEVEL
497 # V = 1 L = 1 SW = 0 RPN = 0
498 # R = 1 C = 1 ATT = 0 EAA 0x7
499 b(0xc000000000000183),
501 0x1000000: # PROCESS_TABLE_3
502 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
503 b(0x40000000000300ad),
510 sim
.add_sync_process(wrap(ldst_sim_dcache_random(m
)))
511 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
512 with sim
.write_vcd('test_ldst_pi_random.vcd'):
515 def test_dcache_random2():
517 m
, cmpi
= setup_mmu()
519 # dcache_load at addr 0
521 0x10000: # PARTITION_TABLE_2
522 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
523 b(0x800000000100000b),
525 0x30000: # RADIX_ROOT_PTE
526 # V = 1 L = 0 NLB = 0x400 NLS = 9
527 b(0x8000000000040009),
529 0x40000: # RADIX_SECOND_LEVEL
530 # V = 1 L = 1 SW = 0 RPN = 0
531 # R = 1 C = 1 ATT = 0 EAA 0x7
532 b(0xc000000000000183),
534 0x1000000: # PROCESS_TABLE_3
535 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
536 b(0x40000000000300ad),
543 sim
.add_sync_process(wrap(ldst_sim_dcache_random2(m
)))
544 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
545 with sim
.write_vcd('test_ldst_pi_random2.vcd'):
548 def test_dcache_first():
550 m
, cmpi
= setup_mmu()
552 # dcache_load at addr 0
554 0x10000: # PARTITION_TABLE_2
555 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
556 b(0x800000000100000b),
558 0x30000: # RADIX_ROOT_PTE
559 # V = 1 L = 0 NLB = 0x400 NLS = 9
560 b(0x8000000000040009),
562 0x40000: # RADIX_SECOND_LEVEL
563 # V = 1 L = 1 SW = 0 RPN = 0
564 # R = 1 C = 1 ATT = 0 EAA 0x7
565 b(0xc000000000000183),
567 0x1000000: # PROCESS_TABLE_3
568 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
569 b(0x40000000000300ad),
576 sim
.add_sync_process(wrap(ldst_sim_dcache_first(m
)))
577 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
578 with sim
.write_vcd('test_ldst_pi_first.vcd'):
581 if __name__
== '__main__':
585 ### tests taken from src/soc/experiment/test/test_dcache.py
586 test_dcache_regression()
588 test_dcache_random() #sometimes fails
589 test_dcache_random2() #reproduce error