PIPE-已经是一个流水线化的处理器了,但是当相近指令间存在相关时PIPE-会出现问题.后一指令引用前一指令的结果,是非常常见的,所以一个完整的处理器必须要解决这个问题.
本文探讨流水线的两种形式的相关及其冒险.
相关的两种形式
————
相关有两种形式
(1).数据相关.下一条指令要用到上一条指令计算出的结果.
(2).控制相关.一条指令要确定下一条指令的位置.比如:跳转指令,调用或者返回指令.
这些相关导致流水线得到不正确的计算结果,称为冒险(hazard).相应地,分别对应数据冒险和控制冒险.
数据冒险
————
1.数据相关一例
irmovl$10,%edx
irmovl$3,%eax
addl %edx, %eax
2.数据冒险
指令的执行在流水线处理器中被划分为若干阶段,同一个时刻有多条指令处于流水线的不同阶段(所以, SEQ/SEQ+不会存在这个问题).当出现读取数据和写入数据之间的时空相关性时,如果不加以处理,可能会发生数据冒险.
有三种可能的数据冒险:写后读(RAW),读后写(WAR),写后写(WAW).
对于简单的PIPELINE来说,只有RAW可能会导致数据冒险.另外两种情况在superscalar处理器(乱序处理器)中才会发现.
3.数据相关可能导致数据冒险
假定程序寄存器原始值为0.
图1: 3 Nop's 数据相关未造成数据冒险.
图2: 2 Nop's数据相关造成数据冒险
图3: 1 Nop数据相关造成数据冒险
图4: No Nop数据相关造成数据冒险
4.数据冒险的本质和种类
在SEQ/SEQ+中不用考虑冒险的问题,因为每条指令都是等到前面的指令执行完才进入CPU,换一句话说,前一条指令的可见状态都一次性更新之后才会执行下一条指令,也就是说,当前指令执行所需要的数据都有了.PIPE会产生冒险就在于读取下一条指令所需要的数据并没有完全准备好.
前面说过,在PIPE的实现中,只需要考虑写后读(RAW)的问题.根据程序的可见状态可以具体到以下几种:
(1).程序寄存器
-这是最典型导致数据冒险的情形.
-读取程序寄存器在Decode阶段,更新程序寄存器在Write Back阶段发生(2种情况,以后讨论).
(2).控制码
- 读/写控制码都在执行阶段发生.所以不会发生数据冒险.
(3). PC
-读/写 PC会导致控制冒险.
(4).存储器
-读/写存储器都在Memory阶段发生.
-存储器在Memory阶段被当作数据存取,在Fetch阶段被当作代码存取.如果代码会修改自身,那么就有可能出冒险.
-本系统不允许"修改自身的代码",所以,也就不会发生冒险.
控制冒险
————
1.两种控制冒险
(1).预测错误的分支
例如:
0x000: xorl %eax,%eax
0x002: jne t # Not taken
0x007: irmovl $1, %eax# Fall through
0x00d: nop
0x00e: nop
0x00f: nop
0x010: halt
0x011: t:irmovl $3, %edx# Target (Should not execute)
0x017: irmovl $4, %ecx # Should not execute
0x01d: irmovl $5, %edx # Should not execute
图5:分支预测错误,导致控制冒险
(2). ret
前文说过, PIPE不对ret的PC进行预测.所以ret也会导致控制冒险.
例如:
注*:本篇中的图片均来自本书的官网,我进行了改造(注释和添加),详见http://csapp.cs.cmu.edu/public/figures.html
(Copyright© 2011, Randal E. Bryant and David R. O'Hallaron )
reference:
(版权所有,转载时请注明作者和出处-dennis_fan-http://blog.csdn.net/dennis_fan