# Lecture15 - 指令周期

# 指令周期:状态图

取址周期:取指令

执行周期:其他都是执行指令

“返回字符串或向量数据” —— 不断地取出字符串的东西进行操作 ?

# 带中断的指令周期

在每次周期内检查一次中断

# 间址周期

” 间接地址的读取 “看做一个子周期

# CPU 的任务

# CPU 需求:寄存器

MAR 地址寄存器 Memory Address Register

MBR 缓冲寄存器 Memory Buffer Register

MDR 数据寄存器 Memory Data Register

PC 程序计数器 Program Counter

IR 指令寄存器 Instruction Register

# 数据流:取指周期

红线:PC 通过 MAR 将地址放到地址总线上

绿线:控制器告诉存储器地址已经准备好了

黄线:存储器从地址总线读取地址

数据准备好之后:

存储器将数据放在数据总线上,进而放在 MBR,然后放到 IR 中

控制器取下一条指令

控制器取完下一条指令之后,告诉 PC 加 1

# 数据流:间址周期

MBR 中存取的是间接地址,与之前类似,地址类源于 MBR 而不是 PC

取出来的不是操作数,而是有效地址

# 数据流:中断周期

在进行写操作

保存 PC 中的内容,需要知道返回到哪里

控制器告诉 MAR 返回地址存在哪里(可能是一个栈的指针)

控制器通知存储器写入返回地址

# 指令流水线

# 两阶段方法

时间分配不均匀,取指令太闲,执行执行太忙。

取指令和执行指令都需要访问内存、取地址,所以会造成访问冲突。

等待:条件分支指令导致地址可能取的不对,前面取的地址作废。

# 六阶段方法

后面五个是把执行指令拆成了五个去完成。

解决了两个阶段处理时间分配严重不平衡。

好处:大大缩减了时间单位。

# 问题

  1. LOAD 不需要 WO 写操作数。

​ 不需要给特殊的指令设计特殊的流水线,从硬件设计的角度来说,不划算。没有这个阶段就不执行。

  1. 不是所有阶段都可以并行完成
  2. 虽然不像两个阶段的差异那么大,但是六个阶段的时间还是有差异的,以每个流水阶段的最长的为基础

# 限制:条件转移指令

红框框出的指令执行无效。

# 限制:中断

操作:排空流水线

只能在时钟上升沿进行操作,可以有效避免噪声

# 流水线性能

锁存延时:锁数据,先放入寄存器,再从寄存器中取出来

对应理想情况下的阶梯。

第一条指令需要 k 个 t,后面(n-1)条每条时间长度多一个 t。

加速比:评价流水线性能好坏的标准。用没有使用流水线的时间除以使用了流水线的时间。

(误解)指令越多,k 越大,加速因子越大。

  1. d 锁存延时会累计。

  2. 冲突会累计

# 冒险 Hazard

阻塞或停顿

# 结构冒险

红色:使用不同的硬件资源(数据和地址使用不同的寄存器、使用了 cache)

蓝色:分时复用,一个在上升沿使用,一个在下降沿使用。本身阶段所需时间就比较短,可以一起操作。

# 数据冒险.

r1 在第一条是结果,但是在下面的指令中是操作数

# 插入 nop 指令

等待

# 插入 bubble

有时间开销

# 转发 旁路

重点

其实 ALU 已经算出来结果了,不需要等待 WB 写回。

用到 R1 的时候,可以从别的地方拿过来,不需要等待。

# 交换指令顺序

旁路什么时候有效?后面的数据是算出来的。

但是 load 拿出来的数据,是要等到 WB 的,此时旁路失效。

把一个跟前面没有关系的指令提前执行。

# 控制冒险

取错指令了

# 取多条指令(枚举?)

有限的,分支太多就数量爆炸了

循环缓冲器:缓存一个数量

# 分支预测(猜得更对一点)

  1. 静态预测:与历史指令无关,简单但是效果不好
  2. 动态预测:
# 动态预测

# 总结