pysvp64db: fix traversal
[openpower-isa.git] / src / openpower / decoder / isa / test_caller_svp64_bc.py
1 import unittest
2 from copy import deepcopy
3
4 from nmutil.formaltest import FHDLTestCase
5 from openpower.consts import SVP64CROffs
6 from openpower.decoder.isa.caller import SVP64State
7 from openpower.decoder.isa.test_caller import run_tst
8 from openpower.decoder.selectable_int import SelectableInt
9 from openpower.simulator.program import Program
10 from openpower.insndb.asm import SVP64Asm
11
12
13 class DecoderTestCase(FHDLTestCase):
14
15 def _check_regs(self, sim, expected):
16 for i in range(32):
17 self.assertEqual(sim.gpr(i), SelectableInt(expected[i], 64))
18
19 def test_sv_load_store(self):
20 """>>> lst = ["addi 2, 0, 0x0010",
21 "addi 3, 0, 0x0008",
22 "addi 6, 0, 0x1234",
23 "addi 7, 0, 0x1235",
24 "sv.stw *6, 0(*2)",
25 "sv.lwz *8, 0(*2)"]
26 """
27 lst = SVP64Asm(["addi 2, 0, 0x0010",
28 "addi 3, 0, 0x0008",
29 "addi 6, 0, 0x1234",
30 "addi 7, 0, 0x1235",
31 "sv.stw *6, 0(*2)",
32 "sv.lwz *8, 0(*2)"])
33 lst = list(lst)
34
35 # SVSTATE (in this case, VL=2)
36 svstate = SVP64State()
37 svstate.vl = 2 # VL
38 svstate.maxvl = 2 # MAXVL
39 print("SVSTATE", bin(svstate.asint()))
40
41 with Program(lst, bigendian=False) as program:
42 sim = self.run_tst_program(program, svstate=svstate)
43 print(sim.gpr(1))
44 self.assertEqual(sim.gpr(8), SelectableInt(0x1234, 64))
45 self.assertEqual(sim.gpr(9), SelectableInt(0x1235, 64))
46
47 def test_sv_branch_cond(self):
48 for i in [0, 10]: # , 10]: #[0, 10]:
49 lst = SVP64Asm(
50 [f"addi 1, 0, {i}", # set r1 to i
51 f"addi 2, 0, {i}", # set r2 to i
52 "cmpi cr0, 1, 1, 10", # compare r1 with 10 and store to cr0
53 "cmpi cr1, 1, 2, 10", # compare r2 with 10 and store to cr1
54 "sv.bc 12, *2, 0xc", # beq 0xc -
55 # branch if r1 equals 10 to the nop below
56 "addi 3, 0, 0x1234", # if r1 == 10 this shouldn't execute
57 "or 0, 0, 0"] # branch target
58 )
59 lst = list(lst)
60
61 # SVSTATE (in this case, VL=2)
62 svstate = SVP64State()
63 svstate.vl = 2 # VL
64 svstate.maxvl = 2 # MAXVL
65 print("SVSTATE", bin(svstate.asint()))
66
67 with Program(lst, bigendian=False) as program:
68 sim = self.run_tst_program(program, svstate=svstate)
69 if i == 10:
70 self.assertEqual(sim.gpr(3), SelectableInt(0, 64))
71 else:
72 self.assertEqual(sim.gpr(3), SelectableInt(0x1234, 64))
73
74 def test_sv_branch_cond_all(self):
75 for i in [7, 8, 9]:
76 lst = SVP64Asm(
77 [f"addi 1, 0, {i+1}", # set r1 to i
78 f"addi 2, 0, {i}", # set r2 to i
79 "cmpi cr0, 1, 1, 8", # compare r1 with 10 and store to cr0
80 "cmpi cr1, 1, 2, 8", # compare r2 with 10 and store to cr1
81 "sv.bc/all 12, *1, 0xc", # bgt 0xc - branch if BOTH
82 # r1 AND r2 greater 8 to the nop below
83 "addi 3, 0, 0x1234", # if tests fail this shouldn't execute
84 "or 0, 0, 0"] # branch target
85 )
86 lst = list(lst)
87
88 # SVSTATE (in this case, VL=2)
89 svstate = SVP64State()
90 svstate.vl = 2 # VL
91 svstate.maxvl = 2 # MAXVL
92 print("SVSTATE", bin(svstate.asint()))
93
94 with Program(lst, bigendian=False) as program:
95 sim = self.run_tst_program(program, svstate=svstate)
96 if i == 9:
97 self.assertEqual(sim.gpr(3), SelectableInt(0, 64))
98 else:
99 self.assertEqual(sim.gpr(3), SelectableInt(0x1234, 64))
100
101 def test_sv_branch_cond_all_vlset(self):
102 for i in [7, 8, 9]:
103 lst = SVP64Asm(
104 [f"addi 1, 0, {i+1}", # set r1 to i
105 f"addi 2, 0, {i}", # set r2 to i
106 "cmpi cr0, 1, 1, 8", # compare r1 with 10 and store to cr0
107 "cmpi cr1, 1, 2, 8", # compare r2 with 10 and store to cr1
108 "sv.bc/all/vs 12, *1, 0xc", # bgt 0xc - branch if BOTH
109 # r1 AND r2 greater 8 to the nop below
110 # also truncate VL at the fail-point
111 "addi 3, 0, 0x1234", # if tests fail this shouldn't execute
112 "or 0, 0, 0"] # branch target
113 )
114 lst = list(lst)
115
116 # SVSTATE (in this case, VL=2)
117 svstate = SVP64State()
118 svstate.vl = 2 # VL
119 svstate.maxvl = 2 # MAXVL
120 print("SVSTATE", bin(svstate.asint()))
121
122 with Program(lst, bigendian=False) as program:
123 sim = self.run_tst_program(program, svstate=svstate)
124 if i == 9:
125 self.assertEqual(sim.gpr(3), SelectableInt(0, 64))
126 else:
127 self.assertEqual(sim.gpr(3), SelectableInt(0x1234, 64))
128 print("SVSTATE.vl", bin(svstate.vl))
129 self.assertEqual(svstate.vl, i-7)
130
131 def test_sv_branch_cond_vlset_inv(self):
132 for i in [7, 8, 9]:
133 lst = SVP64Asm(
134 [f"addi 1, 0, {i+1}", # set r1 to i
135 f"addi 2, 0, {i}", # set r2 to i
136 "cmpi cr0, 1, 1, 8", # compare r1 with 8 and store to cr0
137 "cmpi cr1, 1, 2, 8", # compare r2 with 8 and store to cr1
138 "sv.bc/vsb 4, *1, 0xc", # bgt 0xc - branch if BOTH
139 # r1 AND r2 greater 8 to the nop below
140 # also truncate VL at the fail-point
141 "addi 3, 0, 0x1234", # if tests fail this shouldn't execute
142 "or 0, 0, 0"] # branch target
143 )
144 lst = list(lst)
145
146 # SVSTATE (in this case, VL=2)
147 svstate = SVP64State()
148 svstate.vl = 2 # VL
149 svstate.maxvl = 2 # MAXVL
150 print("SVSTATE", bin(svstate.asint()))
151
152 with self.subTest("vlset_inv %d" % i):
153 with Program(lst, bigendian=False) as program:
154 sim = self.run_tst_program(program, svstate=svstate)
155 print("SVSTATE.vl", bin(svstate.vl))
156 if i == 9:
157 self.assertEqual(sim.gpr(3), SelectableInt(0x1234, 64))
158 else:
159 self.assertEqual(sim.gpr(3), SelectableInt(0, 64))
160 self.assertEqual(svstate.vl, i-7)
161
162 def test_sv_branch_cond_ctr_vlset_inv(self):
163 for i in [7, 8, 9]:
164 lst = SVP64Asm(
165 [f"addi 1, 0, {i+1}", # set r1 to i
166 f"addi 2, 0, {i}", # set r2 to i
167 "cmpi cr0, 1, 1, 8", # compare r1 with 8 and store to cr0
168 "cmpi cr1, 1, 2, 8", # compare r2 with 8 and store to cr1
169 "sv.bc/vsb 0, *1, 0xc", # bgt 0xc - branch if BOTH
170 # r1 AND r2 greater 8 to the nop below
171 # also truncate VL at the fail-point
172 "addi 3, 0, 0x1234", # if tests fail this shouldn't execute
173 "or 0, 0, 0"] # branch target
174 )
175 lst = list(lst)
176
177 # SVSTATE (in this case, VL=2)
178 svstate = SVP64State()
179 svstate.vl = 2 # VL
180 svstate.maxvl = 2 # MAXVL
181 print("SVSTATE", bin(svstate.asint()))
182 sprs = {'CTR': i}
183
184 with self.subTest("vlset_ctr_inv %d" % i):
185 with Program(lst, bigendian=False) as program:
186 sim = self.run_tst_program(program, svstate=svstate,
187 initial_sprs=sprs)
188 print("SVSTATE.vl", bin(svstate.vl))
189 print("CTR", sim.spr('CTR').value)
190 if i == 9:
191 self.assertEqual(sim.gpr(3), SelectableInt(0x1234, 64))
192 else:
193 self.assertEqual(sim.gpr(3), SelectableInt(0, 64))
194 self.assertEqual(svstate.vl, i-7)
195
196 def test_sv_branch_ctr(self):
197 """XXX under development, seems to be good.
198 basically this will reduce CTR under a *vector* loop, where BO[0]
199 is 1 so there is no CR-bit-test, and BO[2] is 0 so there is a CTR-zero
200 test. when the CTR-zero test fails the loop is exited, with CTR
201 having been reduced by up to at least VL times. without VLSET
202 mode at the same time (which truncates VL at this same fail-point)
203 however this is not necessarily so useful, but at least the branch
204 occurs with CTR being reduced *at least* by VL.
205 """
206 for i in [1, 2, 3]:
207 lst = SVP64Asm([
208 "sv.bc/ctr/all 16, *0, 0xc", # branch, test CTR, reducing by VL
209 "addi 3, 0, 0x1234", # if tests fail shouldn't execute
210 "or 0, 0, 0" # branch target
211 ])
212 lst = list(lst)
213
214 # SVSTATE (in this case, VL=2)
215 svstate = SVP64State()
216 svstate.vl = 2 # VL
217 svstate.maxvl = 2 # MAXVL
218 print("SVSTATE", bin(svstate.asint()))
219 sprs = {'CTR': i}
220
221 with Program(lst, bigendian=False) as program:
222 sim = self.run_tst_program(program, svstate=svstate,
223 initial_sprs=sprs)
224 sim.gpr.dump()
225 sim.spr.dump()
226 if i != 3:
227 self.assertEqual(sim.gpr(3), SelectableInt(0x1234, 64))
228 self.assertEqual(sim.spr('CTR'), SelectableInt(0, 64))
229 else:
230 self.assertEqual(sim.gpr(3), SelectableInt(0, 64))
231 self.assertEqual(sim.spr('CTR'), SelectableInt(1, 64))
232
233 def test_sv_branch_ctr_loop(self):
234 """this is a branch-ctr-loop demo which shows an (unconditional)
235 decrementing of CTR by VL. BI still has to be set to Vector even
236 though it is unused (BO[0]=1).
237 """
238 maxvl = 4
239 lst = SVP64Asm(
240 [
241 # VL (and r1) = MIN(CTR,MAXVL=4)
242 "setvl 1, 0, %d, 0, 1, 1" % maxvl,
243 "add 2, 2, 1", # for fun accumulate r1 (VL) into r2
244 "sv.bc/all 16, *0, -0x8", # branch, test CTR, reducing by VL
245 ]
246 )
247 lst = list(lst)
248
249 # SVSTATE - set vl and maxvl to 2, they get overridden with setvl
250 svstate = SVP64State()
251 svstate.vl = 2 # VL
252 svstate.maxvl = 2 # MAXVL
253 print("SVSTATE", bin(svstate.asint()))
254 target = 15
255 sprs = {'CTR': target}
256
257 with Program(lst, bigendian=False) as program:
258 sim = self.run_tst_program(program, svstate=svstate,
259 initial_sprs=sprs)
260 sim.gpr.dump()
261 sim.spr.dump()
262 self.assertEqual(sim.spr('CTR'), SelectableInt(0, 64))
263 self.assertEqual(sim.gpr(2), SelectableInt(target, 64))
264 # MAXVL repeatedly subtracted from VL (r1), last loop has remainder
265 self.assertEqual(sim.gpr(1), SelectableInt(target % maxvl, 64))
266
267 def norun_sv_add_cr(self):
268 """>>> lst = ['sv.add. *1, *5, *9'
269 ]
270
271 adds when Rc=1: TODO CRs higher up
272 * 1 = 5 + 9 => 0 = -1+1 CR0=0b100
273 * 2 = 6 + 10 => 0x3334 = 0x2223+0x1111 CR1=0b010
274 """
275 isa = SVP64Asm(['sv.add. *1, *5, *9'
276 ])
277 lst = list(isa)
278 print("listing", lst)
279
280 # initial values in GPR regfile
281 initial_regs = [0] * 32
282 initial_regs[9] = 0xffffffffffffffff
283 initial_regs[10] = 0x1111
284 initial_regs[5] = 0x1
285 initial_regs[6] = 0x2223
286 # SVSTATE (in this case, VL=2)
287 svstate = SVP64State()
288 svstate.vl = 2 # VL
289 svstate.maxvl = 2 # MAXVL
290 print("SVSTATE", bin(svstate.asint()))
291 # copy before running
292 expected_regs = deepcopy(initial_regs)
293 expected_regs[1] = initial_regs[5] + initial_regs[9] # 0x0
294 expected_regs[2] = initial_regs[6] + initial_regs[10] # 0x3334
295
296 with Program(lst, bigendian=False) as program:
297 sim = self.run_tst_program(program, initial_regs, svstate)
298 # XXX TODO, these need to move to higher range (offset)
299 cr0_idx = SVP64CROffs.CR0
300 cr1_idx = SVP64CROffs.CR1
301 CR0 = sim.crl[cr0_idx].get_range().value
302 CR1 = sim.crl[cr1_idx].get_range().value
303 print("CR0", CR0)
304 print("CR1", CR1)
305 self._check_regs(sim, expected_regs)
306 self.assertEqual(CR0, SelectableInt(2, 4))
307 self.assertEqual(CR1, SelectableInt(4, 4))
308
309 def test_sv_branch_vertical_first(self):
310 """this is a branch-vertical-first-loop demo which shows an early
311 branch from vertical-first loop based on the value of CR field bit.
312 """
313 maxvl = 2
314 lst = SVP64Asm(
315 [
316 "setvl 0, 0, %d, 1, 1, 1" % maxvl, # VL = MAXVL = 2, vf=1
317 "sv.cmpi *cr0, 1, *10, 0x10", # compare reg val with immediate
318 "sv.bc 0, *2, 0x10", # jmp if CTR!=0 AND reg not equal to imm
319 "svstep. 27, 0, 1, 0",
320 "bc 4, 3, -0x14", # CR_BI=0, jump to start of loop (sv.cmpi)
321 "or 0, 0, 0", # jump to here if terminate VF loop early
322 ]
323 )
324 lst = list(lst)
325
326 gprs = [0] * 32
327
328 # Two registers filled, but only the first one matters
329 gprs[10] = 0x20
330 gprs[11] = 0x10
331
332 sprs = {'CTR': maxvl}
333
334 with Program(lst, bigendian=False) as program:
335 sim = self.run_tst_program(program,
336 initial_sprs=sprs,
337 initial_regs=gprs)
338 sim.gpr.dump()
339 sim.spr.dump()
340 self.assertEqual(sim.spr('CTR'), SelectableInt(1, 64))
341
342 def run_tst_program(self, prog, initial_regs=None,
343 svstate=None,
344 initial_sprs=None):
345 if initial_regs is None:
346 initial_regs = [0] * 32
347 simulator = run_tst(prog, initial_regs, svstate=svstate,
348 initial_sprs=initial_sprs)
349 simulator.gpr.dump()
350 return simulator
351
352
353 if __name__ == "__main__":
354 unittest.main()