-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[分享]Verilog代码接入到Difftest #9
Comments
大佬你好,请问是要在SimTop.v中融合原cpu中顶层.v,还是在SimTop.v中调用原顶层.v呢? |
都可以,只要能把提交信息的端口连到相应的模块就行 |
你好,请问“在指令提交的时刻其产生的影响恰好生效”,是不是要求需要实现流水线结构? |
想请问一下这里的CPU的所有RTL文件,指的是什么?是define.v,if_stage.v之类的文件吗? |
我理解是的。要把自己所有的CPU代码接入进来。 |
你好,请问您这个教程中接入的CPU是单周期的吗? |
你好,请问这个地方为什么是写入一半数据呢 |
是的,流水线的提交也是类似的 |
不好意思,可能给你造成了一些误解,这个是我测试sw ld 时为了让地址对齐临时写的,我在上面已经更新代码了,我把掩码的处理和数据的对仿真内存的适应放到了一个单独的模块(只针对difftest中的仿真内存有效)。 module mem_ctrl(
input rst,
// CPU端接口
input [7:0]mem_byte_enble,
input [`BUS_WIDTH]mem_addr,
input mem_rd_en,
input mem_wr_en,
input [`BUS_WIDTH]mem_wr_data,
output reg [`BUS_WIDTH]mem_rd_data,
// 内存接口
output [`BUS_WIDTH]ram_addr,
output ram_wr_en,
output reg [`BUS_WIDTH]ram_wmask,
output reg [`BUS_WIDTH]ram_wr_data,
output ram_rd_en,
input [`BUS_WIDTH]ram_rd_data
);
reg [`BUS_WIDTH] sb_ram_wmask ;
reg [`BUS_WIDTH] sb_ram_wr_data ;
reg [`BUS_WIDTH] sh_ram_wmask ;
reg [`BUS_WIDTH] sh_ram_wr_data ;
reg [`BUS_WIDTH] sw_ram_wmask ;
reg [`BUS_WIDTH] sw_ram_wr_data ;
reg [`BUS_WIDTH] sd_ram_wmask ;
reg [`BUS_WIDTH] sd_ram_wr_data ;
reg [`BUS_WIDTH] lb_ram_rd_data ;
reg [`BUS_WIDTH] lh_ram_rd_data ;
reg [`BUS_WIDTH] lw_ram_rd_data ;
reg [`BUS_WIDTH] ld_ram_rd_data ;
assign ram_addr = mem_addr;
assign ram_wr_en = rst ? 0 : mem_wr_en;
assign ram_rd_en = rst ? 0 : mem_rd_en;
wire sb_signal = mem_wr_en & (mem_byte_enble == 8'b0000_0001);
wire sh_signal = mem_wr_en & (mem_byte_enble == 8'b0000_0011);
wire sw_signal = mem_wr_en & (mem_byte_enble == 8'b0000_1111);
wire sd_signal = mem_wr_en & (mem_byte_enble == 8'b1111_1111);
wire lb_signal = mem_rd_en & (mem_byte_enble == 8'b0000_0001);
wire lh_signal = mem_rd_en & (mem_byte_enble == 8'b0000_0011);
wire lw_signal = mem_rd_en & (mem_byte_enble == 8'b0000_1111);
wire ld_signal = mem_rd_en & (mem_byte_enble == 8'b1111_1111);
// 写MUX
always @(*) begin
if(rst)begin
ram_wmask = `ZERO_WORD;
ram_wr_data = `ZERO_WORD;
end
else if(sb_signal)begin
ram_wmask = sb_ram_wmask ;
ram_wr_data = sb_ram_wr_data;
end
else if(sh_signal)begin
ram_wmask = sh_ram_wmask ;
ram_wr_data = sh_ram_wr_data;
end
else if(sw_signal)begin
ram_wmask = sw_ram_wmask ;
ram_wr_data = sw_ram_wr_data;
end
else if(sd_signal)begin
ram_wmask = sd_ram_wmask ;
ram_wr_data = sd_ram_wr_data;
end
else begin
ram_wmask = `ZERO_WORD;
ram_wr_data = `ZERO_WORD;
end
end
// 读MUX
always @(*) begin
if(rst)
mem_rd_data = `ZERO_WORD;
else if(lb_signal)
mem_rd_data = lb_ram_rd_data;
else if(lh_signal)
mem_rd_data = lh_ram_rd_data;
else if(lw_signal)
mem_rd_data = lw_ram_rd_data;
else if(ld_signal)
mem_rd_data = ld_ram_rd_data;
else
mem_rd_data = `ZERO_WORD;
end
// 写字节的处理
always @(sb_signal or mem_addr[2:0] or mem_wr_data[7:0]) begin
if(sb_signal)begin
case(mem_addr[2:0])
3'd0:begin
sb_ram_wmask = 64'h0000_0000_0000_00FF;
sb_ram_wr_data = {56'd0,mem_wr_data[7:0]};
end
3'd1:begin
sb_ram_wmask = 64'h0000_0000_0000_FF00;
sb_ram_wr_data = {48'd0,mem_wr_data[7:0],8'd0};
end
3'd2:begin
sb_ram_wmask = 64'h0000_0000_00FF_0000;
sb_ram_wr_data = {40'd0,mem_wr_data[7:0],16'd0};
end
3'd3:begin
sb_ram_wmask = 64'h0000_0000_FF00_0000;
sb_ram_wr_data = {32'd0,mem_wr_data[7:0],24'd0};
end
3'd4:begin
sb_ram_wmask = 64'h0000_00FF_0000_0000;
sb_ram_wr_data = {24'd0,mem_wr_data[7:0],32'd0};
end
3'd5:begin
sb_ram_wmask = 64'h0000_FF00_0000_0000;
sb_ram_wr_data = {16'd0,mem_wr_data[7:0],40'd0};
end
3'd6:begin
sb_ram_wmask = 64'h00FF_0000_0000_0000;
sb_ram_wr_data = {8'd0,mem_wr_data[7:0],48'd0};
end
3'd7:begin
sb_ram_wmask = 64'hFF00_0000_0000_0000;
sb_ram_wr_data = {mem_wr_data[7:0],56'd0};
end
endcase
end
else begin
sb_ram_wmask = `ZERO_WORD;
sb_ram_wr_data = `ZERO_WORD;
end
end
// 写双字的处理
always @(sh_signal or mem_addr[2:1] or mem_wr_data[15:0]) begin
if(sh_signal)begin
case(mem_addr[2:1])
2'd0:begin
sh_ram_wmask = 64'h0000_0000_0000_FFFF;
sh_ram_wr_data = {48'd0,mem_wr_data[15:0]};
end
2'd1:begin
sh_ram_wmask = 64'h0000_0000_FFFF_0000;
sh_ram_wr_data = {32'd0,mem_wr_data[15:0],16'd0};
end
2'd2:begin
sh_ram_wmask = 64'h0000_FFFF_0000_0000;
sh_ram_wr_data = {16'd0,mem_wr_data[15:0],32'd0};
end
2'd3:begin
sh_ram_wmask = 64'hFFFF_0000_0000_0000;
sh_ram_wr_data = {mem_wr_data[15:0],48'd0};
end
endcase
end
else begin
sh_ram_wmask = `ZERO_WORD;
sh_ram_wr_data = `ZERO_WORD;
end
end
// 4字节写
always @(sw_signal or mem_addr[2] or mem_wr_data[31:0]) begin
if(sw_signal)begin
case(mem_addr[2])
1'b0:begin
sw_ram_wmask = 64'h0000_0000_FFFF_FFFF;
sw_ram_wr_data = {32'd0,mem_wr_data[31:0]};
end
1'b1:begin
sw_ram_wmask = 64'hFFFF_FFFF_0000_0000;
sw_ram_wr_data = {mem_wr_data[31:0],32'd0};
end
endcase
end
else begin
sw_ram_wmask = `ZERO_WORD;
sw_ram_wr_data = `ZERO_WORD;
end
end
// 8字节写
always @(sd_signal or mem_wr_data) begin
if(sd_signal) begin
sd_ram_wmask = 64'hFFFF_FFFF_FFFF_FFFF;
sd_ram_wr_data = mem_wr_data;
end
else begin
sd_ram_wmask = `ZERO_WORD;
sd_ram_wr_data = `ZERO_WORD;
end
end
// 读字节处理
always @(lb_signal or mem_addr[2:0] or ram_rd_data) begin
if(lb_signal)
case(mem_addr[2:0])
3'd0:lb_ram_rd_data = {56'd0,ram_rd_data[ 7: 0]};
3'd1:lb_ram_rd_data = {56'd0,ram_rd_data[15: 8]};
3'd2:lb_ram_rd_data = {56'd0,ram_rd_data[23:16]};
3'd3:lb_ram_rd_data = {56'd0,ram_rd_data[31:24]};
3'd4:lb_ram_rd_data = {56'd0,ram_rd_data[39:32]};
3'd5:lb_ram_rd_data = {56'd0,ram_rd_data[47:40]};
3'd6:lb_ram_rd_data = {56'd0,ram_rd_data[55:48]};
3'd7:lb_ram_rd_data = {56'd0,ram_rd_data[63:56]};
endcase
else
lb_ram_rd_data = `ZERO_WORD;
end
// 读双字节
always @(lh_signal or mem_addr[2:1] or ram_rd_data) begin
if(lh_signal)
case(mem_addr[2:1])
2'd0:lh_ram_rd_data = {48'd0,ram_rd_data[15: 0]};
2'd1:lh_ram_rd_data = {48'd0,ram_rd_data[31:16]};
2'd2:lh_ram_rd_data = {48'd0,ram_rd_data[47:32]};
2'd3:lh_ram_rd_data = {48'd0,ram_rd_data[63:48]};
endcase
else
lh_ram_rd_data = `ZERO_WORD;
end
// 读四字节
always @(lw_signal or mem_addr[2] or ram_rd_data) begin
if(lw_signal)
case(mem_addr[2])
1'b0:lw_ram_rd_data = {32'd0,ram_rd_data[31: 0]};
1'b1:lw_ram_rd_data = {32'd0,ram_rd_data[63:32]};
endcase
else
lw_ram_rd_data = `ZERO_WORD;
end
// 读八字节
always @(ld_signal or ram_rd_data) begin
if(ld_signal)
ld_ram_rd_data = ram_rd_data;
else
ld_ram_rd_data = `ZERO_WORD;
end
endmodule
|
求问如果流水线的话是不是要把wb阶段的pc接入cmt_pc,那么如果发生控制冒险清零PC,difftest报错pc不一致的问题如何处理呢,我的思路是能不能发生冒险的时候不让difftest继续比较pc的值,直到正常指令执行到wb阶段再进行比较(已经试过设置skip信号的方法,但是没有用) |
写回阶段的pc,你指的是计算出的跳转地址,还是执行到写回阶段跳转指令所在的地址呢 |
我用的是wb_pc和cmt_pc连接,也就是执行到写回阶段指令所在的地址。当出现控制冒险时,我flush了一些寄存器(包括PC,就算不flush,pc也是错误的,所以不如都flush了🤣),之后这些气泡执行到wb阶段时,wb_pc 为0,这时候difftest就会给我报错,表示this_pc出现错误,right_pc为目标指令跳转地址,wrong_pc 为000000000,但其实我跳转正确了,只是指令还没有执行到wb阶段,所以想跳过那些对于气泡的比较,不知道怎么办😂 |
我想请问 |
|
请问difftest是只能对比指令和通用寄存器的差异吗?写到RAM中的数据是否正确能否对比出来呢? |
请问difftest框架内的ram是不能支持既取指又读内存中的数据吗?必须要自己重新改写ram吗? |
应该是,这个issue也给了一写两读的RAM模块供使用 |
同学你好,我参照你的ram模块和mem_ctrl模块接入了simtop模块,也能正常difftest,但是在ld指令显示出错 |
请问如何编译及运行cpu_test下的全部验证程序呢? |
https://github.com/OSCPU/oscpu-framework repo的readme里面 |
多谢多谢! |
前言
昨天看到有老哥写了Chisel的difftest接入,心血来潮想试试Verilog怎么接入。
一定要参考Chisel的difftest接入、DiffTest Usge这两篇,我算是一点点补充
水平有限,请各位多多指教。
TOP文件
首先我们要在difftest的上一层建立一个build文件夹,并新建一个 SimTop.v 并将下列内容写入,这个文件就是整个RTL仿真设计的顶层。
还要将CPU的所有RTL文件放入。(也可以考虑用 make install 自动copy)
RAM的接入
对于DiffTest框架,提供了一块申请的8GB内存在路径,在difftest/src/test/csrc/common/ram.h中定义了仿真内存的大小,也提供了对应的读写函数,Verilog通过DPI-C的方式访问读写函数完成对仿真内存的读写,代码在difftest/src/test/vsrc/common/ram.v
下面提供的RAMHelper好像只有一读一写,而在没有Cache的情况下,没有办法让取指和访存同时访问这块内存(我在想可不可以上升取指下降访存来过渡),于是我重写了一个有一写两读的RAM模块。
其中指令端口通过一个MUX将64位数据对齐到了32位。inst_addr右移3位是因为CPU内部是以字节编址,而仿真内存是以8字节编址,MUX的选择信号是右移出去三位数据的最高位,来选择64位中的高32位/低32位。
数据的读写也是按照4字节对齐,为了适应仿真内存也要做相应的映射,详情见下述代码
将此模块实例化到 SimTop.v 中并且将端口接入到自己设计的CPU中,这样就完成了,RAM的接入
指令的提交
Difftest通过,DifftestInstrCommit这个模块来将信号提交到DiffTest中。
将需要提交的信号链接,记住手册里的一句话,在指令提交的时刻其产生的影响恰好生效
REGFILE的提交
对应模块名为DifftestArchIntRegState,类似的方法接入
编译运行
然后就可以编译emu
运行difftest
根据日志可以看到已经捕获到错误的信息
Tips:
将Difftest的Makefile中clean:vcs-clean下面的一行改成
可以在执行make clean时不删除RTL代码
The text was updated successfully, but these errors were encountered: