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_random(dut
):
315 mmu
= dut
.submodules
.mmu
316 pi
= dut
.submodules
.ldst
.pi
320 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
325 for i
in range(1024):
326 addr
= randint(0, memsize
-1)
327 data
= randint(0, (1<<64)-1)
331 yield from pi_st(pi
, addr
, data
, 8, msr_pr
=1)
334 ld_data
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
337 print ("dcache_random random ld data", hex(data
), hex(ld_data
))
339 print("==== data read at random test differs")
340 #assert(data==ld_data)
345 def test_radixmiss_mmu():
347 m
, cmpi
= setup_mmu()
349 # virtual "memory" to use for this test
351 mem
= {0x10000: # PARTITION_TABLE_2
352 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
353 b(0x800000000100000b),
355 0x30000: # RADIX_ROOT_PTE
356 # V = 1 L = 0 NLB = 0x400 NLS = 9
357 b(0x8000000000040009),
359 0x40000: # RADIX_SECOND_LEVEL
360 # V = 1 L = 1 SW = 0 RPN = 0
361 # R = 1 C = 1 ATT = 0 EAA 0x7
362 b(0xc000000000000183),
364 0x1000000: # PROCESS_TABLE_3
365 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
366 b(0x40000000000300ad),
369 0x1000: 0xdeadbeef01234567,
370 0x1008: 0xfeedf00ff001a5a5
378 sim
.add_sync_process(wrap(ldst_sim_radixmiss(m
)))
379 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
380 with sim
.write_vcd('test_ldst_pi_radix_miss.vcd'):
383 def test_dcache_regression():
385 m
, cmpi
= setup_mmu()
387 # dcache_load at addr 0
389 0x10000: # PARTITION_TABLE_2
390 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
391 b(0x800000000100000b),
393 0x30000: # RADIX_ROOT_PTE
394 # V = 1 L = 0 NLB = 0x400 NLS = 9
395 b(0x8000000000040009),
397 0x40000: # RADIX_SECOND_LEVEL
398 # V = 1 L = 1 SW = 0 RPN = 0
399 # R = 1 C = 1 ATT = 0 EAA 0x7
400 b(0xc000000000000183),
402 0x1000000: # PROCESS_TABLE_3
403 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
404 b(0x40000000000300ad),
407 0x10000: 0xdeadbeef01234567,
408 0x10008: 0xfeedf00ff001a5a5
415 sim
.add_sync_process(wrap(ldst_sim_dcache_regression(m
)))
416 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
417 with sim
.write_vcd('test_ldst_pi_radix_miss.vcd'):
420 def test_dcache_random():
422 m
, cmpi
= setup_mmu()
424 # dcache_load at addr 0
426 0x10000: # PARTITION_TABLE_2
427 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
428 b(0x800000000100000b),
430 0x30000: # RADIX_ROOT_PTE
431 # V = 1 L = 0 NLB = 0x400 NLS = 9
432 b(0x8000000000040009),
434 0x40000: # RADIX_SECOND_LEVEL
435 # V = 1 L = 1 SW = 0 RPN = 0
436 # R = 1 C = 1 ATT = 0 EAA 0x7
437 b(0xc000000000000183),
439 0x1000000: # PROCESS_TABLE_3
440 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
441 b(0x40000000000300ad),
448 sim
.add_sync_process(wrap(ldst_sim_dcache_random(m
)))
449 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
450 with sim
.write_vcd('test_ldst_pi_radix_miss.vcd'):
453 if __name__
== '__main__':
457 ### tests taken from src/soc/experiment/test/test_dcache.py
458 test_dcache_regression()
459 test_dcache_random() #first access to memory fails - investigate