1 from nmigen
import (C
, Module
, Signal
, Elaboratable
, Mux
, Cat
, Repl
, Signal
,
3 from nmigen
.cli
import main
4 from nmigen
.cli
import rtlil
5 from nmutil
.mask
import Mask
, masked
6 from nmutil
.util
import Display
7 from random
import randint
, seed
8 from nmigen
.sim
import Simulator
, Delay
, Settle
9 from nmutil
.util
import wrap
11 from soc
.config
.test
.test_pi2ls
import pi_ld
, pi_st
, pi_ldst
, wait_busy
12 #from soc.config.test.test_pi2ls import pi_st_debug
13 from soc
.config
.test
.test_loadstore
import TestMemPspec
14 from soc
.config
.loadstore
import ConfigMemoryPortInterface
16 from soc
.fu
.ldst
.loadstore
import LoadStore1
17 from soc
.experiment
.mmu
import MMU
18 from soc
.experiment
.test
import pagetables
20 from nmigen
.compat
.sim
import run_simulation
21 from random
import random
22 from openpower
.test
.wb_get
import wb_get
23 from openpower
.test
import wb_get
as wbget
30 pspec
= TestMemPspec(ldst_ifacetype
='mmu_cache_wb',
33 #disable_cache=True, # hmmm...
39 cmpi
= ConfigMemoryPortInterface(pspec
)
40 m
.submodules
.ldst
= ldst
= cmpi
.pi
41 m
.submodules
.mmu
= mmu
= MMU()
45 l_in
, l_out
= mmu
.l_in
, mmu
.l_out
46 d_in
, d_out
= dcache
.d_in
, dcache
.d_out
47 i_in
, i_out
= icache
.i_in
, icache
.i_out
# FetchToICache, ICacheToDecode
49 # link mmu, dcache and icache together
50 m
.d
.comb
+= dcache
.m_in
.eq(mmu
.d_out
) # MMUToDCacheType
51 m
.d
.comb
+= icache
.m_in
.eq(mmu
.i_out
) # MMUToICacheType
52 m
.d
.comb
+= mmu
.d_in
.eq(dcache
.m_out
) # DCacheToMMUType
54 # link ldst and MMU together
55 comb
+= l_in
.eq(ldst
.m_out
)
56 comb
+= ldst
.m_in
.eq(l_out
)
61 test_exceptions
= True
66 def _test_loadstore1_ifetch(dut
, mem
):
67 mmu
= dut
.submodules
.mmu
68 ldst
= dut
.submodules
.ldst
70 icache
= dut
.submodules
.ldst
.icache
73 print("=== test loadstore instruction (real) ===")
79 # first virtual memory test
81 print ("set process table")
82 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
85 # set address to zero, update mem[0] to 01234
87 expected_insn
= 0x1234
88 mem
[addr
] = expected_insn
90 yield i_in
.priv_mode
.eq(1)
92 yield i_in
.nia
.eq(addr
)
93 yield i_in
.stop_mark
.eq(0)
94 yield i_m_in
.tlbld
.eq(0)
95 yield i_m_in
.tlbie
.eq(0)
96 yield i_m_in
.addr
.eq(0)
97 yield i_m_in
.pte
.eq(0)
102 # miss, stalls for a bit
104 yield i_in
.nia
.eq(addr
)
106 valid
= yield i_out
.valid
109 valid
= yield i_out
.valid
112 nia
= yield i_out
.nia
113 insn
= yield i_out
.insn
117 print ("fetched %x from addr %x" % (insn
, nia
))
118 assert insn
== expected_insn
120 print("=== test loadstore instruction (virtual) ===")
122 # look up i-cache expecting it to fail
124 # set address to zero, update mem[0] to 01234
126 real_addr
= virt_addr
127 expected_insn
= 0x5678
128 mem
[real_addr
] = expected_insn
130 yield i_in
.priv_mode
.eq(1)
131 yield i_in
.virt_mode
.eq(1)
133 yield i_in
.nia
.eq(virt_addr
)
134 yield i_in
.stop_mark
.eq(0)
135 yield i_m_in
.tlbld
.eq(0)
136 yield i_m_in
.tlbie
.eq(0)
137 yield i_m_in
.addr
.eq(0)
138 yield i_m_in
.pte
.eq(0)
143 # miss, stalls for a bit
145 yield i_in
.nia
.eq(virt_addr
)
147 valid
= yield i_out
.valid
148 failed
= yield i_out
.fetch_failed
149 while not valid
and not failed
:
151 valid
= yield i_out
.valid
152 failed
= yield i_out
.fetch_failed
155 print ("failed?", "yes" if failed
else "no")
160 print("=== test loadstore instruction (instruction fault) ===")
164 yield mmu
.l_in
.iside
.eq(1)
165 yield mmu
.l_in
.load
.eq(1)
166 yield mmu
.l_in
.valid
.eq(1)
167 yield mmu
.l_in
.priv
.eq(1)
168 yield mmu
.l_in
.addr
.eq(virt_addr
)
169 #ld_data, exctype, exc = yield from pi_ld(pi, virt_addr, 8, msr_pr=1)
170 #yield ldst.iside.eq(0)
172 l_done
= yield (mmu
.l_out
.done
)
173 l_err
= yield (mmu
.l_out
.err
)
174 while not l_done
and not l_err
:
176 l_done
= yield (mmu
.l_out
.done
)
177 l_err
= yield (mmu
.l_out
.err
)
178 yield mmu
.l_in
.valid
.eq(0)
186 def _test_loadstore1_invalid(dut
, mem
):
187 mmu
= dut
.submodules
.mmu
188 pi
= dut
.submodules
.ldst
.pi
191 print("=== test invalid ===")
194 ld_data
, exctype
, exc
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
195 print("ld_data", ld_data
, exctype
, exc
)
196 assert (exctype
== "slow")
197 invalid
= exc
.invalid
198 assert (invalid
== 1)
200 print("=== test invalid done ===")
205 def _test_loadstore1(dut
, mem
):
206 mmu
= dut
.submodules
.mmu
207 pi
= dut
.submodules
.ldst
.pi
208 ldst
= dut
.submodules
.ldst
# to get at DAR (NOT part of PortInterface)
211 yield mmu
.rin
.prtbl
.eq(0x1000000) # set process table
215 data
= 0xf553b658ba7e1f51
218 yield from pi_st(pi
, addr
, data
, 8, msr_pr
=1)
221 ld_data
, exctype
, exc
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
222 assert ld_data
== 0xf553b658ba7e1f51
223 assert exctype
is None
225 ld_data
, exctype
, exc
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
226 assert ld_data
== 0xf553b658ba7e1f51
227 assert exctype
is None
229 print("do_dcbz ===============")
230 yield from pi_st(pi
, addr
, data
, 8, msr_pr
=1, is_dcbz
=1)
231 print("done_dcbz ===============")
234 ld_data
, exctype
, exc
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
235 print("ld_data after dcbz")
238 assert exctype
is None
241 print("=== alignment error (ld) ===")
243 ld_data
, exctype
, exc
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
245 alignment
= exc
.alignment
246 happened
= exc
.happened
247 yield # wait for dsr to update
253 assert (happened
== 1)
254 assert (alignment
== 1)
256 assert (exctype
== "fast")
257 yield from wait_busy(pi
, debug
="pi_ld_E_alignment_error")
258 # wait is only needed in case of in exception here
259 print("=== alignment error test passed (ld) ===")
261 # take some cycles in between so that gtkwave separates out
268 print("=== alignment error (st) ===")
270 exctype
, exc
= yield from pi_st(pi
, addr
,0, 8, msr_pr
=1)
272 alignment
= exc
.alignment
273 happened
= exc
.happened
277 assert (happened
== 1)
278 assert (alignment
==1)
280 assert (exctype
== "fast")
281 #???? yield from wait_busy(pi, debug="pi_st_E_alignment_error")
282 # wait is only needed in case of in exception here
283 print("=== alignment error test passed (st) ===")
287 print("=== no alignment error (ld) ===")
289 ld_data
, exctype
, exc
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
290 print("ld_data", ld_data
, exctype
, exc
)
292 alignment
= exc
.alignment
293 happened
= exc
.happened
297 assert (happened
== 0)
298 assert (alignment
== 0)
299 print("=== no alignment error done (ld) ===")
302 addrs
= [0x456920,0xa7a180,0x299420,0x1d9d60]
305 print("== RANDOM addr ==",hex(addr
))
306 ld_data
, exctype
, exc
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
307 print("ld_data[RANDOM]",ld_data
,exc
,addr
)
308 assert (exctype
== None)
311 print("== RANDOM addr ==",hex(addr
))
312 exc
= yield from pi_st(pi
, addr
,0xFF*addr
, 8, msr_pr
=1)
313 assert (exctype
== None)
315 # readback written data and compare
317 print("== RANDOM addr ==",hex(addr
))
318 ld_data
, exctype
, exc
= yield from pi_ld(pi
, addr
, 8, msr_pr
=1)
319 print("ld_data[RANDOM_READBACK]",ld_data
,exc
,addr
)
320 assert (exctype
== None)
321 assert (ld_data
== 0xFF*addr
)
323 print("== RANDOM addr done ==")
328 def test_loadstore1_ifetch():
330 m
, cmpi
= setup_mmu()
332 mem
= pagetables
.test1
338 icache
= m
.submodules
.ldst
.icache
339 sim
.add_sync_process(wrap(_test_loadstore1_ifetch(m
, mem
)))
340 # add two wb_get processes onto the *same* memory dictionary.
341 # this shouuuld work.... cross-fingers...
342 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
343 sim
.add_sync_process(wrap(wb_get(icache
.bus
, mem
)))
344 with sim
.write_vcd('test_loadstore1_ifetch.vcd'):
348 def test_loadstore1():
350 m
, cmpi
= setup_mmu()
352 mem
= pagetables
.test1
358 sim
.add_sync_process(wrap(_test_loadstore1(m
, mem
)))
359 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
360 with sim
.write_vcd('test_loadstore1.vcd'):
364 def test_loadstore1_invalid():
366 m
, cmpi
= setup_mmu()
374 sim
.add_sync_process(wrap(_test_loadstore1_invalid(m
, mem
)))
375 sim
.add_sync_process(wrap(wb_get(cmpi
.wb_bus(), mem
)))
376 with sim
.write_vcd('test_loadstore1_invalid.vcd'):
380 if __name__
== '__main__':
382 #test_loadstore1_invalid()
383 test_loadstore1_ifetch()