1a9de470cSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
2a9de470cSBruce Richardson * Copyright(c) 2017 Cavium, Inc
3a9de470cSBruce Richardson */
4a9de470cSBruce Richardson
5a9de470cSBruce Richardson #include "test.h"
6a9de470cSBruce Richardson
7a9de470cSBruce Richardson #include <stdio.h>
8a9de470cSBruce Richardson #include <unistd.h>
9a9de470cSBruce Richardson #include <inttypes.h>
10a9de470cSBruce Richardson
11a9de470cSBruce Richardson #include <rte_common.h>
12a9de470cSBruce Richardson #include <rte_cycles.h>
13a9de470cSBruce Richardson #include <rte_random.h>
14a9de470cSBruce Richardson #include <rte_reciprocal.h>
15a9de470cSBruce Richardson
16a9de470cSBruce Richardson #define MAX_ITERATIONS (1ULL << 32)
17a9de470cSBruce Richardson #define DIVIDE_ITER (100)
18a9de470cSBruce Richardson
19a9de470cSBruce Richardson static int
test_reciprocal(void)20a9de470cSBruce Richardson test_reciprocal(void)
21a9de470cSBruce Richardson {
22a9de470cSBruce Richardson int result = 0;
23a9de470cSBruce Richardson uint32_t divisor_u32 = 0;
24a9de470cSBruce Richardson uint32_t dividend_u32;
25a9de470cSBruce Richardson uint32_t nresult_u32;
26a9de470cSBruce Richardson uint32_t rresult_u32;
27a9de470cSBruce Richardson uint64_t i, j;
28a9de470cSBruce Richardson uint64_t divisor_u64 = 0;
29a9de470cSBruce Richardson uint64_t dividend_u64;
30a9de470cSBruce Richardson uint64_t nresult_u64;
31a9de470cSBruce Richardson uint64_t rresult_u64;
32a9de470cSBruce Richardson struct rte_reciprocal reci_u32 = {0};
33a9de470cSBruce Richardson struct rte_reciprocal_u64 reci_u64 = {0};
34a9de470cSBruce Richardson
35a9de470cSBruce Richardson printf("Validating unsigned 32bit division.\n");
36a9de470cSBruce Richardson for (i = 0; i < MAX_ITERATIONS; i++) {
37a9de470cSBruce Richardson /* Change divisor every DIVIDE_ITER iterations. */
38a9de470cSBruce Richardson if (i % DIVIDE_ITER == 0) {
39a9de470cSBruce Richardson divisor_u32 = rte_rand();
40a9de470cSBruce Richardson reci_u32 = rte_reciprocal_value(divisor_u32);
41a9de470cSBruce Richardson }
42a9de470cSBruce Richardson
43a9de470cSBruce Richardson dividend_u32 = rte_rand();
44a9de470cSBruce Richardson nresult_u32 = dividend_u32 / divisor_u32;
45a9de470cSBruce Richardson rresult_u32 = rte_reciprocal_divide(dividend_u32,
46a9de470cSBruce Richardson reci_u32);
47a9de470cSBruce Richardson if (nresult_u32 != rresult_u32) {
48a9de470cSBruce Richardson printf("Division failed, %"PRIu32"/%"PRIu32" = "
49a9de470cSBruce Richardson "expected %"PRIu32" result %"PRIu32"\n",
50a9de470cSBruce Richardson dividend_u32, divisor_u32,
51a9de470cSBruce Richardson nresult_u32, rresult_u32);
52a9de470cSBruce Richardson result = 1;
53a9de470cSBruce Richardson break;
54a9de470cSBruce Richardson }
55a9de470cSBruce Richardson }
56a9de470cSBruce Richardson
57a9de470cSBruce Richardson printf("Validating unsigned 64bit division.\n");
58a9de470cSBruce Richardson for (i = 0; i < MAX_ITERATIONS; i++) {
59a9de470cSBruce Richardson /* Change divisor every DIVIDE_ITER iterations. */
60a9de470cSBruce Richardson if (i % DIVIDE_ITER == 0) {
61a9de470cSBruce Richardson divisor_u64 = rte_rand();
62a9de470cSBruce Richardson reci_u64 = rte_reciprocal_value_u64(divisor_u64);
63a9de470cSBruce Richardson }
64a9de470cSBruce Richardson
65a9de470cSBruce Richardson dividend_u64 = rte_rand();
66a9de470cSBruce Richardson nresult_u64 = dividend_u64 / divisor_u64;
67a9de470cSBruce Richardson rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
68a9de470cSBruce Richardson &reci_u64);
69a9de470cSBruce Richardson if (nresult_u64 != rresult_u64) {
70a9de470cSBruce Richardson printf("Division failed, %"PRIu64"/%"PRIu64" = "
71a9de470cSBruce Richardson "expected %"PRIu64" result %"PRIu64"\n",
72a9de470cSBruce Richardson dividend_u64, divisor_u64,
73a9de470cSBruce Richardson nresult_u64, rresult_u64);
74a9de470cSBruce Richardson result = 1;
75a9de470cSBruce Richardson break;
76a9de470cSBruce Richardson }
77a9de470cSBruce Richardson }
78a9de470cSBruce Richardson
79a9de470cSBruce Richardson printf("Validating unsigned 64bit division with 32bit divisor.\n");
80a9de470cSBruce Richardson for (i = 0; i < MAX_ITERATIONS; i++) {
81a9de470cSBruce Richardson /* Change divisor every DIVIDE_ITER iterations. */
82a9de470cSBruce Richardson if (i % DIVIDE_ITER == 0) {
83a9de470cSBruce Richardson divisor_u64 = rte_rand() >> 32;
84a9de470cSBruce Richardson reci_u64 = rte_reciprocal_value_u64(divisor_u64);
85a9de470cSBruce Richardson }
86a9de470cSBruce Richardson
87a9de470cSBruce Richardson dividend_u64 = rte_rand();
88a9de470cSBruce Richardson
89a9de470cSBruce Richardson nresult_u64 = dividend_u64 / divisor_u64;
90a9de470cSBruce Richardson rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
91a9de470cSBruce Richardson &reci_u64);
92a9de470cSBruce Richardson
93a9de470cSBruce Richardson if (nresult_u64 != rresult_u64) {
94a9de470cSBruce Richardson printf("Division failed, %"PRIu64"/%"PRIu64" = "
95a9de470cSBruce Richardson "expected %"PRIu64" result %"PRIu64"\n",
96a9de470cSBruce Richardson dividend_u64, divisor_u64,
97a9de470cSBruce Richardson nresult_u64, rresult_u64);
98a9de470cSBruce Richardson result = 1;
99a9de470cSBruce Richardson break;
100a9de470cSBruce Richardson }
101a9de470cSBruce Richardson }
102a9de470cSBruce Richardson
103a9de470cSBruce Richardson printf("Validating division by power of 2.\n");
104a9de470cSBruce Richardson for (i = 0; i < 32; i++) {
105a9de470cSBruce Richardson divisor_u64 = 1ull << i;
106a9de470cSBruce Richardson reci_u64 = rte_reciprocal_value_u64(divisor_u64);
107a9de470cSBruce Richardson reci_u32 = rte_reciprocal_value((uint32_t)divisor_u64);
108a9de470cSBruce Richardson
109a9de470cSBruce Richardson for (j = 0; j < MAX_ITERATIONS >> 4; j++) {
110a9de470cSBruce Richardson dividend_u64 = rte_rand();
111a9de470cSBruce Richardson
112a9de470cSBruce Richardson nresult_u64 = dividend_u64 / divisor_u64;
113a9de470cSBruce Richardson rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
114a9de470cSBruce Richardson &reci_u64);
115a9de470cSBruce Richardson
116a9de470cSBruce Richardson if (nresult_u64 != rresult_u64) {
117a9de470cSBruce Richardson printf(
118a9de470cSBruce Richardson "Division 64 failed, %"PRIu64"/%"PRIu64" = "
119a9de470cSBruce Richardson "expected %"PRIu64" result %"PRIu64"\n",
120a9de470cSBruce Richardson dividend_u64, divisor_u64,
121a9de470cSBruce Richardson nresult_u64, rresult_u64);
122a9de470cSBruce Richardson result = 1;
123a9de470cSBruce Richardson }
124a9de470cSBruce Richardson
125a9de470cSBruce Richardson nresult_u32 = (dividend_u64 >> 32) / divisor_u64;
126a9de470cSBruce Richardson rresult_u32 = rte_reciprocal_divide(
127a9de470cSBruce Richardson (dividend_u64 >> 32), reci_u32);
128a9de470cSBruce Richardson
129a9de470cSBruce Richardson if (nresult_u32 != rresult_u32) {
130a9de470cSBruce Richardson printf(
131a9de470cSBruce Richardson "Division 32 failed, %"PRIu64"/%"PRIu64" = "
132a9de470cSBruce Richardson "expected %"PRIu64" result %"PRIu64"\n",
133a9de470cSBruce Richardson dividend_u64 >> 32, divisor_u64,
134a9de470cSBruce Richardson nresult_u64, rresult_u64);
135a9de470cSBruce Richardson result = 1;
136a9de470cSBruce Richardson break;
137a9de470cSBruce Richardson }
138a9de470cSBruce Richardson }
139a9de470cSBruce Richardson }
140a9de470cSBruce Richardson
141a9de470cSBruce Richardson for (; i < 64; i++) {
142a9de470cSBruce Richardson divisor_u64 = 1ull << i;
143a9de470cSBruce Richardson reci_u64 = rte_reciprocal_value_u64(divisor_u64);
144a9de470cSBruce Richardson
145a9de470cSBruce Richardson for (j = 0; j < MAX_ITERATIONS >> 4; j++) {
146a9de470cSBruce Richardson dividend_u64 = rte_rand();
147a9de470cSBruce Richardson
148a9de470cSBruce Richardson nresult_u64 = dividend_u64 / divisor_u64;
149a9de470cSBruce Richardson rresult_u64 = rte_reciprocal_divide_u64(dividend_u64,
150a9de470cSBruce Richardson &reci_u64);
151a9de470cSBruce Richardson
152a9de470cSBruce Richardson if (nresult_u64 != rresult_u64) {
153a9de470cSBruce Richardson printf("Division failed, %"PRIu64"/%"PRIu64" = "
154a9de470cSBruce Richardson "expected %"PRIu64" result %"PRIu64"\n",
155a9de470cSBruce Richardson dividend_u64, divisor_u64,
156a9de470cSBruce Richardson nresult_u64, rresult_u64);
157a9de470cSBruce Richardson result = 1;
158a9de470cSBruce Richardson break;
159a9de470cSBruce Richardson }
160a9de470cSBruce Richardson }
161a9de470cSBruce Richardson }
162a9de470cSBruce Richardson
163a9de470cSBruce Richardson return result;
164a9de470cSBruce Richardson }
165a9de470cSBruce Richardson
166*e0a8442cSBruce Richardson REGISTER_PERF_TEST(reciprocal_division, test_reciprocal);
167