流水线实现
MIPS(子集)数据通路(非流水线)
在该数据通路,一条指令的操作(至多)包含5个时钟周期:取值、指令译码/读寄存器、执行/有效地计算、存储器访问/分支完成、写回。
PC(程序计数器):存放当前指令的地址
NPC(下一条程序计数器):存放下一条指令的地址
IR(指令寄存器):存放当前正在处理的指令
A(第一操作数寄存器):存放从通用寄存器组读出来的操作数
B(第二操作数寄存器):存放从通用寄存器组读出来的另一个操作数
Imm :存放符号扩展后的立即数操作数
Cond :用来存放条件判断的结果,其值为 “ 真 ” 表示分支成功
ALUo(Output):存放ALU的运算结构
LMD:存放load指令从存储器读出的数据
取指令周期(IF)
操作
IR <— Mem[PC]
NPC <— PC+4
指令译码 / 读寄存器周期(ID)
主要操作
A <— Regs[rs]
B <— Regs[rt]
指令译码
Imm <— ((IR16)16##IR16..31)
(注意:指令的译码操作和读寄存器操作是并行进行的:在MIPS指令格式中,操作码字以及rs、rt字段都是固定的位置。这种技术称为**固定字段译码**技术)
执行 / 有效地址计算周期(EX)
不同指令进行的操作不同
load指令和store指令
ALUo <— A + Imm
寄存器 — 寄存器ALU指令
ALUo <— A funct B
寄存器 — 立即值ALU指令
ALUo <— op Imm
分支指令
ALUo <— NPC+(Imm<<2)
cond <—(A == 0)
(注意:将有效地址计算周期和执行周期合并为一个时钟周期,这是因为MIPS指令集采用load/store结构,没有任何指令需要同时进行数据有效地址的计算、专一目标地址的计算和对数据进行运算。)
存储器访问 / 分支完成周期(MEM)
不同指令进行的操作不同
所有指令都要在该周期对PC进行更新
非分支指令:PC <— NPC
分支指令:
if (cond)
PC <— ALUo else PC <— NPC
(该周期内需要处理的MIPS指令仅包含load、store和分支三种)
写回周期(WB)
不同指令进行的操作不同
寄存器 — 寄存器ALU指令
Regs[rd] <— ALUo
寄存器 — 立即数ALU指令
Regs[rt] <— ALUo
load指令
Regs[rd] <— LMD
MIPS的流水化
基本原则:每一个时钟周期完成的工作看做是流水线的一段,每个时钟周期启动一条新的指令。
流水寄存器的位置与作用
位置:段与段之间设置流水线寄存器
作用:① 将各段的工作隔开,使得它们不会互相干扰 ② 保存相应的处理结果 ③ 向后传递后面将要用到的数据或者控制信息
流水寄存器命名规则
三个部分:流水寄存器.子寄存器名[字段名]
- 流水寄存器名:用其相邻的两个段的名称拼合而成。例如:ID段与EX段之间的流水寄存器用ID / EX表示。(每个流水寄存器是由若干个子寄存器构成的)
- 子寄存器名:基本寄存器(如:IR)
- 字段名:基本寄存器的某字段
实例:ID / EX.IR[op]:流水寄存器ID / EX中的子寄存器IR的op字段(即操作码字段)
其他数据通路改动
1. 增加了向后传递IR和从MEM / WB.IR送回通用寄存器组的连接。
2. 将对PC的修改移到了IF段,以便PC能及时地加4,为取下一条指令做好准备。
数据冲突
1. 所有的数据冲突均可在ID段检测到
* 如何存在数据冲突,就在相应的指令流出ID段之前将之暂停。
* 完成该工作的硬件成为流水线的互锁机制。
2. 在ID段确定需要什么样的定向,并设置相应的控制
* 降低流水线的硬件复杂度。(不必挂起已经改变了机器状态的指令)
3. 在使用操作数的那个时钟中期的开始检测冲突和确定必需的定向
4. 检测冲突是通过比较寄存器地址是否相等来实现的
控制冲突
1. 分支指令的条件测试和分支目标地址计算是在EX段完成,对PC的修改是在MEM段完成。
2. 它所带来的分支延迟是3个时钟周期。
3. 减少分支延迟
网友评论