221661f500912d7de96be32f58802bc0cb8902c0
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
.isa
.caller
import ISACaller
, special_sprs
10 from openpower
.decoder
.power_decoder
import (create_pdecode
)
11 from openpower
.decoder
.power_decoder2
import (PowerDecode2
)
12 from openpower
.decoder
.power_enums
import (XER_bits
, Function
, MicrOp
)
13 from openpower
.decoder
.selectable_int
import SelectableInt
14 from openpower
.simulator
.program
import Program
15 from openpower
.decoder
.isa
.all
import ISA
16 from soc
.regfile
.regfiles
import FastRegs
17 from soc
.config
.endian
import bigendian
19 from openpower
.test
.common
import TestAccumulatorBase
, TestCase
, ALUHelpers
20 from soc
.fu
.branch
.pipeline
import BranchBasePipe
21 from soc
.fu
.branch
.pipe_data
import BranchPipeSpec
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 BranchTestCase(TestAccumulatorBase
):
52 def case_0_regression_unconditional(self
):
54 imm
= random
.randrange(-1 << 23, (1 << 23)-1) * 4
56 initial_regs
= [0] * 32
57 self
.add_case(Program(lst
, bigendian
), initial_regs
)
59 def case_unconditional(self
):
60 choices
= ["b", "ba", "bl", "bla"]
62 choice
= random
.choice(choices
)
63 imm
= random
.randrange(-1 << 23, (1 << 23)-1) * 4
64 lst
= [f
"{choice} {imm}"]
65 initial_regs
= [0] * 32
66 self
.add_case(Program(lst
, bigendian
), initial_regs
)
70 bc
= random
.randrange(-1 << 13, (1 << 13)-1) * 4
71 bo
= random
.choice([0b01100, 0b00100, 0b10100])
72 bi
= random
.randrange(0, 31)
73 cr
= random
.randrange(0, (1 << 32)-1)
74 lst
= [f
"bc {bo}, {bi}, {bc}"]
75 initial_regs
= [0] * 32
76 self
.add_case(Program(lst
, bigendian
), initial_cr
=cr
)
78 def case_bc_ctr(self
):
80 bc
= random
.randrange(-1 << 13, (1 << 13)-1) * 4
81 bo
= random
.choice([0, 2, 8, 10, 16, 18])
82 bi
= random
.randrange(0, 31)
83 cr
= random
.randrange(0, (1 << 32)-1)
84 ctr
= random
.randint(0, (1 << 32)-1)
85 lst
= [f
"bc {bo}, {bi}, {bc}"]
86 initial_sprs
= {9: SelectableInt(ctr
, 64)}
87 self
.add_case(Program(lst
, bigendian
),
88 initial_sprs
=initial_sprs
,
91 def case_bc_reg(self
):
92 # XXX: bcctr and bcctrl time out (irony: they're counters)
93 choices
= ["bclr", "bclrl", "bcctr", "bcctrl", "bctar", "bctarl"]
96 bh
= random
.randrange(0, 3)
97 bo
= random
.choice([4, 12])
98 bi
= random
.randrange(0, 31)
99 cr
= random
.randrange(0, (1 << 32)-1)
100 ctr
= random
.randint(0, (1 << 32)-1)
101 lr
= random
.randint(0, (1 << 64)-1) & ~
3
102 tar
= random
.randint(0, (1 << 64)-1) & ~
3
103 lst
= [f
"{insn} {bo}, {bi}, {bh}"]
104 initial_sprs
= {9: SelectableInt(ctr
, 64),
105 8: SelectableInt(lr
, 64),
106 815: SelectableInt(tar
, 64)}
107 self
.add_case(Program(lst
, bigendian
),
108 initial_sprs
=initial_sprs
,
111 def case_bc_microwatt_1_regression(self
):
112 """bc found to be testing ctr rather than (ctr-1)
113 11fb4: 08 00 49 40 bc 2,4*cr2+gt,0x11fbc
114 cr_file.vhdl:83:13:@136835ns:(report note): Reading CR 33209703
117 initial_regs
= [0] * 32
119 self
.add_case(Program(lst
, bigendian
), initial_regs
,
122 def case_bc_microwatt_2_regression(self
):
123 """modified version, set CTR=1 so that it hits zero in BC
126 initial_regs
= [0] * 32
129 initial_sprs
= {9: SelectableInt(ctr
, 64),
131 self
.add_case(Program(lst
, bigendian
), initial_regs
,
132 initial_sprs
=initial_sprs
,
135 def case_ilang(self
):
136 pspec
= BranchPipeSpec(id_wid
=2)
137 alu
= BranchBasePipe(pspec
)
138 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
139 with
open("branch_pipeline.il", "w") as f
:
143 class TestRunner(unittest
.TestCase
):
145 test_data
= BranchTestCase().test_data
148 instruction
= Signal(32)
151 opkls
= BranchPipeSpec
.opsubsetkls
153 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(None, opkls
, fn_name
)
154 pdecode
= pdecode2
.dec
156 pspec
= BranchPipeSpec(id_wid
=2)
157 m
.submodules
.branch
= branch
= BranchBasePipe(pspec
)
159 comb
+= branch
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.do
)
160 comb
+= branch
.p
.valid_i
.eq(1)
161 comb
+= branch
.n
.ready_i
.eq(1)
162 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
168 for test
in test_data
:
170 program
= test
.program
171 with self
.subTest(test
.name
):
172 simulator
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
176 simulator
.set_pc(initial_cia
)
177 gen
= program
.generate_instructions()
179 zip(gen
, program
.assembly
.splitlines()))
181 pc
= simulator
.pc
.CIA
.value
182 msr
= simulator
.msr
.value
183 index
= (pc
- initial_cia
)//4
184 while index
< len(instructions
) and index
>= 0:
186 ins
, code
= instructions
[index
]
188 print("0x{:X}".format(ins
& 0xffffffff))
191 # ask the decoder to decode this binary data (endian'd)
193 yield pdecode2
.dec
.bigendian
.eq(bigendian
)
194 yield pdecode2
.state
.msr
.eq(msr
) # set MSR in pdecode2
195 yield pdecode2
.state
.pc
.eq(pc
) # set PC in pdecode2
196 yield instruction
.eq(ins
) # raw binary instr.
197 # note, here, the op will need further decoding in order
198 # to set the correct SPRs on SPR1/2/3. op_bc* require
199 # spr1 to be set to CTR, op_bctar require spr2 to be
200 # set to TAR, op_bclr* require spr2 to be set to LR.
201 # if op_sc*, op_rf* and op_hrfid are to be added here
202 # then additional op-decoding is required, accordingly
204 lk
= yield pdecode2
.e
.do
.lk
206 yield from self
.set_inputs(branch
, pdecode2
, simulator
)
207 fn_unit
= yield pdecode2
.e
.do
.fn_unit
208 self
.assertEqual(fn_unit
, Function
.BRANCH
.value
, code
)
211 opname
= code
.split(' ')[0]
212 prev_nia
= simulator
.pc
.NIA
.value
213 yield from simulator
.call(opname
)
214 pc
= simulator
.pc
.CIA
.value
215 msr
= simulator
.msr
.value
216 index
= (pc
- initial_cia
)//4
218 yield from self
.assert_outputs(branch
, pdecode2
,
222 sim
.add_sync_process(process
)
223 with sim
.write_vcd("branch_simulator.vcd"):
226 def assert_outputs(self
, branch
, dec2
, sim
, prev_nia
, code
):
227 branch_taken
= yield branch
.n
.data_o
.nia
.ok
228 sim_branch_taken
= prev_nia
!= sim
.pc
.CIA
229 self
.assertEqual(branch_taken
, sim_branch_taken
, code
)
231 branch_addr
= yield branch
.n
.data_o
.nia
.data
232 print(f
"real: {branch_addr:x}, sim: {sim.pc.CIA.value:x}")
233 self
.assertEqual(branch_addr
, sim
.pc
.CIA
.value
, code
)
235 # TODO: check write_fast1 as well (should contain CTR)
237 # TODO: this should be checking write_fast2
238 lk
= yield dec2
.e
.do
.lk
239 branch_lk
= yield branch
.n
.data_o
.lr
.ok
240 self
.assertEqual(lk
, branch_lk
, code
)
242 branch_lr
= yield branch
.n
.data_o
.lr
.data
243 self
.assertEqual(sim
.spr
['LR'], branch_lr
, code
)
245 def set_inputs(self
, branch
, dec2
, sim
):
246 print(f
"cr0: {sim.crl[0].get_range()}")
248 inp
= yield from get_cu_inputs(dec2
, sim
)
250 yield from ALUHelpers
.set_fast_spr1(branch
, dec2
, inp
)
251 yield from ALUHelpers
.set_fast_spr2(branch
, dec2
, inp
)
252 yield from ALUHelpers
.set_cr_a(branch
, dec2
, inp
)
255 if __name__
== "__main__":