计算机原理与嵌入式系统笔记:第九篇
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)
记好开头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不需要。
主控制单元设计
- 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是数值计算类的,传入两个地址,目的寄存器字段为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
。
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指令为分支跳转型,源操作数寄存器字段都为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。
最后来点练习搞里头:
答案
- 高六位是43即sw,因此是Load/Store类。符号扩展单元输出是把符号位扩展16位,因此应该是A。
- 对于Load/Store类的指令,ALUop是00
- 这是sw,因此是存储数据到数据存储器而非寄存器中,因此RegWrite=0。
下一篇该讲MIPS的流水线与竞争冒险了,最难的一章 哪一章都很难