RVV C Intrinsic 配置教程
一、环境配置
目前riscv-gnu-toolchain中对RVV扩展已经非常成熟,但并没有提供合适的RVV C Intrinsics接口供开发人员使用。
自 RVV 1.0发布以来,intriniscs的相关支持在 LLVM 上比较活跃,相关接口包含在头文件 riscv_vector.h
内。
参考博客后,采用 LLVM Clang + GCC Newlib Toolchain 的方式进行配合,前者做编译,后者提供libc等基础库。
- Ubuntu 22.04 (jammy):Ubuntu 20.04 (focal) 也可以,其他OS需要自行编译
riscv64
工具链 - LLVM-14:从 apt源 下载即可
riscv64-unknown-elf
工具链:从 GitHub 上拉去最新的Nightly release即可
首先安装 LLVM-14:
注意 LLVM 15及以后采用内部规则解析,作为前端
riscv_vector.h
的一系列声明就没了,因此本篇报告使用的是 LLVM-14。
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 14
检查安装是否成功:
$ 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
几个关键词。
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
为例:
sudo tar -xvf riscv64-elf-ubuntu-22.04-gcc-nightly-2024.04.12-nightly.tar.gz -C /usr/local/
然后将/usr/local/riscv/bin
添加到当前Shell的环境变量中:
echo export PATH="/usr/local/riscv/bin:$PATH" >> ~/.bashrc
source ~/.bashrc
检查riscv64-unknown-elf
工具链:
$ 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
如下所示:
// Reference: https://pages.dogdog.run/toolchain/riscv_vector_extension.html
#include <riscv_vector.h>
#include <stdio.h>
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是能很好支持的:
编译:
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运行:
qemu-riscv64 -cpu rv64,v=true,vlen=128 ./vadd
-cpu
指定目标处理器架构,选用rv64
,同时令v=true
表示启用V扩展,并设置vlen=128
一次完整执行过程如下:
$ 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的示例代码,需要注意不再需要包含__riscv
前缀
三、参考
你需要熟悉这两份参考手册:
- RISCV Unprivileged Specification:RISC-V 指令集手册,已集成 V 扩展,原本的 RVV 1.0 手册 已归档
- v-intrinsic-spec:详细列举了可使用的 RVV C Intrinsics接口
同时也可以了解 RiVEC Benchmark,是体系结构中最早应用于gem5上的RVV Benchmark