0%

计算机组成 P3 CPU 设计文档

思考题

1 通过FSM理解CPU

单周期CPU所用到的模块中,发挥状态存储功能的包括IFU(PC寄存器),GRF(通过寄存器组存储状态),DM(使用RAM存储状态);发挥状态转移功能的包括IFU(实现PC地址不断自增),Controller(实现将指令转移为控制信号),ALU(计算得到目标结果)。

2 存储元件合理性

  • IM使用ROM:IM一次只需要读取一条指令,且IM中存储的指令不可被修改,符合ROM大容量存储且只读的特点,同时现实中的计算机需要保证在关闭电源后也能保存指令,因此不能使用断电会丢失数据的RAM。
  • DM使用RAM:DM一次只需要读取一个地址对应的数据且需要支持可读写,符合RAM大容量存储且可反复读写的特点,同时现实中的寄存器单位存储大小的价格远高于RAM,对于没有那么刚需读写速度的DM而言使用RAM成本最为合适。
  • GRF使用寄存器:基本上CPU执行每条指令都涉及到对于GRF的读写,且常常需要一次读取两个不同寄存器的值,Logisim中的RAM和ROM都不支持同时读取两个地址值加写入数据(ROM甚至完全不支持写入),因此需要使用分开来的寄存器组实现同时读取数据和写入数据。且现实中的寄存器读写速度远高于RAM和ROM,符合CPU需要频繁读取和写入GRF的特点。
  • 为何不使用Logisim提供的其他触发器:其他触发器是组成寄存器的基础电路,使用其他触发器再行包装的话与直接使用寄存器元件效果并无不同,却更容易在包装过程中造成问题,为了减少开发难度选择不使用这些元件。

3 其他模块

无其他模块

4 nop指令

对于nop指令,由于Controller采用的电路连接方式,op和func全0时AND_logic输出也是全0,对应OR_logic输出也是全0,所以不会执行指令跳转,不会执行任何GRF或DM写入,因此此时不会执行任何改变当前状态的操作,等价于nop空指令需要达成的效果。

5 MARS导出指令

在课程MIPS要求的设置下,Data从0x00000000开始,Text即代码部分从0x00003000开始,则可以直接通过单独区分J型指令并将其对应指令地址与0x00003000相减即可,增加一个减法器即可解决问题,不需要手工修改最终的机器码。

但在本次P3题目中,由于Compact设置为Data从0x00000000开始,且唯一的跳转指令beq并不涉及指令地址的绝对位置,只涉及相对位置,因此并不需要进行相关修改。

6 Pre的MIPS测试样例强度

各个指令的覆盖率分析

  • ori 立即数范围可以更扩大,测试边界情况(如0xffff)时的情况
  • lui 应增加被改变寄存器本来已存有值的情况,比如lui误实现为“将立即数置于高位但保留原数低16位”的情况就不能检测到
  • add 没有检测到寄存器自增自减的情况
  • sw 没有测试同寄存器同时作为地址存储和被写入寄存器的情况
  • lw 同上,且测试范围不够,可以考虑测试更多边界条件。
  • beq 没有考察立即数是负数的情况(向前跳跃)

测试方案

  1. 采用github上的hex2mips工具将所给的P3_Testcode.txt转回汇编语言后,逐行运行对比观察模块行为,处理不同的位置并定位bug。
  2. 采用自己书写的测试MIPS汇编代码,通过自动化测试工具(使用python在已有MIPS模拟器的基础上进行更改、修复与扩展后输出对应信息到logisim自动测试模块内进行评测并定位问题,进而处理bug,详见自动化测试文件提交。

指令集综述

简要说明

包含指令集如下:

1
add sub ori lw sw beq lui nop

R I J 型指令说明

R型

包括

1
add sub and or nor sll srl jr
位置 (位数) 31~26 (6) 25~21 (5) 20~16 (5) 15~11 (5) 10~6 (5) 5~0 (6)
类型 操作码 寄存器地址 寄存器地址 寄存器地址 五位立即数 操作码
名称 OP rs rt rd shamt (sa) func
解释 恒为0x0 第一参 第二参 目的参 移位量 指示操作类型

I型

包括

1
addi andi ori xori lw sw beq bne lui
位置 (位数) 31~26 (6) 25~21 (5) 20~16(5) 15~0 (16)
类型 操作码 寄存器地址 寄存器地址 立即数
名称 OP rs rt imm
解释 指示操作类型 第一参 目的参 立即数

J型

包括

1
j jal
位置 (位数) 31~26 (6) 25~0 (26)
类型 操作码 指令地址
名称 OP address
解释 指示操作类型 目标跳转位置

(无)符号加 add

按照要求,依照add的机器码处理,但加法依照无符号数加法完成。取两个寄存器中的数,无符号相加(不考虑溢出)后存入目标寄存器。为R型指令。

位置 (位数) 31~26 (6) 25~21 (5) 20~16 (5) 15~11 (5) 10~6 (5) 5~0 (6)
名称 OP rs rt rd 0 func
解释 000000 第一加数地址 第二加数地址 结果存储地址 00000 100000

(无)符号减 sub

按照要求,依照sub的机器码处理,但减法依照无符号数加法完成。无符号相减(不考虑溢出)后存入目标寄存器。为R型指令。

位置 (位数) 31~26 (6) 25~21 (5) 20~16 (5) 15~11 (5) 10~6 (5) 5~0 (6)
名称 OP rs rt rd 0 func
解释 000000 被减数地址 减数地址 结果存储地址 00000 100010

或立即数 ori

按照要求,即为将某寄存器中数或一个16位立即数,将得到的数存到目标寄存器中。为I型指令。

位置 (位数) 31~26 (6) 25~21 (5) 20~16(5) 15~0 (16)
名称 OP rs rt imm
解释 001101 被或数地址 结果存储地址 立即数

加载字 lw

取内存中的一字长的内容存入目标寄存器。为I型指令。

1
2
addr <- GPR[base] + sign_ext(offset)
GPR[rt] <- memory[addr]
位置 (位数) 31~26 (6) 25~21 (5) 20~16(5) 15~0 (16)
名称 OP base rt offset
解释 100011 内存地址所在寄存器 结果存储地址 内存地址偏移量(立即数)

存储字 sw

将目标寄存器中的内容存入内存中一字长的位置。为I型指令。

1
2
addr <- GPR[base] + sign_ext(offset)
memory[addr] <- GPR[rt]
位置 (位数) 31~26 (6) 25~21 (5) 20~16(5) 15~0 (16)
名称 OP base rt offset
解释 101011 内存地址所在寄存器 目标寄存器地址 内存地址偏移量(立即数)

相等时转移 beq

当两个目标寄存器中存储的值相等时转移到目标指令处。为I型指令。

1
2
3
4
if (GPR[rs] == GPR[rt])
PC <- PC + 4 + sign_extend({offset,2{0}})
else
PC <- PC + 4
位置 (位数) 31~26 (6) 25~21 (5) 20~16(5) 15~0 (16)
名称 OP rs rt offset
解释 000100 第一目标寄存器 第二目标寄存器 转移目标指令地址

立即数加载至高位 lui

将立即数赋值到目标寄存器的高16位。为I型指令。

位置 (位数) 31~26 (6) 25~21 (5) 20~16(5) 15~0 (16)
名称 OP 0 rt imm
解释 001111 00000 目标寄存器 立即数

空指令 nop

机器码为0x00000000,不进行任何有效行为。

IFU 取指令单元

功能要求

  • 内部包括 PC(程序计数器)、IM(指令存储器)及相关逻辑。
  • PC 用寄存器实现,应具有异步复位功能,复位值为起始地址。
  • 起始地址:0x00000000。
  • IM 用 ROM 实现,容量为 32bit × 32字。
  • IM 实际地址宽度仅为 5 位,需要使用恰当的方法将 PC 中储存的地址同 IM 联系起来。

输入端口

  • clk 时钟信号
  • Reset 异步复位信号
  • ALUZero 代表Branch指令是否满足要求
  • PCSrc [1:0] 指示当前的指令类型,00代表指令不影响跳转,01代表Branch指令,10代表J型指令(跳转到标记),11代表jr类指令(跳转到寄存器地址)
  • PCBranch [7:0] Branch后的新指令地址
  • PCJAL [31:0] 连接RD1,对应jal取出的寄存器内存储的值。

输出端口

  • Inst [31:0] 取得的指令
  • PCNxt [7:0] 下一条要执行的指令地址

行为逻辑

  • 任何时刻,输出当前PC寄存器对应ROM地址中的指令
  • 每个clk上沿将当前PC寄存器存储的地址+4并输出到PCNxt,PCSrc为00时将该值存储到PC寄存器中
  • 每个clk上沿PCSrc为01时,判断ALUZero是否为真,为真则将PCBranch存入PC寄存器中,为假将PC+4存入PC寄存器中。
  • 每个clk上沿PCSrc为10或11时,分别对应J型和jr类指令,按照相应方式处理。

ALU 算术逻辑单元

功能要求

  • 提供 32 位加、减、或运算及大小比较功能。
  • 加减法按无符号处理(不考虑溢出)。

输入端口

  • SrcA [31:0] 第一个参数输入
  • SrcB [31:0] 第二个参数输入
  • ALUCtrl [2:0] ALU操作类型控制码

输出端口

  • Zero 输出结果是否为0
  • ALUResult [31:0] 计算结果

控制信号说明

  • 或运算 000
  • 与运算 001
  • 加法运算(无符号无溢出) 010
  • 减法运算(无符号无溢出) 011
  • 立即数加载至高位 100
  • 或立即数(将SrcB取低16位进行0扩展后和SrcA取或) 101

GRF 通用寄存器组

功能要求

  • 用具有写使能的寄存器实现,寄存器总数为 32 个,应具有异步复位功能。
  • 0 号寄存器的值始终保持为 0。其他寄存器初始值(复位后)均为 0,无需专门设置。

输入端口

  • clk 时钟信号
  • Reset 异步复位信号
  • WE 写使能信号
  • A1 [4:0] 第一读取地址
  • A2 [4:0] 第二读取地址
  • A3 [4:0] 写入地址
  • WD [31:0] 写入数据输入

输出端口

  • RD1 [31:0] 第一读取输出 输出A1地址的寄存器中的数据
  • RD2 [31:0] 第二读取输出 输出A2地址的寄存器中的数据

功能说明

  • 任何时刻,RD1和RD2都输出A1和A2对应地址的寄存器中的数据
  • Reset异步复位,将所有寄存器复位为0
  • 0号寄存器永远保持为0
  • 当WE为真时,将WD的数据在clk上沿写入A3对应地址的寄存器

DM 数据存储器(内存)

功能要求

  • 使用 RAM 实现,容量为 32bit × 32字,应具有异步复位功能,复位值为 0x00000000。
  • 起始地址:0x00000000
  • RAM 应使用双端口模式,即设置 RAM 的 Data Interface 属性为 Separate load and store ports

输入端口

  • clk 时钟信号
  • Reset 异步复位信号
  • WE 写使能信号
  • Addr [4:0] 写入/读取地址
  • WD [31:0] 写入数据

输出端口

  • RD [31:0] 读取结果数据

功能说明

  • 任何时刻,在RD输出AddrR对应内存地址的内存数据
  • 当WE为真时,将WD的数据在clk上沿写入AddrW对应内存地址

Controller 控制器

功能要求

将输入的opcode和funct转化为CPU各部分对应信号输出

实现方式

将Controller分为将opcode和funct转化为各个指令对应的独热输出的AND_logic模块和将各个指令对应到不同输出信号的OR_logic模块,两模块不额外进行封装,直接在顶层模块中进行连接,这样可以通过两模块中间线的高亮直观判断当前在执行何种指令。

输入端口

  • OP [5:0] 标识命令种类的指令,按MIPS汇编标准执行
  • func [5:0] 标识R型指令具体种类的指令,按MIPS汇编标准执行

输出端口

  • Mem2Reg [1:0] 决定GRF写入数据来源,00代表ALU输出,01代表DM输出
  • MemWrite 决定DM是否允许写入
  • Branch [1:0] 指示当前的指令类型,00代表指令不影响跳转,01代表Branch指令,10代表J型指令(跳转到标记),11代表jr类指令(跳转到寄存器地址)
  • ALUCtrl [2:0] 决定当前ALU执行何种运算,具体见ALU说明
  • ALUSrc 决定ALU的第二参来自GRF的RD2(对应值0)还是立即数(对应值1)
  • RegDest [1:0] 决定寄存器写入地址来源是Inst[15:11](对应值01)还是Inst[20:16](对应值00)
  • RegWrite 决定GRF是否允许写入
  • ExtSign 决定扩展方式,0代表0扩展,1代表符号扩展。

各指令对应Controller输出

func 10 0000 10 0010 -
op 00 0000 00 0000 00 1101 10 0011 10 1011 00 0100 00 1111
add sub ori lw sw beq lui
Mem2Reg 00 00 00 01 - - 0
MemWrite 0 0 0 0 1 0 0
Branch 00 00 00 00 00 01 00
ALUCtrl 2 3 5 2 2 3 4
(CalcMode) add sub ori add add sub lui
ALUSrc 0 0 1 1 1 0 1
RegDest 01 01 00 00 - - 00
RegWrite 1 1 1 1 0 0 1
ExtSign 0 0 0 1 1 1 0