首页 > 代码库 > 流水线设计
流水线设计
20世纪80年代,流水线技术成为RISC处理器设计方法中最基本的技术之一,RISC的设计多以高流水为目标设计。
而后流水线技术也被应用到CISC处理器
在流水线的发展史上主要有两种流水线,算术流水线和指令流水线。
首先通过算术流水线的例子,介绍流水线理想假设。
流水线意味着将系统分割为许多段,段与段之间增加合适的缓冲,这样每隔D/K个时间单位就可以启动新的任务,而不是每隔D个时间单位。
流水线并不能被无限制的增加下去,因为时钟的限制(setup time/clock uncertainty),流水线的划分有一个物理局限。
流水线深度的权衡:
一个k级流水线的价格:C = G + k *L,原来非流水的价格+流水线段数×增加一级流水价格;
流水系统的性能:1/(T/k + S),T非流水系统的延时,S引入流水新加的延时,k级流水。
通过微分求解:可以得到一个流水线的最佳深度
K<Kopt:不够完全流水化,可以进一步增加流水,性能的提升比价格的提高更明显;
K>Kopt:过度流水化,增加流水,价格的提升比性能的提升更明显;
流水线操作中的硬件要求:
1):每一段进行控制和完成数据操作的逻辑;
2):支持多个流水段同时访问的寄存器文件接口;
3):支持多个流水段访问的存储器接口;
随着流水线深度的增加,流水线的硬件资源会显著的增加,最突出的是寄存器文件和存储器端口数目的增加。
目前流水线处理器的设计趋势是向着更高的流水程度和更深的流水深度发展,这样流水线级颗粒更小,时钟频率更高,目前超过10级的流水线很常见,
还有一个趋势是多条级数不等的流水线。
流水化的理想假设:只有在理想情况下,流水线的吞吐量才能得到K倍;
1):一致的运算分量,要完成的整个运算量均匀的分成延迟一致的若干分量。
由于流水线的时钟周期取决于延迟最长的那一段,所以各个流水段最好做平,来减少”内部碎片”,
并且,流水段之间的缓冲不会带来额外的延迟(setup time),时钟也不会引入额外的延迟(clock uncertainty)
2):重复的运算,输入数据有大量相同的,重复的运算。
不同的功能流水段中,可能不需要一些特定的流水段,这些空闲的流水段”外部碎片”
各个流水段只有完全流水阶段,不存在流水线填充阶段。
3):独立的运算,所有相同的运算之间没有相关性。
后面的运算可能会用到之前运算的结果,当这两条命令都在流水线中时,会产生等待状态,”流水线停顿(pipeline stall)”
指令流水化设计:
一条指令的处理过程,流水化的运算,被划分为多个一致的子运算,获得尽可能均衡的流水线。
处理一条指令的时间延迟:
指令周期-------体系结构原语,由指令集体系结构定义。
机器周期-------流水线的时钟周期,机器原语,由处理器的微体系结构定义。
指令流水线设计的主要任务,将逻辑指令周期映射到物理机器周期,将指令周期合理的分割为一个子运算的序列,需要考虑:
1):一致的运算分量,量化流水段,尽可能的减少内部碎片,流水线越均衡,内部碎片越少。
2):重复的运算,指令流水线天生就是多功能流水线,对应的子运算序列不同,硬件资源不同,
连接或者整合不同指令类型对不同资源的需求。尽量减少无效或者空闲的机器周期。
3):独立的运算,尽量减少流水线停顿。
指令集体系结构对流水线的影响:
1):一致的运算分量,在流水线设计中,关键分量是对存储器的访问,采用cache访问。典型6级流水设计
2):重复的计算,RISC体系结构的主要目的之一,降低指令类型的复杂性和多样性,可以降低整理不同指令类型的难度。主要分为三种指令类型
3):寄存器相关比较容易检测,可以由编译器静态完成,或者运行时硬件动态完成,存储器相关比较难判断。
保持流水段均衡:
一个典型的指令周期,可以划分为:
1):取指(IF,Instruction Fetch)
2):译码(ID,Instruction Decode)
3):取操作数(OF,Operand Fetch)
4):执行(EX,Instruction execution)
5):存储(OS,Operand Store)
分割指令周期的很自然的方法是按5个基本运算分量来划分,得到一个5级指令流水线,称为基本指令流水线GNR(generic)流水线。
其中逻辑指令周期映射到5个物理机器周期中,这个值反映了流水化的程度和颗粒。
在量化流水线中,可以根据实际分量的大小,进行合并和再分解。从而增大流水度和减小流水度。或者可以将合并与分解结合使用。
不管在哪种情况下,目的都是为了减小内部碎片。
统一指令类型:
指令流水线需要满足不同的需求,必须提供所有指令类型所需要的所有运算分量。
对于单独一种指令类型,不需要的流水段将成为某种形式的失效和开销,称为外部碎片。
要完成一次运算,计算机必须完成三个基本任务:
1):算术操作,ALU部分,执行算术和逻辑运算
2):数据移动,将操作数和结果在存储地址之间进行移动
3):指令定序,由指令自身来确定
CISC指令集多采用,一条指令都能完成一条以上的基本任务。
在现代RISC体系结构中,指令集采用一种专门的指令类型来完成三个基本任务中的一个,定长正交指令,load/store体系结构和简单寻址模式。
其中指令可以分为三种类型:(包括无条件跳转指令和条件跳转指令,定点指令和浮点指令)
ALU:算术和逻辑运算
Load/Store:数据在寄存器和存储器间移动,选择简单寻址模式,带偏移的寄存器间接寻址模式。
分支指令:控制指令执行的顺序,寻址模式支持PC相对寻址。
Load/Store之间也有微小区别:load指令,OF可以新分为读寄存器得基址,有效地址生成,存储器访问
Store指令,OS可以分为有效地址生成,寄存器操作数写入存储器
资源需求的整合:
尽量提高流水线中所有资源的利用率,合理分配各个流水段的资源,减少各个指令类型带来的空闲周期。
针对四种指令(ALU, Load/Store, jump)进行功能划分:
1):所有四种指令有相同的IF和ID分量,完成取指和译码操作;
2):所有四种指令的OF分量都要读寄存器文件,ALU访问寄存器操作数,load得到基地址,store得到操作数和基地址,jump访问PC寄存器
RD段从寄存器文件中读取最多两个寄存器操作数,所以寄存器文件在每个时钟都必须支持两个独立的并行读操作。
3):ALU完成算术逻辑运算,load/store/jump完成有效地址生成。
4):Load/store访问存储器,流水线第五段,MEM
5):ALU和load都要向寄存器文件写入结果,为了统一,在ALU执行完后,不直接向寄存器写入,和load一样在流水线第六段写入。
ALU在MEM段后,产生一个空闲周期,外部碎片
6):对于条件分支指令,必须在更新程序计数器之前,确定分支条件,所以最早能用分支目标地址更新程序计数器的段是MEM
以上是一个TYP的指令流水线,ALU有一个空闲周期(MEM),store和jump没有WB段,只有load指令用了其中6个流水段,这是一条效率比较高的流水线了。
在这个指令流水线的实现过程中,每个时钟周期最多有6条指令会驻留在流水线中,所以一个机器时钟,I-Cache需要支持一次读操作,D-cache需要支持一次读操作
和一次写操作。
减少流水线停顿。
两条指令之间的关系可以分为:数据相关和控制相关,数据相关分为;
数据相关即可以发生在存储器中也可以发生在寄存器中。
1):先写后读,(RAW,read after write),后一指令的操作数是该指令的结果。该指令的结果被后指令使用。真相关。
2):先读后写,(WAR,write after read),反相关,防止后一指令的结果对上一指令的操作数产生影响。
3):写后写,(WAW,write after write),两条指令的顺序不能改变。输出相关。
4):读后读,(RAR,read after read),无影响。
在以上的TYP的6级流水线中,可以发生的数据相关,是RAW相关。
要化解RAW相关,就要阻止后续的指令进入读相关寄存器的流水段中。知道前面的指令通过了相关寄存器的流水段。
除了停止执行发生相关的指令,还有一些更加有效的方法:
1):采用定向路径。前面的指令i与后面的指令j存在相关,对于RAW相关,指令j需要指令i的结果,则在指令i结束ALU之后,
ALU的输出可以通过一段物理的定向路径(Forwarding path)到达ALU的输入端,这样j指令执行时,可以直接使用,而不用等到i指令到达WB。
如果指令i是load指令,指令j需要的数据需要在MEM段,也可以再增加一条定向路径。
ALU指令引起的RAW相关,称为ALU开销。Load指令的开销称为load开销。从MEM段和WB段到ALU的输入的路径称为定向路径。
2):流水线互锁实现。检测出所有的流水线相关,并保证所有的相关得到满足。包括停止流水线的某一段,以及,数据在定向路径中的传输控制。
RAW相关的检测是通过比较器,连续比较连续两条指令的寄存器标识来实现的。如果检测到数据的相关性,则使能相关的定向路径。
如果没有相关的定向路径,则停止流水线的某段。
流水线的互锁硬件还必须处理控制相关引起的流水线相关。
流水线处理器性能的主要障碍是指令相关引起的流水线停顿,其中控制相关引起的分支开销是最重要的部分。
动态分支预测能减少这一部分的开销,预测成功时,流水线没有停顿。在检测到预测失败时,必须清空流水线。
减少从取指段到完成分支指令段的距离也可以减少分支指令引起的开销。
在流水线处理器设计中,不仅仅数据通道被流水化了,连控制通道也被流水化了,传统的数据通道和控制通道被合并到同一条流水线。
流水线设计