【ICS总结】第4章 处理器体系结构

这周肝作业肝得差不多了,也快到考试周了,终于抽时间把第四章弄了弄,写了一份总结。发上去就吃晚饭!
不一定有时间定期更新这样的东西,毕竟是个卷心菜,总要担心自己忙不忙得完23333

Y86-64指令集

instructionaccess memoryneed valCneed regids
halt
nop
rrmovqyes
irmovqyesyes
mrmovqyes (read)yes(offset)yes
rmmovqyes (write)yes(offset)yes
Opqyes
jXXyes
cmovXXyes
callyes (return) (write)yes
retyes (return) (read)
pushqyes (write)yes
popqyes (read)yes

两个特殊的(暂停和跳过),四个移动,一个计算(多个功能),两个条件(条件传送和条件转移),四个涉及栈指针。

Y86-64的指令分阶段实现

实际上没有必要记住每一个指令的细节,只需要知道大体的指导原则。这样才能面对错综复杂的新指令。

1 Fetch

取指阶段遵从一致的原则:

  • 总是读取icode: ifun (split)
  • 根据需要读取寄存器rA: rBvalC (align)
  • 根据指令长度调整valP (need_valC,need_regids)

取指阶段的硬件逻辑如下:

  • 访问内存可能产生imem_error
  • 合法的指令icode才能产生instr_valid

2 Decode & Writeback

译码和写回阶段都要对寄存器文件操作,其硬件逻辑如下:

  • Decode时需要从寄存器文件读出valAvalB,Writeback时可能写Execute阶段的valE,可能写回Memory阶段的valM
  • 根据icode来决定选择rA, rB还是其他寄存器名,valA不一定来自R[rA],比如popq rA
  • 所有不经过内存的写回都使用valE,即使不需要计算也要加个0!
  • 通常来说,rA决定了内存的写回端口,rB决定了其他的写回端口。只有popq %rsp用到了两个写回端口,涉及到先后顺序的问题,这个先后是寄存器文件的硬件决定的。
  • cmovXX如何实现条件传送?就是根据Cnd调整dstERNONE
  • 涉及%rsp的几条指令不太好理解,总结一下:
    • 访存阶段,mem_addr只能是valEvalAmem_data只能是valAvalP。其中通用的规则是:valE存储Execute阶段修改过的偏置地址或栈指针,valA保存原来的栈指针或待写入的值。注意到valAvalP不会被同时使用,只有call会使用valP,所以在PIPE阶段这两个信号被合并。
    • mrmovqrmmovq比较简单,不涉及栈指针的变化,以下就不讨论了。
    • 如果是读取内存,重点关注两个操作popqret这两个操作都会使用操作开始前的%rsp访问栈,本来就如此,栈顶元素在那里摆着呢。那么valE干什么呢?它负责写回阶段调整栈指针的值。需要注意的是,x86-64保证popq %rsp执行完后%rsp存储指令执行前栈顶元素的值,y86-64继承了这一点
    • 如果是写内存,重点关注pushqcall。他们俩不需要使用原来的栈指针,所以pushqvalA用来保存待写入的值了,call直接没用valA(因为它要用valP)。如果是pushq %rsp,它会把原来栈指针的值压栈,再把栈指针加8,这涉及到所谓“从不回读”原则,一个操作的完成不依赖于这个操作的结果(看起来像废话)

3 Execute

执行阶段的逻辑比较简单。

  • aluA可以来自valAvalCaluB只能来自valB。当然,它们可以是常数。
  • CC是ALU单元产生的条件码信号,cond是决定是否更新条件码的硬件单元(根据ifunCC),Cnd是条件码寄存器的值。
  • alufun只在OPq中被设置,其他情况默认是加。

4 Memory

  • 内存访问的地址mem_addr和数据信号mem_data在上面讲过了,不多讲。
  • mem_readmem_write信号决定是读还是写,注意到没有指令又读内存又写内存。
  • 到这一阶段产生dmem_error,所有可能报错的点都报完了,结合取指阶段的报错和指令,更新整个处理器的状态码Stat。到了PIPE还是这个思路,流水线寄存器始终保存当前整个处理器的状态码(当然,为了逻辑上的一致,它到最后的W阶段才修改状态码寄存器),并以此指导整个流水线控制逻辑。

5 PC Update

  • 需要五个信号icode, Cnd, valC, valM, valP。回头把代码补一下。

Extra Exercises

我把每个阶段核心的要点列出来了。回头再把这些单独做一遍。

  • srcAsrcB的代码?
  • aluAaluB的代码?
  • mem_addrmem_data的代码?
  • mem_readmem_write的代码?
  • stat的代码?
  • new_pc的代码?

Pipeline的通用原理

  • 流水线的延迟单位通常为 p s ps ps,而吞吐量单位通常是 G I P S = 1 i n s t r u c t i o n ⋅ n s − 1 GIPS = 1 instruction \cdot ns^{-1} GIPS=1instructionns1。所以算吞吐量要补个系数 1000 p s 1 n s \dfrac{1000ps}{1ns} 1ns1000ps
  • 流水线处理器的延迟取决于最长的阶段开销和寄存器的延迟。不能说某一个阶段算完了这个周期就提前结束了!
  • 流水线不能太深,否则寄存器延迟占比太大。

SEQ to PIPE

PIPE-

从SEQ到SEQ+再到PIPE-,核心的工作就几件事:

  • 把取指和更新PC值,预测PC值合并到一起作为一个阶段,指令执行过程整合成五个阶段
  • 插入流水线寄存器
  • valAvalPselectA合并,减少电路复杂度。

剩下的工作全是在处理各种hazard。

Data Hazard

避免数据冒险最简单的方法就是暂停流水线。比如说,我发现data dependency,后面的指令需要等一等再执行,那么我让F和D阶段的寄存器stall,他们这周期都不更新,下一周期又把这周期干的事又干了一遍。E阶段插入一个气泡,相当于代码当中多了个nop。那么,流水线后面的部分正常执行,会不会对取指有影响呢(这是最有必要的一个转发)?答案是并不会。大多数情况下predict_pc的值是准确的,根本不依赖上面两个转发。除非我们面对的是ret或者预测错误的jXX,这时候这个问题就变成多个hazard同时出现了,这个留到后面有更具体的方案,我们会解决它。

stalling对性能损害太大,所以有forwarding 的解决方法。这个不详细解释了,注意顺序,待会自己推一遍Sel+FwdAFwdB是怎样实现的。唯一需要注意的是E阶段的用的是小写的,因为e_dstEE_dstEcmovXX指令中可能不一致。

在我们的设计里,stalling可以解决数据冒险的所有问题,但forwarding不行,因为不允许内存中读出的值直接转发到E阶段。所以会有加载互锁load interlock。

Control Hazard

控制冒险有两个,一个是ret,这个在我们的实现中没有给预测,就三个bubble硬等;另一个是jXX预测错误,在E阶段检查到时要立刻在D和E插入两个泡泡,然后到下一周期jXX进入到M阶段时,新一个指令的取指一定会从jXX的转发取指(所以没有必要再F阶段插入bubble)。

Pipeline Control Logic

流水线控制逻辑,它一共会面临几种情况:

  • load/use hazard
  • ret
  • misprediction branch
  • exception

前面三个简单来说就是插泡泡和暂停。如果需要插入nop,那么应该插入一个bubble并让前面的阶段都暂停;如果是要实现instruction squashing,那就把需要清除的指令用bubble覆盖,后面的取值仍然可以正常进行(转发会保证predict_pc用不上)。

比较不常见的是exception,单独说一下。在SEQ中我们说了,直到M阶段,我们才能拿到当前整个处理器的状态码;在PIPE中,直到W阶段我们才写回Stat。我们的控制逻辑遵从了最基本的原则:后面不应该做的指令不应该修改全局状态,并采取了一种比较省事的策略:只要全局状态不被修改就完了。全局状态有三个:寄存器文件(到W就停了,不用管)、内存(M发现问题)、条件码CC(E阶段算,E阶段存)。所以我们必须保证当前周期不写回内存,也不修改条件码CC。

多种情况的组合,就看你想干啥了。ret和错误分支的比较简单,它俩加在一起就是我想要的结果。但是ret和load interlock需要关注一下,他们在D阶段一个插bubble,一个插暂停。例如,前一条指令是popq %rsp,后一条指令是ret,我希望的行为是让流水线停下来,确定到底该返回啥,而不是让ret开始咣咣咣插bubble,否则ret拿到的值是不对的,M阶段又没办法向E阶段转发。这样的分析思路,对于新加入的指令也是适用的。(做过往年题后写这篇总结,我很关注分析问题的思路。)

Extra Exercise

  • predict_pcselect_PC
  • d_valAd_valB?
  • 四个控制逻辑的触发条件?
  • 什么时候需要向哪个阶段插入bubble/stall?控制的逻辑是什么?
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值