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