BUAA_CO_P7设计文稿

P7CPU设计文稿

1.总体架构

Structure

任务清单

新增指令:mfc0, mtc0, eret, syscall

P7 与之前的 project 相比,涉及的内容较多,所以在实现的时候很容易手忙脚乱,这里列出完成 P7 需要的事宜:

任务 解释
计时器 课程组提供实现代码,只需要结合代码和文档理解应用即可。
系统桥 为 CPU 提供统一的访问外设的接口,需要按规格自行实现。
协处理器 CP0 设置 CPU 的异常处理功能,反馈 CPU 的异常信息,需要按规格自行实现。
内部异常检测与流水 CPU 需要具有可以检测内部指令执行错误的能力。
外部中断响应 CPU 需要具有初步响应外部中断信号的能力。
异常处理指令 在异常处理程序中,会有一些特殊的指令需要实现。
单周期 CPU 的封装 让 CPU 从外部看上去是一个单周期 CPU。
异常处理程序 利用 MARS 编写简单的异常处理程序用于测试。

p6CPU

2.具体实现

1.CP0

将CP0置于M级,故宏观PC为M级对于PC

CP0 的端口声明如下:

端口 方向 位数 解释
clk I 1 时钟信号。
reset I 1 复位信号。
en I 1 写使能信号。
CP0Addr I 5 寄存器地址。
CP0In I 32 CP0 写入数据。
CP0Out O 32 CP0 读出数据。
VPC I 32 受害 PC。
BDIn I 1 是否是延迟槽指令。
ExcCodeIn I 5 记录异常类型。
HWInt I 6 输入中断信号。
EXLClr I 1 用来复位 EXL。
EPCOut O 32 EPC 的值。
Req O 1 进入处理程序请求。

CP0位置确定

2.约定

  1. 如果发生异常的指令是延迟槽指令,那么返回程序时仍然返回这条指令所属的跳转指令。也就是说“异常延迟槽回到跳转”。
  2. 如果发生异常的指令是跳转指令,那么我们要求执行完延迟槽。
  3. 如果发生异常的指令是乘除指令的下一条,乘除指令不被撤回。也就是对于 M错误指令,W乘除指令 的情况,此时乘除槽正在计算,本来在异常处理时可能会覆盖乘除槽的结果,但是我们约定不会这么做。但是注意,如果是 E乘除指令,M错误指令,你要保证乘除指令不执行。

范围约定

strict

3.中断异常

中断异常约束

  • 异常入口:《SMRL》的表 5.1 中定义了 MIPS 的异常入口,但考虑到简化设计以及与 MARS 保持一致,我们只支持 0x4180 一个入口地址,所有异常与中断都将从这里进入。

  • 嵌套中断异常:本实验不要求支持中断异常嵌套的情况。

  • 优先级:中断优先级高于异常优先级,即当有异常提交至 CP0 寄存器时,若有中断发生,则硬件应先响应中断,并重新执行受害指令及其后续指令;若没有中断发生,则处理异常。

  • 精确异常:

    • 除下面的情况外,对所有中断异常的处理都应遵循精确异常的处理规则。

    • 在进入中断或异常状态时,如果受害指令及其后续指令

      已经改变

      了 MDU 的状态,则无需恢复。假设 CP0 在 M 级,MDU 在 E 级,考虑以下情况:

      • mult 在 E 级启动了乘法运算,流水到 M 级时产生了中断,此时无需停止乘法计算,其它乘除法指令同理。
      • mthi 在 E 级修改了 HI 寄存器,流水到 M 级时产生了中断,此时无需恢复 HI 寄存器的值,mtlo 同理。
      • mult 在 E 级,受害指令在 M 级,此时还未改变 MDU 状态,不应开始乘法计算,其它乘除法指令同理。
      • mthi 在 E 级,受害指令在 M 级,此时还未改变 MDU 状态,不应修改 HI 寄存器的值,mtlo 同理。
  • 中断规范:

    • Timer0 输出的中断信号接入 HWInt[0] (最低中断位),Timer1 输出的中断信号接入 HWInt[1],来自中断发生器的中断信号接入 HWInt[2]。
    • 规定中断产生时的受害指令为宏观 PC 对应的指令,此时应将宏观 PC 写入 EPC。
  • MIPS 微系统需要支持的异常:

    | ExcCode | 助记符 | 描述 |
    | :——— | :——— | :———————————————————————- |
    | 0 | Int | 中断。 |
    | 4 | AdEL | 取数或取指时地址错误。 |
    | 5 | AdES | 存数时地址错误。 |
    | 8 | Syscall | 系统调用。 |
    | 10 | RI | 不认识的(或者非法的)指令码。 |
    | 12 | Ov | 自陷形式的整数算术指令(例如 add)导致的溢出。 |

异常与中断码 助记符与名称 指令与指令类型 描述
0 Int (外部中断) 所有指令 中断请求,来源于计时器与外部中断。
4 AdEL (取指异常) 所有指令 PC 地址未字对齐。
PC 地址超过 0x3000 ~ 0x6ffc
AdEL (取数异常) lw 取数地址未与 4 字节对齐。
lh 取数地址未与 2 字节对齐。
lh, lb 取 Timer 寄存器的值。
load 型指令 计算地址时加法溢出。
load 型指令 取数地址超出 DM、Timer0、Timer1、中断发生器的范围。
5 AdES (存数异常) sw 存数地址未 4 字节对齐。
sh 存数地址未 2 字节对齐。
sh, sb 存 Timer 寄存器的值。
store 型指令 计算地址加法溢出。
store 型指令 向计时器的 Count 寄存器存值。
store 型指令 存数地址超出 DM、Timer0、Timer1、中断发生器的范围。
8 Syscall (系统调用) syscall 系统调用。
10 RI(未知指令) 未知的指令码。
12 Ov(溢出异常) add, addi, sub 算术溢出。

4.eret指令

eret 将保存在 CP0 的 EPC 寄存器中的现场(被中断指令的下一条地址)写入 PC,从而实现从中断、 异常或指令执行错误的处理程序中返回

3.思考题

1.问题

1、请查阅相关资料,说明鼠标和键盘的输入信号是如何被 CPU 知晓的?

2、请思考为什么我们的 CPU 处理中断异常必须是已经指定好的地址?如果你的 CPU 支持用户自定义入口地址,即处理中断异常的程序由用户提供,其还能提供我们所希望的功能吗?如果可以,请说明这样可能会出现什么问题?否则举例说明。(假设用户提供的中断处理程序合法)

3、为何与外设通信需要 Bridge?

4、请阅读官方提供的定时器源代码,阐述两种中断模式的异同,并分别针对每一种模式绘制状态移图。

5、倘若中断信号流入的时候,在检测宏观 PC 的一级如果是一条空泡(你的 CPU 该级所有信息均为空)指令,此时会发生什么问题?在此例基础上请思考:在 P7 中,清空流水线产生的空泡指令应该保留原指令的哪些信息?

6、为什么 jalr 指令为什么不能写成 jalr $31, $31

2.答案

  1. 鼠标和键盘的输入信号是通过它们的接口(例如 USB)发送给计算机的主板。主板上的输入/输出控制器会将这些信号转换成数字信号,然后发送给中央处理器(CPU)。CPU会解析这些信号并根据用户的操作来执行相应的指令。IO设备的输入输出有好几种方式,键盘、鼠标这类的低速设备是通过中断请求的方式进行IO操作的。即当键盘上按下一个按键的时候,键盘会发出一个中断信号,中断信号经过中断控制器传到CPU,然后CPU根据不同的中断号执行不同的中断响应程序,然后进行相应的IO操作,把按下的按键编码读到寄存器(或者鼠标的操作),最后放入内存中。

  2. 保证设计的统一性,即通过协议保证接口更加兼容。用户使用自定义处理可能出现不兼容的问题

  3. 正如教程所说,系统桥是连接 CPU 和外设的功能设备,它会给 CPU 提供一种接口,使得 CPU 可以像读写普通存储器一样(即按地址读写)来读写复杂多变的外设,不用管数据是从哪来,怎么来,只用发挥CPU本身功能就可以。系统桥统一且简化了 CPU 的对外接口,CPU 不必为每种外设单独提供接口,符合高内聚,低耦合的设计思想。

  4. 模式0通常用于产生定时中断 ,当计数器倒计数为 0 后,计数器停止计数,Ctrl 寄存器的计数使能自动变为 0,并且中断信号始终保持有效,直到屏蔽中断或重新开始计数。

    mode0

    模式1当计数器倒计数为 0 后, 初值寄存器值被自动加载至计数器, 计数器继续倒计数。模式 1 通常用于产生周期性脉冲

    mode1

  5. 会导致宏观PC突然为0或者为x。在清空流水线的时候,应该保留PC信息。

  6. PC <- GPR[rs]和GPR[rd] <- PC + 4的进行顺序未知,存在二义


BUAA_CO_P7设计文稿
https://fantasylee21.github.io/2024/01/01/BUAA-CO-P7设计文稿/
作者
Fantasylee
发布于
2024年1月1日
更新于
2024年3月6日
许可协议