From d199a2df02cf35b419bd0a2f83323c692a2f82b0 Mon Sep 17 00:00:00 2001 From: Olaf Bernstein Date: Sat, 5 Oct 2024 17:44:03 +0200 Subject: [PATCH] add detection for RISC-V bitmanip extensions --- include/cpuinfo_riscv.h | 10 ++++++++ include/internal/hwcaps.h | 1 + src/impl_riscv_linux.c | 17 ++++++++++--- test/cpuinfo_riscv_test.cc | 52 +++++++++++++++++++++++++++++++++++++- 4 files changed, 76 insertions(+), 4 deletions(-) diff --git a/include/cpuinfo_riscv.h b/include/cpuinfo_riscv.h index 1fa7aa51..56812d79 100644 --- a/include/cpuinfo_riscv.h +++ b/include/cpuinfo_riscv.h @@ -36,9 +36,14 @@ typedef struct { int D : 1; // Standard Extension for Double-Precision Floating-Point int Q : 1; // Standard Extension for Quad-Precision Floating-Point int C : 1; // Standard Extension for Compressed Instructions + int B : 1; // Standard Extension for Bit Manipulation Instructions int V : 1; // Standard Extension for Vector Instructions int Zicsr : 1; // Control and Status Register (CSR) int Zifencei : 1; // Instruction-Fetch Fence + int Zba : 1; // Address generation instructions + int Zbb : 1; // Basic bit-manipulation + int Zbs : 1; // Single-bit instructions + int Zbc : 1; // Carry-less multiplication } RiscvFeatures; typedef struct { @@ -56,9 +61,14 @@ typedef enum { RISCV_D, RISCV_Q, RISCV_C, + RISCV_B, RISCV_V, RISCV_Zicsr, RISCV_Zifencei, + RISCV_Zba, + RISCV_Zbb, + RISCV_Zbs, + RISCV_Zbc, RISCV_LAST_, } RiscvFeaturesEnum; diff --git a/include/internal/hwcaps.h b/include/internal/hwcaps.h index 2490e3e0..a0d31515 100644 --- a/include/internal/hwcaps.h +++ b/include/internal/hwcaps.h @@ -255,6 +255,7 @@ CPU_FEATURES_START_CPP_NAMESPACE #define RISCV_HWCAP_D (1UL << ('D' - 'A')) #define RISCV_HWCAP_Q (1UL << ('Q' - 'A')) #define RISCV_HWCAP_C (1UL << ('C' - 'A')) +#define RISCV_HWCAP_B (1UL << ('B' - 'A')) #define RISCV_HWCAP_V (1UL << ('V' - 'A')) // https://github.com/torvalds/linux/blob/master/arch/loongarch/include/uapi/asm/hwcap.h diff --git a/src/impl_riscv_linux.c b/src/impl_riscv_linux.c index 8abec6eb..0cf2be17 100644 --- a/src/impl_riscv_linux.c +++ b/src/impl_riscv_linux.c @@ -39,9 +39,14 @@ LINE(RISCV_D, D, "d", RISCV_HWCAP_D, 0) \ LINE(RISCV_Q, Q, "q", RISCV_HWCAP_Q, 0) \ LINE(RISCV_C, C, "c", RISCV_HWCAP_C, 0) \ + LINE(RISCV_B, B, "b", RISCV_HWCAP_B, 0) \ LINE(RISCV_V, V, "v", RISCV_HWCAP_V, 0) \ LINE(RISCV_Zicsr, Zicsr, "_zicsr", 0, 0) \ - LINE(RISCV_Zifencei, Zifencei, "_zifencei", 0, 0) + LINE(RISCV_Zifencei, Zifencei, "_zifencei", 0, 0) \ + LINE(RISCV_Zba, Zba, "_zba", 0, 0) \ + LINE(RISCV_Zbb, Zbb, "_zbb", 0, 0) \ + LINE(RISCV_Zbs, Zbs, "_zbs", 0, 0) \ + LINE(RISCV_Zbc, Zbc, "_zbc", 0, 0) #define INTROSPECTION_PREFIX Riscv #define INTROSPECTION_ENUM_PREFIX RISCV #include "define_introspection_and_hwcaps.inl" @@ -64,8 +69,7 @@ static void HandleRiscVIsaLine(StringView line, RiscvFeatures* const features) { int index_of_flag = CpuFeatures_StringView_IndexOf(line, flag); bool is_set = index_of_flag != -1; kSetters[i](features, is_set); - if (is_set) - line = CpuFeatures_StringView_PopFront(line, index_of_flag + flag.size); + line = CpuFeatures_StringView_PopFront(line, index_of_flag + flag.size); } } @@ -104,6 +108,13 @@ static void FillProcCpuInfoData(RiscvInfo* const info) { RiscvInfo GetRiscvInfo(void) { RiscvInfo info = kEmptyRiscvInfo; FillProcCpuInfoData(&info); + RiscvFeatures f = info.features; + // B <-> Zba + Zbb + Zbs + f.B = f.B || (f.Zba && f.Zbb && f.Zbs); + f.Zba = f.Zba || f.B; + f.Zbb = f.Zbb || f.B; + f.Zbs = f.Zbs || f.B; + info.features = f; return info; } diff --git a/test/cpuinfo_riscv_test.cc b/test/cpuinfo_riscv_test.cc index 2ffe2b35..2acfa151 100644 --- a/test/cpuinfo_riscv_test.cc +++ b/test/cpuinfo_riscv_test.cc @@ -24,7 +24,7 @@ namespace { TEST(CpuinfoRiscvTest, Sipeed_Lichee_RV_FromCpuInfo) { ResetHwcaps(); auto& fs = GetEmptyFilesystem(); - fs.CreateFile("/proc/cpuinfo", R"(processor : 0 + fs.CreateFile("/proc/cpuinfo", R"(processor : 0 hart : 0 isa : rv64imafdc mmu : sv39 @@ -41,7 +41,12 @@ uarch : thead,c906)"); EXPECT_TRUE(info.features.D); EXPECT_FALSE(info.features.Q); EXPECT_TRUE(info.features.C); + EXPECT_FALSE(info.features.B); EXPECT_FALSE(info.features.V); + EXPECT_FALSE(info.features.Zba); + EXPECT_FALSE(info.features.Zbb); + EXPECT_FALSE(info.features.Zbs); + EXPECT_FALSE(info.features.Zbc); } // https://github.com/ThomasKaiser/sbc-bench/blob/284e82b016ec1beeac42a5fcbe556b670f68441a/results/Kendryte-K510-4.17.0.cpuinfo @@ -68,7 +73,12 @@ mmu : sv39"); EXPECT_TRUE(info.features.D); EXPECT_FALSE(info.features.Q); EXPECT_TRUE(info.features.C); + EXPECT_FALSE(info.features.B); EXPECT_FALSE(info.features.V); + EXPECT_FALSE(info.features.Zba); + EXPECT_FALSE(info.features.Zbb); + EXPECT_FALSE(info.features.Zbs); + EXPECT_FALSE(info.features.Zbc); } // https://github.com/ThomasKaiser/sbc-bench/blob/284e82b016ec1beeac42a5fcbe556b670f68441a/results/T-Head-C910-5.10.4.cpuinfo @@ -111,7 +121,12 @@ cpu-vector : 0.7.1"); EXPECT_TRUE(info.features.D); EXPECT_FALSE(info.features.Q); EXPECT_TRUE(info.features.C); + EXPECT_FALSE(info.features.B); EXPECT_FALSE(info.features.V); + EXPECT_FALSE(info.features.Zba); + EXPECT_FALSE(info.features.Zbb); + EXPECT_FALSE(info.features.Zbs); + EXPECT_FALSE(info.features.Zbc); } TEST(CpuinfoRiscvTest, UnknownFromCpuInfo) { @@ -153,7 +168,12 @@ uarch : sifive,bullet0)"); EXPECT_TRUE(info.features.D); EXPECT_FALSE(info.features.Q); EXPECT_TRUE(info.features.C); + EXPECT_FALSE(info.features.B); EXPECT_FALSE(info.features.V); + EXPECT_FALSE(info.features.Zba); + EXPECT_FALSE(info.features.Zbb); + EXPECT_FALSE(info.features.Zbs); + EXPECT_FALSE(info.features.Zbc); } TEST(CpuinfoRiscvTest, QemuCpuInfo) { @@ -173,7 +193,37 @@ mmu : sv48)"); EXPECT_TRUE(info.features.D); EXPECT_FALSE(info.features.Q); EXPECT_TRUE(info.features.C); + EXPECT_TRUE(info.features.B); EXPECT_TRUE(info.features.V); + EXPECT_TRUE(info.features.Zba); + EXPECT_TRUE(info.features.Zbb); + EXPECT_TRUE(info.features.Zbs); + EXPECT_TRUE(info.features.Zbc); +} + +TEST(CpuinfoRiscvTest, JustBCpuInfo) { + ResetHwcaps(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"( +processor : 0 +hart : 0 +isa : rv64imafdcbvh +mmu : sv48)"); + const auto info = GetRiscvInfo(); + EXPECT_FALSE(info.features.RV32I); + EXPECT_TRUE(info.features.RV64I); + EXPECT_TRUE(info.features.M); + EXPECT_TRUE(info.features.A); + EXPECT_TRUE(info.features.F); + EXPECT_TRUE(info.features.D); + EXPECT_FALSE(info.features.Q); + EXPECT_TRUE(info.features.C); + EXPECT_TRUE(info.features.B); + EXPECT_TRUE(info.features.V); + EXPECT_TRUE(info.features.Zba); + EXPECT_TRUE(info.features.Zbb); + EXPECT_TRUE(info.features.Zbs); + EXPECT_FALSE(info.features.Zbc); } } // namespace