p7-搭建时的细节总结

cuzn

p7-课下总结

以下是我在写p7课下时看教程与博客产生的一些问题,记录一下它们的回答~

eret不支持延迟槽,若正常操作会带来什么影响?应如何操作以避免这种影响?

img1.png 如图所示,

设计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
2
F_PC = (D_eret) ? EPC : F_PC_tmp;
F_NPC = (D_eret) ? EPC + 4;

直观的图像表示:(来自答疑时一位同学画的图)

img2.png

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,其它信号都为0

    req清空: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
    2
      assign m_data_byteen = (req) ? 4'b0 :
    m_data_byteen_tmp;

乘除槽MDU怎么对中断信号进行反应?

根据教程P7提交要求->中断异常约束中下图:

img3.png

我们只需要在mult/div/multu/divu等乘除法相关指令的启动信号判断中加入!req,在mthi/mtlo等写hi/lo相关指令的写使能信号中加入!req即可.

0%