typo fix, add missing stop statement to _test_loadstore1_ifetch_multi()
[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 def _test_loadstore1_ifetch_multi(dut, mem):
187 yield from debug(dut, "TODO")
188 yield
189 yield
190 yield
191 # TODO fetch instructions from multiple addresses
192 # should cope with some addresses being invalid
193 addrs = [0x10200,0x10204,10208,10200]
194 for addr in addrs:
195 yield from debug(dut, "TODO_fetch_from "+hex(addr))
196 # use the new interface in this test
197 yield
198 yield
199 yield
200
201 wbget.stop = True
202
203 def _test_loadstore1_ifetch(dut, mem):
204 """test_loadstore1_ifetch
205
206 this is quite a complex multi-step test.
207
208 * first (just because, as a demo) read in priv mode, non-virtual.
209 just like in experiment/icache.py itself.
210
211 * second, using the (usual) PTE for these things (which came originally
212 from gem5-experimental experiment/radix_walk_example.txt) do a
213 virtual-memory read through the *instruction* cache.
214 this is expected to FAIL
215
216 * third: mess about with the MMU, setting "iside" (instruction-side),
217 requesting an MMU RADIX LOOKUP. this triggers an itlb_load
218 (instruction-cache TLB entry-insertion)
219
220 * fourth and finally: retry the read of the instruction through i-cache.
221 this is now expected to SUCCEED
222
223 a lot going on.
224 """
225
226 mmu = dut.submodules.mmu
227 ldst = dut.submodules.ldst
228 pi = ldst.pi
229 icache = dut.submodules.ldst.icache
230 wbget.stop = False
231
232 print("=== test loadstore instruction (real) ===")
233
234 i_in = icache.i_in
235 i_out = icache.i_out
236 i_m_in = icache.m_in
237
238 # first virtual memory test
239
240 print ("set process table")
241 yield from debug(dut, "set prtble")
242 yield mmu.rin.prtbl.eq(0x1000000) # set process table
243 yield
244
245 yield from debug(dut, "real mem instruction")
246 # set address to zero, update mem[0] to 01234
247 addr = 8
248 expected_insn = 0x1234
249 mem[addr] = expected_insn
250
251 yield i_in.priv_mode.eq(1)
252 yield i_in.req.eq(0)
253 yield i_in.nia.eq(addr)
254 yield i_in.stop_mark.eq(0)
255 yield i_m_in.tlbld.eq(0)
256 yield i_m_in.tlbie.eq(0)
257 yield i_m_in.addr.eq(0)
258 yield i_m_in.pte.eq(0)
259 yield
260 yield
261 yield
262
263 # miss, stalls for a bit -- this one is different here
264 ##nia, insn, valid, failed = yield from icache_read(dut,addr,0,0)
265 ##assert(valid==0)
266 ##assert(failed==1)
267
268 yield i_in.req.eq(1)
269 yield i_in.nia.eq(addr)
270 yield
271 valid = yield i_out.valid
272 while not valid:
273 yield
274 valid = yield i_out.valid
275 yield i_in.req.eq(0)
276
277 nia = yield i_out.nia
278 insn = yield i_out.insn
279 yield
280 yield
281
282 print ("fetched %x from addr %x" % (insn, nia))
283 assert insn == expected_insn
284
285 print("=== test loadstore instruction (virtual) ===")
286
287 # look up i-cache expecting it to fail
288
289 yield from debug(dut, "virtual instr req")
290 # set address to 0x10200, update mem[] to 5678
291 virt_addr = 0x10200
292 real_addr = virt_addr
293 expected_insn = 0x5678
294 mem[real_addr] = expected_insn
295
296 yield i_in.priv_mode.eq(0)
297 yield i_in.virt_mode.eq(1)
298 yield i_in.req.eq(0)
299 yield i_in.nia.eq(virt_addr)
300 yield i_in.stop_mark.eq(0)
301 yield i_m_in.tlbld.eq(0)
302 yield i_m_in.tlbie.eq(0)
303 yield i_m_in.addr.eq(0)
304 yield i_m_in.pte.eq(0)
305 yield
306 yield
307 yield
308
309 # miss, stalls for a bit
310 yield i_in.req.eq(1)
311 yield i_in.nia.eq(virt_addr)
312 yield
313 valid = yield i_out.valid
314 failed = yield i_out.fetch_failed
315 while not valid and not failed:
316 yield
317 valid = yield i_out.valid
318 failed = yield i_out.fetch_failed
319 yield i_in.req.eq(0)
320
321 print ("failed?", "yes" if failed else "no")
322 assert failed == 1
323 yield
324 yield
325
326 print("=== test loadstore instruction (instruction fault) ===")
327
328 yield from debug(dut, "instr fault")
329
330 virt_addr = 0x10200
331
332 yield ldst.priv_mode.eq(0)
333 yield ldst.instr_fault.eq(1)
334 yield ldst.maddr.eq(virt_addr)
335 #ld_data, exctype, exc = yield from pi_ld(pi, virt_addr, 8, msr_pr=1)
336 yield
337 yield ldst.instr_fault.eq(0)
338 while True:
339 done = yield (ldst.done)
340 exc_info = yield from get_exception_info(pi.exc_o)
341 if done or exc_info.happened:
342 break
343 yield
344 assert exc_info.happened == 0 # assert just before doing the fault set zero
345 yield ldst.instr_fault.eq(0)
346 yield
347 yield
348 yield
349
350 print("=== test loadstore instruction (try instruction again) ===")
351 yield from debug(dut, "instr virt retry")
352 # set address to 0x10200, update mem[] to 5678
353 virt_addr = 0x10200
354 real_addr = virt_addr
355 expected_insn = 0x5678
356
357 yield i_in.priv_mode.eq(0)
358 yield i_in.virt_mode.eq(1)
359 yield i_in.req.eq(0)
360 yield i_in.nia.eq(virt_addr)
361 yield i_in.stop_mark.eq(0)
362 yield i_m_in.tlbld.eq(0)
363 yield i_m_in.tlbie.eq(0)
364 yield i_m_in.addr.eq(0)
365 yield i_m_in.pte.eq(0)
366 yield
367 yield
368 yield
369
370 # miss, stalls for a bit
371 """
372 yield i_in.req.eq(1)
373 yield i_in.nia.eq(virt_addr)
374 yield
375 valid = yield i_out.valid
376 failed = yield i_out.fetch_failed
377 while not valid and not failed:
378 yield
379 valid = yield i_out.valid
380 failed = yield i_out.fetch_failed
381 yield i_in.req.eq(0)
382 nia = yield i_out.nia
383 insn = yield i_out.insn
384 """
385
386 ## part 4
387 nia, insn, valid, failed = yield from icache_read(dut,virt_addr,0,1)
388
389 yield from debug(dut, "test done")
390 yield
391 yield
392
393 print ("failed?", "yes" if failed else "no")
394 assert failed == 0
395
396 print ("fetched %x from addr %x" % (insn, nia))
397 assert insn == expected_insn
398
399 wbget.stop = True
400
401
402 def _test_loadstore1_invalid(dut, mem):
403 mmu = dut.submodules.mmu
404 pi = dut.submodules.ldst.pi
405 wbget.stop = False
406
407 print("=== test invalid ===")
408
409 addr = 0
410 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
411 print("ld_data", ld_data, exctype, exc)
412 assert (exctype == "slow")
413 invalid = exc.invalid
414 assert (invalid == 1)
415
416 print("=== test invalid done ===")
417
418 wbget.stop = True
419
420
421 def _test_loadstore1(dut, mem):
422 mmu = dut.submodules.mmu
423 pi = dut.submodules.ldst.pi
424 ldst = dut.submodules.ldst # to get at DAR (NOT part of PortInterface)
425 wbget.stop = False
426
427 yield mmu.rin.prtbl.eq(0x1000000) # set process table
428 yield
429
430 addr = 0x100e0
431 data = 0xf553b658ba7e1f51
432
433 if test_dcbz:
434 yield from pi_st(pi, addr, data, 8, msr_pr=1)
435 yield
436
437 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
438 assert ld_data == 0xf553b658ba7e1f51
439 assert exctype is None
440
441 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
442 assert ld_data == 0xf553b658ba7e1f51
443 assert exctype is None
444
445 print("do_dcbz ===============")
446 yield from pi_st(pi, addr, data, 8, msr_pr=1, is_dcbz=1)
447 print("done_dcbz ===============")
448 yield
449
450 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
451 print("ld_data after dcbz")
452 print(ld_data)
453 assert ld_data == 0
454 assert exctype is None
455
456 if test_exceptions:
457 print("=== alignment error (ld) ===")
458 addr = 0xFF100e0FF
459 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
460 if exc:
461 alignment = exc.alignment
462 happened = exc.happened
463 yield # wait for dsr to update
464 dar = yield ldst.dar
465 else:
466 alignment = 0
467 happened = 0
468 dar = 0
469 assert (happened == 1)
470 assert (alignment == 1)
471 assert (dar == addr)
472 assert (exctype == "fast")
473 yield from wait_busy(pi, debug="pi_ld_E_alignment_error")
474 # wait is only needed in case of in exception here
475 print("=== alignment error test passed (ld) ===")
476
477 # take some cycles in between so that gtkwave separates out
478 # signals
479 yield
480 yield
481 yield
482 yield
483
484 print("=== alignment error (st) ===")
485 addr = 0xFF100e0FF
486 exctype, exc = yield from pi_st(pi, addr,0, 8, msr_pr=1)
487 if exc:
488 alignment = exc.alignment
489 happened = exc.happened
490 else:
491 alignment = 0
492 happened = 0
493 assert (happened == 1)
494 assert (alignment==1)
495 assert (dar==addr)
496 assert (exctype == "fast")
497 #???? yield from wait_busy(pi, debug="pi_st_E_alignment_error")
498 # wait is only needed in case of in exception here
499 print("=== alignment error test passed (st) ===")
500 yield #FIXME hangs
501
502 if True:
503 print("=== no alignment error (ld) ===")
504 addr = 0x100e0
505 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
506 print("ld_data", ld_data, exctype, exc)
507 if exc:
508 alignment = exc.alignment
509 happened = exc.happened
510 else:
511 alignment = 0
512 happened = 0
513 assert (happened == 0)
514 assert (alignment == 0)
515 print("=== no alignment error done (ld) ===")
516
517 if test_random:
518 addrs = [0x456920,0xa7a180,0x299420,0x1d9d60]
519
520 for addr in addrs:
521 print("== RANDOM addr ==",hex(addr))
522 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
523 print("ld_data[RANDOM]",ld_data,exc,addr)
524 assert (exctype == None)
525
526 for addr in addrs:
527 print("== RANDOM addr ==",hex(addr))
528 exc = yield from pi_st(pi, addr,0xFF*addr, 8, msr_pr=1)
529 assert (exctype == None)
530
531 # readback written data and compare
532 for addr in addrs:
533 print("== RANDOM addr ==",hex(addr))
534 ld_data, exctype, exc = yield from pi_ld(pi, addr, 8, msr_pr=1)
535 print("ld_data[RANDOM_READBACK]",ld_data,exc,addr)
536 assert (exctype == None)
537 assert (ld_data == 0xFF*addr)
538
539 print("== RANDOM addr done ==")
540
541 wbget.stop = True
542
543
544 def _test_loadstore1_ifetch_invalid(dut, mem):
545 mmu = dut.submodules.mmu
546 ldst = dut.submodules.ldst
547 pi = ldst.pi
548 icache = dut.submodules.ldst.icache
549 wbget.stop = False
550
551 print("=== test loadstore instruction (invalid) ===")
552
553 i_in = icache.i_in
554 i_out = icache.i_out
555 i_m_in = icache.m_in
556
557 # first virtual memory test
558
559 print ("set process table")
560 yield from debug(dut, "set prtbl")
561 yield mmu.rin.prtbl.eq(0x1000000) # set process table
562 yield
563
564 yield from debug(dut, "real mem instruction")
565 # set address to zero, update mem[0] to 01234
566 addr = 8
567 expected_insn = 0x1234
568 mem[addr] = expected_insn
569
570 yield i_in.priv_mode.eq(1)
571 yield i_in.req.eq(0)
572 yield i_in.nia.eq(addr)
573 yield i_in.stop_mark.eq(0)
574 yield i_m_in.tlbld.eq(0)
575 yield i_m_in.tlbie.eq(0)
576 yield i_m_in.addr.eq(0)
577 yield i_m_in.pte.eq(0)
578 yield
579 yield
580 yield
581
582 # miss, stalls for a bit
583 yield i_in.req.eq(1)
584 yield i_in.nia.eq(addr)
585 yield
586 valid = yield i_out.valid
587 nia = yield i_out.nia
588 while not valid:
589 yield
590 valid = yield i_out.valid
591 yield i_in.req.eq(0)
592
593 nia = yield i_out.nia
594 insn = yield i_out.insn
595
596 yield
597 yield
598
599 print ("fetched %x from addr %x" % (insn, nia))
600 assert insn == expected_insn
601
602 print("=== test loadstore instruction (virtual) ===")
603 yield from debug(dut, "virtual instr req")
604
605 # look up i-cache expecting it to fail
606
607 # set address to 0x10200, update mem[] to 5678
608 virt_addr = 0x10200
609 real_addr = virt_addr
610 expected_insn = 0x5678
611 mem[real_addr] = expected_insn
612
613 yield i_in.priv_mode.eq(1)
614 yield i_in.virt_mode.eq(1)
615 yield i_in.req.eq(0)
616 yield i_in.nia.eq(virt_addr)
617 yield i_in.stop_mark.eq(0)
618 yield i_m_in.tlbld.eq(0)
619 yield i_m_in.tlbie.eq(0)
620 yield i_m_in.addr.eq(0)
621 yield i_m_in.pte.eq(0)
622 yield
623 yield
624 yield
625
626 # miss, stalls for a bit
627 yield i_in.req.eq(1)
628 yield i_in.nia.eq(virt_addr)
629 yield
630 valid = yield i_out.valid
631 failed = yield i_out.fetch_failed
632 while not valid and not failed:
633 yield
634 valid = yield i_out.valid
635 failed = yield i_out.fetch_failed
636 yield i_in.req.eq(0)
637
638 print ("failed?", "yes" if failed else "no")
639 assert failed == 1
640 yield
641 yield
642
643 print("=== test invalid loadstore instruction (instruction fault) ===")
644
645 yield from debug(dut, "instr fault (perm err expected)")
646 virt_addr = 0x10200
647
648 yield ldst.priv_mode.eq(0)
649 yield ldst.instr_fault.eq(1)
650 yield ldst.maddr.eq(virt_addr)
651 #ld_data, exctype, exc = yield from pi_ld(pi, virt_addr, 8, msr_pr=1)
652 yield
653 yield ldst.instr_fault.eq(0)
654 while True:
655 done = yield (ldst.done)
656 exc_info = yield from get_exception_info(pi.exc_o)
657 if done or exc_info.happened:
658 break
659 yield
660 assert exc_info.happened == 1 # different here as expected
661
662 # TODO: work out what kind of exception occurred and check it's
663 # the right one. we *expect* it to be a permissions error because
664 # the RPTE leaf node in pagetables.test2 is marked as "non-executable"
665 # but we also expect instr_fault to be set because it is an instruction
666 # (iside) lookup
667 print (" MMU lookup exception type?")
668 for fname in LDSTExceptionTuple._fields:
669 print (" fname %20s %d" % (fname, getattr(exc_info, fname)))
670
671 # ok now printed them out and visually inspected: check them with asserts
672 assert exc_info.instr_fault == 1 # instruction fault (yes!)
673 assert exc_info.perm_error == 1 # permissions (yes!)
674 assert exc_info.rc_error == 0
675 assert exc_info.alignment == 0
676 assert exc_info.invalid == 0
677 assert exc_info.segment_fault == 0
678 assert exc_info.rc_error == 0
679
680 yield from debug(dut, "test done")
681 yield ldst.instr_fault.eq(0)
682 yield
683 yield
684 yield
685
686 wbget.stop = True
687
688
689 def test_loadstore1_ifetch_unit_iface():
690
691 m, cmpi = setup_mmu()
692
693 mem = pagetables.test1
694
695 # nmigen Simulation
696 sim = Simulator(m)
697 sim.add_clock(1e-6)
698
699 icache = m.submodules.ldst.icache
700 icache.use_fetch_interface() # this is the function which converts
701 # to FetchUnitInterface. *including*
702 # rewiring the Wishbone Bus to ibus
703 sim.add_sync_process(wrap(_test_loadstore1_ifetch_iface(m, mem)))
704 # add two wb_get processes onto the *same* memory dictionary.
705 # this shouuuld work.... cross-fingers...
706 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
707 sim.add_sync_process(wrap(wb_get(icache.ibus, mem))) # ibus not bus
708 with sim.write_vcd('test_loadstore1_ifetch_iface.vcd',
709 traces=[m.debug_status]): # include extra debug
710 sim.run()
711
712
713 def test_loadstore1_ifetch():
714
715 m, cmpi = setup_mmu()
716
717 mem = pagetables.test1
718
719 # nmigen Simulation
720 sim = Simulator(m)
721 sim.add_clock(1e-6)
722
723 icache = m.submodules.ldst.icache
724 sim.add_sync_process(wrap(_test_loadstore1_ifetch(m, mem)))
725 # add two wb_get processes onto the *same* memory dictionary.
726 # this shouuuld work.... cross-fingers...
727 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
728 sim.add_sync_process(wrap(wb_get(icache.bus, mem)))
729 with sim.write_vcd('test_loadstore1_ifetch.vcd',
730 traces=[m.debug_status]): # include extra debug
731 sim.run()
732
733
734 def test_loadstore1():
735
736 m, cmpi = setup_mmu()
737
738 mem = pagetables.test1
739
740 # nmigen Simulation
741 sim = Simulator(m)
742 sim.add_clock(1e-6)
743
744 sim.add_sync_process(wrap(_test_loadstore1(m, mem)))
745 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
746 with sim.write_vcd('test_loadstore1.vcd'):
747 sim.run()
748
749
750 def test_loadstore1_invalid():
751
752 m, cmpi = setup_mmu()
753
754 mem = {}
755
756 # nmigen Simulation
757 sim = Simulator(m)
758 sim.add_clock(1e-6)
759
760 sim.add_sync_process(wrap(_test_loadstore1_invalid(m, mem)))
761 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
762 with sim.write_vcd('test_loadstore1_invalid.vcd'):
763 sim.run()
764
765 def test_loadstore1_ifetch_invalid():
766 m, cmpi = setup_mmu()
767
768 # this is a specially-arranged page table which has the permissions
769 # barred for execute on the leaf node (EAA=0x2 instead of EAA=0x3)
770 mem = pagetables.test2
771
772 # nmigen Simulation
773 sim = Simulator(m)
774 sim.add_clock(1e-6)
775
776 icache = m.submodules.ldst.icache
777 sim.add_sync_process(wrap(_test_loadstore1_ifetch_invalid(m, mem)))
778 # add two wb_get processes onto the *same* memory dictionary.
779 # this shouuuld work.... cross-fingers...
780 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
781 sim.add_sync_process(wrap(wb_get(icache.bus, mem)))
782 with sim.write_vcd('test_loadstore1_ifetch_invalid.vcd',
783 traces=[m.debug_status]): # include extra debug
784 sim.run()
785
786 def test_loadstore1_ifetch_multi():
787 m, cmpi = setup_mmu()
788
789 # this is a specially-arranged page table which has the permissions
790 # barred for execute on the leaf node (EAA=0x2 instead of EAA=0x3)
791 mem = pagetables.test1
792
793 # nmigen Simulation
794 sim = Simulator(m)
795 sim.add_clock(1e-6)
796
797 icache = m.submodules.ldst.icache
798 sim.add_sync_process(wrap(_test_loadstore1_ifetch_multi(m, mem)))
799 # add two wb_get processes onto the *same* memory dictionary.
800 # this shouuuld work.... cross-fingers...
801 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
802 sim.add_sync_process(wrap(wb_get(icache.bus, mem)))
803 with sim.write_vcd('test_loadstore1_ifetch_multi.vcd',
804 traces=[m.debug_status]): # include extra debug
805 sim.run()
806
807 if __name__ == '__main__':
808 test_loadstore1()
809 test_loadstore1_invalid()
810 test_loadstore1_ifetch()
811 test_loadstore1_fetch_unit_iface()
812 test_loadstore1_ifetch_invalid()
813 test_loadstore1_ifetch_multi()
814