4784b72c5a9c254e7e6d343ce25b5ddf6b71e7af
[openpower-isa.git] / src / openpower / test / prefix_codes / prefix_codes_cases.py
1 from openpower.test.common import TestAccumulatorBase
2 from openpower.sv.trans.svp64 import SVP64Asm
3 from openpower.test.state import ExpectedState
4 from openpower.simulator.program import Program
5
6
7 def tree_code(code):
8 # type: (str) -> int
9 retval = 1
10 for bit in code:
11 assert bit in "01"
12 retval = retval * 2 + int(bit)
13 assert retval < 64, "code too long"
14 return retval
15
16
17 def make_tree(*codes):
18 # type: (*str) -> int
19 retval = 0
20 for code in sorted(codes, key=len):
21 for i in range(len(code)):
22 assert retval & (1 << tree_code(code[:i])) == 0, \
23 f"conflicting code: {code} conflicts with {code[:i]}"
24 retval |= 1 << tree_code(code)
25 return retval
26
27
28 def reference_pcdec(supported_codes, input_bits, max_count):
29 # type: (set[str], str, int) -> tuple[list[str], bool]
30 assert input_bits.lstrip("01") == "", "input_bits must be binary bits"
31 retval = []
32 current_code = ""
33 overflow = False
34 for bit in input_bits:
35 current_code += bit
36 if len(current_code) > 6:
37 overflow = True
38 break
39 if current_code in supported_codes:
40 retval.append(current_code)
41 current_code = ""
42 if len(retval) >= max_count:
43 break
44 return retval, overflow
45
46
47 CODE_2 = "0"
48 CODE_7 = "11"
49 CODE_19 = "1001"
50 CODE_35 = "10101"
51 CODE_37 = "10111"
52 CODES = {CODE_2, CODE_7, CODE_19, CODE_35, CODE_37}
53
54
55 class PrefixCodesCases(TestAccumulatorBase):
56 def check_pcdec(self, supported_codes, input_bits, src_loc_at=0):
57 # type: (set[str], str, int) -> None
58 original_input_bits = input_bits
59 input_bits = input_bits.replace("_", "")
60 assert input_bits.lstrip("01") == "", "input_bits must be binary bits"
61 assert len(input_bits) < 128, "input_bits too long"
62 decoded, expected_SO = reference_pcdec(
63 supported_codes, input_bits, max_count=8)
64 expected_EQ = len(decoded) == 0
65 expected_RT = int.from_bytes(
66 [int("1" + code, 2) for code in decoded], 'little')
67 decoded_bits_len = len("".join(decoded))
68 expected_rb_used = False
69 RB_val = make_tree(*supported_codes)
70 rev_input_bits = input_bits[::-1]
71 RA_val = 0
72 RA = 0
73 expected_RS = None
74 if len(input_bits) >= 64:
75 RA_val = int(rev_input_bits[:64], 2)
76 RA = 7
77 rev_input_bits = rev_input_bits[64:]
78 expected_rb_used = decoded_bits_len > len(rev_input_bits)
79 if expected_rb_used:
80 expected_RS = (RA_val + 2 ** 64) >> decoded_bits_len
81 RC_val = int("1" + rev_input_bits, 2)
82 if expected_RS is None:
83 expected_RS = RC_val >> decoded_bits_len
84 lst = list(SVP64Asm([f"pcdec. 4,{RA},6,5,0"]))
85 gprs = [0] * 32
86 gprs[6] = RB_val
87 if RA:
88 gprs[RA] = RA_val
89 gprs[5] = RC_val
90 e = ExpectedState(pc=4, int_regs=gprs)
91 e.intregs[4] = expected_RT
92 e.intregs[5] = expected_RS
93 e.crregs[0] = expected_rb_used * 8 + expected_EQ * 2 + expected_SO
94 with self.subTest(supported_codes=supported_codes,
95 input_bits=original_input_bits):
96 self.add_case(Program(lst, False), gprs, expected=e,
97 src_loc_at=src_loc_at + 1)
98
99 def case_pcdec_empty(self):
100 self.check_pcdec({CODE_2}, "")
101
102 def case_pcdec_only_one_code(self):
103 self.check_pcdec({CODE_37}, CODE_37)
104
105 def case_pcdec_short_seq(self):
106 self.check_pcdec(CODES, "_".join([CODE_2, CODE_19, CODE_35]))
107
108 def case_pcdec_medium_seq(self):
109 self.check_pcdec(CODES, "0_11_1001_10101_10111_10111_10101_1001_11_0")
110
111 def case_pcdec_long_seq(self):
112 self.check_pcdec(CODES,
113 "0_11_1001_10101_10111_10111_10101_1001_11_0"
114 + CODE_37 * 6)
115
116 def case_pcdec_invalid_code_at_start(self):
117 self.check_pcdec(CODES, "_".join(["1000", CODE_35]))
118
119 def case_pcdec_invalid_code_after_3(self):
120 self.check_pcdec(CODES, "_".join(
121 [CODE_2, CODE_19, CODE_35, "1000", CODE_35]))
122
123 def case_pcdec_invalid_code_after_8(self):
124 self.check_pcdec(CODES, "_".join(
125 [CODE_2, CODE_19, *([CODE_35] * 6), "1000", CODE_35]))
126
127 def case_pcdec_invalid_code_in_rb(self):
128 self.check_pcdec(CODES, "_".join(
129 [CODE_2, CODE_19, "1000", *([CODE_19] * 15)]))
130
131 def case_pcdec_overlong_code(self):
132 self.check_pcdec(CODES, "_".join([CODE_2, CODE_19, "10000000"]))