文章目录
周期
指令周期
状态图
- 操作数地址计算:通过不同的寻址方式,计算出操作数的有效地址,从而取出操作数
- 取操作数、存操作数都需要进行操作数地址计算
- 返回字符串或向量数据:连续对相关的操作数进行处理,只需要进行一次操作译码
带中断的指令周期
状态图
间址周期
状态图
先取有效地址,再通过有效地址取得操作数,是两个重复的过程。
CPU的任务
CPU需求:寄存器
数据流
取指周期
PC寄存器中存储指令地址,通过MAR将下一条指令的地址传到地址总线上
此时取到的是一条指令,所以需要把指令从MBR中传入到IR中
CPU和存储器之间常采用同步,效率更高
控制器:
- 开始进入取指周期,向PC下达指令
- 取指周期结束,指令取到之后控制器就会让PC+1
间址周期
MAR一直连接在地址总线上,所以MAR中有什么地址总线上就会有什么 MDR同理
因此,控制器只需要通过控制总线告诉存储器取数据即可
易错
**间址周期:取出来的是有效地址而不是操作数。 **
通过有效地址去取操作数是在执行周期中的
在普通的指令周期中,取值周期只进行指令的读取。而取操作数、处理操作数都是在执行周期中进行的
中断周期
写操作而非读操作
对PC中的内容的保存。因为处理完中断后,需要知道返回的地址,所以数据总线方向向右
控制器通知PC要进入中断周期了,需要保存地址
MAR:用来保存PC寄存器的指令的存储地址。
- 控制器通知PC,将下一条指令保存到存储器中
- 控制器通知MAR,因为保存到存储器中了,所以会有一条存储地址/取值地址,需要保存到地址总线上。
- 控制器通知存储器获得数据
存储器:
- 获得控制信号,知道要写入数据
- 从地址线上获得地址,不是写入的时候找到一个空区放入,再返回相应的地址
- 从数据线上获得数据,将数据写到获得的地址上
指令流水线
两阶段方法
- 取指令、执行指令都需要访问内存,造成访问冲突
- 分支语句中,下一条指令的地址不确定。很有可能取过来的地址不对,导致作废,重新取一条新地址
- 执行指令就也会等待,等待取指周期完成获得一条新地址
六阶段方法
解决了处理时间的不平衡
6阶段还是时间不一样的
限制1:条件转移指令
两阶段时只会有第一阶段的浪费;但是六阶段时,会导致更多阶段的浪费
限制2:中断
另一种描述
超流水线
- 将六级流水线分为更多的阶段,增加流水线的深度
- 提升时钟频率,从而提高指令吞吐率
- 上升沿处理能有效避免噪声
- 锁存延迟:将处理结果存储在寄存器中所消耗的时间
- 单条指令的延迟随着流水线深度的增加而增加 – 延迟占比提高了
流水线性能
d
:
d:
d:两个执行阶段中间的延迟
第一条指令:完整执行,需要
k
t
kt
kt的时间
剩余
n
−
1
n-1
n−1条指令,只需要多一个
t
t
t的时间,总共就是
(
n
−
1
)
t
(n-1)t
(n−1)t
所以
T
=
k
t
+
(
n
−
1
)
t
T = kt + (n-1)t
T=kt+(n−1)t
n
∗
k
∗
t
n*k*t
n∗k∗t:n条指令,k个阶段,每个阶段是
t
t
t
加速比是一个大于1的数字
冒险
结构冒险
已进入流水线的不同指令在同一时刻访问相同的硬件资源
解决方案:
- 插入空泡,但是会导致和原来的下一条又有影响
- 使用不同用途的多个存储器
Dm:处理数据
Im:处理指令
但寄存器较贵,且有可能访问相同的寄存器。类比数据Cache和代码Cache是分离的 - 同一个寄存器提供分时处理:寄存器时钟上升沿写,时钟下降沿读 – 访问寄存器的延迟比其他步骤短,本来就很短,只是被迫和其他步骤一样长,所以可以分割为读和写的两个步骤
数据冒险
一个指令需要使用之前的运算结果,但是结果还没有写回
和结构冒险不同,可以执行下去,只是执行结果会发送错误r1
在add
指令中是一个输出的结果,但是又是其他指令中输入的数据,在sub
中的r1
没有更新
解决方案1:插入nop指令
第三条nop
可以略去,一个上升沿写入,一个下降沿读。硬件上不需要做任何修改
缺点:
- 对于程序员来说十分麻烦
- 软件的可迁移性非常糟糕
解决方案2:插入bubble
缺点:
- 效率低下,流水线失去意义。使用之前的运算结果,是非常频繁的操作
- 控制比较复杂,需要区分哪一个需要加
bubble
解决方案3:转发/旁路
前递:forwarding
- 在
ALU
中,新的r1
其实已经获得了。第一个的ALU
的输出是在第二个的ALU
的输出之前的 **ALU**
是复用的,刚算完,又重新给自己。- 电路上:
bypassing 旁路
,从旁边传数据过来; - 数据上:把之后的数据提前传递过来,并不需要从后面读出来,所以是
forwarding 前递
- 电路上:
- 只能解决和运算有关的数据冒险
缺点:
无法解决 一条指令使用之前指令的访存结果Load-Use Harzard
.
解决方案4:交换指令顺序
左边的案例:
- 无法通过转发/旁路解决问题
- 无法交换,只能插入
bubble
右边的案例:可以通过交换顺序减少等待
控制冒险
影响:
- 转移指令占比15%-25%(平均每隔4-7条指令)
- 转移平均损失10个周期
- 流水线越深、超标量数越多,转移指令的影响越大
解决方案1:取多条指令
不是完备的解决方案
解决方案2:分支预测
尝试猜的更对 – 预测
两层嵌套for
循环十分常见,所以采用两次错误i=1,j=10
,预测不发生,预测正确,到第二层嵌套,再次预测不发生,预测错误。
静态预测,两种方式是并用对同一种方式更好。
看看曾经有没有预测过:
- 没有预测过:加入历史表中
- 预测过:按照以往的历史进行预测,并更新结果