【P7&Loongson】支持部分中断/异常处理
概况
常规单发射5级流水线cpu。新增支持指令{mtc0, mfc0, eret, syscall, break, bgezal, bltzal}
;新增异常处理{Int, AdEL, AdES, Ov, RI}
,其中Int中断包括软件、硬件、计时器中断(硬件中断未测);新增CP0寄存器{BadVAddr, Count, Compare, Status, Cause, EPC, PrID}
。通过Loongson.SRAM功能测试。
(新增设计均为能暂停便暂停,无cache、tlb)
Thinking_Log
1.为何将 取指/访存 地址错误一并归到AdEL异常中?
如此写BadVAddr寄存器的操作又复杂了些
2.为何不约定eret存在延迟槽?
如此eret的相关硬件处理又复杂了些
Bug_Log
1.检测到异常后,未能完全将受害指令之后的指令影响消除
受害指令前后指令“假冲突”产生的阻塞
Stall与Req同时存在时,忽略了增添Req对F_pc写使能的影响,导致Stall单方面使F_pc不可写,F_pc未更新,异常跳转NPC失效。
例: 某时刻 D-E-M : mfhi-syscall-divu;下一周期stall和req同时存在
下方红圈处F_pc值未更新
解决: 顶层Req信号优先级最高,修正IFU的写使能We
错误开始的乘除槽
例: 某时刻 D-E-M : bnez-divu-syscall;req存在,div进入乘除槽HILO开始运算
解决: M级必定能检测出是否发生异常,只有在E级的乘除槽脱离管控;所以异常发生时,受害指令后的指令最多刚刚到乘除槽,所以只需要用Req信号限制乘除槽的运作即可
always @(posedge Clk) begin
if(Rst == 1) begin
HI <= 0;
LO <= 0;
Wait <= 0;
Busy <= 0;
end else if(Req != 1) begin //Req limitation
if(Wait == 0) begin
case(HILOOp)
...
end
2.放走W级指令不意味着W级不需要Req清空
事实上,放走W级指令是只GRF处可以仍写。5级流水各级含义时间长了容易混淆;寄存器是组合信号的源头;顶层信号的来历要清楚(全是组合逻辑,有些搭配了fsm)
3.端口/信号的隐藏意义改变
最初的DMWr是区分Store和Load类指令的必要条件,因而最初设计用DMWr区分AdES和AdEL。
但后续设计令Req==1
时强制将传入BE.DMWr
端口的信号改0,导致BE.DMWr
无法区分L/S指令,但自己仍认为DMWr信号具有相关功能,所以错判异常。
此BE.DMWr
非最初的CU.DMWr
,而是CU.DMWr & ~Req
随着不断增加设计,传入信号的意义可能和最初端口命名的意义有所脱节,从而导致错误。要时刻熟悉设计的部件,同时端口/信号命名仍需完善!
类似问题:顶层寄存器控制信号Stall传入各流水级时,使用了端口名Reg_Rst,导致各级内Reg_Rst端口信号含义不清,需改进!
4.eret指令不存在延迟槽
看了测试程序给的异常处理程序断eret后跟了nop,想当然当作延迟槽了。
结果之后有一段程序,利用eret返回错误epc导致AdEL异常,同时eret后紧跟sw,提前修改了data_sram导致错误。
解决:将错就错,对eret增加清空延迟槽操作。
5.顶层寄存器控制信号冲突的担忧
需弄清各信号产生的逻辑和关联:①产生逻辑;②信号优先级
- Stall
- Req
- linger
- LoadDelay
- Clr
6.由于读BRAM IP核在下一拍返回值,因而将D_instr改为的组合逻辑,不在寄存器中
D级指令的一些操作时,要记得这点
7.寄存器信号的可读写性
CP0各寄存器各个位的可读写性不尽相同。
重申了本质问题:寄存器的读/写/复位