任务介绍

本期验证任务要求参与者完成基于 RISC-V “V” 扩展的向量计算编译验证流程,通过端到端的实战测试,深入理解从高级算子到RISC-V汇编的完整编译链及其功能验证方法。

RISC-V “V” (Vector) 扩展旨在通过单指令多数据(SIMD)并行处理模式,显著提升处理器在科学计算、机器学习、多媒体处理等领域的性能。 向量处理器的核心思想是使用一条指令,对一组数据(即“向量”)中的所有元素执行相同的操作。它通过引入一组专门的向量寄存器和丰富的向量指令,使处理器能够高效地并行处理大量数据。

本次验证的核心是构建完整的Triton算子→MLIR→LLVM→RISC-V汇编→Spike模拟验证闭环。 参与者将使用Triton编写的高性能算子,经过MLIR编译框架进行多层中间表示转换,最终降级至LLVM IR并生成包含向量指令的RISC-V汇编代码。 通过在Spike模拟器中编写C测试程序、设置输入数据并执行结果比对,验证编译生成向量kernel的功能正确性。

本次任务将提供完整的编译工具链和必要的链接文件,包括算子kernel的LLVM IR文件、RISC-V汇编文件以及交叉编译环境。

欢迎各位报名参加,请填写报名问卷并加入交流群:

  • 万众一芯验证交流群(QQ):600480230
  • 向量计算验证交流群(QQ):946483102

RISC-V 向量计算验证流程文档

1 验证对象

1.1 RISC-V“V”扩展简介

RISC-V “V” (Vector) 扩展旨在通过单指令多数据(SIMD)并行处理模式,显著提升处理器在科学计算、机器学习、多媒体处理等领域的性能。向量处理器的核心思想是使用一条指令,对一组数据(即“向量”)中的所有元素执行相同的操作。它通过引入一组专门的向量寄存器和丰富的向量指令,使处理器能够高效地并行处理大量数据,特别适用于高性能计算、人工智能、信号处理等数据密集型应用场景。

1.2 Spike模拟器简介

Spike 是由 RISC-V 官方开发的一款功能模拟器(functional simulator),常被用作 RISC-V 软件栈的“黄金参考模型”。它可以模拟包括 RV32 和 RV64 在内的多种 RISC-V 架构变体,并支持包括“V”向量扩展在内的多个标准扩展(需编译时启用)。Spike 能够运行完整的操作系统(如 Linux)或裸机程序,为开发者提供调试、验证和教学的理想环境。由于其开源、轻量且行为规范,Spike 广泛应用于 RISC-V 生态系统的开发与教育场景中,是学习和测试 RISC-V 指令(包括向量指令)的重要工具。

2 测试功能与任务要求

你将参与一个端到端的 RISC-V 向量计算验证流程。具体而言,一个使用 Triton 编写的高性能算子(kernel)会首先通过 MLIR 编译框架进行多层中间表示(IR)转换,最终被 lowering(降级)至 LLVM Dialect,并生成标准的 LLVM IR(.ll 文件)。当编译目标启用 RISC-V 的 “V” 向量扩展后,LLVM 后端会进一步将该 IR 编译为包含向量指令的 RISC-V 汇编代码(.s 文件)。

为了验证这一编译链所生成的向量 kernel 是否功能正确,你需要在 Spike 模拟器环境下编写一段 C 语言测试程序:该程序应能调用并执行上述生成的汇编 kernel,通过设置合理的输入数据、调用约定和结果比对机制,确认其输出与预期行为一致。这项任务不仅要求你理解 RISC-V 向量扩展的基本使用方式,还需掌握如何在 Spike 中构建完整的测试环境,从而打通从高级算子到底层硬件模拟的验证闭环。

2.1 测试流程1: 提供环境及流程说明

RISC-V 交叉编译工具链

该工具链用于在宿主机(如 x86 Linux 或 macOS)上为 RISC-V 目标平台编译代码。在本任务中,你需要使用它分别处理两个源文件,并最终链接生成一个可在模拟器中运行的可执行文件(接下来全部流程都以add算子举例,请注意命名规则):

  • 将提供的 算子 kernel 的 .s 汇编文件编译为 kernel.o(如提供 add.s 则编译命名为 add.o);
  • 将你自己编写的 C 测试主程序(命名为 test_add.c)编译为 .o 文件(命名为 test_add.o);
  • 最后,使用同一工具链的链接器将这两个 .o 文件与所提供的四个文件链接成一个完整的 ELF 可执行文件。(命名为 test_add.elf)。

所需链接文件:

  • add.o
  • test_add.o
  • crt.o
  • syscalls.o
  • mlir_memrefcopy_spike.o
  • test_compact.ld

Spike RISC-V 模拟器

你将把上述生成的 test_add.elf 文件作为输入加载到 Spike 中运行。Spike 会逐条执行其中的指令(包括向量指令),并输出程序的运行结果(如打印信息、返回值等)。你可以通过比对实际输出与预期结果,判断 Triton 算子经 MLIR → LLVM → RISC-V 汇编这一完整编译链后生成的 kernel 是否功能正确。

2.2 测试流程2: 提供文件说明

算子 kernel 的 LLVM IR 文件(add.ll)

该文件是 Triton 算子经过 MLIR 编译流程后生成的 LLVM 中间表示(Intermediate Representation)。它以可读的文本形式描述了算子的完整计算逻辑、控制流结构以及函数签名。通过阅读此文件,你可以明确以下关键信息:

  • 算子函数的名称及其参数列表(包括参数类型、数量和顺序);
  • 每个参数在计算中的语义角色(例如:输入张量指针、输出缓冲区、维度大小、步长等);
  • 算子内部的核心操作逻辑(如循环、访存、向量运算等)。这些信息对于编写正确的 C 测试代码至关重要——你需要据此构造符合调用约定的输入数据,并设计预期输出用于结果比对,从而验证 kernel 功能的正确性。

算子 kernel 的 RISC-V 汇编文件(add.s)

该文件是在启用 RISC-V “V” 向量扩展的前提下,由 LLVM 后端将上述 .ll 文件进一步编译生成的 RISC-V 汇编代码。它包含了实际将在目标硬件(或模拟器)上执行的指令序列,其中可能包含 vsetvli、vle32.v、vadd.vv 等向量指令。

你的任务是使用 RISC-V 交叉编译工具链(riscv64-unknown-elf-gcc)将该 .s 文件编译为可重定位的目标文件(.o),然后与你编写的 C 测试主程序链接,生成可在 Spike 模拟器中运行的完整可执行文件。通过这种方式,你可以真实运行并验证向量化 kernel 在 RISC-V 架构下的行为是否符合预期。

四个必需编译文件

  • crt.o
  • syscalls.o
  • mlir_memrefcopy_spike.o
  • test_compact.ld

作为必需编译文件,在生成 test_add.elf 时需与 add.o 和 test_add.o 共同编译链接,具体可参考流程示例文档。

3 验收要求

为了全面验证算子 kernel 的功能正确性,测试代码需覆盖多种典型和边界输入情况,并能清晰反映 kernel 在不同场景下的输出行为。我们不要求穷尽所有组合,但期望测试能够体现对 kernel 核心逻辑的理解,包括对关键参数变化(如向量长度、数据类型、内存布局等)的响应。所有测试均应包含与理论预期结果的比对,并通过可读的输出展示验证结论。如同参考设计中所述,只要测试能系统性地反映“结果与参照模型一致”这一基本正确性要求,并体现出对不同运行情形的考量,即视为满足验收标准。

下图皆以 add 算子为例,请根据具体情况替换算子名称,并将全部提交文件打包命名为 姓名_算子名称.zip (xxx_add.zip)

提交文件文件说明与具体要求
test_add.elf按照作业流程说明和样例文档,使用 RISC-V 交叉编译工具链将以下目标文件正确链接生成的可执行 ELF 文件:
  • add.o (由 add.s 编译生成)
  • crt.o ; syscalls.o ; mlir_memrefcopy_spike.o ; test_compact.ld (由任务包内提供)
  • test_add.o (由自行编写的 test_add.c 编译生成)
测试代码 (test_add.c)用于验证算子 kernel 正确性的 C 源代码,需满足:
  • 正确声明并调用 kernel 函数,参数传递符合 .ll 文件定义,并附注释说明各参数语义;
  • 包含与理论预期结果的比对逻辑;
  • 根据算子类型提供充分测试:
    • 若为计算类算子(如加法、乘法等),需使用 至少 500 个输入数据 并输出对应计算结果;
    • 若为数据操作类算子(如 transpose、repeat 等),需覆盖 2–3 种典型情形(如不同维度、步长、对齐方式等),若存在特殊边界情况(如空输入、单元素、非对齐访问等),也必须包含相应测试。
运行截图在终端中使用 Spike 模拟器运行 test_add.elf 后输出截图,需清晰显示:
  • Spike 启动命令;
  • 程序打印的输入摘要、实际输出、预期结果及最终验证结论(如 “PASS” / “FAIL”);
(可参考流程示例文档)