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 openpower
.decoder
.power_decoder
import create_pdecode
10 from openpower
.decoder
.power_decoder2
import PowerDecode2
11 from openpower
.decoder
.power_enums
import (XER_bits
, Function
, MicrOp
, CryIn
)
12 from openpower
.simulator
.program
import Program
13 from openpower
.decoder
.isa
.all
import ISA
14 from openpower
.endian
import bigendian
15 from openpower
.consts
import MSR
17 from openpower
.test
.mmu
.mmu_cases
import MMUTestCase
19 from openpower
.test
.common
import (TestAccumulatorBase
, skip_case
, ALUHelpers
)
20 from soc
.config
.test
.test_loadstore
import TestMemPspec
21 #from soc.fu.spr.pipeline import SPRBasePipe
22 #from soc.fu.spr.pipe_data import SPRPipeSpec
23 from soc
.fu
.mmu
.fsm
import FSMMMUStage
, LoadStore1
24 from soc
.fu
.mmu
.pipe_data
import MMUPipeSpec
27 from soc
.fu
.div
.test
.helper
import (log_rand
, get_cu_inputs
,
30 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 i_data.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
74 class MMUIlangCase(TestAccumulatorBase
):
75 # def case_ilang(self):
76 # pspec = SPRPipeSpec(id_wid=2, parent_pspec=None)
77 # alu = SPRBasePipe(pspec)
78 # vl = rtlil.convert(alu, ports=alu.ports())
79 # with open("trap_pipeline.il", "w") as f:
84 class TestRunner(unittest
.TestCase
):
85 def __init__(self
, test_data
):
86 super().__init
__("run_all")
87 self
.test_data
= test_data
88 # hack here -- all unit tests are affected
91 def check_fsm_outputs(self
, alu
, dec2
, sim
, code
, pia_res
):
93 rc
= yield dec2
.e
.do
.rc
.data
94 cridx_ok
= yield dec2
.e
.write_cr
.ok
95 cridx
= yield dec2
.e
.write_cr
.data
97 print("check extra output", repr(code
), cridx_ok
, cridx
)
99 self
.assertEqual(cridx
, 0, code
)
104 # MMUOutputData does not have xer
106 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
107 # yield from ALUHelpers.get_xer_ov(res, alu, dec2)
108 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
109 # yield from ALUHelpers.get_xer_so(res, alu, dec2)
111 print("res output", res
)
113 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
114 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
115 # yield from ALUHelpers.get_sim_xer_ov(sim_o, sim, dec2)
116 # yield from ALUHelpers.get_sim_xer_so(sim_o, sim, dec2)
118 print("sim output", sim_o
)
120 print("power-instruction-analyzer result:")
122 # if pia_res is not None:
123 # with self.subTest(check="pia", sim_o=sim_o, pia_res=str(pia_res)):
124 # pia_o = pia_res_to_output(pia_res)
125 # ALUHelpers.check_int_o(self, res, pia_o, code)
126 # ALUHelpers.check_cr_a(self, res, pia_o, code)
127 # #ALUHelpers.check_xer_ov(self, res, pia_o, code)
128 # #ALUHelpers.check_xer_so(self, res, pia_o, code)
130 with self
.subTest(check
="sim", sim_o
=sim_o
, pia_res
=str(pia_res
)):
131 # ALUHelpers.check_int_o(self, res, sim_o, code) # mmu is not an alu
132 ALUHelpers
.check_cr_a(self
, res
, sim_o
, code
)
133 #ALUHelpers.check_xer_ov(self, res, sim_o, code)
134 #ALUHelpers.check_xer_so(self, res, sim_o, code)
136 # oe = yield dec2.e.do.oe.oe
137 # oe_ok = yield dec2.e.do.oe.ok
138 #print("oe, oe_ok", oe, oe_ok)
139 # if not oe or not oe_ok:
140 # # if OE not enabled, XER SO and OV must not be activated
141 # so_ok = yield alu.n.o_data.xer_so.ok
142 # ov_ok = yield alu.n.o_data.xer_ov.ok
143 # print("so, ov", so_ok, ov_ok)
144 # self.assertEqual(ov_ok, False, code)
145 # self.assertEqual(so_ok, False, code)
147 def execute(self
, fsm
, instruction
, pdecode2
, test
):
148 program
= test
.program
149 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
152 gen
= program
.generate_instructions()
153 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
155 pc
= sim
.pc
.CIA
.value
158 while index
< len(instructions
):
159 ins
, code
= instructions
[index
]
161 print("pc %08x instr: %08x" % (pc
, ins
& 0xffffffff))
165 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
166 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
167 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
168 print("before: so/ov/32", so
, ov
, ov32
)
170 # ask the decoder to decode this binary data (endian'd)
171 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
172 yield pdecode2
.state
.msr
.eq(msr
) # set MSR in pdecode2
173 yield pdecode2
.state
.pc
.eq(pc
) # set PC in pdecode2
174 yield instruction
.eq(ins
) # raw binary instr.
177 fast_in
= yield pdecode2
.e
.read_fast1
.data
178 spr_in
= yield pdecode2
.e
.read_spr1
.data
179 print("dec2 spr/fast in", fast_in
, spr_in
)
181 fast_out
= yield pdecode2
.e
.write_fast1
.data
182 spr_out
= yield pdecode2
.e
.write_spr
.data
183 print("dec2 spr/fast in", fast_out
, spr_out
)
185 fn_unit
= yield pdecode2
.e
.do
.fn_unit
186 # FIXME this fails -- self.assertEqual(fn_unit, Function.SPR.value)
187 pia_res
= yield from set_fsm_inputs(fsm
, pdecode2
, sim
)
189 opname
= code
.split(' ')[0]
190 yield from sim
.call(opname
)
191 pc
= sim
.pc
.CIA
.value
194 print("pc after %08x" % (pc
))
196 vld
= yield fsm
.n
.o_valid
# fsm
200 print("not valid -- hang")
202 vld
= yield fsm
.n
.o_valid
207 yield from self
.check_fsm_outputs(fsm
, pdecode2
, sim
, code
, pia_res
)
212 instruction
= Signal(32)
214 pspec
= TestMemPspec(addr_wid
=64,
219 pdecode
= create_pdecode()
221 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
223 pipe_spec
= MMUPipeSpec(id_wid
=2, parent_pspec
=None)
224 ldst
= LoadStore1(pspec
)
225 fsm
= FSMMMUStage(pipe_spec
)
226 fsm
.set_ldst_interface(ldst
)
227 m
.submodules
.fsm
= fsm
228 m
.submodules
.ldst
= ldst
230 # FIXME connect fsm inputs
232 comb
+= fsm
.p
.i_data
.ctx
.op
.eq_from_execute1(pdecode2
.do
)
233 comb
+= fsm
.p
.i_valid
.eq(1)
234 comb
+= fsm
.n
.i_ready
.eq(1)
235 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
241 for test
in self
.test_data
:
242 print("test", test
.name
)
243 print("sprs", test
.sprs
)
244 program
= test
.program
245 with self
.subTest(test
.name
):
246 yield from self
.execute(fsm
, instruction
, pdecode2
, test
)
248 sim
.add_sync_process(process
)
249 with sim
.write_vcd("alu_simulator.vcd", "simulator.gtkw",
254 if __name__
== "__main__":
255 unittest
.main(exit
=False)
256 suite
= unittest
.TestSuite()
257 suite
.addTest(TestRunner(MMUTestCase().test_data
))
258 suite
.addTest(TestRunner(MMUIlangCase().test_data
))
260 runner
= unittest
.TextTestRunner()