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