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_extsb(self
):
292 insns
= ["extsb", "extsh", "extsw"]
294 choice
= random
.choice(insns
)
295 lst
= [f
"{choice} 3, 1"]
297 initial_regs
= [0] * 32
298 initial_regs
[1] = random
.randint(0, (1 << 64)-1)
299 self
.add_case(Program(lst
, bigendian
), initial_regs
)
301 def case_cmpeqb(self
):
302 lst
= ["cmpeqb cr1, 1, 2"]
304 initial_regs
= [0] * 32
306 initial_regs
[2] = 0x0001030507090b0f
307 self
.add_case(Program(lst
, bigendian
), initial_regs
, {})
309 def case_ilang(self
):
310 pspec
= ALUPipeSpec(id_wid
=2)
311 alu
= ALUBasePipe(pspec
)
312 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
313 with
open("alu_pipeline.il", "w") as f
:
317 class TestRunner(unittest
.TestCase
):
319 def execute(self
, alu
,instruction
, pdecode2
, test
):
320 program
= test
.program
321 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
324 gen
= program
.generate_instructions()
325 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
327 index
= sim
.pc
.CIA
.value
//4
328 while index
< len(instructions
):
329 ins
, code
= instructions
[index
]
331 print("instruction: 0x{:X}".format(ins
& 0xffffffff))
334 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
335 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
336 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
337 print("before: so/ov/32", so
, ov
, ov32
)
339 # ask the decoder to decode this binary data (endian'd)
341 yield pdecode2
.dec
.bigendian
.eq(bigendian
)
342 yield instruction
.eq(ins
) # raw binary instr.
344 fn_unit
= yield pdecode2
.e
.do
.fn_unit
345 self
.assertEqual(fn_unit
, Function
.ALU
.value
)
346 yield from set_alu_inputs(alu
, pdecode2
, sim
)
348 # set valid for one cycle, propagate through pipeline...
349 yield alu
.p
.valid_i
.eq(1)
351 yield alu
.p
.valid_i
.eq(0)
353 opname
= code
.split(' ')[0]
354 yield from sim
.call(opname
)
355 index
= sim
.pc
.CIA
.value
//4
357 vld
= yield alu
.n
.valid_o
360 vld
= yield alu
.n
.valid_o
363 yield from self
.check_alu_outputs(alu
, pdecode2
, sim
, code
)
367 test_data
= ALUTestCase().test_data
370 instruction
= Signal(32)
372 pdecode
= create_pdecode()
374 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
376 pspec
= ALUPipeSpec(id_wid
=2)
377 m
.submodules
.alu
= alu
= ALUBasePipe(pspec
)
379 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
380 comb
+= alu
.n
.ready_i
.eq(1)
381 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
387 for test
in test_data
:
389 program
= test
.program
390 with self
.subTest(test
.name
):
391 yield from self
.execute(alu
, instruction
, pdecode2
, test
)
393 sim
.add_sync_process(process
)
394 with sim
.write_vcd("alu_simulator.vcd"):
397 def check_alu_outputs(self
, alu
, dec2
, sim
, code
):
399 rc
= yield dec2
.e
.do
.rc
.data
400 cridx_ok
= yield dec2
.e
.write_cr
.ok
401 cridx
= yield dec2
.e
.write_cr
.data
403 print("check extra output", repr(code
), cridx_ok
, cridx
)
405 self
.assertEqual(cridx
, 0, code
)
407 oe
= yield dec2
.e
.do
.oe
.oe
408 oe_ok
= yield dec2
.e
.do
.oe
.ok
409 if not oe
or not oe_ok
:
410 # if OE not enabled, XER SO and OV must correspondingly be false
411 so_ok
= yield alu
.n
.data_o
.xer_so
.ok
412 ov_ok
= yield alu
.n
.data_o
.xer_ov
.ok
413 self
.assertEqual(so_ok
, False, code
)
414 self
.assertEqual(ov_ok
, False, code
)
419 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
420 yield from ALUHelpers
.get_xer_ov(res
, alu
, dec2
)
421 yield from ALUHelpers
.get_xer_ca(res
, alu
, dec2
)
422 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
423 yield from ALUHelpers
.get_xer_so(res
, alu
, dec2
)
425 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
426 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
427 yield from ALUHelpers
.get_sim_xer_ov(sim_o
, sim
, dec2
)
428 yield from ALUHelpers
.get_wr_sim_xer_ca(sim_o
, sim
, dec2
)
429 yield from ALUHelpers
.get_sim_xer_so(sim_o
, sim
, dec2
)
431 ALUHelpers
.check_cr_a(self
, res
, sim_o
, "CR%d %s" % (cridx
, code
))
432 ALUHelpers
.check_xer_ov(self
, res
, sim_o
, code
)
433 ALUHelpers
.check_xer_ca(self
, res
, sim_o
, code
)
434 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
435 ALUHelpers
.check_xer_so(self
, res
, sim_o
, code
)
438 if __name__
== "__main__":