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