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
82 "mfspr 18, 1", # DSISR
85 #"mfspr 27, 4", # SRR1
87 #next two need to be added to the simulator
88 #"dcbz 5,6" # Data Cache Block set to Zero - RA,RB (hangs)
89 "tlbie 1,1,1,1,1" #does not hang -- not verified yet
92 initial_regs
= [0] * 32
93 initial_regs
[1] = 0xBADCAB1E
94 initial_regs
[2] = 0xDEADC0DE
95 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
97 self
.add_case(Program(lst
, bigendian
),
98 initial_regs
, initial_sprs
)
100 #def case_ilang(self):
101 # pspec = SPRPipeSpec(id_wid=2)
102 # alu = SPRBasePipe(pspec)
103 # vl = rtlil.convert(alu, ports=alu.ports())
104 # with open("trap_pipeline.il", "w") as f:
108 class TestRunner(unittest
.TestCase
):
109 def __init__(self
, test_data
):
110 super().__init
__("run_all")
111 self
.test_data
= test_data
113 def check_fsm_outputs(self
, alu
, dec2
, sim
, code
, pia_res
):
115 rc
= yield dec2
.e
.do
.rc
.data
116 cridx_ok
= yield dec2
.e
.write_cr
.ok
117 cridx
= yield dec2
.e
.write_cr
.data
119 print("check extra output", repr(code
), cridx_ok
, cridx
)
121 self
.assertEqual(cridx
, 0, code
)
126 #MMUOutputData does not have xer
128 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
129 #yield from ALUHelpers.get_xer_ov(res, alu, dec2)
130 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
131 #yield from ALUHelpers.get_xer_so(res, alu, dec2)
134 print("res output", res
)
136 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
137 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
138 #yield from ALUHelpers.get_sim_xer_ov(sim_o, sim, dec2)
139 #yield from ALUHelpers.get_sim_xer_so(sim_o, sim, dec2)
141 print("sim output", sim_o
)
143 print("power-instruction-analyzer result:")
145 #if pia_res is not None:
146 # with self.subTest(check="pia", sim_o=sim_o, pia_res=str(pia_res)):
147 # pia_o = pia_res_to_output(pia_res)
148 # ALUHelpers.check_int_o(self, res, pia_o, code)
149 # ALUHelpers.check_cr_a(self, res, pia_o, code)
150 # #ALUHelpers.check_xer_ov(self, res, pia_o, code)
151 # #ALUHelpers.check_xer_so(self, res, pia_o, code)
153 with self
.subTest(check
="sim", sim_o
=sim_o
, pia_res
=str(pia_res
)):
154 #ALUHelpers.check_int_o(self, res, sim_o, code) # mmu is not an alu
155 ALUHelpers
.check_cr_a(self
, res
, sim_o
, code
)
156 #ALUHelpers.check_xer_ov(self, res, sim_o, code)
157 #ALUHelpers.check_xer_so(self, res, sim_o, code)
159 #oe = yield dec2.e.do.oe.oe
160 #oe_ok = yield dec2.e.do.oe.ok
161 #print("oe, oe_ok", oe, oe_ok)
162 #if not oe or not oe_ok:
163 # # if OE not enabled, XER SO and OV must not be activated
164 # so_ok = yield alu.n.data_o.xer_so.ok
165 # ov_ok = yield alu.n.data_o.xer_ov.ok
166 # print("so, ov", so_ok, ov_ok)
167 # self.assertEqual(ov_ok, False, code)
168 # self.assertEqual(so_ok, False, code)
170 def execute(self
, fsm
, instruction
, pdecode2
, test
):
171 program
= test
.program
172 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
175 gen
= program
.generate_instructions()
176 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
178 pc
= sim
.pc
.CIA
.value
181 while index
< len(instructions
):
182 ins
, code
= instructions
[index
]
184 print("pc %08x instr: %08x" % (pc
, ins
& 0xffffffff))
188 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
189 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
190 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
191 print("before: so/ov/32", so
, ov
, ov32
)
193 # ask the decoder to decode this binary data (endian'd)
194 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
195 yield pdecode2
.state
.msr
.eq(msr
) # set MSR in pdecode2
196 yield pdecode2
.state
.pc
.eq(pc
) # set PC in pdecode2
197 yield instruction
.eq(ins
) # raw binary instr.
200 fast_in
= yield pdecode2
.e
.read_fast1
.data
201 spr_in
= yield pdecode2
.e
.read_spr1
.data
202 print("dec2 spr/fast in", fast_in
, spr_in
)
204 fast_out
= yield pdecode2
.e
.write_fast1
.data
205 spr_out
= yield pdecode2
.e
.write_spr
.data
206 print("dec2 spr/fast in", fast_out
, spr_out
)
208 fn_unit
= yield pdecode2
.e
.do
.fn_unit
209 #FIXME this fails -- self.assertEqual(fn_unit, Function.SPR.value)
210 pia_res
= yield from set_fsm_inputs(fsm
, pdecode2
, sim
)
212 opname
= code
.split(' ')[0]
213 yield from sim
.call(opname
)
214 pc
= sim
.pc
.CIA
.value
217 print("pc after %08x" % (pc
))
219 vld
= yield fsm
.n
.valid_o
#fsm
222 if debughang
: print("not valid -- hang")
223 vld
= yield fsm
.n
.valid_o
224 if debughang
==2: vld
=1
227 yield from self
.check_fsm_outputs(fsm
, pdecode2
, sim
, code
, pia_res
)
232 instruction
= Signal(32)
234 pdecode
= create_pdecode()
236 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
238 pspec
= MMUPipeSpec(id_wid
=2)
239 m
.submodules
.fsm
= fsm
= FSMMMUStage(pspec
)
241 #FIXME connect fsm inputs
243 comb
+= fsm
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.do
)
244 comb
+= fsm
.p
.valid_i
.eq(1)
245 comb
+= fsm
.n
.ready_i
.eq(1)
246 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
252 for test
in self
.test_data
:
253 print("test", test
.name
)
254 print("sprs", test
.sprs
)
255 program
= test
.program
256 with self
.subTest(test
.name
):
257 yield from self
.execute(fsm
, instruction
, pdecode2
, test
)
259 sim
.add_sync_process(process
)
260 with sim
.write_vcd("alu_simulator.vcd", "simulator.gtkw",
264 if __name__
== "__main__":
265 unittest
.main(exit
=False)
266 suite
= unittest
.TestSuite()
267 suite
.addTest(TestRunner(MMUTestCase().test_data
))
269 runner
= unittest
.TextTestRunner()