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
24 from soc
.fu
.mmu
.fsm
import FSMMMUStage
25 from soc
.fu
.mmu
.pipe_data
import MMUPipeSpec
28 from soc
.fu
.div
.test
.helper
import (log_rand
, get_cu_inputs
,
29 set_alu_inputs
, DivTestHelper
)
31 from soc
.simple
.core
import NonProductionCore
32 from soc
.config
.test
.test_loadstore
import TestMemPspec
34 import power_instruction_analyzer
as pia
38 def set_fsm_inputs(alu
, dec2
, sim
):
39 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
40 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
41 # and place it into data_i.b
44 inp
= yield from get_cu_inputs(dec2
, sim
)
45 # set int registers a and b
46 yield from ALUHelpers
.set_int_ra(alu
, dec2
, inp
)
47 yield from ALUHelpers
.set_int_rb(alu
, dec2
, inp
)
48 # TODO set spr register
49 # yield from ALUHelpers.set_spr_spr1(alu, dec2, inp)
56 print("xer_so::::::::::::::::::::::::::::::::::::::::::::::::")
59 overflow
= pia
.OverflowFlags(so
=bool(so
),
67 return pia
.InstructionInput(ra
=a
, rb
=b
, overflow
=overflow
)
70 def check_fsm_outputs(fsm
, pdecode2
, sim
, code
):
71 # check that MMUOutputData is correct
75 # TODO use AllFunctionUnits or NonProductionCore instead of
77 #incomplete test - connect fsm inputs first
78 class MMUTestCase(TestAccumulatorBase
):
79 # MMU handles MTSPR, MFSPR, DCBZ and TLBIE.
80 # other instructions here -> must be load/store
82 #before running the test case: set DISR and DAR
84 def case_mfspr_after_invalid_load(self
):
85 lst
= [ # TODO -- set SPR on both sinulator and port interface
86 "mfspr 1, 18", # DSISR to reg 1
87 "mfspr 2, 19", # DAR to reg 2
88 # TODO -- verify returned sprvals
91 initial_regs
= [0] * 32
93 initial_sprs
= {'DSISR': 0x12345678, 'DAR': 0x87654321}
94 self
.add_case(Program(lst
, bigendian
),
95 initial_regs
, initial_sprs
)
97 #def case_ilang(self):
98 # pspec = SPRPipeSpec(id_wid=2)
99 # alu = SPRBasePipe(pspec)
100 # vl = rtlil.convert(alu, ports=alu.ports())
101 # with open("trap_pipeline.il", "w") as f:
105 class TestRunner(unittest
.TestCase
):
106 def __init__(self
, test_data
):
107 super().__init
__("run_all")
108 self
.test_data
= test_data
110 def check_fsm_outputs(self
, alu
, dec2
, sim
, code
, pia_res
):
112 rc
= yield dec2
.e
.do
.rc
.data
113 cridx_ok
= yield dec2
.e
.write_cr
.ok
114 cridx
= yield dec2
.e
.write_cr
.data
116 print("check extra output", repr(code
), cridx_ok
, cridx
)
118 self
.assertEqual(cridx
, 0, code
)
123 #MMUOutputData does not have xer
125 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
126 #yield from ALUHelpers.get_xer_ov(res, alu, dec2)
127 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
128 #yield from ALUHelpers.get_xer_so(res, alu, dec2)
131 print("res output", res
)
133 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
134 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
135 #yield from ALUHelpers.get_sim_xer_ov(sim_o, sim, dec2)
136 #yield from ALUHelpers.get_sim_xer_so(sim_o, sim, dec2)
138 print("sim output", sim_o
)
140 print("power-instruction-analyzer result:")
142 #if pia_res is not None:
143 # with self.subTest(check="pia", sim_o=sim_o, pia_res=str(pia_res)):
144 # pia_o = pia_res_to_output(pia_res)
145 # ALUHelpers.check_int_o(self, res, pia_o, code)
146 # ALUHelpers.check_cr_a(self, res, pia_o, code)
147 # #ALUHelpers.check_xer_ov(self, res, pia_o, code)
148 # #ALUHelpers.check_xer_so(self, res, pia_o, code)
150 with self
.subTest(check
="sim", sim_o
=sim_o
, pia_res
=str(pia_res
)):
151 #ALUHelpers.check_int_o(self, res, sim_o, code) # mmu is not an alu
152 ALUHelpers
.check_cr_a(self
, res
, sim_o
, code
)
153 #ALUHelpers.check_xer_ov(self, res, sim_o, code)
154 #ALUHelpers.check_xer_so(self, res, sim_o, code)
156 #oe = yield dec2.e.do.oe.oe
157 #oe_ok = yield dec2.e.do.oe.ok
158 #print("oe, oe_ok", oe, oe_ok)
159 #if not oe or not oe_ok:
160 # # if OE not enabled, XER SO and OV must not be activated
161 # so_ok = yield alu.n.data_o.xer_so.ok
162 # ov_ok = yield alu.n.data_o.xer_ov.ok
163 # print("so, ov", so_ok, ov_ok)
164 # self.assertEqual(ov_ok, False, code)
165 # self.assertEqual(so_ok, False, code)
167 def execute(self
, fsm
, instruction
, pdecode2
, test
):
168 program
= test
.program
169 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
172 gen
= program
.generate_instructions()
173 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
175 pc
= sim
.pc
.CIA
.value
178 while index
< len(instructions
):
179 ins
, code
= instructions
[index
]
181 print("pc %08x instr: %08x" % (pc
, ins
& 0xffffffff))
185 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
186 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
187 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
188 print("before: so/ov/32", so
, ov
, ov32
)
190 # ask the decoder to decode this binary data (endian'd)
191 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
192 yield pdecode2
.state
.msr
.eq(msr
) # set MSR in pdecode2
193 yield pdecode2
.state
.pc
.eq(pc
) # set PC in pdecode2
194 yield instruction
.eq(ins
) # raw binary instr.
197 fast_in
= yield pdecode2
.e
.read_fast1
.data
198 spr_in
= yield pdecode2
.e
.read_spr1
.data
199 print("dec2 spr/fast in", fast_in
, spr_in
)
201 fast_out
= yield pdecode2
.e
.write_fast1
.data
202 spr_out
= yield pdecode2
.e
.write_spr
.data
203 print("dec2 spr/fast in", fast_out
, spr_out
)
205 fn_unit
= yield pdecode2
.e
.do
.fn_unit
206 #FIXME this fails -- self.assertEqual(fn_unit, Function.SPR.value)
207 pia_res
= yield from set_fsm_inputs(fsm
, pdecode2
, sim
)
209 opname
= code
.split(' ')[0]
210 yield from sim
.call(opname
)
211 pc
= sim
.pc
.CIA
.value
214 print("pc after %08x" % (pc
))
216 vld
= yield fsm
.n
.valid_o
#fsm
219 if debughang
: print("not valid -- hang")
220 vld
= yield fsm
.n
.valid_o
221 if debughang
==2: vld
=1
224 yield from self
.check_fsm_outputs(fsm
, pdecode2
, sim
, code
, pia_res
)
229 instruction
= Signal(32)
231 pdecode
= create_pdecode()
233 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
235 pspec
= TestMemPspec(ldst_ifacetype
='testpi',
241 m
.submodules
.core
= NonProductionCore(pspec
)
243 # TODO connect outputs of power decoder
244 #comb += fsm.p.data_i.ctx.op.eq_from_execute1(pdecode2.do)
245 #comb += fsm.p.valid_i.eq(1)
246 #comb += fsm.n.ready_i.eq(1)
247 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
253 for test
in self
.test_data
:
254 print("test", test
.name
)
255 print("sprs", test
.sprs
)
256 program
= test
.program
257 with self
.subTest(test
.name
):
258 yield from self
.execute(fsm
, instruction
, pdecode2
, test
)
260 sim
.add_sync_process(process
)
261 with sim
.write_vcd("alu_simulator.vcd", "simulator.gtkw",
265 if __name__
== "__main__":
266 unittest
.main(exit
=False)
267 suite
= unittest
.TestSuite()
268 suite
.addTest(TestRunner(MMUTestCase().test_data
))
270 runner
= unittest
.TextTestRunner()