我的理解是,这个寄存器用于指示:在jalr的rs1!=x0且x1的情况下,jalr的rs1idx是否已经发送到了寄存器文件rs1端口。
源代码:
wire dec_jalr_rs1xn = (~dec_jalr_rs1x0) & (~dec_jalr_rs1x1);
wire jalr_rs1x1_dep = dec_i_valid & dec_jalr & dec_jalr_rs1x1 & ((~oitf_empty) | (jalr_rs1idx_cam_irrdidx));
wire jalr_rs1xn_dep = dec_i_valid & dec_jalr & dec_jalr_rs1xn & ((~oitf_empty) | (~ir_empty));
// If only depend to IR stage (OITF is empty), then if IR is under clearing, or
// it does not use RS1 index, then we can also treat it as non-dependency
wire jalr_rs1xn_dep_ir_clr = (jalr_rs1xn_dep & oitf_empty & (~ir_empty)) & (ir_valid_clr | (~ir_rs1en));
wire rs1xn_rdrf_r;
wire rs1xn_rdrf_set = (~rs1xn_rdrf_r) & dec_i_valid & dec_jalr & dec_jalr_rs1xn & ((~jalr_rs1xn_dep) | jalr_rs1xn_dep_ir_clr);
wire rs1xn_rdrf_clr = rs1xn_rdrf_r;
wire rs1xn_rdrf_ena = rs1xn_rdrf_set | rs1xn_rdrf_clr;
wire rs1xn_rdrf_nxt = rs1xn_rdrf_set | (~rs1xn_rdrf_clr);
sirv_gnrl_dfflr #(1) rs1xn_rdrf_dfflrs(rs1xn_rdrf_ena, rs1xn_rdrf_nxt, rs1xn_rdrf_r, clk, rst_n);
assign bpu2rf_rs1_ena = rs1xn_rdrf_set;
assign bpu_wait = jalr_rs1x1_dep | jalr_rs1xn_dep | rs1xn_rdrf_set;
~rs1xn_rdrf_r
断言)) 且 (~jalr_rs1xn_dep
断言) 或~ir_rs1en
断言)rs1xn_rdrf_r
断言)根据上述理解(如果正确的话),个人感觉,这个清除条件不太恰当,会造成不必要的性能损失,考虑以下一种情况:
假设jalr(rs1!=x0且x1)的前序指令A是一条执行周期为2的(当然,E203源码实现的指令中不存在这种指令,但可以假设如果将乘法指令改成执行周期为2个周期的话),不使用rs1的指令,此时OITF为空,A在IR中。
如上表所示,在周期4恢复取指。但正常的应该是在周期3就恢复,因为寄存器文件中rs1的值在周期3已经正确取得,此时不应该又发送一次rs1idx到寄存器端口(即rs1xn_rdrf_set不应该断言)而 导致无法取指(即造成bpu_wait
断言)。虽然这种不恰当会后续得到恢复,但多产生了一个气泡。
修改方式有两种(简言之就是将rs1xn_rdrf的标志,维持到前序指令将结果写回寄存器文件/执行完毕):
rs1xn_rdrf的清除条件改成:jalr的rs1idx已经发送到寄存器文件的rs1端口 并且 所有指令已经执行完毕(即指令已经写回目的寄存器)。 即 rs1xn_rdrf_clr=(~jalr_rs1xn_dep) & rs1xn_rdrf_r
。
删除jalr_rs1xn_dep_ir_clr
的~ir_rs1en
这一项,在OITF为空的情况下,无论IR中的指令是否使用了rs1作为源寄存器,最终都需要到达最后一个执行周期,即ir_vlaid_clr
的断言一定会发生。此时,无需修改rs1xn_rdrf的清除条件,因为修改后,rs1xn_rdrf_clr=rs1xn_rdrf_r
断言时,所有指令必定已经完成了,即蕴含了~jalr_rs1xn_dep
断言。