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
)
42 def set_alu_inputs(alu
, dec2
, sim
):
43 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
44 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
45 # and place it into data_i.b
47 inp
= yield from get_cu_inputs(dec2
, sim
)
48 yield from ALUHelpers
.set_int_ra(alu
, dec2
, inp
)
49 yield from ALUHelpers
.set_xer_ca(alu
, dec2
, inp
)
50 yield from ALUHelpers
.set_xer_ov(alu
, dec2
, inp
)
51 yield from ALUHelpers
.set_xer_so(alu
, dec2
, inp
)
53 yield from ALUHelpers
.set_fast_spr1(alu
, dec2
, inp
)
54 yield from ALUHelpers
.set_slow_spr1(alu
, dec2
, inp
)
58 # This test bench is a bit different than is usual. Initially when I
59 # was writing it, I had all of the tests call a function to create a
60 # device under test and simulator, initialize the dut, run the
61 # simulation for ~2 cycles, and assert that the dut output what it
62 # should have. However, this was really slow, since it needed to
63 # create and tear down the dut and simulator for every test case.
65 # Now, instead of doing that, every test case in SPRTestCase puts some
66 # data into the test_data list below, describing the instructions to
67 # be tested and the initial state. Once all the tests have been run,
68 # test_data gets passed to TestRunner which then sets up the DUT and
69 # simulator once, runs all the data through it, and asserts that the
70 # results match the pseudocode sim at every cycle.
72 # By doing this, I've reduced the time it takes to run the test suite
73 # massively. Before, it took around 1 minute on my computer, now it
74 # takes around 3 seconds
77 class SPRTestCase(FHDLTestCase
):
80 def __init__(self
, name
):
81 super().__init
__(name
)
84 def run_tst_program(self
, prog
, initial_regs
=None, initial_sprs
=None,
86 tc
= TestCase(prog
, self
.test_name
, initial_regs
, initial_sprs
,
88 self
.test_data
.append(tc
)
90 def test_1_mfspr(self
):
91 lst
= ["mfspr 1, 26", # SRR0
95 initial_regs
= [0] * 32
96 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
98 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
, initial_sprs
)
100 def test_1_mtspr(self
):
101 lst
= ["mtspr 26, 1", # SRR0
102 "mtspr 27, 2", # SRR1
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
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
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
)
184 for test
in self
.test_data
:
185 print("test", test
.name
)
186 print ("sprs", test
.sprs
)
187 program
= test
.program
188 self
.subTest(test
.name
)
189 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
192 gen
= program
.generate_instructions()
193 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
195 pc
= sim
.pc
.CIA
.value
198 while index
< len(instructions
):
199 ins
, code
= instructions
[index
]
201 print("pc %08x instr: %08x" % (pc
, ins
& 0xffffffff))
205 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
206 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
207 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
208 print ("before: so/ov/32", so
, ov
, ov32
)
210 # ask the decoder to decode this binary data (endian'd)
211 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
212 yield pdecode2
.msr
.eq(msr
) # set MSR in pdecode2
213 yield pdecode2
.cia
.eq(pc
) # set PC in pdecode2
214 yield instruction
.eq(ins
) # raw binary instr.
217 fast_in
= yield pdecode2
.e
.read_fast1
.data
218 spr_in
= yield pdecode2
.e
.read_spr1
.data
219 print ("dec2 spr/fast in", fast_in
, spr_in
)
221 fast_out
= yield pdecode2
.e
.write_fast1
.data
222 spr_out
= yield pdecode2
.e
.write_spr
.data
223 print ("dec2 spr/fast in", fast_out
, spr_out
)
225 fn_unit
= yield pdecode2
.e
.do
.fn_unit
226 self
.assertEqual(fn_unit
, Function
.SPR
.value
)
227 alu_o
= yield from set_alu_inputs(alu
, pdecode2
, sim
)
229 opname
= code
.split(' ')[0]
230 yield from sim
.call(opname
)
231 pc
= sim
.pc
.CIA
.value
234 print("pc after %08x" % (pc
))
236 vld
= yield alu
.n
.valid_o
239 vld
= yield alu
.n
.valid_o
242 yield from self
.check_alu_outputs(alu
, pdecode2
, sim
, code
)
244 sim
.add_sync_process(process
)
245 with sim
.write_vcd("alu_simulator.vcd", "simulator.gtkw",
249 def check_alu_outputs(self
, alu
, dec2
, sim
, code
):
251 rc
= yield dec2
.e
.do
.rc
.data
252 cridx_ok
= yield dec2
.e
.write_cr
.ok
253 cridx
= yield dec2
.e
.write_cr
.data
255 print ("check extra output", repr(code
), cridx_ok
, cridx
)
257 self
.assertEqual(cridx
, 0, code
)
262 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
263 yield from ALUHelpers
.get_fast_spr1(res
, alu
, dec2
)
264 yield from ALUHelpers
.get_slow_spr1(res
, alu
, dec2
)
265 yield from ALUHelpers
.get_xer_ov(res
, alu
, dec2
)
266 yield from ALUHelpers
.get_xer_ca(res
, alu
, dec2
)
267 yield from ALUHelpers
.get_xer_so(res
, alu
, dec2
)
269 print ("output", res
)
271 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
272 yield from ALUHelpers
.get_wr_sim_xer_so(sim_o
, sim
, alu
, dec2
)
273 yield from ALUHelpers
.get_wr_sim_xer_ov(sim_o
, sim
, alu
, dec2
)
274 yield from ALUHelpers
.get_wr_sim_xer_ca(sim_o
, sim
, dec2
)
275 yield from ALUHelpers
.get_wr_fast_spr1(sim_o
, sim
, dec2
)
276 yield from ALUHelpers
.get_wr_slow_spr1(sim_o
, sim
, dec2
)
278 print ("sim output", sim_o
)
280 ALUHelpers
.check_xer_ov(self
, res
, sim_o
, code
)
281 ALUHelpers
.check_xer_ca(self
, res
, sim_o
, code
)
282 ALUHelpers
.check_xer_so(self
, res
, sim_o
, code
)
283 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
284 ALUHelpers
.check_fast_spr1(self
, res
, sim_o
, code
)
285 ALUHelpers
.check_slow_spr1(self
, res
, sim_o
, code
)
288 if __name__
== "__main__":
289 unittest
.main(exit
=False)
290 suite
= unittest
.TestSuite()
291 suite
.addTest(TestRunner(SPRTestCase
.test_data
))
293 runner
= unittest
.TextTestRunner()