MIPS处理器

MIPS是RISC处理器的一种,全程为无内部互锁流水级的微处理器(Microprocessor without interlocked pipelined stages),其机制是尽量利用软件办法避免流水线中的数据相关问题。MIPS处理器广泛用于路由器上,常见的路由器使用的处理器有发哥联发科MT7621等。

时钟周期

MIPS采用两相非交叠时钟,流水线级是两层的锁存器。

指令

MIPS有三类指令:

  • 存储器访问指令(Load/Store指令)
    • 取字(lw),存字(sw)
  • 算术/逻辑指令(R-type指令)
    • 加法(add),减法(sub),与(and),或(or),小于则置位(slt)
  • 分支指令(Branch指令)
    • 相等则跳转(beq),无条件跳转(j)
MIPS的三种指令编码格式

记好开头6位对应的数字就知道这是什么指令了!最简单的办法!

  • 0:R-Type
  • 4:Branch
  • 35:lw
  • 43:sw

寄存器中的Rs/Rt/Rd到底是什么意思?

Rs表示源寄存器Source Register,Rt代表作为中间缓存的目标寄存器Target Register,Rd表示目的寄存器Destination Register

构建数据通路

采用递增的方法逐步构建MIPS处理器的数据通路:

  • 读取指令
  • 指令译码和执行
  • 数据存取
  • 分支跳转

读取指令

读取指令的通路由程序计数器指令存储器加法器构成

读取指令数据通路

指令译码和执行

MIPS处理器的32个通用寄存器位于一个寄存器堆(register file) 。ALU可以输出运算结果和零标志

add $t1, $t2, $t3为例:

  • 读取2个寄存器($t2$t3)的数据
  • 执行算术/逻辑操作(add)
  • 计算结果写入寄存器$t1

数据存取

lw|sw $t1, offset($t2)为例:

  • 读取2个寄存器($t1$t2)的数据
  • 以基址$t2加上16位偏移地址offset计算存取地址
    • 在ALU中计算,使用带符号扩展的offset值,需经过符号扩展单元
  • Load:从数据存储器中读取数据并更新到寄存器$t1
  • Store:将寄存器$t1的值写入数据存储器中

分支跳转

beq $t1, $t2, offset为例:

  • 读取2个寄存器($t1$t2)的数据,并比较是否相等
    • 在ALU中执行减操作,并检查输出是否为0
  • 使用加法器计算跳转的目标地址
    • 自增后的PC值加上字对齐(左移2位)且带符号扩展的offset值,需经过符号扩展单元

存取指令和分支跳转指令都需要使用符号扩展(Sign-extend)单元,但是R-Type不需要

主控制单元设计

MIPS三种指令类型的编码格式
  • opcode:指令的基本操作,通常称为操作码
  • rs:第一源操作数寄存器,也作为Load/Store指令的基址寄存器
  • rt:第二源操作数寄存器
  • rd:用于存放操作结果的目的寄存器
  • shamt:位移量(移位指令使用)
  • funct:功能码,指明R-type指令操作的功能
  • offset address: 指明Load/Store指令或Branch指令的偏移地址

控制信号

控制信号类型 控制信号名 无效时含义 有效时含义
寄存器操作类 RegDst 写寄存器目标来自rt段[20:16] 写寄存器目标来自rd段[15:11]
RegWrite 寄存器堆写使能有效
源地址类 ALUSrc ALU第二个操作数来自寄存器堆第二个输出 ALU第二个操作数来自指令中[15:0]符号扩展
PCSrc PC变为PC+4 PC由分支的目标地址取代
存储器操作类 MemRead 数据存储器读使能有效
MemWrite 数据存储器写使能,将输入端数据写入存储器单元
MemtoReg 写入寄存器的数据来自ALU 写入寄存器的数据来自数据存储器
带控制信号的数据通路

主控制单元的输入信号为指令的六位操作码[31:26],输出信号为9位:

  • RegDst、ALUSrc和MemtoReg
  • RegWrite、MemRead和MemWrite
  • 决定是否可以转移的分支控制信号Branch
  • 1个2位的ALU控制信号ALUop

PCSrc是一个间接信号,由Branch信号与ALU单元的Zero标志通过一个与门得到,因此不在里面,但多了一个Branch信号。

对于ALUop,记下对应模式的操作码就行:

操作码 算术/逻辑指令 R-Type 存储器访问指令 lw/sw 分支跳转指令 Branch
ALUop[1:0] 10 00 01

R-Type的数据通路

  • 从指令存储器中取出指令,PC自增4。
  • 根据指令的[25:21]和[20:16]位,从寄存器堆中读出两个源操作数寄存器$t2$t3;同时,主控制单元根据指令的opcode字段(31:26位)计算各控制信号的状态。
  • ALU控制模块根据指令的funct字段(5:0位)确定ALU的功能,对寄存器堆读出的数据进行操作。
  • 将ALU的运算结果写入寄存器堆,根据指令的[15:11]位选择目标寄存器$t1
R-Type的数据通路,注意ALUop

如何分析控制信号的状态?

R-Type是数值计算类的,传入两个地址,目的寄存器字段为rd,因此ALUSrc=0,RegDst=1.

计算的值需要存入寄存器堆,但不需要读取内存,因此RegWrite=1,存储器操作类信号全为0.

PC更新为PC+4,则PCSrc=0,Branch=0(与门运算),ALUop=10

Load指令的数据通路

  • 从指令存储器中取出指令,PC自增4。
  • 根据指令的[25:21]位,从寄存器堆中读出基址寄存器$t2的值;同时,主控制单元根据指令的opcode字段(31:26位)计算各控制信号的状态。
  • ALU将$t2的值与符号扩展后的16位偏移地址(指令的15:0位)相加,作为数据存储器的地址。
  • 从数据存储器中读出的数据写入寄存器堆,根据指令的[20:16]位选择目标寄存器$t1
Load指令的数据通路,注意操作数和ALUSrc

lw指令为数据存取型,因此仅有两个地址传入,且第二个为目标寄存器。因此写寄存器来自rt[20:16],RegDst=0。lw指令要从数据存储器中读出数据并存入寄存器堆中,因此MemRead=1,MemWrite=1,MemtoReg=1,RegWrite=1。

对于sw指令,是要将数据写入数据存储器而非寄存器堆中,因此不关心写寄存器的目标寄存器号,RegDst=X,MemRead=0,MemWrite=1,MemtoReg=X,RegWrite=0。

对于lw和sw,PC都更新为PC+4,则Branch=0,ALUop=00。

Beq指令的数据通路

  • 从指令存储器中取出指令,PC自增4。
  • 根据指令的[25:21]和[20:16]位,从寄存器堆中读出两个源操作数寄存器$t1$t2;同时,主控制单元根据指令的opcode字段[31:26]计算各控制信号的状态。
  • ALU将从寄存器堆读出的两数相减。PC+4的值与符号扩展并左移两位后的16位偏移地址(指令的15:0位)相加,结果就是分支跳转的目标地址。
  • 根据ALU的Zero标志决定下一条指令地址,存入PC中。
Beq指令的数据通路,注意PC

Beq指令为分支跳转型,源操作数寄存器字段都为rs和rt,因此ALUSrc=0。分支跳转型不对数据存储器和寄存器堆进行读写,因此MemRead=0,MemWrite=0,MemtoReg=X,RegWrite=0,RegDst=X。

PC值会更新为跳转地址,因此Branch=1,ALUop=01。

Jump指令的数据通路

Jump指令实现无条件分支,使用字对齐的地址,如j offset。更新32位PC值时,使用下列位拼接的方式:

  • 最高4-bit使用PC+4的高4位

  • 中间26-bit来自Jump指令的[25:0]位偏移地址字段

  • 最低2-bit为00(左移2位,字对齐)

需要从指令的操作码opcode字段(31:26位)中获得额外的解码控制信号Jump。

Jump指令的数据通路,注意ALUop

最后来点练习搞里头:

image-20240614152008739
答案
  1. 高六位是43即sw,因此是Load/Store类。符号扩展单元输出是把符号位扩展16位,因此应该是A。
  2. 对于Load/Store类的指令,ALUop是00
  3. 这是sw,因此是存储数据到数据存储器而非寄存器中,因此RegWrite=0。

下一篇该讲MIPS的流水线与竞争冒险了,最难的一章 哪一章都很难