DiffTest (差分测试): a modern co-simulation framework for RISC-V processors.
DiffTest interfaces are provided in Chisel bundles and expected to be integrated into Chisel designs with auto-generated C++ interfaces. However, we also provide examples of the generated Verilog modules.
make difftest_verilog NOOP_HOME=$(pwd)
- Add this submodule to your design.
In your Git project:
git submodule add https://github.com/OpenXiangShan/difftest.git
In Mill build.sc
:
import $file.difftest.build
// We recommend using a fixed Chisel version.
object difftest extends millbuild.difftest.build.CommonDiffTest {
def crossValue: String = "3.6.0"
override def millSourcePath = os.pwd / "difftest"
}
// This is for advanced users only.
// All supported Chisel versions are listed in `build.sc`.
// To pass a cross value to difftest:
object difftest extends Cross[millbuild.difftest.build.CommonDiffTest](chiselVersions) {
override def millSourcePath = os.pwd / "difftest"
}
In Makefile
:
emu: sim-verilog
@$(MAKE) -C difftest emu WITH_CHISELDB=0 WITH_CONSTANTIN=0
- Add difftest modules (in Chisel or Verilog) to your design. All modules have been listed in the APIs chapter. Some of them are optional.
import difftest._
val difftest = DifftestModule(new DiffInstrCommit, delay = 1, dontCare = true)
difftest.valid := io.in.valid
difftest.pc := SignExt(io.in.bits.decode.cf.pc, AddrBits)
difftest.instr := io.in.bits.decode.cf.instr
difftest.skip := io.in.bits.isMMIO
difftest.isRVC := io.in.bits.decode.cf.instr(1, 0)=/="b11".U
difftest.rfwen := io.wb.rfWen && io.wb.rfDest =/= 0.U
difftest.wdest := io.wb.rfDest
difftest.wpdest := io.wb.rfDest
- Call
val difftesst = DifftestModule.finish(cpu: String)
at the top module whose module name should beSimTop
. The variable namedifftest
must be used to ensure DiffTest could capture the input signals.
An optional UART input/output can be connected to DiffTest. DiffTest will automatically DontCare it internally.
val difftest = DifftestModule.finish("Demo")
// Optional UART connections. Remove this line if UART is not needed.
difftest.uart <> mmio.io.uart
-
Generate verilog files for simulation.
-
make emu
and start simulating & debugging!
We provide example designs, including:
If you encountered any issues when integrating DiffTest to your own design, feel free to let us know with necessary information on how you have modified your design. We will try our best to assist you.
Currently we are supporting the RISC-V base ISA as well as some extensions, including Float/Double, Debug, and Vector. We also support checking the cache coherence via RefillTest.
Probe Name | Descriptions | Mandatory |
---|---|---|
DiffArchEvent |
Exceptions and interrupts | Yes |
DiffInstrCommit |
Executed instructions | Yes |
DiffTrapEvent |
Simulation environment call | Yes |
DiffArchIntRegState |
General-purpose registers | Yes |
DiffArchFpRegState |
Floating-point registers | No |
DiffArchVecRegState |
Floating-point registers | No |
DiffCSRState |
Control and status registers | Yes |
DiffVecCSRState |
Control and status registers | No |
DiffDebugMode |
Debug mode registers | No |
DiffIntWriteback |
General-purpose writeback operations | No |
DiffFpWriteback |
Floating-point writeback operations | No |
DiffArchIntDelayedUpdate |
Delayed general-purpose writeback | No |
DiffArchFpDelayedUpdate |
Delayed floating-point writeback | No |
DiffStoreEvent |
Store operations | No |
DiffSbufferEvent |
Store buffer operations | No |
DiffLoadEvent |
Load operations | No |
DiffAtomicEvent |
Atomic operations | No |
DiffL1TLBEvent |
L1 TLB operations | No |
DiffL2TLBEvent |
L2 TLB operations | No |
DiffRefillEvent |
Cache refill operations | No |
DiffLrScEvent |
Executed LR/SC instructions | No |
The DiffTest framework comes with a simulation framework with some top-level IOs.
They will be automatically created when calling DifftestModule.finish(cpu: String)
.
LogCtrlIO
PerfCtrlIO
UARTIO
These IOs can be used along with the controller wrapper at src/main/scala/common/LogPerfControl.scala
.
For compatibility on different platforms, the CPU should access a C++ memory via DPI-C interfaces. This memory will be initialized in C++.
val mem = DifftestMem(memByte, 8)
when (wen) {
mem.write(
addr = wIdx,
data = in.w.bits.data.asTypeOf(Vec(DataBytes, UInt(8.W))),
mask = in.w.bits.strb.asBools
)
}
val rdata = mem.readAndHold(rIdx, ren).asUInt
To use DiffTest, please include all necessary modules and top-level IOs in your design. It's worth noting the Chisel Bundles may have arguments with default values. Please set the correct parameters for the interfaces.