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
):
75 # test case for MTSPR, MFSPR, DCBZ and TLBIE.
76 #lst = ["dcbz 2,3"] not yet implemented
77 lst
= ["mtspr 18, 1", # DSISR
83 initial_regs
= [0] * 32
84 initial_regs
[1] = 0xBADCAB1E
85 initial_regs
[2] = 0xDEADC0DE
86 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
88 self
.add_case(Program(lst
, bigendian
),
89 initial_regs
, initial_sprs
)
91 #def case_ilang(self):
92 # pspec = SPRPipeSpec(id_wid=2)
93 # alu = SPRBasePipe(pspec)
94 # vl = rtlil.convert(alu, ports=alu.ports())
95 # with open("trap_pipeline.il", "w") as f:
99 class TestRunner(unittest
.TestCase
):
100 def __init__(self
, test_data
):
101 super().__init
__("run_all")
102 self
.test_data
= test_data
104 def check_fsm_outputs(self
, alu
, dec2
, sim
, code
, pia_res
):
106 rc
= yield dec2
.e
.do
.rc
.data
107 cridx_ok
= yield dec2
.e
.write_cr
.ok
108 cridx
= yield dec2
.e
.write_cr
.data
110 print("check extra output", repr(code
), cridx_ok
, cridx
)
112 self
.assertEqual(cridx
, 0, code
)
117 #MMUOutputData does not have xer
119 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
120 #yield from ALUHelpers.get_xer_ov(res, alu, dec2)
121 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
122 #yield from ALUHelpers.get_xer_so(res, alu, dec2)
125 print("res output", res
)
127 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
128 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
129 #yield from ALUHelpers.get_sim_xer_ov(sim_o, sim, dec2)
130 #yield from ALUHelpers.get_sim_xer_so(sim_o, sim, dec2)
132 print("sim output", sim_o
)
134 print("power-instruction-analyzer result:")
136 #if pia_res is not None:
137 # with self.subTest(check="pia", sim_o=sim_o, pia_res=str(pia_res)):
138 # pia_o = pia_res_to_output(pia_res)
139 # ALUHelpers.check_int_o(self, res, pia_o, code)
140 # ALUHelpers.check_cr_a(self, res, pia_o, code)
141 # #ALUHelpers.check_xer_ov(self, res, pia_o, code)
142 # #ALUHelpers.check_xer_so(self, res, pia_o, code)
144 with self
.subTest(check
="sim", sim_o
=sim_o
, pia_res
=str(pia_res
)):
145 ALUHelpers
.check_int_o(self
, res
, sim_o
, code
)
146 ALUHelpers
.check_cr_a(self
, res
, sim_o
, code
)
147 #ALUHelpers.check_xer_ov(self, res, sim_o, code)
148 #ALUHelpers.check_xer_so(self, res, sim_o, code)
150 #oe = yield dec2.e.do.oe.oe
151 #oe_ok = yield dec2.e.do.oe.ok
152 #print("oe, oe_ok", oe, oe_ok)
153 #if not oe or not oe_ok:
154 # # if OE not enabled, XER SO and OV must not be activated
155 # so_ok = yield alu.n.data_o.xer_so.ok
156 # ov_ok = yield alu.n.data_o.xer_ov.ok
157 # print("so, ov", so_ok, ov_ok)
158 # self.assertEqual(ov_ok, False, code)
159 # self.assertEqual(so_ok, False, code)
161 def execute(self
, fsm
, instruction
, pdecode2
, test
):
162 program
= test
.program
163 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
166 gen
= program
.generate_instructions()
167 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
169 pc
= sim
.pc
.CIA
.value
172 while index
< len(instructions
):
173 ins
, code
= instructions
[index
]
175 print("pc %08x instr: %08x" % (pc
, ins
& 0xffffffff))
179 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
180 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
181 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
182 print("before: so/ov/32", so
, ov
, ov32
)
184 # ask the decoder to decode this binary data (endian'd)
185 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
186 yield pdecode2
.state
.msr
.eq(msr
) # set MSR in pdecode2
187 yield pdecode2
.state
.pc
.eq(pc
) # set PC in pdecode2
188 yield instruction
.eq(ins
) # raw binary instr.
191 fast_in
= yield pdecode2
.e
.read_fast1
.data
192 spr_in
= yield pdecode2
.e
.read_spr1
.data
193 print("dec2 spr/fast in", fast_in
, spr_in
)
195 fast_out
= yield pdecode2
.e
.write_fast1
.data
196 spr_out
= yield pdecode2
.e
.write_spr
.data
197 print("dec2 spr/fast in", fast_out
, spr_out
)
199 fn_unit
= yield pdecode2
.e
.do
.fn_unit
200 #FIXME this fails -- self.assertEqual(fn_unit, Function.SPR.value)
201 pia_res
= yield from set_fsm_inputs(fsm
, pdecode2
, sim
)
203 opname
= code
.split(' ')[0]
204 yield from sim
.call(opname
)
205 pc
= sim
.pc
.CIA
.value
208 print("pc after %08x" % (pc
))
210 vld
= yield fsm
.n
.valid_o
#fsm
213 if debughang
: print("not valid -- hang")
214 vld
= yield fsm
.n
.valid_o
215 if debughang
==2: vld
=1
218 yield from self
.check_fsm_outputs(fsm
, pdecode2
, sim
, code
, pia_res
)
223 instruction
= Signal(32)
225 pdecode
= create_pdecode()
227 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
229 pspec
= MMUPipeSpec(id_wid
=2)
230 m
.submodules
.fsm
= fsm
= FSMMMUStage(pspec
)
232 #FIXME connect fsm inputs
234 comb
+= fsm
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.do
)
235 comb
+= fsm
.p
.valid_i
.eq(1)
236 comb
+= fsm
.n
.ready_i
.eq(1)
237 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
243 for test
in self
.test_data
:
244 print("test", test
.name
)
245 print("sprs", test
.sprs
)
246 program
= test
.program
247 with self
.subTest(test
.name
):
248 yield from self
.execute(fsm
, instruction
, pdecode2
, test
)
250 sim
.add_sync_process(process
)
251 with sim
.write_vcd("alu_simulator.vcd", "simulator.gtkw",
255 if __name__
== "__main__":
256 unittest
.main(exit
=False)
257 suite
= unittest
.TestSuite()
258 suite
.addTest(TestRunner(MMUTestCase().test_data
))
260 runner
= unittest
.TextTestRunner()