order of XER so/ca wrong way round from regspec
[soc.git] / src / soc / fu / compunits / test / test_alu_compunit.py
1 from nmigen import Module, Signal
2 from nmigen.back.pysim import Simulator, Delay, Settle
3 from nmigen.test.utils import FHDLTestCase
4 from nmigen.cli import rtlil
5 import unittest
6 from soc.decoder.isa.caller import ISACaller, special_sprs
7 from soc.decoder.power_decoder import (create_pdecode)
8 from soc.decoder.power_decoder2 import (PowerDecode2)
9 from soc.decoder.power_enums import (XER_bits, Function, InternalOp)
10 from soc.decoder.selectable_int import SelectableInt
11 from soc.simulator.program import Program
12 from soc.decoder.isa.all import ISA
13
14 from soc.fu.alu.test.test_pipe_caller import TestCase, ALUTestCase, test_data
15 from soc.fu.compunits.compunits import ALUFunctionUnit
16 import random
17
18 def set_cu_input(cu, idx, data):
19 yield cu.src_i[idx].eq(data)
20 while True:
21 rd_rel_o = yield cu.rd.rel[idx]
22 print ("rd_rel %d wait HI" % idx, rd_rel_o)
23 if rd_rel_o:
24 break
25 yield
26 yield cu.rd.go[idx].eq(1)
27 while True:
28 yield
29 rd_rel_o = yield cu.rd.rel[idx]
30 if rd_rel_o:
31 break
32 print ("rd_rel %d wait HI" % idx, rd_rel_o)
33 yield
34 yield cu.rd.go[idx].eq(0)
35
36
37 def get_cu_output(cu, idx):
38 while True:
39 wr_relall_o = yield cu.wr.rel
40 wr_rel_o = yield cu.wr.rel[idx]
41 print ("wr_rel %d wait" % idx, hex(wr_relall_o), wr_rel_o)
42 if wr_rel_o:
43 break
44 yield
45 yield cu.wr.go[idx].eq(1)
46 yield
47 result = yield cu.dest[idx]
48 yield cu.wr.go[idx].eq(0)
49 return result
50
51
52 def set_cu_inputs(cu, dec2, sim):
53 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
54 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
55 # and place it into data_i.b
56
57 reg3_ok = yield dec2.e.read_reg3.ok
58 reg1_ok = yield dec2.e.read_reg1.ok
59 assert reg3_ok != reg1_ok
60 if reg3_ok:
61 data1 = yield dec2.e.read_reg3.data
62 data1 = sim.gpr(data1).value
63 elif reg1_ok:
64 data1 = yield dec2.e.read_reg1.data
65 data1 = sim.gpr(data1).value
66 else:
67 data1 = 0
68
69 if reg3_ok or reg1_ok:
70 yield from set_cu_input(cu, 0, data1)
71
72 # If there's an immediate, set the B operand to that
73 reg2_ok = yield dec2.e.read_reg2.ok
74 if reg2_ok:
75 data2 = yield dec2.e.read_reg2.data
76 data2 = sim.gpr(data2).value
77 else:
78 data2 = 0
79
80 if reg2_ok:
81 yield from set_cu_input(cu, 1, data2)
82
83
84 def set_operand(cu, dec2, sim):
85 yield from cu.oper_i.eq_from_execute1(dec2.e)
86 yield cu.issue_i.eq(1)
87 yield
88 yield cu.issue_i.eq(0)
89 yield
90
91
92 def set_extra_cu_inputs(cu, dec2, sim):
93 carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0
94 carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0
95 yield from set_cu_input(cu, 3, carry | (carry32<<1))
96 so = 1 if sim.spr['XER'][XER_bits['SO']] else 0
97 yield from set_cu_input(cu, 2, so)
98
99
100
101 class TestRunner(FHDLTestCase):
102 def __init__(self, test_data):
103 super().__init__("run_all")
104 self.test_data = test_data
105
106 def run_all(self):
107 m = Module()
108 comb = m.d.comb
109 instruction = Signal(32)
110
111 pdecode = create_pdecode()
112
113 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
114 m.submodules.cu = cu = ALUFunctionUnit()
115
116 comb += pdecode2.dec.raw_opcode_in.eq(instruction)
117 sim = Simulator(m)
118
119 sim.add_clock(1e-6)
120
121 def process():
122 yield cu.issue_i.eq(0)
123 yield
124
125 for test in self.test_data:
126 print(test.name)
127 program = test.program
128 self.subTest(test.name)
129 sim = ISA(pdecode2, test.regs, test.sprs, 0)
130 gen = program.generate_instructions()
131 instructions = list(zip(gen, program.assembly.splitlines()))
132
133 index = sim.pc.CIA.value//4
134 while index < len(instructions):
135 ins, code = instructions[index]
136
137 print("0x{:X}".format(ins & 0xffffffff))
138 print(code)
139
140 # ask the decoder to decode this binary data (endian'd)
141 yield pdecode2.dec.bigendian.eq(0) # little / big?
142 yield instruction.eq(ins) # raw binary instr.
143 yield Settle()
144 fn_unit = yield pdecode2.e.fn_unit
145 self.assertEqual(fn_unit, Function.ALU.value)
146 yield from set_operand(cu, pdecode2, sim)
147 rd_rel_o = yield cu.rd.rel
148 wr_rel_o = yield cu.wr.rel
149 print ("before inputs, rd_rel, wr_rel: ",
150 bin(rd_rel_o), bin(wr_rel_o))
151 yield from set_cu_inputs(cu, pdecode2, sim)
152 yield from set_extra_cu_inputs(cu, pdecode2, sim)
153 yield
154 rd_rel_o = yield cu.rd.rel
155 wr_rel_o = yield cu.wr.rel
156 print ("after inputs, rd_rel, wr_rel: ",
157 bin(rd_rel_o), bin(wr_rel_o))
158 opname = code.split(' ')[0]
159 yield from sim.call(opname)
160 index = sim.pc.CIA.value//4
161
162 out_reg_valid = yield pdecode2.e.write_reg.ok
163 if out_reg_valid:
164 write_reg_idx = yield pdecode2.e.write_reg.data
165 expected = sim.gpr(write_reg_idx).value
166 cu_out = yield from get_cu_output(cu, 0)
167 print(f"expected {expected:x}, actual: {cu_out:x}")
168 self.assertEqual(expected, cu_out, code)
169 yield from self.check_extra_cu_outputs(cu, pdecode2,
170 sim, code)
171
172 sim.add_sync_process(process)
173 with sim.write_vcd("simulator.vcd", "simulator.gtkw",
174 traces=[]):
175 sim.run()
176
177 def check_extra_cu_outputs(self, cu, dec2, sim, code):
178 rc = yield dec2.e.rc.data
179 if rc:
180 cr_expected = sim.crl[0].get_range().value
181 cr_actual = yield cu.n.data_o.cr0.data
182 self.assertEqual(cr_expected, cr_actual, code)
183
184 op = yield dec2.e.insn_type
185 if op == InternalOp.OP_CMP.value or \
186 op == InternalOp.OP_CMPEQB.value:
187 bf = yield dec2.dec.BF
188 cr_actual = yield cu.n.data_o.cr0.data
189 cr_expected = sim.crl[bf].get_range().value
190 self.assertEqual(cr_expected, cr_actual, code)
191
192 cry_out = yield dec2.e.output_carry
193 if cry_out:
194 expected_carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0
195 real_carry = yield cu.n.data_o.xer_ca.data[0] # XXX CO not CO32
196 self.assertEqual(expected_carry, real_carry, code)
197 expected_carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0
198 real_carry32 = yield cu.n.data_o.xer_ca.data[1] # XXX CO32
199 self.assertEqual(expected_carry32, real_carry32, code)
200
201
202
203 if __name__ == "__main__":
204 unittest.main(exit=False)
205 suite = unittest.TestSuite()
206 suite.addTest(TestRunner(test_data))
207
208 runner = unittest.TextTestRunner()
209 runner.run(suite)