1#include "ggml-backend-impl.h"
 2
 3#if defined(__aarch64__)
 4
 5#if defined(__linux__)
 6#include <sys/auxv.h>
 7#elif defined(__APPLE__)
 8#include <sys/sysctl.h>
 9#endif
10
11#if !defined(HWCAP2_SVE2)
12#define HWCAP2_SVE2 (1 << 1)
13#endif
14
15#if !defined(HWCAP2_I8MM)
16#define HWCAP2_I8MM (1 << 13)
17#endif
18
19#if !defined(HWCAP2_SME)
20#define HWCAP2_SME (1 << 23)
21#endif
22
23struct aarch64_features {
24    // has_neon not needed, aarch64 has NEON guaranteed
25    bool has_dotprod     = false;
26    bool has_fp16_va     = false;
27    bool has_sve         = false;
28    bool has_sve2        = false;
29    bool has_i8mm        = false;
30    bool has_sme         = false;
31
32    aarch64_features() {
33#if defined(__linux__)
34        uint32_t hwcap = getauxval(AT_HWCAP);
35        uint32_t hwcap2 = getauxval(AT_HWCAP2);
36
37        has_dotprod = !!(hwcap & HWCAP_ASIMDDP);
38        has_fp16_va = !!(hwcap & HWCAP_FPHP);
39        has_sve     = !!(hwcap & HWCAP_SVE);
40        has_sve2    = !!(hwcap2 & HWCAP2_SVE2);
41        has_i8mm    = !!(hwcap2 & HWCAP2_I8MM);
42        has_sme     = !!(hwcap2 & HWCAP2_SME);
43#elif defined(__APPLE__)
44        int oldp = 0;
45        size_t size = sizeof(oldp);
46
47        if (sysctlbyname("hw.optional.arm.FEAT_DotProd", &oldp, &size, NULL, 0) == 0) {
48            has_dotprod = static_cast<bool>(oldp);
49        }
50
51        if (sysctlbyname("hw.optional.arm.FEAT_I8MM", &oldp, &size, NULL, 0) == 0) {
52            has_i8mm = static_cast<bool>(oldp);
53        }
54
55        if (sysctlbyname("hw.optional.arm.FEAT_SME", &oldp, &size, NULL, 0) == 0) {
56            has_sme = static_cast<bool>(oldp);
57        }
58
59        // Apple apparently does not implement SVE yet
60#endif
61    }
62};
63
64static int ggml_backend_cpu_aarch64_score() {
65    int score = 1;
66    aarch64_features af;
67
68#ifdef GGML_USE_DOTPROD
69    if (!af.has_dotprod) { return 0; }
70    score += 1<<1;
71#endif
72#ifdef GGML_USE_FP16_VECTOR_ARITHMETIC
73    if (!af.has_fp16_va) { return 0; }
74    score += 1<<2;
75#endif
76#ifdef GGML_USE_SVE
77    if (!af.has_sve) { return 0; }
78    score += 1<<3;
79#endif
80#ifdef GGML_USE_MATMUL_INT8
81    if (!af.has_i8mm) { return 0; }
82    score += 1<<4;
83#endif
84#ifdef GGML_USE_SVE2
85    if (!af.has_sve2) { return 0; }
86    score += 1<<5;
87#endif
88#ifdef GGML_USE_SME
89    if (!af.has_sme) { return 0; }
90    score += 1<<6;
91#endif
92
93    return score;
94}
95
96GGML_BACKEND_DL_SCORE_IMPL(ggml_backend_cpu_aarch64_score)
97
98# endif // defined(__aarch64__)