2022-09-26 14:52:21 +00:00
|
|
|
/*
|
|
|
|
* Copyright © 2022 Rémi Denis-Courmont.
|
|
|
|
*
|
|
|
|
* This file is part of FFmpeg.
|
|
|
|
*
|
|
|
|
* FFmpeg is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* FFmpeg is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with FFmpeg; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*/
|
|
|
|
|
2023-11-18 20:09:57 +00:00
|
|
|
#define _GNU_SOURCE
|
2022-09-26 14:52:21 +00:00
|
|
|
#include "libavutil/cpu.h"
|
|
|
|
#include "libavutil/cpu_internal.h"
|
2023-11-18 20:09:57 +00:00
|
|
|
#include "libavutil/macros.h"
|
2022-09-26 14:52:21 +00:00
|
|
|
#include "libavutil/log.h"
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#if HAVE_GETAUXVAL
|
|
|
|
#include <sys/auxv.h>
|
|
|
|
#define HWCAP_RV(letter) (1ul << ((letter) - 'A'))
|
|
|
|
#endif
|
2024-05-07 15:28:03 +00:00
|
|
|
#if HAVE_SYS_HWPROBE_H
|
2023-11-18 20:09:57 +00:00
|
|
|
#include <sys/hwprobe.h>
|
2024-05-03 17:08:03 +00:00
|
|
|
#elif HAVE_ASM_HWPROBE_H
|
|
|
|
#include <asm/hwprobe.h>
|
|
|
|
#include <sys/syscall.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
static int __riscv_hwprobe(struct riscv_hwprobe *pairs, size_t pair_count,
|
|
|
|
size_t cpu_count, unsigned long *cpus,
|
|
|
|
unsigned int flags)
|
|
|
|
{
|
|
|
|
return syscall(__NR_riscv_hwprobe, pairs, pair_count, cpu_count, cpus,
|
|
|
|
flags);
|
|
|
|
}
|
2023-11-18 20:09:57 +00:00
|
|
|
#endif
|
2022-09-26 14:52:21 +00:00
|
|
|
|
|
|
|
int ff_get_cpu_flags_riscv(void)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
2024-05-03 17:08:03 +00:00
|
|
|
#if HAVE_SYS_HWPROBE_H || HAVE_ASM_HWPROBE_H
|
2023-11-18 20:09:57 +00:00
|
|
|
struct riscv_hwprobe pairs[] = {
|
|
|
|
{ RISCV_HWPROBE_KEY_BASE_BEHAVIOR, 0 },
|
|
|
|
{ RISCV_HWPROBE_KEY_IMA_EXT_0, 0 },
|
2024-05-11 15:49:24 +00:00
|
|
|
{ RISCV_HWPROBE_KEY_CPUPERF_0, 0 },
|
2023-11-18 20:09:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if (__riscv_hwprobe(pairs, FF_ARRAY_ELEMS(pairs), 0, NULL, 0) == 0) {
|
|
|
|
if (pairs[0].value & RISCV_HWPROBE_BASE_BEHAVIOR_IMA)
|
|
|
|
ret |= AV_CPU_FLAG_RVI;
|
|
|
|
if (pairs[1].value & RISCV_HWPROBE_IMA_FD)
|
|
|
|
ret |= AV_CPU_FLAG_RVF | AV_CPU_FLAG_RVD;
|
2024-05-03 17:08:03 +00:00
|
|
|
#ifdef RISCV_HWPROBE_IMA_V
|
2023-11-18 20:09:57 +00:00
|
|
|
if (pairs[1].value & RISCV_HWPROBE_IMA_V)
|
|
|
|
ret |= AV_CPU_FLAG_RVV_I32 | AV_CPU_FLAG_RVV_I64
|
|
|
|
| AV_CPU_FLAG_RVV_F32 | AV_CPU_FLAG_RVV_F64;
|
2024-05-03 17:08:03 +00:00
|
|
|
#endif
|
|
|
|
#ifdef RISCV_HWPROBE_EXT_ZBA
|
2023-11-18 20:09:57 +00:00
|
|
|
if (pairs[1].value & RISCV_HWPROBE_EXT_ZBA)
|
|
|
|
ret |= AV_CPU_FLAG_RVB_ADDR;
|
2024-05-03 17:08:03 +00:00
|
|
|
#endif
|
|
|
|
#ifdef RISCV_HWPROBE_EXT_ZBB
|
2023-11-18 20:09:57 +00:00
|
|
|
if (pairs[1].value & RISCV_HWPROBE_EXT_ZBB)
|
|
|
|
ret |= AV_CPU_FLAG_RVB_BASIC;
|
2024-05-03 17:08:03 +00:00
|
|
|
#endif
|
2024-05-07 19:09:27 +00:00
|
|
|
#ifdef RISCV_HWPROBE_EXT_ZVBB
|
|
|
|
if (pairs[1].value & RISCV_HWPROBE_EXT_ZVBB)
|
|
|
|
ret |= AV_CPU_FLAG_RV_ZVBB;
|
|
|
|
#endif
|
2024-05-14 20:13:12 +00:00
|
|
|
switch (pairs[2].value & RISCV_HWPROBE_MISALIGNED_MASK) {
|
|
|
|
case RISCV_HWPROBE_MISALIGNED_FAST:
|
|
|
|
ret |= AV_CPU_FLAG_RV_MISALIGNED;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
}
|
2023-11-18 20:09:57 +00:00
|
|
|
} else
|
|
|
|
#endif
|
2022-09-26 14:52:21 +00:00
|
|
|
#if HAVE_GETAUXVAL
|
2023-11-18 20:08:58 +00:00
|
|
|
{
|
|
|
|
const unsigned long hwcap = getauxval(AT_HWCAP);
|
2022-09-26 14:52:21 +00:00
|
|
|
|
2023-11-18 20:08:58 +00:00
|
|
|
if (hwcap & HWCAP_RV('I'))
|
|
|
|
ret |= AV_CPU_FLAG_RVI;
|
|
|
|
if (hwcap & HWCAP_RV('F'))
|
|
|
|
ret |= AV_CPU_FLAG_RVF;
|
|
|
|
if (hwcap & HWCAP_RV('D'))
|
|
|
|
ret |= AV_CPU_FLAG_RVD;
|
lavu/cpu: CPU flags for the RISC-V Vector extension
RVV defines a total of 12 different extensions, including:
- 5 different instruction subsets:
- Zve32x: 8-, 16- and 32-bit integers,
- Zve32f: Zve32x plus single precision floats,
- Zve64x: Zve32x plus 64-bit integers,
- Zve64f: Zve32f plus Zve64x,
- Zve64d: Zve64f plus double precision floats.
- 6 different vector lengths:
- Zvl32b (embedded only),
- Zvl64b (embedded only),
- Zvl128b,
- Zvl256b,
- Zvl512b,
- Zvl1024b,
- and the V extension proper: equivalent to Zve64f and Zvl128b.
In total, there are 6 different possible sets of supported instructions
(including the empty set), but for convenience we allocate one bit for
each type sets: up-to-32-bit ints (RVV_I32), floats (RVV_F32),
64-bit ints (RVV_I64) and doubles (RVV_F64).
Whence the vector size is needed, it can be retrieved by reading the
unprivileged read-only vlenb CSR. This should probably be a separate
helper macro if needed at a later point.
2022-09-26 14:52:25 +00:00
|
|
|
|
2023-11-18 20:08:58 +00:00
|
|
|
/* The V extension implies all Zve* functional subsets */
|
|
|
|
if (hwcap & HWCAP_RV('V'))
|
|
|
|
ret |= AV_CPU_FLAG_RVV_I32 | AV_CPU_FLAG_RVV_I64
|
|
|
|
| AV_CPU_FLAG_RVV_F32 | AV_CPU_FLAG_RVV_F64;
|
|
|
|
}
|
2022-09-26 14:52:21 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __riscv_i
|
|
|
|
ret |= AV_CPU_FLAG_RVI;
|
|
|
|
#endif
|
|
|
|
#if defined (__riscv_flen) && (__riscv_flen >= 32)
|
|
|
|
ret |= AV_CPU_FLAG_RVF;
|
|
|
|
#if (__riscv_flen >= 64)
|
|
|
|
ret |= AV_CPU_FLAG_RVD;
|
|
|
|
#endif
|
lavu/cpu: CPU flags for the RISC-V Vector extension
RVV defines a total of 12 different extensions, including:
- 5 different instruction subsets:
- Zve32x: 8-, 16- and 32-bit integers,
- Zve32f: Zve32x plus single precision floats,
- Zve64x: Zve32x plus 64-bit integers,
- Zve64f: Zve32f plus Zve64x,
- Zve64d: Zve64f plus double precision floats.
- 6 different vector lengths:
- Zvl32b (embedded only),
- Zvl64b (embedded only),
- Zvl128b,
- Zvl256b,
- Zvl512b,
- Zvl1024b,
- and the V extension proper: equivalent to Zve64f and Zvl128b.
In total, there are 6 different possible sets of supported instructions
(including the empty set), but for convenience we allocate one bit for
each type sets: up-to-32-bit ints (RVV_I32), floats (RVV_F32),
64-bit ints (RVV_I64) and doubles (RVV_F64).
Whence the vector size is needed, it can be retrieved by reading the
unprivileged read-only vlenb CSR. This should probably be a separate
helper macro if needed at a later point.
2022-09-26 14:52:25 +00:00
|
|
|
#endif
|
|
|
|
|
2023-07-16 12:08:08 +00:00
|
|
|
#ifdef __riscv_zba
|
|
|
|
ret |= AV_CPU_FLAG_RVB_ADDR;
|
|
|
|
#endif
|
lavu/riscv: CPU flag for the Zbb extension
Unfortunately, it is common, and will remain so, that the Bit
manipulations are not enabled at compilation time. This is an official
policy for Debian ports in general (though they do not support RISC-V
officially as of yet) to stick to the minimal target baseline, which
does not include the B extension or even its Zbb subset.
For inline helpers (CPOP, REV8), compiler builtins (CTZ, CLZ) or
even plain C code (MIN, MAX, MINU, MAXU), run-time detection seems
impractical. But at least it can work for the byte-swap DSP functions.
2022-10-02 11:54:58 +00:00
|
|
|
#ifdef __riscv_zbb
|
|
|
|
ret |= AV_CPU_FLAG_RVB_BASIC;
|
|
|
|
#endif
|
|
|
|
|
lavu/cpu: CPU flags for the RISC-V Vector extension
RVV defines a total of 12 different extensions, including:
- 5 different instruction subsets:
- Zve32x: 8-, 16- and 32-bit integers,
- Zve32f: Zve32x plus single precision floats,
- Zve64x: Zve32x plus 64-bit integers,
- Zve64f: Zve32f plus Zve64x,
- Zve64d: Zve64f plus double precision floats.
- 6 different vector lengths:
- Zvl32b (embedded only),
- Zvl64b (embedded only),
- Zvl128b,
- Zvl256b,
- Zvl512b,
- Zvl1024b,
- and the V extension proper: equivalent to Zve64f and Zvl128b.
In total, there are 6 different possible sets of supported instructions
(including the empty set), but for convenience we allocate one bit for
each type sets: up-to-32-bit ints (RVV_I32), floats (RVV_F32),
64-bit ints (RVV_I64) and doubles (RVV_F64).
Whence the vector size is needed, it can be retrieved by reading the
unprivileged read-only vlenb CSR. This should probably be a separate
helper macro if needed at a later point.
2022-09-26 14:52:25 +00:00
|
|
|
/* If RV-V is enabled statically at compile-time, check the details. */
|
2023-10-26 16:04:27 +00:00
|
|
|
#ifdef __riscv_vector
|
lavu/cpu: CPU flags for the RISC-V Vector extension
RVV defines a total of 12 different extensions, including:
- 5 different instruction subsets:
- Zve32x: 8-, 16- and 32-bit integers,
- Zve32f: Zve32x plus single precision floats,
- Zve64x: Zve32x plus 64-bit integers,
- Zve64f: Zve32f plus Zve64x,
- Zve64d: Zve64f plus double precision floats.
- 6 different vector lengths:
- Zvl32b (embedded only),
- Zvl64b (embedded only),
- Zvl128b,
- Zvl256b,
- Zvl512b,
- Zvl1024b,
- and the V extension proper: equivalent to Zve64f and Zvl128b.
In total, there are 6 different possible sets of supported instructions
(including the empty set), but for convenience we allocate one bit for
each type sets: up-to-32-bit ints (RVV_I32), floats (RVV_F32),
64-bit ints (RVV_I64) and doubles (RVV_F64).
Whence the vector size is needed, it can be retrieved by reading the
unprivileged read-only vlenb CSR. This should probably be a separate
helper macro if needed at a later point.
2022-09-26 14:52:25 +00:00
|
|
|
ret |= AV_CPU_FLAG_RVV_I32;
|
|
|
|
#if __riscv_v_elen >= 64
|
|
|
|
ret |= AV_CPU_FLAG_RVV_I64;
|
|
|
|
#endif
|
|
|
|
#if __riscv_v_elen_fp >= 32
|
|
|
|
ret |= AV_CPU_FLAG_RVV_F32;
|
|
|
|
#if __riscv_v_elen_fp >= 64
|
|
|
|
ret |= AV_CPU_FLAG_RVV_F64;
|
|
|
|
#endif
|
|
|
|
#endif
|
2024-05-07 19:09:27 +00:00
|
|
|
#endif
|
|
|
|
#ifdef __riscv_zvbb
|
|
|
|
ret |= AV_CPU_FLAG_RV_ZVBB;
|
2022-09-26 14:52:21 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|