update test_compldst_multi_mmu.py to use pagetables
[soc.git] / src / soc / experiment / test / test_compldst_multi_mmu.py
1 # test case for LOAD / STORE Computation Unit using MMU
2
3 #from nmigen.compat.sim import run_simulation
4 from nmigen.sim import Simulator, Delay, Settle
5 from nmigen.cli import verilog, rtlil
6 from nmigen import Module, Signal, Mux, Cat, Elaboratable, Array, Repl
7 from nmigen.hdl.rec import Record, Layout
8
9 from nmutil.latch import SRLatch, latchregister
10 from nmutil.byterev import byte_reverse
11 from nmutil.extend import exts
12 from nmutil.util import wrap
13 from soc.fu.regspec import RegSpecAPI
14
15 from openpower.decoder.power_enums import MicrOp, Function, LDSTMode
16 from soc.fu.ldst.ldst_input_record import CompLDSTOpSubset
17 from openpower.decoder.power_decoder2 import Data
18 from openpower.consts import MSR
19
20 from soc.experiment.compalu_multi import go_record, CompUnitRecord
21 from soc.experiment.l0_cache import PortInterface
22 from soc.experiment.pimem import LDSTException
23 from soc.experiment.compldst_multi import LDSTCompUnit, load, store
24 from soc.config.test.test_loadstore import TestMemPspec
25
26 from soc.experiment.mmu import MMU
27 from nmutil.util import Display
28
29 from soc.config.loadstore import ConfigMemoryPortInterface
30 from soc.experiment.test import pagetables
31
32
33 def wait_for_debug(sig, event, wait=True, test1st=False):
34 v = (yield sig)
35 print("wait for", sig, v, wait, test1st)
36 if test1st and bool(v) == wait:
37 return
38 while True:
39 yield
40 v = (yield sig)
41 yield Display("waiting for "+event)
42 if bool(v) == wait:
43 break
44
45 def load_debug(dut, src1, src2, imm, imm_ok=True, update=False, zero_a=False,
46 byterev=True):
47 print("LD", src1, src2, imm, imm_ok, update)
48 yield dut.oper_i.insn_type.eq(MicrOp.OP_LOAD)
49 yield dut.oper_i.data_len.eq(2) # half-word
50 yield dut.oper_i.byte_reverse.eq(byterev)
51 yield dut.src1_i.eq(src1)
52 yield dut.src2_i.eq(src2)
53 yield dut.oper_i.zero_a.eq(zero_a)
54 yield dut.oper_i.imm_data.data.eq(imm)
55 yield dut.oper_i.imm_data.ok.eq(imm_ok)
56 yield dut.issue_i.eq(1)
57 yield
58 yield dut.issue_i.eq(0)
59 yield
60
61 # set up read-operand flags
62 rd = 0b00
63 if not imm_ok: # no immediate means RB register needs to be read
64 rd |= 0b10
65 if not zero_a: # no zero-a means RA needs to be read
66 rd |= 0b01
67
68 # wait for the operands (RA, RB, or both)
69 if rd:
70 yield dut.rd.go_i.eq(rd)
71 yield from wait_for_debug(dut.rd.rel_o,"operands")
72 yield dut.rd.go_i.eq(0)
73
74 yield from wait_for_debug(dut.adr_rel_o, "adr_rel_o" ,False, test1st=True)
75 yield Display("load_debug: done")
76 # yield dut.ad.go.eq(1)
77 # yield
78 # yield dut.ad.go.eq(0)
79
80 """
81 guess: hangs here
82
83 if update:
84 yield from wait_for(dut.wr.rel_o[1])
85 yield dut.wr.go.eq(0b10)
86 yield
87 addr = yield dut.addr_o
88 print("addr", addr)
89 yield dut.wr.go.eq(0)
90 else:
91 addr = None
92
93 yield from wait_for(dut.wr.rel_o[0], test1st=True)
94 yield dut.wr.go.eq(1)
95 yield
96 data = yield dut.o_data
97 print(data)
98 yield dut.wr.go.eq(0)
99 yield from wait_for(dut.busy_o)
100 yield
101 # wait_for(dut.stwd_mem_o)
102 return data, addr
103 """
104
105 # removed
106
107 # same thing as soc/src/soc/experiment/test/test_dcbz_pi.py
108 def ldst_sim(dut):
109 yield dut.mmu.rin.prtbl.eq(0x1000000) # set process table
110 ###yield from dcbz(dut, 4, 0, 3) # EA=7
111 addr = 0x100e0
112 data = 0xf553b658ba7e1f51
113
114 yield from store(dut, addr, 0, data, 0)
115 yield
116 yield from load_debug(dut, 4, 0, 2) #FIXME
117 """
118 ld_data = yield from pi_ld(pi, addr, 8, msr_pr=0)
119 assert ld_data == 0xf553b658ba7e1f51
120 ld_data = yield from pi_ld(pi, addr, 8, msr_pr=0)
121 assert ld_data == 0xf553b658ba7e1f51
122 """
123 yield
124
125 ########################################
126
127
128 class TestLDSTCompUnitMMU(LDSTCompUnit):
129
130 def __init__(self, rwid, pspec):
131 from soc.experiment.l0_cache import TstL0CacheBuffer
132 self.l0 = l0 = TstL0CacheBuffer(pspec)
133 pi = l0.l0.dports[0]
134 LDSTCompUnit.__init__(self, pi, rwid, 4)
135
136 def elaborate(self, platform):
137 m = LDSTCompUnit.elaborate(self, platform)
138 m.submodules.l0 = self.l0
139 # link addr-go direct to rel
140 m.d.comb += self.ad.go_i.eq(self.ad.rel_o)
141 return m
142
143
144 def test_scoreboard_mmu():
145
146 units = {}
147 pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
148 imem_ifacetype='bare_wb',
149 addr_wid=48,
150 mask_wid=8,
151 reg_wid=64,
152 units=units)
153
154 dut = TestLDSTCompUnitMMU(16,pspec)
155 vl = rtlil.convert(dut, ports=dut.ports())
156 with open("test_ldst_comp_mmu1.il", "w") as f:
157 f.write(vl)
158
159 run_simulation(dut, ldst_sim(dut), vcd_name='test_ldst_comp.vcd')
160 #TODO add wb runner here
161
162
163 ########################################
164 class TestLDSTCompUnitRegSpecMMU(LDSTCompUnit):
165
166 def __init__(self, pspec):
167 from soc.experiment.l0_cache import TstL0CacheBuffer
168 from soc.fu.ldst.pipe_data import LDSTPipeSpec
169 regspec = LDSTPipeSpec.regspec
170
171 # use a LoadStore1 here
172
173 cmpi = ConfigMemoryPortInterface(pspec)
174 self.cmpi = cmpi
175 ldst = cmpi.pi
176 self.l0 = ldst
177
178 self.mmu = MMU()
179 LDSTCompUnit.__init__(self, ldst.pi, regspec, 4)
180
181 def elaborate(self, platform):
182 m = LDSTCompUnit.elaborate(self, platform)
183 m.submodules.l0 = self.l0
184 m.submodules.mmu = self.mmu
185 # link addr-go direct to rel
186 m.d.comb += self.ad.go_i.eq(self.ad.rel_o)
187
188 # link mmu and dcache together
189 dcache = self.l0.dcache
190 mmu = self.mmu
191 m.d.comb += dcache.m_in.eq(mmu.d_out) # MMUToDCacheType
192 m.d.comb += mmu.d_in.eq(dcache.m_out) # DCacheToMMUType
193
194 return m
195
196 # FIXME: this is redundant code
197 def wb_get(wb, mem):
198 """simulator process for getting memory load requests
199 """
200
201 global stop
202 assert(stop==False)
203
204 while not stop:
205 while True: # wait for dc_valid
206 if stop:
207 return
208 cyc = yield (wb.cyc)
209 stb = yield (wb.stb)
210 if cyc and stb:
211 break
212 yield
213 addr = (yield wb.adr) << 3
214 stop = True # hack for testing
215 if addr not in mem:
216 print (" WB LOOKUP NO entry @ %x, returning zero" % (addr))
217
218 # read or write?
219 we = (yield wb.we)
220 if we:
221 store = (yield wb.dat_w)
222 sel = (yield wb.sel)
223 data = mem.get(addr, 0)
224 # note we assume 8-bit sel, here
225 res = 0
226 for i in range(8):
227 mask = 0xff << (i*8)
228 if sel & (1<<i):
229 res |= store & mask
230 else:
231 res |= data & mask
232 mem[addr] = res
233 print (" DCACHE set %x mask %x data %x" % (addr, sel, res))
234 else:
235 data = mem.get(addr, 0)
236 yield wb.dat_r.eq(data)
237 print (" DCACHE get %x data %x" % (addr, data))
238
239 yield wb.ack.eq(1)
240 yield
241 yield wb.ack.eq(0)
242 yield
243
244 def test_scoreboard_regspec_mmu():
245
246 m = Module()
247
248 units = {}
249 pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
250 imem_ifacetype='bare_wb',
251 addr_wid=48,
252 mask_wid=8,
253 reg_wid=64,
254 units=units)
255
256 dut = TestLDSTCompUnitRegSpecMMU(pspec)
257
258 m.submodules.dut = dut
259
260 sim = Simulator(m)
261 sim.add_clock(1e-6)
262
263 mem = pagetables.test1
264
265 sim.add_sync_process(wrap(ldst_sim(dut)))
266 sim.add_sync_process(wrap(wb_get(dut.cmpi.wb_bus(), mem)))
267 with sim.write_vcd('test_scoreboard_regspec_mmu'):
268 sim.run()
269
270
271 if __name__ == '__main__':
272 #FIXME: avoid using global variables
273 global stop
274 stop = False
275 test_scoreboard_regspec_mmu()
276 #only one test for now -- test_scoreboard_mmu()