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 soc
.decoder
.isa
.caller
import ISACaller
, special_sprs
12 from soc
.decoder
.power_decoder
import (create_pdecode
)
13 from soc
.decoder
.power_decoder2
import (PowerDecode2
)
14 from soc
.decoder
.power_enums
import (XER_bits
, Function
, MicrOp
, CryIn
)
15 from soc
.decoder
.selectable_int
import SelectableInt
16 from soc
.simulator
.program
import Program
17 from soc
.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
, has_third_input
):
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
35 yield from ALUHelpers
.get_sim_int_rc(res
, sim
, dec2
) # RC
36 yield from ALUHelpers
.get_sim_xer_so(res
, sim
, dec2
) # XER.so
38 print("alu get_cu_inputs", res
)
43 def set_alu_inputs(alu
, dec2
, sim
, has_third_input
):
44 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
45 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
46 # and place it into data_i.b
48 inp
= yield from get_cu_inputs(dec2
, sim
, has_third_input
)
49 print("set alu inputs", inp
)
50 yield from ALUHelpers
.set_int_ra(alu
, dec2
, inp
)
51 yield from ALUHelpers
.set_int_rb(alu
, dec2
, inp
)
53 yield from ALUHelpers
.set_int_rc(alu
, dec2
, inp
)
55 yield from ALUHelpers
.set_xer_so(alu
, dec2
, inp
)
60 overflow
= pia
.OverflowFlags(so
=bool(so
),
63 rc
= inp
["rb"] if has_third_input
else None
64 return pia
.InstructionInput(ra
=inp
["ra"], rb
=inp
["rb"],
65 rc
=rc
, overflow
=overflow
)
68 class MulTestHelper(unittest
.TestCase
):
69 def execute(self
, pdecode2
, test
, instruction
, alu
, has_third_input
, sim
):
70 program
= test
.program
71 isa_sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
74 gen
= program
.generate_instructions()
75 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
78 index
= isa_sim
.pc
.CIA
.value
//4
79 while index
< len(instructions
):
80 ins
, code
= instructions
[index
]
82 print("instruction: 0x{:X}".format(ins
& 0xffffffff))
84 if 'XER' in isa_sim
.spr
:
85 so
= 1 if isa_sim
.spr
['XER'][XER_bits
['SO']] else 0
86 ov
= 1 if isa_sim
.spr
['XER'][XER_bits
['OV']] else 0
87 ov32
= 1 if isa_sim
.spr
['XER'][XER_bits
['OV32']] else 0
88 print("before: so/ov/32", so
, ov
, ov32
)
90 # ask the decoder to decode this binary data (endian'd)
91 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
92 yield instruction
.eq(ins
) # raw binary instr.
94 fn_unit
= yield pdecode2
.e
.do
.fn_unit
95 self
.assertEqual(fn_unit
, Function
.MUL
.value
)
96 pia_inputs
= yield from set_alu_inputs(alu
, pdecode2
, isa_sim
,
99 # set valid for one cycle, propagate through pipeline...
100 yield alu
.p
.valid_i
.eq(1)
102 yield alu
.p
.valid_i
.eq(0)
104 opname
= code
.split(' ')[0]
105 fnname
= opname
.replace(".", "_")
106 print(f
"{fnname}({pia_inputs})")
107 pia_res
= getattr(pia
, opname
.replace(".", "_"))(pia_inputs
)
108 print(f
"-> {pia_res}")
110 yield from isa_sim
.call(opname
)
111 index
= isa_sim
.pc
.CIA
.value
//4
113 # ...wait for valid to pop out the end
114 vld
= yield alu
.n
.valid_o
118 vld
= yield alu
.n
.valid_o
121 # XXX sim._engine is an internal variable
122 # Waiting on https://github.com/nmigen/nmigen/issues/443
124 print(f
"check time: {sim._engine.now * 1e6}us")
125 except AttributeError:
127 msg
= (f
"{code!r} {program.assembly!r} "
128 f
"{list(map(hex, test.regs))!r}")
129 yield from self
.check_alu_outputs(alu
, pdecode2
, isa_sim
, msg
,
133 def run_all(self
, test_data
, file_name_prefix
, has_third_input
):
136 instruction
= Signal(32)
139 opkls
= MulPipeSpec
.opsubsetkls
141 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(None, opkls
, fn_name
)
142 pdecode
= pdecode2
.dec
144 pspec
= MulPipeSpec(id_wid
=2)
145 m
.submodules
.alu
= alu
= MulBasePipe(pspec
)
147 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.do
)
148 comb
+= alu
.n
.ready_i
.eq(1)
149 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
155 for test
in test_data
:
157 with self
.subTest(test
.name
):
158 yield from self
.execute(pdecode2
, test
, instruction
, alu
,
159 has_third_input
, sim
)
161 sim
.add_sync_process(process
)
162 with sim
.write_vcd(f
"{file_name_prefix}.vcd"):
165 def check_alu_outputs(self
, alu
, dec2
, sim
, code
, pia_res
):
167 rc
= yield dec2
.e
.do
.rc
.rc
168 cridx_ok
= yield dec2
.e
.write_cr
.ok
169 cridx
= yield dec2
.e
.write_cr
.data
171 print("check extra output", repr(code
), cridx_ok
, cridx
)
173 self
.assertEqual(cridx
, 0, code
)
175 oe
= yield dec2
.e
.do
.oe
.oe
176 oe_ok
= yield dec2
.e
.do
.oe
.ok
177 if not oe
or not oe_ok
:
178 # if OE not enabled, XER SO and OV must correspondingly be false
179 so_ok
= yield alu
.n
.data_o
.xer_so
.ok
180 ov_ok
= yield alu
.n
.data_o
.xer_ov
.ok
181 self
.assertEqual(so_ok
, False, code
)
182 self
.assertEqual(ov_ok
, False, code
)
187 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
188 yield from ALUHelpers
.get_xer_ov(res
, alu
, dec2
)
189 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
190 yield from ALUHelpers
.get_xer_so(res
, alu
, dec2
)
192 print("res output", res
)
194 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
195 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
196 yield from ALUHelpers
.get_sim_xer_ov(sim_o
, sim
, dec2
)
197 yield from ALUHelpers
.get_sim_xer_so(sim_o
, sim
, dec2
)
199 print("sim output", sim_o
)
201 print("power-instruction-analyzer result:")
203 if pia_res
is not None:
204 with self
.subTest(check
="pia", sim_o
=sim_o
, pia_res
=str(pia_res
)):
205 pia_o
= pia_res_to_output(pia_res
)
206 ALUHelpers
.check_int_o(self
, res
, pia_o
, code
)
207 ALUHelpers
.check_cr_a(self
, res
, pia_o
, code
)
208 ALUHelpers
.check_xer_ov(self
, res
, pia_o
, code
)
209 ALUHelpers
.check_xer_so(self
, res
, pia_o
, code
)
211 with self
.subTest(check
="sim", sim_o
=sim_o
, pia_res
=str(pia_res
)):
212 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
213 ALUHelpers
.check_xer_ov(self
, res
, sim_o
, code
)
214 ALUHelpers
.check_xer_so(self
, res
, sim_o
, code
)
215 ALUHelpers
.check_cr_a(self
, res
, sim_o
, "CR%d %s" % (cridx
, code
))