pysvp64db: fix traversal
[openpower-isa.git] / src / openpower / test / bitmanip / bitmanip_cases.py
1 from openpower.insndb.asm import SVP64Asm
2 from openpower.test.common import TestAccumulatorBase, skip_case
3 from openpower.endian import bigendian
4 from openpower.simulator.program import Program
5 from openpower.test.state import ExpectedState
6 from nmutil.sim_util import hash_256
7 from openpower.decoder.isa.caller import SVP64State, CRFields
8 from openpower.util import log
9 import struct
10 import itertools
11
12 def bmatflip(ra):
13 result = 0
14 for j in range(8):
15 for k in range(8):
16 b = (ra >> (63-k*8-j)) & 1
17 result |= b << (63-j*8-k)
18 return result
19
20
21 def crbinlog(bt, ba, bfb):
22 lut = bfb
23 expected = 0
24 checks = (ba, bt) # LUT positions 1<<0=ba 1<<1=bt
25 lut_index = 0
26 for j, check in enumerate(checks):
27 if check & 1:
28 lut_index |= 1<<j
29 lut_index = 3-lut_index # MSB0 inversion
30 if lut & (1<<lut_index):
31 expected = 1
32 return expected
33
34
35 def crfbinlog(bf, bfa, bfb, mask):
36 lut = bfb
37 expected = bf&~mask # start at BF, mask overwrites masked bits only
38 checks = (bfa, bf) # LUT positions 1<<0=bfa 1<<1=bf
39 for i in range(4):
40 lut_index = 0
41 for j, check in enumerate(checks):
42 if check & (1<<i):
43 lut_index |= 1<<j
44 maskbit = (mask >> i) & 0b1
45 lut_index = 3-lut_index # MSB0 inversion
46 if (lut & (1<<lut_index)) and maskbit:
47 expected |= 1<<i
48 return expected
49
50
51 def ternlogi(rc, rt, ra, rb, imm):
52 expected = 0
53 for i in range(64):
54 lut_index = 0
55 if rb & 2 ** i:
56 lut_index |= 2 ** 2
57 if ra & 2 ** i:
58 lut_index |= 2 ** 1
59 if rt & 2 ** i:
60 lut_index |= 2 ** 0
61 if imm & 2 ** lut_index:
62 expected |= 2 ** i
63 return expected
64
65
66 def crternlogi(bt, ba, bb, imm):
67 expected = 0
68 checks = (bb, ba, bt) # LUT positions 1<<0=bb 1<<1=ba 1<<2=bt
69 lut_index = 0
70 for j, check in enumerate(checks):
71 if check & 1:
72 lut_index |= 1<<j
73 lut_index = 7-lut_index # MSB0 inversion
74 if imm & (1<<lut_index):
75 expected |= 1
76 return expected
77
78
79 def crfternlogi(bf, bfa, bfb, imm, mask):
80 expected = bf&~mask # start at BF, mask overwrites masked bits only
81 checks = (bfb, bfa, bf) # LUT positions 1<<0=bfb 1<<1=bfa 1<<2=bf
82 for i in range(4):
83 lut_index = 0
84 for j, check in enumerate(checks):
85 if check & (1<<i):
86 lut_index |= 1<<j
87 maskbit = (mask >> i) & 0b1
88 lut_index = 7-lut_index # MSB0 inversion
89 if (imm & (1<<lut_index)) and maskbit:
90 expected |= 1<<i
91 return expected
92
93
94 class BitManipTestCase(TestAccumulatorBase):
95 def case_gbbd(self):
96 lst = ["gbbd 0, 1"]
97 lst = list(SVP64Asm(lst, bigendian))
98 initial_regs = [0] * 32
99 initial_regs[1] = 0x9231_5897_2083_ffff
100 e = ExpectedState(pc=4)
101 e.intregs[0] = bmatflip(initial_regs[1])
102 e.intregs[1] = initial_regs[1]
103 log("case_gbbd", bin(initial_regs[1]), bin(e.intregs[0]))
104 log("hex", hex(initial_regs[1]), hex(e.intregs[0]))
105
106 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
107
108 def do_case_crternlogi(self, bt, ba, bb, imm):
109 lst = ["crternlogi 0,4,8,%d" % imm]
110 # set up CR to match bt bit 0, ba bit 4, bb bit 8, in MSB0 order
111 # bearing in mind that CRFields.cr is a 64-bit SelectableInt. sigh.
112 cr = CRFields()
113 cr.cr[32+0] = bt
114 cr.cr[32+4] = ba
115 cr.cr[32+8] = bb
116 initial_cr = cr.cr.asint()
117 print("initial cr", bin(initial_cr), bt, ba, bb,
118 "tli", bin(imm), lst)
119
120 lst = list(SVP64Asm(lst, bigendian))
121 e = ExpectedState(pc=4)
122 e.crregs[0] = crternlogi(bt, ba, bb, imm) << 3
123 e.crregs[1] = ba << 3
124 e.crregs[2] = bb << 3
125 self.add_case(Program(lst, bigendian), initial_regs=None, expected=e,
126 initial_cr=initial_cr)
127
128 def case_crternlogi_0(self):
129 self.do_case_crternlogi(0b1,
130 0b1,
131 0b1,
132 0x80)
133
134 def case_crternlogi_random(self):
135 for i in range(100):
136 imm = hash_256(f"crternlogi imm {i}") & 0xFF
137 bt = hash_256(f"crternlogi bt {i}") & 1
138 ba = hash_256(f"crternlogi ba {i}") & 1
139 bb = hash_256(f"crternlogi bb {i}") & 1
140 self.do_case_crternlogi(bt, ba, bb, imm)
141
142 def do_case_crfternlogi(self, bf, bfa, bfb, imm, mask):
143 lst = [f"crfternlogi 3,4,5,%d,%d" % (imm, mask)]
144 # set up CR
145 bf %= 2 ** 4
146 bfa %= 2 ** 4
147 bfb %= 2 ** 4
148 cr = CRFields()
149 cr.crl[3][0:4] = bf
150 cr.crl[4][0:4] = bfa
151 cr.crl[5][0:4] = bfb
152 initial_cr = cr.cr.asint()
153 print("initial cr", bin(initial_cr), bf, bfa, bfb)
154 print("mask tli", bin(mask), bin(imm))
155
156 lst = list(SVP64Asm(lst, bigendian))
157 e = ExpectedState(pc=4)
158 e.crregs[3] = crfternlogi(bf, bfa, bfb, imm, mask)
159 e.crregs[4] = bfa
160 e.crregs[5] = bfb
161 self.add_case(Program(lst, bigendian), initial_regs=None, expected=e,
162 initial_cr=initial_cr)
163
164 def case_crfternlogi_0(self):
165 self.do_case_crfternlogi(0b1111,
166 0b1100,
167 0b1010,
168 0x80, 0b1111)
169
170 def case_crfternlogi_random(self):
171 for i in range(100):
172 imm = hash_256(f"crfternlogi imm {i}") & 0xFF
173 bf = hash_256(f"crfternlogi bf {i}") % 2 ** 4
174 bfa = hash_256(f"crfternlogi bfa {i}") % 2 ** 4
175 bfb = hash_256(f"crfternlogi bfb {i}") % 2 ** 4
176 msk = hash_256(f"crfternlogi msk {i}") % 2 ** 4
177 self.do_case_crfternlogi(bf, bfa, bfb, imm, msk)
178
179 def do_case_crbinlog(self, bt, ba, bfb):
180 lst = ["crbinlog 4,8,0"]
181 # set up CR
182 cr = CRFields()
183 cr.cr[32+4] = bt # BT bit
184 cr.cr[32+8] = ba # BA bit
185 cr.crl[0][0:4] = bfb # BFB *field*
186 lut = bfb
187 initial_cr = cr.cr.asint()
188 print("initial cr", bin(initial_cr), bt, ba, bfb)
189
190 lst = list(SVP64Asm(lst, bigendian))
191 e = ExpectedState(pc=4)
192 e.crregs[1] = crbinlog(bt, ba, bfb) << 3 # overwrites BT
193 e.crregs[2] = ba << 3
194 e.crregs[0] = bfb
195 self.add_case(Program(lst, bigendian), initial_regs=None, expected=e,
196 initial_cr=initial_cr)
197
198 def case_crbinlog_0(self):
199 self.do_case_crbinlog(0b1,
200 0b1,
201 0x8)
202
203 def case_crbinlog_random(self):
204 for i in range(100):
205 bt = hash_256(f"crbinlog bt {i}") % 2
206 ba = hash_256(f"crbinlog ba {i}") % 2
207 bfb = hash_256(f"crbinlog bfb {i}") % 2 ** 4
208 self.do_case_crbinlog(bt, ba, bfb)
209
210 def do_case_crfbinlog(self, bf, bfa, bfb, mask):
211 lst = ["crfbinlog 3,4,5,%d" % mask]
212 # set up CR
213 bf %= 2 ** 4
214 bfa %= 2 ** 4
215 bfb %= 2 ** 4
216 cr = CRFields()
217 cr.crl[3][0:4] = bf
218 cr.crl[4][0:4] = bfa
219 cr.crl[5][0:4] = bfb
220 lut = bfb
221 initial_cr = cr.cr.asint()
222 print("initial cr", bin(initial_cr), bf, bfa, bfb)
223 print("mask lut2", bin(mask), bin(lut))
224
225 lst = list(SVP64Asm(lst, bigendian))
226 e = ExpectedState(pc=4)
227 e.crregs[3] = crfbinlog(bf, bfa, bfb, mask)
228 e.crregs[4] = bfa
229 e.crregs[5] = bfb
230 self.add_case(Program(lst, bigendian), initial_regs=None, expected=e,
231 initial_cr=initial_cr)
232
233 def case_crfbinlog_0(self):
234 self.do_case_crfbinlog(0b1111,
235 0b1100,
236 0x8, 0b1111)
237
238 def case_crfbinlog_random(self):
239 for i in range(100):
240 bf = hash_256(f"crfbinlog bf {i}") % 2 ** 4
241 bfa = hash_256(f"crfbinlog bfa {i}") % 2 ** 4
242 bfb = hash_256(f"crfbinlog bfb {i}") % 2 ** 4
243 msk = hash_256(f"crfbinlog msk {i}") % 2 ** 4
244 self.do_case_crfbinlog(bf, bfa, bfb, msk)
245
246 def do_case_ternlogi(self, rc, rt, ra, rb, imm):
247 rc_dot = "." if rc else ""
248 lst = [f"ternlogi{rc_dot} 3, 4, 5, {imm}"]
249 initial_regs = [0] * 32
250 rt %= 2 ** 64
251 ra %= 2 ** 64
252 rb %= 2 ** 64
253 initial_regs[3] = rt
254 initial_regs[4] = ra
255 initial_regs[5] = rb
256 lst = list(SVP64Asm(lst, bigendian))
257 e = ExpectedState(pc=4)
258 expected = 0
259 for i in range(64):
260 lut_index = 0
261 if rb & 2 ** i:
262 lut_index |= 2 ** 0
263 if ra & 2 ** i:
264 lut_index |= 2 ** 1
265 if rt & 2 ** i:
266 lut_index |= 2 ** 2
267 lut_index = 7-lut_index # MSB0 inversion
268 if imm & 2 ** lut_index:
269 expected |= 2 ** i
270 e.intregs[3] = expected
271 e.intregs[4] = ra
272 e.intregs[5] = rb
273 if rc:
274 if expected & 2 ** 63: # sign extend
275 expected -= 2 ** 64
276 eq = expected == 0
277 gt = expected > 0
278 lt = expected < 0
279 e.crregs[0] = (eq << 1) | (gt << 2) | (lt << 3)
280 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
281
282 def do_case_binlog(self, ra, rb, rc, nh):
283 lst = ["binlog 3, 4, 5, 6, %d" % nh]
284 initial_regs = [0] * 32
285 initial_regs[4] = ra
286 initial_regs[5] = rb
287 initial_regs[6] = rc
288 lut = rc & 0b11111111 # one of two 4-bit LUTs is in 1st 8 bits
289 if nh == 1: # top half (bits 4-7... sigh MSB 56-59) else 0-3 (60-63)
290 lut = lut >> 4
291 lut = lut & 0b1111
292 lst = list(SVP64Asm(lst, bigendian))
293 e = ExpectedState(pc=4)
294 expected = 0
295 for i in range(64):
296 lut_index = 0
297 if rb & 2 ** i:
298 lut_index |= 2 ** 0
299 if ra & 2 ** i:
300 lut_index |= 2 ** 1
301 lut_index = 3-lut_index # MSB0 inversion
302 if lut & 2 ** lut_index:
303 expected |= 2 ** i
304 e.intregs[3] = expected
305 e.intregs[4] = ra
306 e.intregs[5] = rb
307 e.intregs[6] = rc
308 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
309
310 def case_binlog_0(self):
311 self.do_case_binlog(0x8000_0000_FFFF_0000,
312 0x8000_0000_FF00_FF00,
313 0x8, 1)
314 self.do_case_binlog(0x8000_0000_FFFF_0000,
315 0x8000_0000_FF00_FF00,
316 0x8, 0)
317
318 def case_binlog_random(self):
319 for i in range(100):
320 ra = hash_256(f"binlog ra {i}") % 2 ** 64
321 rb = hash_256(f"binlog rb {i}") % 2 ** 64
322 rc = hash_256(f"binlog rc {i}") % 2 ** 8
323 nh = hash_256(f"binlog nh {i}") & 0b1
324 self.do_case_binlog(ra, rb, rc, nh)
325
326 def do_case_grev(self, w, is_imm, ra, rb):
327 bits = 32 if w else 64
328 masked_rb = rb % bits
329 if is_imm:
330 lst = [f"grev{'w' if w else ''}i. 3, 4, {masked_rb}"]
331 else:
332 lst = [f"grev{'w' if w else ''}. 3, 4, 5"]
333 initial_regs = [0] * 32
334 ra %= 2 ** 64
335 rb %= 2 ** 64
336 initial_regs[4] = ra
337 initial_regs[5] = rb
338 lst = list(SVP64Asm(lst, bigendian))
339 e = ExpectedState(pc=4)
340 expected = 0
341 for i in range(bits):
342 dest_bit = i ^ masked_rb
343 if ra & 2 ** i:
344 expected |= 2 ** dest_bit
345 e.intregs[3] = expected
346 e.intregs[4] = ra
347 e.intregs[5] = rb
348 if expected & 2 ** 63: # sign extend
349 expected -= 2 ** 64
350 eq = expected == 0
351 gt = expected > 0
352 lt = expected < 0
353 e.crregs[0] = (eq << 1) | (gt << 2) | (lt << 3)
354 self.add_case(Program(lst, bigendian), initial_regs, expected=e)
355
356 def case_ternlogi_0(self):
357 self.do_case_ternlogi(False,
358 0x8000_0000_FFFF_0000,
359 0x8000_0000_FF00_FF00,
360 0x8000_0000_F0F0_F0F0, 0x80)
361 self.do_case_ternlogi(True,
362 0x8000_0000_FFFF_0000,
363 0x8000_0000_FF00_FF00,
364 0x8000_0000_F0F0_F0F0, 0x80)
365
366 def case_ternlogi_FF(self):
367 self.do_case_ternlogi(False, 0, 0, 0, 0xFF)
368 self.do_case_ternlogi(True, 0, 0, 0, 0xFF)
369
370 def case_ternlogi_random(self):
371 for i in range(100):
372 rc = bool(hash_256(f"ternlogi rc {i}") & 1)
373 imm = hash_256(f"ternlogi imm {i}") & 0xFF
374 rt = hash_256(f"ternlogi rt {i}") % 2 ** 64
375 ra = hash_256(f"ternlogi ra {i}") % 2 ** 64
376 rb = hash_256(f"ternlogi rb {i}") % 2 ** 64
377 self.do_case_ternlogi(rc, rt, ra, rb, imm)
378
379 @skip_case("grev removed -- leaving code for later use in grevlut")
380 def case_grev_random(self):
381 for i in range(100):
382 w = hash_256(f"grev w {i}") & 1
383 is_imm = hash_256(f"grev is_imm {i}") & 1
384 ra = hash_256(f"grev ra {i}") % 2 ** 64
385 rb = hash_256(f"grev rb {i}") % 2 ** 64
386 self.do_case_grev(w, is_imm, ra, rb)
387
388 @skip_case("grev removed -- leaving code for later use in grevlut")
389 def case_grevi_1(self):
390 self.do_case_grev(False, True, 14361919363078703450,
391 8396479064514513069)
392
393 @skip_case("grev removed -- leaving code for later use in grevlut")
394 def case_grevi_2(self):
395 self.do_case_grev(True, True, 397097147229333315, 8326716970539357702)
396
397 @skip_case("grev removed -- leaving code for later use in grevlut")
398 def case_grevi_3(self):
399 self.do_case_grev(True, True, 0xFFFF_FFFF_0000_0000, 6)
400
401 def case_byterev(self):
402 """ brh/brw/brd """
403 options = (("HHHH", "brh"), ("LL", "brw"), ("Q", "brd"))
404 values = (0x0123456789ABCDEF, 0xFEDCBA9876543210)
405 for RS, (pack_str, mnemonic) in itertools.product(values, options):
406 prog = Program(list(SVP64Asm(["%s 3,4" % mnemonic])), bigendian)
407 chunks = struct.unpack("<" + pack_str, struct.pack("<Q", RS))
408 res = struct.unpack("<Q", struct.pack(">" + pack_str, *chunks))[0]
409 with self.subTest(mnemonic=mnemonic, RS=hex(RS), expected=hex(res)):
410 gprs = [0] * 32
411 gprs[4] = RS
412 e = ExpectedState(pc=4, int_regs=gprs)
413 e.intregs[3] = res
414 self.add_case(prog, gprs, expected=e)
415
416 def case_sv_byterev(self):
417 """ sv.brh/brw/brd """
418 options = (("HHHH", "brh"), ("LL", "brw"), ("Q", "brd"))
419 values = range(10)
420 for idx, (pack_str, mnemonic) in itertools.product(values, options):
421 listing = list(SVP64Asm(["sv.%s *10,*20" % mnemonic]))
422 prog = Program(listing, bigendian)
423 VL = 5
424 svstate = SVP64State()
425 svstate.vl = VL
426 svstate.maxvl = VL
427 gprs = [0] * 128
428 for elidx in range(VL):
429 k = "sv.%s %d %d r20" % (mnemonic, idx, elidx)
430 gprs[20 + elidx] = hash_256(k) % 2**64
431 e = ExpectedState(pc=8, int_regs=gprs)
432 for elidx in range(VL):
433 packed = struct.pack("<Q", gprs[20 + elidx])
434 chunks = struct.unpack( "<" + pack_str, packed)
435 packed = struct.pack(">" + pack_str, *chunks)
436 res = struct.unpack("<Q", packed)[0]
437 e.intregs[10 + elidx] = res
438 RS = [hex(gprs[20 + i]) for i in range(VL)],
439 res =[hex(e.intregs[10 + i]) for i in range(VL)]
440 with self.subTest(case_idx=idx, RS_in=RS, expected_RA=res):
441 self.add_case(prog, gprs, expected=e, initial_svstate=svstate)
442
443 def do_case_sv_crternlogi(self, idx, bt, ba, bb, imm):
444 """note for now that this test is LIMITED due to the
445 range of CR EXTRA3 encoding, it can only do CR0 CR4 CR8 CR12 ... CR124
446 therefore BB is marked as *scalar*.
447 see https://bugs.libre-soc.org/show_bug.cgi?id=1034#c11
448 """
449 lst = ["sv.crternlogi *0,*16,31,%d" % imm]
450 # set up CR to match bt bit 0, ba bit 16, bb bit 31, in MSB0 order
451 # bearing in mind that CRFields.cr is a 64-bit SelectableInt. sigh.
452 cr = CRFields()
453 #for i, (t, a, b) in enumerate(zip(bt, ba, bb)):
454 for i, (t, a) in enumerate(zip(bt, ba)):
455 cr.cr[32+i*4+0] = t # *vector* BT
456 cr.cr[32+i*4+16] = a # *vector* BA
457 # XXX cannot do vector yet cr.cr[32+i+32] = bb # *SCALAR* BB
458 cr.cr[32+31] = bb # *SCALAR* BB
459 initial_cr = cr.cr.asint()
460 print("initial cr", bin(initial_cr), bt, ba, bb,
461 "tli", bin(imm), lst)
462 for i in range(8):
463 print("cr field %d" % i, bin(cr.crl[i].asint()))
464
465 lst = list(SVP64Asm(lst, bigendian))
466 e = ExpectedState(pc=8)
467 #for i, (t, a, b) in enumerate(zip(bt, ba, bb)):
468 # ok so remember that you have to do MSB0-to-LSB0 conversion
469 # so subtract 3-0 for vector BT=*0 and BA=*16 (hence n<<3) but 3-3
470 # (hence bb<<0) for BB=31 (the scalar BB)
471 for i, (t, a) in enumerate(zip(bt, ba)):
472 expected = crternlogi(t, a, bb, imm)
473 print("crternlogi expected", i, bin(expected))
474 e.crregs[i+0] &= ~1<<3 # clear vector result bit first
475 e.crregs[i+0] |= expected<<3 # vector result
476 e.crregs[i+4] |= a<<3 # vector input BA
477 e.crregs[7] |= bb<<0 # scalar input BB
478 with self.subTest(case_idx=idx):
479 VL = len(bt)
480 svstate = SVP64State()
481 svstate.vl = VL
482 svstate.maxvl = VL
483 self.add_case(Program(lst, bigendian), initial_regs=None,
484 expected=e,
485 initial_cr=initial_cr,
486 initial_svstate=svstate)
487
488 def case_sv_crternlogi_0(self):
489 self.do_case_sv_crternlogi(0, [1,1,1], [1,0,1], 1, 0x80)
490
491 def case_sv_crternlogi(self):
492 for i in range(100):
493 bt, ba, bb = [], [], []
494 for j in range(3):
495 t = hash_256("crternlogi bt %d %d" % (i, j)) & 1
496 a = hash_256("crternlogi ba %d %d" % (i, j)) & 1
497 b = hash_256("crternlogi bb %d %d" % (i, j)) & 1
498 bt.append(t)
499 ba.append(a)
500 bb.append(b)
501 imm = hash_256("crternlogi imm %d" % (i)) & 0xFF
502 # temporarily do Vector BT, Vector BA, but *scalar* BB
503 self.do_case_sv_crternlogi(i, bt, ba, bb[0], imm)