aboutsummaryrefslogtreecommitdiff
path: root/src/common/cpuinfo/CpuIsaInfo.cpp
blob: c9e39b9a088fc926a12d0aef32e171d383c215f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
/*
 * Copyright (c) 2021-2022, 2024 Arm Limited.
 *
 * SPDX-License-Identifier: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#include "src/common/cpuinfo/CpuIsaInfo.h"

#include "arm_compute/core/Error.h"

#include "src/common/cpuinfo/CpuModel.h"

/* Arm Feature flags */
#define ARM_COMPUTE_CPU_FEATURE_HWCAP_HALF (1 << 1)
#define ARM_COMPUTE_CPU_FEATURE_HWCAP_NEON (1 << 12)

/* Arm64 Feature flags */
#define ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMD     (1 << 1)
#define ARM_COMPUTE_CPU_FEATURE_HWCAP_FPHP      (1 << 9)
#define ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDHP   (1 << 10)
#define ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDDP   (1 << 20)
#define ARM_COMPUTE_CPU_FEATURE_HWCAP_SVE       (1 << 22)
#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVE2     (1 << 1)
#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEI8MM  (1 << 9)
#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEF32MM (1 << 10)
#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEBF16  (1 << 12)
#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_I8MM     (1 << 13)
#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_BF16     (1 << 14)
#define ARM_COMPUTE_CPU_FEATURE_HWCAP2_SME      (1 << 23)

namespace arm_compute
{
namespace cpuinfo
{
namespace
{
inline bool is_feature_supported(uint64_t features, uint64_t feature_mask)
{
    return (features & feature_mask);
}

#if defined(__arm__)
void decode_hwcaps(CpuIsaInfo &isa, const uint32_t hwcaps, const uint32_t hwcaps2)
{
    ARM_COMPUTE_UNUSED(hwcaps2);
    isa.fp16 = false;
    isa.neon = is_feature_supported(hwcaps, ARM_COMPUTE_CPU_FEATURE_HWCAP_NEON);
}
#elif defined(__aarch64__)
void decode_hwcaps(CpuIsaInfo &isa, const uint32_t hwcaps, const uint32_t hwcaps2)
{
    // High-level SIMD support
    isa.neon = is_feature_supported(hwcaps, ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMD);
    isa.sve  = is_feature_supported(hwcaps, ARM_COMPUTE_CPU_FEATURE_HWCAP_SVE);
    isa.sve2 = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVE2);

    // Detection of SME from type HWCAP2 in the auxillary vector
    isa.sme  = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_SME);
    isa.sme2 = isa.sme; // Needs to be set properly

    // Data-type support
    isa.fp16 = is_feature_supported(hwcaps, ARM_COMPUTE_CPU_FEATURE_HWCAP_FPHP | ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDHP);
    isa.bf16 = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_BF16);
    isa.svebf16 = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEBF16);

    // Instruction extensions
    isa.dot      = is_feature_supported(hwcaps, ARM_COMPUTE_CPU_FEATURE_HWCAP_ASIMDDP);
    isa.i8mm     = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_I8MM);
    isa.svei8mm  = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEI8MM);
    isa.svef32mm = is_feature_supported(hwcaps2, ARM_COMPUTE_CPU_FEATURE_HWCAP2_SVEF32MM);
}
#else  /* defined(__aarch64__) */
void decode_hwcaps(CpuIsaInfo &isa, const uint32_t hwcaps, const uint32_t hwcaps2)
{
    ARM_COMPUTE_UNUSED(isa, hwcaps, hwcaps2);
}
#endif /* defined(__aarch64__) */

void decode_regs(CpuIsaInfo    &isa,
                 const uint64_t isar0,
                 const uint64_t isar1,
                 const uint64_t pfr0,
                 const uint64_t pfr1,
                 const uint64_t svefr0)
{
    auto is_supported = [](uint64_t feature_reg, uint8_t feature_pos) -> bool
    { return ((feature_reg >> feature_pos) & 0xf); };

    // High-level SIMD support
    isa.sve  = is_supported(pfr0, 32);
    isa.sve2 = is_supported(svefr0, 0);
    isa.sme  = is_supported(pfr1, 24);
    isa.sme2 = (((pfr1 >> 24) & 0xf) > 1);

    // Data-type support
    isa.fp16    = is_supported(pfr0, 16);
    isa.bf16    = is_supported(isar1, 44);
    isa.svebf16 = is_supported(svefr0, 20);

    // Instruction extensions
    isa.dot      = is_supported(isar0, 44);
    isa.i8mm     = is_supported(isar1, 48);
    isa.svei8mm  = is_supported(svefr0, 44);
    isa.svef32mm = is_supported(svefr0, 52);
}

/** Handle features from allow-listed models in case of problematic kernels
 *
 * @param[in, out] isa   ISA to update
 * @param[in]      model CPU model type
 */
void allowlisted_model_features(CpuIsaInfo &isa, CpuModel model)
{
    if (isa.dot == false)
    {
        isa.dot = model_supports_dot(model);
    }
    if (isa.fp16 == false)
    {
        isa.fp16 = model_supports_fp16(model);
    }
}
} // namespace

CpuIsaInfo init_cpu_isa_from_hwcaps(uint32_t hwcaps, uint32_t hwcaps2, uint32_t midr)
{
    CpuIsaInfo isa;

    decode_hwcaps(isa, hwcaps, hwcaps2);

    const CpuModel model = midr_to_model(midr);
    allowlisted_model_features(isa, model);

    return isa;
}

CpuIsaInfo
init_cpu_isa_from_regs(uint64_t isar0, uint64_t isar1, uint64_t pfr0, uint64_t pfr1, uint64_t svefr0, uint64_t midr)
{
    CpuIsaInfo isa;

    decode_regs(isa, isar0, isar1, pfr0, pfr1, svefr0);

    const CpuModel model = midr_to_model(midr);
    allowlisted_model_features(isa, model);

    return isa;
}
} // namespace cpuinfo
} // namespace arm_compute