Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/google/cpu_features.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniAffCH <danieleaffinita2000@gmail.com>2022-08-07 23:42:47 +0300
committerGuillaume Chatelet <gchatelet@google.com>2022-11-09 18:47:51 +0300
commit0d00d3fa929627afc144595f886544b23ca9fc82 (patch)
tree94057b89b42e13874f277f055d5348ffdd72c75a
parent4e191a4cc872263c60eb473550e2b7d2965690f9 (diff)
Add RISC-V support
-rw-r--r--CMakeLists.txt5
-rw-r--r--README.md38
-rw-r--r--include/cpuinfo_riscv.h72
-rw-r--r--include/internal/hwcaps.h3
-rw-r--r--scripts/generate_badges.d3
-rw-r--r--src/impl_riscv_linux.c101
-rw-r--r--src/utils/list_cpu_features.c11
-rw-r--r--test/CMakeLists.txt7
-rw-r--r--test/cpuinfo_riscv_test.cc125
9 files changed, 346 insertions, 19 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e2ffbe2..b1677c2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,6 +50,7 @@ set(PROCESSOR_IS_AARCH64 FALSE)
set(PROCESSOR_IS_X86 FALSE)
set(PROCESSOR_IS_POWER FALSE)
set(PROCESSOR_IS_S390X FALSE)
+set(PROCESSOR_IS_RISCV FALSE)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips")
set(PROCESSOR_IS_MIPS TRUE)
@@ -63,6 +64,8 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
set(PROCESSOR_IS_POWER TRUE)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(s390x)")
set(PROCESSOR_IS_S390X TRUE)
+elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^riscv")
+ set(PROCESSOR_IS_RISCV TRUE)
endif()
macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
@@ -84,6 +87,8 @@ macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_ppc.h)
elseif(PROCESSOR_IS_S390X)
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_s390x.h)
+ elseif(PROCESSOR_IS_RISCV)
+ list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_riscv.h)
else()
message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}")
endif()
diff --git a/README.md b/README.md
index f37d29b..9475123 100644
--- a/README.md
+++ b/README.md
@@ -7,12 +7,12 @@ instructions) at runtime.
[comment]: <> (The following lines are generated by "scripts/generate_badges.d" that you can run online https://run.dlang.io/)
-| Os | amd64 | AArch64 | ARM | MIPS | s390x | POWER |
-| :-- | --: | --: | --: | --: | --: | --: |
-| Linux | [![][i1a0]][l1a0]<br/>[![][i1a1]][l1a1] | [![][i1b0]][l1b0]<br/>![][d1] | [![][i1c0]][l1c0]<br/>![][d1] | [![][i1d0]][l1d0]<br/>![][d1] | [![][i1e0]][l1e0]<br/>![][d1] | [![][i1f0]][l1f0]<br/>![][d1] |
-| FreeBSD | [![][i2a0]][l2a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] |
-| MacOS | [![][i3a0]][l3a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] |
-| Windows | [![][i4a0]][l4a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] |
+| Os | amd64 | AArch64 | ARM | MIPS | POWER | RISCV | s390x |
+| :-- | --: | --: | --: | --: | --: | --: | --: |
+| Linux | [![][i1a0]][l1a0]<br/>[![][i1a1]][l1a1] | [![][i1b0]][l1b0]<br/>![][d1] | [![][i1c0]][l1c0]<br/>![][d1] | [![][i1d0]][l1d0]<br/>![][d1] | [![][i1e0]][l1e0]<br/>![][d1] | [![][i1f0]][l1f0]<br/>![][d1] | [![][i1g0]][l1g0]<br/>![][d1] |
+| FreeBSD | [![][i2a0]][l2a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] |
+| MacOS | [![][i3a0]][l3a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] |
+| Windows | [![][i4a0]][l4a0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] | ![][d0]<br/>![][d1] |
[d0]: https://img.shields.io/badge/CMake-N%2FA-lightgrey
[d1]: https://img.shields.io/badge/Bazel-N%2FA-lightgrey
@@ -21,8 +21,9 @@ instructions) at runtime.
[i1b0]: https://img.shields.io/github/workflow/status/google/cpu_features/AArch64%20Linux%20CMake/main?label=CMake
[i1c0]: https://img.shields.io/github/workflow/status/google/cpu_features/ARM%20Linux%20CMake/main?label=CMake
[i1d0]: https://img.shields.io/github/workflow/status/google/cpu_features/MIPS%20Linux%20CMake/main?label=CMake
-[i1e0]: https://img.shields.io/github/workflow/status/google/cpu_features/s390x%20Linux%20CMake/main?label=CMake
-[i1f0]: https://img.shields.io/github/workflow/status/google/cpu_features/POWER%20Linux%20CMake/main?label=CMake
+[i1e0]: https://img.shields.io/github/workflow/status/google/cpu_features/POWER%20Linux%20CMake/main?label=CMake
+[i1f0]: https://img.shields.io/github/workflow/status/google/cpu_features/RISCV%20Linux%20CMake/main?label=CMake
+[i1g0]: https://img.shields.io/github/workflow/status/google/cpu_features/s390x%20Linux%20CMake/main?label=CMake
[i2a0]: https://img.shields.io/github/workflow/status/google/cpu_features/amd64%20FreeBSD%20CMake/main?label=CMake
[i3a0]: https://img.shields.io/github/workflow/status/google/cpu_features/amd64%20MacOS%20CMake/main?label=CMake
[i4a0]: https://img.shields.io/github/workflow/status/google/cpu_features/amd64%20Windows%20CMake/main?label=CMake
@@ -31,8 +32,9 @@ instructions) at runtime.
[l1b0]: https://github.com/google/cpu_features/actions/workflows/aarch64_linux_cmake.yml
[l1c0]: https://github.com/google/cpu_features/actions/workflows/arm_linux_cmake.yml
[l1d0]: https://github.com/google/cpu_features/actions/workflows/mips_linux_cmake.yml
-[l1e0]: https://github.com/google/cpu_features/actions/workflows/s390x_linux_cmake.yml
-[l1f0]: https://github.com/google/cpu_features/actions/workflows/power_linux_cmake.yml
+[l1e0]: https://github.com/google/cpu_features/actions/workflows/power_linux_cmake.yml
+[l1f0]: https://github.com/google/cpu_features/actions/workflows/riscv_linux_cmake.yml
+[l1g0]: https://github.com/google/cpu_features/actions/workflows/s390x_linux_cmake.yml
[l2a0]: https://github.com/google/cpu_features/actions/workflows/amd64_freebsd_cmake.yml
[l3a0]: https://github.com/google/cpu_features/actions/workflows/amd64_macos_cmake.yml
[l4a0]: https://github.com/google/cpu_features/actions/workflows/amd64_windows_cmake.yml
@@ -176,14 +178,14 @@ flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3
<a name="support"></a>
## What's supported
-| | x86³ | AArch64 | ARM | MIPS⁴ | s390x | POWER |
-|---------|:----:|:-------:|:-------:|:-------:|:-------:|:-------:|
-| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ |
-| FreeBSD | yes² | not yet | not yet | not yet | not yet | not yet |
-| MacOs | yes² | not yet | N/A | N/A | no | no |
-| Windows | yes² | not yet | not yet | N/A | N/A | N/A |
-| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | N/A |
-| iOS | N/A | not yet | not yet | N/A | N/A | N/A |
+| | x86³ | AArch64 | ARM | MIPS⁴ | s390x | POWER | RISC-V |
+|---------|:----:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|
+| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ |
+| FreeBSD | yes² | not yet | not yet | not yet | not yet | not yet | N/A |
+| MacOs | yes² | not yet | N/A | N/A | no | no | N/A |
+| Windows | yes² | not yet | not yet | N/A | N/A | N/A | N/A |
+| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | N/A | N/A |
+| iOS | N/A | not yet | not yet | N/A | N/A | N/A | N/A |
1. **Features revealed from Linux.** We gather data from several sources
depending on availability:
diff --git a/include/cpuinfo_riscv.h b/include/cpuinfo_riscv.h
new file mode 100644
index 0000000..fba8804
--- /dev/null
+++ b/include/cpuinfo_riscv.h
@@ -0,0 +1,72 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef CPU_FEATURES_INCLUDE_CPUINFO_RISCV_H_
+#define CPU_FEATURES_INCLUDE_CPUINFO_RISCV_H_
+
+#include "cpu_features_cache_info.h"
+#include "cpu_features_macros.h"
+
+#if !defined(CPU_FEATURES_ARCH_RISCV)
+#error "Including cpuinfo_riscv.h from a non-riscv target."
+#endif
+
+CPU_FEATURES_START_CPP_NAMESPACE
+
+typedef struct {
+ int riscv32 : 1; // Is a 32 bit architecture
+ int riscv64 : 1; // Is a 64 bit architecture
+ int riscv128 : 1; // Is a 128 bit architecture
+ int a : 1; // Atomic Instructions
+ int c : 1; // Compressed Instructions
+ int d : 1; // Double Precision Floating Point
+ int e : 1; // Base Integer Reduced
+ int f : 1; // Single Precision Floating Point
+ int i : 1; // Base Integer
+ int m : 1; // Integer Multiplication and Division
+ int v : 1; // Vector Operations
+ int q : 1; // Quad Precision Floating Point
+} RiscvFeatures;
+
+
+typedef struct {
+ RiscvFeatures features;
+ char uarch[64]; // 0 terminated string
+ char vendor[64]; // 0 terminated string
+} RiscvInfo;
+
+typedef enum {
+ RISCV_32,
+ RISCV_64,
+ RISCV_128,
+ RISCV_A,
+ RISCV_C,
+ RISCV_D,
+ RISCV_E,
+ RISCV_F,
+ RISCV_I,
+ RISCV_M,
+ RISCV_V,
+ RISCV_Q,
+ RISCV_LAST_,
+} RiscvFeaturesEnum;
+
+RiscvInfo GetRiscvInfo(void);
+int GetRiscvFeaturesEnumValue(const RiscvFeatures* features, RiscvFeaturesEnum value);
+const char* GetRiscvFeaturesEnumName(RiscvFeaturesEnum);
+
+CPU_FEATURES_END_CPP_NAMESPACE
+
+#endif // CPU_FEATURES_INCLUDE_CPUINFO_RISCV_H_
+
diff --git a/include/internal/hwcaps.h b/include/internal/hwcaps.h
index 5030582..adb61f8 100644
--- a/include/internal/hwcaps.h
+++ b/include/internal/hwcaps.h
@@ -205,6 +205,9 @@ CPU_FEATURES_START_CPP_NAMESPACE
#define HWCAP_S390_SIE 4194304
// https://elixir.bootlin.com/linux/latest/source/arch/riscv/include/uapi/asm/hwcap.h
+#define RISCV_HWCAP_32 0x32
+#define RISCV_HWCAP_64 0x64
+#define RISCV_HWCAP_128 0x128
#define RISCV_HWCAP_A (1UL << ('A' - 'A'))
#define RISCV_HWCAP_C (1UL << ('C' - 'A'))
#define RISCV_HWCAP_D (1UL << ('D' - 'A'))
diff --git a/scripts/generate_badges.d b/scripts/generate_badges.d
index 2e357a5..1cb8159 100644
--- a/scripts/generate_badges.d
+++ b/scripts/generate_badges.d
@@ -18,8 +18,9 @@ enum Cpu
AArch64,
ARM,
MIPS,
- s390x,
POWER,
+ RISCV,
+ s390x,
}
enum Os
diff --git a/src/impl_riscv_linux.c b/src/impl_riscv_linux.c
new file mode 100644
index 0000000..8911a84
--- /dev/null
+++ b/src/impl_riscv_linux.c
@@ -0,0 +1,101 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cpu_features_macros.h"
+
+#ifdef CPU_FEATURES_ARCH_RISCV
+#if defined(CPU_FEATURES_OS_LINUX)
+
+#include "cpuinfo_riscv.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// Definitions for introspection.
+////////////////////////////////////////////////////////////////////////////////
+#define INTROSPECTION_TABLE \
+ LINE(RISCV_32, riscv32, "32", RISCV_HWCAP_32, 0) \
+ LINE(RISCV_64, riscv64, "64", RISCV_HWCAP_64, 0) \
+ LINE(RISCV_128, riscv128, "128", RISCV_HWCAP_128, 0) \
+ LINE(RISCV_A, a, "a", RISCV_HWCAP_A, 0) \
+ LINE(RISCV_C, c, "c", RISCV_HWCAP_C, 0) \
+ LINE(RISCV_D, d, "d", RISCV_HWCAP_D, 0) \
+ LINE(RISCV_E, e, "e", RISCV_HWCAP_E, 0) \
+ LINE(RISCV_F, f, "f", RISCV_HWCAP_F, 0) \
+ LINE(RISCV_I, i, "i", RISCV_HWCAP_I, 0) \
+ LINE(RISCV_M, m, "m", RISCV_HWCAP_M, 0) \
+ LINE(RISCV_V, v, "v", RISCV_HWCAP_V, 0) \
+ LINE(RISCV_Q, q, "q", RISCV_HWCAP_Q, 0)
+#define INTROSPECTION_PREFIX Riscv
+#define INTROSPECTION_ENUM_PREFIX RISCV
+#include "define_introspection_and_hwcaps.inl"
+
+////////////////////////////////////////////////////////////////////////////////
+// Implementation.
+////////////////////////////////////////////////////////////////////////////////
+
+#include <stdbool.h>
+#include <stdio.h>
+
+#include "internal/filesystem.h"
+#include "internal/stack_line_reader.h"
+
+static const RiscvInfo kEmptyRiscvInfo;
+
+static bool HandleRiscVLine(const LineResult result, RiscvInfo* const info) {
+ StringView line = result.line;
+ StringView key, value;
+ if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) {
+ if (CpuFeatures_StringView_IsEquals(key, str("isa"))) {
+ // Strip "rv" prefix
+ if (!CpuFeatures_StringView_StartsWith(value, "rv")) continue;
+ value = CpuFeatures_StringView_PopFront(value, 2);
+ for (size_t i = 0; i < RISCV_LAST_; ++i) {
+ StringView flag = str(kCpuInfoFlags[i]);
+ bool is_set = CpuFeatures_StringView_IndexOf(value, flag) != -1;
+ kSetters[i](&info->features, is_set);
+ }
+ }
+ if (CpuFeatures_StringView_IsEquals(key, str("uarch"))) {
+ int index = CpuFeatures_StringView_IndexOfChar(value, ',');
+ if (index == -1) continue;
+ StringView vendor = CpuFeatures_StringView_KeepFront(value, index);
+ StringView uarch = CpuFeatures_StringView_PopFront(value, index + 1);
+ CpuFeatures_StringView_CopyString(vendor, info->vendor,
+ sizeof(info->vendor));
+ CpuFeatures_StringView_CopyString(uarch, info->uarch,
+ sizeof(info->uarch));
+ }
+ }
+ return !result.eof;
+}
+
+static void FillProcCpuInfoData(RiscvInfo* const info) {
+ const int fd = CpuFeatures_OpenFile("/proc/cpuinfo");
+ if (fd >= 0) {
+ StackLineReader reader;
+ StackLineReader_Initialize(&reader, fd);
+ for (;;) {
+ if (!HandleRiscVLine(StackLineReader_NextLine(&reader), info)) break;
+ }
+ CpuFeatures_CloseFile(fd);
+ }
+}
+
+RiscvInfo GetRiscvInfo(void) {
+ RiscvInfo info = kEmptyRiscvInfo;
+ FillProcCpuInfoData(&info);
+ return info;
+}
+
+#endif // defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
+#endif // CPU_FEATURES_ARCH_RISCV
diff --git a/src/utils/list_cpu_features.c b/src/utils/list_cpu_features.c
index b280f69..8226d85 100644
--- a/src/utils/list_cpu_features.c
+++ b/src/utils/list_cpu_features.c
@@ -37,6 +37,8 @@
#include "cpuinfo_ppc.h"
#elif defined(CPU_FEATURES_ARCH_S390X)
#include "cpuinfo_s390x.h"
+#elif defined(CPU_FEATURES_ARCH_RISCV)
+#include "cpuinfo_riscv.h"
#endif
// Design principles
@@ -210,6 +212,9 @@ DEFINE_ADD_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures,
#elif defined(CPU_FEATURES_ARCH_S390X)
DEFINE_ADD_FLAGS(GetS390XFeaturesEnumValue, GetS390XFeaturesEnumName, S390XFeatures,
S390X_LAST_)
+#elif defined(CPU_FEATURES_ARCH_RISCV)
+DEFINE_ADD_FLAGS(GetRiscvFeaturesEnumValue, GetRiscvFeaturesEnumName, RiscvFeatures,
+ RISCV_LAST_)
#endif
// Prints a json string with characters escaping.
@@ -421,6 +426,12 @@ static Node* CreateTree(void) {
AddMapEntry(root, "model", CreateString(strings.type.platform));
AddMapEntry(root, "# processors", CreateInt(strings.num_processors));
AddFlags(root, &info.features);
+#elif defined(CPU_FEATURES_ARCH_RISCV)
+ const RiscvInfo info = GetRiscvInfo();
+ AddMapEntry(root, "arch", CreateString("risc-v"));
+ AddMapEntry(root, "vendor", CreateString(info.vendor));
+ AddMapEntry(root, "microarchitecture", CreateString(info.uarch));
+ AddFlags(root, &info.features);
#endif
return root;
}
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index a87d18a..82e129a 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -96,3 +96,10 @@ if(PROCESSOR_IS_S390X)
target_link_libraries(cpuinfo_s390x_test all_libraries)
add_test(NAME cpuinfo_s390x_test COMMAND cpuinfo_s390x_test)
endif()
+##------------------------------------------------------------------------------
+## cpuinfo_riscv_test
+if(PROCESSOR_IS_RISCV)
+ add_executable(cpuinfo_riscv_test cpuinfo_riscv_test.cc ../src/impl_riscv_linux.c)
+ target_link_libraries(cpuinfo_riscv_test all_libraries)
+ add_test(NAME cpuinfo_riscv_test COMMAND cpuinfo_riscv_test)
+endif()
diff --git a/test/cpuinfo_riscv_test.cc b/test/cpuinfo_riscv_test.cc
new file mode 100644
index 0000000..ff7d979
--- /dev/null
+++ b/test/cpuinfo_riscv_test.cc
@@ -0,0 +1,125 @@
+// Copyright 2022 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "cpuinfo_riscv.h"
+
+#include "filesystem_for_testing.h"
+#include "gtest/gtest.h"
+#include "hwcaps_for_testing.h"
+
+namespace cpu_features {
+namespace {
+
+TEST(CpuinfoRiscvTest, LicheeFromCpuInfo) {
+ ResetHwcaps();
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo", R"(processor : 0
+hart : 0
+isa : rv64imafdc
+mmu : sv39
+uarch : thead,c906)");
+ const auto info = GetRiscvInfo();
+ EXPECT_STREQ(info.uarch, "c906");
+ EXPECT_STREQ(info.vendor, "thead");
+
+ EXPECT_FALSE(info.features.riscv32);
+ EXPECT_TRUE(info.features.riscv64);
+ EXPECT_FALSE(info.features.riscv128);
+ EXPECT_TRUE(info.features.a);
+ EXPECT_TRUE(info.features.c);
+ EXPECT_TRUE(info.features.d);
+ EXPECT_FALSE(info.features.e);
+ EXPECT_TRUE(info.features.f);
+ EXPECT_TRUE(info.features.i);
+ EXPECT_TRUE(info.features.m);
+ EXPECT_FALSE(info.features.q);
+ EXPECT_FALSE(info.features.v);
+}
+
+TEST(CpuinfoRiscvTest, KendryteFromCpuInfo) {
+ ResetHwcaps();
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo", R"(
+hart : 0
+isa : rv64i2p0m2p0a2p0f2p0d2p0c2p0xv5-0p0
+mmu : sv39
+
+hart : 1
+isa : rv64i2p0m2p0a2p0f2p0d2p0c2p0xv5-0p0
+mmu : sv39)");
+ const auto info = GetRiscvInfo();
+ EXPECT_STREQ(info.uarch, "");
+ EXPECT_STREQ(info.vendor, "");
+
+ EXPECT_FALSE(info.features.riscv32);
+ EXPECT_TRUE(info.features.riscv64);
+ EXPECT_FALSE(info.features.riscv128);
+ EXPECT_TRUE(info.features.a);
+ EXPECT_TRUE(info.features.c);
+ EXPECT_TRUE(info.features.d);
+ EXPECT_FALSE(info.features.e);
+ EXPECT_TRUE(info.features.f);
+ EXPECT_TRUE(info.features.i);
+ EXPECT_TRUE(info.features.m);
+ EXPECT_FALSE(info.features.q);
+ EXPECT_TRUE(info.features.v);
+}
+
+TEST(CpuinfoRiscvTest, UnknownFromCpuInfo) {
+ ResetHwcaps();
+ auto& fs = GetEmptyFilesystem();
+ fs.CreateFile("/proc/cpuinfo", R"(
+processor : 0
+hart : 2
+isa : rv64imafdc
+mmu : sv39
+uarch : sifive,bullet0
+
+processor : 1
+hart : 1
+isa : rv64imafdc
+mmu : sv39
+uarch : sifive,bullet0
+
+processor : 2
+hart : 3
+isa : rv64imafdc
+mmu : sv39
+uarch : sifive,bullet0
+
+processor : 3
+hart : 4
+isa : rv64imafdc
+mmu : sv39
+uarch : sifive,bullet0)");
+ const auto info = GetRiscvInfo();
+ EXPECT_STREQ(info.uarch, "bullet0");
+ EXPECT_STREQ(info.vendor, "sifive");
+
+ EXPECT_FALSE(info.features.riscv32);
+ EXPECT_TRUE(info.features.riscv64);
+ EXPECT_FALSE(info.features.riscv128);
+ EXPECT_TRUE(info.features.a);
+ EXPECT_TRUE(info.features.c);
+ EXPECT_TRUE(info.features.d);
+ EXPECT_FALSE(info.features.e);
+ EXPECT_TRUE(info.features.f);
+ EXPECT_TRUE(info.features.i);
+ EXPECT_TRUE(info.features.m);
+ EXPECT_FALSE(info.features.q);
+ EXPECT_FALSE(info.features.v);
+}
+
+} // namespace
+} // namespace cpu_features