Check write register number too
[soc.git] / src / soc / alu / test / test_pipe_caller.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
7 from soc.decoder.power_decoder import (create_pdecode)
8 from soc.decoder.power_decoder2 import (PowerDecode2)
9 from soc.decoder.selectable_int import SelectableInt
10 from soc.simulator.program import Program
11 from soc.decoder.isa.all import ISA
12
13
14 from soc.alu.pipeline import ALUBasePipe
15 from soc.alu.alu_input_record import CompALUOpSubset
16 from soc.alu.pipe_data import ALUPipeSpec
17 import random
18
19 def get_rec_width(rec):
20 recwidth = 0
21 # Setup random inputs for dut.op
22 for p in rec.ports():
23 width = p.width
24 recwidth += width
25 return recwidth
26
27 def set_alu_inputs(alu, dec2, sim):
28 inputs = []
29 reg1_ok = yield dec2.e.read_reg1.ok
30 if reg1_ok:
31 reg1_sel = yield dec2.e.read_reg1.data
32 inputs.append(sim.gpr(reg1_sel).value)
33 reg3_ok = yield dec2.e.read_reg3.ok
34 if reg3_ok:
35 reg3_sel = yield dec2.e.read_reg3.data
36 inputs.append(sim.gpr(reg3_sel).value)
37 reg2_ok = yield dec2.e.read_reg2.ok
38 if reg2_ok:
39 reg2_sel = yield dec2.e.read_reg2.data
40 inputs.append(sim.gpr(reg2_sel).value)
41
42 print(inputs)
43
44 if len(inputs) == 0:
45 yield alu.p.data_i.a.eq(0)
46 yield alu.p.data_i.b.eq(0)
47 if len(inputs) == 1:
48 yield alu.p.data_i.a.eq(inputs[0])
49 yield alu.p.data_i.b.eq(0)
50 if len(inputs) == 2:
51 yield alu.p.data_i.a.eq(inputs[0])
52 yield alu.p.data_i.b.eq(inputs[1])
53
54
55
56 class ALUTestCase(FHDLTestCase):
57 def run_tst(self, program, initial_regs):
58 m = Module()
59 comb = m.d.comb
60 instruction = Signal(32)
61
62 pdecode = create_pdecode()
63
64 m.submodules.pdecode2 = pdecode2 = PowerDecode2(pdecode)
65
66 rec = CompALUOpSubset()
67
68 pspec = ALUPipeSpec(id_wid=2, op_wid=get_rec_width(rec))
69 m.submodules.alu = alu = ALUBasePipe(pspec)
70
71 comb += alu.p.data_i.ctx.op.eq_from_execute1(pdecode2.e)
72 comb += alu.p.valid_i.eq(1)
73 comb += alu.n.ready_i.eq(1)
74 simulator = ISA(pdecode2, initial_regs)
75 comb += pdecode2.dec.raw_opcode_in.eq(instruction)
76 sim = Simulator(m)
77 gen = program.generate_instructions()
78
79 sim.add_clock(1e-6)
80 def process():
81 instructions = list(zip(gen, program.assembly.splitlines()))
82
83 index = simulator.pc.CIA.value//4
84 while index < len(instructions):
85 ins, code = instructions[index]
86
87 print("0x{:X}".format(ins & 0xffffffff))
88 print(code)
89
90 # ask the decoder to decode this binary data (endian'd)
91 yield pdecode2.dec.bigendian.eq(0) # little / big?
92 yield instruction.eq(ins) # raw binary instr.
93 yield Settle()
94 yield from set_alu_inputs(alu, pdecode2, simulator)
95 yield
96 opname = code.split(' ')[0]
97 yield from simulator.call(opname)
98 index = simulator.pc.CIA.value//4
99
100 vld = yield alu.n.valid_o
101 while not vld:
102 yield
103 vld = yield alu.n.valid_o
104 yield
105 alu_out = yield alu.n.data_o.o
106 out_reg_valid = yield pdecode2.e.write_reg.ok
107 if out_reg_valid:
108 write_reg_idx = yield pdecode2.e.write_reg.data
109 expected = simulator.gpr(write_reg_idx).value
110 print(f"expected {expected:x}, actual: {alu_out:x}")
111 self.assertEqual(expected, alu_out)
112
113 sim.add_sync_process(process)
114 with sim.write_vcd("simulator.vcd", "simulator.gtkw",
115 traces=[]):
116 sim.run()
117 return simulator
118
119 def run_tst_program(self, prog, initial_regs=[0] * 32):
120 simulator = self.run_tst(prog, initial_regs)
121 simulator.gpr.dump()
122 return simulator
123
124 def test_rand(self):
125 insns = ["add", "add.", "and", "or", "xor", "subf"]
126 for i in range(40):
127 choice = random.choice(insns)
128 lst = [f"{choice} 3, 1, 2"]
129 initial_regs = [0] * 32
130 initial_regs[1] = random.randint(0, (1<<64)-1)
131 initial_regs[2] = random.randint(0, (1<<64)-1)
132 with Program(lst) as program:
133 sim = self.run_tst_program(program, initial_regs)
134
135 def test_rand_imm(self):
136 insns = ["addi", "addis", "subfic"]
137 for i in range(10):
138 choice = random.choice(insns)
139 imm = random.randint(-(1<<15), (1<<15)-1)
140 lst = [f"{choice} 3, 1, {imm}"]
141 print(lst)
142 initial_regs = [0] * 32
143 initial_regs[1] = random.randint(0, (1<<64)-1)
144 with Program(lst) as program:
145 sim = self.run_tst_program(program, initial_regs)
146
147 def test_rand_imm_logical(self):
148 insns = ["andi.", "andis.", "ori", "oris", "xori", "xoris"]
149 for i in range(10):
150 choice = random.choice(insns)
151 imm = random.randint(0, (1<<16)-1)
152 lst = [f"{choice} 3, 1, {imm}"]
153 print(lst)
154 initial_regs = [0] * 32
155 initial_regs[1] = random.randint(0, (1<<64)-1)
156 with Program(lst) as program:
157 sim = self.run_tst_program(program, initial_regs)
158
159 def test_shift(self):
160 insns = ["slw", "sld", "srw", "srd", "sraw", "srad"]
161 for i in range(20):
162 choice = random.choice(insns)
163 lst = [f"{choice} 3, 1, 2"]
164 initial_regs = [0] * 32
165 initial_regs[1] = random.randint(0, (1<<64)-1)
166 initial_regs[2] = random.randint(0, 63)
167 print(initial_regs[1], initial_regs[2])
168 with Program(lst) as program:
169 sim = self.run_tst_program(program, initial_regs)
170
171
172 def test_shift_arith(self):
173 lst = ["sraw 3, 1, 2"]
174 initial_regs = [0] * 32
175 initial_regs[1] = random.randint(0, (1<<64)-1)
176 initial_regs[2] = random.randint(0, 63)
177 print(initial_regs[1], initial_regs[2])
178 with Program(lst) as program:
179 sim = self.run_tst_program(program, initial_regs)
180
181 @unittest.skip("broken")
182 def test_rlwinm(self):
183 for i in range(10):
184 mb = random.randint(0,31)
185 me = random.randint(0,31)
186 sh = random.randint(0,31)
187 lst = [f"rlwinm 3, 1, {mb}, {me}, {sh}"]
188 initial_regs = [0] * 32
189 initial_regs[1] = random.randint(0, (1<<64)-1)
190 with Program(lst) as program:
191 sim = self.run_tst_program(program, initial_regs)
192
193 @unittest.skip("broken")
194 def test_rlwimi(self):
195 lst = ["rlwinm 3, 1, 5, 20, 6",
196 "rlwimi 3, 1, 5, 20, 6"]
197 initial_regs = [0] * 32
198 initial_regs[1] = random.randint(0, (1<<64)-1)
199 initial_regs[3] = random.randint(0, (1<<64)-1)
200 with Program(lst) as program:
201 sim = self.run_tst_program(program, initial_regs)
202
203 @unittest.skip("broken")
204 def test_rlwnm(self):
205 lst = ["rlwnm 3, 1, 2, 20, 6"]
206 initial_regs = [0] * 32
207 initial_regs[1] = random.randint(0, (1<<64)-1)
208 initial_regs[2] = random.randint(0, 63)
209 with Program(lst) as program:
210 sim = self.run_tst_program(program, initial_regs)
211
212 def test_add(self):
213 lst = ["add 3, 1, 2"]
214 initial_regs = [0] * 32
215 initial_regs[1] = random.randint(0, (1<<64)-1)
216 initial_regs[2] = random.randint(0, 63)
217 with Program(lst) as program:
218 sim = self.run_tst_program(program, initial_regs)
219
220 def test_ilang(self):
221 rec = CompALUOpSubset()
222
223 pspec = ALUPipeSpec(id_wid=2, op_wid=get_rec_width(rec))
224 alu = ALUBasePipe(pspec)
225 vl = rtlil.convert(alu, ports=[])
226 with open("pipeline.il", "w") as f:
227 f.write(vl)
228
229 if __name__ == "__main__":
230 unittest.main()