add wishbone driver for test_compldst_multi_mmu.py
[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
31 def b(x): # byte-reverse function
32 return int.from_bytes(x.to_bytes(8, byteorder='little'),
33 byteorder='big', signed=False)
34 #FIXME: move to common module
35
36 def wait_for_debug(sig, event, wait=True, test1st=False):
37 v = (yield sig)
38 print("wait for", sig, v, wait, test1st)
39 if test1st and bool(v) == wait:
40 return
41 while True:
42 yield
43 v = (yield sig)
44 yield Display("waiting for "+event)
45 if bool(v) == wait:
46 break
47
48 def load_debug(dut, src1, src2, imm, imm_ok=True, update=False, zero_a=False,
49 byterev=True):
50 print("LD", src1, src2, imm, imm_ok, update)
51 yield dut.oper_i.insn_type.eq(MicrOp.OP_LOAD)
52 yield dut.oper_i.data_len.eq(2) # half-word
53 yield dut.oper_i.byte_reverse.eq(byterev)
54 yield dut.src1_i.eq(src1)
55 yield dut.src2_i.eq(src2)
56 yield dut.oper_i.zero_a.eq(zero_a)
57 yield dut.oper_i.imm_data.data.eq(imm)
58 yield dut.oper_i.imm_data.ok.eq(imm_ok)
59 yield dut.issue_i.eq(1)
60 yield
61 yield dut.issue_i.eq(0)
62 yield
63
64 # set up read-operand flags
65 rd = 0b00
66 if not imm_ok: # no immediate means RB register needs to be read
67 rd |= 0b10
68 if not zero_a: # no zero-a means RA needs to be read
69 rd |= 0b01
70
71 # wait for the operands (RA, RB, or both)
72 if rd:
73 yield dut.rd.go_i.eq(rd)
74 yield from wait_for_debug(dut.rd.rel_o,"operands")
75 yield dut.rd.go_i.eq(0)
76
77 yield from wait_for_debug(dut.adr_rel_o, "adr_rel_o" ,False, test1st=True)
78 yield Display("load_debug: done")
79 # yield dut.ad.go.eq(1)
80 # yield
81 # yield dut.ad.go.eq(0)
82
83 """
84 guess: hangs here
85
86 if update:
87 yield from wait_for(dut.wr.rel_o[1])
88 yield dut.wr.go.eq(0b10)
89 yield
90 addr = yield dut.addr_o
91 print("addr", addr)
92 yield dut.wr.go.eq(0)
93 else:
94 addr = None
95
96 yield from wait_for(dut.wr.rel_o[0], test1st=True)
97 yield dut.wr.go.eq(1)
98 yield
99 data = yield dut.o_data
100 print(data)
101 yield dut.wr.go.eq(0)
102 yield from wait_for(dut.busy_o)
103 yield
104 # wait_for(dut.stwd_mem_o)
105 return data, addr
106 """
107
108 # removed
109
110 # same thing as soc/src/soc/experiment/test/test_dcbz_pi.py
111 def ldst_sim(dut):
112 yield dut.mmu.rin.prtbl.eq(0x1000000) # set process table
113 ###yield from dcbz(dut, 4, 0, 3) # EA=7
114 addr = 0x100e0
115 data = 0xf553b658ba7e1f51
116
117 yield from store(dut, addr, 0, data, 0)
118 yield
119 yield from load_debug(dut, 4, 0, 2) #FIXME
120 """
121 ld_data = yield from pi_ld(pi, addr, 8, msr_pr=0)
122 assert ld_data == 0xf553b658ba7e1f51
123 ld_data = yield from pi_ld(pi, addr, 8, msr_pr=0)
124 assert ld_data == 0xf553b658ba7e1f51
125 """
126 yield
127
128 ########################################
129
130
131 class TestLDSTCompUnitMMU(LDSTCompUnit):
132
133 def __init__(self, rwid, pspec):
134 from soc.experiment.l0_cache import TstL0CacheBuffer
135 self.l0 = l0 = TstL0CacheBuffer(pspec)
136 pi = l0.l0.dports[0]
137 LDSTCompUnit.__init__(self, pi, rwid, 4)
138
139 def elaborate(self, platform):
140 m = LDSTCompUnit.elaborate(self, platform)
141 m.submodules.l0 = self.l0
142 # link addr-go direct to rel
143 m.d.comb += self.ad.go_i.eq(self.ad.rel_o)
144 return m
145
146
147 def test_scoreboard_mmu():
148
149 units = {}
150 pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
151 imem_ifacetype='bare_wb',
152 addr_wid=48,
153 mask_wid=8,
154 reg_wid=64,
155 units=units)
156
157 dut = TestLDSTCompUnitMMU(16,pspec)
158 vl = rtlil.convert(dut, ports=dut.ports())
159 with open("test_ldst_comp_mmu1.il", "w") as f:
160 f.write(vl)
161
162 run_simulation(dut, ldst_sim(dut), vcd_name='test_ldst_comp.vcd')
163 #TODO add wb runner here
164
165
166 ########################################
167 class TestLDSTCompUnitRegSpecMMU(LDSTCompUnit):
168
169 def __init__(self, pspec):
170 from soc.experiment.l0_cache import TstL0CacheBuffer
171 from soc.fu.ldst.pipe_data import LDSTPipeSpec
172 regspec = LDSTPipeSpec.regspec
173
174 # use a LoadStore1 here
175
176 cmpi = ConfigMemoryPortInterface(pspec)
177 self.cmpi = cmpi
178 ldst = cmpi.pi
179 self.l0 = ldst
180
181 self.mmu = MMU()
182 LDSTCompUnit.__init__(self, ldst.pi, regspec, 4)
183
184 def elaborate(self, platform):
185 m = LDSTCompUnit.elaborate(self, platform)
186 m.submodules.l0 = self.l0
187 m.submodules.mmu = self.mmu
188 # link addr-go direct to rel
189 m.d.comb += self.ad.go_i.eq(self.ad.rel_o)
190
191 # link mmu and dcache together
192 dcache = self.l0.dcache
193 mmu = self.mmu
194 m.d.comb += dcache.m_in.eq(mmu.d_out) # MMUToDCacheType
195 m.d.comb += mmu.d_in.eq(dcache.m_out) # DCacheToMMUType
196
197 return m
198
199 # FIXME: this is redundant code
200 def wb_get(wb, mem):
201 """simulator process for getting memory load requests
202 """
203
204 global stop
205 assert(stop==False)
206
207 while not stop:
208 while True: # wait for dc_valid
209 if stop:
210 return
211 cyc = yield (wb.cyc)
212 stb = yield (wb.stb)
213 if cyc and stb:
214 break
215 yield
216 addr = (yield wb.adr) << 3
217 stop = True # hack for testing
218 if addr not in mem:
219 print (" WB LOOKUP NO entry @ %x, returning zero" % (addr))
220
221 # read or write?
222 we = (yield wb.we)
223 if we:
224 store = (yield wb.dat_w)
225 sel = (yield wb.sel)
226 data = mem.get(addr, 0)
227 # note we assume 8-bit sel, here
228 res = 0
229 for i in range(8):
230 mask = 0xff << (i*8)
231 if sel & (1<<i):
232 res |= store & mask
233 else:
234 res |= data & mask
235 mem[addr] = res
236 print (" DCACHE set %x mask %x data %x" % (addr, sel, res))
237 else:
238 data = mem.get(addr, 0)
239 yield wb.dat_r.eq(data)
240 print (" DCACHE get %x data %x" % (addr, data))
241
242 yield wb.ack.eq(1)
243 yield
244 yield wb.ack.eq(0)
245 yield
246
247 def test_scoreboard_regspec_mmu():
248
249 m = Module()
250
251 units = {}
252 pspec = TestMemPspec(ldst_ifacetype='mmu_cache_wb',
253 imem_ifacetype='bare_wb',
254 addr_wid=48,
255 mask_wid=8,
256 reg_wid=64,
257 units=units)
258
259 dut = TestLDSTCompUnitRegSpecMMU(pspec)
260
261 m.submodules.dut = dut
262
263 sim = Simulator(m)
264 sim.add_clock(1e-6)
265
266 sim.add_sync_process(wrap(ldst_sim(dut)))
267
268 # FIXME: this is redundant code
269 mem = {
270 0x10000: # PARTITION_TABLE_2
271 # PATB_GR=1 PRTB=0x1000 PRTS=0xb
272 b(0x800000000100000b),
273
274 0x30000: # RADIX_ROOT_PTE
275 # V = 1 L = 0 NLB = 0x400 NLS = 9
276 b(0x8000000000040009),
277
278 0x40000: # RADIX_SECOND_LEVEL
279 # V = 1 L = 1 SW = 0 RPN = 0
280 # R = 1 C = 1 ATT = 0 EAA 0x7
281 b(0xc000000000000183),
282
283 0x1000000: # PROCESS_TABLE_3
284 # RTS1 = 0x2 RPDB = 0x300 RTS2 = 0x5 RPDS = 13
285 b(0x40000000000300ad),
286
287 0x10004: 0
288
289 }
290
291 sim.add_sync_process(wrap(wb_get(dut.cmpi.wb_bus(), mem)))
292 with sim.write_vcd('test_dcbz_addr_zero.vcd'):
293 sim.run()
294
295
296 if __name__ == '__main__':
297 #FIXME: avoid using global variables
298 global stop
299 stop = False
300 test_scoreboard_regspec_mmu()
301 #only one test for now -- test_scoreboard_mmu()