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 Function
12 from openpower
.simulator
.program
import Program
13 from openpower
.decoder
.isa
.all
import ISA
14 from soc
.regfile
.regfiles
import FastRegs
15 from openpower
.endian
import bigendian
17 from openpower
.test
.common
import ALUHelpers
18 from soc
.fu
.branch
.pipeline
import BranchBasePipe
19 from soc
.fu
.branch
.pipe_data
import BranchPipeSpec
22 from openpower
.test
.branch
.branch_cases
import BranchTestCase
25 def get_rec_width(rec
):
27 # Setup random inputs for dut.op
34 def get_cu_inputs(dec2
, sim
):
35 """naming (res) must conform to BranchFunctionUnit input regspec
40 #res['cia'] = sim.pc.CIA.value
42 yield from ALUHelpers
.get_sim_fast_spr1(res
, sim
, dec2
)
43 yield from ALUHelpers
.get_sim_fast_spr2(res
, sim
, dec2
)
44 yield from ALUHelpers
.get_sim_cr_a(res
, sim
, dec2
)
46 print("get inputs", res
)
50 class BranchAllCases(BranchTestCase
):
53 pspec
= BranchPipeSpec(id_wid
=2, parent_pspec
=None)
54 alu
= BranchBasePipe(pspec
)
55 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
56 with
open("branch_pipeline.il", "w") as f
:
60 class TestRunner(unittest
.TestCase
):
62 test_data
= BranchTestCase().test_data
63 print ("test data", test_data
)
66 instruction
= Signal(32)
69 opkls
= BranchPipeSpec
.opsubsetkls
71 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(None, opkls
, fn_name
)
72 pdecode
= pdecode2
.dec
74 pspec
= BranchPipeSpec(id_wid
=2, parent_pspec
=None)
75 m
.submodules
.branch
= branch
= BranchBasePipe(pspec
)
77 comb
+= branch
.p
.i_data
.ctx
.op
.eq_from_execute1(pdecode2
.do
)
78 comb
+= branch
.p
.i_valid
.eq(1)
79 comb
+= branch
.n
.i_ready
.eq(1)
80 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
86 for test
in test_data
:
88 program
= test
.program
89 with self
.subTest(test
.name
):
90 simulator
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
94 simulator
.set_pc(initial_cia
)
95 gen
= program
.generate_instructions()
97 zip(gen
, program
.assembly
.splitlines()))
99 pc
= simulator
.pc
.CIA
.value
100 msr
= simulator
.msr
.value
101 index
= (pc
- initial_cia
)//4
102 while index
< len(instructions
) and index
>= 0:
104 ins
, code
= instructions
[index
]
106 print("insn 0x{:X}".format(ins
& 0xffffffff))
109 # ask the decoder to decode this binary data (endian'd)
111 yield pdecode2
.dec
.bigendian
.eq(bigendian
)
112 yield pdecode2
.state
.msr
.eq(msr
) # set MSR in pdecode2
113 yield pdecode2
.state
.pc
.eq(pc
) # set PC in pdecode2
114 yield instruction
.eq(ins
) # raw binary instr.
115 # note, here, the op will need further decoding in order
116 # to set the correct SPRs on SPR1/2/3. op_bc* require
117 # spr1 to be set to CTR, op_bctar require spr2 to be
118 # set to TAR, op_bclr* require spr2 to be set to LR.
119 # if op_sc*, op_rf* and op_hrfid are to be added here
120 # then additional op-decoding is required, accordingly
122 lk
= yield pdecode2
.e
.do
.lk
124 yield from self
.set_inputs(branch
, pdecode2
, simulator
)
125 fn_unit
= yield pdecode2
.e
.do
.fn_unit
126 self
.assertEqual(fn_unit
, Function
.BRANCH
.value
, code
)
129 opname
= code
.split(' ')[0]
130 prev_nia
= simulator
.pc
.NIA
.value
131 yield from simulator
.call(opname
)
132 pc
= simulator
.pc
.CIA
.value
133 msr
= simulator
.msr
.value
134 index
= (pc
- initial_cia
)//4
136 yield from self
.assert_outputs(branch
, pdecode2
,
140 sim
.add_sync_process(process
)
141 with sim
.write_vcd("branch_simulator.vcd"):
144 def assert_outputs(self
, branch
, dec2
, sim
, prev_nia
, code
):
145 branch_taken
= yield branch
.n
.o_data
.nia
.ok
146 sim_branch_taken
= prev_nia
!= sim
.pc
.CIA
147 self
.assertEqual(branch_taken
, sim_branch_taken
, code
)
149 branch_addr
= yield branch
.n
.o_data
.nia
.data
150 print(f
"real: {branch_addr:x}, sim: {sim.pc.CIA.value:x}")
151 self
.assertEqual(branch_addr
, sim
.pc
.CIA
.value
, code
)
153 # TODO: check write_fast1 as well (should contain CTR)
155 # TODO: this should be checking write_fast2
156 lk
= yield dec2
.e
.do
.lk
157 branch_lk
= yield branch
.n
.o_data
.lr
.ok
158 self
.assertEqual(lk
, branch_lk
, code
)
160 branch_lr
= yield branch
.n
.o_data
.lr
.data
161 self
.assertEqual(sim
.spr
['LR'], branch_lr
, code
)
163 def set_inputs(self
, branch
, dec2
, sim
):
164 print(f
"cr0: {sim.crl[0].get_range()}")
166 inp
= yield from get_cu_inputs(dec2
, sim
)
168 yield from ALUHelpers
.set_fast_spr1(branch
, dec2
, inp
)
169 yield from ALUHelpers
.set_fast_spr2(branch
, dec2
, inp
)
170 yield from ALUHelpers
.set_cr_a(branch
, dec2
, inp
)
173 if __name__
== "__main__":