实验测试
实验测试方法¶
首先,下载代码仓库的 master 分支:
cd 2022Spring/ # 选择一个合适的目录
git clone -b master https://github.com/FDUCSLG/Arch-2022Spring-FDU.git #下载仓库的master分支
cd Arch-2022Spring-FDU
git submodule update --init --recursive
make test-lab1 #测试
代码编写¶
我们在 vsrc
里写 SystemVerilog 代码。
有以下要求:
-
每个
.sv
文件仅编写一个 module -
文件名与 module 名一致,一般为全小写
-
每个文件都要用
ifndef __NAME_SV
来保护 -
每个文件都要有:
`ifdef VERILATOR
`else
`endif
-
verilator 仿真中,module 进行元件例化前,需要以vsrc/ 为根的相对路径 include 源文件,写在`ifdef VERILATOR 区域。
-
vivado 中,只需 include 头文件,include 时不写路径,只写文件名.svh 。
-
module 的一般形式:
module sample
import common::*; #(
parameter XLEN = 16
) (
input logic clk, reset
);
endmodule
Verilator 仿真¶
这是我们主要的调试手段。
运行 make test-lab1
等测试,观察输出。如果有 Hit Good Trap 输出则为通过。
Vivado 仿真¶
请在 Verilator 仿真通过后再尝试 Vivado 仿真。
使用 Vivado2018.3 打开 vivado/test1/project/project_1.xpr
,点击 tools 下的Run Tcl Script 运行 vsrc/add_sources.tcl
和 vivado/src/add_source.tcl
添加源文件,然后 Run Simulation 。点击上方三角开始仿真。
Vivado 上板¶
请至少在 Verilator 仿真通过后再尝试上板。
点击 Generate Bitstream ,生成完毕后连接实验板并 Program Device 。
在电脑上打开串口软件 ( Windows 系统可使用 elearning 上发的 SecureCRT,其他系统请自行寻找相关软件),设置串口(Serial)波特率(Baud Rate)9600,然后连接。
按下实验板上的 prog ,可在串口软件中看到一行输出:BASYS3 GPIO/UART DEMO!
这是内置的 bitstream 的输出,不是我们 CPU 的输出。点击 Program Device 才是我们 CPU 的输出。
实验测试介绍¶
CPU 访存接口¶
流水线部分有指令内存接口与数据内存接口,CPU与内存的交互**只需要**这两个接口,定义在 include/common.sv
; 实现在 core.sv
的input
和output
接口
指令内存接口:
typedef struct packed {
logic valid; // in request? (Used in Lab 2)
addr_t addr; // target address
} ibus_req_t;
typedef struct packed {
logic addr_ok; // is the address accepted by cache? (Used in Lab 2)
logic data_ok; // is the field "data" valid? (Used in Lab 2)
u32 data; // the data read from cache
} ibus_resp_t;
数据内存接口:
typedef struct packed {
logic valid; // in request?
addr_t addr; // target address
msize_t size; // number of bytes (Used in Lab 2)
strobe_t strobe; // which bytes are enabled? set to zeros for read request (in Lab 1, it is either '0(0x0) or '1(0xff))
word_t data; // the data to write
} dbus_req_t;
typedef struct packed {
logic addr_ok; // is the address accepted by cache? (Used in Lab 2)
logic data_ok; // is the field "data" valid? (Used in Lab 2)
word_t data; // the data read from cache
} dbus_resp_t;
include与import¶
对于verilator,引用其它文件定义的结构或是模块都需要进行include
`ifdef VERILATOR
`include "文件相对于vsrc的路径"
`else
`endif
比如在core.sv
中,不仅使用到了定义在common.sv
中的ibus
和dbus
,如果也用到了regfile.sv
中定义的regfile
模块,那么**都需要**进行include
:
`ifdef VERILATOR
`include "include/common.sv"
`include "pipeline/regfile/regfile.sv"
`else
`endif
而对于vivado,为了引用其它结构,需要在每个模块内import
对应的package,但是使用其它文件定义的模块则不需要import
,使用tcl脚本加入源文件后,vivado会自行找到,比如core.sv
中
module core
import common::*;(
input logic clk, reset,
output ibus_req_t ireq,
...
);
endmodule
import
了定义在common.sv
中的名叫 common
的package,但是不需要import regfile
,直接使用即可。
package common;
....
endpackage
接入Verilator仿真¶
将 CPU 接入 Verilator Difftest 的仿真接口。
需要例化三个模块(所给框架中已例化好,需要接线)。
首先是当前周期提交的指令:
DifftestInstrCommit DifftestInstrCommit(
.clock (clk),
.coreid (0), // 无需改动
.index (0), // 多发射时,例化多个该模块。前四个 Lab 无需改动它
.valid (0), // 无提交(或提交的指令是flush导致的bubble时,为0)
.pc (0), // 这条指令的 pc
.instr (0), // 这条指令的内容,可不改动
.skip (0), // 提交的是一条内存读写指令,且这部分内存属于设备(addr[31] == 0)时,skip为1
.isRVC (0), // 前四个 Lab 无需改动
.scFailed (0), // 前四个 Lab 无需改动
.wen (0), // 这条指令是否写入通用寄存器,1 bit
.wdest (0), // 写入哪个通用寄存器
.wdata (0) // 写入的值
);
这个周期的指令提交后,通用寄存器的内容(已连接好):
DifftestArchIntRegState DifftestArchIntRegState (
.clock (clk),
.coreid (0),
.gpr_0 (regfile.regs_nxt[0]),
// ...
);
这个周期的指令提交后,系统寄存器的内容(Lab4 的内容,前面的 Lab 可以不管):
DifftestCSRState DifftestCSRState(
);
生成波形图¶
不生成波形图时运行测试,使用make test-lab1
;需要生成波形图,使用 make test-lab1 VOPT="--dump-wave"
,运行结束后可在 build
目录下看到波形图,使用 gtkwave 打开。
默认截取前 10^6 个时钟周期。如果需要调整,使用 make test-lab1 VOPT="--dump-wave -b <begin> -e <end>"
。