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