riscv-tests是一种指令集自测试集,能够自我检测指令集运行成功还是失败的测试程序。这些程序基本由汇编语言编写。
内包含banchmark、isa、programs测试。
github链接:https://github.com/riscv/riscv-tests
1. benchmark测试
benchmark内包含一些业内公认C代码测试集
2. ISA测试
在riscv-tests/isa中,内含测试集均为定向指令测试,包含机器/用户/监督者模式下I/A/C/D/F/M类型的指令的测试。
根据运行环境是否为裸机状态可以分为P/V环境,P为裸机状态下测试,即虚拟内存未启动;V状态测试环境中虚拟内存已启动(通常引导了操作系统)。下文以裸机状态下各功能指令为例介绍测试集相关的头文件、宏、内嵌函数等。
-
PS:激励源文件的结构
在测试激励源文件中,不仅有与测试激励相关的宏,还有一些公用宏——这些宏定义了一些程序段处理(包括模式检测、中断/异常处理初始化等)和数据段处理,以及一些组成汇编程序的工具类宏。
这些宏均由test_macros.h、riscv_test.h和encoding.h组成。
- TEST_CASE
该宏将测试案例代码code执行完后,将案例原本的正确值加载到x29寄存器,并与保存代码结果的寄存器testreg内的值作对比,若不相等则跳转到fail位置;若相等则继续执行。
#define TEST_CASE( testnum, testreg, correctval, code...)
test_ ## testnum:
code; \
li x29, MASK_XLEN(correctval); \
li TESTNUM, testnum; \
bne testreg, x29, fail; - TEST_PASSFAIL
该宏定义了pass和fail的入口,实际结果和理论结果相等则跳到pass,若不相等则执行fail。 - RVTEST_PASS
测试通过,将x3的值设为1,并通过环境调用异常将PC值写入到mepc寄存器。 - RVTEST_FAIL
测试不通过,判断x3是否等于0,若不等于0,则将x3寄存器值左移一位并将最低位置1,后同样通过环境调用异常将PC值写入到mepc寄存器。
- 整数计算指令
整数计算指令可以分为R-I指令(寄存器-立即数)和R-R指令(寄存器-寄存器)。
对于R-I指令测试有操作数激励测试、寄存器激励测试、旁路设计测试、测试0号寄存器、特殊立即数格式测试。
对于R-R指令测试有操作数激励测试、寄存器激励测试、旁路设计测试、测试0号寄存器
- 操作数激励测试
改变操作数的值,验证实际结果和理论结果是否一致
相关宏:TEST_IMM_OP(...)、TEST_RR_OP(...)等。 - 寄存器激励测试
改变源寄存器和操作寄存器,验证实际结果和理论结果是否一致
相关宏:TEST_IMM_SRC1_EQ_DEST(...)、TEST_RR_SRC1_EQ_DEST(...)等。 - 旁路设计测试
对于DEST_BYPASS情形,通过在待测指令和数据相关的运算指令间插入0~2条NOP指令来实现,此时待测指令的目标寄存器与运算指令的源操作数寄存器相同,并循环执行两次(通过x4和x5判断)
相关宏:TEST_IMM_DEST_BYPASS(...)、TEST_RR_DEST_BYPASS(...)等。 - 测试0号寄存器
将x0寄存器作为原寄存器或目的寄存器,验证x0寄存器在整数计算中是否为只读寄存器且内容始终为0
相关宏:TEST_IMM_ZEROSRC1(...)、TEST_RR_ZEROSRC1(...)等。 - 特殊立即数格式测试
在R-I指令测试中,由LUI指令和AUIPC指令采用U型格式的立即数
- 存储器访问指令
存储器访存指令分为load指令和store指令。
- load/store指令基本测试
测试方案为分别采用正常地址类型(即基址和偏移值皆为正数);偏移量为负数;基址负数,将基址读到寄存器,然后减少32得到新的基址,测试基址偏移32的读出结果;非对齐地址,将基址读到寄存器,然后减少3得到新的基址,测试基址偏移7的读出结果 - 旁路设计测试
类似于整数计算指令的旁路测试 - 数据相关性测试
主要针对load指令WRW冒险测试
- 控制转移指令
控制转移指令分为无条件跳转指令和条件分支指令
- 控制和状态寄存器指令
该类指令包括CSR指令测试和环境调用相关指令测试
- CSR指令测试
分为指令操作测试用例(即以mepc寄存器为操作对象分别测试CSRRRW、CSRRS、CSRRC三类指令),CSR寄存器读写测试 - 环境调用相关测试
ECALL、EBREAK