本项目是根据RISC-V官方指令集测试项目 riscv-tests 裁剪而成,具有以下特性
- 只支持rv32i标准
- 不含有任何特权架构的内容
支持Verilog自动化测试(TODO)
功能测试是针对CPU指令集功能的兼容性进行测试(并不保证微架构没有任何错误),项目结构如下
isa
│ -- link.ld // 链接文件
│ -- macros.h // 宏文件
│ -- Makefile // 编译脚本
└ -- rv32mi // rv32i测试文件夹
| -- add.S // ADD指令测试文件
| -- addi.S // ADDI指令测试文件
...
根据指令的功能可以将指令划分为
- 算数逻辑指令
- 访存指令(对应
TEST_LD_*
与TEST_ST_*
) - 分支指令(对应
TEST_BR2_*
与TEST_JR_*
和TEST_JALR_*
)
算数逻辑指令根据寻址方式可以将指令划分为
- 立即数寻址(对应
TEST_IMM_*
) - 寄存器寻址(对应
TEST_R_*
) - 寄存器与寄存器寻址(对应
TEST_RR_*
)
提出微架构中可能出现的几类问题(对应*_BYPASS
)
- 结构相关
- 数据相关
- 控制相关
在宏文件中可以看到上述测试用例的定义,测试程序会对上述几类功能进行测试。
一个测试程序的测试流程为
- 预处理。将所有寄存器清零,检查机器字长。
- 执行测试条目。逐条执行代码段内的测试用例。
- 后处理。检查所有测试是否通过,返回结果。
一条测试用例的执行流程为
- 将操作数和正确结果装载到寄存器,一般通过
li
指令完成。 - 执行待测试的指令。
- 检查指令执行结果是否正确,一般通过
bne
指令完成。 - 如果正确,继续执行剩余的测试用例;如果错误,跳转到错误处理代码段。
数据段起始地址为0x00000000
,代码段起始地址为0x00001000
。
请确保CPU已基本正确实现addi, lui, bne, jal
这几条基本指令,这是测试的基础。此外,不同的指令测试程序所用到的指令不尽相同,建议按照一定的顺序进行测试,比如jal -> bne -> lui -> addi -> ...
。
-
单独测试
使用.coe文件初始化IP存储器,执行。注意内存读写为小端模式。
-
批量测试
见批量测试
-
自定义测试
- 修改汇编程序
.S
文件内的测试用例 - 根据需要修改编译脚本
Makefile
和链接脚本link.ld
(一般情况下不用修改) - 在交叉编译环境下(Vlab已配置)执行
make
- 可以使用
bin2coe
工具将生成的.bin文件转换为.coe文件(单独修改coe文件时使用,在Makefile
中已配置)
- 修改汇编程序
每执行一段测试,都会检查寄存器的值是否正确,若不正确则直接跳转到错误处理代码段。在测试文件的最后还会执行TEST_PASSFAIL
代码段来判断整个测试成功与否,寄存器TESTRES
为1反映测试完成,寄存器TESTNUM
非0反映测试成功。
反映测试正确的方法应该是多样化的,这部分可以根据情况自行修改,如观察仿真波形、发送LED显示、发送数码管显示、发送串口等。
性能测试是针对CPU执行程序的性能进行测试,项目结构如下
benchmark
│ -- datasheet.h // 测试数据集
│ -- link.ld // 链接脚本
│ -- Makefile // 编译脚本
└ -- sort.c // 测试程序
项目使用冒泡排序作为测试程序。文件datasheet.h
中存储了2048项待排序数据和待验证数据,作为测试数据。文件sort.c
为冒泡排序主程序,先执行sort
函数进行排序,再执行verify
函数验证排序结果是否正确。如果排序出错,返回出错的序号,如果排序正确,返回0。
数据段起始地址为0x00000000
,代码段起始地址为0x00004000
。
请确保CPU已正确实现addi, slli, lw, sw, jal, jalr, bge, blt, bltu
这几条指令,并通过功能测试。
同功能测试。
请选择合适的时钟频率,并计算程序执行的时钟周期数。
TODO