MIPS微系统

P7需要我们的CPU支持异常处理。

具体地说,就是在“异常事件”发生的时候,调用一段预先写好的程序来处理这种异常,处理结束后再跳转回原来的程序。

P7新增了4条与系统相关的指令:mfc0 mtc0 eret syscall

概念

异常事件

我们提到的“异常事件”有两种:异常和中断

  1. (内部)异常:
    • 加法溢出
    • 除法除零
  2. (外部)中断:
    • 计时器信号
    • 键盘输入

系统桥

系统桥是连接CPU和外设的功能设备,它会给 CPU 提供一种接口,使得 CPU 可以像读写普通存储器一样(即按地址读写)来读写复杂多变的外设。

系统桥统一且简化了 CPU 的对外接口,CPU 不必为每种外设单独提供接口,符合高内聚,低耦合的设计思想。

将CPU封装成单周期

对于CPU的外部来说,它并不关心流水线中有多少条指令,是否阻塞等问题。

他们可以简单的认为CPU就是每次处理一条指令的“单周期”的。这是理解流水线CPU封装的关键所在。

CP0协处理器

CP0的两个功能:读写内部寄存器(mfc0 mtc0)+ 判断是否进行异常跳转

  1. 读写内部寄存器

    有哪些寄存器?

    | 寄存器 | 位数 | 编号 | 功能 |
    | ———- | —— | —— | ——————————————— |
    | SR | 32 | 12 | 配置异常的功能 |
    | Cause | 32 | 13 | 记录异常发生的原因和情况 |
    | EPC | 32 | 14 | 记录异常处理结束后需要返回的PC |

    寄存器功能具体解释:

    | 寄存器 | 功能域 | 位域 | 解释 |
    | :——————————- | :———————————— | :——— | :—————————————————————————————- |
    | SR(State Register) | IM(Interrupt Mask) | 15:10 | 分别对应六个外部中断,相应位置 1 表示允许中断,置 0 表示禁止中断。这是一个被动的功能,只能通过 mtc0 这个指令修改,通过修改这个功能域,我们可以屏蔽一些中断。 |
    | SR(State Register) | EXL(Exception Level) | 1 | 任何异常中断发生时置位,这会强制进入核心态(也就是进入异常中断处理程序)并禁止再次触发异常中断。 |
    | SR(State Register) | IE(Interrupt Enable) | 0 | 全局中断使能,该位置 1 表示允许中断,置 0 表示禁止中断。 |
    | Cause | BD(Branch Delay) | 31 | 当该位置 1 的时候,EPC 指向当前指令的前一条指令(一定为跳转),否则指向当前指令。 |
    | Cause | IP(Interrupt Pending) | 15:10 | 为 6 位待决的中断位,分别对应 6 个外部中断,相应位置 1 表示有中断,置 0 表示无中断,将会每个周期被修改一次,修改的内容来自计时器和外部中断。 |
    | Cause | ExcCode | 6:2 | 异常中断编码,记录当前发生的是什么异常中断。 |
    | EPC | EPC | 31:0 | 记录异常中断处理结束后需要返回的 PC。 |

    (by: Lazyfish)

  2. 判断是否进行异常跳转

    • 首先检查是否正在处理异常或中断(SR[1]是否为1)?
    • 再检查是否存在异常(ExcCodeIn是否为5'd0)?
    • 再检查是否允许中断且存在未被禁用的中断(HWInt & IM是否不为0,且SR[0] == 1)?

如果此时并未在处理异常或中断,且上述二,三条至少有一条成立,则Req置1。

1
2
3
wire abnormal = (ExcCodeIn != 5'd0) ? 1 : 0;
wire stop = ((HWInt & SR[15:10]) != 6'b0 && SR[0] == 1) ? 1 : 0;
assign Req = ((abnormal | stop) && SR[1] == 0) ? 1 : 0;