1 from nmigen
import Module
, Signal
3 # NOTE: to use cxxsim, export NMIGEN_SIM_MODE=cxxsim from the shell
4 # Also, check out the cxxsim nmigen branch, and latest yosys from git
5 from nmutil
.sim_tmp_alternative
import Simulator
, Settle
7 from nmigen
.cli
import rtlil
9 from soc
.decoder
.isa
.caller
import ISACaller
, special_sprs
10 from soc
.decoder
.power_decoder
import (create_pdecode
)
11 from soc
.decoder
.power_decoder2
import (PowerDecode2
)
12 from soc
.decoder
.power_enums
import (XER_bits
, Function
, MicrOp
, CryIn
)
13 from soc
.decoder
.selectable_int
import SelectableInt
14 from soc
.simulator
.program
import Program
15 from soc
.decoder
.isa
.all
import ISA
16 from soc
.config
.endian
import bigendian
17 from soc
.consts
import MSR
20 from soc
.fu
.test
.common
import (
21 TestAccumulatorBase
, skip_case
, TestCase
, ALUHelpers
)
22 from soc
.fu
.spr
.pipeline
import SPRBasePipe
23 from soc
.fu
.spr
.pipe_data
import SPRPipeSpec
27 def get_cu_inputs(dec2
, sim
):
28 """naming (res) must conform to SPRFunctionUnit input regspec
32 yield from ALUHelpers
.get_sim_int_ra(res
, sim
, dec2
) # RA
33 yield from ALUHelpers
.get_sim_int_rb(res
, sim
, dec2
) # RB
34 yield from ALUHelpers
.get_sim_slow_spr1(res
, sim
, dec2
) # FAST1
35 yield from ALUHelpers
.get_sim_fast_spr1(res
, sim
, dec2
) # FAST1
36 yield from ALUHelpers
.get_rd_sim_xer_ca(res
, sim
, dec2
) # XER.ca
37 yield from ALUHelpers
.get_sim_xer_ov(res
, sim
, dec2
) # XER.ov
38 yield from ALUHelpers
.get_sim_xer_so(res
, sim
, dec2
) # XER.so
40 print("spr get_cu_inputs", res
)
45 def set_alu_inputs(alu
, dec2
, sim
):
46 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
47 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
48 # and place it into data_i.b
50 inp
= yield from get_cu_inputs(dec2
, sim
)
51 yield from ALUHelpers
.set_int_ra(alu
, dec2
, inp
)
52 yield from ALUHelpers
.set_xer_ca(alu
, dec2
, inp
)
53 yield from ALUHelpers
.set_xer_ov(alu
, dec2
, inp
)
54 yield from ALUHelpers
.set_xer_so(alu
, dec2
, inp
)
56 yield from ALUHelpers
.set_fast_spr1(alu
, dec2
, inp
)
57 yield from ALUHelpers
.set_slow_spr1(alu
, dec2
, inp
)
61 # This test bench is a bit different than is usual. Initially when I
62 # was writing it, I had all of the tests call a function to create a
63 # device under test and simulator, initialize the dut, run the
64 # simulation for ~2 cycles, and assert that the dut output what it
65 # should have. However, this was really slow, since it needed to
66 # create and tear down the dut and simulator for every test case.
68 # Now, instead of doing that, every test case in SPRTestCase puts some
69 # data into the test_data list below, describing the instructions to
70 # be tested and the initial state. Once all the tests have been run,
71 # test_data gets passed to TestRunner which then sets up the DUT and
72 # simulator once, runs all the data through it, and asserts that the
73 # results match the pseudocode sim at every cycle.
75 # By doing this, I've reduced the time it takes to run the test suite
76 # massively. Before, it took around 1 minute on my computer, now it
77 # takes around 3 seconds
80 class SPRTestCase(TestAccumulatorBase
):
82 def case_1_mfspr(self
):
83 lst
= ["mfspr 1, 26", # SRR0
87 initial_regs
= [0] * 32
88 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
90 self
.add_case(Program(lst
, bigendian
),
91 initial_regs
, initial_sprs
)
93 def case_1_mtspr(self
):
94 lst
= ["mtspr 26, 1", # SRR0
98 initial_regs
= [0] * 32
99 initial_regs
[1] = 0x129518230011feed
100 initial_regs
[2] = 0x123518230011feed
101 initial_regs
[3] = 0xe00c0000
102 initial_regs
[4] = 0x1010101010101010
103 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
105 self
.add_case(Program(lst
, bigendian
),
106 initial_regs
, initial_sprs
)
108 def case_2_mtspr_mfspr(self
):
109 lst
= ["mtspr 26, 1", # SRR0
110 "mtspr 27, 2", # SRR1
113 "mfspr 2, 26", # SRR0
114 "mfspr 3, 27", # and into reg 2
116 "mfspr 5, 9", ] # CTR
117 initial_regs
= [0] * 32
118 initial_regs
[1] = 0x129518230011feed
119 initial_regs
[2] = 0x123518230011feed
120 initial_regs
[3] = 0xe00c0000
121 initial_regs
[4] = 0x1010101010101010
122 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
124 self
.add_case(Program(lst
, bigendian
),
125 initial_regs
, initial_sprs
)
128 @skip_case("spr does not have TRAP in it. has to be done another way")
129 def case_3_mtspr_priv(self
):
130 lst
= ["mtspr 26, 1", # SRR0
131 "mtspr 27, 2", # SRR1
133 "mtspr 9, 4", ] # CTR
134 initial_regs
= [0] * 32
135 initial_regs
[1] = 0x129518230011feed
136 initial_regs
[2] = 0x123518230011feed
137 initial_regs
[3] = 0xe00c0000
138 initial_regs
[4] = 0x1010101010101010
139 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
142 self
.add_case(Program(lst
, bigendian
),
143 initial_regs
, initial_sprs
, initial_msr
=msr
)
145 def case_4_mfspr_slow(self
):
146 lst
= ["mfspr 1, 272", # SPRG0
147 "mfspr 4, 273", ] # SPRG1
148 initial_regs
= [0] * 32
149 initial_sprs
= {'SPRG0_priv': 0x12345678, 'SPRG1_priv': 0x5678,
151 self
.add_case(Program(lst
, bigendian
),
152 initial_regs
, initial_sprs
)
154 def case_5_mtspr(self
):
155 lst
= ["mtspr 272, 1", # SPRG0
156 "mtspr 273, 2", # SPRG1
158 initial_regs
= [0] * 32
159 initial_regs
[1] = 0x129518230011feed
160 initial_regs
[2] = 0x123518230011fee0
161 initial_sprs
= {'SPRG0_priv': 0x12345678, 'SPRG1_priv': 0x5678,
163 self
.add_case(Program(lst
, bigendian
),
164 initial_regs
, initial_sprs
)
166 def case_ilang(self
):
167 pspec
= SPRPipeSpec(id_wid
=2)
168 alu
= SPRBasePipe(pspec
)
169 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
170 with
open("trap_pipeline.il", "w") as f
:
174 class TestRunner(unittest
.TestCase
):
175 def __init__(self
, test_data
):
176 super().__init
__("run_all")
177 self
.test_data
= test_data
179 def execute(self
, alu
, instruction
, pdecode2
, test
):
180 program
= test
.program
181 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
184 gen
= program
.generate_instructions()
185 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
187 pc
= sim
.pc
.CIA
.value
190 while index
< len(instructions
):
191 ins
, code
= instructions
[index
]
193 print("pc %08x instr: %08x" % (pc
, ins
& 0xffffffff))
197 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
198 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
199 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
200 print("before: so/ov/32", so
, ov
, ov32
)
202 # ask the decoder to decode this binary data (endian'd)
203 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
204 yield pdecode2
.state
.msr
.eq(msr
) # set MSR in pdecode2
205 yield pdecode2
.state
.pc
.eq(pc
) # set PC in pdecode2
206 yield instruction
.eq(ins
) # raw binary instr.
209 fast_in
= yield pdecode2
.e
.read_fast1
.data
210 spr_in
= yield pdecode2
.e
.read_spr1
.data
211 print("dec2 spr/fast in", fast_in
, spr_in
)
213 fast_out
= yield pdecode2
.e
.write_fast1
.data
214 spr_out
= yield pdecode2
.e
.write_spr
.data
215 print("dec2 spr/fast in", fast_out
, spr_out
)
217 fn_unit
= yield pdecode2
.e
.do
.fn_unit
218 self
.assertEqual(fn_unit
, Function
.SPR
.value
)
219 alu_o
= yield from set_alu_inputs(alu
, pdecode2
, sim
)
221 opname
= code
.split(' ')[0]
222 yield from sim
.call(opname
)
223 pc
= sim
.pc
.CIA
.value
226 print("pc after %08x" % (pc
))
228 vld
= yield alu
.n
.valid_o
231 vld
= yield alu
.n
.valid_o
234 yield from self
.check_alu_outputs(alu
, pdecode2
, sim
, code
)
239 instruction
= Signal(32)
241 pdecode
= create_pdecode()
243 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
245 pspec
= SPRPipeSpec(id_wid
=2)
246 m
.submodules
.alu
= alu
= SPRBasePipe(pspec
)
248 comb
+= alu
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.do
)
249 comb
+= alu
.p
.valid_i
.eq(1)
250 comb
+= alu
.n
.ready_i
.eq(1)
251 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
257 for test
in self
.test_data
:
258 print("test", test
.name
)
259 print("sprs", test
.sprs
)
260 program
= test
.program
261 with self
.subTest(test
.name
):
262 yield from self
.execute(alu
, instruction
, pdecode2
, test
)
264 sim
.add_sync_process(process
)
265 with sim
.write_vcd("alu_simulator.vcd", "simulator.gtkw",
269 def check_alu_outputs(self
, alu
, dec2
, sim
, code
):
271 rc
= yield dec2
.e
.do
.rc
.data
272 cridx_ok
= yield dec2
.e
.write_cr
.ok
273 cridx
= yield dec2
.e
.write_cr
.data
275 print("check extra output", repr(code
), cridx_ok
, cridx
)
277 self
.assertEqual(cridx
, 0, code
)
282 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
283 yield from ALUHelpers
.get_fast_spr1(res
, alu
, dec2
)
284 yield from ALUHelpers
.get_slow_spr1(res
, alu
, dec2
)
285 yield from ALUHelpers
.get_xer_ov(res
, alu
, dec2
)
286 yield from ALUHelpers
.get_xer_ca(res
, alu
, dec2
)
287 yield from ALUHelpers
.get_xer_so(res
, alu
, dec2
)
291 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
292 yield from ALUHelpers
.get_wr_sim_xer_so(sim_o
, sim
, alu
, dec2
)
293 yield from ALUHelpers
.get_wr_sim_xer_ov(sim_o
, sim
, alu
, dec2
)
294 yield from ALUHelpers
.get_wr_sim_xer_ca(sim_o
, sim
, dec2
)
295 yield from ALUHelpers
.get_wr_fast_spr1(sim_o
, sim
, dec2
)
296 yield from ALUHelpers
.get_wr_slow_spr1(sim_o
, sim
, dec2
)
298 print("sim output", sim_o
)
300 ALUHelpers
.check_xer_ov(self
, res
, sim_o
, code
)
301 ALUHelpers
.check_xer_ca(self
, res
, sim_o
, code
)
302 ALUHelpers
.check_xer_so(self
, res
, sim_o
, code
)
303 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
304 ALUHelpers
.check_fast_spr1(self
, res
, sim_o
, code
)
305 ALUHelpers
.check_slow_spr1(self
, res
, sim_o
, code
)
308 if __name__
== "__main__":
309 unittest
.main(exit
=False)
310 suite
= unittest
.TestSuite()
311 suite
.addTest(TestRunner(SPRTestCase().test_data
))
313 runner
= unittest
.TextTestRunner()