]> git.ipfire.org Git - thirdparty/zlib-ng.git/commitdiff
Add supporting RISC-V cross compilation workflows
authorAlex Chiang <achiang@sw04.internal.sifive.com>
Thu, 27 Apr 2023 08:40:15 +0000 (01:40 -0700)
committerHans Kristian Rosbach <hk-github@circlestorm.org>
Fri, 12 May 2023 14:57:32 +0000 (16:57 +0200)
Add RISC-V cross-compilation test
Enable RVV support at compile time

.github/workflows/cmake.yml
CMakeLists.txt
README.md
arch/riscv/README.md [new file with mode: 0644]
arch/riscv/riscv_features.c [new file with mode: 0644]
arch/riscv/riscv_features.h [new file with mode: 0644]
cmake/detect-intrinsics.cmake
cmake/toolchain-riscv.cmake [new file with mode: 0644]
cpu_features.c
cpu_features.h

index d50a2dcfab245a3004565bd065299c6bb8906fe8..bbed1db0ca8720baf77f4bf73e45ba65fec52ac5 100644 (file)
@@ -378,6 +378,12 @@ jobs:
             # https://github.com/llvm/llvm-project/issues/55785
             msan-options: use_sigaltstack=0
 
+          - name: Ubuntu Clang RISC-V
+            os: ubuntu-latest
+            cmake-args: -GNinja -DCMAKE_TOOLCHAIN_FILE=./cmake/toolchain-riscv.cmake -DTOOLCHAIN_PATH=${PWD}/prebuilt-riscv-toolchain-qemu/riscv-clang -DQEMU_PATH=${PWD}/prebuilt-riscv-toolchain-qemu/riscv-qemu/bin/qemu-riscv64
+            packages: build-essential cmake ninja-build
+            codecov: ubuntu_clang_toolchain_riscv
+
           - name: Ubuntu Emscripten WASM32
             os: ubuntu-latest
             chost: wasm32
@@ -502,6 +508,14 @@ jobs:
         sudo apt-get update
         sudo apt-get install -y --allow-downgrades --no-install-recommends ${{ matrix.packages }}
 
+    - name: Download prebuilt RISC-V Clang toolchain & QEMU emulator
+      if: runner.os == 'Linux' && contains(matrix.name, 'RISC-V')
+      run: |
+        gh release download ubuntu20.04_llvm16.0.0_qemu7.0.0 --repo sifive/prepare-riscv-toolchain-qemu
+        tar zxvf prebuilt-riscv-toolchain-qemu.tar.gz
+      env:
+        GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
     - name: Install packages (Windows)
       if: runner.os == 'Windows'
       run: |
index cdb38311ddab0968adab0aa127694c55675f0da3..a6199d35ab37ccdac3fd4055a579baa7e0f64f0d 100644 (file)
@@ -105,6 +105,8 @@ elseif(BASEARCH_PPC_FOUND)
     option(WITH_ALTIVEC "Build with AltiVec (VMX) optimisations for PowerPC" ON)
     option(WITH_POWER8 "Build with optimisations for POWER8" ON)
     option(WITH_POWER9 "Build with optimisations for POWER9" ON)
+elseif(BASEARCH_RISCV_FOUND)
+    option(WITH_RVV "Build with RVV intrinsics" ON)
 elseif(BASEARCH_S360_FOUND)
     option(WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z" OFF)
     option(WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z" OFF)
@@ -135,6 +137,7 @@ mark_as_advanced(FORCE
     WITH_ALTIVEC
     WITH_POWER8
     WITH_POWER9
+    WITH_RVV
     WITH_INFLATE_STRICT
     WITH_INFLATE_ALLOW_INVALID_DIST
     WITH_UNALIGNED
@@ -544,6 +547,8 @@ if(BASEARCH_ARM_FOUND)
     set(ARCHDIR "arch/arm")
 elseif(BASEARCH_PPC_FOUND)
     set(ARCHDIR "arch/power")
+elseif(BASEARCH_RISCV_FOUND)
+    set(ARCHDIR "arch/riscv")
 elseif(BASEARCH_S360_FOUND)
     set(ARCHDIR "arch/s390")
 elseif(BASEARCH_X86_FOUND)
@@ -718,6 +723,18 @@ if(WITH_OPTIM)
                 set(WITH_POWER9 OFF)
             endif()
         endif()
+    elseif(BASEARCH_RISCV_FOUND)
+        if(WITH_RVV)
+            check_rvv_intrinsics()
+            if(HAVE_RVV_INTRIN)
+                add_definitions(-DRISCV_FEATURES)
+                add_definitions(-DRISCV_RVV)
+                list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/riscv_features.h)
+                list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/riscv_features.c)
+            else()
+                set(WITH_RVV OFF)
+            endif()
+        endif()
     elseif(BASEARCH_S360_FOUND)
         check_s390_intrinsics()
         if(HAVE_S390_INTRIN)
@@ -1228,6 +1245,8 @@ elseif(BASEARCH_PPC_FOUND)
     add_feature_info(WITH_ALTIVEC WITH_ALTIVEC "Build with AltiVec optimisations")
     add_feature_info(WITH_POWER8 WITH_POWER8 "Build with optimisations for POWER8")
     add_feature_info(WITH_POWER9 WITH_POWER9 "Build with optimisations for POWER9")
+elseif(BASEARCH_RISCV_FOUND)
+    add_feature_info(WITH_RVV WITH_RVV "Build with RVV intrinsics")
 elseif(BASEARCH_S360_FOUND)
     add_feature_info(WITH_DFLTCC_DEFLATE WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z")
     add_feature_info(WITH_DFLTCC_INFLATE WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z")
index aa72365c9526b306c0b36b0c672c47d8a38ddbb1..367dc9463b3342b618fd28e7de7f15176abd7b45 100644 (file)
--- a/README.md
+++ b/README.md
@@ -34,7 +34,7 @@ Features
 * Comprehensive set of CMake unit tests
 * Code sanitizers, fuzzing, and coverage
 * GitHub Actions continuous integration on Windows, macOS, and Linux
-  * Emulated CI for ARM, AARCH64, PPC, PPC64, SPARC64, S390x using qemu
+  * Emulated CI for ARM, AARCH64, PPC, PPC64, RISCV, SPARC64, S390x using qemu
 
 
 History
@@ -221,6 +221,7 @@ Advanced Build Options
 | WITH_NEON                       | --without-neon        | Build with NEON intrinsics                                          | ON                     |
 | WITH_ALTIVEC                    | --without-altivec     | Build with AltiVec (VMX) intrinsics                                 | ON                     |
 | WITH_POWER8                     | --without-power8      | Build with POWER8 optimisations                                     | ON                     |
+| WITH_RVV                        |                       | Build with RVV intrinsics                                           | ON                     |
 | WITH_CRC32_VX                   | --without-crc32-vx    | Build with vectorized CRC32 on IBM Z                                | ON                     |
 | WITH_DFLTCC_DEFLATE             | --with-dfltcc-deflate | Build with DFLTCC intrinsics for compression on IBM Z               | OFF                    |
 | WITH_DFLTCC_INFLATE             | --with-dfltcc-inflate | Build with DFLTCC intrinsics for decompression on IBM Z             | OFF                    |
diff --git a/arch/riscv/README.md b/arch/riscv/README.md
new file mode 100644 (file)
index 0000000..b4309e1
--- /dev/null
@@ -0,0 +1,45 @@
+# Building RISC-V Target with Cmake #
+
+> **Warning**
+> We cannot detect rvv support at runtime, running the rvv code on a no-rvv target is a risk. Users should disable the rvv when the target does not support it. 
+>
+> We will have a better solution when the kernels update `hwcap` or `hwprobe` for risc-v.
+
+## Prerequisite: Build RISC-V Clang Toolchain and QEMU ##
+
+If you don't have prebuilt clang and riscv64 qemu, you can refer to the [script](https://github.com/sifive/prepare-riscv-toolchain-qemu/blob/main/prepare_riscv_toolchain_qemu.sh) to get the source. Copy the script to the zlib-ng root directory, and run it to download the source and build them. Modify the content according to your conditions (e.g., toolchain version).
+
+```bash
+./prepare_riscv_toolchain_qemu.sh
+```
+
+After running script, clang & qemu are built in `build-toolchain-qemu/riscv-clang/` & `build-toolchain-qemu/riscv-qemu/`.
+
+`build-toolchain-qemu/riscv-clang/` is your `TOOLCHAIN_PATH`.
+`build-toolchain-qemu/riscv-qemu/bin/qemu-riscv64` is your `QEMU_PATH`.
+
+You can also download the prebuilt toolchain & qemu from [the release page](https://github.com/sifive/prepare-riscv-toolchain-qemu/releases), and enjoy using them.
+
+## Cross-Compile for RISC-V Target ##
+
+```bash
+cmake -G Ninja -B ./build-riscv \
+  -D CMAKE_TOOLCHAIN_FILE=./cmake/toolchain-riscv.cmake \
+  -D CMAKE_INSTALL_PREFIX=./build-riscv/install \
+  -D TOOLCHAIN_PATH={TOOLCHAIN_PATH} \
+  -D QEMU_PATH={QEMU_PATH} \
+  .
+
+cmake --build ./build-riscv
+```
+
+Disable the option if there is no RVV support:
+```
+-D WITH_RVV=OFF
+```
+
+## Run Unittests on User Mode QEMU ##
+
+```bash
+cd ./build-riscv && ctest --verbose
+```
diff --git a/arch/riscv/riscv_features.c b/arch/riscv/riscv_features.c
new file mode 100644 (file)
index 0000000..362d714
--- /dev/null
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../../zbuild.h"
+#include "riscv_features.h"
+
+/* TODO: detect risc-v cpu info at runtime when the kernel updates hwcap or hwprobe for risc-v */
+void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features) {
+#if defined(__riscv_v) && defined(__linux__)
+    features->has_rvv = 1;
+#else
+    features->has_rvv = 0;
+#endif
+}
diff --git a/arch/riscv/riscv_features.h b/arch/riscv/riscv_features.h
new file mode 100644 (file)
index 0000000..f933fc9
--- /dev/null
@@ -0,0 +1,18 @@
+/* riscv_features.h -- check for riscv features.
+ *
+ * Copyright (C) 2023 SiFive, Inc. All rights reserved.
+ * Contributed by Alex Chiang <alex.chiang@sifive.com>
+ * 
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#ifndef RISCV_H_
+#define RISCV_H_
+
+struct riscv_cpu_features {
+    int has_rvv;
+};
+
+void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features);
+
+#endif /* RISCV_H_ */
index 0491d53bf89b67528547a19249110cde41141b16..c20c9e16074b7d1939683d034b5f6ea451091720 100644 (file)
@@ -347,6 +347,24 @@ macro(check_power8_intrinsics)
     set(CMAKE_REQUIRED_FLAGS)
 endmacro()
 
+macro(check_rvv_intrinsics)
+    if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
+        if(NOT NATIVEFLAG)
+            set(RISCVFLAG "-march=rv64gcv")
+        endif()
+    endif()
+    # Check whether compiler supports RVV
+    set(CMAKE_REQUIRED_FLAGS "${RISCVFLAG} ${NATIVEFLAG}")
+    check_c_source_compiles(
+        "#include <riscv_vector.h>
+        int main() { 
+            return 0; 
+        }" 
+        HAVE_RVV_INTRIN
+    )
+    set(CMAKE_REQUIRED_FLAGS)
+endmacro()
+
 macro(check_s390_intrinsics)
     check_c_source_compiles(
         "#include <sys/auxv.h>
diff --git a/cmake/toolchain-riscv.cmake b/cmake/toolchain-riscv.cmake
new file mode 100644 (file)
index 0000000..9cf8fdb
--- /dev/null
@@ -0,0 +1,28 @@
+set(CMAKE_CROSSCOMPILING TRUE)
+set(CMAKE_SYSTEM_NAME "Linux")
+set(CMAKE_SYSTEM_PROCESSOR "riscv64")
+
+# Avoid to use system path for cross-compile
+set(CMAKE_FIND_USE_CMAKE_SYSTEM_PATH FALSE)
+
+set(TOOLCHAIN_PATH "" CACHE STRING "The toolchain path.")
+if(NOT TOOLCHAIN_PATH)
+  set(TOOLCHAIN_PATH ${CMAKE_SOURCE_DIR}/prebuilt-riscv-toolchain-qemu/riscv-clang)
+endif()
+
+set(TOOLCHAIN_PREFIX "riscv64-unknown-linux-gnu-" CACHE STRING "The toolchain prefix.")
+set(QEMU_PATH "" CACHE STRING "The qemu path.")
+if(NOT QEMU_PATH)
+  set(QEMU_PATH ${CMAKE_SOURCE_DIR}/prebuilt-riscv-toolchain-qemu/riscv-qemu/bin/qemu-riscv64)
+endif()
+
+# toolchain setting
+set(CMAKE_C_COMPILER "${TOOLCHAIN_PATH}/bin/${TOOLCHAIN_PREFIX}clang")
+set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PATH}/bin/${TOOLCHAIN_PREFIX}clang++")
+
+# disable auto-vectorizer
+add_compile_options(-fno-vectorize -fno-slp-vectorize)
+
+# emulator setting
+set(QEMU_CPU_OPTION "rv64,zba=true,zbb=true,zbc=true,zbs=true,v=true,vlen=512,elen=64,vext_spec=v1.0")
+set(CMAKE_CROSSCOMPILING_EMULATOR ${QEMU_PATH} -cpu ${QEMU_CPU_OPTION} -L ${TOOLCHAIN_PATH}/sysroot/)
index b69a01304a706dd47e83d129f992e4dd4d247e3e..3585172e5d2006abe8dea8abc9091f0e5b8a3141 100644 (file)
@@ -17,5 +17,7 @@ Z_INTERNAL void cpu_check_features(struct cpu_features *features) {
     power_check_features(&features->power);
 #elif defined(S390_FEATURES)
     s390_check_features(&features->s390);
+#elif defined(RISCV_FEATURES)
+    riscv_check_features(&features->riscv);
 #endif
 }
index 2e1a888e38794225ff85ecfa80577a04b67f35c4..647d027f6ec2d04202d9ce141a96c23afb30b1e7 100644 (file)
@@ -18,6 +18,8 @@
 #  include "arch/power/power_features.h"
 #elif defined(S390_FEATURES)
 #  include "arch/s390/s390_features.h"
+#elif defined(RISCV_FEATURES)
+#  include "arch/riscv/riscv_features.h"
 #endif
 
 struct cpu_features {
@@ -29,6 +31,8 @@ struct cpu_features {
     struct power_cpu_features power;
 #elif defined(S390_FEATURES)
     struct s390_cpu_features s390;
+#elif defined(RISCV_FEATURES)
+    struct riscv_cpu_features riscv;
 #else
     char empty;
 #endif