Allow the formal engine to perform a same-cycle result in the ALU
[soc.git] / src / soc / experiment / test / test_ldst_pi_misalign.py
1 """MMU PortInterface Test
2
3 quite basic, goes directly to the MMU to assert signals (does not
4 yet use PortInterface)
5 """
6
7 from nmigen import (C, Module, Signal, Elaboratable, Mux, Cat, Repl, Signal)
8 from nmigen.cli import main
9 from nmigen.cli import rtlil
10 from nmutil.mask import Mask, masked
11 from nmutil.util import Display
12
13 if True:
14 from nmigen.back.pysim import Simulator, Delay, Settle
15 else:
16 from nmigen.sim.cxxsim import Simulator, Delay, Settle
17 from nmutil.util import wrap
18
19 from soc.config.test.test_pi2ls import pi_ld, pi_st, pi_ldst
20 from soc.config.test.test_loadstore import TestMemPspec
21 from soc.config.loadstore import ConfigMemoryPortInterface
22
23 from soc.fu.ldst.loadstore import LoadStore1
24 from soc.experiment.mmu import MMU
25
26 from nmigen.compat.sim import run_simulation
27 from openpower.test.wb_get import wb_get
28 from openpower.test import wb_get as wbget
29 from openpower.decoder.power_enums import MSRSpec
30
31 msr_default = MSRSpec(pr=0, dr=0, sf=1) # 64 bit by default
32
33
34 wbget.stop = False
35
36 def b(x): # byte-reverse function
37 return int.from_bytes(x.to_bytes(8, byteorder='little'),
38 byteorder='big', signed=False)
39
40
41 def setup_mmu():
42
43 pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
44 imem_ifacetype='',
45 addr_wid=48,
46 #disable_cache=True, # hmmm...
47 mask_wid=8,
48 reg_wid=64)
49
50 m = Module()
51 comb = m.d.comb
52 cmpi = ConfigMemoryPortInterface(pspec)
53 m.submodules.ldst = ldst = cmpi.pi
54 m.submodules.mmu = mmu = MMU()
55 dcache = ldst.dcache
56
57 l_in, l_out = mmu.l_in, mmu.l_out
58 d_in, d_out = dcache.d_in, dcache.d_out
59
60 # link mmu and dcache together
61 m.d.comb += dcache.m_in.eq(mmu.d_out) # MMUToDCacheType
62 m.d.comb += mmu.d_in.eq(dcache.m_out) # DCacheToMMUType
63
64 # link ldst and MMU together
65 comb += l_in.eq(ldst.m_out)
66 comb += ldst.m_in.eq(l_out)
67
68 return m, cmpi
69
70
71
72 def ldst_sim_misalign(dut):
73 mmu = dut.submodules.mmu
74 wbget.stop = False
75
76 yield mmu.rin.prtbl.eq(0x1000000) # set process table
77 yield
78
79 # load 8 bytes at aligned address
80 align_addr = 0x1000
81 data, exctype, exc = yield from pi_ld(dut.submodules.ldst.pi,
82 align_addr, 8, msr=msr_default)
83 print ("ldst_sim_misalign (aligned)", hex(data), exctype, exc)
84 assert data == 0xdeadbeef01234567
85
86 # load 4 bytes at aligned address
87 align_addr = 0x1004
88 data, exctype, exc = yield from pi_ld(dut.submodules.ldst.pi,
89 align_addr, 4, msr=msr_default)
90 print ("ldst_sim_misalign (aligned)", hex(data), exctype, exc)
91 assert data == 0xdeadbeef
92
93 # load 8 bytes at *mis*-aligned address which is still within
94 # the page
95 misalign_addr = 0x1004
96 data, exctype, exc = yield from pi_ld(dut.submodules.ldst.pi,
97 misalign_addr, 8, msr=msr_default)
98
99 print ("ldst_sim_misalign", hex(data), exctype, exc)
100 assert data == 0xf001a5a5deadbeef
101
102 # load 8 bytes at *mis*-aligned address which is still within
103 # the page
104 misalign_addr = 0x1006
105 data, exctype, exc = yield from pi_ld(dut.submodules.ldst.pi,
106 misalign_addr, 8, msr=msr_default)
107
108 print ("ldst_sim_misalign", hex(data), exctype, exc)
109 assert data == 0xf00ff001a5a5dead
110 wbget.stop = True
111 return
112
113 # load 8 bytes at *mis*-aligned address which is NOT within
114 # the page - TODO - work this out
115 misalign_addr = 0x10000004
116 data, exctype, exc = yield from pi_ld(dut.submodules.ldst.pi,
117 misalign_addr, 8, msr=msr_default)
118 print ("ldst_sim_misalign", data, exctype, exc)
119 yield
120 dar = yield dut.submodules.ldst.dar
121 print ("DAR", hex(dar))
122 assert dar == misalign_addr
123 # check exception bits
124 assert exc.happened
125 assert exc.alignment
126 assert not exc.segment_fault
127 assert not exc.instr_fault
128 assert not exc.invalid
129 assert not exc.perm_error
130 assert not exc.rc_error
131 assert not exc.badtree
132
133 wbget.stop = True
134
135
136 def test_misalign_mmu():
137
138 m, cmpi = setup_mmu()
139
140 # virtual "memory" to use for this test
141
142 mem = {0x10000: # PARTITION_TABLE_2
143 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
144 b(0x800000000100000b),
145
146 0x30000: # RADIX_ROOT_PTE
147 # V = 1 L = 0 NLB = 0x400 NLS = 9
148 b(0x8000000000040009),
149
150 0x40000: # RADIX_SECOND_LEVEL
151 # V = 1 L = 1 SW = 0 RPN = 0
152 # R = 1 C = 1 ATT = 0 EAA 0x7
153 b(0xc000000000000183),
154
155 0x1000000: # PROCESS_TABLE_3
156 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
157 b(0x40000000000300ad),
158
159 # data to return
160 0x1000: 0xdeadbeef01234567,
161 0x1008: 0xfeedf00ff001a5a5
162 }
163
164
165 # nmigen Simulation
166 sim = Simulator(m)
167 sim.add_clock(1e-6)
168
169 sim.add_sync_process(wrap(ldst_sim_misalign(m)))
170 sim.add_sync_process(wrap(wb_get(cmpi.wb_bus(), mem)))
171 with sim.write_vcd('test_ldst_pi_misalign.vcd'):
172 sim.run()
173
174
175 if __name__ == '__main__':
176 test_misalign_mmu()