Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
176 changes: 176 additions & 0 deletions .github/workflows/build-and-test-riscv.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@

name: "RISC-V Build & Test"

on:
push:
pull_request:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

env:
# Cross-compile for riscv64 targeting the RVV 1.0 ISA (rv64gcv).
# The experimental RVVM1 SIMD backend is enabled here so that the
# vector code paths are also built and exercised under QEMU.
COMMON_CMAKE_FLAGS: >
-DSLEEF_SHOW_CONFIG=1
-DSLEEF_BUILD_INLINE_HEADERS=ON
-DSLEEF_BUILD_DFT=ON
-DSLEEF_ENFORCE_DFT=ON
-DSLEEF_BUILD_QUAD=ON
-DSLEEF_BUILD_STATIC_TEST_BINS=OFF
-DSLEEF_ENABLE_RVVM1=ON
-DSLEEF_ENFORCE_RVVM1=ON

jobs:
build-riscv:
runs-on: ubuntu-24.04
name: build-riscv64-gcc

steps:
- uses: actions/checkout@v4.1.1
with:
persist-credentials: false

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
cmake ninja-build pkg-config \
libmpfr-dev libgmp-dev libssl-dev \
qemu-user-static binfmt-support \
gcc-14-riscv64-linux-gnu g++-14-riscv64-linux-gnu

- name: Print compiler and tool versions
run: |
riscv64-linux-gnu-gcc-14 --version
riscv64-linux-gnu-g++-14 --version
qemu-riscv64-static --version
cmake --version

- name: Native build (host tools required for cross build)
shell: bash -ex -o pipefail {0}
run: |
export NATIVE_INSTALL_PREFIX=$(pwd)/_install-native
cmake -S . -B _build-native -GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=$NATIVE_INSTALL_PREFIX \
-DSLEEF_SHOW_CONFIG=1 \
-DSLEEF_BUILD_QUAD=ON \
-DSLEEF_BUILD_DFT=ON \
-DSLEEF_ENFORCE_DFT=OFF
cmake --build _build-native -j$(nproc)

- name: Cross-build for RISC-V (rv64gcv, RVVM1)
shell: bash -ex -o pipefail {0}
run: |
# The shipped riscv64-gcc.cmake toolchain file only configures
# CMAKE_C_COMPILER via find_program. CMake otherwise falls back
# to the host /usr/bin/c++ for CXX. Resolve absolute paths and
# pass both compilers explicitly.
RISCV_CC=$(command -v riscv64-linux-gnu-gcc-14)
RISCV_CXX=$(command -v riscv64-linux-gnu-g++-14)
echo "Using CC=$RISCV_CC CXX=$RISCV_CXX"
export CROSS_INSTALL_PREFIX=$(pwd)/_install-riscv
# The RVVM1 backend is enabled via SLEEF_ENABLE_RVVM1 /
# SLEEF_ENFORCE_RVVM1. SLEEF's Configure.cmake automatically
# appends -march=rv64gcv_zba_zbb_zbs to the RVVM1 sources, so
# the toolchain does not need a global -march override.
cmake -S . -B _build-riscv -GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=$(pwd)/toolchains/riscv64-gcc.cmake \
-DCMAKE_C_COMPILER="$RISCV_CC" \
-DCMAKE_CXX_COMPILER="$RISCV_CXX" \
-DNATIVE_BUILD_DIR=$(pwd)/_build-native \
-DCMAKE_INSTALL_PREFIX=$CROSS_INSTALL_PREFIX \
${COMMON_CMAKE_FLAGS}
cmake --build _build-riscv -j$(nproc)
cmake --install _build-riscv

- name: Upload build-riscv64-gcc artifacts
uses: actions/upload-artifact@v4
with:
name: build-riscv64-gcc
path: |
_build-riscv
_install-riscv
if: always()

test-riscv:
runs-on: ubuntu-24.04
needs: [build-riscv]
name: test-riscv64-gcc
env:
# QEMU user-mode needs to be told where the riscv64 sysroot
# lives so it can locate the dynamic linker
# (/lib/ld-linux-riscv64-lp64d.so.1). Without this the kernel
# binfmt_misc handler invokes qemu-riscv64-static and qemu
# fails with "Could not open '/lib/ld-linux-riscv64-lp64d.so.1'".
QEMU_LD_PREFIX: /usr/riscv64-linux-gnu

steps:
- uses: actions/checkout@v4.1.1
with:
persist-credentials: false

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
cmake ninja-build \
libmpfr-dev libgmp-dev libssl-dev \
qemu-user-static binfmt-support \
gcc-14-riscv64-linux-gnu g++-14-riscv64-linux-gnu

- name: Register QEMU binfmt for riscv64
run: |
# Make sure the kernel binfmt_misc handler is enabled so
# RISC-V binaries are transparently launched under QEMU.
sudo update-binfmts --enable qemu-riscv64 || true
cat /proc/sys/fs/binfmt_misc/qemu-riscv64 || true
# Sanity check
echo 'int main(void){return 0;}' | riscv64-linux-gnu-gcc-14 -x c - -o /tmp/_rvchk
/tmp/_rvchk && echo "binfmt OK"

- name: Download build-riscv64-gcc artifacts
uses: actions/download-artifact@v4
with:
name: build-riscv64-gcc

- name: Fix permissions
run: |
chmod -R +x _build-riscv/bin || true

- name: Test riscv64 (under QEMU)
env:
CTEST_OUTPUT_ON_FAILURE: "TRUE"
OMP_WAIT_POLICY: passive
run: |
export LD_LIBRARY_PATH=$(pwd)/_install-riscv/lib:$(pwd)/_install-riscv/lib64
cd _build-riscv
# QEMU emulation is much slower than native, so use fewer parallel
# jobs to avoid timeouts and excessive memory use.
ctest -j2 --output-on-failure --timeout 1800

- name: Hello example RISC-V
shell: bash -ex -o pipefail {0}
run: |
export LD_LIBRARY_PATH=$(pwd)/_install-riscv/lib:$(pwd)/_install-riscv/lib64
RISCV_CC=$(command -v riscv64-linux-gnu-gcc-14)
"$RISCV_CC" -march=rv64gcv_zba_zbb_zbs -static \
docs/src/helloriscv.c -o hello-riscv \
-I"$(pwd)/_install-riscv/include" \
-L"$(pwd)/_install-riscv/lib" -lsleef
qemu-riscv64-static -L /usr/riscv64-linux-gnu ./hello-riscv

- name: Upload test-riscv64-gcc artifacts
uses: actions/upload-artifact@v4
with:
name: test-riscv64-gcc
path: |
_build-riscv/Testing
if: always()
24 changes: 24 additions & 0 deletions docs/src/helloriscv.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <stdio.h>
#include <riscv_vector.h>
#include <sleef.h>

int main(int argc, char **argv) {
double a[] = {2, 10};
double b[] = {3, 20};

size_t vl = __riscv_vsetvl_e64m1(2);

vfloat64m1_t va, vb, vc;

va = __riscv_vle64_v_f64m1(a, vl);
vb = __riscv_vle64_v_f64m1(b, vl);

vc = Sleef_powdx_u10rvvm1(va, vb);

double c[2];

__riscv_vse64_v_f64m1(c, vc, vl);

printf("pow(%g, %g) = %g\n", a[0], b[0], c[0]);
printf("pow(%g, %g) = %g\n", a[1], b[1], c[1]);
}
12 changes: 7 additions & 5 deletions src/arch/helperrvv.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,14 @@
//@#define ENABLE_FMA_DP
#endif

#if __riscv_v_intrinsic < 1000000 && !(defined(__clang_major__) && __clang_major__ >= 18)
#if __riscv_v_intrinsic < 1000000 && \
!(defined(__clang_major__) && __clang_major__ >= 18) && \
!(defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 14)
// __riscv_vcreate* intrinsics only showed up in v1.0-rc0 of the RVV intrinsics
// spec and have already been implemented in clang-18, but are useful for
// eliminating issues with uninitialised data because they are explicit that
// the whole result has defined values. Here we do our best to offer fallback
// implementations where needed.
// spec and have already been implemented in clang-18 and gcc-14, but are
// useful for eliminating issues with uninitialised data because they are
// explicit that the whole result has defined values. Here we do our best to
// offer fallback implementations where needed.
//
#define __riscv_vcreate_v_f32m1_f32m2(x, y) __riscv_vset(__riscv_vlmul_ext_v_f32m1_f32m2(x), 1, y)
#define __riscv_vcreate_v_f32m2_f32m4(x, y) __riscv_vset(__riscv_vlmul_ext_v_f32m2_f32m4(x), 1, y)
Expand Down