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
79 #"mtspr 26, 3", # SRR0
80 #"mtspr 27, 4", # SRR1
82 #"mfspr 18, 1", # DSISR
84 #"mfspr 26, 3", # SRR0
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_regs
[5] = 0x100
96 initial_regs
[6] = 0x100
98 initial_sprs
= {'SRR0': 0x12345678, 'SRR1': 0x5678, 'LR': 0x1234,
100 self
.add_case(Program(lst
, bigendian
),
101 initial_regs
, initial_sprs
)
103 #def case_ilang(self):
104 # pspec = SPRPipeSpec(id_wid=2)
105 # alu = SPRBasePipe(pspec)
106 # vl = rtlil.convert(alu, ports=alu.ports())
107 # with open("trap_pipeline.il", "w") as f:
111 class TestRunner(unittest
.TestCase
):
112 def __init__(self
, test_data
):
113 super().__init
__("run_all")
114 self
.test_data
= test_data
116 def check_fsm_outputs(self
, alu
, dec2
, sim
, code
, pia_res
):
118 rc
= yield dec2
.e
.do
.rc
.data
119 cridx_ok
= yield dec2
.e
.write_cr
.ok
120 cridx
= yield dec2
.e
.write_cr
.data
122 print("check extra output", repr(code
), cridx_ok
, cridx
)
124 self
.assertEqual(cridx
, 0, code
)
129 #MMUOutputData does not have xer
131 yield from ALUHelpers
.get_cr_a(res
, alu
, dec2
)
132 #yield from ALUHelpers.get_xer_ov(res, alu, dec2)
133 yield from ALUHelpers
.get_int_o(res
, alu
, dec2
)
134 #yield from ALUHelpers.get_xer_so(res, alu, dec2)
137 print("res output", res
)
139 yield from ALUHelpers
.get_sim_int_o(sim_o
, sim
, dec2
)
140 yield from ALUHelpers
.get_wr_sim_cr_a(sim_o
, sim
, dec2
)
141 #yield from ALUHelpers.get_sim_xer_ov(sim_o, sim, dec2)
142 #yield from ALUHelpers.get_sim_xer_so(sim_o, sim, dec2)
144 print("sim output", sim_o
)
146 print("power-instruction-analyzer result:")
148 #if pia_res is not None:
149 # with self.subTest(check="pia", sim_o=sim_o, pia_res=str(pia_res)):
150 # pia_o = pia_res_to_output(pia_res)
151 # ALUHelpers.check_int_o(self, res, pia_o, code)
152 # ALUHelpers.check_cr_a(self, res, pia_o, code)
153 # #ALUHelpers.check_xer_ov(self, res, pia_o, code)
154 # #ALUHelpers.check_xer_so(self, res, pia_o, code)
156 with self
.subTest(check
="sim", sim_o
=sim_o
, pia_res
=str(pia_res
)):
157 #ALUHelpers.check_int_o(self, res, sim_o, code) # mmu is not an alu
158 ALUHelpers
.check_cr_a(self
, res
, sim_o
, code
)
159 #ALUHelpers.check_xer_ov(self, res, sim_o, code)
160 #ALUHelpers.check_xer_so(self, res, sim_o, code)
162 #oe = yield dec2.e.do.oe.oe
163 #oe_ok = yield dec2.e.do.oe.ok
164 #print("oe, oe_ok", oe, oe_ok)
165 #if not oe or not oe_ok:
166 # # if OE not enabled, XER SO and OV must not be activated
167 # so_ok = yield alu.n.data_o.xer_so.ok
168 # ov_ok = yield alu.n.data_o.xer_ov.ok
169 # print("so, ov", so_ok, ov_ok)
170 # self.assertEqual(ov_ok, False, code)
171 # self.assertEqual(so_ok, False, code)
173 def execute(self
, fsm
, instruction
, pdecode2
, test
):
174 program
= test
.program
175 sim
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
178 gen
= program
.generate_instructions()
179 instructions
= list(zip(gen
, program
.assembly
.splitlines()))
181 pc
= sim
.pc
.CIA
.value
184 while index
< len(instructions
):
185 ins
, code
= instructions
[index
]
187 print("pc %08x instr: %08x" % (pc
, ins
& 0xffffffff))
191 so
= 1 if sim
.spr
['XER'][XER_bits
['SO']] else 0
192 ov
= 1 if sim
.spr
['XER'][XER_bits
['OV']] else 0
193 ov32
= 1 if sim
.spr
['XER'][XER_bits
['OV32']] else 0
194 print("before: so/ov/32", so
, ov
, ov32
)
196 # ask the decoder to decode this binary data (endian'd)
197 yield pdecode2
.dec
.bigendian
.eq(bigendian
) # little / big?
198 yield pdecode2
.state
.msr
.eq(msr
) # set MSR in pdecode2
199 yield pdecode2
.state
.pc
.eq(pc
) # set PC in pdecode2
200 yield instruction
.eq(ins
) # raw binary instr.
203 fast_in
= yield pdecode2
.e
.read_fast1
.data
204 spr_in
= yield pdecode2
.e
.read_spr1
.data
205 print("dec2 spr/fast in", fast_in
, spr_in
)
207 fast_out
= yield pdecode2
.e
.write_fast1
.data
208 spr_out
= yield pdecode2
.e
.write_spr
.data
209 print("dec2 spr/fast in", fast_out
, spr_out
)
211 fn_unit
= yield pdecode2
.e
.do
.fn_unit
212 #FIXME this fails -- self.assertEqual(fn_unit, Function.SPR.value)
213 pia_res
= yield from set_fsm_inputs(fsm
, pdecode2
, sim
)
215 opname
= code
.split(' ')[0]
216 yield from sim
.call(opname
)
217 pc
= sim
.pc
.CIA
.value
220 print("pc after %08x" % (pc
))
222 vld
= yield fsm
.n
.valid_o
#fsm
225 if debughang
: print("not valid -- hang")
226 vld
= yield fsm
.n
.valid_o
227 if debughang
==2: vld
=1
230 yield from self
.check_fsm_outputs(fsm
, pdecode2
, sim
, code
, pia_res
)
235 instruction
= Signal(32)
237 pdecode
= create_pdecode()
239 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(pdecode
)
241 pspec
= MMUPipeSpec(id_wid
=2)
242 m
.submodules
.fsm
= fsm
= FSMMMUStage(pspec
)
244 #FIXME connect fsm inputs
246 comb
+= fsm
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.do
)
247 comb
+= fsm
.p
.valid_i
.eq(1)
248 comb
+= fsm
.n
.ready_i
.eq(1)
249 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
255 for test
in self
.test_data
:
256 print("test", test
.name
)
257 print("sprs", test
.sprs
)
258 program
= test
.program
259 with self
.subTest(test
.name
):
260 yield from self
.execute(fsm
, instruction
, pdecode2
, test
)
262 sim
.add_sync_process(process
)
263 with sim
.write_vcd("alu_simulator.vcd", "simulator.gtkw",
267 if __name__
== "__main__":
268 unittest
.main(exit
=False)
269 suite
= unittest
.TestSuite()
270 suite
.addTest(TestRunner(MMUTestCase().test_data
))
272 runner
= unittest
.TextTestRunner()