Rocket - core - id阶段异常的处理


https://mp.weixin.qq.com/s/-FmAFPptdUCibzOGO_yCnQ

 

简单介绍ID阶段异常的处理。

本文目录:

1. id_xcpt

2. alu

 

以下正文:

1. id_xcpt

id_xcpt表示ID阶段发生的异常和检测到的中断:

 

2. ex_reg_xcpt

id_xcpt在ctrl_killd的过滤下向ex_reg_xcpt传递:

因为csr.io.interrupt会触发ctrl_killd导致id_xcpt无法向ex_reg_xcpt传递,所以只有当没有发生中断时,id_xcpt才会向ex_reg_xcpt传递。也就是说:

a. 如果ID阶段同时发生异常和检测到中断,那么中断优先得到处理;待中断处理完成后重新执行该指令时,同样会触发异常;

b. ex_reg_xcpt中只记录了id阶段传递过来的异常,而没有中断的情形;

 

3. alu

id_xcpt同样会对ex阶段的alu产生影响:

 

1) !ctrl_killd && id_xcpt

首先,!ctrl_killd && id_xcpt表示仅发生异常的情况。

其次,在这种情况下,需要记录发生异常的指令的地址,这个地址使用alu进行计算。

 

2) alu

 

ID阶段发生异常的指令的地址,通过alu进行计算:

其中:

a. 需要alu执行加法操作;

b. 计算结果alu.io.out辗转存入mtval寄存器;

c. 如果是rvc的情况,且4字节2指令中的第二条指令发生异常,那么第一个运算数为pc,第二个运算数为指令大小即2,即addr(inst) = pc + 2;

d. bpu.io.xcpt_if表示断点触发,只需要记录指令地址即可;

e. id_xcpt0的两种错误皆为取指异常,记录指令地址(同c):

f. bpu.io.debug_if暂不考虑;

g. 现在只剩下id_illegal_insn的情况,非法指令异常的处理是记录指令的内容。这里使用的第一个运算数是A1_RS1,第二个运算数是0。

所以alu的第一个运算数的值要组装成指令内容:

指令的内容装入ex_reg_rs_msb/lsb之后,经过bypass逻辑,进入到ex_op1:

 

3) alu.io.out

 

alu.io.out是如何进入mtval寄存器的呢?

 

A. alu.io.out的值存入mem_reg_wdata寄存器中:

这里受到开关ex_pc_valid的影响,因为只有异常而没有中断,所以ex_reg_valid = ex_pc_valid = 1:

 

B. mem_reg_wdata存入mem_int_wdata:

 

C. mem_int_data存入wb_reg_wdata寄存器中:

 

D. wb_reg_data写入到csr.io.tval:

这里需要经过tval_valid的过滤,其包括两个条件:

a. wb_xcpt = 1:这里发生了异常,可以满足;

b. wb_cause列举的情况,包含了ID阶段异常中除CSR.debugTriggerCause之外的全部情况;

 

E. tval写入到reg_mtval寄存器中: