8795c9423e6366ef43dbdec5a25e822451b5a9aa
[soc.git] / src / soc / experiment / test / test_loadstore1.py
1 from nmigen import (C, Module, Signal, Elaboratable, Mux, Cat, Repl, Signal,
2 Const)
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
10
11 from soc.config.test.test_pi2ls import (pi_ld, pi_st, pi_ldst, wait_busy,
12 get_exception_info)
13 #from soc.config.test.test_pi2ls import pi_st_debug
14 from soc.config.test.test_loadstore import TestMemPspec
15 from soc.config.loadstore import ConfigMemoryPortInterface
16
17 from soc.fu.ldst.loadstore import LoadStore1
18 from soc.experiment.mmu import MMU
19 from soc.experiment.test import pagetables
20
21 from nmigen.compat.sim import run_simulation
22 from random import random
23 from openpower.test.wb_get import wb_get
24 from openpower.test import wb_get as wbget
25 from openpower.exceptions import LDSTExceptionTuple
26
27
28 def setup_mmu():
29
30 wbget.stop = False
31
32 pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
33 imem_ifacetype='',
34 addr_wid=48,
35 #disable_cache=True, # hmmm...
36 mask_wid=8,
37 reg_wid=64)
38
39 m = Module()
40 comb = m.d.comb
41 cmpi = ConfigMemoryPortInterface(pspec)
42 m.submodules.ldst = ldst = cmpi.pi
43 m.submodules.mmu = mmu = MMU()
44 dcache = ldst.dcache
45 icache = ldst.icache
46
47 l_in, l_out = mmu.l_in, mmu.l_out
48 d_in, d_out = dcache.d_in, dcache.d_out
49 i_in, i_out = icache.i_in, icache.i_out # FetchToICache, ICacheToDecode
50
51 # link mmu, dcache and icache together
52 m.d.comb += dcache.m_in.eq(mmu.d_out) # MMUToDCacheType
53 m.d.comb += icache.m_in.eq(mmu.i_out) # MMUToICacheType
54 m.d.comb += mmu.d_in.eq(dcache.m_out) # DCacheToMMUType
55
56 # link ldst and MMU together
57 comb += l_in.eq(ldst.m_out)
58 comb += ldst.m_in.eq(l_out)
59
60 # add a debug status Signal: use "msg.str = "blah"
61 # then toggle with yield msg.eq(0); yield msg.eq(1)
62 debug_status = Signal(8, decoder=lambda _ : debug_status.str)
63 m.debug_status = debug_status
64 debug_status.str = ''
65
66 return m, cmpi
67
68
69 def icache_read(dut,addr,priv,virt):
70
71 icache = dut.submodules.ldst.icache
72 i_in = icache.i_in
73 i_out = icache.i_out
74
75 yield i_in.priv_mode.eq(priv)
76 yield i_in.virt_mode.eq(virt)
77 yield i_in.req.eq(1)
78 yield i_in.nia.eq(addr)
79 yield i_in.stop_mark.eq(0)
80
81 yield i_in.req.eq(1)
82 yield i_in.nia.eq(addr)
83 yield
84 valid = yield i_out.valid
85 failed = yield i_out.fetch_failed
86 while not valid and not failed:
87 yield
88 valid = yield i_out.valid
89 failed = yield i_out.fetch_failed
90 yield i_in.req.eq(0)
91
92 nia = yield i_out.nia
93 insn = yield i_out.insn
94 yield
95 yield
96
97 return nia, insn, valid, failed
98
99
100 test_exceptions = True
101 test_dcbz = True
102 test_random = True
103
104
105 def debug(dut, msg):
106 print ("set debug message", msg)
107 dut.debug_status.str = msg # set the message
108 yield dut.debug_status.eq(0) # trigger an update
109 yield dut.debug_status.eq(1)
110
111
112 def _test_loadstore1_ifetch_iface(dut, mem):
113 """test_loadstore1_ifetch_iface
114
115 read in priv mode, non-virtual. tests the FetchUnitInterface
116
117 """
118
119 mmu = dut.submodules.mmu
120 ldst = dut.submodules.ldst
121 pi = ldst.pi
122 icache = dut.submodules.ldst.icache
123 wbget.stop = False
124
125
126 print("=== test loadstore instruction (real) ===")
127
128 i_in = icache.i_in
129 i_out = icache.i_out
130 i_m_in = icache.m_in
131
132 yield from debug(dut, "real mem instruction")
133 # set address to zero, update mem[0] to 01234
134 addr = 8
135 expected_insn = 0x1234
136 mem[addr] = expected_insn
137
138 yield i_in.priv_mode.eq(1)
139 yield i_in.req.eq(0) # NO, must use FetchUnitInterface
140 yield i_in.nia.eq(addr) # NO, must use FetchUnitInterface
141 yield i_in.stop_mark.eq(0) # NO, must use FetchUnitInterface
142 yield i_m_in.tlbld.eq(0)
143 yield i_m_in.tlbie.eq(0)
144 yield i_m_in.addr.eq(0)
145 yield i_m_in.pte.eq(0)
146 yield
147 yield
148 yield
149
150 # miss, stalls for a bit -- this one is different here
151 ##nia, insn, valid, failed = yield from icache_read(dut,addr,0,0)
152 ##assert(valid==0)
153 ##assert(failed==1)
154
155 yield i_in.req.eq(1) # NO, must use FetchUnitInterface
156 yield i_in.nia.eq(addr) # NO, must use FetchUnitInterface
157 yield
158 valid = yield i_out.valid # NO, must use FetchUnitInterface
159 while not valid: # NO, must use FetchUnitInterface
160 yield # NO, must use FetchUnitInterface
161 valid = yield i_out.valid # NO, must use FetchUnitInterface
162 yield i_in.req.eq(0) # NO, must use FetchUnitInterface
163
164 nia = yield i_out.nia # NO, must use FetchUnitInterface
165 insn = yield i_out.insn # NO, must use FetchUnitInterface
166 yield
167 yield
168
169 print ("fetched %x from addr %x" % (insn, nia))
170 assert insn == expected_insn
171
172 print("=== test loadstore instruction (done) ===")
173
174 yield from debug(dut, "test done")
175 yield
176 yield
177
178 print ("failed?", "yes" if failed else "no")
179 assert failed == 0
180
181 print ("fetched %x from addr %x" % (insn, nia))
182 assert insn == expected_insn
183
184 wbget.stop = True
185
186
187 def _test_loadstore1_ifetch(dut, mem):
188 """test_loadstore1_ifetch
189
190 this is quite a complex multi-step test.
191
192 * first (just because, as a demo) read in priv mode, non-virtual.
193 just like in experiment/icache.py itself.
194
195 * second, using the (usual) PTE for these things (which came originally
196 from gem5-experimental experiment/radix_walk_example.txt) do a
197 virtual-memory read through the *instruction* cache.
198 this is expected to FAIL
199
200 * third: mess about with the MMU, setting "iside" (instruction-side),
201 requesting an MMU RADIX LOOKUP. this triggers an itlb_load
202 (instruction-cache TLB entry-insertion)
203
204 * fourth and finally: retry the read of the instruction through i-cache.
205 this is now expected to SUCCEED
206
207 a lot going on.
208 """
209
210 mmu = dut.submodules.mmu
211 ldst = dut.submodules.ldst
212 pi = ldst.pi
213 icache = dut.submodules.ldst.icache
214 wbget.stop = False
215
216 print("=== test loadstore instruction (real) ===")
217
218 i_in = icache.i_in
219 i_out = icache.i_out
220 i_m_in = icache.m_in
221
222 # first virtual memory test
223
224 print ("set process table")
225 yield from debug(dut, "set prtble")
226 yield mmu.rin.prtbl.eq(0x1000000) # set process table
227 yield
228
229 yield from debug(dut, "real mem instruction")
230 # set address to zero, update mem[0] to 01234
231 addr = 8
232 expected_insn = 0x1234
233 mem[addr] = expected_insn
234
235 yield i_in.priv_mode.eq(1)
236 yield i_in.req.eq(0)
237 yield i_in.nia.eq(addr)
238 yield i_in.stop_mark.eq(0)
239 yield i_m_in.tlbld.eq(0)
240 yield i_m_in.tlbie.eq(0)
241 yield i_m_in.addr.eq(0)
242 yield i_m_in.pte.eq(0)
243 yield
244 yield
245 yield
246
247 # miss, stalls for a bit -- this one is different here
248 ##nia, insn, valid, failed = yield from icache_read(dut,addr,0,0)
249 ##assert(valid==0)
250 ##assert(failed==1)
251
252 yield i_in.req.eq(1)
253 yield i_in.nia.eq(addr)
254 yield
255 valid = yield i_out.valid
256 while not valid:
257 yield
258 valid = yield i_out.valid
259 yield i_in.req.eq(0)
260
261 nia = yield i_out.nia
262 insn = yield i_out.insn
263 yield
264 yield
265
266 print ("fetched %x from addr %x" % (insn, nia))
267 assert insn == expected_insn
268
269 print("=== test loadstore instruction (virtual) ===")
270
271 # look up i-cache expecting it to fail
272
273 yield from debug(dut, "virtual instr req")
274 # set address to 0x10200, update mem[] to 5678
275 virt_addr = 0x10200
276 real_addr = virt_addr
277 expected_insn = 0x5678
278 mem[real_addr] = expected_insn
279
280 yield i_in.priv_mode.eq(0)
281 yield i_in.virt_mode.eq(1)
282 yield i_in.req.eq(0)
283 yield i_in.nia.eq(virt_addr)
284 yield i_in.stop_mark.eq(0)
285 yield i_m_in.tlbld.eq(0)
286 yield i_m_in.tlbie.eq(0)
287 yield i_m_in.addr.eq(0)
288 yield i_m_in.pte.eq(0)
289 yield
290 yield
291 yield
292
293 # miss, stalls for a bit
294 yield i_in.req.eq(1)
295 yield i_in.nia.eq(virt_addr)
296 yield
297 valid = yield i_out.valid
298 failed = yield i_out.fetch_failed
299 while not valid and not failed:
300 yield
301 valid = yield i_out.valid
302 failed = yield i_out.fetch_failed
303 yield i_in.req.eq(0)
304
305 print ("failed?", "yes" if failed else "no")
306 assert failed == 1
307 yield
308 yield
309
310 print("=== test loadstore instruction (instruction fault) ===")
311
312 yield from debug(dut, "instr fault")
313
314 virt_addr = 0x10200
315
316 yield ldst.priv_mode.eq(0)
317 yield ldst.instr_fault.eq(1)
318 yield ldst.maddr.eq(virt_addr)
319 #ld_data, exctype, exc = yield from pi_ld(pi, virt_addr, 8, msr_pr=1)
320 yield
321 yield ldst.instr_fault.eq(0)
322 while True:
323 done = yield (ldst.done)
324 exc_info = yield from get_exception_info(pi.exc_o)
325 if done or exc_info.happened:
326 break
327 yield
328 assert exc_info.happened == 0 # assert just before doing the fault set zero
329 yield ldst.instr_fault.eq(0)
330 yield
331 yield
332 yield
333
334 print("=== test loadstore instruction (try instruction again) ===")
335 yield from debug(dut, "instr virt retry")
336 # set address to 0x10200, update mem[] to 5678
337 virt_addr = 0x10200
338 real_addr = virt_addr
339 expected_insn = 0x5678
340
341 yield i_in.priv_mode.eq(0)
342 yield i_in.virt_mode.eq(1)
343 yield i_in.req.eq(0)
344 yield i_in.nia.eq(virt_addr)
345 yield i_in.stop_mark.eq(0)
346 yield i_m_in.tlbld.eq(0)
347 yield i_m_in.tlbie.eq(0)
348 yield i_m_in.addr.eq(0)
349 yield i_m_in.pte.eq(0)
350 yield
351 yield
352 yield
353
354 # miss, stalls for a bit
355 """
356 yield i_in.req.eq(1)
357 yield i_in.nia.eq(virt_addr)
358 yield
359 valid = yield i_out.valid
360 failed = yield i_out.fetch_failed
361 while not valid and not failed:
362 yield
363 valid = yield i_out.valid
364 failed = yield i_out.fetch_failed
365 yield i_in.req.eq(0)
366 nia = yield i_out.nia
367 insn = yield i_out.insn
368 """
369
370 ## part 4
371 nia, insn, valid, failed = yield from icache_read(dut,virt_addr,0,1)
372
373 yield from debug(dut, "test done")
374 yield
375 yield
376
377 print ("failed?", "yes" if failed else "no")
378 assert failed == 0
379
380 print ("fetched %x from addr %x" % (insn, nia))
381 assert insn == expected_insn
382
383 wbget.stop = True
384
385
386 def _test_loadstore1_invalid(dut, mem):
387 mmu = dut.submodules.mmu
388 pi = dut.submodules.ldst.pi
389 wbget.stop = False
390
391 print("=== test invalid ===")
392
393 addr = 0
394 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
395 print("ld_data", ld_data, exctype, exc)
396 assert (exctype == "slow")
397 invalid = exc.invalid
398 assert (invalid == 1)
399
400 print("=== test invalid done ===")
401
402 wbget.stop = True
403
404
405 def _test_loadstore1(dut, mem):
406 mmu = dut.submodules.mmu
407 pi = dut.submodules.ldst.pi
408 ldst = dut.submodules.ldst # to get at DAR (NOT part of PortInterface)
409 wbget.stop = False
410
411 yield mmu.rin.prtbl.eq(0x1000000) # set process table
412 yield
413
414 addr = 0x100e0
415 data = 0xf553b658ba7e1f51
416
417 if test_dcbz:
418 yield from pi_st(pi, addr, data, 8, msr_pr=1)
419 yield
420
421 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
422 assert ld_data == 0xf553b658ba7e1f51
423 assert exctype is None
424
425 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
426 assert ld_data == 0xf553b658ba7e1f51
427 assert exctype is None
428
429 print("do_dcbz ===============")
430 yield from pi_st(pi, addr, data, 8, msr_pr=1, is_dcbz=1)
431 print("done_dcbz ===============")
432 yield
433
434 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
435 print("ld_data after dcbz")
436 print(ld_data)
437 assert ld_data == 0
438 assert exctype is None
439
440 if test_exceptions:
441 print("=== alignment error (ld) ===")
442 addr = 0xFF100e0FF
443 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
444 if exc:
445 alignment = exc.alignment
446 happened = exc.happened
447 yield # wait for dsr to update
448 dar = yield ldst.dar
449 else:
450 alignment = 0
451 happened = 0
452 dar = 0
453 assert (happened == 1)
454 assert (alignment == 1)
455 assert (dar == addr)
456 assert (exctype == "fast")
457 yield from wait_busy(pi, debug="pi_ld_E_alignment_error")
458 # wait is only needed in case of in exception here
459 print("=== alignment error test passed (ld) ===")
460
461 # take some cycles in between so that gtkwave separates out
462 # signals
463 yield
464 yield
465 yield
466 yield
467
468 print("=== alignment error (st) ===")
469 addr = 0xFF100e0FF
470 exctype, exc = yield from pi_st(pi, addr,0, 8, msr_pr=1)
471 if exc:
472 alignment = exc.alignment
473 happened = exc.happened
474 else:
475 alignment = 0
476 happened = 0
477 assert (happened == 1)
478 assert (alignment==1)
479 assert (dar==addr)
480 assert (exctype == "fast")
481 #???? yield from wait_busy(pi, debug="pi_st_E_alignment_error")
482 # wait is only needed in case of in exception here
483 print("=== alignment error test passed (st) ===")
484 yield #FIXME hangs
485
486 if True:
487 print("=== no alignment error (ld) ===")
488 addr = 0x100e0
489 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
490 print("ld_data", ld_data, exctype, exc)
491 if exc:
492 alignment = exc.alignment
493 happened = exc.happened
494 else:
495 alignment = 0
496 happened = 0
497 assert (happened == 0)
498 assert (alignment == 0)
499 print("=== no alignment error done (ld) ===")
500
501 if test_random:
502 addrs = [0x456920,0xa7a180,0x299420,0x1d9d60]
503
504 for addr in addrs:
505 print("== RANDOM addr ==",hex(addr))
506 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
507 print("ld_data[RANDOM]",ld_data,exc,addr)
508 assert (exctype == None)
509
510 for addr in addrs:
511 print("== RANDOM addr ==",hex(addr))
512 exc = yield from pi_st(pi, addr,0xFF*addr, 8, msr_pr=1)
513 assert (exctype == None)
514
515 # readback written data and compare
516 for addr in addrs:
517 print("== RANDOM addr ==",hex(addr))
518 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
519 print("ld_data[RANDOM_READBACK]",ld_data,exc,addr)
520 assert (exctype == None)
521 assert (ld_data == 0xFF*addr)
522
523 print("== RANDOM addr done ==")
524
525 wbget.stop = True
526
527
528 def _test_loadstore1_ifetch_invalid(dut, mem):
529 mmu = dut.submodules.mmu
530 ldst = dut.submodules.ldst
531 pi = ldst.pi
532 icache = dut.submodules.ldst.icache
533 wbget.stop = False
534
535 print("=== test loadstore instruction (invalid) ===")
536
537 i_in = icache.i_in
538 i_out = icache.i_out
539 i_m_in = icache.m_in
540
541 # first virtual memory test
542
543 print ("set process table")
544 yield from debug(dut, "set prtbl")
545 yield mmu.rin.prtbl.eq(0x1000000) # set process table
546 yield
547
548 yield from debug(dut, "real mem instruction")
549 # set address to zero, update mem[0] to 01234
550 addr = 8
551 expected_insn = 0x1234
552 mem[addr] = expected_insn
553
554 yield i_in.priv_mode.eq(1)
555 yield i_in.req.eq(0)
556 yield i_in.nia.eq(addr)
557 yield i_in.stop_mark.eq(0)
558 yield i_m_in.tlbld.eq(0)
559 yield i_m_in.tlbie.eq(0)
560 yield i_m_in.addr.eq(0)
561 yield i_m_in.pte.eq(0)
562 yield
563 yield
564 yield
565
566 # miss, stalls for a bit
567 yield i_in.req.eq(1)
568 yield i_in.nia.eq(addr)
569 yield
570 valid = yield i_out.valid
571 nia = yield i_out.nia
572 while not valid:
573 yield
574 valid = yield i_out.valid
575 yield i_in.req.eq(0)
576
577 nia = yield i_out.nia
578 insn = yield i_out.insn
579
580 yield
581 yield
582
583 print ("fetched %x from addr %x" % (insn, nia))
584 assert insn == expected_insn
585
586 print("=== test loadstore instruction (virtual) ===")
587 yield from debug(dut, "virtual instr req")
588
589 # look up i-cache expecting it to fail
590
591 # set address to 0x10200, update mem[] to 5678
592 virt_addr = 0x10200
593 real_addr = virt_addr
594 expected_insn = 0x5678
595 mem[real_addr] = expected_insn
596
597 yield i_in.priv_mode.eq(1)
598 yield i_in.virt_mode.eq(1)
599 yield i_in.req.eq(0)
600 yield i_in.nia.eq(virt_addr)
601 yield i_in.stop_mark.eq(0)
602 yield i_m_in.tlbld.eq(0)
603 yield i_m_in.tlbie.eq(0)
604 yield i_m_in.addr.eq(0)
605 yield i_m_in.pte.eq(0)
606 yield
607 yield
608 yield
609
610 # miss, stalls for a bit
611 yield i_in.req.eq(1)
612 yield i_in.nia.eq(virt_addr)
613 yield
614 valid = yield i_out.valid
615 failed = yield i_out.fetch_failed
616 while not valid and not failed:
617 yield
618 valid = yield i_out.valid
619 failed = yield i_out.fetch_failed
620 yield i_in.req.eq(0)
621
622 print ("failed?", "yes" if failed else "no")
623 assert failed == 1
624 yield
625 yield
626
627 print("=== test invalid loadstore instruction (instruction fault) ===")
628
629 yield from debug(dut, "instr fault (perm err expected)")
630 virt_addr = 0x10200
631
632 yield ldst.priv_mode.eq(0)
633 yield ldst.instr_fault.eq(1)
634 yield ldst.maddr.eq(virt_addr)
635 #ld_data, exctype, exc = yield from pi_ld(pi, virt_addr, 8, msr_pr=1)
636 yield
637 yield ldst.instr_fault.eq(0)
638 while True:
639 done = yield (ldst.done)
640 exc_info = yield from get_exception_info(pi.exc_o)
641 if done or exc_info.happened:
642 break
643 yield
644 assert exc_info.happened == 1 # different here as expected
645
646 # TODO: work out what kind of exception occurred and check it's
647 # the right one. we *expect* it to be a permissions error because
648 # the RPTE leaf node in pagetables.test2 is marked as "non-executable"
649 # but we also expect instr_fault to be set because it is an instruction
650 # (iside) lookup
651 print (" MMU lookup exception type?")
652 for fname in LDSTExceptionTuple._fields:
653 print (" fname %20s %d" % (fname, getattr(exc_info, fname)))
654
655 # ok now printed them out and visually inspected: check them with asserts
656 assert exc_info.instr_fault == 1 # instruction fault (yes!)
657 assert exc_info.perm_error == 1 # permissions (yes!)
658 assert exc_info.rc_error == 0
659 assert exc_info.alignment == 0
660 assert exc_info.invalid == 0
661 assert exc_info.segment_fault == 0
662 assert exc_info.rc_error == 0
663
664 yield from debug(dut, "test done")
665 yield ldst.instr_fault.eq(0)
666 yield
667 yield
668 yield
669
670 wbget.stop = True
671
672
673 def test_loadstore1_ifetch_unit_iface():
674
675 m, cmpi = setup_mmu()
676
677 mem = pagetables.test1
678
679 # nmigen Simulation
680 sim = Simulator(m)
681 sim.add_clock(1e-6)
682
683 icache = m.submodules.ldst.icache
684 icache.use_fetch_interface() # this is the function which converts
685 # to FetchUnitInterface. *including*
686 # rewiring the Wishbone Bus to ibus
687 sim.add_sync_process(wrap(_test_loadstore1_ifetch_iface(m, mem)))
688 # add two wb_get processes onto the *same* memory dictionary.
689 # this shouuuld work.... cross-fingers...
690 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
691 sim.add_sync_process(wrap(wb_get(icache.ibus, mem))) # ibus not bus
692 with sim.write_vcd('test_loadstore1_ifetch_iface.vcd',
693 traces=[m.debug_status]): # include extra debug
694 sim.run()
695
696
697 def test_loadstore1_ifetch():
698
699 m, cmpi = setup_mmu()
700
701 mem = pagetables.test1
702
703 # nmigen Simulation
704 sim = Simulator(m)
705 sim.add_clock(1e-6)
706
707 icache = m.submodules.ldst.icache
708 sim.add_sync_process(wrap(_test_loadstore1_ifetch(m, mem)))
709 # add two wb_get processes onto the *same* memory dictionary.
710 # this shouuuld work.... cross-fingers...
711 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
712 sim.add_sync_process(wrap(wb_get(icache.bus, mem)))
713 with sim.write_vcd('test_loadstore1_ifetch.vcd',
714 traces=[m.debug_status]): # include extra debug
715 sim.run()
716
717
718 def test_loadstore1():
719
720 m, cmpi = setup_mmu()
721
722 mem = pagetables.test1
723
724 # nmigen Simulation
725 sim = Simulator(m)
726 sim.add_clock(1e-6)
727
728 sim.add_sync_process(wrap(_test_loadstore1(m, mem)))
729 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
730 with sim.write_vcd('test_loadstore1.vcd'):
731 sim.run()
732
733
734 def test_loadstore1_invalid():
735
736 m, cmpi = setup_mmu()
737
738 mem = {}
739
740 # nmigen Simulation
741 sim = Simulator(m)
742 sim.add_clock(1e-6)
743
744 sim.add_sync_process(wrap(_test_loadstore1_invalid(m, mem)))
745 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
746 with sim.write_vcd('test_loadstore1_invalid.vcd'):
747 sim.run()
748
749 def test_loadstore1_ifetch_invalid():
750 m, cmpi = setup_mmu()
751
752 # this is a specially-arranged page table which has the permissions
753 # barred for execute on the leaf node (EAA=0x2 instead of EAA=0x3)
754 mem = pagetables.test2
755
756 # nmigen Simulation
757 sim = Simulator(m)
758 sim.add_clock(1e-6)
759
760 icache = m.submodules.ldst.icache
761 sim.add_sync_process(wrap(_test_loadstore1_ifetch_invalid(m, mem)))
762 # add two wb_get processes onto the *same* memory dictionary.
763 # this shouuuld work.... cross-fingers...
764 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
765 sim.add_sync_process(wrap(wb_get(icache.bus, mem)))
766 with sim.write_vcd('test_loadstore1_ifetch_invalid.vcd',
767 traces=[m.debug_status]): # include extra debug
768 sim.run()
769
770
771
772 if __name__ == '__main__':
773 test_loadstore1()
774 test_loadstore1_invalid()
775 test_loadstore1_ifetch()
776 test_loadstore1_fetch_unit_iface()
777 test_loadstore1_ifetch_invalid()
778