p7-课下总结
以下是我在写p7课下时看教程与博客产生的一些问题,记录一下它们的回答~
eret不支持延迟槽,若正常操作会带来什么影响?应如何操作以避免这种影响?
如图所示,
设计1:当eret流到D级时检测eret,并把F级NPC改成EPC.
1 | NPC = (D_eret) ? EPC : else; |
导致的问题:直接类比beq的跳转,eret的下一条指令A不可避免地会从IM中被取出来,而它本来不应该流进来的.故这样的设计会导致PC一个周期的错误.但是,之前beq如此设计是因为只有流到D级利用D级CMP模块比较两个数,才能得到跳转结果(即NPC);而eret的下一条指令的PC一定是EPC.
所以改成设计2:当eret流到D级时检测eret,若为eret则F级PC直接输出为EPC,否则仍为原来的值.NPC从而为PC + 4
1 | F_PC = (D_eret) ? EPC : F_PC_tmp; |
直观的图像表示:(来自答疑时一位同学画的图)
syscall的exccode在哪一级判断?
无所谓.在我的设计中,我在D级判断.
不过其实在教程中异常处理流的实现
->异常码
这一节中,异常码exccode越小的异常,优先级越高.
在未出现异常时,exccode应该用哪个数字表示?
教程中,中断的exccode为0,但是中断是从外部输入的,与内部异常无关;而exccode是由内部异常被判断出来的.故把未出现异常的exccode设置为0即可.
(不要设置一些奇怪的数,比如5'd31
之类的()一是因为上机可能增加新的异常exccode,二是因为这样每一级判断exccode的时候把异常exccode当成"非零值",而非"非31值"处理,从而出错)
F级中NPC模块对rst/req/stall/eret的处理?
- 优先级rst>req>stall>D_eret
- 为什么req>D_eret? 其实这种情况不会发生.req的同时D_eret,意味着异常处理程序出现了异常,而这是得到保证不会出现的.
- 为什么stall>D_eret?
当D_eret和stall同时发生,即D级是eret,E/M级存在
mtc0
指令产生stall信号,这意味着EPC还没有准备好,还需要再stall一会儿.那么必须要优先处理stall,再处理D_eret. - 以上讨论也可以理解为,D_eret只是流水级内部的一个小指令,而req/stall都更为宏观,故应处理更为宏观的信号.
PC\bd在流水时对rst/req/stall的异常处理?
(基于CP0设置在M级)
bd在F级判断后,向后流水,直至流到CP0模块用于判断EPC
rst
清空:PC
归为32'h0000_3000
,其它信号都为0req
清空:PC
归为32'h0000_4180
,其它信号都为0注意以下的信号优先级!!否则中测会出现interrupt count的问题!
FD级:优先级:rst>req>stall
rst
:全部流水信号按照rst
清空;req
:部分流水信号按照req
清空stall
:所有流水信号保持不变.
DE级:优先级rst>req>stall
rst
:全部流水信号按照rst
清空;req
:全部流水信号按照req
清空stall
:部分流水信号清空,PC
,bd
继续向下一级正常流水
EM级:优先级rst>req
rst
:全部流水信号按照rst
清空req
:全部流水信号按照req
清空
MW级:优先级rst>req
rst
:全部流水信号按照rst
清空req
:全部流水信号按照req
清空
怎么保证异常指令不会产生结果?
这里的结果指向各种寄存器里存进去了值,包括GRF,DM,hi,lo 一种比较粗暴的实现方法:假如这条指令有异常,那么就把它视作nop向后流水,具体来说是这样:
1 | E_instr = (E_exccode != 0) ? 0 : E_instr_tmp;//以E级要从EM流水线寄存器向M级流水的E_instr为例子 |
通过这种方法,大多数异常指令都将不能发挥作用.但是当CP0放在M级时,有可能产生一个小bug,见下一个问题
CP0设在M级时,怎么保证DM不会存进异常指令让它存的值?
有两种方法.
法一:将存数/取数异常(
adel
/ades
)置于E级判断.即在ALU运算出ALU_result
之后,判断其是否是这两种异常,得到E_exccode
. 由上一个问题的例子可知,因为E_exccode
不为0,我们将从E级准备向M级流水的E_instr
清零了,从而M级得不到存数/取数的相关 信息, 不会对DM产生影响.法二:将存数/取数异常(
adel
/ades
)置于M级初判断,得到M_exccode
接入CP0.若CP0显示产生异常(即req
为1),那么将DM的写使能byteen
置0,从而无法写入(这里易错,上一个问题提到的"视为nop"处理方法在这种架构中会因为太晚判断(即到了CP0所在级才判断)exccode而失效,必须要改DM写使能)具体来说:
1
2assign m_data_byteen = (req) ? 4'b0 :
m_data_byteen_tmp;
乘除槽MDU怎么对中断信号进行反应?
根据教程P7提交要求
->中断异常约束
中下图:
我们只需要在mult/div/multu/divu等乘除法相关指令的启动信号判断中加入!req
,在mthi/mtlo等写hi/lo相关指令的写使能信号中加入!req
即可.