pysvp64db: fix traversal
[openpower-isa.git] / src / openpower / decoder / isa / test_caller_svp64_predication.py
1 import unittest
2 from copy import deepcopy
3
4 from nmutil.formaltest import FHDLTestCase
5 from openpower.decoder.isa.caller import CRFields, SVP64State
6 from openpower.decoder.isa.test_caller import run_tst
7 from openpower.decoder.selectable_int import SelectableInt
8 from openpower.simulator.program import Program
9 from openpower.insndb.asm import SVP64Asm
10
11
12 class DecoderTestCase(FHDLTestCase):
13
14 def _check_regs(self, sim, expected):
15 for i in range(32):
16 self.assertEqual(sim.gpr(i), SelectableInt(expected[i], 64),
17 "reg %d expected %x got %x" %
18 (i, sim.gpr(i).value, expected[i]))
19
20 def tst_sv_load_store(self):
21 lst = SVP64Asm(["addi 1, 0, 0x0010",
22 "addi 2, 0, 0x0008",
23 "addi 5, 0, 0x1234",
24 "addi 6, 0, 0x1235",
25 "sv.stw *5, 0(*1)",
26 "sv.lwz *9, 0(*1)"])
27 lst = list(lst)
28
29 # SVSTATE (in this case, VL=2)
30 svstate = SVP64State()
31 svstate.vl = 2 # VL
32 svstate.maxvl = 2 # MAXVL
33 print("SVSTATE", bin(svstate.asint()))
34
35 with Program(lst, bigendian=False) as program:
36 sim = self.run_tst_program(program, svstate=svstate)
37 print(sim.gpr(1))
38 self.assertEqual(sim.gpr(9), SelectableInt(0x1234, 64))
39 self.assertEqual(sim.gpr(10), SelectableInt(0x1235, 64))
40
41 def test_sv_extsw_intpred(self):
42 # extsb, integer twin-pred mask: source is ~r3 (0b01), dest r3 (0b10)
43 # works as follows, where any zeros indicate "skip element"
44 # - sources are 9 and 10
45 # - dests are 5 and 6
46 # - source mask says "pick first element from source (5)
47 # - dest mask says "pick *second* element from dest (10)
48 #
49 # therefore the operation that's carried out is:
50 # GPR(10) = extsb(GPR(5))
51 #
52 # this is a type of back-to-back VREDUCE and VEXPAND but it applies
53 # to *operations*, not just MVs like in traditional Vector ISAs
54 # ascii graphic:
55 #
56 # reg num 0 1 2 3 4 5 6 7 8 9 10
57 # src ~r3=0b01 Y N
58 # |
59 # +-----+
60 # |
61 # dest r3=0b10 N Y
62
63 isa = SVP64Asm(['sv.extsb/sm=~r3/dm=r3 *5, *9'
64 ])
65 lst = list(isa)
66 print("listing", lst)
67
68 # initial values in GPR regfile
69 initial_regs = [0] * 32
70 initial_regs[3] = 0b10 # predicate mask
71 initial_regs[9] = 0x91 # source ~r3 is 0b01 so this will be used
72 initial_regs[10] = 0x90 # this gets skipped
73 # SVSTATE (in this case, VL=2)
74 svstate = SVP64State()
75 svstate.vl = 2 # VL
76 svstate.maxvl = 2 # MAXVL
77 print("SVSTATE", bin(svstate.asint()))
78 # copy before running
79 expected_regs = deepcopy(initial_regs)
80 expected_regs[5] = 0x0 # dest r3 is 0b10: skip
81 expected_regs[6] = 0xffff_ffff_ffff_ff91 # 2nd bit of r3 is 1
82
83 with Program(lst, bigendian=False) as program:
84 sim = self.run_tst_program(program, initial_regs, svstate)
85 self._check_regs(sim, expected_regs)
86
87 def test_sv_extsw_intpred_dz(self):
88 # extsb, integer twin-pred mask: dest is r3 (0b01), zeroing on dest
89 isa = SVP64Asm(['sv.extsb/dm=r3/dz *5, *9'
90 ])
91 lst = list(isa)
92 print("listing", lst)
93
94 # initial values in GPR regfile
95 initial_regs = [0] * 32
96 initial_regs[3] = 0b01 # predicate mask (dest)
97 initial_regs[5] = 0xfeed # going to be overwritten
98 initial_regs[6] = 0xbeef # going to be overwritten (with zero)
99 initial_regs[9] = 0x91 # dest r3 is 0b01 so this will be used
100 initial_regs[10] = 0x90 # this gets read but the output gets zero'd
101 # SVSTATE (in this case, VL=2)
102 svstate = SVP64State()
103 svstate.vl = 2 # VL
104 svstate.maxvl = 2 # MAXVL
105 print("SVSTATE", bin(svstate.asint()))
106 # copy before running
107 expected_regs = deepcopy(initial_regs)
108 expected_regs[5] = 0xffff_ffff_ffff_ff91 # dest r3 is 0b01: store
109 expected_regs[6] = 0 # 2nd bit of r3 is 1: zero
110
111 with Program(lst, bigendian=False) as program:
112 sim = self.run_tst_program(program, initial_regs, svstate)
113 self._check_regs(sim, expected_regs)
114
115 def test_sv_add_intpred(self):
116 # adds, integer predicated mask r3=0b10
117 # 1 = 5 + 9 => not to be touched (skipped)
118 # 2 = 6 + 10 => 0x3334 = 0x2223+0x1111
119 # reg num 0 1 2 3 4 5 6 7 8 9 10 11
120 # src r3=0b10 N Y N Y
121 # | | | |
122 # +-------+ | add + |
123 # | +-------+ add --+
124 # | |
125 # dest r3=0b10 N Y
126 isa = SVP64Asm(['sv.add/m=r3 *1, *5, *9'
127 ])
128 lst = list(isa)
129 print("listing", lst)
130
131 # initial values in GPR regfile
132 initial_regs = [0] * 32
133 initial_regs[1] = 0xbeef # not to be altered
134 initial_regs[3] = 0b10 # predicate mask
135 initial_regs[9] = 0x1234
136 initial_regs[10] = 0x1111
137 initial_regs[5] = 0x4321
138 initial_regs[6] = 0x2223
139 # SVSTATE (in this case, VL=2)
140 svstate = SVP64State()
141 svstate.vl = 2 # VL
142 svstate.maxvl = 2 # MAXVL
143 print("SVSTATE", bin(svstate.asint()))
144 # copy before running
145 expected_regs = deepcopy(initial_regs)
146 expected_regs[1] = 0xbeef
147 expected_regs[2] = 0x3334
148
149 with Program(lst, bigendian=False) as program:
150 sim = self.run_tst_program(program, initial_regs, svstate)
151 self._check_regs(sim, expected_regs)
152
153 def test_sv_add_cr_pred(self):
154 # adds, CR predicated mask CR4.eq = 1, CR5.eq = 0, invert (ne)
155 # 1 = 5 + 9 => not to be touched (skipped)
156 # 2 = 6 + 10 => 0x3334 = 0x2223+0x1111
157 isa = SVP64Asm(['sv.add/m=ne *1, *5, *9'
158 ])
159 lst = list(isa)
160 print("listing", lst)
161
162 # initial values in GPR regfile
163 initial_regs = [0] * 32
164 initial_regs[1] = 0xbeef # not to be altered
165 initial_regs[9] = 0x1234
166 initial_regs[10] = 0x1111
167 initial_regs[5] = 0x4321
168 initial_regs[6] = 0x2223
169 # SVSTATE (in this case, VL=2)
170 svstate = SVP64State()
171 svstate.vl = 2 # VL
172 svstate.maxvl = 2 # MAXVL
173 print("SVSTATE", bin(svstate.asint()))
174 # copy before running
175 expected_regs = deepcopy(initial_regs)
176 expected_regs[1] = 0xbeef
177 expected_regs[2] = 0x3334
178
179 # set up CR predicate - CR4.eq=1 and CR5.eq=0
180 cr = (0b0010) << ((7-4)*4) # CR4.eq (we hope)
181
182 with Program(lst, bigendian=False) as program:
183 sim = self.run_tst_program(program, initial_regs, svstate,
184 initial_cr=cr)
185 self._check_regs(sim, expected_regs)
186
187 def test_intpred_vcompress(self):
188 # reg num 0 1 2 3 4 5 6 7 8 9 10 11
189 # src r3=0b101 Y N Y
190 # | |
191 # +-------+ |
192 # | +-----------+
193 # | |
194 # dest always Y Y Y
195
196 isa = SVP64Asm(['sv.extsb/sm=r3 *5, *9'])
197 lst = list(isa)
198 print("listing", lst)
199
200 # initial values in GPR regfile
201 initial_regs = [0] * 32
202 initial_regs[3] = 0b101 # predicate mask
203 initial_regs[9] = 0x90 # source r3 is 0b101 so this will be used
204 initial_regs[10] = 0x91 # this gets skipped
205 initial_regs[11] = 0x92 # source r3 is 0b101 so this will be used
206 # SVSTATE (in this case, VL=3)
207 svstate = SVP64State()
208 svstate.vl = 3 # VL
209 svstate.maxvl = 3 # MAXVL
210 print("SVSTATE", bin(svstate.asint()))
211 # copy before running
212 expected_regs = deepcopy(initial_regs)
213 expected_regs[5] = 0xffff_ffff_ffff_ff90 # (from r9)
214 expected_regs[6] = 0xffff_ffff_ffff_ff92 # (from r11)
215 expected_regs[7] = 0x0 # (VL loop runs out before we can use it)
216
217 with Program(lst, bigendian=False) as program:
218 sim = self.run_tst_program(program, initial_regs, svstate)
219 self._check_regs(sim, expected_regs)
220
221 def test_intpred_vexpand(self):
222 # reg num 0 1 2 3 4 5 6 7 8 9 10 11
223 # src always Y Y Y
224 # | |
225 # +-------+ |
226 # | +------+
227 # | |
228 # dest r3=0b101 Y N Y
229
230 isa = SVP64Asm(['sv.extsb/dm=r3 *5, *9'])
231 lst = list(isa)
232 print("listing", lst)
233
234 # initial values in GPR regfile
235 initial_regs = [0] * 32
236 initial_regs[3] = 0b101 # predicate mask
237 initial_regs[9] = 0x90 # source is "always", so this will be used
238 initial_regs[10] = 0x91 # likewise
239 initial_regs[11] = 0x92 # the VL loop runs out before we can use it
240 # SVSTATE (in this case, VL=3)
241 svstate = SVP64State()
242 svstate.vl = 3 # VL
243 svstate.maxvl = 3 # MAXVL
244 print("SVSTATE", bin(svstate.asint()))
245 # copy before running
246 expected_regs = deepcopy(initial_regs)
247 expected_regs[5] = 0xffff_ffff_ffff_ff90 # 1st bit of r3 is 1
248 expected_regs[6] = 0x0 # skip
249 expected_regs[7] = 0xffff_ffff_ffff_ff91 # 3nd bit of r3 is 1
250
251 with Program(lst, bigendian=False) as program:
252 sim = self.run_tst_program(program, initial_regs, svstate)
253 self._check_regs(sim, expected_regs)
254
255 def test_intpred_twinpred(self):
256 # reg num 0 1 2 3 4 5 6 7 8 9 10 11
257 # src r3=0b101 Y N Y
258 # |
259 # +-----+
260 # |
261 # dest ~r3=0b010 N Y N
262
263 isa = SVP64Asm(['sv.extsb/sm=r3/dm=~r3 *5, *9'])
264 lst = list(isa)
265 print("listing", lst)
266
267 # initial values in GPR regfile
268 initial_regs = [0] * 32
269 initial_regs[3] = 0b101 # predicate mask
270 initial_regs[9] = 0x90 # source r3 is 0b101 so this will be used
271 initial_regs[10] = 0x91 # this gets skipped
272 initial_regs[11] = 0x92 # VL loop runs out before we can use it
273 # SVSTATE (in this case, VL=3)
274 svstate = SVP64State()
275 svstate.vl = 3 # VL
276 svstate.maxvl = 3 # MAXVL
277 print("SVSTATE", bin(svstate.asint()))
278 # copy before running
279 expected_regs = deepcopy(initial_regs)
280 expected_regs[5] = 0x0 # dest ~r3 is 0b010: skip
281 expected_regs[6] = 0xffff_ffff_ffff_ff90 # 2nd bit of ~r3 is 1
282 expected_regs[7] = 0x0 # dest ~r3 is 0b010: skip
283
284 with Program(lst, bigendian=False) as program:
285 sim = self.run_tst_program(program, initial_regs, svstate)
286 self._check_regs(sim, expected_regs)
287
288 # checks that we are able to resume in the middle of a VL loop,
289 # after an interrupt, or after the user has updated src/dst step
290 # let's assume the user has prepared src/dst step before running this
291 # vector instruction
292 def test_intpred_reentrant(self):
293 # reg num 0 1 2 3 4 5 6 7 8 9 10 11 12
294 # srcstep=1 v
295 # src r3=0b0101 Y N Y N
296 # : |
297 # + - - + |
298 # : +-------+
299 # : |
300 # dest ~r3=0b1010 N Y N Y
301 # dststep=2 ^
302
303 isa = SVP64Asm(['sv.extsb/sm=r3/dm=~r3 *5, *9'])
304 lst = list(isa)
305 print("listing", lst)
306
307 # initial values in GPR regfile
308 initial_regs = [0] * 32
309 initial_regs[3] = 0b0101 # mask
310 initial_regs[9] = 0x90 # srcstep starts at 2, so this gets skipped
311 initial_regs[10] = 0x91 # skip
312 initial_regs[11] = 0x92 # this will be used
313 initial_regs[12] = 0x93 # skip
314
315 # SVSTATE (in this case, VL=4)
316 svstate = SVP64State()
317 svstate.vl = 4 # VL
318 svstate.maxvl = 4 # MAXVL
319 # set src/dest step on the middle of the loop
320 svstate.srcstep = 1
321 svstate.dststep = 2
322 print("SVSTATE", bin(svstate.asint()))
323 # copy before running
324 expected_regs = deepcopy(initial_regs)
325 expected_regs[5] = 0x0 # skip
326 expected_regs[6] = 0x0 # dststep starts at 3, so this gets skipped
327 expected_regs[7] = 0x0 # skip
328 expected_regs[8] = 0xffff_ffff_ffff_ff92 # this will be used
329
330 with Program(lst, bigendian=False) as program:
331 sim = self.run_tst_program(program, initial_regs, svstate)
332 self._check_regs(sim, expected_regs)
333
334 def test_shift_one_by_r3_dest(self):
335 # reg num 0 1 2 3 4 5 6 7 8 9 10 11
336 # src r30=0b100 N N Y
337 # |
338 # +-----------+
339 # |
340 # dest r3=1: 1<<r3=0b010 N Y N
341
342 isa = SVP64Asm(['sv.extsb/dm=1<<r3/sm=r30 *5, *9'])
343 lst = list(isa)
344 print("listing", lst)
345
346 # initial values in GPR regfile
347 initial_regs = [0] * 32
348 initial_regs[3] = 1 # dest mask = 1<<r3 = 0b010
349 initial_regs[30] = 0b100 # source mask
350 initial_regs[9] = 0x90 # skipped
351 initial_regs[10] = 0x91 # skipped
352 initial_regs[11] = 0x92 # 3rd bit of r30 is 1
353 # SVSTATE (in this case, VL=3)
354 svstate = SVP64State()
355 svstate.vl = 3 # VL
356 svstate.maxvl = 3 # MAXVL
357 print("SVSTATE", bin(svstate.asint()))
358 # copy before running
359 expected_regs = deepcopy(initial_regs)
360 expected_regs[5] = 0x0 # skip
361 expected_regs[6] = 0xffff_ffff_ffff_ff92 # r3 is 1, so this is used
362 expected_regs[7] = 0x0 # skip
363
364 with Program(lst, bigendian=False) as program:
365 sim = self.run_tst_program(program, initial_regs, svstate)
366 self._check_regs(sim, expected_regs)
367
368 def test_shift_one_by_r3_source(self):
369 # reg num 0 1 2 3 4 5 6 7 8 9 10 11
370 # src r3=2: 1<<r3=0b100 N N Y
371 # |
372 # +-----------+
373 # |
374 # dest r30=0b010 N Y N
375
376 isa = SVP64Asm(['sv.extsb/sm=1<<r3/dm=r30 *5, *9'])
377 lst = list(isa)
378 print("listing", lst)
379
380 # initial values in GPR regfile
381 initial_regs = [0] * 32
382 initial_regs[3] = 2 # source mask = 1<<r3 = 0b100
383 initial_regs[30] = 0b010 # dest mask
384 initial_regs[9] = 0x90 # skipped
385 initial_regs[10] = 0x91 # skipped
386 initial_regs[11] = 0x92 # r3 is 2, so this will be used
387 # SVSTATE (in this case, VL=3)
388 svstate = SVP64State()
389 svstate.vl = 3 # VL
390 svstate.maxvl = 3 # MAXVL
391 print("SVSTATE", bin(svstate.asint()))
392 # copy before running
393 expected_regs = deepcopy(initial_regs)
394 expected_regs[5] = 0x0 # skip
395 expected_regs[6] = 0xffff_ffff_ffff_ff92 # 2nd bit of r30 is 1
396 expected_regs[7] = 0x0 # skip
397
398 with Program(lst, bigendian=False) as program:
399 sim = self.run_tst_program(program, initial_regs, svstate)
400 self._check_regs(sim, expected_regs)
401
402 # checks reentrant CR predication
403 def test_crpred_reentrant(self):
404 # reg num 0 1 2 3 4 5 6 7 8 9 10 11 12
405 # srcstep=1 v
406 # src cr4.eq=1 Y N Y N
407 # cr6.eq=1 : |
408 # + - - + |
409 # : +-------+
410 # dest cr5.lt=1 : |
411 # cr7.lt=1 N Y N Y
412 # dststep=2 ^
413
414 isa = SVP64Asm(['sv.extsb/sm=eq/dm=lt *5, *9'])
415 lst = list(isa)
416 print("listing", lst)
417
418 # initial values in GPR regfile
419 initial_regs = [0] * 32
420 initial_regs[9] = 0x90 # srcstep starts at 2, so this gets skipped
421 initial_regs[10] = 0x91 # skip
422 initial_regs[11] = 0x92 # this will be used
423 initial_regs[12] = 0x93 # skip
424
425 cr = CRFields()
426 # set up CR predicate
427 # CR4.eq=1 and CR6.eq=1
428 cr.crl[4][CRFields.EQ] = 1
429 cr.crl[6][CRFields.EQ] = 1
430 # CR5.lt=1 and CR7.lt=1
431 cr.crl[5][CRFields.LT] = 1
432 cr.crl[7][CRFields.LT] = 1
433 # SVSTATE (in this case, VL=4)
434 svstate = SVP64State()
435 svstate.vl = 4 # VL
436 svstate.maxvl = 4 # MAXVL
437 # set src/dest step on the middle of the loop
438 svstate.srcstep = 1
439 svstate.dststep = 2
440 print("SVSTATE", bin(svstate.asint()))
441 # copy before running
442 expected_regs = deepcopy(initial_regs)
443 expected_regs[5] = 0x0 # skip
444 expected_regs[6] = 0x0 # dststep starts at 3, so this gets skipped
445 expected_regs[7] = 0x0 # skip
446 expected_regs[8] = 0xffff_ffff_ffff_ff92 # this will be used
447
448 with Program(lst, bigendian=False) as program:
449 sim = self.run_tst_program(program, initial_regs, svstate,
450 initial_cr=cr.cr.asint())
451 self._check_regs(sim, expected_regs)
452
453 def run_tst_program(self, prog, initial_regs=None,
454 svstate=None,
455 initial_cr=0):
456 if initial_regs is None:
457 initial_regs = [0] * 32
458 simulator = run_tst(prog, initial_regs, svstate=svstate,
459 initial_cr=initial_cr)
460 simulator.gpr.dump()
461 return simulator
462
463
464 if __name__ == "__main__":
465 unittest.main()