# 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 返回地址存在哪里(可能是一个栈的指针)
控制器通知存储器写入返回地址
# 指令流水线
# 两阶段方法
时间分配不均匀,取指令太闲,执行执行太忙。
取指令和执行指令都需要访问内存、取地址,所以会造成访问冲突。
等待:条件分支指令导致地址可能取的不对,前面取的地址作废。
# 六阶段方法
后面五个是把执行指令拆成了五个去完成。
解决了两个阶段处理时间分配严重不平衡。
好处:大大缩减了时间单位。
# 问题
- LOAD 不需要 WO 写操作数。
不需要给特殊的指令设计特殊的流水线,从硬件设计的角度来说,不划算。没有这个阶段就不执行。
- 不是所有阶段都可以并行完成
- 虽然不像两个阶段的差异那么大,但是六个阶段的时间还是有差异的,以每个流水阶段的最长的为基础
# 限制:条件转移指令
红框框出的指令执行无效。
# 限制:中断
操作:排空流水线
只能在时钟上升沿进行操作,可以有效避免噪声
# 流水线性能
锁存延时:锁数据,先放入寄存器,再从寄存器中取出来
对应理想情况下的阶梯。
第一条指令需要 k 个 t,后面(n-1)条每条时间长度多一个 t。
加速比:评价流水线性能好坏的标准。用没有使用流水线的时间除以使用了流水线的时间。
(误解)指令越多,k 越大,加速因子越大。
d 锁存延时会累计。
冲突会累计
# 冒险 Hazard
阻塞或停顿
# 结构冒险
红色:使用不同的硬件资源(数据和地址使用不同的寄存器、使用了 cache)
蓝色:分时复用,一个在上升沿使用,一个在下降沿使用。本身阶段所需时间就比较短,可以一起操作。
# 数据冒险.
r1 在第一条是结果,但是在下面的指令中是操作数
# 插入 nop 指令
等待
# 插入 bubble
有时间开销
# 转发 旁路
重点
其实 ALU 已经算出来结果了,不需要等待 WB 写回。
用到 R1 的时候,可以从别的地方拿过来,不需要等待。
# 交换指令顺序
旁路什么时候有效?后面的数据是算出来的。
但是 load 拿出来的数据,是要等到 WB 的,此时旁路失效。
把一个跟前面没有关系的指令提前执行。
# 控制冒险
取错指令了
# 取多条指令(枚举?)
有限的,分支太多就数量爆炸了
循环缓冲器:缓存一个数量
# 分支预测(猜得更对一点)
- 静态预测:与历史指令无关,简单但是效果不好
- 动态预测: