一、Difftest简介

Difftest是差分测试框架,有什么用呢?高性能CPU的设计需要做复杂的测试,传统的测试方法运行较慢,而且出了问题很难定位,Difftest就是为了解决这两个问题,基本的逻辑也不难: image.png

  • 处理器运行一条指令
  • 模拟器运行相同的指令
  • 比较两者的状态

为什么能运行更快呢?最著名的模拟器当属Qemu,此外伯克利也提供了针对riscv的模拟器spike,但两者的实现都比较复杂,中科院采用了南大的开发的轻量级教学模拟器Nemu。因为只需要在指令层面做仿真,因此有很大的优化空间。

为什么能容易定位bug?因为每运行一条指令,都会对比关键寄存器的数值,做到动态实时比对,spike需要最终运行完才能比对。计算机的运行就是不同状态的转移,这个观点非常精妙。

那么,这么好的框架如何用起来呢?

二、NutShell difftest

NutShellXiangshan都有difftest相关的介绍,也提供了Difftest使用指南,但真正搭起来还真不容易。

  • 第一是因为这些资料比较零散,没有完整的“保姆级教程”。
  • 第二是版本、版本、版本,包括chisel3、difftest、Nutshell等版本,不同介绍的时间点不一样,复现起来也不简单。

为了有个初步的认识,先简单体验NutShell的difftest框架。

1.找对版本

进入xs-env工程,下载对应的NutShell@3a8832e和NEMU@26c7e50版本,参考仓库的setuptools.sh安装比要的软件。如verilator v4.218等。

2.Run起来

NutShell的文档对difftest的使用介绍不多,但有个彩蛋给出了完整的操作流程:nutshell/difftest/.github/workflows/main.yml。这是持续集成框架:在项目开发的时候,每次commit提交,会在云端github提供的服务器Docker上按照main.yml的规则运行新提交代码,对新代码进行自动测试。

参照main.yml不难跑通,如果遇到报错,根据提示不难定位:比如需要在difftest/verilator.mk文件中,将clang++换成g++;或者注释掉41行的VEXTRA-FLAGS += - - instr-count-dpi 1;或者装一些依赖库。

# git clone 对饮版本的NEMU和NutShell
cd NEMU 
make riscv64-xs-ref_defconfig
make

cd NutShell
source ./env.sh
make clean
make emu EMU_CXX_EXTRA_FLAGS="-DFIRST_INST_ADDRESS=0x80000000"
./build/emu -b 0 -e 0 -i ./ready-to-run/microbench.bin

如果想看看difftest的效果,可以修改NutShell中ALU单元的某个运算符,再生成emu并运行。

Idea下打开工程全红怎么办?最新的NutShell用mill构建,而不是sbt,因此目录下没有build.sbt,而是build.sc,,如果直接用idea.sh打开,自动检查功能用不了,不能快乐跳转。Mill的官网提供了IntelliJ Support的解决方案:

mill mill.scalalib.GenIdea/idea

三、小结

Difftest是CPU开发过程中的高效调试框架,NutShell下跑通Difftest需要非常注意版本,参考持续集成main.yml能很容易跑通。

如果自己从头写CPU,该如果接入Difftest呢?请看下回分解

标签: riscv, difftest, cpu

添加新评论