2e4d7a8928559b6a167f0cd3e9ffbb552dd7ab2e
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
)
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
.regfile
.regfiles
import FastRegs
17 from soc
.config
.endian
import bigendian
19 from soc
.fu
.test
.common
import TestAccumulatorBase
, TestCase
, ALUHelpers
20 from soc
.fu
.branch
.pipeline
import BranchBasePipe
21 from soc
.fu
.branch
.pipe_data
import BranchPipeSpec
24 from soc
.regfile
.util
import fast_reg_to_spr
# HACK!
27 def get_rec_width(rec
):
29 # Setup random inputs for dut.op
36 def get_cu_inputs(dec2
, sim
):
37 """naming (res) must conform to BranchFunctionUnit input regspec
42 #res['cia'] = sim.pc.CIA.value
44 yield from ALUHelpers
.get_sim_fast_spr1(res
, sim
, dec2
)
45 yield from ALUHelpers
.get_sim_fast_spr2(res
, sim
, dec2
)
46 yield from ALUHelpers
.get_sim_cr_a(res
, sim
, dec2
)
48 print("get inputs", res
)
52 class BranchTestCase(TestAccumulatorBase
):
54 def case_0_regression_unconditional(self
):
56 imm
= random
.randrange(-1 << 23, (1 << 23)-1) * 4
58 initial_regs
= [0] * 32
59 self
.add_case(Program(lst
, bigendian
), initial_regs
)
61 def case_unconditional(self
):
62 choices
= ["b", "ba", "bl", "bla"]
64 choice
= random
.choice(choices
)
65 imm
= random
.randrange(-1 << 23, (1 << 23)-1) * 4
66 lst
= [f
"{choice} {imm}"]
67 initial_regs
= [0] * 32
68 self
.add_case(Program(lst
, bigendian
), initial_regs
)
72 bc
= random
.randrange(-1 << 13, (1 << 13)-1) * 4
73 bo
= random
.choice([0b01100, 0b00100, 0b10100])
74 bi
= random
.randrange(0, 31)
75 cr
= random
.randrange(0, (1 << 32)-1)
76 lst
= [f
"bc {bo}, {bi}, {bc}"]
77 initial_regs
= [0] * 32
78 self
.add_case(Program(lst
, bigendian
), initial_cr
=cr
)
80 def case_bc_ctr(self
):
82 bc
= random
.randrange(-1 << 13, (1 << 13)-1) * 4
83 bo
= random
.choice([0, 2, 8, 10, 16, 18])
84 bi
= random
.randrange(0, 31)
85 cr
= random
.randrange(0, (1 << 32)-1)
86 ctr
= random
.randint(0, (1 << 32)-1)
87 lst
= [f
"bc {bo}, {bi}, {bc}"]
88 initial_sprs
= {9: SelectableInt(ctr
, 64)}
89 self
.add_case(Program(lst
, bigendian
),
90 initial_sprs
=initial_sprs
,
93 def case_bc_reg(self
):
94 # XXX: bcctr and bcctrl time out (irony: they're counters)
95 choices
= ["bclr", "bclrl", "bcctr", "bcctrl", "bctar", "bctarl"]
98 bh
= random
.randrange(0, 3)
99 bo
= random
.choice([4, 12])
100 bi
= random
.randrange(0, 31)
101 cr
= random
.randrange(0, (1 << 32)-1)
102 ctr
= random
.randint(0, (1 << 32)-1)
103 lr
= random
.randint(0, (1 << 64)-1) & ~
3
104 tar
= random
.randint(0, (1 << 64)-1) & ~
3
105 lst
= [f
"{insn} {bo}, {bi}, {bh}"]
106 initial_sprs
= {9: SelectableInt(ctr
, 64),
107 8: SelectableInt(lr
, 64),
108 815: SelectableInt(tar
, 64)}
109 self
.add_case(Program(lst
, bigendian
),
110 initial_sprs
=initial_sprs
,
113 def case_bc_microwatt_1_regression(self
):
114 """bc found to be testing ctr rather than (ctr-1)
115 11fb4: 08 00 49 40 bc 2,4*cr2+gt,0x11fbc
116 cr_file.vhdl:83:13:@136835ns:(report note): Reading CR 33209703
119 initial_regs
= [0] * 32
121 self
.add_case(Program(lst
, bigendian
), initial_regs
,
124 def case_bc_microwatt_2_regression(self
):
125 """modified version, set CTR=1 so that it hits zero in BC
128 initial_regs
= [0] * 32
131 initial_sprs
= {9: SelectableInt(ctr
, 64),
133 self
.add_case(Program(lst
, bigendian
), initial_regs
,
134 initial_sprs
=initial_sprs
,
137 def case_ilang(self
):
138 pspec
= BranchPipeSpec(id_wid
=2)
139 alu
= BranchBasePipe(pspec
)
140 vl
= rtlil
.convert(alu
, ports
=alu
.ports())
141 with
open("branch_pipeline.il", "w") as f
:
145 class TestRunner(unittest
.TestCase
):
147 test_data
= BranchTestCase().test_data
150 instruction
= Signal(32)
153 opkls
= BranchPipeSpec
.opsubsetkls
155 m
.submodules
.pdecode2
= pdecode2
= PowerDecode2(None, opkls
, fn_name
)
156 pdecode
= pdecode2
.dec
158 pspec
= BranchPipeSpec(id_wid
=2)
159 m
.submodules
.branch
= branch
= BranchBasePipe(pspec
)
161 comb
+= branch
.p
.data_i
.ctx
.op
.eq_from_execute1(pdecode2
.e
)
162 comb
+= branch
.p
.valid_i
.eq(1)
163 comb
+= branch
.n
.ready_i
.eq(1)
164 comb
+= pdecode2
.dec
.raw_opcode_in
.eq(instruction
)
170 for test
in test_data
:
172 program
= test
.program
173 with self
.subTest(test
.name
):
174 simulator
= ISA(pdecode2
, test
.regs
, test
.sprs
, test
.cr
,
178 simulator
.set_pc(initial_cia
)
179 gen
= program
.generate_instructions()
181 zip(gen
, program
.assembly
.splitlines()))
183 pc
= simulator
.pc
.CIA
.value
184 msr
= simulator
.msr
.value
185 index
= (pc
- initial_cia
)//4
186 while index
< len(instructions
) and index
>= 0:
188 ins
, code
= instructions
[index
]
190 print("0x{:X}".format(ins
& 0xffffffff))
193 # ask the decoder to decode this binary data (endian'd)
195 yield pdecode2
.dec
.bigendian
.eq(bigendian
)
196 yield pdecode2
.state
.msr
.eq(msr
) # set MSR in pdecode2
197 yield pdecode2
.state
.pc
.eq(pc
) # set PC in pdecode2
198 yield instruction
.eq(ins
) # raw binary instr.
199 # note, here, the op will need further decoding in order
200 # to set the correct SPRs on SPR1/2/3. op_bc* require
201 # spr1 to be set to CTR, op_bctar require spr2 to be
202 # set to TAR, op_bclr* require spr2 to be set to LR.
203 # if op_sc*, op_rf* and op_hrfid are to be added here
204 # then additional op-decoding is required, accordingly
206 lk
= yield pdecode2
.e
.do
.lk
208 yield from self
.set_inputs(branch
, pdecode2
, simulator
)
209 fn_unit
= yield pdecode2
.e
.do
.fn_unit
210 self
.assertEqual(fn_unit
, Function
.BRANCH
.value
, code
)
213 opname
= code
.split(' ')[0]
214 prev_nia
= simulator
.pc
.NIA
.value
215 yield from simulator
.call(opname
)
216 pc
= simulator
.pc
.CIA
.value
217 msr
= simulator
.msr
.value
218 index
= (pc
- initial_cia
)//4
220 yield from self
.assert_outputs(branch
, pdecode2
,
224 sim
.add_sync_process(process
)
225 with sim
.write_vcd("branch_simulator.vcd"):
228 def assert_outputs(self
, branch
, dec2
, sim
, prev_nia
, code
):
229 branch_taken
= yield branch
.n
.data_o
.nia
.ok
230 sim_branch_taken
= prev_nia
!= sim
.pc
.CIA
231 self
.assertEqual(branch_taken
, sim_branch_taken
, code
)
233 branch_addr
= yield branch
.n
.data_o
.nia
.data
234 print(f
"real: {branch_addr:x}, sim: {sim.pc.CIA.value:x}")
235 self
.assertEqual(branch_addr
, sim
.pc
.CIA
.value
, code
)
237 # TODO: check write_fast1 as well (should contain CTR)
239 # TODO: this should be checking write_fast2
240 lk
= yield dec2
.e
.do
.lk
241 branch_lk
= yield branch
.n
.data_o
.lr
.ok
242 self
.assertEqual(lk
, branch_lk
, code
)
244 branch_lr
= yield branch
.n
.data_o
.lr
.data
245 self
.assertEqual(sim
.spr
['LR'], branch_lr
, code
)
247 def set_inputs(self
, branch
, dec2
, sim
):
248 print(f
"cr0: {sim.crl[0].get_range()}")
250 inp
= yield from get_cu_inputs(dec2
, sim
)
252 yield from ALUHelpers
.set_fast_spr1(branch
, dec2
, inp
)
253 yield from ALUHelpers
.set_fast_spr2(branch
, dec2
, inp
)
254 yield from ALUHelpers
.set_cr_a(branch
, dec2
, inp
)
257 if __name__
== "__main__":