CSAPP学习笔记 -- 第四章 处理器体系结构(三)
4.3.4 SEQ阶段的实现
HCL描述中使用的常数值
- nop指令只是简单的经过各个阶段,除了要将PC加1,不进行任何处理
- halt指令使得处理器状态被设置为HLT,导致处理器停止运行
SEQ不同阶段的HCL实现
- 取指阶段
- imem_error指明指令地址是否合法
- 根据icode的值计算三个1位的信号
- instr_valid:这个字节对应于一个合法的Y86-64指令吗
- need_regids:这个指令包括一个寄存器指示符字节码
- need_valC:这个指令包括一个常数字吗
- instr_valid 和 imem_error在访存阶段被用来产生状态码
- 当need_regids = 1时
- 字节1被分别装入rA,rB
- 若只有一个寄存器,则另一个的响应字段为0xF
- 若need_valC = 1,则字节2-9载入常数字
- 当need_regids = 0时
- 若need_valC = 0,则字节1为0xFF
- 若need_valC = 1,则字节1-8载入常数字
- PC增加其硬件单元根据当前PC值、need_regids、need_valC产生valP信号,valP = pc + 1 + need_regids + need_valC * 8
- 译码和写回阶段
- 寄存器文件由4个端口,A/B用来读,M/E用来写,每个端口都有一个地址连接和一个数据连接,地址连接是一个寄存器ID,而数据连接是一组64根线路,既可以作为寄存器文件的输出字(对读端口来说),也可以作为它的输入字(对写端口来说)
- 寄存器ID srcA表明应该读哪个寄存器以产生valA,所需要的值依赖于指令类型
- 执行阶段
- aluA的值可以是valA、valC、8、-8
- aluB的值可以是valB、0
- 访存阶段
- 更新PC阶段
SEQ小结
- 唯一的问题就是太慢了
- 这种方法不能充分地利用硬件单元,因为每个单元只在整个时钟周期的一部分时间内才被使用
- 因此引入流水线
4.4 流水线的通用原理
4.4.1 计算流水线
流水线的一个重要特性就是提高了系统的吞吐量
,不过也会轻微的增加延迟
,代价是增加了一些硬件
,延迟变大是由于增加的流水线寄存器的时间开销。
4.4.2 流水新操作的详细说明
- 减缓时钟不会影响流水线的行为
- 信号传播到流水线寄存器的输入,但是直到时钟上升时才会改变寄存器的状态
- 如果时钟运行得太快,就会有灾难性的后果
- 值可能会来不及通过组合逻辑,因此当时钟上升时,寄存器的输入还不是合法的值。
4.4.3 流水线的局限性
局限
- 不一致的划分
- 运行时钟的速率是由最慢的阶段的延迟限制的
- 对硬件设计者来说,将系统设计划分成一组具有相同延迟的阶段是一个严峻的挑战
- 流水线过深,收益反而下降
- 延迟时间占比过大,成了流水线吞吐量的制约因素
设计高速微处理器面临的挑战
- 指令执行阶段划分
- 流水线寄存器的设计
- 时钟传播网络的设计
- ......
4.4.4 带反馈的流水线系统
Y86-64指令序列之间并不是相互独立的,有数据相关,也有控制相关。在SEQ设计中,这些相关都是由反馈路径来解决的,但是直接将流水线直接引入这种含有反馈路径的系统中存在危险。
4.5 Y86-64的流水线实现
4.5.1 SEQ+:重新安排计算阶段
SEQ ---> SEQ+
- 更新PC阶段在一个时钟周期开始时执行,而不是结束时执行
- 在SEQ+中创建状态寄存器保存在一条指令执行过程中计算出来的信号
- 当一个新的时钟周期开始时,这些信号值通过同样的逻辑来计算当前指令的PC
- 这些信号值是任意给定周期的前一周期中产生的控制信号
- SEQ+没有硬件寄存器来存放程序计数器,而是通过通过前一条指令计算得到的状态信息计算得到当前PC值
4.5.2 插入流水线寄存器
中间版本无话可说
4.5.3 对信号进行重新排列和标号
我们需要很小心以确保使用的是正确版本的信号,否则会有很严重的错误
- 我们采用的命名机制,
- 通过在信号名前加上大写的流水线寄存器名字作为前缀,存储在流水线寄存器中的信号可以唯一被标识
- 某些在一个阶段内刚刚计算出来的信号,他们的命名是在信号名前面加上小写的阶段名的第一个字母作为前缀
- 作为一条通用原则,我们要保存处于一个流水线阶段的指令的所有信息
4.5.4 预测下一个PC
流水线设计的目的就是每个时钟周期都发射一条指令,也就是说每个时钟周期都有一条新指令进入执行阶段并最终完成。
- 要达到这个目的也就意味着吞吐量是每个周期一条指令,要做到这一点,我们必须在取出当前指令后就马上确定下一条指令的位置,即预测下一个PC
- 对于call和jmp指令来说,下一个PC就是指令中的常数字
- 对于条件转移指令来说,我们必须以某种方式来处理预测错误的情况
- 猜测分支方向并根据猜测开始取址的技术叫做分支预测
- Y86-64总是选择条件分支,因此预测PC的新值为valC
- 对于ret指令不做任何预测,而是暂停处理新指令,知道ret指令通过写回阶段