From a7cd2a23c3bd078122cba7f9990388375d98695e Mon Sep 17 00:00:00 2001 From: ihb2032 Date: Fri, 3 Apr 2026 11:03:33 +0800 Subject: [PATCH 1/4] build(cmake): add RISC-V architecture and RVV compilation support Signed-off-by: ihb2032 --- cmake/option.cmake | 91 ++++++++++++++++++++++++++++++++++++++- src/ailego/CMakeLists.txt | 37 +++++++++++++--- 2 files changed, 119 insertions(+), 9 deletions(-) diff --git a/cmake/option.cmake b/cmake/option.cmake index a4560f73d..255f52c93 100644 --- a/cmake/option.cmake +++ b/cmake/option.cmake @@ -1,6 +1,7 @@ ## https://en.wikipedia.org/wiki/List_of_Intel_CPU_microarchitectures ## https://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures ## https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html +## https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Options.html ## Intel Microarchitectures option(ENABLE_NEHALEM "Enable Intel Nehalem CPU microarchitecture" OFF) @@ -30,6 +31,11 @@ option(ENABLE_ARMV8.4A "Enable ARMv8.4-a architecture" OFF) option(ENABLE_ARMV8.5A "Enable ARMv8.5-a architecture" OFF) option(ENABLE_ARMV8.6A "Enable ARMv8.6-a architecture" OFF) +## RISC-V architectures +option(ENABLE_RISCV64 "Enable RISC-V 64-bit base architecture" OFF) +option(ENABLE_RISCV_VECTOR "Enable RISC-V Vector extension" OFF) +option(ENABLE_RISCV_ZVFH "Enable RISC-V Zvfh extension" OFF) + ## OpenMP option option(ENABLE_OPENMP "Enable OpenMP support" OFF) @@ -39,6 +45,7 @@ set(ARCH_OPTIONS ENABLE_ZEN1 ENABLE_ZEN2 ENABLE_ZEN3 ENABLE_ARMV8A ENABLE_ARMV8.1A ENABLE_ARMV8.2A ENABLE_ARMV8.3A ENABLE_ARMV8.4A ENABLE_ARMV8.5A ENABLE_ARMV8.6A + ENABLE_RISCV64 ENABLE_RISCV_VECTOR ENABLE_RISCV_ZVFH ENABLE_NATIVE ) @@ -51,6 +58,10 @@ foreach(opt IN LISTS ARCH_OPTIONS) endif() endforeach() +if((ENABLE_RISCV_VECTOR OR ENABLE_RISCV_ZVFH) AND NOT ENABLE_RISCV64) + message(FATAL_ERROR "ENABLE_RISCV_VECTOR and ENABLE_RISCV_ZVFH require ENABLE_RISCV64") +endif() + include(CheckCCompilerFlag) function(_AppendFlags _RESULT _FLAG) @@ -90,6 +101,60 @@ macro(add_arch_flag FLAG VAR_NAME OPTION_NAME) endif() endmacro() +function(_build_riscv64_march RESULT_VAR) + set(_march "rv64gc") + if(ENABLE_RISCV_VECTOR) + string(APPEND _march "v") + endif() + if(ENABLE_RISCV_ZVFH) + if(NOT ENABLE_RISCV_VECTOR) + message(FATAL_ERROR "ENABLE_RISCV_ZVFH requires ENABLE_RISCV_VECTOR") + endif() + string(APPEND _march "_zvfh") + endif() + set(${RESULT_VAR} "${_march}" PARENT_SCOPE) +endfunction() + +function(_build_riscv64_rvv_march RESULT_VAR) + set(_march "rv64gcv") + if(ENABLE_RISCV_ZVFH) + string(APPEND _march "_zvfh") + endif() + set(${RESULT_VAR} "${_march}" PARENT_SCOPE) +endfunction() + +function(_setup_riscv64_march) + _build_riscv64_march(_riscv_march) + set(CMAKE_REQUIRED_FLAGS "-mabi=lp64d") + check_c_compiler_flag("-march=${_riscv_march}" _COMP_SUPP_riscv64) + unset(CMAKE_REQUIRED_FLAGS) + + if(_COMP_SUPP_riscv64) + _AppendFlags(CMAKE_C_FLAGS "-march=${_riscv_march}") + _AppendFlags(CMAKE_C_FLAGS "-mabi=lp64d") + _AppendFlags(CMAKE_CXX_FLAGS "-march=${_riscv_march}") + _AppendFlags(CMAKE_CXX_FLAGS "-mabi=lp64d") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE) + message(STATUS "RISC-V: enabled -march=${_riscv_march} -mabi=lp64d") + else() + message(WARNING "Compiler does not support -march=${_riscv_march} -mabi=lp64d") + endif() +endfunction() + +function(setup_compiler_march_for_riscv64_rvv RESULT_VAR) + _build_riscv64_rvv_march(_riscv_rvv_march) + set(CMAKE_REQUIRED_FLAGS "-mabi=lp64d") + check_c_compiler_flag("-march=${_riscv_rvv_march}" _COMP_SUPP_riscv64_rvv) + unset(CMAKE_REQUIRED_FLAGS) + + if(_COMP_SUPP_riscv64_rvv) + set(${RESULT_VAR} "-march=${_riscv_rvv_march} -mabi=lp64d" PARENT_SCOPE) + else() + set(${RESULT_VAR} "" PARENT_SCOPE) + endif() +endfunction() + function(_setup_armv8_march) if(MSVC) return() @@ -247,8 +312,7 @@ if(NOT AUTO_DETECT_ARCH) add_arch_flag("-march=nehalem" NEHALEM ENABLE_NEHALEM) endif() - # ARM (newest first — allow multiple? usually only one) - # But GCC allows only one -march=, so honor highest enabled + # ARM (newest first) if(ENABLE_ARMV8.6A) add_arch_flag("-march=armv8.6-a" ARMV86A ENABLE_ARMV8.6A) endif() @@ -271,6 +335,25 @@ if(NOT AUTO_DETECT_ARCH) add_arch_flag("-march=armv8-a" ARMV8A ENABLE_ARMV8A) endif() + # RISC-V 64-bit + if(ENABLE_RISCV64) + _build_riscv64_march(_riscv_march) + set(CMAKE_REQUIRED_FLAGS "-mabi=lp64d") + check_c_compiler_flag("-march=${_riscv_march}" COMPILER_SUPPORT_RISCV64) + unset(CMAKE_REQUIRED_FLAGS) + if(COMPILER_SUPPORT_RISCV64) + _AppendFlags(CMAKE_C_FLAGS "-march=${_riscv_march}") + _AppendFlags(CMAKE_C_FLAGS "-mabi=lp64d") + _AppendFlags(CMAKE_CXX_FLAGS "-march=${_riscv_march}") + _AppendFlags(CMAKE_CXX_FLAGS "-mabi=lp64d") + message(STATUS "RISC-V: enabled -march=${_riscv_march} -mabi=lp64d") + else() + message(FATAL_ERROR + "Compiler does not support required flags: " + "-march=${_riscv_march} -mabi=lp64d for ENABLE_RISCV64") + endif() + endif() + else() # AUTO DETECT # Heuristic: detect host architecture and probe appropriate flags @@ -284,6 +367,8 @@ else() set(HOST_ARCH arm64) elseif(SYSTEM_PROC_LOWER MATCHES "^(arm|armv7|armv7-a|armv7l)$") set(HOST_ARCH arm) + elseif(SYSTEM_PROC_LOWER MATCHES "^(riscv64)$") + set(HOST_ARCH riscv64) else() set(HOST_ARCH unknown) message(WARNING "unknown host arch: ${CMAKE_SYSTEM_PROCESSOR}") @@ -294,6 +379,8 @@ else() _setup_armv8_march() elseif (HOST_ARCH MATCHES "^(x86|x64)$") _setup_x86_march() + elseif (HOST_ARCH STREQUAL "riscv64") + _setup_riscv64_march() else () message(WARNING "unknown host arch - no -march set") endif () diff --git a/src/ailego/CMakeLists.txt b/src/ailego/CMakeLists.txt index fdaa1b13c..e50795944 100644 --- a/src/ailego/CMakeLists.txt +++ b/src/ailego/CMakeLists.txt @@ -84,13 +84,14 @@ if(NOT ANDROID AND AUTO_DETECT_ARCH) endforeach() foreach(MATH_FILE ${MATH_FILES_AVX512FP16}) - set_source_files_properties( - ${MATH_FILE} - PROPERTIES - COMPILE_FLAGS "${MATH_MARCH_FLAG_AVX512FP16}" - ) - endforeach() - elseif (HOST_ARCH MATCHES "^(arm|arm64)$") + set_source_files_properties( + ${MATH_FILE} + PROPERTIES + COMPILE_FLAGS "${MATH_MARCH_FLAG_AVX512FP16}" + ) + endforeach() + + elseif(HOST_ARCH MATCHES "^(arm|arm64)$") if(MSVC) return() endif() @@ -114,6 +115,28 @@ if(NOT ANDROID AND AUTO_DETECT_ARCH) COMPILE_FLAGS "${MATH_MARCH_FLAG_NEON}" ) endforeach() + + elseif(HOST_ARCH STREQUAL "riscv64") + setup_compiler_march_for_riscv64_rvv(MATH_MARCH_FLAG_RVV) + + if(MATH_MARCH_FLAG_RVV) + file(GLOB_RECURSE MATH_FILES_RVV + ${CMAKE_CURRENT_SOURCE_DIR}/math/*_rvv.cc + ${CMAKE_CURRENT_SOURCE_DIR}/math/*_rvv.c + ${CMAKE_CURRENT_SOURCE_DIR}/math_batch/*_rvv.cc + ${CMAKE_CURRENT_SOURCE_DIR}/math_batch/*_rvv.c + ) + + foreach(MATH_FILE ${MATH_FILES_RVV}) + set_source_files_properties( + ${MATH_FILE} + PROPERTIES + COMPILE_FLAGS "${MATH_MARCH_FLAG_RVV}" + ) + endforeach() + else() + message(STATUS "RISC-V RVV-specific march is not supported by the compiler; skipping *_rvv sources") + endif() endif() endif() From cc6e3c2126e2945a421e6beab8860359b16d484b Mon Sep 17 00:00:00 2001 From: ihb2032 Date: Fri, 3 Apr 2026 14:18:18 +0800 Subject: [PATCH 2/4] feat(platform): setup RISC-V macros and alignment rules Signed-off-by: ihb2032 --- src/ailego/version.i | 10 ++++++++++ src/include/zvec/ailego/internal/platform.h | 10 ++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/ailego/version.i b/src/ailego/version.i index c1b14be2e..1701c287f 100644 --- a/src/ailego/version.i +++ b/src/ailego/version.i @@ -114,6 +114,10 @@ #define AILEGO_VERSION_PROCESSOR "x86 64-bit Processor" #elif defined(__i386) || defined(_M_IX86) #define AILEGO_VERSION_PROCESSOR "x86 32-bit Processor" +#elif defined(__riscv) && defined(__riscv_xlen) && (__riscv_xlen == 64) +#define AILEGO_VERSION_PROCESSOR "RISC-V 64-bit Processor" +#elif defined(__riscv) && defined(__riscv_xlen) && (__riscv_xlen == 32) +#define AILEGO_VERSION_PROCESSOR "RISC-V 32-bit Processor" #elif defined(__ARM_ARCH) #if defined(__ARM_64BIT_STATE) #define AILEGO_VERSION_PROCESSOR "ARM 64-bit Processor" @@ -227,6 +231,12 @@ #if defined(__ARM_NEON) #define AILEGO_VERSION_SIMD " Arm Neon Instruction Set\n" +#elif defined(__riscv_vector) +#if defined(__riscv_zvfh) +#define AILEGO_VERSION_SIMD " RISC-V Vector Instruction Set (+Zvfh)\n" +#else +#define AILEGO_VERSION_SIMD " RISC-V Vector Instruction Set\n" +#endif #elif defined(__AVX512FP16__) #define AILEGO_VERSION_SIMD " AVX-512FP16 Instruction Set\n" #elif defined(__AVX512F__) diff --git a/src/include/zvec/ailego/internal/platform.h b/src/include/zvec/ailego/internal/platform.h index ccd33971e..fa1f61412 100644 --- a/src/include/zvec/ailego/internal/platform.h +++ b/src/include/zvec/ailego/internal/platform.h @@ -42,6 +42,9 @@ #if defined(__ARM_FEATURE_CRC32) #include #endif +#if defined(__riscv_vector) +#include +#endif #endif //! MSVC platform compatibility (before extern "C" so available in C++) @@ -110,7 +113,8 @@ extern "C" { #endif #if defined(__GNUC__) -#if defined(__x86_64__) || defined(__aarch64__) || defined(__ppc64__) +#if defined(__x86_64__) || defined(__aarch64__) || defined(__ppc64__) || \ + (defined(__riscv) && defined(__riscv_xlen) && (__riscv_xlen == 64)) #define AILEGO_M64 #else #define AILEGO_M32 @@ -238,6 +242,8 @@ static inline int ailego_clz64(uint64_t x) { #endif // __CC_ARM #elif defined(__SSE2__) #define ailego_yield() _mm_pause() +#elif defined(__riscv) && defined(__riscv_zihintpause) +#define ailego_yield() __asm__ __volatile__("pause" ::: "memory") #else #define ailego_yield() ((void)0) #endif // __arm__ || __aarch64__ @@ -269,7 +275,7 @@ static inline int ailego_clz64(uint64_t x) { #if !defined(ailego_malloc) #if defined(__AVX512F__) #define ailego_malloc(SIZE) ailego_aligned_malloc((SIZE), 64) -#elif defined(__AVX__) +#elif defined(__AVX__) || defined(__riscv_vector) #define ailego_malloc(SIZE) ailego_aligned_malloc((SIZE), 32) #elif defined(__SSE__) #define ailego_malloc(SIZE) ailego_aligned_malloc((SIZE), 16) From 1f6095aec40dae211c20667372ba9f70212ad365 Mon Sep 17 00:00:00 2001 From: ihb2032 Date: Fri, 3 Apr 2026 14:43:23 +0800 Subject: [PATCH 3/4] feat(cpu_features): implement runtime detection for RISC-V RVV Signed-off-by: ihb2032 --- src/ailego/internal/cpu_features.cc | 134 ++++++++++++++++++++++++++-- src/ailego/internal/cpu_features.h | 16 +++- 2 files changed, 140 insertions(+), 10 deletions(-) diff --git a/src/ailego/internal/cpu_features.cc b/src/ailego/internal/cpu_features.cc index 06e1444d5..a6bb64e5b 100644 --- a/src/ailego/internal/cpu_features.cc +++ b/src/ailego/internal/cpu_features.cc @@ -14,13 +14,27 @@ #include "cpu_features.h" #include +#include #if defined(_MSC_VER) #include -#elif !defined(__ARM_ARCH) +#endif + +#if (defined(__x86_64__) || defined(__i386__)) && !defined(_MSC_VER) #include #endif +#if defined(__riscv) && defined(__linux__) +#include +#include +#if defined(__has_include) +#if __has_include() +#define AILEGO_HAVE_RISCV_HWPROBE_HEADER 1 +#include +#endif +#endif +#endif + namespace zvec { namespace ailego { namespace internal { @@ -34,9 +48,82 @@ namespace internal { CpuFeatures::CpuFlags CpuFeatures::flags_; -#if defined(_MSC_VER) +namespace { + +#if defined(__riscv) && defined(__linux__) + +constexpr uint32_t kRiscvFlagVector = (1u << 0); +constexpr uint32_t kRiscvFlagZvfh = (1u << 1); + +#if !defined(SYS_riscv_hwprobe) && !defined(__NR_riscv_hwprobe) +#define __NR_riscv_hwprobe 258 +#endif + +#if !defined(AILEGO_HAVE_RISCV_HWPROBE_HEADER) +struct riscv_hwprobe { + int64_t key; + uint64_t value; +}; +#endif + +#ifndef RISCV_HWPROBE_KEY_IMA_EXT_0 +#define RISCV_HWPROBE_KEY_IMA_EXT_0 4 +#endif + +#ifndef RISCV_HWPROBE_IMA_V +#define RISCV_HWPROBE_IMA_V (1ULL << 2) +#endif + +static long AilegoRiscvHwprobe(struct riscv_hwprobe *pairs, size_t pair_count) { +#if defined(SYS_riscv_hwprobe) + return syscall(SYS_riscv_hwprobe, pairs, pair_count, 0, nullptr, 0); +#elif defined(__NR_riscv_hwprobe) + return syscall(__NR_riscv_hwprobe, pairs, pair_count, 0, nullptr, 0); +#else + (void)pairs; + (void)pair_count; + return -1; +#endif +} + +static uint32_t ProbeRiscvFlags() { + uint32_t flags = 0; + + riscv_hwprobe pairs[] = { + {static_cast(RISCV_HWPROBE_KEY_IMA_EXT_0), 0}, + }; + + const long ret = AilegoRiscvHwprobe(pairs, sizeof(pairs) / sizeof(pairs[0])); + if (ret != 0) { + return 0; + } + + if (pairs[0].key < 0) { + return 0; + } + + const uint64_t ext = pairs[0].value; + + if (ext & RISCV_HWPROBE_IMA_V) { + flags |= kRiscvFlagVector; + } + +#if defined(RISCV_HWPROBE_EXT_ZVFH) + if (ext & RISCV_HWPROBE_EXT_ZVFH) { + flags |= kRiscvFlagZvfh; + } +#endif + + return flags; +} + +#endif // defined(__riscv) && defined(__linux__) + +} // namespace + +#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) CpuFeatures::CpuFlags::CpuFlags(void) - : L1_ECX(0), L1_EDX(0), L7_EBX(0), L7_ECX(0), L7_EDX(0) { + : L1_ECX(0), L1_EDX(0), L7_EBX(0), L7_ECX(0), L7_EDX(0), RISCV_FLAGS(0) { int l1[4] = {0, 0, 0, 0}; int l7[4] = {0, 0, 0, 0}; @@ -48,9 +135,10 @@ CpuFeatures::CpuFlags::CpuFlags(void) L7_ECX = l7[2]; L7_EDX = l7[3]; } -#elif !defined(__ARM_ARCH) + +#elif (defined(__x86_64__) || defined(__i386__)) && !defined(_MSC_VER) CpuFeatures::CpuFlags::CpuFlags(void) - : L1_ECX(0), L1_EDX(0), L7_EBX(0), L7_ECX(0), L7_EDX(0) { + : L1_ECX(0), L1_EDX(0), L7_EBX(0), L7_ECX(0), L7_EDX(0), RISCV_FLAGS(0) { uint32_t eax, ebx, ecx, edx; if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) { @@ -64,9 +152,24 @@ CpuFeatures::CpuFlags::CpuFlags(void) L7_EDX = edx; } } + +#elif defined(__riscv) +CpuFeatures::CpuFlags::CpuFlags(void) + : L1_ECX(0), + L1_EDX(0), + L7_EBX(0), + L7_ECX(0), + L7_EDX(0), +#if defined(__linux__) + RISCV_FLAGS(ProbeRiscvFlags()) { +#else + RISCV_FLAGS(0) { +#endif +} + #else CpuFeatures::CpuFlags::CpuFlags(void) - : L1_ECX(0), L1_EDX(0), L7_EBX(0), L7_ECX(0), L7_EDX(0) {} + : L1_ECX(0), L1_EDX(0), L7_EBX(0), L7_ECX(0), L7_EDX(0), RISCV_FLAGS(0) {} #endif //! 16-bit FP conversions @@ -329,11 +432,20 @@ bool CpuFeatures::VMX(void) { return !!(flags_.L1_ECX & (1u << 5)); } -// !Running on a hypervisor bool CpuFeatures::HYPERVISOR(void) { return !!(flags_.L1_ECX & (1u << 31)); } +//! RISC-V Vector Extension +bool CpuFeatures::RISCV_VECTOR(void) { + return !!(flags_.RISCV_FLAGS & (1u << 0)); +} + +//! RISC-V Zvfh Extension +bool CpuFeatures::RISCV_ZVFH(void) { + return !!(flags_.RISCV_FLAGS & (1u << 1)); +} + const char *CpuFeatures::Intrinsics(void) { return "" #if defined(__ARM_NEON) @@ -345,6 +457,11 @@ const char *CpuFeatures::Intrinsics(void) { defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) "+FP16" #endif +#elif defined(__riscv_vector) + "RVV" +#if defined(__riscv_zvfh) + "+Zvfh" +#endif #elif defined(__AVX512F__) "AVX512F" #if defined(__AVX512VL__) @@ -420,6 +537,7 @@ const char *CpuFeatures::Intrinsics(void) { } CpuFeatures::StaticFlags CpuFeatures::static_flags_; + } // namespace internal } // namespace ailego -} // namespace zvec \ No newline at end of file +} // namespace zvec diff --git a/src/ailego/internal/cpu_features.h b/src/ailego/internal/cpu_features.h index 3db1dee2a..488dd38ea 100644 --- a/src/ailego/internal/cpu_features.h +++ b/src/ailego/internal/cpu_features.h @@ -15,6 +15,7 @@ #pragma once #include + namespace zvec { namespace ailego { namespace internal { @@ -179,9 +180,14 @@ class CpuFeatures { //! Hardware virtualization static bool VMX(void); - // !Running on a hypervisor static bool HYPERVISOR(void); + //! RISC-V Vector Extension + static bool RISCV_VECTOR(void); + + //! RISC-V Zvfh Extension + static bool RISCV_ZVFH(void); + //! Intrinsics of compiling static const char *Intrinsics(void); @@ -196,6 +202,7 @@ class CpuFeatures { uint32_t L7_EBX; uint32_t L7_ECX; uint32_t L7_EDX; + uint32_t RISCV_FLAGS; }; //! Static Members @@ -359,8 +366,13 @@ class CpuFeatures { //! Hardware virtualization bool VMX = CpuFeatures::VMX(); - // !Running on a hypervisor bool HYPERVISOR = CpuFeatures::HYPERVISOR(); + + //! RISC-V Vector Extension + bool RISCV_VECTOR = CpuFeatures::RISCV_VECTOR(); + + //! RISC-V Zvfh Extension + bool RISCV_ZVFH = CpuFeatures::RISCV_ZVFH(); }; static StaticFlags static_flags_; }; From 325ba2d6266a8b1a7128b0c8e106b1586714c964 Mon Sep 17 00:00:00 2001 From: ihb2032 Date: Fri, 3 Apr 2026 14:43:23 +0800 Subject: [PATCH 4/4] feat(cpu_features): implement runtime detection for RISC-V RVV Signed-off-by: ihb2032 --- tests/ailego/internal/cpu_features_test.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/ailego/internal/cpu_features_test.cc b/tests/ailego/internal/cpu_features_test.cc index 287232197..1f751ae8b 100644 --- a/tests/ailego/internal/cpu_features_test.cc +++ b/tests/ailego/internal/cpu_features_test.cc @@ -80,6 +80,9 @@ TEST(CpuFeatures, General) { std::cout << "* HT: " << CpuFeatures::HT() << std::endl; std::cout << "* VMX: " << CpuFeatures::VMX() << std::endl; std::cout << "* HYPERVISOR: " << CpuFeatures::HYPERVISOR() << std::endl; + std::cout << "* RISCV_VECTOR: " << CpuFeatures::RISCV_VECTOR() + << std::endl; + std::cout << "* RISCV_ZVFH: " << CpuFeatures::RISCV_ZVFH() << std::endl; // #if defined(__AVX512VBMI2__) // EXPECT_TRUE(CpuFeatures::AVX512VBMI2()); @@ -175,6 +178,12 @@ TEST(CpuFeatures, General) { #if defined(__MMX__) EXPECT_TRUE(CpuFeatures::MMX()); #endif +#if defined(__riscv_vector) + EXPECT_TRUE(CpuFeatures::RISCV_VECTOR()); +#endif +#if defined(__riscv_zvfh) + EXPECT_TRUE(CpuFeatures::RISCV_ZVFH()); +#endif } @@ -283,4 +292,8 @@ TEST(CpuFeatures, Static) { << std::endl; std::cout << "* HYPERVISOR: " << CpuFeatures::static_flags_.HYPERVISOR << std::endl; -} \ No newline at end of file + std::cout << "* RISCV_VECTOR: " << CpuFeatures::static_flags_.RISCV_VECTOR + << std::endl; + std::cout << "* RISCV_ZVFH: " << CpuFeatures::static_flags_.RISCV_ZVFH + << std::endl; +}