forgot to pass cix (cache-inhibited) through to LD/ST which was
[soc.git] / src / soc / experiment / test / test_mmu_dcache_pi.py
1 """MMU PortInterface Test
2
3 quite basic, calls pi_ld to get data via PortInterface. this test
4 shouldn't really exist, it's superceded by test_ldst_pi.py
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.iocontrol import RecordObject
11 from nmutil.byterev import byte_reverse
12 from nmutil.mask import Mask, masked
13 from nmutil.util import Display
14
15 if True:
16 from nmigen.back.pysim import Simulator, Delay, Settle
17 else:
18 from nmigen.sim.cxxsim import Simulator, Delay, Settle
19 from nmutil.util import wrap
20
21 from soc.config.test.test_pi2ls import pi_ld, pi_st, pi_ldst
22
23 from soc.experiment.mem_types import (LoadStore1ToMMUType,
24 MMUToLoadStore1Type,
25 MMUToDCacheType,
26 DCacheToMMUType,
27 MMUToICacheType)
28
29 from soc.experiment.mmu import MMU
30 from soc.experiment.dcache import DCache
31 from openpower.test.wb_get import wb_get
32 from openpower.test import wb_get as wbget
33
34 #more imports
35
36 from soc.experiment.l0_cache import L0CacheBuffer2
37 from nmigen import Module, Signal, Mux, Elaboratable, Cat, Const
38 from nmigen.cli import rtlil
39
40 from soc.config.test.test_pi2ls import pi_ld, pi_st, pi_ldst
41
42 from soc.experiment.pimem import PortInterfaceBase
43
44 from nmigen.compat.sim import run_simulation, Settle
45
46 # guess: those four need to be connected
47 #class DCacheToLoadStore1Type(RecordObject): dcache.d_out
48 #class LoadStore1ToDCacheType(RecordObject): dcache.d_in
49 #class LoadStore1ToMMUType(RecordObject): mmu.l_in
50 #class MMUToLoadStore1Type(RecordObject): mmu.l_out
51 # will take at least one week (10.10.2020)
52 # many unconnected signals
53
54 def b(x):
55 return int.from_bytes(x.to_bytes(8, byteorder='little'),
56 byteorder='big', signed=False)
57
58 mem = {0x10000: # PARTITION_TABLE_2
59 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
60 b(0x800000000100000b),
61
62 0x30000: # RADIX_ROOT_PTE
63 # V = 1 L = 0 NLB = 0x400 NLS = 9
64 b(0x8000000000040009),
65
66 0x40000: # RADIX_SECOND_LEVEL
67 # V = 1 L = 1 SW = 0 RPN = 0
68 # R = 1 C = 1 ATT = 0 EAA 0x7
69 b(0xc000000000000187),
70
71 0x1000000: # PROCESS_TABLE_3
72 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
73 b(0x40000000000300ad),
74 }
75
76
77 class TestMicrowattMemoryPortInterface(PortInterfaceBase):
78 """TestMicrowattMemoryPortInterface
79
80 This is a Test Class for MMU and DCache conforming to PortInterface
81 """
82
83 def __init__(self, mmu, dcache, regwid=64, addrwid=4):
84 super().__init__(regwid, addrwid)
85 self.mmu = mmu
86 self.dcache = dcache
87
88 def set_wr_addr(self, m, addr, mask, misalign, msr, is_dcbz, is_nc):
89 m.d.comb += self.dcache.d_in.addr.eq(addr)
90 m.d.comb += self.mmu.l_in.addr.eq(addr)
91 m.d.comb += self.mmu.l_in.load.eq(0)
92 m.d.comb += self.mmu.l_in.priv.eq(~msr.pr) # TODO verify
93 m.d.comb += self.mmu.l_in.valid.eq(1)
94
95 def set_rd_addr(self, m, addr, mask, misalign, msr, is_nc):
96 m.d.comb += self.dcache.d_in.addr.eq(addr)
97 m.d.comb += self.mmu.l_in.addr.eq(addr)
98 m.d.comb += self.mmu.l_in.load.eq(1)
99 m.d.comb += self.mmu.l_in.priv.eq(~msr.pr) # TODO verify
100 m.d.comb += self.mmu.l_in.valid.eq(1)
101
102 def set_wr_data(self, m, data, wen):
103 m.d.comb += self.dcache.d_in.data.eq(data) # write st to mem
104 m.d.comb += self.dcache.d_in.load.eq(~wen) # enable writes
105 st_ok = Const(1, 1)
106 return st_ok
107
108 # LoadStore1ToDCacheType
109 # valid
110 # dcbz
111 # nc
112 # reserve
113 # virt_mode
114 # addr # TODO
115 # byte_sel(8)
116
117 def get_rd_data(self, m):
118 # get data from dcache
119 ld_ok = self.mmu.l_out.done
120 data = self.dcache.d_out.data
121 return data, ld_ok
122
123
124 # DCacheToLoadStore1Type NC
125 # store_done
126 # error
127 # cache_paradox
128
129 return None
130
131 def elaborate(self, platform):
132 m = super().elaborate(platform)
133
134 m.submodules.mmu = self.mmu
135 m.submodules.dcache = self.dcache
136
137 # link mmu and dcache together
138 m.d.comb += self.dcache.m_in.eq(self.mmu.d_out)
139 m.d.comb += self.mmu.d_in.eq(self.dcache.m_out)
140
141 return m
142
143 def ports(self):
144 yield from super().ports()
145 # TODO: memory ports
146
147 wbget.stop = False
148
149
150 def mmu_lookup(dut, addr):
151 mmu = dut.mmu
152
153 print("pi_ld")
154 yield from pi_ld(dut.pi, addr, 1)
155 print("pi_ld done")
156 """
157 # original test code kept for reference
158 while not stop: # wait for dc_valid / err
159 print("waiting for mmu")
160 l_done = yield (mmu.l_out.done)
161 l_err = yield (mmu.l_out.err)
162 l_badtree = yield (mmu.l_out.badtree)
163 l_permerr = yield (mmu.l_out.perm_error)
164 l_rc_err = yield (mmu.l_out.rc_error)
165 l_segerr = yield (mmu.l_out.segerr)
166 l_invalid = yield (mmu.l_out.invalid)
167 if (l_done or l_err or l_badtree or
168 l_permerr or l_rc_err or l_segerr or l_invalid):
169 break
170 yield
171 """
172 phys_addr = yield mmu.d_out.addr
173 pte = yield mmu.d_out.pte
174 l_done = yield (mmu.l_out.done)
175 l_err = yield (mmu.l_out.err)
176 l_badtree = yield (mmu.l_out.badtree)
177 print ("translated done %d err %d badtree %d addr %x pte %x" % \
178 (l_done, l_err, l_badtree, phys_addr, pte))
179 yield
180 yield mmu.l_in.valid.eq(0)
181
182 return phys_addr
183
184 def mmu_sim(dut):
185 mmu = dut.mmu
186 yield mmu.rin.prtbl.eq(0x1000000) # set process table
187 yield
188
189 addr = 0x10000
190 data = 0
191 print("pi_st")
192
193 # TODO mmu_lookup using port interface
194 # set inputs
195 phys_addr = yield from mmu_lookup(dut, 0x10000)
196 assert phys_addr == 0x40000
197
198 phys_addr = yield from mmu_lookup(dut, 0x10000)
199 assert phys_addr == 0x40000
200
201 wbget.stop = True
202
203
204 def test_mmu():
205 mmu = MMU()
206 dcache = DCache()
207 dut = TestMicrowattMemoryPortInterface(mmu, dcache)
208
209 m = Module()
210 m.submodules.dut = dut
211
212 # nmigen Simulation
213 sim = Simulator(m)
214 sim.add_clock(1e-6)
215
216 sim.add_sync_process(wrap(mmu_sim(dut)))
217 sim.add_sync_process(wrap(wb_get(dcache.bus, mem)))
218 with sim.write_vcd('test_mmu_pi.vcd'):
219 sim.run()
220
221
222 if __name__ == '__main__':
223 test_mmu()