用前递技术解决数据相关引发的冲突
前言
实践任务三是在实践任务二的基础上进行修改的!!!
在lab4的实验环境下,增加相应代码用前递技术解决相关引发的冲突,最后使得仿真时间相比实践任务二更少。
实验
1.添加将执行级、访存级或者写回级的数据前递到译码级的数据通路
在译码级判断当前时刻处于执行级、访存级或者写回级的指令的目的操作数的寄存器号是否与译码级源操作数的寄存器号是否相同后,表示已经发生了数据相关,需要将执行级、访存级或者写回级的数据前递到译码级。代码如下:
EXE_stage:
output [31:0] EXE_result, //执行级
assign EXE_result = es_alu_result;
MEM_stage:
output [31:0] MEM_result
assign MEM_result = ms_final_result;
WB_stage:
output [31:0] WB_result
assign WB_result = ws_final_result;
ID_stage:
input [31:0] EXE_result,
input [31:0] MEM_result,
input [31:0] WB_result,
在mycpu_top相应模块的实例化中添加对应的信号:
//实例化所用线路声明
wire [31:0] EXE_result;
wire [31:0] MEM_result;
wire [31:0] WB_result;
ID_stage:
.EXE_result (EXE_result),
.MEM_result (MEM_result),
.WB_result (WB_result)
EXE_stage:
.EXE_result (EXE_result)
MEM_stage:
.MEM_result (MEM_result)
WB_stage:
.WB_result (WB_result)
2.判断需要前递的是执行级、访存级还是写回级的数据
我们在译码级得到了当前时刻处于执行级、访存级和写回级的指令需要最终写回到寄存器的目的操作数后,接下来就要产生相应的逻辑来判断需要前递的是执行级、访存级还是写回级的数据。在译码级修改的代码如下:
//删除
/*
assign rs_value = rf_rdata1;
assign rt_value = rf_rdata2;
*/
//添加-begin
assign rs_value = rs_wait ? (rs == EXE_dest ? EXE_result :
rs == MEM_dest ? MEM_result : WB_result)
: rf_rdata1;
assign rt_value = rt_wait ? (rt == EXE_dest ? EXE_result :
rt == MEM_dest ? MEM_result : WB_result)
: rf_rdata2;
assign ds_ready_go = ds_valid & ~load_stall;
//load_stall在实践任务二就已经添加,表示第i条指令是load指令,第i+1条指令
//和load指令发生数据相关,此时需要前递的数据还未准备好,需要流水线暂停。
//添加-end
实验结果
仿真结果:
launch_simulation: Time (s): cpu = 00:00:05 ; elapsed = 00:00:12 . Memory (MB): peak = 958.809 ; gain = 0.000
过测试:
----PASS!!!
run: Time (s): cpu = 00:00:18 ; elapsed = 00:00:16 . Memory (MB): peak = 958.809 ; gain = 0.000