1 from nmigen
import Module
, Signal
2 from nmigen
.back
.pysim
import Simulator
, Delay
, Settle
3 from nmigen
.cli
import rtlil
5 from soc
.decoder
.isa
.caller
import ISACaller
, special_sprs
6 from soc
.decoder
.power_decoder
import (create_pdecode
)
7 from soc
.decoder
.power_decoder2
import (PowerDecode2
)
8 from soc
.decoder
.power_enums
import (XER_bits
, Function
, MicrOp
)
9 from soc
.decoder
.selectable_int
import SelectableInt
10 from soc
.simulator
.program
import Program
11 from soc
.decoder
.isa
.all
import ISA
12 from soc
.regfile
.regfiles
import FastRegs
13 from soc
.config
.endian
import bigendian
15 from soc
.fu
.test
.common
import TestAccumulatorBase
, TestCase
, ALUHelpers
16 from soc
.fu
.branch
.pipeline
import BranchBasePipe
17 from soc
.fu
.branch
.pipe_data
import BranchPipeSpec
20 from soc
.regfile
.util
import fast_reg_to_spr
# HACK!
23 def get_rec_width(rec
):
25 # Setup random inputs for dut.op
32 def get_cu_inputs(dec2
, sim
):
33 """naming (res) must conform to BranchFunctionUnit input regspec
38 #res['cia'] = sim.pc.CIA.value
40 yield from ALUHelpers
.get_sim_fast_spr1(res
, sim
, dec2
)
41 yield from ALUHelpers
.get_sim_fast_spr2(res
, sim
, dec2
)
42 yield from ALUHelpers
.get_sim_cr_a(res
, sim
, dec2
)
44 print("get inputs", res
)
48 class BranchTestCase(TestAccumulatorBase
):
50 def case_0_regression_unconditional(self
):
52 imm
= random
.randrange(-1 << 23, (1 << 23)-1) * 4
54 initial_regs
= [0] * 32
55 self
.add_case(Program(lst
, bigendian
), initial_regs
)
57 def case_unconditional(self
):
58 choices
= ["b", "ba", "bl", "bla"]
60 choice
= random
.choice(choices
)
61 imm
= random
.randrange(-1 << 23, (1 << 23)-1) * 4
62 lst
= [f
"{choice} {imm}"]
63 initial_regs
= [0] * 32
64 self
.add_case(Program(lst
, bigendian
), initial_regs
)
68 bc
= random
.randrange(-1 << 13, (1 << 13)-1) * 4
69 bo
= random
.choice([0b01100, 0b00100, 0b10100])
70 bi
= random
.randrange(0, 31)
71 cr
= random
.randrange(0, (1 << 32)-1)
72 lst
= [f
"bc {bo}, {bi}, {bc}"]
73 initial_regs
= [0] * 32
74 self
.add_case(Program(lst
, bigendian
), initial_cr
=cr
)
76 def case_bc_ctr(self
):
78 bc
= random
.randrange(-1 << 13, (1 << 13)-1) * 4
79 bo
= random
.choice([0, 2, 8, 10, 16, 18])
80 bi
= random
.randrange(0, 31)
81 cr
= random
.randrange(0, (1 << 32)-1)
82 ctr
= random
.randint(0, (1 << 32)-1)
83 lst
= [f
"bc {bo}, {bi}, {bc}"]
84 initial_sprs
= {9: SelectableInt(ctr
, 64)}
85 self
.add_case(Program(lst
, bigendian
),
86 initial_sprs
=initial_sprs
,
89 def case_bc_reg(self
):
90 # XXX: bcctr and bcctrl time out (irony: they're counters)
91 choices
= ["bclr", "bclrl", "bcctr", "bcctrl", "bctar", "bctarl"]
94 bh
= random
.randrange(0, 3)
95 bo
= random
.choice([4, 12])
96 bi
= random
.randrange(0, 31)
97 cr
= random
.randrange(0, (1 << 32)-1)
98 ctr
= random
.randint(0, (1 << 32)-1)
99 lr
= random
.randint(0, (1 << 64)-1) & ~
3
100 tar
= random
.randint(0, (1 << 64)-1) & ~
3
101 lst
= [f
"{insn} {bo}, {bi}, {bh}"]
102 initial_sprs
= {9: SelectableInt(ctr
, 64),
103 8: SelectableInt(lr
, 64),
104 815: SelectableInt(tar
, 64)}
105 self
.add_case(Program(lst
, bigendian
),
106 initial_sprs
=initial_sprs
,
109 def case_bc_microwatt_1_regression(self
):
110 """bc found to be testing ctr rather than (ctr-1)
111 11fb4: 08 00 49 40 bc 2,4*cr2+gt,0x11fbc
112 cr_file.vhdl:83:13:@136835ns:(report note): Reading CR 33209703
115 initial_regs
= [0] * 32
117 self
.add_case(Program(lst
, bigendian
), initial_regs
,
120 def case_bc_microwatt_2_regression(self
):
121 """modified version, set CTR=1 so that it hits zero in BC
124 initial_regs
= [0] * 32
127 initial_sprs
= {9: SelectableInt(ctr
, 64),
129 self
.add_case(Program(lst
, bigendian
), initial_regs
,
130 initial_sprs
=initial_sprs
,
133 def case_ilang(self
):
134 pspec
= BranchPipeSpec(id_wid
=2)
135 alu
= BranchBasePipe(pspec
)
136 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
137 with
open("branch_pipeline.il", "w") as f
:
141 class TestRunner(unittest
.TestCase
):
143 test_data
= BranchTestCase().test_data
146 instruction
= Signal(32)
149 opkls
= BranchPipeSpec
.opsubsetkls
151 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(None, opkls
, fn_name
)
152 pdecode
= pdecode2
.dec
154 pspec
= BranchPipeSpec(id_wid
=2)
155 m
.submodules
.branch
= branch
= BranchBasePipe(pspec
)
157 comb
+= branch
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
158 comb
+= branch
.p
.valid_i
.eq(1)
159 comb
+= branch
.n
.ready_i
.eq(1)
160 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
166 for test
in test_data
:
168 program
= test
.program
169 with self
.subTest(test
.name
):
170 simulator
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
174 simulator
.set_pc(initial_cia
)
175 gen
= program
.generate_instructions()
177 zip(gen
, program
.assembly
.splitlines()))
179 pc
= simulator
.pc
.CIA
.value
180 msr
= simulator
.msr
.value
181 index
= (pc
- initial_cia
)//4
182 while index
< len(instructions
) and index
>= 0:
184 ins
, code
= instructions
[index
]
186 print("0x{:X}".format(ins
& 0xffffffff))
189 # ask the decoder to decode this binary data (endian'd)
191 yield pdecode2
.dec
.bigendian
.eq(bigendian
)
192 yield pdecode2
.state
.msr
.eq(msr
) # set MSR in pdecode2
193 yield pdecode2
.state
.pc
.eq(pc
) # set PC in pdecode2
194 yield instruction
.eq(ins
) # raw binary instr.
195 # note, here, the op will need further decoding in order
196 # to set the correct SPRs on SPR1/2/3. op_bc* require
197 # spr1 to be set to CTR, op_bctar require spr2 to be
198 # set to TAR, op_bclr* require spr2 to be set to LR.
199 # if op_sc*, op_rf* and op_hrfid are to be added here
200 # then additional op-decoding is required, accordingly
202 lk
= yield pdecode2
.e
.do
.lk
204 yield from self
.set_inputs(branch
, pdecode2
, simulator
)
205 fn_unit
= yield pdecode2
.e
.do
.fn_unit
206 self
.assertEqual(fn_unit
, Function
.BRANCH
.value
, code
)
209 opname
= code
.split(' ')[0]
210 prev_nia
= simulator
.pc
.NIA
.value
211 yield from simulator
.call(opname
)
212 pc
= simulator
.pc
.CIA
.value
213 msr
= simulator
.msr
.value
214 index
= (pc
- initial_cia
)//4
216 yield from self
.assert_outputs(branch
, pdecode2
,
217 simulator
, prev_nia
, code
)
219 sim
.add_sync_process(process
)
220 with sim
.write_vcd("branch_simulator.vcd"):
223 def assert_outputs(self
, branch
, dec2
, sim
, prev_nia
, code
):
224 branch_taken
= yield branch
.n
.data_o
.nia
.ok
225 sim_branch_taken
= prev_nia
!= sim
.pc
.CIA
226 self
.assertEqual(branch_taken
, sim_branch_taken
, code
)
228 branch_addr
= yield branch
.n
.data_o
.nia
.data
229 print(f
"real: {branch_addr:x}, sim: {sim.pc.CIA.value:x}")
230 self
.assertEqual(branch_addr
, sim
.pc
.CIA
.value
, code
)
232 # TODO: check write_fast1 as well (should contain CTR)
234 # TODO: this should be checking write_fast2
235 lk
= yield dec2
.e
.do
.lk
236 branch_lk
= yield branch
.n
.data_o
.lr
.ok
237 self
.assertEqual(lk
, branch_lk
, code
)
239 branch_lr
= yield branch
.n
.data_o
.lr
.data
240 self
.assertEqual(sim
.spr
['LR'], branch_lr
, code
)
242 def set_inputs(self
, branch
, dec2
, sim
):
243 print(f
"cr0: {sim.crl[0].get_range()}")
245 inp
= yield from get_cu_inputs(dec2
, sim
)
247 yield from ALUHelpers
.set_fast_spr1(branch
, dec2
, inp
)
248 yield from ALUHelpers
.set_fast_spr2(branch
, dec2
, inp
)
249 yield from ALUHelpers
.set_cr_a(branch
, dec2
, inp
)
252 if __name__
== "__main__":