2 from soc
.fu
.alu
.pipe_data
import ALUPipeSpec
3 from soc
.fu
.alu
.pipeline
import ALUBasePipe
4 from soc
.fu
.test
.common
import (TestCase
, TestAccumulatorBase
, ALUHelpers
)
5 from soc
.config
.endian
import bigendian
6 from soc
.decoder
.isa
.all
import ISA
7 from soc
.simulator
.program
import Program
8 from soc
.decoder
.selectable_int
import SelectableInt
9 from soc
.decoder
.power_enums
import (XER_bits
, Function
, MicrOp
, CryIn
)
10 from soc
.decoder
.power_decoder2
import (PowerDecode2
)
11 from soc
.decoder
.power_decoder
import (create_pdecode
)
12 from soc
.decoder
.isa
.caller
import ISACaller
, special_sprs
14 from nmigen
.cli
import rtlil
15 from nmutil
.formaltest
import FHDLTestCase
16 from nmigen
import Module
, Signal
17 from nmigen
.back
.pysim
import Delay
, Settle
18 # NOTE: to use this (set to True), at present it is necessary to check
19 # out the cxxsim nmigen branch
23 from nmigen
.sim
.cxxsim
import Simulator
25 print("nope, sorry, have to use nmigen cxxsim branch for now")
27 from nmigen
.back
.pysim
import Simulator
29 from nmigen
.back
.pysim
import Simulator
32 def get_cu_inputs(dec2
, sim
):
33 """naming (res) must conform to ALUFunctionUnit input regspec
37 yield from ALUHelpers
.get_sim_int_ra(res
, sim
, dec2
) # RA
38 yield from ALUHelpers
.get_sim_int_rb(res
, sim
, dec2
) # RB
39 yield from ALUHelpers
.get_rd_sim_xer_ca(res
, sim
, dec2
) # XER.ca
40 yield from ALUHelpers
.get_sim_xer_so(res
, sim
, dec2
) # XER.so
42 print("alu get_cu_inputs", res
)
47 def set_alu_inputs(alu
, dec2
, sim
):
48 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
49 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
50 # and place it into data_i.b
52 inp
= yield from get_cu_inputs(dec2
, sim
)
53 yield from ALUHelpers
.set_int_ra(alu
, dec2
, inp
)
54 yield from ALUHelpers
.set_int_rb(alu
, dec2
, inp
)
56 yield from ALUHelpers
.set_xer_ca(alu
, dec2
, inp
)
57 yield from ALUHelpers
.set_xer_so(alu
, dec2
, inp
)
60 class ALUTestCase(TestAccumulatorBase
):
62 def case_1_regression(self
):
64 initial_regs
= [0] * 32
65 initial_regs
[1] = 0xb6a1fc6c8576af91
66 self
.add_case(Program(lst
, bigendian
), initial_regs
)
67 lst
= [f
"subf 3, 1, 2"]
68 initial_regs
= [0] * 32
69 initial_regs
[1] = 0x3d7f3f7ca24bac7b
70 initial_regs
[2] = 0xf6b2ac5e13ee15c2
71 self
.add_case(Program(lst
, bigendian
), initial_regs
)
72 lst
= [f
"subf 3, 1, 2"]
73 initial_regs
= [0] * 32
74 initial_regs
[1] = 0x833652d96c7c0058
75 initial_regs
[2] = 0x1c27ecff8a086c1a
76 self
.add_case(Program(lst
, bigendian
), initial_regs
)
78 initial_regs
= [0] * 32
79 initial_regs
[1] = 0x7f9497aaff900ea0
80 self
.add_case(Program(lst
, bigendian
), initial_regs
)
81 lst
= [f
"add. 3, 1, 2"]
82 initial_regs
= [0] * 32
83 initial_regs
[1] = 0xc523e996a8ff6215
84 initial_regs
[2] = 0xe1e5b9cc9864c4a8
85 self
.add_case(Program(lst
, bigendian
), initial_regs
)
86 lst
= [f
"add 3, 1, 2"]
87 initial_regs
= [0] * 32
88 initial_regs
[1] = 0x2e08ae202742baf8
89 initial_regs
[2] = 0x86c43ece9efe5baa
90 self
.add_case(Program(lst
, bigendian
), initial_regs
)
93 insns
= ["add", "add.", "subf"]
95 choice
= random
.choice(insns
)
96 lst
= [f
"{choice} 3, 1, 2"]
97 initial_regs
= [0] * 32
98 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
99 initial_regs
[2] = random
.randint(0, (1 << 64)-1)
100 self
.add_case(Program(lst
, bigendian
), initial_regs
)
102 def case_addme_ca_0(self
):
103 insns
= ["addme", "addme.", "addmeo", "addmeo."]
105 lst
= [f
"{choice} 6, 16"]
106 for value
in [0x7ffffffff,
108 initial_regs
= [0] * 32
109 initial_regs
[16] = value
111 xer
= SelectableInt(0, 64)
112 xer
[XER_bits
['CA']] = 0
113 initial_sprs
[special_sprs
['XER']] = xer
114 self
.add_case(Program(lst
, bigendian
),
115 initial_regs
, initial_sprs
)
117 def case_addme_ca_1(self
):
118 insns
= ["addme", "addme.", "addmeo", "addmeo."]
120 lst
= [f
"{choice} 6, 16"]
121 for value
in [0x7ffffffff, # fails, bug #476
123 initial_regs
= [0] * 32
124 initial_regs
[16] = value
126 xer
= SelectableInt(0, 64)
127 xer
[XER_bits
['CA']] = 1
128 initial_sprs
[special_sprs
['XER']] = xer
129 self
.add_case(Program(lst
, bigendian
),
130 initial_regs
, initial_sprs
)
132 def case_addme_ca_so_3(self
):
133 """bug where SO does not get passed through to CR0
135 lst
= ["addme. 6, 16"]
136 initial_regs
= [0] * 32
137 initial_regs
[16] = 0x7ffffffff
139 xer
= SelectableInt(0, 64)
140 xer
[XER_bits
['CA']] = 1
141 xer
[XER_bits
['SO']] = 1
142 initial_sprs
[special_sprs
['XER']] = xer
143 self
.add_case(Program(lst
, bigendian
),
144 initial_regs
, initial_sprs
)
146 def case_addze(self
):
147 insns
= ["addze", "addze.", "addzeo", "addzeo."]
149 lst
= [f
"{choice} 6, 16"]
150 initial_regs
= [0] * 32
151 initial_regs
[16] = 0x00ff00ff00ff0080
152 self
.add_case(Program(lst
, bigendian
), initial_regs
)
154 self
.add_case(Program(lst
, bigendian
), initial_regs
)
156 def case_addis_nonzero_r0_regression(self
):
157 lst
= [f
"addis 3, 0, 1"]
159 initial_regs
= [0] * 32
161 self
.add_case(Program(lst
, bigendian
), initial_regs
)
163 def case_addis_nonzero_r0(self
):
165 imm
= random
.randint(-(1 << 15), (1 << 15)-1)
166 lst
= [f
"addis 3, 0, {imm}"]
168 initial_regs
= [0] * 32
169 initial_regs
[0] = random
.randint(0, (1 << 64)-1)
170 self
.add_case(Program(lst
, bigendian
), initial_regs
)
172 def case_rand_imm(self
):
173 insns
= ["addi", "addis", "subfic"]
175 choice
= random
.choice(insns
)
176 imm
= random
.randint(-(1 << 15), (1 << 15)-1)
177 lst
= [f
"{choice} 3, 1, {imm}"]
179 initial_regs
= [0] * 32
180 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
181 self
.add_case(Program(lst
, bigendian
), initial_regs
)
183 def case_0_adde(self
):
184 lst
= ["adde. 5, 6, 7"]
186 initial_regs
= [0] * 32
187 initial_regs
[6] = random
.randint(0, (1 << 64)-1)
188 initial_regs
[7] = random
.randint(0, (1 << 64)-1)
190 xer
= SelectableInt(0, 64)
191 xer
[XER_bits
['CA']] = 1
192 initial_sprs
[special_sprs
['XER']] = xer
193 self
.add_case(Program(lst
, bigendian
),
194 initial_regs
, initial_sprs
)
197 lst
= ["subf. 1, 6, 7",
199 initial_regs
= [0] * 32
200 initial_regs
[6] = 0x10
201 initial_regs
[7] = 0x05
202 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
205 lst
= ["cmp cr2, 0, 2, 3"]
206 initial_regs
= [0] * 32
207 initial_regs
[2] = 0xffffffffaaaaaaaa
208 initial_regs
[3] = 0x00000000aaaaaaaa
209 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
211 lst
= ["cmp cr2, 0, 4, 5"]
212 initial_regs
= [0] * 32
213 initial_regs
[4] = 0x00000000aaaaaaaa
214 initial_regs
[5] = 0xffffffffaaaaaaaa
215 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
218 lst
= ["cmp cr2, 1, 2, 3"]
219 initial_regs
= [0] * 32
220 initial_regs
[2] = 0xffffffffaaaaaaaa
221 initial_regs
[3] = 0x00000000aaaaaaaa
222 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
224 lst
= ["cmp cr2, 1, 4, 5"]
225 initial_regs
= [0] * 32
226 initial_regs
[4] = 0x00000000aaaaaaaa
227 initial_regs
[5] = 0xffffffffaaaaaaaa
228 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
230 def case_cmpl_microwatt_0(self
):
232 115b8: 40 50 d1 7c .long 0x7cd15040 # cmpl 6, 0, 17, 10
233 register_file.vhdl: Reading GPR 11 000000000001C026
234 register_file.vhdl: Reading GPR 0A FEDF3FFF0001C025
235 cr_file.vhdl: Reading CR 35055050
236 cr_file.vhdl: Writing 35055058 to CR mask 01 35055058
239 lst
= ["cmpl 6, 0, 17, 10"]
240 initial_regs
= [0] * 32
241 initial_regs
[0x11] = 0x1c026
242 initial_regs
[0xa] = 0xFEDF3FFF0001C025
246 self
.add_case(Program(lst
, bigendian
), initial_regs
,
247 initial_sprs
= {'XER': XER
},
250 def case_cmpl_microwatt_0_disasm(self
):
251 """microwatt 1.bin: disassembled version
252 115b8: 40 50 d1 7c .long 0x7cd15040 # cmpl 6, 0, 17, 10
253 register_file.vhdl: Reading GPR 11 000000000001C026
254 register_file.vhdl: Reading GPR 0A FEDF3FFF0001C025
255 cr_file.vhdl: Reading CR 35055050
256 cr_file.vhdl: Writing 35055058 to CR mask 01 35055058
259 dis
= ["cmpl 6, 0, 17, 10"]
260 lst
= bytes([0x40, 0x50, 0xd1, 0x7c]) # 0x7cd15040
261 initial_regs
= [0] * 32
262 initial_regs
[0x11] = 0x1c026
263 initial_regs
[0xa] = 0xFEDF3FFF0001C025
267 p
= Program(lst
, bigendian
)
268 p
.assembly
= '\n'.join(dis
)+'\n'
269 self
.add_case(p
, initial_regs
,
270 initial_sprs
= {'XER': XER
},
273 def case_cmplw_microwatt_1(self
):
275 10d94: 40 20 96 7c cmplw cr1,r22,r4
276 gpr: 00000000ffff6dc1 <- r4
277 gpr: 0000000000000000 <- r22
280 lst
= ["cmpl 1, 0, 22, 4"]
281 initial_regs
= [0] * 32
282 initial_regs
[4] = 0xffff6dc1
287 self
.add_case(Program(lst
, bigendian
), initial_regs
,
288 initial_sprs
= {'XER': XER
},
291 def case_cmpli_microwatt(self
):
292 """microwatt 1.bin: cmpli
293 123ac: 9c 79 8d 2a cmpli cr5,0,r13,31132
294 gpr: 00000000301fc7a7 <- r13
295 cr : 0000000090215393
296 xer: so 1 ca 0 32 0 ov 0 32 0
300 lst
= ["cmpli 5, 0, 13, 31132"]
301 initial_regs
= [0] * 32
302 initial_regs
[13] = 0x301fc7a7
306 self
.add_case(Program(lst
, bigendian
), initial_regs
,
307 initial_sprs
= {'XER': XER
},
310 def case_extsb(self
):
311 insns
= ["extsb", "extsh", "extsw"]
313 choice
= random
.choice(insns
)
314 lst
= [f
"{choice} 3, 1"]
316 initial_regs
= [0] * 32
317 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
318 self
.add_case(Program(lst
, bigendian
), initial_regs
)
320 def case_cmpeqb(self
):
321 lst
= ["cmpeqb cr1, 1, 2"]
323 initial_regs
= [0] * 32
325 initial_regs
[2] = 0x0001030507090b0f
326 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
328 def case_ilang(self
):
329 pspec
= ALUPipeSpec(id_wid
=2)
330 alu
= ALUBasePipe(pspec
)
331 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
332 with
open("alu_pipeline.il", "w") as f
:
336 class TestRunner(unittest
.TestCase
):
338 def execute(self
, alu
,instruction
, pdecode2
, test
):
339 program
= test
.program
340 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
343 gen
= program
.generate_instructions()
344 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
346 index
= sim
.pc
.CIA
.value
//4
347 while index
< len(instructions
):
348 ins
, code
= instructions
[index
]
350 print("instruction: 0x{:X}".format(ins
& 0xffffffff))
353 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
354 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
355 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
356 print("before: so/ov/32", so
, ov
, ov32
)
358 # ask the decoder to decode this binary data (endian'd)
360 yield pdecode2
.dec
.bigendian
.eq(bigendian
)
361 yield instruction
.eq(ins
) # raw binary instr.
363 fn_unit
= yield pdecode2
.e
.do
.fn_unit
364 self
.assertEqual(fn_unit
, Function
.ALU
.value
)
365 yield from set_alu_inputs(alu
, pdecode2
, sim
)
367 # set valid for one cycle, propagate through pipeline...
368 yield alu
.p
.valid_i
.eq(1)
370 yield alu
.p
.valid_i
.eq(0)
372 opname
= code
.split(' ')[0]
373 yield from sim
.call(opname
)
374 index
= sim
.pc
.CIA
.value
//4
376 vld
= yield alu
.n
.valid_o
379 vld
= yield alu
.n
.valid_o
382 yield from self
.check_alu_outputs(alu
, pdecode2
, sim
, code
)
386 test_data
= ALUTestCase().test_data
389 instruction
= Signal(32)
391 pdecode
= create_pdecode()
393 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
395 pspec
= ALUPipeSpec(id_wid
=2)
396 m
.submodules
.alu
= alu
= ALUBasePipe(pspec
)
398 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
399 comb
+= alu
.n
.ready_i
.eq(1)
400 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
406 for test
in test_data
:
408 program
= test
.program
409 with self
.subTest(test
.name
):
410 yield from self
.execute(alu
, instruction
, pdecode2
, test
)
412 sim
.add_sync_process(process
)
413 with sim
.write_vcd("alu_simulator.vcd"):
416 def check_alu_outputs(self
, alu
, dec2
, sim
, code
):
418 rc
= yield dec2
.e
.do
.rc
.data
419 cridx_ok
= yield dec2
.e
.write_cr
.ok
420 cridx
= yield dec2
.e
.write_cr
.data
422 print("check extra output", repr(code
), cridx_ok
, cridx
)
424 self
.assertEqual(cridx
, 0, code
)
426 oe
= yield dec2
.e
.do
.oe
.oe
427 oe_ok
= yield dec2
.e
.do
.oe
.ok
428 if not oe
or not oe_ok
:
429 # if OE not enabled, XER SO and OV must correspondingly be false
430 so_ok
= yield alu
.n
.data_o
.xer_so
.ok
431 ov_ok
= yield alu
.n
.data_o
.xer_ov
.ok
432 self
.assertEqual(so_ok
, False, code
)
433 self
.assertEqual(ov_ok
, False, code
)
438 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
439 yield from ALUHelpers
.get_xer_ov(res
, alu
, dec2
)
440 yield from ALUHelpers
.get_xer_ca(res
, alu
, dec2
)
441 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
442 yield from ALUHelpers
.get_xer_so(res
, alu
, dec2
)
444 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
445 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
446 yield from ALUHelpers
.get_sim_xer_ov(sim_o
, sim
, dec2
)
447 yield from ALUHelpers
.get_wr_sim_xer_ca(sim_o
, sim
, dec2
)
448 yield from ALUHelpers
.get_sim_xer_so(sim_o
, sim
, dec2
)
450 ALUHelpers
.check_cr_a(self
, res
, sim_o
, "CR%d %s" % (cridx
, code
))
451 ALUHelpers
.check_xer_ov(self
, res
, sim_o
, code
)
452 ALUHelpers
.check_xer_ca(self
, res
, sim_o
, code
)
453 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
454 ALUHelpers
.check_xer_so(self
, res
, sim_o
, code
)
457 if __name__
== "__main__":