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