PIPE是最终要实现的简易处理器,本篇主要介绍PIPE的硬件结构和流水线控制逻辑.
PIPE的硬件结构
————
流水化的最终实现-PIPE
PIPE使用旁路转发技术,能够解决大多数形式的数据冒险,但是不能解决Load/Use冒险和控制冒险,这需要通过流水线控制逻辑来进行控制.
PIPE的各个阶段的详见:wside-hcl.pdf,这篇文档使用HCL详细描述了PIPE的各个阶段的实现.下面简单图示下.
(1).Select PC &Fetch
(2).Decode & Write Back
(3).Execute
(4).Memory
PIPE流水线的控制逻辑
————
PIPE流水线的控制逻辑必须要包含下面四个:
-加载/使用冒险(Load/UseHazard)
-预测错误的分支(Mispredicted Branch )
-处理ret(Processing ret)
-异常(Exception)
前三个是对冒险的控制,将它们放在一起讨论,异常另外讨论.
1.冒险
-触发条件
条件 | 触发条件 |
加载/使用冒险 | E_icode in { IMRMOVL, IPOPL } && E_dstM in { d_srcA, d_srcB } |
预测错误的分支 | E_icode = IJXX & !e_Bch |
处理ret | IRET in { D_icode, E_icode, M_icode } |
-流水线控制逻辑的动作
Condition | F | D | E | M | W |
加载/使用冒险 | stall | stall | bubble | normal | normal |
预测错误的分支 | normal | bubble | bubble | normal | normal |
处理ret | stall | bubble | normal | normal | normal |
附:流水线寄存器的动作(Normal; Stall; Bubble).

- PIPE流水线控制逻辑(原始)

HCL描述
boolF_stall =
# Conditions for a load/use hazard
E_icode in { IMRMOVL, IPOPL } &&
E_dstM in { d_srcA, d_srcB }||
# Stalling at fetch
while ret passes through pipeline
IRET in { D_icode, E_icode, M_icode };
boolD_stall =
# Conditions for a load/use hazard
E_icode in { IMRMOVL, IPOPL } &&
E_dstM in { d_srcA, d_srcB };
boolF_stall =
# Conditions for a load/use hazard
E_icode in { IMRMOVL, IPOPL } &&
E_dstM in { d_srcA, d_srcB }||
# Stalling at fetch
while ret passes through pipeline
IRET in { D_icode, E_icode, M_icode };
boolD_stall =
# Conditions for a load/use hazard
E_icode in { IMRMOVL, IPOPL } &&
E_dstM in { d_srcA, d_srcB };
- PIPE流水线控制逻辑(合并) - 详见CSAPP 301-303
2.异常处理
-异常简介
(1).在一个实际的处理器中,处理器中很多事情会导致异常控制流,程序正常的执行流程被破坏.
(2).在一个完整的设计中,一旦异常发生,处理器会调用操作系统提供的异常处理程序.
(3).可能恢复正常的程序流.
(4).异常可以由程序执行从内部产生,也可以来自外部信号.
-异常的诱发
本文只讨论四种内部产生的异常: (1). Halt指令; (2). 非法指令; (3).取指或者数据读取访问非法地址; (4).流水线控制错误.很明显,这四类都会导致正常的程序流破坏.
-异常的处理
为了方便处理
(1).当处理器遇到异常时,处理器直接停止运行;
(2).设置适当的状态码.
-典型异常示例
(1).发生在Fetch阶段
主要有三种情况:
jmp $-1 #Invalid jump target(-1=0xF…F)
.byte 0xFF # Invalid instruction code
halt # Halt instruction
(2).发生在Memory阶段
访问非法地址.例如:
irmovl $100,%eax
rmmovl %eax,0x10000(%eax) # invalid address(假定如允许超过0x10000以上的地址)
(3).流水线控制错误
很重要的一点就是在exception发生时,引起exception的语句之前的语句已经全部执行完毕,而在exception之后的语句还没有被执行.
示例1:多条导致异常的指令

处理方式:应该rmmovl导致异常.
示例2:分支预测错误

处理方式:应该没有异常发生.
-处理方法

(1).每一个阶段设置一个状态码;
(2). Fetch阶段将状态字段设置为"AOK"(表示合法指令), "ADR"(取指时访问非法地址)和"INS"(非法指令);
(3). Decode和Execute阶段直接传递状态字段;
(4). Memory当出现访问非法指令,设置"ADR",或者直接使用传递指令;
(5).只有在Write Back阶段异常才触发.
---消除副作用:前面的exception引发后就不应该执行后面的指令.

rmmovl应该引发异常, addl指令addl指令也就不应该修改状态.
解决方法:
(1).当在Memory阶段检测到异常,Execute阶段Condition Code就不应该设置;
(2).当异常传递到Write Back阶段(只有在Write Back阶段异常才会触发),应该避免写回存储器和设置ConditionCode.
注*:本篇中的图片均来自本书的官网,我进行了改造(注释和添加),详见http://csapp.cs.cmu.edu/public/figures.html
(Copyright© 2011, Randal E. Bryant and David R. O'Hallaron )
reference:
(版权所有,转载时请注明作者和出处-dennis_fan-http://blog.youkuaiyun.com/dennis_fan