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
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
14 from soc
.alu
.pipeline
import ALUBasePipe
15 from soc
.alu
.alu_input_record
import CompALUOpSubset
16 from soc
.alu
.pipe_data
import ALUPipeSpec
19 def get_rec_width(rec
):
21 # Setup random inputs for dut.op
27 def set_alu_inputs(alu
, dec2
, sim
):
29 reg1_ok
= yield dec2
.e
.read_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
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
39 reg2_sel
= yield dec2
.e
.read_reg2
.data
40 inputs
.append(sim
.gpr(reg2_sel
).value
)
45 yield alu
.p
.data_i
.a
.eq(0)
46 yield alu
.p
.data_i
.b
.eq(0)
48 yield alu
.p
.data_i
.a
.eq(inputs
[0])
49 yield alu
.p
.data_i
.b
.eq(0)
51 yield alu
.p
.data_i
.a
.eq(inputs
[0])
52 yield alu
.p
.data_i
.b
.eq(inputs
[1])
56 class ALUTestCase(FHDLTestCase
):
57 def run_tst(self
, program
, initial_regs
):
60 instruction
= Signal(32)
62 pdecode
= create_pdecode()
64 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
66 rec
= CompALUOpSubset()
68 pspec
= ALUPipeSpec(id_wid
=2, op_wid
=get_rec_width(rec
))
69 m
.submodules
.alu
= alu
= ALUBasePipe(pspec
)
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
)
77 gen
= program
.generate_instructions()
81 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
83 index
= simulator
.pc
.CIA
.value
//4
84 while index
< len(instructions
):
85 ins
, code
= instructions
[index
]
87 print("0x{:X}".format(ins
& 0xffffffff))
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.
94 yield from set_alu_inputs(alu
, pdecode2
, simulator
)
96 opname
= code
.split(' ')[0]
97 yield from simulator
.call(opname
)
98 index
= simulator
.pc
.CIA
.value
//4
100 vld
= yield alu
.n
.valid_o
103 vld
= yield alu
.n
.valid_o
105 alu_out
= yield alu
.n
.data_o
.o
106 out_reg_valid
= yield pdecode2
.e
.write_reg
.ok
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
)
113 sim
.add_sync_process(process
)
114 with sim
.write_vcd("simulator.vcd", "simulator.gtkw",
119 def run_tst_program(self
, prog
, initial_regs
=[0] * 32):
120 simulator
= self
.run_tst(prog
, initial_regs
)
125 insns
= ["add", "add.", "and", "or", "xor", "subf"]
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
)
135 def test_rand_imm(self
):
136 insns
= ["addi", "addis", "subfic"]
138 choice
= random
.choice(insns
)
139 imm
= random
.randint(-(1<<15), (1<<15)-1)
140 lst
= [f
"{choice} 3, 1, {imm}"]
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
)
147 def test_rand_imm_logical(self
):
148 insns
= ["andi.", "andis.", "ori", "oris", "xori", "xoris"]
150 choice
= random
.choice(insns
)
151 imm
= random
.randint(0, (1<<16)-1)
152 lst
= [f
"{choice} 3, 1, {imm}"]
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
)
159 def test_shift(self
):
160 insns
= ["slw", "sld", "srw", "srd", "sraw", "srad"]
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
)
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
)
181 @unittest.skip("broken")
182 def test_rlwinm(self
):
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
)
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
)
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
)
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
)
220 def test_ilang(self
):
221 rec
= CompALUOpSubset()
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
:
229 if __name__
== "__main__":