split out common code from test_alu_compunit.py
[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 from soc.fu.compunits.test.test_compunit import TestRunner
17 from soc.experiment.compalu_multi import find_ok # hack
18 import random
19
20 def set_cu_input(cu, idx, data):
21 rdop = cu.get_in_name(idx)
22 yield cu.src_i[idx].eq(data)
23 while True:
24 rd_rel_o = yield cu.rd.rel[idx]
25 print ("rd_rel %d wait HI" % idx, rd_rel_o, rdop, hex(data))
26 if rd_rel_o:
27 break
28 yield
29 yield cu.rd.go[idx].eq(1)
30 while True:
31 yield
32 rd_rel_o = yield cu.rd.rel[idx]
33 if rd_rel_o:
34 break
35 print ("rd_rel %d wait HI" % idx, rd_rel_o)
36 yield
37 yield cu.rd.go[idx].eq(0)
38
39
40 def get_cu_output(cu, idx, code):
41 wrmask = yield cu.wrmask
42 wrop = cu.get_out_name(idx)
43 wrok = cu.get_out(idx)
44 fname = find_ok(wrok.fields)
45 wrok = yield getattr(wrok, fname)
46 print ("wr_rel mask", repr(code), idx, wrop, bin(wrmask), fname, wrok)
47 assert wrmask & (1<<idx), \
48 "get_cu_output '%s': mask bit %d not set\n" \
49 "write-operand '%s' Data.ok likely not set (%s)" \
50 % (code, idx, wrop, hex(wrok))
51 while True:
52 wr_relall_o = yield cu.wr.rel
53 wr_rel_o = yield cu.wr.rel[idx]
54 print ("wr_rel %d wait" % idx, hex(wr_relall_o), wr_rel_o)
55 if wr_rel_o:
56 break
57 yield
58 yield cu.wr.go[idx].eq(1)
59 yield Settle()
60 result = yield cu.dest[idx]
61 yield
62 yield cu.wr.go[idx].eq(0)
63 print ("result", repr(code), idx, wrop, wrok, hex(result))
64 return result
65
66
67
68 class ALUTestRunner(TestRunner):
69 def __init__(self, test_data):
70 super().__init__(test_data, ALUFunctionUnit, self)
71
72 def get_cu_inputs(self, dec2, sim):
73 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
74 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
75 # and place it into data_i.b
76 res = {}
77
78 reg3_ok = yield dec2.e.read_reg3.ok
79 reg1_ok = yield dec2.e.read_reg1.ok
80 assert reg3_ok != reg1_ok
81 if reg3_ok:
82 data1 = yield dec2.e.read_reg3.data
83 res[0] = sim.gpr(data1).value
84 elif reg1_ok:
85 data1 = yield dec2.e.read_reg1.data
86 res[0] = sim.gpr(data1).value
87
88 # If there's an immediate, set the B operand to that
89 reg2_ok = yield dec2.e.read_reg2.ok
90 if reg2_ok:
91 data2 = yield dec2.e.read_reg2.data
92 res[1] = sim.gpr(data2).value
93
94 carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0
95 carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0
96 res[3] = carry | (carry32<<1)
97 so = 1 if sim.spr['XER'][XER_bits['SO']] else 0
98 res[2] = so
99
100 return res
101
102 def check_cu_outputs(self, res, dec2, sim, code):
103 out_reg_valid = yield dec2.e.write_reg.ok
104 if out_reg_valid:
105 write_reg_idx = yield dec2.e.write_reg.data
106 expected = sim.gpr(write_reg_idx).value
107 cu_out = res['o']
108 print(f"expected {expected:x}, actual: {cu_out:x}")
109 self.assertEqual(expected, cu_out, code)
110
111 rc = yield dec2.e.rc.data
112 op = yield dec2.e.insn_type
113 cridx_ok = yield dec2.e.write_cr.ok
114 cridx = yield dec2.e.write_cr.data
115
116 print ("check extra output", repr(code), cridx_ok, cridx)
117
118 if rc:
119 self.assertEqual(cridx_ok, 1, code)
120 self.assertEqual(cridx, 0, code)
121
122 if cridx_ok:
123 cr_expected = sim.crl[cridx].get_range().value
124 cr_actual = res['cr0']
125 print ("CR", cridx, cr_expected, cr_actual)
126 self.assertEqual(cr_expected, cr_actual, "CR%d %s" % (cridx, code))
127
128 cry_out = yield dec2.e.output_carry
129 if cry_out:
130 expected_carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0
131 xer_ca = res['xer_ca']
132 real_carry = xer_ca & 0b1 # XXX CO not CO32
133 self.assertEqual(expected_carry, real_carry, code)
134 expected_carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0
135 real_carry32 = bool(xer_ca & 0b10) # XXX CO32
136 self.assertEqual(expected_carry32, real_carry32, code)
137
138 # TODO
139 oe = yield dec2.e.oe.data
140 if oe:
141 xer_ov = res['xer_ov']
142 xer_so = res['xer_so']
143
144
145 if __name__ == "__main__":
146 unittest.main(exit=False)
147 suite = unittest.TestSuite()
148 suite.addTest(ALUTestRunner(test_data))
149
150 runner = unittest.TextTestRunner()
151 runner.run(suite)