xref: /dpdk/app/test/test_ptr_compress.c (revision 077596a4b0776d98c58787529a4858de69e605c7)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2024 Arm Limited
3  */
4 
5 #include "test.h"
6 #include <stdint.h>
7 #include <string.h>
8 
9 #include <rte_ptr_compress.h>
10 
11 #define MAX_ALIGN_EXPONENT 3
12 #define MAX_PTRS 16
13 #define NUM_BASES 2
14 #define NUM_REGIONS 4
15 #define MAX_32BIT_REGION ((uint64_t)UINT32_MAX + 1)
16 #define MAX_16BIT_REGION (UINT16_MAX + 1)
17 
18 static int
test_ptr_compress_params(void * base,uint64_t mem_sz,unsigned int align_exp,unsigned int num_ptrs,bool use_32_bit)19 test_ptr_compress_params(
20 	void *base,
21 	uint64_t mem_sz,
22 	unsigned int align_exp,
23 	unsigned int num_ptrs,
24 	bool use_32_bit)
25 {
26 	unsigned int i;
27 	unsigned int align = 1 << align_exp;
28 	void *ptrs[MAX_PTRS] = {0};
29 	void *ptrs_out[MAX_PTRS] = {0};
30 	uint32_t offsets32[MAX_PTRS] = {0};
31 	uint16_t offsets16[MAX_PTRS] = {0};
32 
33 	for (i = 0; i < num_ptrs; i++) {
34 		/* make pointers point at memory in steps of align */
35 		/* alternate steps from the start and end of memory region */
36 		if ((i & 1) == 1)
37 			ptrs[i] = (char *)base + mem_sz - i * align;
38 		else
39 			ptrs[i] = (char *)base + i * align;
40 	}
41 
42 	if (use_32_bit) {
43 		rte_ptr_compress_32_shift(
44 				base, ptrs, offsets32, num_ptrs, align_exp);
45 		rte_ptr_decompress_32_shift(base, offsets32, ptrs_out, num_ptrs,
46 				align_exp);
47 	} else {
48 		rte_ptr_compress_16_shift(
49 				base, ptrs, offsets16, num_ptrs, align_exp);
50 		rte_ptr_decompress_16_shift(base, offsets16, ptrs_out, num_ptrs,
51 				align_exp);
52 	}
53 
54 	TEST_ASSERT_BUFFERS_ARE_EQUAL(ptrs, ptrs_out, sizeof(void *) * num_ptrs,
55 		"Decompressed pointers corrupted\nbase pointer: %p, "
56 		"memory region size: %" PRIu64 ", alignment exponent: %u, "
57 		"num of pointers: %u, using %s offsets",
58 		base, mem_sz, align_exp, num_ptrs,
59 		use_32_bit ? "32-bit" : "16-bit");
60 
61 	return 0;
62 }
63 
64 static int
test_ptr_compress(void)65 test_ptr_compress(void)
66 {
67 	unsigned int j, k, n;
68 	int ret = 0;
69 	/* the test is run with multiple memory regions and base addresses */
70 	void * const bases[NUM_BASES] = { (void *)0, (void *)UINT16_MAX };
71 	/* maximum size for pointers aligned by consecutive powers of 2 */
72 	const uint64_t region_sizes_16[NUM_REGIONS] = {
73 		MAX_16BIT_REGION,
74 		MAX_16BIT_REGION * 2,
75 		MAX_16BIT_REGION * 4,
76 		MAX_16BIT_REGION * 8,
77 	};
78 	const uint64_t region_sizes_32[NUM_REGIONS] = {
79 		MAX_32BIT_REGION,
80 		MAX_32BIT_REGION * 2,
81 		MAX_32BIT_REGION * 4,
82 		MAX_32BIT_REGION * 8,
83 	};
84 
85 	/* main test compresses and decompresses arrays of pointers
86 	 * and compares the array before and after to verify that
87 	 * pointers are successfully decompressed
88 	 */
89 
90 	for (j = 0; j < NUM_REGIONS; j++) {
91 		for (k = 0; k < NUM_BASES; k++) {
92 			for (n = 1; n < MAX_PTRS; n++) {
93 				ret |= test_ptr_compress_params(
94 					bases[k],
95 					region_sizes_16[j],
96 					j /* exponent of alignment */,
97 					n,
98 					false
99 				);
100 				ret |= test_ptr_compress_params(
101 					bases[k],
102 					region_sizes_32[j],
103 					j /* exponent of alignment */,
104 					n,
105 					true
106 				);
107 				if (ret != 0)
108 					return ret;
109 			}
110 		}
111 	}
112 
113 	/* verify helper macro computations */
114 
115 	n = RTE_PTR_COMPRESS_BITS_NEEDED_FOR_POINTER_WITHIN_RANGE(0);
116 	TEST_ASSERT_EQUAL(n, 1,
117 			"RTE_PTR_COMPRESS_BITS_NEEDED_FOR_POINTER_WITHIN_RANGE "
118 			"macro computation incorrect\n");
119 
120 	n = RTE_PTR_COMPRESS_BITS_NEEDED_FOR_POINTER_WITHIN_RANGE(1);
121 	TEST_ASSERT_EQUAL(n, 1,
122 			"RTE_PTR_COMPREtopSS_BITS_REQUIRED_TO_STORE_VALUE "
123 			"macro computation incorrect\n");
124 
125 	n = RTE_PTR_COMPRESS_BITS_NEEDED_FOR_POINTER_WITHIN_RANGE(MAX_16BIT_REGION);
126 	TEST_ASSERT_EQUAL(n, 16,
127 			"RTE_PTR_COMPRESS_BITS_NEEDED_FOR_POINTER_WITHIN_RANGE "
128 			"macro computation incorrect\n");
129 
130 	n = RTE_PTR_COMPRESS_BITS_NEEDED_FOR_POINTER_WITHIN_RANGE(MAX_32BIT_REGION);
131 	TEST_ASSERT_EQUAL(n, 32,
132 			"RTE_PTR_COMPRESS_BITS_NEEDED_FOR_POINTER_WITHIN_RANGE "
133 			"macro computation incorrect\n");
134 
135 	n = RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT(0);
136 	TEST_ASSERT_EQUAL(n, 0,
137 			"RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT "
138 			"macro computation incorrect\n");
139 
140 	n = RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT(1);
141 	TEST_ASSERT_EQUAL(n, 0,
142 			"RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT "
143 			"macro computation incorrect\n");
144 
145 	n = RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT(2);
146 	TEST_ASSERT_EQUAL(n, 1,
147 			"RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT "
148 			"macro computation incorrect\n");
149 
150 	n = RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT(3);
151 	TEST_ASSERT_EQUAL(n, 0,
152 			"RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT "
153 			"macro computation incorrect\n");
154 
155 	n = RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT(4);
156 	TEST_ASSERT_EQUAL(n, 2,
157 			"RTE_PTR_COMPRESS_BIT_SHIFT_FROM_ALIGNMENT "
158 			"macro computation incorrect\n");
159 
160 	ret = RTE_PTR_COMPRESS_CAN_COMPRESS_16_SHIFT(MAX_16BIT_REGION, 1);
161 	TEST_ASSERT_EQUAL(ret, 1,
162 			"RTE_PTR_COMPRESS_CAN_COMPRESS_16_SHIFT "
163 			"macro computation incorrect\n");
164 
165 	ret = RTE_PTR_COMPRESS_CAN_COMPRESS_16_SHIFT(MAX_16BIT_REGION + 1, 1);
166 	TEST_ASSERT_EQUAL(ret, 0,
167 			"RTE_PTR_COMPRESS_CAN_COMPRESS_16_SHIFT "
168 			"macro computation incorrect\n");
169 
170 	ret = RTE_PTR_COMPRESS_CAN_COMPRESS_16_SHIFT(MAX_16BIT_REGION + 1, 2);
171 	TEST_ASSERT_EQUAL(ret, 1,
172 			"RTE_PTR_COMPRESS_CAN_COMPRESS_16_SHIFT "
173 			"macro computation incorrect\n");
174 
175 	ret = RTE_PTR_COMPRESS_CAN_COMPRESS_32_SHIFT(MAX_32BIT_REGION, 1);
176 	TEST_ASSERT_EQUAL(ret, 1,
177 			"RTE_PTR_COMPRESS_CAN_COMPRESS_32_SHIFT "
178 			"macro computation incorrect\n");
179 
180 	ret = RTE_PTR_COMPRESS_CAN_COMPRESS_32_SHIFT(MAX_32BIT_REGION + 1, 1);
181 	TEST_ASSERT_EQUAL(ret, 0,
182 			"RTE_PTR_COMPRESS_CAN_COMPRESS_32_SHIFT "
183 			"macro computation incorrect\n");
184 
185 	ret = RTE_PTR_COMPRESS_CAN_COMPRESS_32_SHIFT(MAX_32BIT_REGION + 1, 2);
186 	TEST_ASSERT_EQUAL(ret, 1,
187 			"RTE_PTR_COMPRESS_CAN_COMPRESS_32_SHIFT "
188 			"macro computation incorrect\n");
189 
190 	return 0;
191 }
192 
193 REGISTER_FAST_TEST(ptr_compress_autotest, true, true, test_ptr_compress);
194