1 from nmigen
import Module
, Signal
3 # NOTE: to use cxxsim, export NMIGEN_SIM_MODE=cxxsim from the shell
4 # Also, check out the cxxsim nmigen branch, and latest yosys from git
5 from nmutil
.sim_tmp_alternative
import Simulator
, Delay
, Settle
7 import power_instruction_analyzer
as pia
9 from nmigen
.cli
import rtlil
11 from openpower
.decoder
.isa
.caller
import ISACaller
, special_sprs
12 from openpower
.decoder
.power_decoder
import (create_pdecode
)
13 from openpower
.decoder
.power_decoder2
import (PowerDecode2
)
14 from openpower
.decoder
.power_enums
import (XER_bits
, Function
, MicrOp
, CryIn
)
15 from openpower
.decoder
.selectable_int
import SelectableInt
16 from openpower
.simulator
.program
import Program
17 from openpower
.decoder
.isa
.all
import ISA
18 from soc
.config
.endian
import bigendian
20 from soc
.fu
.test
.common
import (TestAccumulatorBase
, TestCase
, ALUHelpers
)
21 from soc
.fu
.test
.pia
import pia_res_to_output
22 from soc
.fu
.mul
.pipeline
import MulBasePipe
23 from soc
.fu
.mul
.pipe_data
import MulPipeSpec
27 def get_cu_inputs(dec2
, sim
):
28 """naming (res) must conform to MulFunctionUnit input regspec
32 yield from ALUHelpers
.get_sim_int_ra(res
, sim
, dec2
) # RA
33 yield from ALUHelpers
.get_sim_int_rb(res
, sim
, dec2
) # RB
34 yield from ALUHelpers
.get_sim_int_rc(res
, sim
, dec2
) # RC
35 yield from ALUHelpers
.get_sim_xer_so(res
, sim
, dec2
) # XER.so
37 print("alu get_cu_inputs", res
)
42 def set_alu_inputs(alu
, dec2
, sim
, has_third_input
):
43 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
44 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
45 # and place it into data_i.b
47 inp
= yield from get_cu_inputs(dec2
, sim
)
48 print("set alu inputs", inp
)
49 yield from ALUHelpers
.set_int_ra(alu
, dec2
, inp
)
50 yield from ALUHelpers
.set_int_rb(alu
, dec2
, inp
)
52 yield from ALUHelpers
.set_int_rc(alu
, dec2
, inp
)
54 yield from ALUHelpers
.set_xer_so(alu
, dec2
, inp
)
59 overflow
= pia
.OverflowFlags(so
=bool(so
),
62 rc
= inp
["rc"] if has_third_input
else None
63 return pia
.InstructionInput(ra
=inp
.get("ra"), rb
=inp
.get("rb"),
64 rc
=rc
, overflow
=overflow
)
67 class MulTestHelper(unittest
.TestCase
):
68 def execute(self
, pdecode2
, test
, instruction
, alu
, has_third_input
, sim
):
69 program
= test
.program
70 isa_sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
73 gen
= program
.generate_instructions()
74 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
77 index
= isa_sim
.pc
.CIA
.value
//4
78 while index
< len(instructions
):
79 ins
, code
= instructions
[index
]
81 print("instruction: 0x{:X}".format(ins
& 0xffffffff))
83 if 'XER' in isa_sim
.spr
:
84 so
= 1 if isa_sim
.spr
['XER'][XER_bits
['SO']] else 0
85 ov
= 1 if isa_sim
.spr
['XER'][XER_bits
['OV']] else 0
86 ov32
= 1 if isa_sim
.spr
['XER'][XER_bits
['OV32']] else 0
87 print("before: so/ov/32", so
, ov
, ov32
)
89 # ask the decoder to decode this binary data (endian'd)
90 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
91 yield instruction
.eq(ins
) # raw binary instr.
93 fn_unit
= yield pdecode2
.e
.do
.fn_unit
94 self
.assertEqual(fn_unit
, Function
.MUL
.value
)
95 pia_inputs
= yield from set_alu_inputs(alu
, pdecode2
, isa_sim
,
98 # set valid for one cycle, propagate through pipeline...
99 yield alu
.p
.valid_i
.eq(1)
101 yield alu
.p
.valid_i
.eq(0)
103 opname
= code
.split(' ')[0]
104 fnname
= opname
.replace(".", "_")
105 print(f
"{fnname}({pia_inputs})")
108 pia_res
= getattr(pia
, fnname
)(pia_inputs
)
109 except AttributeError:
110 EXPECTED_FAILURES
= ["mulli"]
111 if fnname
not in EXPECTED_FAILURES
:
114 print("not implemented, as expected.")
115 print(f
"-> {pia_res}")
117 yield from isa_sim
.call(opname
)
118 index
= isa_sim
.pc
.CIA
.value
//4
120 # ...wait for valid to pop out the end
121 vld
= yield alu
.n
.valid_o
125 vld
= yield alu
.n
.valid_o
128 # XXX sim._engine is an internal variable
129 # Waiting on https://github.com/nmigen/nmigen/issues/443
131 print(f
"check time: {sim._engine.now * 1e6}us")
132 except AttributeError:
134 msg
= (f
"{code!r} {program.assembly!r} "
135 f
"{list(map(hex, test.regs))!r}")
136 yield from self
.check_alu_outputs(alu
, pdecode2
, isa_sim
, msg
,
140 def run_all(self
, test_data
, file_name_prefix
, has_third_input
):
143 instruction
= Signal(32)
146 opkls
= MulPipeSpec
.opsubsetkls
148 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(None, opkls
, fn_name
)
149 pdecode
= pdecode2
.dec
151 pspec
= MulPipeSpec(id_wid
=2)
152 m
.submodules
.alu
= alu
= MulBasePipe(pspec
)
154 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.do
)
155 comb
+= alu
.n
.ready_i
.eq(1)
156 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
162 for test
in test_data
:
164 with self
.subTest(test
.name
):
165 yield from self
.execute(pdecode2
, test
, instruction
, alu
,
166 has_third_input
, sim
)
168 sim
.add_sync_process(process
)
169 with sim
.write_vcd(f
"{file_name_prefix}.vcd"):
172 def check_alu_outputs(self
, alu
, dec2
, sim
, code
, pia_res
):
174 rc
= yield dec2
.e
.do
.rc
.rc
175 cridx_ok
= yield dec2
.e
.write_cr
.ok
176 cridx
= yield dec2
.e
.write_cr
.data
178 print("check extra output", repr(code
), cridx_ok
, cridx
)
180 self
.assertEqual(cridx
, 0, code
)
182 oe
= yield dec2
.e
.do
.oe
.oe
183 oe_ok
= yield dec2
.e
.do
.oe
.ok
184 if not oe
or not oe_ok
:
185 # if OE not enabled, XER SO and OV must correspondingly be false
186 so_ok
= yield alu
.n
.data_o
.xer_so
.ok
187 ov_ok
= yield alu
.n
.data_o
.xer_ov
.ok
188 self
.assertEqual(so_ok
, False, code
)
189 self
.assertEqual(ov_ok
, False, code
)
194 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
195 yield from ALUHelpers
.get_xer_ov(res
, alu
, dec2
)
196 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
197 yield from ALUHelpers
.get_xer_so(res
, alu
, dec2
)
199 print("res output", res
)
201 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
202 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
203 yield from ALUHelpers
.get_sim_xer_ov(sim_o
, sim
, dec2
)
204 yield from ALUHelpers
.get_sim_xer_so(sim_o
, sim
, dec2
)
206 print("sim output", sim_o
)
208 print("power-instruction-analyzer result:")
210 if pia_res
is not None:
211 with self
.subTest(check
="pia", sim_o
=sim_o
, pia_res
=str(pia_res
)):
212 pia_o
= pia_res_to_output(pia_res
)
213 ALUHelpers
.check_int_o(self
, res
, pia_o
, code
)
214 ALUHelpers
.check_cr_a(self
, res
, pia_o
, code
)
215 ALUHelpers
.check_xer_ov(self
, res
, pia_o
, code
)
216 ALUHelpers
.check_xer_so(self
, res
, pia_o
, code
)
218 with self
.subTest(check
="sim", sim_o
=sim_o
, pia_res
=str(pia_res
)):
219 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
220 ALUHelpers
.check_xer_ov(self
, res
, sim_o
, code
)
221 ALUHelpers
.check_xer_so(self
, res
, sim_o
, code
)
222 ALUHelpers
.check_cr_a(self
, res
, sim_o
, "CR%d %s" % (cridx
, code
))