Skip to content

Commit ec2ee80

Browse files
committed
Upload dfftest doc
1 parent 24c2fe6 commit ec2ee80

File tree

3 files changed

+249
-1
lines changed

3 files changed

+249
-1
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
!*.txt
1717
!Makefile
1818
!README
19-
!README.md
19+
!*.md
2020
!LICENSE
2121
!.gitignore
2222
**/build/

doc/chisel_difftest.md

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
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+
```

doc/difftest_api.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# difftest接口说明
2+
3+
`香山difftest框架`使用`verilator`提供的[DPI-C](https://verilator.org/guide/latest/connecting.html#direct-programming-interface-dpi)功能实现指令执行结果提交至`difftest`。用法可参考`cpu_diff``chisel_cpu_diff`例程。以下对`一生一芯`[基础任务](https://oscpu.github.io/ysyx/wiki/tasks/basic.html)中用到的`verilog difftest`接口进行说明,`chisel difftest`接口用法类似,可参考[chisel_difftest.md](./chisel_difftest.md)
4+
5+
```verilog
6+
// 触发异常
7+
`DIFFTEST_MOD_DECL(ArchEvent) (
8+
input clock, // 时钟
9+
input [ 7:0] coreid, // cpu id,单核时固定为0
10+
input [31:0] intrNO, // 中断号
11+
input [31:0] cause, // 异常号
12+
input [63:0] exceptionPC, // 产生异常时的PC
13+
input [31:0] exceptionInst // 产生异常时的指令
14+
);
15+
16+
// 提交指令
17+
`DIFFTEST_MOD_DECL(InstrCommit)(
18+
input clock,
19+
input [ 7:0] coreid,
20+
input [ 7:0] index,
21+
input valid, // 是否提交指令
22+
input [63:0] pc, // 当前PC
23+
input [31:0] instr, // 当前指令
24+
input skip, // 跳过当前指令的对比
25+
input isRVC, // 压缩指令
26+
input scFailed, // SC指令执行失败
27+
input wen, // 写回
28+
input [ 7:0] wdest, // 写回寄存器堆索引
29+
input [63:0] wdata // 写回值
30+
);
31+
32+
// Trap事件,用于告知difftest程序执行结束
33+
`DIFFTEST_MOD_DECL(TrapEvent)(
34+
input clock,
35+
input [ 7:0] coreid,
36+
input valid, // 执行结束
37+
input [ 2:0] code, // 执行结果
38+
input [63:0] pc, // 当前PC
39+
input [63:0] cycleCnt, // 时钟周期数
40+
input [63:0] instrCnt // 指令数
41+
);
42+
43+
// 提交CSR寄存器
44+
`DIFFTEST_MOD_DECL(CSRState)(
45+
input clock,
46+
input [ 7:0] coreid,
47+
input [ 1:0] priviledgeMode,// 特权模式
48+
input [63:0] mstatus,
49+
input [63:0] sstatus,
50+
input [63:0] mepc,
51+
input [63:0] sepc,
52+
input [63:0] mtval,
53+
input [63:0] stval,
54+
input [63:0] mtvec,
55+
input [63:0] stvec,
56+
input [63:0] mcause,
57+
input [63:0] scause,
58+
input [63:0] satp,
59+
input [63:0] mip,
60+
input [63:0] mie,
61+
input [63:0] mscratch,
62+
input [63:0] sscratch,
63+
input [63:0] mideleg,
64+
input [63:0] medeleg
65+
);
66+
67+
// 提交通用寄存器
68+
`DIFFTEST_MOD_DECL(ArchIntRegState)(
69+
input clock,
70+
input [ 7:0] coreid,
71+
input [63:0] gpr_0,
72+
input [63:0] gpr_1,
73+
input [63:0] gpr_2,
74+
input [63:0] gpr_3,
75+
input [63:0] gpr_4,
76+
input [63:0] gpr_5,
77+
input [63:0] gpr_6,
78+
input [63:0] gpr_7,
79+
input [63:0] gpr_8,
80+
input [63:0] gpr_9,
81+
input [63:0] gpr_10,
82+
input [63:0] gpr_11,
83+
input [63:0] gpr_12,
84+
input [63:0] gpr_13,
85+
input [63:0] gpr_14,
86+
input [63:0] gpr_15,
87+
input [63:0] gpr_16,
88+
input [63:0] gpr_17,
89+
input [63:0] gpr_18,
90+
input [63:0] gpr_19,
91+
input [63:0] gpr_20,
92+
input [63:0] gpr_21,
93+
input [63:0] gpr_22,
94+
input [63:0] gpr_23,
95+
input [63:0] gpr_24,
96+
input [63:0] gpr_25,
97+
input [63:0] gpr_26,
98+
input [63:0] gpr_27,
99+
input [63:0] gpr_28,
100+
input [63:0] gpr_29,
101+
input [63:0] gpr_30,
102+
input [63:0] gpr_31
103+
);
104+
```
105+

0 commit comments

Comments
 (0)