mirror of
https://chromium.googlesource.com/libyuv/libyuv
synced 2025-12-06 16:56:55 +08:00
Add riscv cpu info detection.
* Supports: * The standard single-letter Vector detection. * Vector fp16 detection. Signed-off-by: Darren Hsieh <darren.hsieh@sifive.com> Change-Id: Ia7ee1bd8ec1a990f1b2b1700805942e99c0aa87b Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/4401738 Commit-Queue: Frank Barchard <fbarchard@chromium.org> Reviewed-by: Frank Barchard <fbarchard@chromium.org>
This commit is contained in:
parent
ec48e4328e
commit
aa47d668d8
@ -40,6 +40,9 @@ By default the cpu is detected and the most advanced form of SIMD is used. But
|
|||||||
LIBYUV_DISABLE_LSX
|
LIBYUV_DISABLE_LSX
|
||||||
LIBYUV_DISABLE_LASX
|
LIBYUV_DISABLE_LASX
|
||||||
|
|
||||||
|
## RISCV CPUs
|
||||||
|
LIBYUV_DISABLE_RVV
|
||||||
|
|
||||||
# Test Width/Height/Repeat
|
# Test Width/Height/Repeat
|
||||||
|
|
||||||
The unittests default to a small image (128x72) to run fast. This can be set by environment variable to test a specific resolutions.
|
The unittests default to a small image (128x72) to run fast. This can be set by environment variable to test a specific resolutions.
|
||||||
|
|||||||
@ -55,6 +55,11 @@ static const int kCpuHasLOONGARCH = 0x2000000;
|
|||||||
static const int kCpuHasLSX = 0x4000000;
|
static const int kCpuHasLSX = 0x4000000;
|
||||||
static const int kCpuHasLASX = 0x8000000;
|
static const int kCpuHasLASX = 0x8000000;
|
||||||
|
|
||||||
|
// These flags are only valid on RISCV processors.
|
||||||
|
static const int kCpuHasRISCV = 0x10000000;
|
||||||
|
static const int kCpuHasRVV = 0x20000000;
|
||||||
|
static const int kCpuHasRVVZVFH = 0x40000000;
|
||||||
|
|
||||||
// Optional init function. TestCpuFlag does an auto-init.
|
// Optional init function. TestCpuFlag does an auto-init.
|
||||||
// Returns cpu_info flags.
|
// Returns cpu_info flags.
|
||||||
LIBYUV_API
|
LIBYUV_API
|
||||||
@ -78,6 +83,8 @@ LIBYUV_API
|
|||||||
int ArmCpuCaps(const char* cpuinfo_name);
|
int ArmCpuCaps(const char* cpuinfo_name);
|
||||||
LIBYUV_API
|
LIBYUV_API
|
||||||
int MipsCpuCaps(const char* cpuinfo_name);
|
int MipsCpuCaps(const char* cpuinfo_name);
|
||||||
|
LIBYUV_API
|
||||||
|
int RiscvCpuCaps(const char* cpuinfo_name);
|
||||||
|
|
||||||
// For testing, allow CPU flags to be disabled.
|
// For testing, allow CPU flags to be disabled.
|
||||||
// ie MaskCpuFlags(~kCpuHasSSSE3) to disable SSSE3.
|
// ie MaskCpuFlags(~kCpuHasSSSE3) to disable SSSE3.
|
||||||
|
|||||||
@ -191,6 +191,63 @@ LIBYUV_API SAFEBUFFERS int MipsCpuCaps(const char* cpuinfo_name) {
|
|||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LIBYUV_API SAFEBUFFERS int RiscvCpuCaps(const char* cpuinfo_name) {
|
||||||
|
char cpuinfo_line[512];
|
||||||
|
int flag = 0x0;
|
||||||
|
FILE* f = fopen(cpuinfo_name, "r");
|
||||||
|
if (!f) {
|
||||||
|
// Assume nothing if /proc/cpuinfo is unavailable.
|
||||||
|
// This will occur for Chrome sandbox for Pepper or Render process.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
while (fgets(cpuinfo_line, sizeof(cpuinfo_line) - 1, f)) {
|
||||||
|
if (memcmp(cpuinfo_line, "isa", 3) == 0) {
|
||||||
|
// ISA string must begin with rv64{i,e,g} for a 64-bit processor.
|
||||||
|
char* isa = strstr(cpuinfo_line, "rv64");
|
||||||
|
if (isa) {
|
||||||
|
const int isa_len = strlen(isa);
|
||||||
|
// 5 ISA characters + 1 new-line character
|
||||||
|
if (isa_len < 6) {
|
||||||
|
fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// Skip {i,e,g} canonical checking.
|
||||||
|
// Skip rvxxx
|
||||||
|
isa += 5;
|
||||||
|
|
||||||
|
// Find the very first occurrence of 's', 'x' or 'z'.
|
||||||
|
// To detect multi-letter standard, non-standard, and
|
||||||
|
// supervisor-level extensions.
|
||||||
|
int otherExts_len = 0;
|
||||||
|
char* otherExts = strpbrk(isa, "zxs");
|
||||||
|
if (otherExts) {
|
||||||
|
otherExts_len = strlen(otherExts);
|
||||||
|
// Multi-letter extensions are seperated by a single underscore
|
||||||
|
// as described in RISC-V User-Level ISA V2.2.
|
||||||
|
char* ext = strtok(otherExts, "_");
|
||||||
|
while (ext) {
|
||||||
|
// Search for the ZVFH (Vector FP16) extension.
|
||||||
|
// The ZVFH implied the (Scalar FP16)ZFH extension.
|
||||||
|
if (!strcmp(ext, "zvfh") || !strcmp(ext, "zvfh\n")) {
|
||||||
|
flag |= kCpuHasRVVZVFH;
|
||||||
|
}
|
||||||
|
ext = strtok(NULL, "_");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const int std_isa_len = isa_len - otherExts_len - 5 - 1;
|
||||||
|
// Detect the v in the standard single-letter extensions.
|
||||||
|
// Skip optional Zve* and Zvl* extensions detection at otherExts.
|
||||||
|
if (memchr(isa, 'v', std_isa_len)) {
|
||||||
|
// The RVV implied the F extension.
|
||||||
|
flag |= kCpuHasRVV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(fbarchard): Consider read_loongarch_ir().
|
// TODO(fbarchard): Consider read_loongarch_ir().
|
||||||
#define LOONGARCH_CFG2 0x2
|
#define LOONGARCH_CFG2 0x2
|
||||||
#define LOONGARCH_CFG2_LSX (1 << 6)
|
#define LOONGARCH_CFG2_LSX (1 << 6)
|
||||||
@ -277,6 +334,10 @@ static SAFEBUFFERS int GetCpuFlags(void) {
|
|||||||
#endif
|
#endif
|
||||||
cpu_info |= kCpuHasARM;
|
cpu_info |= kCpuHasARM;
|
||||||
#endif // __arm__
|
#endif // __arm__
|
||||||
|
#if defined(__riscv) && defined(__linux__)
|
||||||
|
cpu_info = RiscvCpuCaps("/proc/cpuinfo");
|
||||||
|
cpu_info |= kCpuHasRISCV;
|
||||||
|
#endif // __riscv
|
||||||
cpu_info |= kCpuInitialized;
|
cpu_info |= kCpuInitialized;
|
||||||
return cpu_info;
|
return cpu_info;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,14 @@ TEST_F(LibYUVBaseTest, TestCpuHas) {
|
|||||||
printf("Has ARM %d\n", has_arm);
|
printf("Has ARM %d\n", has_arm);
|
||||||
int has_neon = TestCpuFlag(kCpuHasNEON);
|
int has_neon = TestCpuFlag(kCpuHasNEON);
|
||||||
printf("Has NEON %d\n", has_neon);
|
printf("Has NEON %d\n", has_neon);
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv) && defined(__linux__)
|
||||||
|
int has_riscv = TestCpuFlag(kCpuHasRISCV);
|
||||||
|
printf("Has RISCV %d\n", has_riscv);
|
||||||
|
int has_rvv = TestCpuFlag(kCpuHasRVV);
|
||||||
|
printf("Has RVV %d\n", has_rvv);
|
||||||
|
int has_rvvzvfh = TestCpuFlag(kCpuHasRVVZVFH);
|
||||||
|
printf("Has RVVZVFH %d\n", has_rvvzvfh);
|
||||||
#endif
|
#endif
|
||||||
int has_x86 = TestCpuFlag(kCpuHasX86);
|
int has_x86 = TestCpuFlag(kCpuHasX86);
|
||||||
int has_sse2 = TestCpuFlag(kCpuHasSSE2);
|
int has_sse2 = TestCpuFlag(kCpuHasSSE2);
|
||||||
@ -164,6 +172,9 @@ TEST_F(LibYUVBaseTest, TestCompilerMacros) {
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
printf("_WIN32 %d\n", _WIN32);
|
printf("_WIN32 %d\n", _WIN32);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef __riscv
|
||||||
|
printf("__riscv %d\n", __riscv);
|
||||||
|
#endif
|
||||||
#ifdef GG_LONGLONG
|
#ifdef GG_LONGLONG
|
||||||
printf("GG_LONGLONG %d\n", GG_LONGLONG);
|
printf("GG_LONGLONG %d\n", GG_LONGLONG);
|
||||||
#endif
|
#endif
|
||||||
@ -264,6 +275,32 @@ TEST_F(LibYUVBaseTest, TestLinuxMipsMsa) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(LibYUVBaseTest, TestLinuxRVV) {
|
||||||
|
if (FileExists("../../unit_test/testdata/riscv64.txt")) {
|
||||||
|
printf("Note: testing to load \"../../unit_test/testdata/riscv64.txt\"\n");
|
||||||
|
|
||||||
|
EXPECT_EQ(0, RiscvCpuCaps("../../unit_test/testdata/riscv64.txt"));
|
||||||
|
EXPECT_EQ(kCpuHasRVV,
|
||||||
|
RiscvCpuCaps("../../unit_test/testdata/riscv64_rvv.txt"));
|
||||||
|
EXPECT_EQ(kCpuHasRVV | kCpuHasRVVZVFH,
|
||||||
|
RiscvCpuCaps("../../unit_test/testdata/riscv64_rvv_zvfh.txt"));
|
||||||
|
} else {
|
||||||
|
printf(
|
||||||
|
"WARNING: unable to load "
|
||||||
|
"\"../../unit_test/testdata/riscv64.txt\"\n");
|
||||||
|
}
|
||||||
|
#if defined(__linux__) && defined(__riscv)
|
||||||
|
if (FileExists("/proc/cpuinfo")) {
|
||||||
|
if (!(kCpuHasRVV & RiscvCpuCaps("/proc/cpuinfo"))) {
|
||||||
|
// This can happen on RVV emulator but /proc/cpuinfo is from host.
|
||||||
|
printf("WARNING: RVV build enabled but CPU does not have RVV\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("WARNING: unable to load \"/proc/cpuinfo\"\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(fbarchard): Fix clangcl test of cpuflags.
|
// TODO(fbarchard): Fix clangcl test of cpuflags.
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
TEST_F(LibYUVBaseTest, DISABLED_TestSetCpuFlags) {
|
TEST_F(LibYUVBaseTest, DISABLED_TestSetCpuFlags) {
|
||||||
|
|||||||
4
unit_test/testdata/riscv64.txt
vendored
Normal file
4
unit_test/testdata/riscv64.txt
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
processor : 0
|
||||||
|
hart : 1
|
||||||
|
isa : rv64imac
|
||||||
|
mmu : sv48
|
||||||
4
unit_test/testdata/riscv64_rvv.txt
vendored
Normal file
4
unit_test/testdata/riscv64_rvv.txt
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
processor : 0
|
||||||
|
hart : 1
|
||||||
|
isa : rv64imafdcv
|
||||||
|
mmu : sv48
|
||||||
4
unit_test/testdata/riscv64_rvv_zvfh.txt
vendored
Normal file
4
unit_test/testdata/riscv64_rvv_zvfh.txt
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
processor : 0
|
||||||
|
hart : 1
|
||||||
|
isa : rv64imafdcv_zfh_zvfh
|
||||||
|
mmu : sv48
|
||||||
@ -88,6 +88,11 @@ int TestCpuEnv(int cpu_info) {
|
|||||||
cpu_info &= ~libyuv::kCpuHasLASX;
|
cpu_info &= ~libyuv::kCpuHasLASX;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(__riscv) && defined(__linux__)
|
||||||
|
if (TestEnv("LIBYUV_DISABLE_RVV")) {
|
||||||
|
cpu_info &= ~libyuv::kCpuHasRVV;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#if !defined(__pnacl__) && !defined(__CLR_VER) && \
|
#if !defined(__pnacl__) && !defined(__CLR_VER) && \
|
||||||
(defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \
|
(defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \
|
||||||
defined(_M_IX86))
|
defined(_M_IX86))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user