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