diff --git a/src/content/posts/2024-01/imgs/01_vscode_support.png b/src/content/posts/2024-01/imgs/01_vscode_support.png new file mode 100644 index 0000000000000000000000000000000000000000..8c35ca3a772945c49c623ef953eabe9a8b82628b Binary files /dev/null and b/src/content/posts/2024-01/imgs/01_vscode_support.png differ diff --git a/src/content/posts/2024-01/zyx_01_config.md b/src/content/posts/2024-01/zyx_01_config.md new file mode 100644 index 0000000000000000000000000000000000000000..471fd53508f8784261bbb1033bdabb4702d8096d --- /dev/null +++ b/src/content/posts/2024-01/zyx_01_config.md @@ -0,0 +1,142 @@ +--- +title: RVV C Intrinsic 配置教程 +author: 张宇轩 +pubDate: 2024-06-14 +categories: ['2024 年第一期'] +description: 'RVV C Intrinsic 环境配置与向量化分析' +--- + +## 一、环境配置 + +目前riscv-gnu-toolchain中对RVV扩展已经非常成熟,但并没有提供合适的RVV C Intrinsics接口供开发人员使用。 +自 RVV 1.0发布以来,intriniscs的相关支持在 LLVM 上比较活跃,相关接口包含在头文件 `riscv_vector.h` 内。 + +参考[博客](https://jia.je/software/2022/01/25/rvv-1.0-toolchain/)后,采用 LLVM Clang + GCC Newlib Toolchain 的方式进行配合,前者做编译,后者提供libc等基础库。 + +- Ubuntu 22.04 (jammy):Ubuntu 20.04 (focal) 也可以,其他OS需要自行编译 `riscv64` 工具链 +- LLVM-14:从 [apt源](https://apt.llvm.org/) 下载即可 +- `riscv64-unknown-elf`工具链:从 [GitHub](https://github.com/riscv-collab/riscv-gnu-toolchain/releases) 上拉去最新的Nightly release即可 + +首先安装 LLVM-14: + +> **注意** LLVM 15及以后采用内部规则解析,作为前端`riscv_vector.h`的一系列声明就没了,因此本篇报告使用的是 LLVM-14。 + +```bash +wget https://apt.llvm.org/llvm.sh +chmod +x llvm.sh +sudo ./llvm.sh 14 +``` + +检查安装是否成功: + +```bash +$ clang-14 --version +Ubuntu clang version 14.0.6 +Target: x86_64-pc-linux-gnu +Thread model: posix +InstalledDir: /usr/bin +``` + +然后下载`riscv64-unknown-elf`工具链;这里特别注意 `riscv64-elf`、`ubuntu-版本号`(我使用的是`22.04`,所以选`ubuntu-22.04`)、`gcc` 几个关键词。 + +```bash +wget https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/2024.04.12/riscv64-elf-ubuntu-22.04-gcc-nightly-2024.04.12-nightly.tar.gz +``` + +下载完毕后解压到指定路径,一般选用`/opt/riscv`或`/usr/local/riscv`,这里以`/usr/local/riscv`为例: + +```bash +sudo tar -xvf riscv64-elf-ubuntu-22.04-gcc-nightly-2024.04.12-nightly.tar.gz -C /usr/local/ +``` + +然后将`/usr/local/riscv/bin`添加到当前Shell的环境变量中: + +```bash +echo export PATH="/usr/local/riscv/bin:$PATH" >> ~/.bashrc +source ~/.bashrc +``` + +检查`riscv64-unknown-elf`工具链: + +```bash +$ riscv64-unknown-elf-gcc --version +riscv64-unknown-elf-gcc () 13.2.0 +Copyright (C) 2023 Free Software Foundation, Inc. +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +``` + +## 二、Hello World + +一个简单的向量加法`vadd.c`如下所示: + +```c +// Reference: https://pages.dogdog.run/toolchain/riscv_vector_extension.html + +#include +#include + +int x[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; +int y[10] = {0, 9, 8, 7, 6, 5, 4, 3, 2, 1}; +int z[10]; + +void vec_add_rvv(int* dst, int* lhs, int* rhs, size_t avl) { + vint32m2_t vlhs, vrhs, vres; + for (size_t vl; (vl = vsetvl_e32m2(avl)); + avl -= vl, lhs += vl, rhs += vl, dst += vl) { + vlhs = vle32_v_i32m2(lhs, vl); + vrhs = vle32_v_i32m2(rhs, vl); + vres = vadd_vv_i32m2(vlhs, vrhs, vl); + vse32_v_i32m2(dst, vres, vl); + } +} + +int main(int argc, char const* argv[]) { + vec_add_rvv(z, x, y, 10); + for (int i = 0; i < 10; ++i) printf("%d ", z[i]); + printf("\n"); + return 0; +} +``` + +可以看到VSCode的Intellisense是能很好支持的: + +![vscode_support](./imgs/01_vscode_support.png) + +编译: + +```bash +clang-14 --target=riscv64-unknown-elf -march=rv64gv --gcc-toolchain=/usr/local/riscv -O2 -g ./vadd.c -o ./vadd +``` + +- 使用 `--target` 指定编译器后端为`riscv64-unknown-elf` +- 通过 `-march=rv64gv` 指定目标指令集为 RV64G(通用) 和 RV64V(向量扩展) +- `--gcc-toolchain`设置为刚刚解压的`riscv64-unknown-elf`工具链目录 + +通过QEMU运行: + +```bash +qemu-riscv64 -cpu rv64,v=true,vlen=128 ./vadd +``` + +- `-cpu` 指定目标处理器架构,选用`rv64`,同时令`v=true`表示启用V扩展,并设置`vlen=128` + +一次完整执行过程如下: + +```bash +$ clang-14 --target=riscv64-unknown-elf -march=rv64gv --gcc-toolchain=/usr/local/riscv -O2 -g ./vadd.c -o ./vadd +$ qemu-riscv64 -cpu rv64,v=true,vlen=128 ./vadd +vector version is not specified, use the default value v1.0 +1 11 11 11 11 11 11 11 11 1 +``` + +可以参考[rvv-intrinsic-doc](https://github.com/riscv-non-isa/rvv-intrinsic-doc/blob/main/doc/rvv-intrinsic-examples.adoc)的示例代码,需要注意不再需要包含`__riscv`前缀 + +## 三、参考 + +你需要熟悉这两份参考手册: + +- [RISCV Unprivileged Specification](https://github.com/riscv/riscv-isa-manual/releases/download/20240411/unpriv-isa-asciidoc.pdf):RISC-V 指令集手册,已集成 V 扩展,原本的 [RVV 1.0 手册](https://github.com/riscv/riscv-v-spec/releases/download/v1.0/riscv-v-spec-1.0.pdf) 已归档 +- [v-intrinsic-spec](https://github.com/riscv-non-isa/rvv-intrinsic-doc/releases/download/v1.0-rc0/v-intrinsic-spec.pdf):详细列举了可使用的 RVV C Intrinsics接口 + +同时也可以了解 [RiVEC Benchmark](https://github.com/RALC88/riscv-vectorized-benchmark-suite/tree/rvv-1.0),是体系结构中最早应用于gem5上的RVV Benchmark \ No newline at end of file