|
| 1 | +# Difftest 使用指南 |
| 2 | + |
| 3 | +## 编写顶层模块 `TopMain.scala` |
| 4 | + |
| 5 | +`TopMain` 是Scala程序的入口,类似于C/C++中的main函数,可以直接参考本框架中的代码,不需要做任何修改。 |
| 6 | + |
| 7 | +```scala |
| 8 | +object TopMain extends App { |
| 9 | + (new chisel3.stage.ChiselStage).execute(args, Seq(chisel3.stage.ChiselGeneratorAnnotation(() => new SimTop()))) |
| 10 | +} |
| 11 | +``` |
| 12 | + |
| 13 | +## 修改 `SimTop.scala` |
| 14 | + |
| 15 | +此文件是处理器的仿真顶层。按照Difftest框架的要求,CPU的顶层模块必须命名为 `SimTop`。在这一模块中,添加上Difftest需要的IO接口,如下所示。所有非必要的接口直接留空或者赋值为0或false即可。 |
| 16 | + |
| 17 | +```scala |
| 18 | +import chisel3._ |
| 19 | +import difftest._ |
| 20 | + |
| 21 | +class SimTop extends Module { |
| 22 | + val io = IO(new Bundle { |
| 23 | + val logCtrl = new LogCtrlIO |
| 24 | + val perfInfo = new PerfInfoIO |
| 25 | + val uart = new UARTIO |
| 26 | + }) |
| 27 | + |
| 28 | + ... |
| 29 | + |
| 30 | + io.uart.out.valid := false.B |
| 31 | + io.uart.out.ch := 0.U |
| 32 | + io.uart.in.valid := false.B |
| 33 | +} |
| 34 | +``` |
| 35 | + |
| 36 | +## 修改 `Core.scala` |
| 37 | + |
| 38 | +此文件是处理器本体的顶层。在我们给出的框架中,在 `Core.scala` 中包含了四个Difftest模块(`DifftestInstrCommit`, `DifftestArchEvent`, `DifftestTrapEvent`, `DifftestCSRState`),但是在进一步完善处理器时,可能需要将其中一些模块迁移到其他部分(如:把 `DifftestCSRState` 迁移到单独编写的CSR处理单元)。同上,没有完善的部分如CSR寄存器的值,可以暂时全部赋值为0。 |
| 39 | + |
| 40 | +```scala |
| 41 | +import chisel3._ |
| 42 | +import chisel3.util.experimental._ |
| 43 | +... |
| 44 | +import difftest._ |
| 45 | + |
| 46 | +class Core extends Module { |
| 47 | + val io = IO(new Bundle { |
| 48 | + ... |
| 49 | + }) |
| 50 | + |
| 51 | + ... |
| 52 | + |
| 53 | + val dt_ic = Module(new DifftestInstrCommit) |
| 54 | + dt_ic.io.clock := clock |
| 55 | + dt_ic.io.coreid := 0.U |
| 56 | + dt_ic.io.index := 0.U |
| 57 | + dt_ic.io.valid := true.B // 提交指令是否有效 |
| 58 | + dt_ic.io.pc := fetch.io.pc |
| 59 | + dt_ic.io.instr := fetch.io.inst |
| 60 | + dt_ic.io.skip := false.B // 是否需要跳过本条指令,按需设置 |
| 61 | + dt_ic.io.isRVC := false.B // 是否是C扩展16位指令,设为false即可 |
| 62 | + dt_ic.io.scFailed := false.B // A扩展sc指令是否失败,设为false即可 |
| 63 | + dt_ic.io.wen := decode.io.rd_en |
| 64 | + dt_ic.io.wdata := execution.io.out |
| 65 | + dt_ic.io.wdest := decode.io.rd_addr |
| 66 | + |
| 67 | + val dt_ae = Module(new DifftestArchEvent) |
| 68 | + dt_ae.io.clock := clock |
| 69 | + dt_ae.io.coreid := 0.U |
| 70 | + dt_ae.io.intrNO := 0.U // 外部中断使用 |
| 71 | + dt_ae.io.cause := 0.U |
| 72 | + dt_ae.io.exceptionPC := 0.U |
| 73 | + |
| 74 | + val cycle_cnt = RegInit(0.U(64.W)) |
| 75 | + val instr_cnt = RegInit(0.U(64.W)) |
| 76 | + |
| 77 | + cycle_cnt := cycle_cnt + 1.U |
| 78 | + instr_cnt := instr_cnt + 1.U |
| 79 | + |
| 80 | + val rf_a0 = WireInit(0.U(64.W)) |
| 81 | + BoringUtils.addSink(rf_a0, "rf_a0") |
| 82 | + |
| 83 | + val dt_te = Module(new DifftestTrapEvent) |
| 84 | + dt_te.io.clock := clock |
| 85 | + dt_te.io.coreid := 0.U |
| 86 | + dt_te.io.valid := (fetch.io.inst === "h0000006b".U) |
| 87 | + // 0x6b是NEMU中定义的HALT指令 |
| 88 | + dt_te.io.code := rf_a0(2, 0) // 读取a0的值判断程序是否正确执行并退出 |
| 89 | + dt_te.io.pc := fetch.io.pc |
| 90 | + dt_te.io.cycleCnt := cycle_cnt // cycle计数器 |
| 91 | + dt_te.io.instrCnt := instr_cnt // 指令计数器 |
| 92 | + |
| 93 | + val dt_cs = Module(new DifftestCSRState) |
| 94 | + dt_cs.io.clock := clock |
| 95 | + dt_cs.io.coreid := 0.U |
| 96 | + dt_cs.io.priviledgeMode := 3.U // Machine mode |
| 97 | + dt_cs.io.mstatus := 0.U |
| 98 | + dt_cs.io.sstatus := 0.U |
| 99 | + dt_cs.io.mepc := 0.U |
| 100 | + dt_cs.io.sepc := 0.U |
| 101 | + dt_cs.io.mtval := 0.U |
| 102 | + dt_cs.io.stval := 0.U |
| 103 | + dt_cs.io.mtvec := 0.U |
| 104 | + dt_cs.io.stvec := 0.U |
| 105 | + dt_cs.io.mcause := 0.U |
| 106 | + dt_cs.io.scause := 0.U |
| 107 | + dt_cs.io.satp := 0.U |
| 108 | + dt_cs.io.mip := 0.U |
| 109 | + dt_cs.io.mie := 0.U |
| 110 | + dt_cs.io.mscratch := 0.U |
| 111 | + dt_cs.io.sscratch := 0.U |
| 112 | + dt_cs.io.mideleg := 0.U |
| 113 | + dt_cs.io.medeleg := 0.U |
| 114 | +} |
| 115 | +``` |
| 116 | + |
| 117 | +## 修改 `RegFile.scala` |
| 118 | + |
| 119 | +在 `RegFile.scala` 中包含了 `DifftestArchIntRegState` 模块。 |
| 120 | + |
| 121 | +```scala |
| 122 | +import chisel3._ |
| 123 | +import chisel3.util.experimental._ |
| 124 | +import difftest._ |
| 125 | + |
| 126 | +class RegFile extends Module { |
| 127 | + val io = IO(new Bundle { |
| 128 | + ... |
| 129 | + }) |
| 130 | + |
| 131 | + // 如果用Mem类型,则需要手动转换成Vec类型后提交给Difftest |
| 132 | + val rf = RegInit(VecInit(Seq.fill(32)(0.U(64.W)))) |
| 133 | + |
| 134 | + ... |
| 135 | + |
| 136 | + val dt_ar = Module(new DifftestArchIntRegState) |
| 137 | + dt_ar.io.clock := clock |
| 138 | + dt_ar.io.coreid := 0.U |
| 139 | + dt_ar.io.gpr := rf |
| 140 | + |
| 141 | + BoringUtils.addSource(rf(10), "rf_a0") |
| 142 | +} |
| 143 | +``` |
0 commit comments