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
, InternalOp
, 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
15 from soc
.fu
.test
.common
import (TestCase
, ALUHelpers
)
16 from soc
.fu
.spr
.pipeline
import SPRBasePipe
17 from soc
.fu
.spr
.pipe_data
import SPRPipeSpec
21 def get_cu_inputs(dec2
, sim
):
22 """naming (res) must conform to SPRFunctionUnit input regspec
26 yield from ALUHelpers
.get_sim_int_ra(res
, sim
, dec2
) # RA
27 yield from ALUHelpers
.get_sim_int_rb(res
, sim
, dec2
) # RB
28 yield from ALUHelpers
.get_sim_slow_spr1(res
, sim
, dec2
) # FAST1
29 yield from ALUHelpers
.get_sim_fast_spr1(res
, sim
, dec2
) # FAST1
30 yield from ALUHelpers
.get_rd_sim_xer_ca(res
, sim
, dec2
) # XER.ca
31 yield from ALUHelpers
.get_sim_xer_ov(res
, sim
, dec2
) # XER.ov
32 yield from ALUHelpers
.get_sim_xer_so(res
, sim
, dec2
) # XER.so
34 print ("spr get_cu_inputs", res
)
40 def set_alu_inputs(alu
, dec2
, sim
):
41 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
42 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
43 # and place it into data_i.b
45 inp
= yield from get_cu_inputs(dec2
, sim
)
46 yield from ALUHelpers
.set_int_ra(alu
, dec2
, inp
)
47 yield from ALUHelpers
.set_xer_ca(alu
, dec2
, inp
)
48 yield from ALUHelpers
.set_xer_ov(alu
, dec2
, inp
)
49 yield from ALUHelpers
.set_xer_so(alu
, dec2
, inp
)
51 yield from ALUHelpers
.set_fast_spr1(alu
, dec2
, inp
)
52 yield from ALUHelpers
.set_slow_spr1(alu
, dec2
, inp
)
55 # This test bench is a bit different than is usual. Initially when I
56 # was writing it, I had all of the tests call a function to create a
57 # device under test and simulator, initialize the dut, run the
58 # simulation for ~2 cycles, and assert that the dut output what it
59 # should have. However, this was really slow, since it needed to
60 # create and tear down the dut and simulator for every test case.
62 # Now, instead of doing that, every test case in SPRTestCase puts some
63 # data into the test_data list below, describing the instructions to
64 # be tested and the initial state. Once all the tests have been run,
65 # test_data gets passed to TestRunner which then sets up the DUT and
66 # simulator once, runs all the data through it, and asserts that the
67 # results match the pseudocode sim at every cycle.
69 # By doing this, I've reduced the time it takes to run the test suite
70 # massively. Before, it took around 1 minute on my computer, now it
71 # takes around 3 seconds
74 class SPRTestCase(FHDLTestCase
):
77 def __init__(self
, name
):
78 super().__init
__(name
)
81 def run_tst_program(self
, prog
, initial_regs
=None, initial_sprs
=None):
82 tc
= TestCase(prog
, self
.test_name
, initial_regs
, initial_sprs
)
83 self
.test_data
.append(tc
)
85 def test_1_mfspr(self
):
86 lst
= ["mfspr 1, 26", # SRR0
90 initial_regs
= [0] * 32
91 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
93 self
.run_tst_program(Program(lst
, bigendian
), initial_regs
, initial_sprs
)
95 def test_1_mtspr(self
):
96 lst
= ["mtspr 26, 1", # SRR0
100 initial_regs
= [0] * 32
101 initial_regs
[1] = 0x129518230011feed
102 initial_regs
[2] = 0x123518230011feed
103 initial_regs
[3] = 0xe00c0000
104 initial_regs
[4] = 0x1010101010101010
105 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
107 self
.run_tst_program(Program(lst
, bigendian
),
108 initial_regs
, initial_sprs
)
110 def test_2_mtspr_mfspr(self
):
111 lst
= ["mtspr 26, 1", # SRR0
112 "mtspr 27, 2", # SRR1
115 "mfspr 2, 26", # SRR0
116 "mfspr 3, 27", # and into reg 2
119 initial_regs
= [0] * 32
120 initial_regs
[1] = 0x129518230011feed
121 initial_regs
[2] = 0x123518230011feed
122 initial_regs
[3] = 0xe00c0000
123 initial_regs
[4] = 0x1010101010101010
124 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
126 self
.run_tst_program(Program(lst
, bigendian
),
127 initial_regs
, initial_sprs
)
129 def test_ilang(self
):
130 pspec
= SPRPipeSpec(id_wid
=2)
131 alu
= SPRBasePipe(pspec
)
132 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
133 with
open("trap_pipeline.il", "w") as f
:
137 class TestRunner(FHDLTestCase
):
138 def __init__(self
, test_data
):
139 super().__init
__("run_all")
140 self
.test_data
= test_data
145 instruction
= Signal(32)
147 pdecode
= create_pdecode()
149 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
151 pspec
= SPRPipeSpec(id_wid
=2)
152 m
.submodules
.alu
= alu
= SPRBasePipe(pspec
)
154 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
155 comb
+= alu
.p
.valid_i
.eq(1)
156 comb
+= alu
.n
.ready_i
.eq(1)
157 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
162 for test
in self
.test_data
:
163 print("test", test
.name
)
164 print ("sprs", test
.sprs
)
165 program
= test
.program
166 self
.subTest(test
.name
)
167 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
170 gen
= program
.generate_instructions()
171 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
173 pc
= sim
.pc
.CIA
.value
175 while index
< len(instructions
):
176 ins
, code
= instructions
[index
]
178 print("pc %08x instr: %08x" % (pc
, ins
& 0xffffffff))
182 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
183 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
184 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
185 print ("before: so/ov/32", so
, ov
, ov32
)
187 # ask the decoder to decode this binary data (endian'd)
188 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
189 yield instruction
.eq(ins
) # raw binary instr.
192 fast_in
= yield pdecode2
.e
.read_fast1
.data
193 spr_in
= yield pdecode2
.e
.read_spr1
.data
194 print ("dec2 spr/fast in", fast_in
, spr_in
)
196 fast_out
= yield pdecode2
.e
.write_fast1
.data
197 spr_out
= yield pdecode2
.e
.write_spr
.data
198 print ("dec2 spr/fast in", fast_out
, spr_out
)
200 fn_unit
= yield pdecode2
.e
.do
.fn_unit
201 self
.assertEqual(fn_unit
, Function
.SPR
.value
)
202 yield from set_alu_inputs(alu
, pdecode2
, sim
)
204 opname
= code
.split(' ')[0]
205 yield from sim
.call(opname
)
206 pc
= sim
.pc
.CIA
.value
208 print("pc after %08x" % (pc
))
210 vld
= yield alu
.n
.valid_o
213 vld
= yield alu
.n
.valid_o
216 yield from self
.check_alu_outputs(alu
, pdecode2
, sim
, code
)
218 sim
.add_sync_process(process
)
219 with sim
.write_vcd("alu_simulator.vcd", "simulator.gtkw",
223 def check_alu_outputs(self
, alu
, dec2
, sim
, code
):
225 rc
= yield dec2
.e
.do
.rc
.data
226 cridx_ok
= yield dec2
.e
.write_cr
.ok
227 cridx
= yield dec2
.e
.write_cr
.data
229 print ("check extra output", repr(code
), cridx_ok
, cridx
)
231 self
.assertEqual(cridx
, 0, code
)
236 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
237 yield from ALUHelpers
.get_fast_spr1(res
, alu
, dec2
)
238 yield from ALUHelpers
.get_slow_spr1(res
, alu
, dec2
)
239 yield from ALUHelpers
.get_xer_ov(res
, alu
, dec2
)
240 yield from ALUHelpers
.get_xer_ca(res
, alu
, dec2
)
241 yield from ALUHelpers
.get_xer_so(res
, alu
, dec2
)
243 print ("output", res
)
245 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
246 yield from ALUHelpers
.get_wr_sim_xer_so(sim_o
, sim
, alu
, dec2
)
247 yield from ALUHelpers
.get_wr_sim_xer_ov(sim_o
, sim
, alu
, dec2
)
248 yield from ALUHelpers
.get_wr_sim_xer_ca(sim_o
, sim
, dec2
)
249 yield from ALUHelpers
.get_wr_fast_spr1(sim_o
, sim
, dec2
)
250 yield from ALUHelpers
.get_wr_slow_spr1(sim_o
, sim
, dec2
)
252 print ("sim output", sim_o
)
254 ALUHelpers
.check_xer_ov(self
, res
, sim_o
, code
)
255 ALUHelpers
.check_xer_ca(self
, res
, sim_o
, code
)
256 ALUHelpers
.check_xer_so(self
, res
, sim_o
, code
)
257 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
258 ALUHelpers
.check_fast_spr1(self
, res
, sim_o
, code
)
259 ALUHelpers
.check_slow_spr1(self
, res
, sim_o
, code
)
262 if __name__
== "__main__":
263 unittest
.main(exit
=False)
264 suite
= unittest
.TestSuite()
265 suite
.addTest(TestRunner(SPRTestCase
.test_data
))
267 runner
= unittest
.TextTestRunner()