Line |
Branch |
Exec |
Source |
1 |
|
|
// SPDX-FileCopyrightText: 2023 - 2025 Arm Limited and/or its affiliates <open-source-office@arm.com> |
2 |
|
|
// |
3 |
|
|
// SPDX-License-Identifier: Apache-2.0 |
4 |
|
|
|
5 |
|
|
#ifndef KLEIDICV_DISPATCH_H |
6 |
|
|
#define KLEIDICV_DISPATCH_H |
7 |
|
|
|
8 |
|
|
#include "kleidicv/config.h" |
9 |
|
|
|
10 |
|
|
#if KLEIDICV_ENABLE_SME2 || KLEIDICV_ENABLE_SME || KLEIDICV_ENABLE_SVE2 |
11 |
|
|
|
12 |
|
|
#include <cstdint> |
13 |
|
|
#include <type_traits> |
14 |
|
|
|
15 |
|
|
#ifdef __APPLE__ |
16 |
|
|
|
17 |
|
|
#include <sys/sysctl.h> |
18 |
|
|
|
19 |
|
|
namespace KLEIDICV_TARGET_NAMESPACE { |
20 |
|
|
|
21 |
|
|
static bool query_sysctl(const char* attribute_name) { |
22 |
|
|
uint64_t attribute_value = 0; |
23 |
|
|
size_t max_attribute_size = sizeof(attribute_value); |
24 |
|
|
if (sysctlbyname(attribute_name, &attribute_value, &max_attribute_size, NULL, |
25 |
|
|
0)) { |
26 |
|
|
return false; |
27 |
|
|
} |
28 |
|
|
|
29 |
|
|
return attribute_value; |
30 |
|
|
} |
31 |
|
|
|
32 |
|
|
#if KLEIDICV_ENABLE_SVE2 |
33 |
|
|
#define KLEIDICV_SVE2_RESOLVE(sve2_impl) \ |
34 |
|
|
if (!std::is_null_pointer_v<decltype(sve2_impl)> && \ |
35 |
|
|
KLEIDICV_TARGET_NAMESPACE::query_sysctl("hw.optional.arm.FEAT_SVE2")) { \ |
36 |
|
|
return sve2_impl; \ |
37 |
|
|
} |
38 |
|
|
#else |
39 |
|
|
#define KLEIDICV_SVE2_RESOLVE(x) |
40 |
|
|
#endif // KLEIDICV_ENABLE_SVE2 |
41 |
|
|
|
42 |
|
|
#if KLEIDICV_ENABLE_SME |
43 |
|
|
#define KLEIDICV_SME_RESOLVE(sme_impl) \ |
44 |
|
|
if (!std::is_null_pointer_v<decltype(sme_impl)> && \ |
45 |
|
|
KLEIDICV_TARGET_NAMESPACE::query_sysctl("hw.optional.arm.FEAT_SME")) { \ |
46 |
|
|
return sme_impl; \ |
47 |
|
|
} |
48 |
|
|
#else |
49 |
|
|
#define KLEIDICV_SME_RESOLVE(x) |
50 |
|
|
#endif // KLEIDICV_ENABLE_SME |
51 |
|
|
|
52 |
|
|
#if KLEIDICV_ENABLE_SME2 |
53 |
|
|
#define KLEIDICV_SME2_RESOLVE(sme2_impl) \ |
54 |
|
|
if (!std::is_null_pointer_v<decltype(sme2_impl)> && \ |
55 |
|
|
KLEIDICV_TARGET_NAMESPACE::query_sysctl("hw.optional.arm.FEAT_SME2")) { \ |
56 |
|
|
return sme2_impl; \ |
57 |
|
|
} |
58 |
|
|
#else |
59 |
|
|
#define KLEIDICV_SME2_RESOLVE(x) |
60 |
|
|
#endif // KLEIDICV_ENABLE_SME2 |
61 |
|
|
|
62 |
|
|
} // namespace KLEIDICV_TARGET_NAMESPACE |
63 |
|
|
|
64 |
|
|
#define KLEIDICV_MULTIVERSION_C_API(api_name, neon_impl, sve2_impl, sme_impl, \ |
65 |
|
|
sme2_impl) \ |
66 |
|
|
static decltype(neon_impl) api_name##_resolver() { \ |
67 |
|
|
KLEIDICV_SME2_RESOLVE(sme2_impl); \ |
68 |
|
|
KLEIDICV_SME_RESOLVE(sme_impl); \ |
69 |
|
|
KLEIDICV_SVE2_RESOLVE(sve2_impl); \ |
70 |
|
|
return neon_impl; \ |
71 |
|
|
} \ |
72 |
|
|
extern "C" { \ |
73 |
|
|
decltype(neon_impl) api_name = api_name##_resolver(); \ |
74 |
|
|
} |
75 |
|
|
|
76 |
|
|
#else // __APPLE__ |
77 |
|
|
|
78 |
|
|
#include <sys/auxv.h> |
79 |
|
|
namespace KLEIDICV_TARGET_NAMESPACE { |
80 |
|
|
|
81 |
|
|
using HwCapTy = uint64_t; |
82 |
|
|
|
83 |
|
|
struct HwCaps final { |
84 |
|
|
HwCapTy hwcap1; |
85 |
|
|
HwCapTy hwcap2; |
86 |
|
|
}; |
87 |
|
|
|
88 |
|
456 |
static inline HwCaps get_hwcaps() { |
89 |
|
456 |
return HwCaps{getauxval(AT_HWCAP), getauxval(AT_HWCAP2)}; |
90 |
|
|
} |
91 |
|
|
|
92 |
|
|
#if KLEIDICV_ENABLE_SVE2 |
93 |
|
327 |
static inline bool hwcaps_has_sve2(HwCaps hwcaps) { |
94 |
|
327 |
return hwcaps.hwcap2 & (1 << 1); |
95 |
|
|
} |
96 |
|
|
|
97 |
|
|
#define KLEIDICV_SVE2_RESOLVE(sve2_impl) \ |
98 |
|
|
if (!std::is_null_pointer_v<decltype(sve2_impl)> && \ |
99 |
|
|
KLEIDICV_TARGET_NAMESPACE::hwcaps_has_sve2(hwcaps)) { \ |
100 |
|
|
return sve2_impl; \ |
101 |
|
|
} |
102 |
|
|
#else |
103 |
|
|
#define KLEIDICV_SVE2_RESOLVE(x) |
104 |
|
|
#endif // KLEIDICV_ENABLE_SVE2 |
105 |
|
|
|
106 |
|
|
#if KLEIDICV_ENABLE_SME |
107 |
|
372 |
static inline bool hwcaps_has_sme(HwCaps hwcaps) { |
108 |
|
372 |
const int kSMEBit = 23; |
109 |
|
744 |
return hwcaps.hwcap2 & (1UL << kSMEBit); |
110 |
|
372 |
} |
111 |
|
|
|
112 |
|
|
#define KLEIDICV_SME_RESOLVE(sme_impl) \ |
113 |
|
|
if (!std::is_null_pointer_v<decltype(sme_impl)> && \ |
114 |
|
|
KLEIDICV_TARGET_NAMESPACE::hwcaps_has_sme(hwcaps)) { \ |
115 |
|
|
return sme_impl; \ |
116 |
|
|
} |
117 |
|
|
#else |
118 |
|
|
#define KLEIDICV_SME_RESOLVE(x) |
119 |
|
|
#endif // KLEIDICV_ENABLE_SME |
120 |
|
|
|
121 |
|
|
#if KLEIDICV_ENABLE_SME2 |
122 |
|
|
static inline bool hwcaps_has_sme2(HwCaps hwcaps) { |
123 |
|
|
const int kSME2Bit = 37; |
124 |
|
|
return hwcaps.hwcap2 & (1UL << kSME2Bit); |
125 |
|
|
} |
126 |
|
|
|
127 |
|
|
#define KLEIDICV_SME2_RESOLVE(sme2_impl) \ |
128 |
|
|
if (!std::is_null_pointer_v<decltype(sme2_impl)> && \ |
129 |
|
|
KLEIDICV_TARGET_NAMESPACE::hwcaps_has_sme2(hwcaps)) { \ |
130 |
|
|
return sme2_impl; \ |
131 |
|
|
} |
132 |
|
|
#else |
133 |
|
|
#define KLEIDICV_SME2_RESOLVE(x) |
134 |
|
|
#endif // KLEIDICV_ENABLE_SME2 |
135 |
|
|
|
136 |
|
|
} // namespace KLEIDICV_TARGET_NAMESPACE |
137 |
|
|
|
138 |
|
|
#define KLEIDICV_MULTIVERSION_C_API(api_name, neon_impl, sve2_impl, sme_impl, \ |
139 |
|
|
sme2_impl) \ |
140 |
|
|
static decltype(neon_impl) api_name##_resolver() { \ |
141 |
|
|
[[maybe_unused]] KLEIDICV_TARGET_NAMESPACE::HwCaps hwcaps = \ |
142 |
|
|
KLEIDICV_TARGET_NAMESPACE::get_hwcaps(); \ |
143 |
|
|
KLEIDICV_SME2_RESOLVE(sme2_impl); \ |
144 |
|
|
KLEIDICV_SME_RESOLVE(sme_impl); \ |
145 |
|
|
KLEIDICV_SVE2_RESOLVE(sve2_impl); \ |
146 |
|
|
return neon_impl; \ |
147 |
|
|
} \ |
148 |
|
|
extern "C" { \ |
149 |
|
|
decltype(neon_impl) api_name = api_name##_resolver(); \ |
150 |
|
|
} |
151 |
|
|
|
152 |
|
|
#endif // __APPLE__ |
153 |
|
|
|
154 |
|
|
#else // KLEIDICV_HAVE_SVE2 || KLEIDICV_HAVE_SME || KLEIDICV_HAVE_SME2 |
155 |
|
|
|
156 |
|
|
#define KLEIDICV_MULTIVERSION_C_API(api_name, neon_impl, sve2_impl, sme_impl, \ |
157 |
|
|
sme2_impl) \ |
158 |
|
|
\ |
159 |
|
|
extern "C" { \ |
160 |
|
|
decltype(neon_impl) api_name = neon_impl; \ |
161 |
|
|
} |
162 |
|
|
|
163 |
|
|
#endif // KLEIDICV_ENABLE_SME2 || KLEIDICV_ENABLE_SME || KLEIDICV_ENABLE_SVE2 |
164 |
|
|
|
165 |
|
|
#if KLEIDICV_ALWAYS_ENABLE_SME2 |
166 |
|
|
#define KLEIDICV_SME2_IMPL_IF(func) func |
167 |
|
|
#else |
168 |
|
|
#define KLEIDICV_SME2_IMPL_IF(func) nullptr |
169 |
|
|
#endif // KLEIDICV_ALWAYS_ENABLE_SME2 |
170 |
|
|
|
171 |
|
|
#if KLEIDICV_ALWAYS_ENABLE_SME |
172 |
|
|
#define KLEIDICV_SME_IMPL_IF(func) func |
173 |
|
|
#else |
174 |
|
|
#define KLEIDICV_SME_IMPL_IF(func) nullptr |
175 |
|
|
#endif // KLEIDICV_ALWAYS_ENABLE_SME |
176 |
|
|
|
177 |
|
|
#if KLEIDICV_ALWAYS_ENABLE_SVE2 |
178 |
|
|
#define KLEIDICV_SVE2_IMPL_IF(func) func |
179 |
|
|
#else |
180 |
|
|
#define KLEIDICV_SVE2_IMPL_IF(func) nullptr |
181 |
|
|
#endif // KLEIDICV_ALWAYS_ENABLE_SVE2 |
182 |
|
|
|
183 |
|
|
#endif // KLEIDICV_DISPATCH_H |
184 |
|
|
|