设计文档
任务分类
- 支持异常处理
- 支持系统桥
支持异常处理
添加CP0协处理器
拥有三个寄存器,分别为[12]SR、[13]Cause、[14]EPC
SR为配置寄存器,IM可以设置屏蔽对应中断,EXL在进入中断时设置1,退出时设置0,IE决定全局中断是否响应。
Cause为原因寄存器,BD记录是否是跳转指令,IP写入HWint,ExcCode写入异常编码
EPC为返回地址EPC,写入受害指令,特别地,如果是延迟槽指令,写入PC-4既受害指令
CP0协处理器连接及表现
- clk时钟信号进入
- reset复位信号,上升沿有效则复位所有寄存器
- en写使能
- add写入寄存器地址
- wd写入数据
- rd读出数据
- vpc受害pc,直接连入M级wpc
- bd是否延迟槽,M级增加寄存器保存上一条是否是跳转,由此输出是否延迟槽
- exccode每级流水
- hwint输入timer1、2和中断发生器中断信号
- exlclr复位exl
- epcout输出EPC寄存器保存的地址
- req输出激活异常处理的信号
单周期封装
由于异常产生位置最晚为M级,故设置M级PC为宏观PC,并将CP0放置在M级
清空流水线设计
M级产生req信号激活异常处理,通入mips父模块,F级新pc为4180H,freg、dreg、ereg上升沿触发清零。
eret设计
cp0的epcout直接连接到f级,f级输出指令判断是否eret,若是,则pcin跳转到epc。
遇到的bug
-
关键bug1:当m级是由于stall产生的空泡时产生外部中断,未能成功保存受害指令pc 解决方法:可以只有非空泡才响应中断,或者在空泡中流水堵塞指令的所需数据,如pc和bd
-
关键bug2:eret的无延迟槽实现有误,直接特判改变了指令地址,却流水了错误的npco 解决方法:npco也加入eret特判,或者按照保留空延迟槽统一处理
-
bug3:cp0内部实现优先级问题,应保证除reset任何情况下hwint每一周期都保存进对应位,同时中断优先于异常
-
bug4:bd判定,如果通过判断cp0所在流水级上一条指令是否是跳转来判断,一定要注意处理reset和空泡。
-
bug5:bridge实现中,注意结合exccode判断sl指令是否合法,如果指令非法应不写使能任何外设。
-
bug6:mfc0或eret两指令与mtc0冲突一定注意解决,我官方贴看的有点快,以为不需要考虑epc冲突,其实是需要的,只是不需要通过转发解决。
思考题
- 鼠标键盘输入信号一方面可以通过系统桥访问,另一方面会产生中断,可以对信号做出响应。
- 如果中断异常程序由用户提供,同样可以提供所希望的功能,但是会有一定风险。既处理程序地址可能被篡改到非法程序所在位置,进而修改正常程序运行数据。
- 因为cpu要保持简洁性,无法针对每一种外设提供接口,故借助bridge提供封装,简化cpu设计。
- 模式0
模式1
1 2 3 4 5
s(t)->s(t-1),t>0 s(0)-x=0-->s(0) s(0)->y=1 s(t)->t=0,t>0 s(0)-x=1-->s(t)
1 2
s(t)->s(t-1),t>0 s(0)->s(t),t=0
- 会导致无法获取到受害pc和bd信号,应该保留受害pc和bd信号。
- 读取和写入为同一地址,则重复执行结果不同,导致异常处理程序处理延迟槽指令跳回重新执行时无法再一次正确执行jalr指令。
选做: 重点测试新加入的指令,构建延迟槽内外的外部中断时异常、阻塞时eret、外部中断时m级stall空泡、mtc0后跟eret、mtc0后跟mfc0等组合。