1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Cavium, Inc
3  */
4 
5 #include "test.h"
6 
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <inttypes.h>
10 
11 #include <rte_common.h>
12 #include <rte_cycles.h>
13 #include <rte_random.h>
14 #include <rte_reciprocal.h>
15 
16 #define MAX_ITERATIONS	(1ULL << 32)
17 #define DIVIDE_ITER	(1ULL << 28)
18 
19 static int
test_reciprocal_division_perf(void)20 test_reciprocal_division_perf(void)
21 {
22 	int result = 0;
23 	uint32_t divisor_u32 = 0;
24 	uint32_t dividend_u32;
25 	uint64_t divisor_u64 = 0;
26 	uint64_t dividend_u64;
27 	volatile uint32_t nresult_u32;
28 	volatile uint32_t rresult_u32;
29 	volatile uint64_t nresult_u64;
30 	volatile uint64_t rresult_u64;
31 	uint64_t start_cyc;
32 	uint64_t split_cyc;
33 	uint64_t end_cyc;
34 	uint64_t tot_cyc_n = 0;
35 	uint64_t tot_cyc_r = 0;
36 	uint64_t i;
37 	struct rte_reciprocal reci_u32 = {0};
38 	struct rte_reciprocal_u64 reci_u64 = {0};
39 
40 	rte_srand(rte_rdtsc());
41 
42 	printf("Validating unsigned 32bit division.\n");
43 	for (i = 0; i < MAX_ITERATIONS; i++) {
44 		/* Change divisor every DIVIDE_ITER iterations. */
45 		if (i % DIVIDE_ITER == 0) {
46 			divisor_u32 = rte_rand();
47 			reci_u32 = rte_reciprocal_value(divisor_u32);
48 		}
49 
50 		dividend_u32 = rte_rand();
51 
52 		start_cyc = rte_rdtsc();
53 		nresult_u32 = dividend_u32 / divisor_u32;
54 		split_cyc = rte_rdtsc();
55 		rresult_u32 = rte_reciprocal_divide(dividend_u32,
56 				reci_u32);
57 		end_cyc = rte_rdtsc();
58 
59 		tot_cyc_n += split_cyc - start_cyc;
60 		tot_cyc_r += end_cyc - split_cyc;
61 		if (nresult_u32 != rresult_u32) {
62 			printf("Division failed, expected %"PRIu32" "
63 					"result %"PRIu32"",
64 					nresult_u32, rresult_u32);
65 			result = 1;
66 			break;
67 		}
68 	}
69 	printf("32bit Division results:\n");
70 	printf("Total number of cycles normal division     : %"PRIu64"\n",
71 			tot_cyc_n);
72 	printf("Total number of cycles reciprocal division : %"PRIu64"\n",
73 			tot_cyc_r);
74 	if (i != 0) {
75 		printf("Cycles per division(normal) : %3.2f\n",
76 				((double)tot_cyc_n)/i);
77 		printf("Cycles per division(reciprocal) : %3.2f\n\n",
78 				((double)tot_cyc_r)/i);
79 	}
80 
81 	tot_cyc_n = 0;
82 	tot_cyc_r = 0;
83 
84 	printf("Validating unsigned 64bit division.\n");
85 	for (i = 0; i < MAX_ITERATIONS; i++) {
86 		/* Change divisor every DIVIDE_ITER iterations. */
87 		if (i % DIVIDE_ITER == 0) {
88 			divisor_u64 = rte_rand();
89 			reci_u64 = rte_reciprocal_value_u64(divisor_u64);
90 		}
91 
92 		dividend_u64 = rte_rand();
93 
94 		start_cyc = rte_rdtsc();
95 		nresult_u64 = dividend_u64 / divisor_u64;
96 		split_cyc = rte_rdtsc();
97 		rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
98 				&reci_u64);
99 		end_cyc = rte_rdtsc();
100 
101 		tot_cyc_n += split_cyc - start_cyc;
102 		tot_cyc_r += end_cyc - split_cyc;
103 		if (nresult_u64 != rresult_u64) {
104 			printf("Division failed, expected %"PRIu64" "
105 					"result %"PRIu64"",
106 					nresult_u64, rresult_u64);
107 			result = 1;
108 			break;
109 		}
110 	}
111 	printf("64bit Division results:\n");
112 	printf("Total number of cycles normal division     : %"PRIu64"\n",
113 			tot_cyc_n);
114 	printf("Total number of cycles reciprocal division : %"PRIu64"\n",
115 			tot_cyc_r);
116 	if (i != 0) {
117 		printf("Cycles per division(normal) : %3.2f\n",
118 				((double)tot_cyc_n)/i);
119 		printf("Cycles per division(reciprocal) : %3.2f\n\n",
120 				((double)tot_cyc_r)/i);
121 	}
122 	tot_cyc_n = 0;
123 	tot_cyc_r = 0;
124 
125 	printf("Validating unsigned 64bit division with 32bit divisor.\n");
126 	for (i = 0; i < MAX_ITERATIONS; i++) {
127 		/* Change divisor every DIVIDE_ITER iterations. */
128 		if (i % DIVIDE_ITER == 0) {
129 			divisor_u64 = rte_rand() >> 32;
130 			reci_u64 = rte_reciprocal_value_u64(divisor_u64);
131 		}
132 
133 		dividend_u64 = rte_rand();
134 
135 		start_cyc = rte_rdtsc();
136 		nresult_u64 = dividend_u64 / divisor_u64;
137 		split_cyc = rte_rdtsc();
138 		rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
139 				&reci_u64);
140 		end_cyc = rte_rdtsc();
141 
142 		tot_cyc_n += split_cyc - start_cyc;
143 		tot_cyc_r += end_cyc - split_cyc;
144 		if (nresult_u64 != rresult_u64) {
145 			printf("Division failed, expected %"PRIu64" "
146 					"result %"PRIu64"",
147 					nresult_u64, rresult_u64);
148 			result = 1;
149 			break;
150 		}
151 	}
152 
153 	printf("64bit Division results:\n");
154 	printf("Total number of cycles normal division     : %"PRIu64"\n",
155 			tot_cyc_n);
156 	printf("Total number of cycles reciprocal division : %"PRIu64"\n",
157 			tot_cyc_r);
158 	if (i != 0) {
159 		printf("Cycles per division(normal) : %3.2f\n",
160 				((double)tot_cyc_n)/i);
161 		printf("Cycles per division(reciprocal) : %3.2f\n\n",
162 				((double)tot_cyc_r)/i);
163 	}
164 
165 	tot_cyc_n = 0;
166 	tot_cyc_r = 0;
167 
168 	printf("Validating division by power of 2.\n");
169 	for (i = 0; i < 64; i++) {
170 		divisor_u64 = 1ull << i;
171 		reci_u64 = rte_reciprocal_value_u64(divisor_u64);
172 
173 		dividend_u64 = rte_rand();
174 
175 		start_cyc = rte_rdtsc();
176 		nresult_u64 = dividend_u64 / divisor_u64;
177 		split_cyc = rte_rdtsc();
178 		rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
179 				&reci_u64);
180 		end_cyc = rte_rdtsc();
181 
182 		tot_cyc_n += split_cyc - start_cyc;
183 		tot_cyc_r += end_cyc - split_cyc;
184 		if (nresult_u64 != rresult_u64) {
185 			printf("Division 64 failed, %"PRIu64"/%"PRIu64" = "
186 					"expected %"PRIu64" result %"PRIu64"\n",
187 					dividend_u64, divisor_u64,
188 					nresult_u64, rresult_u64);
189 			result = 1;
190 			break;
191 		}
192 	}
193 	printf("64bit Division results:\n");
194 	printf("Total number of cycles normal division     : %"PRIu64"\n",
195 			tot_cyc_n);
196 	printf("Total number of cycles reciprocal division : %"PRIu64"\n",
197 			tot_cyc_r);
198 	if (i != 0) {
199 		printf("Cycles per division(normal) : %3.2f\n",
200 				((double)tot_cyc_n)/i);
201 		printf("Cycles per division(reciprocal) : %3.2f\n",
202 				((double)tot_cyc_r)/i);
203 	}
204 
205 	return result;
206 }
207 
208 REGISTER_TEST_COMMAND(reciprocal_division_perf, test_reciprocal_division_perf);
209