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
86 def check_fsm_outputs(self
, alu
, dec2
, sim
, code
, pia_res
):
88 rc
= yield dec2
.e
.do
.rc
.data
89 cridx_ok
= yield dec2
.e
.write_cr
.ok
90 cridx
= yield dec2
.e
.write_cr
.data
92 print("check extra output", repr(code
), cridx_ok
, cridx
)
94 self
.assertEqual(cridx
, 0, code
)
99 #MMUOutputData does not have xer
101 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
102 #yield from ALUHelpers.get_xer_ov(res, alu, dec2)
103 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
104 #yield from ALUHelpers.get_xer_so(res, alu, dec2)
107 print("res output", res
)
109 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
110 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
111 #yield from ALUHelpers.get_sim_xer_ov(sim_o, sim, dec2)
112 #yield from ALUHelpers.get_sim_xer_so(sim_o, sim, dec2)
114 print("sim output", sim_o
)
116 print("power-instruction-analyzer result:")
118 #if pia_res is not None:
119 # with self.subTest(check="pia", sim_o=sim_o, pia_res=str(pia_res)):
120 # pia_o = pia_res_to_output(pia_res)
121 # ALUHelpers.check_int_o(self, res, pia_o, code)
122 # ALUHelpers.check_cr_a(self, res, pia_o, code)
123 # #ALUHelpers.check_xer_ov(self, res, pia_o, code)
124 # #ALUHelpers.check_xer_so(self, res, pia_o, code)
126 with self
.subTest(check
="sim", sim_o
=sim_o
, pia_res
=str(pia_res
)):
127 #ALUHelpers.check_int_o(self, res, sim_o, code) # mmu is not an alu
128 ALUHelpers
.check_cr_a(self
, res
, sim_o
, code
)
129 #ALUHelpers.check_xer_ov(self, res, sim_o, code)
130 #ALUHelpers.check_xer_so(self, res, sim_o, code)
132 #oe = yield dec2.e.do.oe.oe
133 #oe_ok = yield dec2.e.do.oe.ok
134 #print("oe, oe_ok", oe, oe_ok)
135 #if not oe or not oe_ok:
136 # # if OE not enabled, XER SO and OV must not be activated
137 # so_ok = yield alu.n.o_data.xer_so.ok
138 # ov_ok = yield alu.n.o_data.xer_ov.ok
139 # print("so, ov", so_ok, ov_ok)
140 # self.assertEqual(ov_ok, False, code)
141 # self.assertEqual(so_ok, False, code)
143 def execute(self
, fsm
, instruction
, pdecode2
, test
):
144 program
= test
.program
145 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
148 gen
= program
.generate_instructions()
149 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
151 pc
= sim
.pc
.CIA
.value
154 while index
< len(instructions
):
155 ins
, code
= instructions
[index
]
157 print("pc %08x instr: %08x" % (pc
, ins
& 0xffffffff))
161 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
162 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
163 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
164 print("before: so/ov/32", so
, ov
, ov32
)
166 # ask the decoder to decode this binary data (endian'd)
167 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
168 yield pdecode2
.state
.msr
.eq(msr
) # set MSR in pdecode2
169 yield pdecode2
.state
.pc
.eq(pc
) # set PC in pdecode2
170 yield instruction
.eq(ins
) # raw binary instr.
173 fast_in
= yield pdecode2
.e
.read_fast1
.data
174 spr_in
= yield pdecode2
.e
.read_spr1
.data
175 print("dec2 spr/fast in", fast_in
, spr_in
)
177 fast_out
= yield pdecode2
.e
.write_fast1
.data
178 spr_out
= yield pdecode2
.e
.write_spr
.data
179 print("dec2 spr/fast in", fast_out
, spr_out
)
181 fn_unit
= yield pdecode2
.e
.do
.fn_unit
182 #FIXME this fails -- self.assertEqual(fn_unit, Function.SPR.value)
183 pia_res
= yield from set_fsm_inputs(fsm
, pdecode2
, sim
)
185 opname
= code
.split(' ')[0]
186 yield from sim
.call(opname
)
187 pc
= sim
.pc
.CIA
.value
190 print("pc after %08x" % (pc
))
192 vld
= yield fsm
.n
.o_valid
#fsm
196 print("not valid -- hang")
198 vld
= yield fsm
.n
.o_valid
199 if debughang
==2: vld
=1
202 yield from self
.check_fsm_outputs(fsm
, pdecode2
, sim
, code
, pia_res
)
207 instruction
= Signal(32)
209 pspec
= TestMemPspec(addr_wid
=48,
214 pdecode
= create_pdecode()
216 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
218 pipe_spec
= MMUPipeSpec(id_wid
=2)
219 ldst
= LoadStore1(pspec
)
220 fsm
= FSMMMUStage(pipe_spec
)
221 fsm
.set_ldst_interface(ldst
)
222 m
.submodules
.fsm
= fsm
223 m
.submodules
.ldst
= ldst
225 #FIXME connect fsm inputs
227 comb
+= fsm
.p
.i_data
.ctx
.op
.eq_from_execute1(pdecode2
.do
)
228 comb
+= fsm
.p
.i_valid
.eq(1)
229 comb
+= fsm
.n
.i_ready
.eq(1)
230 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
236 for test
in self
.test_data
:
237 print("test", test
.name
)
238 print("sprs", test
.sprs
)
239 program
= test
.program
240 with self
.subTest(test
.name
):
241 yield from self
.execute(fsm
, instruction
, pdecode2
, test
)
243 sim
.add_sync_process(process
)
244 with sim
.write_vcd("alu_simulator.vcd", "simulator.gtkw",
248 if __name__
== "__main__":
249 unittest
.main(exit
=False)
250 suite
= unittest
.TestSuite()
251 suite
.addTest(TestRunner(MMUTestCase().test_data
))
252 suite
.addTest(TestRunner(MMUIlangCase().test_data
))
254 runner
= unittest
.TextTestRunner()