1. 向量寄存器初始化与数据搬运
任务目标
本案例演示RISC-V向量扩展(RVV)中向量寄存器的初始化与数据搬运操作。通过向量加载指令vle32.v将内存中的32位整型数据批量载入向量寄存器,再通过向量存储指令vse32.v将向量寄存器内容写回另一段内存区域,完成一次完整的数据搬运闭环。同时展示如何通过vsetvli配置向量长度与数据类型。
环境依赖
- 支持RVV 1.0的RISC-V工具链(如GCC 12+,编译参数
-march=rv64gcv) - 支持向量扩展的模拟器(如QEMU 7.0+,
-cpu rv64,v=true)或真实硬件
关键完整代码
#include <stdio.h>
#include <stdint.h>
#include <riscv_vector.h>
#define N 16 // 数据元素个数
int main() {
// 源数据与目标缓冲区(均按16字节对齐以满足向量访问要求)
int32_t src[N] __attribute__((aligned(16)));
int32_t dst[N] __attribute__((aligned(16)));
// 初始化源数据
for (int i = 0; i < N; i++) {
src[i] = i * 3 + 1;
dst[i] = 0;
}
// 向量数据搬运:src → 向量寄存器 → dst
size_t vl;
int32_t *ps = src;
int32_t *pd = dst;
int32_t avl = N; // 剩余元素数
while (avl > 0) {
// 设置向量长度:32位整型,每次处理min(avl, VLMAX)个元素
vl = vsetvl_e32m1(avl);
// 从内存加载avl个元素到向量寄存器v0
vint32m1_t vec = vle32_v_i32m1(ps, vl);
// 将向量寄存器v0的内容存储到目标内存
vse32_v_i32m1(pd, vec, vl);
// 更新指针与剩余计数
ps += vl;
pd += vl;
avl -= vl;
}
// 验证搬运结果
int err = 0;
for (int i = 0; i < N; i++) {
if (dst[i] != src[i]) {
printf("Mismatch at [%d]: src=%d dst=%d\n", i, src[i], dst[i]);
err = 1;
}
}
if (!err) {
printf("PASS: all %d elements copied correctly\n", N);
}
return err;
}
编译与运行
# 编译(需RVV工具链)
riscv64-unknown-elf-gcc -march=rv64gcv -mabi=lp64d -O2 -o vec_copy vec_copy.c
# QEMU模拟运行
qemu-riscv64 -cpu rv64,v=true ./vec_copy
验证方法与判定标准
程序执行后,通过逐元素比较dst与src内容完成自校验。若所有元素一致,输出PASS: all 16 elements copied correctly,退出码为0;否则打印首个不匹配位置并返回非零退出码。该验证覆盖了向量寄存器初始化(vle32.v载入)与数据搬运(vse32.v写出)的完整链路。
关键说明
vsetvl_e32m1将向量长度配置为32位整数、LMUL=1,返回实际处理的元素数vl,该值受硬件VLMAX约束。- 循环处理保证当
N超过VLMAX时,代码仍能通过分段搬运正确处理全部数据。 - 源与目标缓冲区均显式16字节对齐,避免非对齐访问异常。