add checks for pcdec. once=1
[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, once, src_loc_at=0):
57 # type: (set[str], str, bool, 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 max_count = 1 if once else 8
63 decoded, expected_SO = reference_pcdec(
64 supported_codes, input_bits, max_count=max_count)
65 expected_EQ = len(decoded) == 0
66 expected_RT = int.from_bytes(
67 [int("1" + code, 2) for code in decoded], 'little')
68 decoded_bits_len = len("".join(decoded))
69 expected_ra_used = False
70 RB_val = make_tree(*supported_codes)
71 rev_input_bits = input_bits[::-1]
72 RA_val = 0
73 RA = 0
74 expected_RS = None
75 if len(input_bits) >= 64:
76 RA_val = int(rev_input_bits[:64], 2)
77 RA = 7
78 rev_input_bits = rev_input_bits[64:]
79 expected_ra_used = decoded_bits_len > len(rev_input_bits)
80 if expected_ra_used:
81 expected_RS = (RA_val + 2 ** 64) >> decoded_bits_len
82 RC_val = int("1" + rev_input_bits, 2)
83 if expected_RS is None:
84 expected_RS = RC_val >> decoded_bits_len
85 lst = list(SVP64Asm([f"pcdec. 4,{RA},6,5,{int(once)}"]))
86 gprs = [0] * 32
87 gprs[6] = RB_val
88 if RA:
89 gprs[RA] = RA_val
90 gprs[5] = RC_val
91 e = ExpectedState(pc=4, int_regs=gprs)
92 e.intregs[4] = expected_RT
93 e.intregs[5] = expected_RS
94 e.crregs[0] = expected_ra_used * 8 + expected_EQ * 2 + expected_SO
95 with self.subTest(supported_codes=supported_codes,
96 input_bits=original_input_bits):
97 self.add_case(Program(lst, False), gprs, expected=e,
98 src_loc_at=src_loc_at + 1)
99
100 def case_pcdec_empty(self):
101 self.check_pcdec({CODE_2}, "", False)
102
103 def case_pcdec_empty_once(self):
104 self.check_pcdec({CODE_2}, "", True)
105
106 def case_pcdec_only_one_code(self):
107 self.check_pcdec({CODE_37}, CODE_37, False)
108
109 def case_pcdec_only_one_code_once(self):
110 self.check_pcdec({CODE_37}, CODE_37, True)
111
112 def case_pcdec_short_seq(self):
113 self.check_pcdec(CODES, "_".join([CODE_2, CODE_19, CODE_35]), False)
114
115 def case_pcdec_short_seq_once(self):
116 self.check_pcdec(CODES, "_".join([CODE_2, CODE_19, CODE_35]), True)
117
118 def case_pcdec_medium_seq(self):
119 self.check_pcdec(
120 CODES, "0_11_1001_10101_10111_10111_10101_1001_11_0", False)
121
122 def case_pcdec_medium_seq_once(self):
123 self.check_pcdec(
124 CODES, "0_11_1001_10101_10111_10111_10101_1001_11_0", True)
125
126 def case_pcdec_long_seq(self):
127 self.check_pcdec(CODES,
128 "0_11_1001_10101_10111_10111_10101_1001_11_0"
129 + CODE_37 * 6, False)
130
131 def case_pcdec_long_seq_once(self):
132 self.check_pcdec(CODES,
133 "0_11_1001_10101_10111_10111_10101_1001_11_0"
134 + CODE_37 * 6, True)
135
136 def case_pcdec_invalid_code_at_start(self):
137 self.check_pcdec(CODES, "_".join(["1000", CODE_35]), False)
138
139 def case_pcdec_invalid_code_at_start_once(self):
140 self.check_pcdec(CODES, "_".join(["1000", CODE_35]), True)
141
142 def case_pcdec_invalid_code_after_3(self):
143 self.check_pcdec(CODES, "_".join(
144 [CODE_2, CODE_19, CODE_35, "1000", CODE_35]), False)
145
146 def case_pcdec_invalid_code_after_3_once(self):
147 self.check_pcdec(CODES, "_".join(
148 [CODE_2, CODE_19, CODE_35, "1000", CODE_35]), True)
149
150 def case_pcdec_invalid_code_after_8(self):
151 self.check_pcdec(CODES, "_".join(
152 [CODE_2, CODE_19, *([CODE_35] * 6), "1000", CODE_35]), False)
153
154 def case_pcdec_invalid_code_after_8_once(self):
155 self.check_pcdec(CODES, "_".join(
156 [CODE_2, CODE_19, *([CODE_35] * 6), "1000", CODE_35]), True)
157
158 def case_pcdec_invalid_code_in_rb(self):
159 self.check_pcdec(CODES, "_".join(
160 [CODE_2, CODE_19, "1000", *([CODE_19] * 15)]), False)
161
162 def case_pcdec_invalid_code_in_rb_once(self):
163 self.check_pcdec(CODES, "_".join(
164 [CODE_2, CODE_19, "1000", *([CODE_19] * 15)]), True)
165
166 def case_pcdec_overlong_code(self):
167 self.check_pcdec(CODES, "_".join([CODE_2, CODE_19, "10000000"]), False)
168
169 def case_pcdec_overlong_code_once(self):
170 self.check_pcdec(CODES, "_".join([CODE_2, CODE_19, "10000000"]), True)