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 import power_instruction_analyzer
as pia
35 def set_fsm_inputs(alu
, dec2
, sim
):
36 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
37 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
38 # and place it into data_i.b
41 inp
= yield from get_cu_inputs(dec2
, sim
)
42 # set int registers a and b
43 yield from ALUHelpers
.set_int_ra(alu
, dec2
, inp
)
44 yield from ALUHelpers
.set_int_rb(alu
, dec2
, inp
)
45 # TODO set spr register
46 # yield from ALUHelpers.set_spr_spr1(alu, dec2, inp)
53 print("xer_so::::::::::::::::::::::::::::::::::::::::::::::::")
56 overflow
= pia
.OverflowFlags(so
=bool(so
),
64 return pia
.InstructionInput(ra
=a
, rb
=b
, overflow
=overflow
)
67 def check_fsm_outputs(fsm
, pdecode2
, sim
, code
):
68 # check that MMUOutputData is correct
71 #incomplete test - connect fsm inputs first
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 -- KeyError: 2 in simulator
81 "mfspr 2, 19", # DAR to reg 2 -- with key = spr_dict[key].SPR
82 # TODO -- verify returned sprvals
85 initial_regs
= [0] * 32
87 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
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(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
, fsm
, 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.
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 #FIXME this fails -- self.assertEqual(fn_unit, Function.SPR.value)
202 pia_res
= yield from set_fsm_inputs(fsm
, pdecode2
, sim
)
204 opname
= code
.split(' ')[0]
205 yield from sim
.call(opname
)
206 pc
= sim
.pc
.CIA
.value
209 print("pc after %08x" % (pc
))
211 vld
= yield fsm
.n
.valid_o
#fsm
214 if debughang
: print("not valid -- hang")
215 vld
= yield fsm
.n
.valid_o
216 if debughang
==2: vld
=1
219 yield from self
.check_fsm_outputs(fsm
, pdecode2
, sim
, code
, pia_res
)
224 instruction
= Signal(32)
226 pdecode
= create_pdecode()
228 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
230 pspec
= MMUPipeSpec(id_wid
=2)
231 m
.submodules
.fsm
= fsm
= FSMMMUStage(pspec
)
233 #FIXME connect fsm inputs
235 comb
+= fsm
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.do
)
236 comb
+= fsm
.p
.valid_i
.eq(1)
237 comb
+= fsm
.n
.ready_i
.eq(1)
238 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
244 for test
in self
.test_data
:
245 print("test", test
.name
)
246 print("sprs", test
.sprs
)
247 program
= test
.program
248 with self
.subTest(test
.name
):
249 yield from self
.execute(fsm
, instruction
, pdecode2
, test
)
251 sim
.add_sync_process(process
)
252 with sim
.write_vcd("alu_simulator.vcd", "simulator.gtkw",
256 if __name__
== "__main__":
257 unittest
.main(exit
=False)
258 suite
= unittest
.TestSuite()
259 suite
.addTest(TestRunner(MMUTestCase().test_data
))
261 runner
= unittest
.TextTestRunner()