1 from nmigen
import Module
, Signal
2 from nmigen
.back
.pysim
import Simulator
, Delay
, Settle
3 from nmutil
.formaltest
import FHDLTestCase
5 from soc
.decoder
.power_decoder
import (create_pdecode
)
6 from soc
.decoder
.power_enums
import (Function
, MicrOp
,
7 In1Sel
, In2Sel
, In3Sel
,
8 OutSel
, RC
, LdstLen
, CryIn
,
9 single_bit_flags
, Form
, SPR
,
10 get_signal_name
, get_csv
)
11 from soc
.decoder
.power_decoder2
import (PowerDecode2
)
12 from soc
.simulator
.program
import Program
13 from soc
.simulator
.qemu
import run_program
14 from soc
.decoder
.isa
.all
import ISA
15 from soc
.fu
.test
.common
import TestCase
16 from soc
.config
.endian
import bigendian
19 class AttnTestCase(FHDLTestCase
):
22 def __init__(self
, name
="general"):
23 super().__init
__(name
)
26 def test_0_attn(self
):
27 """simple test of attn. program is 4 long: should halt at 2nd op
29 lst
= ["addi 6, 0, 0x10",
34 with
Program(lst
, bigendian
) as program
:
35 self
.run_tst_program(program
, [1])
37 def run_tst_program(self
, prog
, initial_regs
=None, initial_sprs
=None,
39 initial_regs
= [0] * 32
40 tc
= TestCase(prog
, self
.test_name
, initial_regs
, initial_sprs
, 0,
42 self
.test_data
.append(tc
)
45 class GeneralTestCases(FHDLTestCase
):
48 def __init__(self
, name
="general"):
49 super().__init
__(name
)
52 def test_0_litex_bios_ctr_loop(self
):
54 32a4: ff ff 63 38 addi r3,r3,-1
55 32a8: 20 00 63 78 clrldi r3,r3,32
56 32ac: 01 00 23 39 addi r9,r3,1
57 32b0: a6 03 29 7d mtctr r9
59 32b8: fc ff 00 42 bdnz 32b4 <cdelay+0x10>
62 notes on converting pseudo-assembler to actual:
64 * bdnz target (equivalent to: bc 16,0,target)
65 * Clear left immediate clrldi ra,rs,n (n < 64) rldicl ra,rs,0,n
66 * CTR mtctr Rx mtspr 9,Rx
70 @unittest.skip("disable")
71 def test_0_litex_bios_cmp(self
):
72 """litex bios cmp test
74 lst
= [ "addis 26, 0, 21845",
84 with
Program(lst
, bigendian
) as program
:
85 self
.run_tst_program(program
, [5,6,7,26], initial_mem
={})
87 @unittest.skip("disable")
88 def test_0_litex_bios_r1(self
):
89 """litex bios IMM64 macro test
91 lst
= [ "addis 1,0,0",
97 with
Program(lst
, bigendian
) as program
:
98 self
.run_tst_program(program
, [1], initial_mem
={})
100 @unittest.skip("disable")
101 def test_0_litex_trampoline(self
):
102 lst
= ["tdi 0,0,0x48",
112 with
Program(lst
, bigendian
) as program
:
113 self
.run_tst_program(program
, [], initial_mem
={})
115 @unittest.skip("disable")
116 def test_0_cmp(self
):
117 lst
= ["addi 6, 0, 0x10",
122 with
Program(lst
, bigendian
) as program
:
123 self
.run_tst_program(program
, [1])
125 @unittest.skip("disable")
126 def test_example(self
):
127 lst
= ["addi 1, 0, 0x5678",
131 with
Program(lst
, bigendian
) as program
:
132 self
.run_tst_program(program
, [1, 2, 3, 4])
134 @unittest.skip("disable")
136 lst
= ["addi 1, 0, 0x5678",
141 initial_mem
= {0x1230: (0x5432123412345678, 8),
142 0x1238: (0xabcdef0187654321, 8),
144 with
Program(lst
, bigendian
) as program
:
145 self
.run_tst_program(program
,
149 @unittest.skip("disable")
150 def test_ldst_update(self
):
151 lst
= ["addi 1, 0, 0x5678",
156 initial_mem
= {0x1230: (0x5432123412345678, 8),
157 0x1238: (0xabcdef0187654321, 8),
159 with
Program(lst
, bigendian
) as program
:
160 self
.run_tst_program(program
,
164 @unittest.skip("disable")
165 def test_ld_rev_ext(self
):
166 lst
= ["addi 1, 0, 0x5678",
171 with
Program(lst
, bigendian
) as program
:
172 self
.run_tst_program(program
, [1, 2, 3])
174 @unittest.skip("disable")
175 def test_st_rev_ext(self
):
176 lst
= ["addi 1, 0, 0x5678",
181 with
Program(lst
, bigendian
) as program
:
182 self
.run_tst_program(program
, [1, 2, 3])
184 @unittest.skip("disable")
185 def test_ldst_extended(self
):
186 lst
= ["addi 1, 0, 0x5678",
191 with
Program(lst
, bigendian
) as program
:
192 self
.run_tst_program(program
, [1, 2, 3])
194 @unittest.skip("disable")
195 def test_0_ldst_widths(self
):
196 lst
= ["addis 1, 0, 0xdead",
206 with
Program(lst
, bigendian
) as program
:
207 self
.run_tst_program(program
, [1, 2, 3, 4, 5])
209 @unittest.skip("disable")
211 lst
= ["addi 1, 0, 0x1234",
214 "subfic 4, 1, 0x1337",
216 with
Program(lst
, bigendian
) as program
:
217 self
.run_tst_program(program
, [1, 2, 3, 4, 5])
219 @unittest.skip("disable")
220 def test_add_with_carry(self
):
221 lst
= ["addi 1, 0, 5",
228 with
Program(lst
, bigendian
) as program
:
229 self
.run_tst_program(program
, [1, 2, 3])
231 @unittest.skip("disable")
232 def test_addis(self
):
233 lst
= ["addi 1, 0, 0x0FFF",
236 with
Program(lst
, bigendian
) as program
:
237 self
.run_tst_program(program
, [1])
239 @unittest.skip("broken")
240 def test_mulli(self
):
241 lst
= ["addi 1, 0, 3",
244 with
Program(lst
, bigendian
) as program
:
245 self
.run_tst_program(program
, [1])
247 def test_isel_1(self
):
248 lst
= ["addi 1, 0, 0x1004",
251 "mtcrf 0b1111111, 3",
254 initial_regs
= [0] * 32
255 initial_regs
[1] = 0x1004
256 initial_regs
[2] = 0x1008
257 initial_regs
[3] = 0x00ee
258 with
Program(lst
, bigendian
) as program
:
259 self
.run_tst_program(program
, [3, 4])
261 def test_isel_2(self
):
262 lst
= ["addi 1, 0, 0x1004",
265 "mtcrf 0b1111111, 3",
268 initial_regs
= [0] * 32
269 initial_regs
[1] = 0x1004
270 initial_regs
[2] = 0x1008
271 initial_regs
[3] = 0x00ee
272 with
Program(lst
, bigendian
) as program
:
273 self
.run_tst_program(program
, [3, 4])
275 @unittest.skip("disable")
276 def test_2_load_store(self
):
277 lst
= ["addi 1, 0, 0x1004",
283 initial_regs
= [0] * 32
284 initial_regs
[1] = 0x1004
285 initial_regs
[2] = 0x1008
286 initial_regs
[3] = 0x00ee
287 initial_mem
= {0x1000: (0x5432123412345678, 8),
288 0x1008: (0xabcdef0187654321, 8),
289 0x1020: (0x1828384822324252, 8),
291 with
Program(lst
, bigendian
) as program
:
292 self
.run_tst_program(program
, [3, 4], initial_mem
)
294 @unittest.skip("disable")
295 def test_3_load_store(self
):
296 lst
= ["addi 1, 0, 0x1004",
301 initial_regs
= [0] * 32
302 initial_regs
[1] = 0x1004
303 initial_regs
[2] = 0x1002
304 initial_regs
[3] = 0x15eb
305 initial_mem
= {0x1000: (0x5432123412345678, 8),
306 0x1008: (0xabcdef0187654321, 8),
307 0x1020: (0x1828384822324252, 8),
309 with
Program(lst
, bigendian
) as program
:
310 self
.run_tst_program(program
, [1, 2, 3, 4], initial_mem
)
312 @unittest.skip("disable")
314 lst
= ["addi 1, 0, 0x1004",
315 "ori 0,0,0", # "preferred" form of nop
318 initial_regs
= [0] * 32
319 with
Program(lst
, bigendian
) as program
:
320 self
.run_tst_program(program
, [1, 3])
322 @unittest.skip("disable")
323 def test_zero_illegal(self
):
324 lst
= bytes([0x10,0x00,0x20,0x39,
327 disassembly
= ["addi 9, 0, 0x10",
330 initial_regs
= [0] * 32
331 with
Program(lst
, bigendian
) as program
:
332 program
.assembly
= '\n'.join(disassembly
) + '\n' # XXX HACK!
333 self
.run_tst_program(program
, [1, 3])
335 @unittest.skip("disable")
338 register unsigned long i asm ("r12");
346 lst
= ["addi 9, 0, 0x10", # i = 16
347 "addi 9,9,-1", # i = i - 1
348 "cmpi 0,1,9,12", # compare 9 to value 0, store in CR2
349 "bc 4,0,-8" # branch if CR2 "test was != 0"
351 with
Program(lst
, bigendian
) as program
:
352 self
.run_tst_program(program
, [9], initial_mem
={})
354 @unittest.skip("disable")
355 def test_30_addis(self
):
356 lst
= [ # "addi 0, 0, 5",
359 with
Program(lst
, bigendian
) as program
:
360 self
.run_tst_program(program
, [12])
362 @unittest.skip("disable")
363 def test_31_addis(self
):
364 """tests for zero not in register zero
366 lst
= [ "rldicr 0, 0, 32, 31",
371 "rldicr 1, 1, 32, 31",
376 with
Program(lst
, bigendian
) as program
:
377 self
.run_tst_program(program
, [0, 1, 2])
379 def run_tst_program(self
, prog
, initial_regs
=None, initial_sprs
=None,
381 initial_regs
= [0] * 32
382 tc
= TestCase(prog
, self
.test_name
, initial_regs
, initial_sprs
, 0,
384 self
.test_data
.append(tc
)
389 def run_tst(self
, generator
, initial_mem
=None, initial_pc
=0):
393 gen
= list(generator
.generate_instructions())
394 insn_code
= generator
.assembly
.splitlines()
395 instructions
= list(zip(gen
, insn_code
))
397 pdecode
= create_pdecode()
398 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
400 # place program at requested address
401 gen
= (initial_pc
, gen
)
403 simulator
= ISA(pdecode2
, [0] * 32, {}, 0, initial_mem
, 0,
404 initial_insns
=gen
, respect_pc
=True,
405 disassembly
=insn_code
,
406 initial_pc
=initial_pc
,
412 # yield pdecode2.dec.bigendian.eq(bigendian)
417 yield from simulator
.setup_one()
418 except KeyError: # indicates instruction not in imem: stop
421 yield from simulator
.execute_one()
424 sim
.add_process(process
)
425 with sim
.write_vcd("pdecode_simulator.vcd"):
430 def run_tst_program(self
, prog
, reglist
, initial_mem
=None,
431 extra_break_addr
=None):
433 simulator
= self
.run_tst(prog
, initial_mem
=initial_mem
,
434 initial_pc
=0x20000000)
436 with
run_program(prog
, initial_mem
, extra_break_addr
,
437 bigendian
=bigendian
) as q
:
438 self
.qemu_register_compare(simulator
, q
, reglist
)
439 self
.qemu_mem_compare(simulator
, q
, True)
440 print(simulator
.gpr
.dump())
442 def qemu_mem_compare(self
, sim
, qemu
, check
=True):
443 if False: # disable convenient large interesting debugging memory dump
445 qmemdump
= qemu
.get_mem(addr
, 2048)
446 for i
in range(len(qmemdump
)):
447 s
= hex(int(qmemdump
[i
]))
448 print("qemu mem %06x %s" % (addr
+i
*8, s
))
449 for k
, v
in sim
.mem
.mem
.items():
450 qmemdump
= qemu
.get_mem(k
*8, 8)
451 s
= hex(int(qmemdump
[0]))[2:]
452 print("qemu mem %06x %16s" % (k
*8, s
))
453 for k
, v
in sim
.mem
.mem
.items():
454 print("sim mem %06x %016x" % (k
*8, v
))
457 for k
, v
in sim
.mem
.mem
.items():
458 qmemdump
= qemu
.get_mem(k
*8, 1)
459 self
.assertEqual(int(qmemdump
[0]), v
)
461 def qemu_register_compare(self
, sim
, qemu
, regs
):
462 qpc
, qxer
, qcr
= qemu
.get_pc(), qemu
.get_xer(), qemu
.get_cr()
463 sim_cr
= sim
.cr
.get_range().value
464 sim_pc
= sim
.pc
.CIA
.value
465 sim_xer
= sim
.spr
['XER'].value
466 print("qemu pc", hex(qpc
))
467 print("qemu cr", hex(qcr
))
468 print("qemu xer", bin(qxer
))
469 print("sim nia", hex(sim
.pc
.NIA
.value
))
470 print("sim pc", hex(sim
.pc
.CIA
.value
))
471 print("sim cr", hex(sim_cr
))
472 print("sim xer", hex(sim_xer
))
473 self
.assertEqual(qpc
, sim_pc
)
475 qemu_val
= qemu
.get_register(reg
)
476 sim_val
= sim
.gpr(reg
).value
477 self
.assertEqual(qemu_val
, sim_val
,
478 "expect %x got %x" % (qemu_val
, sim_val
))
479 self
.assertEqual(qcr
, sim_cr
)
482 class DecoderTestCase(DecoderBase
, GeneralTestCases
):
486 if __name__
== "__main__":