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
34 def set_fsm_inputs(alu
, dec2
, sim
):
35 # TODO: see https://bugs.libre-soc.org/show_bug.cgi?id=305#c43
36 # detect the immediate here (with m.If(self.i.ctx.op.imm_data.imm_ok))
37 # and place it into i_data.b
40 inp
= yield from get_cu_inputs(dec2
, sim
)
41 # set int registers a and b
42 yield from ALUHelpers
.set_int_ra(alu
, dec2
, inp
)
43 yield from ALUHelpers
.set_int_rb(alu
, dec2
, inp
)
44 # TODO set spr register
45 # yield from ALUHelpers.set_spr_spr1(alu, dec2, inp)
52 print("xer_so::::::::::::::::::::::::::::::::::::::::::::::::")
55 overflow
= pia
.OverflowFlags(so
=bool(so
),
63 return pia
.InstructionInput(ra
=a
, rb
=b
, overflow
=overflow
)
66 def check_fsm_outputs(fsm
, pdecode2
, sim
, code
):
67 # check that MMUOutputData is correct
70 #incomplete test - connect fsm inputs first
71 class MMUIlangCase(TestAccumulatorBase
):
72 #def case_ilang(self):
73 # pspec = SPRPipeSpec(id_wid=2)
74 # alu = SPRBasePipe(pspec)
75 # vl = rtlil.convert(alu, ports=alu.ports())
76 # with open("trap_pipeline.il", "w") as f:
81 class TestRunner(unittest
.TestCase
):
82 def __init__(self
, test_data
):
83 super().__init
__("run_all")
84 self
.test_data
= test_data
85 #hack here -- all unit tests are affected
88 def check_fsm_outputs(self
, alu
, dec2
, sim
, code
, pia_res
):
90 rc
= yield dec2
.e
.do
.rc
.data
91 cridx_ok
= yield dec2
.e
.write_cr
.ok
92 cridx
= yield dec2
.e
.write_cr
.data
94 print("check extra output", repr(code
), cridx_ok
, cridx
)
96 self
.assertEqual(cridx
, 0, code
)
101 #MMUOutputData does not have xer
103 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
104 #yield from ALUHelpers.get_xer_ov(res, alu, dec2)
105 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
106 #yield from ALUHelpers.get_xer_so(res, alu, dec2)
109 print("res output", res
)
111 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
112 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
113 #yield from ALUHelpers.get_sim_xer_ov(sim_o, sim, dec2)
114 #yield from ALUHelpers.get_sim_xer_so(sim_o, sim, dec2)
116 print("sim output", sim_o
)
118 print("power-instruction-analyzer result:")
120 #if pia_res is not None:
121 # with self.subTest(check="pia", sim_o=sim_o, pia_res=str(pia_res)):
122 # pia_o = pia_res_to_output(pia_res)
123 # ALUHelpers.check_int_o(self, res, pia_o, code)
124 # ALUHelpers.check_cr_a(self, res, pia_o, code)
125 # #ALUHelpers.check_xer_ov(self, res, pia_o, code)
126 # #ALUHelpers.check_xer_so(self, res, pia_o, code)
128 with self
.subTest(check
="sim", sim_o
=sim_o
, pia_res
=str(pia_res
)):
129 #ALUHelpers.check_int_o(self, res, sim_o, code) # mmu is not an alu
130 ALUHelpers
.check_cr_a(self
, res
, sim_o
, code
)
131 #ALUHelpers.check_xer_ov(self, res, sim_o, code)
132 #ALUHelpers.check_xer_so(self, res, sim_o, code)
134 #oe = yield dec2.e.do.oe.oe
135 #oe_ok = yield dec2.e.do.oe.ok
136 #print("oe, oe_ok", oe, oe_ok)
137 #if not oe or not oe_ok:
138 # # if OE not enabled, XER SO and OV must not be activated
139 # so_ok = yield alu.n.o_data.xer_so.ok
140 # ov_ok = yield alu.n.o_data.xer_ov.ok
141 # print("so, ov", so_ok, ov_ok)
142 # self.assertEqual(ov_ok, False, code)
143 # self.assertEqual(so_ok, False, code)
145 def execute(self
, fsm
, instruction
, pdecode2
, test
):
146 program
= test
.program
147 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
150 gen
= program
.generate_instructions()
151 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
153 pc
= sim
.pc
.CIA
.value
156 while index
< len(instructions
):
157 ins
, code
= instructions
[index
]
159 print("pc %08x instr: %08x" % (pc
, ins
& 0xffffffff))
163 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
164 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
165 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
166 print("before: so/ov/32", so
, ov
, ov32
)
168 # ask the decoder to decode this binary data (endian'd)
169 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
170 yield pdecode2
.state
.msr
.eq(msr
) # set MSR in pdecode2
171 yield pdecode2
.state
.pc
.eq(pc
) # set PC in pdecode2
172 yield instruction
.eq(ins
) # raw binary instr.
175 fast_in
= yield pdecode2
.e
.read_fast1
.data
176 spr_in
= yield pdecode2
.e
.read_spr1
.data
177 print("dec2 spr/fast in", fast_in
, spr_in
)
179 fast_out
= yield pdecode2
.e
.write_fast1
.data
180 spr_out
= yield pdecode2
.e
.write_spr
.data
181 print("dec2 spr/fast in", fast_out
, spr_out
)
183 fn_unit
= yield pdecode2
.e
.do
.fn_unit
184 #FIXME this fails -- self.assertEqual(fn_unit, Function.SPR.value)
185 pia_res
= yield from set_fsm_inputs(fsm
, pdecode2
, sim
)
187 opname
= code
.split(' ')[0]
188 yield from sim
.call(opname
)
189 pc
= sim
.pc
.CIA
.value
192 print("pc after %08x" % (pc
))
194 vld
= yield fsm
.n
.o_valid
#fsm
198 print("not valid -- hang")
200 vld
= yield fsm
.n
.o_valid
201 if debughang
==2: vld
=1
204 yield from self
.check_fsm_outputs(fsm
, pdecode2
, sim
, code
, pia_res
)
209 instruction
= Signal(32)
211 pspec
= TestMemPspec(addr_wid
=48,
216 pdecode
= create_pdecode()
218 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
220 pipe_spec
= MMUPipeSpec(id_wid
=2)
221 ldst
= LoadStore1(pspec
)
222 fsm
= FSMMMUStage(pipe_spec
)
223 fsm
.set_ldst_interface(ldst
)
224 m
.submodules
.fsm
= fsm
225 m
.submodules
.ldst
= ldst
227 #FIXME connect fsm inputs
229 comb
+= fsm
.p
.i_data
.ctx
.op
.eq_from_execute1(pdecode2
.do
)
230 comb
+= fsm
.p
.i_valid
.eq(1)
231 comb
+= fsm
.n
.i_ready
.eq(1)
232 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
238 for test
in self
.test_data
:
239 print("test", test
.name
)
240 print("sprs", test
.sprs
)
241 program
= test
.program
242 with self
.subTest(test
.name
):
243 yield from self
.execute(fsm
, instruction
, pdecode2
, test
)
245 sim
.add_sync_process(process
)
246 with sim
.write_vcd("alu_simulator.vcd", "simulator.gtkw",
250 if __name__
== "__main__":
251 unittest
.main(exit
=False)
252 suite
= unittest
.TestSuite()
253 suite
.addTest(TestRunner(MMUTestCase().test_data
))
254 suite
.addTest(TestRunner(MMUIlangCase().test_data
))
256 runner
= unittest
.TextTestRunner()