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