Rocket - core - sfence.vma
https://mp.weixin.qq.com/s/eJd4VpU5fsZ6WM_YYXPX4Q
简单介绍流水线对sfence.vma指令的处理。
1. io.imem.sfence
根据规范,sfence.vma指令的用途如下:
其效果最终通过io.imem.sfence/io.ptw.sfence来实现:
本文主要介绍sfence对流水线的影响。
2. wb_reg_sfence
wb_reg_sfence用于组装io.imem.sfence:
wb_reg_sfence的值在mem_pc_valid的控制下,由mem_reg_sfence的传递而来。
3. mem_reg_sfence
mem_reg_sfence可以触发take_pc_mem,导致if阶段重新取指,id/ex阶段被kill:
mem_reg_sfence的值由ex_sfence进行更新,并受到mem_reg_flush_pipe的影响。
4. ex_sfence
ex_sfence在ex_pc_valid的控制下,向mem_reg_sfence传递:
可以看到mem_reg_flush_pipe也会对mem_reg_sfence的值产生影响。mem_reg_flush_pipe的值由ex_reg_flush_pipe传递而来。ex_reg_flush_pipe和ex_ctrl都由id阶段进行更新。
5. id_sfence
如果没有ctrl_killd,则id_ctrl用于更新ex_ctrl:
id_sfence表示当前指令为sfence.vma指令:
id_sfence为真,导致id_csr_flush为真,进而在下一个时钟对ex_reg_flush_pipe寄存器的值进行更新。
可以看出,sfence.vma指令如同fence_i指令,可以触发流水线的flush。
6. 流水线对sfence.vma指令的处理
1) id阶段
更新ex_reg_flush_pipe,触发flush流程。
2) ex阶段
a. 根据ex_ctrl中的信号(ex_ctrl.mem/ex_ctrl.mem_cmd)触发ex_sfence,进而更新mem_reg_sfence寄存器的值;
b. ex_reg_flush_pipe用于更新mem_reg_flush_pipe;
3) mem阶段
a. mem_reg_sfence用于更新wb_reg_sfence;
b. mem_reg_sfence触发take_pc_mem,导致id/ex阶段被kill,if阶段重新取指;需要注意的是,mem阶段本身没有被kill,仍然可以向wb阶段继续传递;
c. mem_reg_flush_pipe用于更新wb_reg_flush_pipe的值;
4) wb阶段
a. wb_reg_sfence用于组装io.imem.sfence;
b. wb_reg_flush_pipe触发take_pc_wb,导致id/ex/mem阶段被kill,if阶段重新取指;流水线再次被kill;
7. mem_reg_flush_pipe对mem_reg_sfence值的影响
图示如下:
一般情况下,mem_reg_sfence的值由ex_sfence进行更新。
在mem_reg_valid && mem_reg_flush_pipe的情况下,mem_reg_sfence的值直接使用0进行更新。即如果前一条指令具备flush流水线的效果,那么其后的sfence指令可以产生sfence的效果。
考虑指令序列fence_i; sfence.vma:
1) 时钟周期t
fence_i: 在mem阶段
sfence.vma: 在ex阶段
此时,mem_reg_valid = mem_reg_flush_pipe = 1, 导致sfence.vma指令未能将用于更新mem_reg_sfence的值置为1;
2) 时钟周期t+1
fence_i: 在wb阶段
sfence.vma: 在mem阶段
此时,fence_i指令触发take_pc_wb,导致mem阶段的sfence.vma指令被kill,sfence.vma指令无法执行到wb阶段。
a. 即便在时钟周期t,改变了用于更新mem_reg_sfence的值,take_pc_mem的效果也已被take_pc_wb的效果掩盖;
b. 因为sfence.vma指令无法执行到wb阶段,所以不会对io.imem.sfence产生影响;
3) 时钟周期t+2
sfence.vma重新被取指执行。