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
33 from soc
.simple
.test
.test_core
import (setup_regs
, check_regs
,
37 import power_instruction_analyzer
as pia
41 def set_fsm_inputs_do_not_use(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
47 inp
= yield from get_cu_inputs(dec2
, sim
)
48 # set int registers a and b
49 yield from ALUHelpers
.set_int_ra(alu
, dec2
, inp
)
50 yield from ALUHelpers
.set_int_rb(alu
, dec2
, inp
)
51 # TODO set spr register
52 # yield from ALUHelpers.set_spr_spr1(alu, dec2, inp)
59 print("xer_so::::::::::::::::::::::::::::::::::::::::::::::::")
62 overflow
= pia
.OverflowFlags(so
=bool(so
),
70 return pia
.InstructionInput(ra
=a
, rb
=b
, overflow
=overflow
)
72 class MMUTestCase(TestAccumulatorBase
):
73 # MMU handles MTSPR, MFSPR, DCBZ and TLBIE.
74 # other instructions here -> must be load/store
76 #before running the test case: set DISR and DAR
78 def case_mfspr_after_invalid_load(self
):
79 lst
= [ # TODO -- set SPR on both sinulator and port interface
80 "mfspr 1, 18", # DSISR to reg 1
81 "mfspr 2, 19", # DAR to reg 2
82 # TODO -- verify returned sprvals
85 initial_regs
= [0] * 32
87 #initial_sprs = {'DSISR': 0x12345678, 'DAR': 0x87654321}
89 self
.add_case(Program(lst
, bigendian
),
90 initial_regs
, initial_sprs
)
92 #def case_ilang(self):
93 # pspec = SPRPipeSpec(id_wid=2)
94 # alu = SPRBasePipe(pspec)
95 # vl = rtlil.convert(alu, ports=alu.ports())
96 # with open("trap_pipeline.il", "w") as f:
100 class TestRunner(unittest
.TestCase
):
101 def __init__(self
, test_data
):
102 super().__init
__("run_all")
103 self
.test_data
= test_data
105 def check_fsm_outputs_delete_me(self
, alu
, dec2
, sim
, code
, pia_res
):
107 rc
= yield dec2
.e
.do
.rc
.data
108 cridx_ok
= yield dec2
.e
.write_cr
.ok
109 cridx
= yield dec2
.e
.write_cr
.data
111 print("check extra output", repr(code
), cridx_ok
, cridx
)
113 self
.assertEqual(cridx
, 0, code
)
118 #MMUOutputData does not have xer
120 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
121 #yield from ALUHelpers.get_xer_ov(res, alu, dec2)
122 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
123 #yield from ALUHelpers.get_xer_so(res, alu, dec2)
126 print("res output", res
)
128 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
129 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
130 #yield from ALUHelpers.get_sim_xer_ov(sim_o, sim, dec2)
131 #yield from ALUHelpers.get_sim_xer_so(sim_o, sim, dec2)
133 print("sim output", sim_o
)
135 print("power-instruction-analyzer result:")
137 #if pia_res is not None:
138 # with self.subTest(check="pia", sim_o=sim_o, pia_res=str(pia_res)):
139 # pia_o = pia_res_to_output(pia_res)
140 # ALUHelpers.check_int_o(self, res, pia_o, code)
141 # ALUHelpers.check_cr_a(self, res, pia_o, code)
142 # #ALUHelpers.check_xer_ov(self, res, pia_o, code)
143 # #ALUHelpers.check_xer_so(self, res, pia_o, code)
145 with self
.subTest(check
="sim", sim_o
=sim_o
, pia_res
=str(pia_res
)):
146 #ALUHelpers.check_int_o(self, res, sim_o, code) # mmu is not an alu
147 ALUHelpers
.check_cr_a(self
, res
, sim_o
, code
)
148 #ALUHelpers.check_xer_ov(self, res, sim_o, code)
149 #ALUHelpers.check_xer_so(self, res, sim_o, code)
151 #oe = yield dec2.e.do.oe.oe
152 #oe_ok = yield dec2.e.do.oe.ok
153 #print("oe, oe_ok", oe, oe_ok)
154 #if not oe or not oe_ok:
155 # # if OE not enabled, XER SO and OV must not be activated
156 # so_ok = yield alu.n.data_o.xer_so.ok
157 # ov_ok = yield alu.n.data_o.xer_ov.ok
158 # print("so, ov", so_ok, ov_ok)
159 # self.assertEqual(ov_ok, False, code)
160 # self.assertEqual(so_ok, False, code)
162 def execute(self
, core
, instruction
, pdecode2
, test
):
163 program
= test
.program
164 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
167 gen
= program
.generate_instructions()
168 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
170 pc
= sim
.pc
.CIA
.value
173 while index
< len(instructions
):
174 ins
, code
= instructions
[index
]
176 print("pc %08x instr: %08x" % (pc
, ins
& 0xffffffff))
180 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
181 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
182 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
183 print("before: so/ov/32", so
, ov
, ov32
)
185 # ask the decoder to decode this binary data (endian'd)
186 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
187 yield pdecode2
.state
.msr
.eq(msr
) # set MSR in pdecode2
188 yield pdecode2
.state
.pc
.eq(pc
) # set PC in pdecode2
189 yield instruction
.eq(ins
) # raw binary instr.
193 yield from setup_regs(pdecode2
, core
, test
)
195 ##fast_in = yield pdecode2.e.read_fast1.data
196 ##spr_in = yield pdecode2.e.read_spr1.data
197 ##print("dec2 spr/fast in", fast_in, spr_in)
199 ##fast_out = yield pdecode2.e.write_fast1.data
200 ##spr_out = yield pdecode2.e.write_spr.data
201 ##print("dec2 spr/fast in", fast_out, spr_out)
203 ##fn_unit = yield pdecode2.e.do.fn_unit
204 ##pia_res = yield from set_fsm_inputs(fsm, pdecode2, sim)
206 opname
= code
.split(' ')[0]
207 yield from sim
.call(opname
)
208 pc
= sim
.pc
.CIA
.value
211 print("pc after %08x" % (pc
))
213 fsm
= core
.fus
.fus
["mmu0"].alu
215 vld
= yield fsm
.n
.valid_o
#fsm
218 if debughang
: print("not valid -- hang")
219 vld
= yield fsm
.n
.valid_o
220 if debughang
==2: vld
=1
226 instruction
= Signal(32)
228 pdecode
= create_pdecode()
230 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
232 pspec
= TestMemPspec(ldst_ifacetype
='testpi',
238 m
.submodules
.core
= core
= NonProductionCore(pspec
,microwatt_mmu
=True)
240 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
246 for test
in self
.test_data
:
247 print("test", test
.name
)
248 print("sprs", test
.sprs
)
249 program
= test
.program
250 with self
.subTest(test
.name
):
251 yield from self
.execute(core
, instruction
, pdecode2
, test
)
253 sim
.add_sync_process(process
)
254 with sim
.write_vcd("mmu_ldst_simulator.vcd", "mmu_ldst_simulator.gtkw",
258 if __name__
== "__main__":
259 unittest
.main(exit
=False)
260 suite
= unittest
.TestSuite()
261 suite
.addTest(TestRunner(MMUTestCase().test_data
))
263 runner
= unittest
.TextTestRunner()