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
43 while True: # wait for dc_valid
51 addr
= (yield wb
.adr
) << 3
53 print (" WB LOOKUP NO entry @ %x, returning zero" % (addr
))
58 store
= (yield wb
.dat_w
)
60 data
= mem
.get(addr
, 0)
61 # note we assume 8-bit sel, here
70 print (" DCACHE set %x mask %x data %x" % (addr
, sel
, res
))
72 data
= mem
.get(addr
, 0)
73 yield wb
.dat_r
.eq(data
)
74 print (" DCACHE get %x data %x" % (addr
, data
))
82 def mmu_lookup(dut
, addr
):
83 mmu
= dut
.submodules
.mmu
86 print("pi_ld", hex(addr
))
87 data
= yield from pi_ld(dut
.submodules
.ldst
.pi
, addr
, 4, msr_pr
=1)
88 print("pi_ld done, data", hex(data
))
90 # original test code kept for reference
91 while not stop: # wait for dc_valid / err
92 print("waiting for mmu")
93 l_done = yield (mmu.l_out.done)
94 l_err = yield (mmu.l_out.err)
95 l_badtree = yield (mmu.l_out.badtree)
96 l_permerr = yield (mmu.l_out.perm_error)
97 l_rc_err = yield (mmu.l_out.rc_error)
98 l_segerr = yield (mmu.l_out.segerr)
99 l_invalid = yield (mmu.l_out.invalid)
100 if (l_done or l_err or l_badtree or
101 l_permerr or l_rc_err or l_segerr or l_invalid):
105 phys_addr
= yield mmu
.d_out
.addr
106 pte
= yield mmu
.d_out
.pte
107 l_done
= yield (mmu
.l_out
.done
)
108 l_err
= yield (mmu
.l_out
.err
)
109 l_badtree
= yield (mmu
.l_out
.badtree
)
110 print ("translated done %d err %d badtree %d addr %x pte %x" % \
111 (l_done
, l_err
, l_badtree
, phys_addr
, pte
))
113 yield mmu
.l_in
.valid
.eq(0)
119 mmu
= dut
.submodules
.mmu
121 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
124 # expecting this data to return
125 # 0x1000: 0xdeadbeef01234567,
126 # 0x1008: 0xfeedf00ff001a5a5
131 # TODO mmu_lookup using port interface
133 data
= yield from mmu_lookup(dut
, addr
)
134 assert data
== 0x1234567
136 data
= yield from mmu_lookup(dut
, addr
+8)
137 assert data
== 0xf001a5a5
138 #assert phys_addr == addr # happens to be the same (for this example)
140 data
= yield from mmu_lookup(dut
, addr
+4)
141 assert data
== 0xdeadbeef
143 data
= yield from mmu_lookup(dut
, addr
+8)
144 assert data
== 0xf001a5a5
146 yield from pi_st(dut
.submodules
.ldst
.pi
, addr
+4, 0x10015a5a, 4, msr_pr
=1)
148 data
= yield from mmu_lookup(dut
, addr
+4)
149 assert data
== 0x10015a5a
158 pspec
= TestMemPspec(ldst_ifacetype
='mmu_cache_wb',
161 #disable_cache=True, # hmmm...
167 cmpi
= ConfigMemoryPortInterface(pspec
)
168 m
.submodules
.ldst
= ldst
= cmpi
.pi
169 m
.submodules
.mmu
= mmu
= MMU()
172 l_in
, l_out
= mmu
.l_in
, mmu
.l_out
173 d_in
, d_out
= dcache
.d_in
, dcache
.d_out
174 wb_out
, wb_in
= dcache
.wb_out
, dcache
.wb_in
176 # link mmu and dcache together
177 m
.d
.comb
+= dcache
.m_in
.eq(mmu
.d_out
) # MMUToDCacheType
178 m
.d
.comb
+= mmu
.d_in
.eq(dcache
.m_out
) # DCacheToMMUType
180 # link ldst and MMU together
181 comb
+= l_in
.eq(ldst
.m_out
)
182 comb
+= ldst
.m_in
.eq(l_out
)
189 m
, cmpi
= setup_mmu()
191 # virtual "memory" to use for this test
193 mem
= {0x10000: # PARTITION_TABLE_2
194 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
195 b(0x800000000100000b),
197 0x30000: # RADIX_ROOT_PTE
198 # V = 1 L = 0 NLB = 0x400 NLS = 9
199 b(0x8000000000040009),
201 0x40000: # RADIX_SECOND_LEVEL
202 # V = 1 L = 1 SW = 0 RPN = 0
203 # R = 1 C = 1 ATT = 0 EAA 0x7
204 b(0xc000000000000183),
206 0x1000000: # PROCESS_TABLE_3
207 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
208 b(0x40000000000300ad),
211 0x1000: 0xdeadbeef01234567,
212 0x1008: 0xfeedf00ff001a5a5
220 sim
.add_sync_process(wrap(ldst_sim(m
)))
221 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
222 with sim
.write_vcd('test_ldst_pi.vcd'):
226 def ldst_sim_misalign(dut
):
227 mmu
= dut
.submodules
.mmu
231 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
234 data
= yield from pi_ld(dut
.submodules
.ldst
.pi
, 0x1007, 8, msr_pr
=1)
235 print ("misalign ld data", hex(data
))
241 def test_misalign_mmu():
243 m
, cmpi
= setup_mmu()
245 # virtual "memory" to use for this test
247 mem
= {0x10000: # PARTITION_TABLE_2
248 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
249 b(0x800000000100000b),
251 0x30000: # RADIX_ROOT_PTE
252 # V = 1 L = 0 NLB = 0x400 NLS = 9
253 b(0x8000000000040009),
255 0x40000: # RADIX_SECOND_LEVEL
256 # V = 1 L = 1 SW = 0 RPN = 0
257 # R = 1 C = 1 ATT = 0 EAA 0x7
258 b(0xc000000000000183),
260 0x1000000: # PROCESS_TABLE_3
261 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
262 b(0x40000000000300ad),
265 0x1000: 0xdeadbeef01234567,
266 0x1008: 0xfeedf00ff001a5a5
274 sim
.add_sync_process(wrap(ldst_sim_misalign(m
)))
275 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
276 with sim
.write_vcd('test_ldst_pi_misalign.vcd'):
280 def ldst_sim_radixmiss(dut
):
281 mmu
= dut
.submodules
.mmu
285 yield mmu
.rin
.prtbl
.eq(1<<40) # set process table
288 data
= yield from pi_ld(dut
.submodules
.ldst
.pi
, 0x10000000, 8, msr_pr
=1)
289 print ("radixmiss ld data", hex(data
))
294 def ldst_sim_dcache_regression(dut
):
295 mmu
= dut
.submodules
.mmu
299 yield mmu
.rin
.prtbl
.eq(1<<40) # set process table
302 data
= yield from pi_ld(dut
.submodules
.ldst
.pi
, 0, 8, msr_pr
=1)
303 print ("dcache_regression ld data", hex(data
))
304 # FIXME: this is 0 but should be 0xFFFFFFFFFFFFFFFF
309 def ldst_sim_dcache_random(dut
):
310 mmu
= dut
.submodules
.mmu
311 pi
= dut
.submodules
.ldst
.pi
315 yield mmu
.rin
.prtbl
.eq(1<<40) # set process table
320 for i
in range(1024):
321 addr
= randint(0, memsize
-1)
322 data
= randint(0, (1<<64)-1)
325 yield from pi_st(pi
, addr
, data
, 8, msr_pr
=1)
328 ld_data
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
330 print ("dcache_random random ld data", hex(data
), hex(read
))
336 def test_radixmiss_mmu():
338 m
, cmpi
= setup_mmu()
340 # virtual "memory" to use for this test
342 mem
= {0x10000: # PARTITION_TABLE_2
343 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
344 b(0x800000000100000b),
346 0x30000: # RADIX_ROOT_PTE
347 # V = 1 L = 0 NLB = 0x400 NLS = 9
348 b(0x8000000000040009),
350 0x40000: # RADIX_SECOND_LEVEL
351 # V = 1 L = 1 SW = 0 RPN = 0
352 # R = 1 C = 1 ATT = 0 EAA 0x7
353 b(0xc000000000000183),
355 0x1000000: # PROCESS_TABLE_3
356 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
357 b(0x40000000000300ad),
360 0x1000: 0xdeadbeef01234567,
361 0x1008: 0xfeedf00ff001a5a5
369 sim
.add_sync_process(wrap(ldst_sim_radixmiss(m
)))
370 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
371 with sim
.write_vcd('test_ldst_pi_radix_miss.vcd'):
374 def test_dcache_regression():
376 m
, cmpi
= setup_mmu()
378 # dcache_load at addr 0
380 0: 0xFFFFFFFFFFFFFFFF
387 sim
.add_sync_process(wrap(ldst_sim_dcache_regression(m
)))
388 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
389 with sim
.write_vcd('test_ldst_pi_radix_miss.vcd'):
392 def test_dcache_random():
394 m
, cmpi
= setup_mmu()
396 # dcache_load at addr 0
404 sim
.add_sync_process(wrap(ldst_sim_dcache_random(m
)))
405 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
406 with sim
.write_vcd('test_ldst_pi_radix_miss.vcd'):
409 if __name__
== '__main__':
413 ### tests taken from src/soc/experiment/test/test_dcache.py
414 test_dcache_regression()
415 #FIXME test_dcache_random()