6164fdd19c7c0c231537a6bd7e582c52423e7ca0
1 from nmigen
import Module
, Signal
2 from nmigen
.back
.pysim
import Simulator
, Delay
, Settle
3 from nmutil
.formaltest
import FHDLTestCase
4 from nmigen
.cli
import rtlil
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
, MicrOp
, CryIn
)
10 from soc
.decoder
.selectable_int
import SelectableInt
11 from soc
.simulator
.program
import Program
12 from soc
.decoder
.isa
.all
import ISA
13 from soc
.config
.endian
import bigendian
14 from soc
.consts
import MSR
17 from soc
.fu
.test
.common
import (TestCase
, ALUHelpers
)
18 from soc
.fu
.spr
.pipeline
import SPRBasePipe
19 from soc
.fu
.spr
.pipe_data
import SPRPipeSpec
23 def get_cu_inputs(dec2
, sim
):
24 """naming (res) must conform to SPRFunctionUnit input regspec
28 yield from ALUHelpers
.get_sim_int_ra(res
, sim
, dec2
) # RA
29 yield from ALUHelpers
.get_sim_int_rb(res
, sim
, dec2
) # RB
30 yield from ALUHelpers
.get_sim_slow_spr1(res
, sim
, dec2
) # FAST1
31 yield from ALUHelpers
.get_sim_fast_spr1(res
, sim
, dec2
) # FAST1
32 yield from ALUHelpers
.get_rd_sim_xer_ca(res
, sim
, dec2
) # XER.ca
33 yield from ALUHelpers
.get_sim_xer_ov(res
, sim
, dec2
) # XER.ov
34 yield from ALUHelpers
.get_sim_xer_so(res
, sim
, dec2
) # XER.so
36 print("spr get_cu_inputs", res
)
41 def set_alu_inputs(alu
, dec2
, sim
):
42 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
43 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
44 # and place it into data_i.b
46 inp
= yield from get_cu_inputs(dec2
, sim
)
47 yield from ALUHelpers
.set_int_ra(alu
, dec2
, inp
)
48 yield from ALUHelpers
.set_xer_ca(alu
, dec2
, inp
)
49 yield from ALUHelpers
.set_xer_ov(alu
, dec2
, inp
)
50 yield from ALUHelpers
.set_xer_so(alu
, dec2
, inp
)
52 yield from ALUHelpers
.set_fast_spr1(alu
, dec2
, inp
)
53 yield from ALUHelpers
.set_slow_spr1(alu
, dec2
, inp
)
57 # This test bench is a bit different than is usual. Initially when I
58 # was writing it, I had all of the tests call a function to create a
59 # device under test and simulator, initialize the dut, run the
60 # simulation for ~2 cycles, and assert that the dut output what it
61 # should have. However, this was really slow, since it needed to
62 # create and tear down the dut and simulator for every test case.
64 # Now, instead of doing that, every test case in SPRTestCase puts some
65 # data into the test_data list below, describing the instructions to
66 # be tested and the initial state. Once all the tests have been run,
67 # test_data gets passed to TestRunner which then sets up the DUT and
68 # simulator once, runs all the data through it, and asserts that the
69 # results match the pseudocode sim at every cycle.
71 # By doing this, I've reduced the time it takes to run the test suite
72 # massively. Before, it took around 1 minute on my computer, now it
73 # takes around 3 seconds
76 class SPRTestCase(FHDLTestCase
):
79 def __init__(self
, name
):
80 super().__init
__(name
)
83 def run_tst_program(self
, prog
, initial_regs
=None, initial_sprs
=None,
85 tc
= TestCase(prog
, self
.test_name
, initial_regs
, initial_sprs
,
87 self
.test_data
.append(tc
)
89 def test_1_mfspr(self
):
90 lst
= ["mfspr 1, 26", # SRR0
94 initial_regs
= [0] * 32
95 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
97 self
.run_tst_program(Program(lst
, bigendian
),
98 initial_regs
, initial_sprs
)
100 def test_1_mtspr(self
):
101 lst
= ["mtspr 26, 1", # SRR0
102 "mtspr 27, 2", # SRR1
104 "mtspr 9, 4", ] # CTR
105 initial_regs
= [0] * 32
106 initial_regs
[1] = 0x129518230011feed
107 initial_regs
[2] = 0x123518230011feed
108 initial_regs
[3] = 0xe00c0000
109 initial_regs
[4] = 0x1010101010101010
110 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
112 self
.run_tst_program(Program(lst
, bigendian
),
113 initial_regs
, initial_sprs
)
115 def test_2_mtspr_mfspr(self
):
116 lst
= ["mtspr 26, 1", # SRR0
117 "mtspr 27, 2", # SRR1
120 "mfspr 2, 26", # SRR0
121 "mfspr 3, 27", # and into reg 2
123 "mfspr 5, 9", ] # CTR
124 initial_regs
= [0] * 32
125 initial_regs
[1] = 0x129518230011feed
126 initial_regs
[2] = 0x123518230011feed
127 initial_regs
[3] = 0xe00c0000
128 initial_regs
[4] = 0x1010101010101010
129 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
131 self
.run_tst_program(Program(lst
, bigendian
),
132 initial_regs
, initial_sprs
)
134 @unittest.skip("spr does not have TRAP in it. has to be done another way")
135 def test_3_mtspr_priv(self
):
136 lst
= ["mtspr 26, 1", # SRR0
137 "mtspr 27, 2", # SRR1
139 "mtspr 9, 4", ] # CTR
140 initial_regs
= [0] * 32
141 initial_regs
[1] = 0x129518230011feed
142 initial_regs
[2] = 0x123518230011feed
143 initial_regs
[3] = 0xe00c0000
144 initial_regs
[4] = 0x1010101010101010
145 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
148 self
.run_tst_program(Program(lst
, bigendian
),
149 initial_regs
, initial_sprs
, initial_msr
=msr
)
151 def test_ilang(self
):
152 pspec
= SPRPipeSpec(id_wid
=2)
153 alu
= SPRBasePipe(pspec
)
154 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
155 with
open("trap_pipeline.il", "w") as f
:
159 class TestRunner(FHDLTestCase
):
160 def __init__(self
, test_data
):
161 super().__init
__("run_all")
162 self
.test_data
= test_data
167 instruction
= Signal(32)
169 pdecode
= create_pdecode()
171 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
173 pspec
= SPRPipeSpec(id_wid
=2)
174 m
.submodules
.alu
= alu
= SPRBasePipe(pspec
)
176 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
177 comb
+= alu
.p
.valid_i
.eq(1)
178 comb
+= alu
.n
.ready_i
.eq(1)
179 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
185 for test
in self
.test_data
:
186 print("test", test
.name
)
187 print("sprs", test
.sprs
)
188 program
= test
.program
189 self
.subTest(test
.name
)
190 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
193 gen
= program
.generate_instructions()
194 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
196 pc
= sim
.pc
.CIA
.value
199 while index
< len(instructions
):
200 ins
, code
= instructions
[index
]
202 print("pc %08x instr: %08x" % (pc
, ins
& 0xffffffff))
206 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
207 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
208 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
209 print("before: so/ov/32", so
, ov
, ov32
)
211 # ask the decoder to decode this binary data (endian'd)
212 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
213 yield pdecode2
.msr
.eq(msr
) # set MSR in pdecode2
214 yield pdecode2
.cia
.eq(pc
) # set PC in pdecode2
215 yield instruction
.eq(ins
) # raw binary instr.
218 fast_in
= yield pdecode2
.e
.read_fast1
.data
219 spr_in
= yield pdecode2
.e
.read_spr1
.data
220 print("dec2 spr/fast in", fast_in
, spr_in
)
222 fast_out
= yield pdecode2
.e
.write_fast1
.data
223 spr_out
= yield pdecode2
.e
.write_spr
.data
224 print("dec2 spr/fast in", fast_out
, spr_out
)
226 fn_unit
= yield pdecode2
.e
.do
.fn_unit
227 self
.assertEqual(fn_unit
, Function
.SPR
.value
)
228 alu_o
= yield from set_alu_inputs(alu
, pdecode2
, sim
)
230 opname
= code
.split(' ')[0]
231 yield from sim
.call(opname
)
232 pc
= sim
.pc
.CIA
.value
235 print("pc after %08x" % (pc
))
237 vld
= yield alu
.n
.valid_o
240 vld
= yield alu
.n
.valid_o
243 yield from self
.check_alu_outputs(alu
, pdecode2
, sim
, code
)
245 sim
.add_sync_process(process
)
246 with sim
.write_vcd("alu_simulator.vcd", "simulator.gtkw",
250 def check_alu_outputs(self
, alu
, dec2
, sim
, code
):
252 rc
= yield dec2
.e
.do
.rc
.data
253 cridx_ok
= yield dec2
.e
.write_cr
.ok
254 cridx
= yield dec2
.e
.write_cr
.data
256 print("check extra output", repr(code
), cridx_ok
, cridx
)
258 self
.assertEqual(cridx
, 0, code
)
263 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
264 yield from ALUHelpers
.get_fast_spr1(res
, alu
, dec2
)
265 yield from ALUHelpers
.get_slow_spr1(res
, alu
, dec2
)
266 yield from ALUHelpers
.get_xer_ov(res
, alu
, dec2
)
267 yield from ALUHelpers
.get_xer_ca(res
, alu
, dec2
)
268 yield from ALUHelpers
.get_xer_so(res
, alu
, dec2
)
272 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
273 yield from ALUHelpers
.get_wr_sim_xer_so(sim_o
, sim
, alu
, dec2
)
274 yield from ALUHelpers
.get_wr_sim_xer_ov(sim_o
, sim
, alu
, dec2
)
275 yield from ALUHelpers
.get_wr_sim_xer_ca(sim_o
, sim
, dec2
)
276 yield from ALUHelpers
.get_wr_fast_spr1(sim_o
, sim
, dec2
)
277 yield from ALUHelpers
.get_wr_slow_spr1(sim_o
, sim
, dec2
)
279 print("sim output", sim_o
)
281 ALUHelpers
.check_xer_ov(self
, res
, sim_o
, code
)
282 ALUHelpers
.check_xer_ca(self
, res
, sim_o
, code
)
283 ALUHelpers
.check_xer_so(self
, res
, sim_o
, code
)
284 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
285 ALUHelpers
.check_fast_spr1(self
, res
, sim_o
, code
)
286 ALUHelpers
.check_slow_spr1(self
, res
, sim_o
, code
)
289 if __name__
== "__main__":
290 unittest
.main(exit
=False)
291 suite
= unittest
.TestSuite()
292 suite
.addTest(TestRunner(SPRTestCase
.test_data
))
294 runner
= unittest
.TextTestRunner()