如何搭建自己的Difftest框架呢?一生一芯仓库的wiki给了优秀的回答,但要全搭起来还是不容易,同样是两个原因:不够保姆、版本。

1. 初始化仓库

首先clone一生一芯官网的初始化仓库。

git clone -b ysyx2204 git@github.com:OSCPU/ysyx-workbench.git
cd ysyx-workbench
# 初始化chisel环境
bash init.sh npc-chisel

2. Difftest文件夹

NutShell@3a8832e下的difftest拷贝到npc目录下,和playground同级。同时需要修改npc/build.sc文件,才能调用difftest中的clas,但需要修改difftest的版本至3.5.0-RC1,不然会报错。 参考以下三个Issue:issue8issue9issue10

// import Mill dependency
import mill._
import mill.scalalib._
import mill.scalalib.scalafmt.ScalafmtModule
import mill.scalalib.TestModule.Utest
// support BSP
import mill.bsp._

object playground extends ScalaModule with ScalafmtModule { m =>
  override def scalaVersion = "2.12.13"
  override def scalacOptions = Seq(
    "-Xsource:2.11",
    "-language:reflectiveCalls",
    "-deprecation",
    "-feature",
    "-Xcheckinit",
    // Enables autoclonetype2 in 3.4.x (on by default in 3.5)
    "-P:chiselplugin:useBundlePlugin"
  )
  override def ivyDeps = Agg(
    ivy"edu.berkeley.cs::chisel3:3.5.0-RC1",
  )
  override def scalacPluginIvyDeps = Agg(
    ivy"edu.berkeley.cs:::chisel3-plugin:3.4.3",
    ivy"org.scalamacros:::paradise:2.1.1"
  )
  object test extends Tests with Utest {
    override def ivyDeps = m.ivyDeps() ++ Agg(
      ivy"com.lihaoyi::utest:0.7.10",
      ivy"edu.berkeley.cs::chiseltest:0.3.3",
    )
  }
  override def moduleDeps = super.moduleDeps ++ Seq(difftest)
}

object difftest extends ScalaModule {
  override def scalaVersion = "2.12.13"
  override def millSourcePath = os.pwd / "difftest"
  override def ivyDeps = Agg(
    ivy"edu.berkeley.cs::chisel3:3.5.0-RC1"
  )
}

3.单周期CPU

CPU的chisel模板参考oscpu-chisel-framework,需要做两方面改动:

  • 添加二读一写端口的ram1w2r.v:difftest/src/test/vsrc/common/ram1w2r.v。因为单周期一般区分imem和dmem。
  • 修改difftest的接入时序,这点比较繁琐,也花了很长时间debug。

时序主要修改了两个文件:InstFetch.scalaCore.scala

  • InstFetch.scala 添加pc_valid信号,告诉difftest这是一个有效提交指令,然后Nemu运行一条指令,再对比各自的寄存器。如果没这样做,第一条提交的指令会出错。

  • Core.scala添加RegNext做延时,这是调节时序的。寄存器的更新在指令的下一拍,传给difftest的pc需要和寄存器的更新同步。这样difftest接受指令提交后,Nemu运行一条指令,然后比对各自的寄存器。

4. 测试BIN文件

测试BIN文件在这个仓库可以找到,感觉是之前一生一芯的开源仓库,不知为什么原官方仓库不见了。

BIN文件生成的时候需要加编译选项-march=rv64g -mabi=lp64d,否则默认会编译出压缩指令,运行时会报错(暂时没有实现压缩指令解码器)。

最后 npc目录下的Makefile 生成emu时,需要加上EMU_CXX_EXTRA_FLAGS="-DFIRST_INST_ADDRESS=0x80000000",告诉nemu在0x80000000的位置开始取值。

5. 小结

本想专心写硬件,没想到花了那么多时间大环境,print大法排查了很久,附上调试好的仓库,希望jyy老师不会打我。系统环境是Ubuntu20.04的虚拟机。如果用wsl,有可能需要改动一些地方。

git clone https://gitee.com/he_zhifan/ysyx-workbench.git
cd ysyx-workbench
git submodule update --init --recursive
bash install_tools.sh
git checkout v0.5

cd nemu
make riscv64-xs-ref_defconfig
make

cd ../npc
make sim

默认仿真addi-riscv-tests.bin文件,会停在0x8000050的位置,因为lui指令还没实现。li,movaddi的伪指令,bne虽然没实现,但默认下条指令是pc+4,也能通过。 image.png

附上difftest的函数跳转图 入口函数:difftest/src/test/csrc/verilator/main.cpp

main.cpp
	|-构造emu
		|-调用构造函数:reset 10 cycles,init_ram,init_flash
	|-调用emu->execute
		|-init_difftest
          *****while*****
		  single_cycle运行dut
		  difftest_step()运行nemu        emu.cpp :426(difftest.cpp:88)
				|-do_first_instr_commit()   difftest.cpp :103(354)
					do_instr_commit()         difftest.cpp :148(222)
					*compare regs             difftest.cpp :178              
					|-打印对比信息             difftest.cpp :180
						state->dispaly:打印Commit Group         difftest.cpp:614
						Difftes display: Instr Trace, REF Regs  difftest.cpp:608
						display_trapinfo打印trap位置,和指令统计结果
					|-打印错误的寄存器
          ****end while***
		  display_trapinfo()             emu.cpp:495(569)

打印verilog里面的日志信息

标签: riscv, difftest, cpu

仅有一条评论

  1. fujie fujie

    写的很好,感谢分享

添加新评论