Fix whitespace
[soc.git] / src / soc / simple / test / test_issuer.py
1 """simple core test, runs instructions from a TestMemory
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 import unittest
17 from soc.decoder.isa.caller import special_sprs
18 from soc.decoder.isa.all import ISA
19 from soc.decoder.power_enums import Function, XER_bits
20 from soc.config.endian import bigendian
21
22 from soc.decoder.power_decoder import create_pdecode
23 from soc.decoder.power_decoder2 import PowerDecode2
24
25 from soc.simple.issuer import TestIssuerInternal
26 from soc.experiment.compalu_multi import find_ok # hack
27
28 from soc.config.test.test_loadstore import TestMemPspec
29 from soc.simple.test.test_core import (setup_regs, check_regs,
30 wait_for_busy_clear,
31 wait_for_busy_hi)
32 from soc.fu.compunits.test.test_compunit import (setup_test_memory,
33 check_sim_memory)
34 from soc.debug.dmi import DBGCore, DBGCtrl, DBGStat
35
36 # test with ALU data and Logical data
37 from soc.fu.alu.test.test_pipe_caller import ALUTestCase
38 from soc.fu.div.test.test_pipe_caller import DivTestCases
39 from soc.fu.logical.test.test_pipe_caller import LogicalTestCase
40 from soc.fu.shift_rot.test.test_pipe_caller import ShiftRotTestCase
41 from soc.fu.cr.test.test_pipe_caller import CRTestCase
42 # from soc.fu.branch.test.test_pipe_caller import BranchTestCase
43 # from soc.fu.spr.test.test_pipe_caller import SPRTestCase
44 from soc.fu.ldst.test.test_pipe_caller import LDSTTestCase
45 from soc.simulator.test_sim import (GeneralTestCases, AttnTestCase)
46 # from soc.simulator.test_helloworld_sim import HelloTestCases
47
48
49 def setup_i_memory(imem, startaddr, instructions):
50 mem = imem
51 print("insn before, init mem", mem.depth, mem.width, mem,
52 len(instructions))
53 for i in range(mem.depth):
54 yield mem._array[i].eq(0)
55 yield Settle()
56 startaddr //= 4 # instructions are 32-bit
57 if mem.width == 32:
58 mask = ((1 << 32)-1)
59 for ins in instructions:
60 if isinstance(ins, tuple):
61 insn, code = ins
62 else:
63 insn, code = ins, ''
64 insn = insn & 0xffffffff
65 yield mem._array[startaddr].eq(insn)
66 yield Settle()
67 if insn != 0:
68 print("instr: %06x 0x%x %s" % (4*startaddr, insn, code))
69 startaddr += 1
70 startaddr = startaddr & mask
71 return
72
73 # 64 bit
74 mask = ((1 << 64)-1)
75 for ins in instructions:
76 if isinstance(ins, tuple):
77 insn, code = ins
78 else:
79 insn, code = ins, ''
80 insn = insn & 0xffffffff
81 msbs = (startaddr >> 1) & mask
82 val = yield mem._array[msbs]
83 if insn != 0:
84 print("before set", hex(4*startaddr),
85 hex(msbs), hex(val), hex(insn))
86 lsb = 1 if (startaddr & 1) else 0
87 val = (val | (insn << (lsb*32)))
88 val = val & mask
89 yield mem._array[msbs].eq(val)
90 yield Settle()
91 if insn != 0:
92 print("after set", hex(4*startaddr), hex(msbs), hex(val))
93 print("instr: %06x 0x%x %s %08x" % (4*startaddr, insn, code, val))
94 startaddr += 1
95 startaddr = startaddr & mask
96
97
98 def set_dmi(dmi, addr, data):
99 yield dmi.req_i.eq(1)
100 yield dmi.addr_i.eq(addr)
101 yield dmi.din.eq(data)
102 yield dmi.we_i.eq(1)
103 while True:
104 ack = yield dmi.ack_o
105 if ack:
106 break
107 yield
108 yield
109 yield dmi.req_i.eq(0)
110 yield dmi.addr_i.eq(0)
111 yield dmi.din.eq(0)
112 yield dmi.we_i.eq(0)
113 yield
114
115
116 def get_dmi(dmi, addr):
117 yield dmi.req_i.eq(1)
118 yield dmi.addr_i.eq(addr)
119 yield dmi.din.eq(0)
120 yield dmi.we_i.eq(0)
121 while True:
122 ack = yield dmi.ack_o
123 if ack:
124 break
125 yield
126 yield # wait one
127 data = yield dmi.dout # get data after ack valid for 1 cycle
128 yield dmi.req_i.eq(0)
129 yield dmi.addr_i.eq(0)
130 yield dmi.we_i.eq(0)
131 yield
132 return data
133
134
135 class TestRunner(FHDLTestCase):
136 def __init__(self, tst_data, microwatt_mmu=False):
137 super().__init__("run_all")
138 self.test_data = tst_data
139 self.microwatt_mmu = microwatt_mmu
140
141 def run_all(self):
142 m = Module()
143 comb = m.d.comb
144 pc_i = Signal(32)
145
146 pspec = TestMemPspec(ldst_ifacetype='test_bare_wb',
147 imem_ifacetype='test_bare_wb',
148 addr_wid=48,
149 mask_wid=8,
150 imem_reg_wid=64,
151 # wb_data_width=32,
152 use_pll=False,
153 nocore=False,
154 xics=False,
155 gpio=False,
156 mmu=self.microwatt_mmu,
157 reg_wid=64)
158 m.submodules.issuer = issuer = TestIssuerInternal(pspec)
159 imem = issuer.imem._get_memory()
160 core = issuer.core
161 dmi = issuer.dbg.dmi
162 pdecode2 = issuer.pdecode2
163 l0 = core.l0
164
165 # copy of the decoder for simulator
166 simdec = create_pdecode()
167 simdec2 = PowerDecode2(simdec)
168 m.submodules.simdec2 = simdec2 # pain in the neck
169
170 # run core clock at same rate as test clock
171 intclk = ClockSignal("coresync")
172 comb += intclk.eq(ClockSignal())
173
174 comb += issuer.pc_i.data.eq(pc_i)
175
176 # nmigen Simulation
177 sim = Simulator(m)
178 sim.add_clock(1e-6)
179
180 def process():
181
182 # start in stopped
183 yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
184 yield
185 yield
186
187 for test in self.test_data:
188
189 # pull a reset
190 # yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.RESET)
191
192 # set up bigendian (TODO: don't do this, use MSR)
193 yield issuer.core_bigendian_i.eq(bigendian)
194 yield Settle()
195
196 yield
197 yield
198 yield
199 yield
200
201 print(test.name)
202 program = test.program
203 self.subTest(test.name)
204 print("regs", test.regs)
205 print("sprs", test.sprs)
206 print("cr", test.cr)
207 print("mem", test.mem)
208 print("msr", test.msr)
209 print("assem", program.assembly)
210 gen = list(program.generate_instructions())
211 insncode = program.assembly.splitlines()
212 instructions = list(zip(gen, insncode))
213 sim = ISA(simdec2, test.regs, test.sprs, test.cr, test.mem,
214 test.msr,
215 initial_insns=gen, respect_pc=True,
216 disassembly=insncode,
217 bigendian=bigendian)
218
219 pc = 0 # start address
220 counter = 0 # test to pause/start
221
222 yield from setup_i_memory(imem, pc, instructions)
223 yield from setup_test_memory(l0, sim)
224 yield from setup_regs(pdecode2, core, test)
225
226 yield pc_i.eq(pc)
227 yield issuer.pc_i.ok.eq(1)
228 yield
229
230 print("instructions", instructions)
231
232 index = sim.pc.CIA.value//4
233 while index < len(instructions):
234 ins, code = instructions[index]
235
236 print("instruction: 0x{:X}".format(ins & 0xffffffff))
237 print(index, code)
238
239 if counter == 0:
240 # start the core
241 yield
242 yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.START)
243 yield issuer.pc_i.ok.eq(0) # no change PC after this
244 yield
245 yield
246
247 counter = counter + 1
248
249 # wait until executed
250 yield from wait_for_busy_hi(core)
251 yield from wait_for_busy_clear(core)
252
253 # set up simulated instruction (in simdec2)
254 try:
255 yield from sim.setup_one()
256 except KeyError: # indicates instruction not in imem: stop
257 break
258 yield Settle()
259
260 # call simulated operation
261 print("sim", code)
262 yield from sim.execute_one()
263 yield Settle()
264 index = sim.pc.CIA.value//4
265
266 terminated = yield issuer.dbg.terminated_o
267 print("terminated", terminated)
268
269 if index >= len(instructions):
270 print ("index over, send dmi stop")
271 # stop at end
272 yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
273 yield
274 yield
275
276 # wait one cycle for registers to settle
277 yield
278
279 # register check
280 yield from check_regs(self, sim, core, test, code)
281
282 # Memory check
283 yield from check_sim_memory(self, l0, sim, code)
284
285 terminated = yield issuer.dbg.terminated_o
286 print("terminated(2)", terminated)
287 if terminated:
288 break
289
290 # stop at end
291 yield from set_dmi(dmi, DBGCore.CTRL, 1<<DBGCtrl.STOP)
292 yield
293 yield
294
295 # get CR
296 cr = yield from get_dmi(dmi, DBGCore.CR)
297 print("after test %s cr value %x" % (test.name, cr))
298
299 # get XER
300 xer = yield from get_dmi(dmi, DBGCore.XER)
301 print("after test %s XER value %x" % (test.name, xer))
302
303 # test of dmi reg get
304 for int_reg in range(32):
305 yield from set_dmi(dmi, DBGCore.GSPR_IDX, int_reg)
306 value = yield from get_dmi(dmi, DBGCore.GSPR_DATA)
307
308 print("after test %s reg %2d value %x" %
309 (test.name, int_reg, value))
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': 'issue and execute'},
320 'core.core_core_insn_type', 'issue_i', 'busy_o',
321 {'comment': 'dmi'},
322 'dbg.dmi_req_i', 'dbg.dmi_ack_o',
323 {'comment': 'instruction memory'},
324 'imem.sram.rdport.memory(0)[63:0]',
325 {'comment': 'registers'},
326 'core.int.rp_src1.memory(0)[63:0]',
327 'core.int.rp_src1.memory(1)[63:0]',
328 'core.int.rp_src1.memory(2)[63:0]',
329 'core.int.rp_src1.memory(3)[63:0]',
330 'core.int.rp_src1.memory(4)[63:0]',
331 'core.int.rp_src1.memory(9)[63:0]',
332 ]
333
334 if self.microwatt_mmu:
335 traces += [
336 {'comment': 'microwatt_mmu'},
337 'core.fus.mmu0.alu_mmu0.illegal',
338 'core.fus.mmu0.alu_mmu0.debug0[3:0]'
339 ]
340
341 write_gtkw("issuer_simulator.gtkw",
342 "issuer_simulator.vcd",
343 traces, module='top.issuer')
344
345 sim.add_sync_process(process)
346 with sim.write_vcd("issuer_simulator.vcd"):
347 sim.run()
348
349
350 if __name__ == "__main__":
351 unittest.main(exit=False)
352 suite = unittest.TestSuite()
353 # suite.addTest(TestRunner(HelloTestCases.test_data))
354 suite.addTest(TestRunner(DivTestCases().test_data))
355 # suite.addTest(TestRunner(AttnTestCase.test_data))
356 suite.addTest(TestRunner(GeneralTestCases.test_data))
357 suite.addTest(TestRunner(LDSTTestCase().test_data))
358 suite.addTest(TestRunner(CRTestCase().test_data))
359 suite.addTest(TestRunner(ShiftRotTestCase().test_data))
360 suite.addTest(TestRunner(LogicalTestCase().test_data))
361 suite.addTest(TestRunner(ALUTestCase().test_data))
362 # suite.addTest(TestRunner(BranchTestCase.test_data))
363 # suite.addTest(TestRunner(SPRTestCase.test_data))
364
365 runner = unittest.TextTestRunner()
366 runner.run(suite)