Revert "Setup SVSTATE, from the test settings, at the start"
[soc.git] / src / soc / simple / test / test_runner.py
1 """TestRunner class, runs TestIssuer instructions
2
3 related bugs:
4
5 * https://bugs.libre-soc.org/show_bug.cgi?id=363
6 """
7 from nmigen import Module, Signal, Cat, ClockSignal
8
9 # NOTE: to use cxxsim, export NMIGEN_SIM_MODE=cxxsim from the shell
10 # Also, check out the cxxsim nmigen branch, and latest yosys from git
11 from nmutil.sim_tmp_alternative import Simulator, Settle
12
13 from nmutil.formaltest import FHDLTestCase
14 from nmutil.gtkw import write_gtkw
15 from nmigen.cli import rtlil
16 from soc.decoder.isa.caller import special_sprs
17 from soc.decoder.isa.all import ISA
18 from soc.config.endian import bigendian
19
20 from soc.decoder.power_decoder import create_pdecode
21 from soc.decoder.power_decoder2 import PowerDecode2
22
23 from soc.simple.issuer import TestIssuerInternal
24
25 from soc.config.test.test_loadstore import TestMemPspec
26 from soc.simple.test.test_core import (setup_regs, check_regs,
27 wait_for_busy_clear,
28 wait_for_busy_hi)
29 from soc.fu.compunits.test.test_compunit import (setup_test_memory,
30 check_sim_memory)
31 from soc.debug.dmi import DBGCore, DBGCtrl, DBGStat
32
33
34 def setup_i_memory(imem, startaddr, instructions):
35 mem = imem
36 print("insn before, init mem", mem.depth, mem.width, mem,
37 len(instructions))
38 for i in range(mem.depth):
39 yield mem._array[i].eq(0)
40 yield Settle()
41 startaddr //= 4 # instructions are 32-bit
42 if mem.width == 32:
43 mask = ((1 << 32)-1)
44 for ins in instructions:
45 if isinstance(ins, tuple):
46 insn, code = ins
47 else:
48 insn, code = ins, ''
49 insn = insn & 0xffffffff
50 yield mem._array[startaddr].eq(insn)
51 yield Settle()
52 if insn != 0:
53 print("instr: %06x 0x%x %s" % (4*startaddr, insn, code))
54 startaddr += 1
55 startaddr = startaddr & mask
56 return
57
58 # 64 bit
59 mask = ((1 << 64)-1)
60 for ins in instructions:
61 if isinstance(ins, tuple):
62 insn, code = ins
63 else:
64 insn, code = ins, ''
65 insn = insn & 0xffffffff
66 msbs = (startaddr >> 1) & mask
67 val = yield mem._array[msbs]
68 if insn != 0:
69 print("before set", hex(4*startaddr),
70 hex(msbs), hex(val), hex(insn))
71 lsb = 1 if (startaddr & 1) else 0
72 val = (val | (insn << (lsb*32)))
73 val = val & mask
74 yield mem._array[msbs].eq(val)
75 yield Settle()
76 if insn != 0:
77 print("after set", hex(4*startaddr), hex(msbs), hex(val))
78 print("instr: %06x 0x%x %s %08x" % (4*startaddr, insn, code, val))
79 startaddr += 1
80 startaddr = startaddr & mask
81
82
83 def set_dmi(dmi, addr, data):
84 yield dmi.req_i.eq(1)
85 yield dmi.addr_i.eq(addr)
86 yield dmi.din.eq(data)
87 yield dmi.we_i.eq(1)
88 while True:
89 ack = yield dmi.ack_o
90 if ack:
91 break
92 yield
93 yield
94 yield dmi.req_i.eq(0)
95 yield dmi.addr_i.eq(0)
96 yield dmi.din.eq(0)
97 yield dmi.we_i.eq(0)
98 yield
99
100
101 def get_dmi(dmi, addr):
102 yield dmi.req_i.eq(1)
103 yield dmi.addr_i.eq(addr)
104 yield dmi.din.eq(0)
105 yield dmi.we_i.eq(0)
106 while True:
107 ack = yield dmi.ack_o
108 if ack:
109 break
110 yield
111 yield # wait one
112 data = yield dmi.dout # get data after ack valid for 1 cycle
113 yield dmi.req_i.eq(0)
114 yield dmi.addr_i.eq(0)
115 yield dmi.we_i.eq(0)
116 yield
117 return data
118
119
120 class TestRunner(FHDLTestCase):
121 def __init__(self, tst_data, microwatt_mmu=False):
122 super().__init__("run_all")
123 self.test_data = tst_data
124 self.microwatt_mmu = microwatt_mmu
125
126 def run_all(self):
127 m = Module()
128 comb = m.d.comb
129 pc_i = Signal(32)
130
131 pspec = TestMemPspec(ldst_ifacetype='test_bare_wb',
132 imem_ifacetype='test_bare_wb',
133 addr_wid=48,
134 mask_wid=8,
135 imem_reg_wid=64,
136 # wb_data_width=32,
137 use_pll=False,
138 nocore=False,
139 xics=False,
140 gpio=False,
141 mmu=self.microwatt_mmu,
142 reg_wid=64)
143 m.submodules.issuer = issuer = TestIssuerInternal(pspec)
144 imem = issuer.imem._get_memory()
145 core = issuer.core
146 dmi = issuer.dbg.dmi
147 pdecode2 = issuer.pdecode2
148 l0 = core.l0
149
150 # copy of the decoder for simulator
151 simdec = create_pdecode()
152 simdec2 = PowerDecode2(simdec)
153 m.submodules.simdec2 = simdec2 # pain in the neck
154
155 # run core clock at same rate as test clock
156 intclk = ClockSignal("coresync")
157 comb += intclk.eq(ClockSignal())
158
159 comb += issuer.pc_i.data.eq(pc_i)
160
161 # nmigen Simulation
162 sim = Simulator(m)
163 sim.add_clock(1e-6)
164
165 def process():
166
167 # start in stopped
168 yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
169 yield
170 yield
171
172 # get each test, completely reset the core, and run it
173
174 for test in self.test_data:
175
176 # pull a reset
177 # yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.RESET)
178
179 # set up bigendian (TODO: don't do this, use MSR)
180 yield issuer.core_bigendian_i.eq(bigendian)
181 yield Settle()
182
183 yield
184 yield
185 yield
186 yield
187
188 print(test.name)
189 program = test.program
190 self.subTest(test.name)
191 print("regs", test.regs)
192 print("sprs", test.sprs)
193 print("cr", test.cr)
194 print("mem", test.mem)
195 print("msr", test.msr)
196 print("assem", program.assembly)
197 gen = list(program.generate_instructions())
198 insncode = program.assembly.splitlines()
199 instructions = list(zip(gen, insncode))
200
201 # set up the Simulator (which must track TestIssuer exactly)
202 sim = ISA(simdec2, test.regs, test.sprs, test.cr, test.mem,
203 test.msr,
204 initial_insns=gen, respect_pc=True,
205 disassembly=insncode,
206 bigendian=bigendian,
207 initial_svstate=test.svstate)
208
209 # establish the TestIssuer context (mem, regs etc)
210
211 pc = 0 # start address
212 counter = 0 # test to pause/start
213
214 yield from setup_i_memory(imem, pc, instructions)
215 yield from setup_test_memory(l0, sim)
216 yield from setup_regs(pdecode2, core, test)
217 # TODO, setup svstate here in core.regs.state regfile
218 # https://bugs.libre-soc.org/show_bug.cgi?id=583#c35
219
220 yield pc_i.eq(pc)
221 yield issuer.pc_i.ok.eq(1)
222 yield
223
224 print("instructions", instructions)
225
226 # run the loop of the instructions on the current test
227 index = sim.pc.CIA.value//4
228 while index < len(instructions):
229 ins, code = instructions[index]
230
231 print("instruction: 0x{:X}".format(ins & 0xffffffff))
232 print(index, code)
233
234 if counter == 0:
235 # start the core
236 yield
237 yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.START)
238 yield issuer.pc_i.ok.eq(0) # no change PC after this
239 yield
240 yield
241
242 counter = counter + 1
243
244 # wait until executed
245 yield from wait_for_busy_hi(core)
246 yield from wait_for_busy_clear(core)
247
248 # set up simulated instruction (in simdec2)
249 try:
250 yield from sim.setup_one()
251 except KeyError: # indicates instruction not in imem: stop
252 break
253 yield Settle()
254
255 # call simulated operation
256 print("sim", code)
257 yield from sim.execute_one()
258 yield Settle()
259 index = sim.pc.CIA.value//4
260
261 terminated = yield issuer.dbg.terminated_o
262 print("terminated", terminated)
263
264 if index >= len(instructions):
265 print ("index over, send dmi stop")
266 # stop at end
267 yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
268 yield
269 yield
270
271 # wait one cycle for registers to settle
272 yield
273
274 # register check
275 yield from check_regs(self, sim, core, test, code)
276
277 # Memory check
278 yield from check_sim_memory(self, l0, sim, code)
279
280 terminated = yield issuer.dbg.terminated_o
281 print("terminated(2)", terminated)
282 if terminated:
283 break
284
285 # stop at end
286 yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
287 yield
288 yield
289
290 # get CR
291 cr = yield from get_dmi(dmi, DBGCore.CR)
292 print("after test %s cr value %x" % (test.name, cr))
293
294 # get XER
295 xer = yield from get_dmi(dmi, DBGCore.XER)
296 print("after test %s XER value %x" % (test.name, xer))
297
298 # test of dmi reg get
299 for int_reg in range(32):
300 yield from set_dmi(dmi, DBGCore.GSPR_IDX, int_reg)
301 value = yield from get_dmi(dmi, DBGCore.GSPR_DATA)
302
303 print("after test %s reg %2d value %x" %
304 (test.name, int_reg, value))
305
306 styles = {
307 'dec': {'base': 'dec'},
308 'bin': {'base': 'bin'}
309 }
310
311 traces = [
312 'clk',
313 {'comment': 'state machines'},
314 'fetch_pc_valid_i', 'fetch_pc_ready_o', 'fetch_fsm_state',
315 'fetch_insn_valid_o', 'fetch_insn_ready_i', 'fsm_state',
316 {'comment': 'fetch and decode'},
317 'cia[63:0]', 'nia[63:0]', 'pc[63:0]', 'raw_insn_i[31:0]',
318 'raw_opcode_in[31:0]', 'insn_type',
319 {'comment': 'svp64 decoding'},
320 'svp64_rm[23:0]',
321 ('dec2.extra[8:0]', 'bin'),
322 ('register augmentation', 'dec', [
323 {'comment': 'v3.0b registers'},
324 'dec2.dec_o.RT[4:0]',
325 'dec2.dec_a.RA[4:0]',
326 'dec2.dec_b.RB[4:0]',
327 ('Rdest', [
328 'dec2.o_svdec.reg_in[4:0]',
329 ('dec2.o_svdec.spec[2:0]', 'bin'),
330 'dec2.o_svdec.reg_out[6:0]']),
331 ('Rsrc1', [
332 'dec2.in1_svdec.reg_in[4:0]',
333 ('dec2.in1_svdec.spec[2:0]', 'bin'),
334 'dec2.in1_svdec.reg_out[6:0]']),
335 ('Rsrc1', [
336 'dec2.in2_svdec.reg_in[4:0]',
337 ('dec2.in2_svdec.spec[2:0]', 'bin'),
338 'dec2.in2_svdec.reg_out[6:0]']),
339 {'comment': 'SVP64 registers'},
340 'dec2.rego[6:0]', 'dec2.reg1[6:0]', 'dec2.reg2[6:0]'
341 ]),
342 {'comment': 'issue and execute'},
343 'core.core_core_insn_type',
344 (None, 'dec', [
345 'core_rego[6:0]', 'core_reg1[6:0]', 'core_reg2[6:0]']),
346 'issue_i', 'busy_o',
347 {'comment': 'dmi'},
348 'dbg.dmi_req_i', 'dbg.dmi_ack_o',
349 {'comment': 'instruction memory'},
350 'imem.sram.rdport.memory(0)[63:0]',
351 {'comment': 'registers'},
352 'core.int.rp_src1.memory(0)[63:0]',
353 'core.int.rp_src1.memory(1)[63:0]',
354 'core.int.rp_src1.memory(2)[63:0]',
355 'core.int.rp_src1.memory(3)[63:0]',
356 'core.int.rp_src1.memory(4)[63:0]',
357 'core.int.rp_src1.memory(5)[63:0]',
358 'core.int.rp_src1.memory(6)[63:0]',
359 'core.int.rp_src1.memory(7)[63:0]',
360 'core.int.rp_src1.memory(9)[63:0]',
361 'core.int.rp_src1.memory(10)[63:0]',
362 'core.int.rp_src1.memory(13)[63:0]',
363 ]
364
365 if self.microwatt_mmu:
366 traces += [
367 {'comment': 'microwatt_mmu'},
368 'core.fus.mmu0.alu_mmu0.illegal',
369 'core.fus.mmu0.alu_mmu0.debug0[3:0]',
370 'core.fus.mmu0.alu_mmu0.mmu.state',
371 'core.fus.mmu0.alu_mmu0.mmu.pid[31:0]',
372 'core.fus.mmu0.alu_mmu0.mmu.prtbl[63:0]'
373 ]
374
375 write_gtkw("issuer_simulator.gtkw",
376 "issuer_simulator.vcd",
377 traces, styles, module='top.issuer')
378
379 sim.add_sync_process(process)
380 with sim.write_vcd("issuer_simulator.vcd"):
381 sim.run()