R型指令和lw指令:从硬件角度看她们的秘密情书!💌
1. lw
指令的执行过程
我们以你图上标注的指令 lw $2, 100($3)
为例。
指令含义: 将基地址寄存器 $3
的内容加上偏移量 100
,得到一个内存地址,然后从该地址读取数据,最后将这个数据写入目标寄存器 $2
。
指令编码格式 (I-Type):
lw
-
op: 6位,
lw
指令的操作码。 -
rs: 5位,基地址寄存器,这里是
$3
,所以是00011
。 -
rt: 5位,目标寄存器,这里是
$2
,所以是00010
。 -
immediate: 16位,偏移量,这里是
100
。
数据通路执行步骤:
-
取指令 (Instruction Fetch, IF)
-
PC (程序计数器) 存放当前指令的地址,该地址送到 指令存储器 的地址端口。
-
指令存储器 根据地址读出
lw $2, 100($3)
的32位机器码,并将其锁存到 指令寄存器 中。 -
与此同时,PC的值被送到上方的 Adder (加法器),与常数
4
相加,计算出下一条指令的地址,准备在时钟CLK的下一个上升沿写入PC。
-
-
指令译码 & 读寄存器 (Instruction Decode & Register Read, ID)
-
指令寄存器中的32位机器码被“分发”到各个部件:
-
op
字段 (指令[31-26]) 送到 主控制单元。主控制单元识别出这是lw
指令,并生成一组特定的控制信号。 -
rs
字段 (指令[25-21],即$3
) 送到 寄存器堆 (Register File) 的 读地址1 (RA) 端口。 -
rt
字段 (指令[20-16],即$2
) 送到 寄存器堆 的 读地址2 (RB) 端口。(注意:虽然$2
的值也被读出来了,但在lw
指令中,ALU并不会使用这个值) -
immediate
字段 (指令[15-0],即100
) 送到 符号扩展单元。
-
-
寄存器堆根据RA端口的地址
$3
,将寄存器$3
中存放的数据(基地址)从 读数据1 端口输出。
-
-
执行 (Execution, EX)
-
主控制单元 为
lw
指令生成的控制信号开始发挥作用:-
ALUSrc = 1
:这是一个关键信号。它控制右边的MUX,使其选择 符号扩展单元 的输出(即立即数100
的32位符号扩展结果)作为ALU的第二个操作数。 -
ALUOp
:主控制单元生成一个特定的值(例如00
),与指令的funct
字段(lw
指令不关心此字段)一起送给 ALU控制单元,使其产生“加法”信号。
-
-
ALU 接收两个输入:
-
输入1:来自寄存器堆的 读数据1 端口(即
$3
的内容)。 -
输入2:来自符号扩展单元的输出(即
100
)。
-
-
ALU执行加法操作,计算结果为
($3的内容) + 100
,这个结果就是我们要访问的 数据内存地址。
-
-
访存 (Memory Access, MEM)
-
ALU计算出的内存地址被送到 数据存储器 的 地址 端口。
-
主控制单元此时会发出读内存的信号(图中未画出,但通常是
MemRead = 1
),且WE
(写使能)为0
,表示不写入。 -
数据存储器 根据输入的地址,从相应的存储单元中读出数据,并从 读数据 端口输出。
-
-
写回 (Write Back, WB)
-
从数据存储器读出的数据,被送到最右边的MUX。
-
主控制单元为
lw
指令生成的控制信号:-
MemtoReg = 1
:控制最右边的MUX,选择来自 数据存储器 的数据(MUX的输入1
)作为最终要写回寄存器的数据。 -
RegWr = 1
:使能寄存器堆的写入操作。 -
RegDst = 0
:控制 写地址 (RW) 来源的MUX,选择指令的rt
字段(指令[20-16],即$2
)作为目标寄存器地址。这是I型指令和R型指令的一个核心区别。
-
-
最终,来自数据存储器的数据通过MUX,被送到寄存器堆的 写数据 端口,目标地址由
rt
字段指定为$2
。在时钟CLK的下一个上升沿,数据被写入寄存器$2
,指令执行完毕。
-
2. R型指令的执行过程
我们以一个典型的R型指令 add $1, $2, $3
为例。
指令含义: 将寄存器 $2
和寄存器 $3
的内容相加,结果存入目标寄存器 $1
。
指令编码格式 (R-Type):
add $rd, $rs, $rt
-
op: 6位,R型指令的操作码,通常为
000000
。 -
rs: 5位,源寄存器1,这里是
$2
。 -
rt: 5位,源寄存器2,这里是
$3
。 -
rd: 5位,目标寄存器,这里是
$1
。 -
shamt: 5位,位移量(
add
指令中为0)。 -
funct: 6位,功能码,用于区分不同的R型指令,这里是
add
的功能码。
数据通路执行步骤:
-
取指令 (IF)
- 此步骤与
lw
指令完全相同。PC找到指令,指令存储器读出机器码。
- 此步骤与
-
指令译码 & 读寄存器 (ID)
-
指令寄存器中的32位机器码被分发:
-
op
字段 (000000
) 送到 主控制单元。它识别出这是R型指令。 -
funct
字段 (指令[5-0]) 送到 ALU控制单元。 -
rs
字段 (指令[25-21],即$2
) 送到寄存器堆的 RA 端口。 -
rt
字段 (指令[20-16],即$3
) 送到寄存器堆的 RB 端口。 -
rd
字段 (指令[15-11],即$1
) 送到决定写地址的MUX。
-
-
寄存器堆根据
RA
和RB
地址,同时读出$2
和$3
的内容,分别从 读数据1 和 读数据2 端口输出。
-
-
执行 (EX)
-
主控制单元 为R型指令生成的控制信号:
ALUSrc = 0
:控制右边的MUX,使其选择来自寄存器堆 读数据2 端口的数据(即$3
的内容)作为ALU的第二个操作数。
-
ALU控制单元 根据从主控制单元传来的
ALUOp
(例如10
,代表是R型指令)和指令中的funct
码,生成具体的“加法”控制信号给ALU。 -
ALU 接收两个输入:
-
输入1:
$2
的内容。 -
输入2:
$3
的内容。
-
-
ALU执行加法操作,计算结果为
($2的内容) + ($3的内容)
。
-
-
访存 (MEM)
- 对于R型指令,此阶段 不进行任何有效操作。ALU的计算结果虽然也连接到了数据存储器的地址端口,但主控制单元会设置
MemRead = 0
和WE = 0
,所以数据存储器既不读也不写,处于空闲状态。
- 对于R型指令,此阶段 不进行任何有效操作。ALU的计算结果虽然也连接到了数据存储器的地址端口,但主控制单元会设置
-
写回 (WB)
-
ALU的计算结果,同时也被送到了最右边的MUX。
-
主控制单元为R型指令生成的控制信号:
-
MemtoReg = 0
:控制最右边的MUX,选择来自 ALU 的计算结果(MUX的输入0
)作为要写回寄存器的数据。 -
RegWr = 1
:使能寄存器堆的写入操作。 -
RegDst = 1
:控制 写地址 (RW) 来源的MUX,选择指令的rd
字段(指令[15-11],即$1
)作为目标寄存器地址。
-
-
最终,ALU的计算结果通过MUX,被送到寄存器堆的 写数据 端口,目标地址由
rd
字段指定为$1
。在时钟CLK下一个上升沿,结果被写入寄存器$1
,指令执行完毕。
-
对比总结与常考点分析
特征/部件 | lw $2, 100($3) (I-Type) |
add $1, $2, $3 (R-Type) |
考点分析 |
---|---|---|---|
指令字段使用 | 使用 op , rs , rt , immediate |
使用 op , rs , rt , rd , funct |
lw 的rt 是目标寄存器,R型的rd 是目标寄存器。这是一个经典的易错点。 |
ALU第二个操作数来源 | 符号扩展后的 immediate |
寄存器堆读出的数据2 ($3 的内容) |
由 ALUSrc 控制信号决定,ALUSrc=1 选立即数,ALUSrc=0 选寄存器。这是核心考点。 |
数据存储器 | 读取数据 | 不使用 (空闲) | 单周期CPU的效率问题就体现在这里,执行R型指令时,这个部件被浪费了。 |
写回寄存器的数据来源 | 来自数据存储器 | 来自ALU的计算结果 | 由 MemtoReg 控制信号决定,MemtoReg=1 选存储器,MemtoReg=0 选ALU结果。这也是核心考点。 |
目标寄存器地址来源 | 指令的rt 字段 (bits [20-16]) |
指令的rd 字段 (bits [15-11]) |
由 RegDst 控制信号决定,RegDst=0 选rt ,RegDst=1 选rd 。区分I型和R型指令的关键。 |