子预测器基类与子预测器接口

本文档介绍了香山BPU中的子预测器接口,以及子预测器基类的使用,阅读此文档可帮助你了解子预测器的对外交互,和子预测器基类中信号的使用。

在香山分支预测单元中,其所有子预测器以及 Composer 的类实现都是继承自子预测器基类(BasePredictor),并且子预测器接口(BasePredictorIO)也是在子预测器基类中进行定义。因此我们可以认为,Compser 和所有子预测器都含有相同的接口。

在子预测的理解及验证当中,我们最直接的外界交互是发生在子预测器接口,以及子预测器基类中定义的一些变量,因此在子预测器的验证之前,强烈建议你阅读并理解本节文档。

子分支预测器接口的大致内容及使用方法,已在香山分支预测单元(BPU)基础设计中进行了介绍,本节文档将专注于接口的信号细节。

子分支预测器接口 (BasePredictorIO)

接口定义: src/main/scala/xiangshan/frontend/BPU.scala

每个子分支预测器都需要实现该接口,该接口定义了子分支预测器的输入输出接口。

注意:其中某些信号被定义为了 numDup 个数量,其中每个信号完全一样,多个相同信号是为其他因素考虑。

详细的信号列表如下:

  • reset_vector 重置向量,reset 时 BPU 的 pc 会被重置为该值

    • 接口类型:UInt(PAddrBits.W)
  • in BPU 向子分支预测器发送的信息

    • 接口类型:DecoupledIO(new BasePredictorInput)
    • 信号列表:
      • s0_pc s0流水级的pc
        • 接口类型:Vec(numDup, UInt(VAddrBits.W))
      • folded_hist 全局折叠历史信息
        • 接口类型:Vec(numDup, new AllFoldedHistories(foldedGHistInfos))
        • 信号列表:详见(AllFoldedHistories
      • ghist 全局分支历史信息
        • 接口类型:UInt(HistoryLength.W)
      • resp_in 全局分支预测信息(包含s1, s2, s3 预测结果信息)
        • 接口类型:BranchPredictionResp
        • 信号列表:详见(BranchPredictionResp
  • out 子分支预测器向 BPU 发送的信息(包含s1, s2, s3 预测结果信息)

    • 接口类型:new BasePredictorOutput 继承自 BranchPredictionResp
    • 信号列表:详见(BranchPredictionResp
  • ctrl BPU 子预测器使能控制信号,主要用于控制各预测器是否开启

    • 接口类型:BPUCtrl
    • 接口列表:
      • ubtb_enable: UBTB 预测器使能
        • 接口类型:Bool()
      • btb_enable: BTB 预测器使能
        • 接口类型:Bool()
      • bim_enable: BIM 预测器使能
        • 接口类型:Bool()
      • tage_enable: TAGE 预测器使能
        • 接口类型:Bool()
      • sc_enable: SC 预测器使能
        • 接口类型:Bool()
      • ras_enable: RAS 预测器使能
        • 接口类型:Bool()
      • loop_enable: LOOP 预测器使能
        • 接口类型:Bool()
  • s0_fire s0阶段握手成功信号

    • 接口类型:Vec(numDup, Bool())
  • s1_fire s1阶段握手成功信号

    • 接口类型:Vec(numDup, Bool())
  • s2_fire s2阶段握手成功信号

    • 接口类型:Vec(numDup, Bool())
  • s3_fire s3阶段握手成功信号

    • 接口类型:Vec(numDup, Bool())
  • s2_redirect s2阶段重定向信号

    • 接口类型:Vec(numDup, Bool())
  • s3_redirect s3阶段重定向信号

    • 接口类型:Vec(numDup, Bool())
  • s1_ready s1阶段是否准备好接收信息 (方向:由子预测器输出)

    • 接口类型:Bool()
  • s2_ready s2阶段是否准备好接收信息 (方向:由子预测器输出)

    • 接口类型:Bool()
  • s3_ready s3阶段是否准备好接收信息 (方向:由子预测器输出)

    • 接口类型:Bool()
  • update BPU 向子分支预测器转发的更新请求

    • 接口类型:Valid(new BranchPredictionUpdate)
    • 信号列表:详见(BranchPredictionUpdate
  • redirect BPU 向子分支预测器转发的重定向请求

    • 接口类型:Valid(new BranchPredictionRedirect)
    • 信号列表:详见(BranchPredictionRedirect

其中,流水线控制信号将会在下面内容中进行进一步的说明。

全局折叠历史 (AllFoldedHistories)

接口定义:src/main/scala/xiangshan/frontend/FrontendBundle.scala

接口类型:AllFoldedHistories(foldedGHistInfos))

全局折叠历史的接口信息仅为一个 FoldedHistory 的列表

  • hist 折叠历史列表
    • 接口类型:MixedVec(gen.map{case (l, cl) => new FoldedHistory(l, cl, numBr)})

FoldedHistory 的接口信息也仅有一项

  • folded_hist 单项折叠历史,其位宽为历史压缩后长度。
    • 接口类型:UInt(compLen.W)

也就是说,全局折叠历史接口实际上是一个存储了折叠后历史的列表,其中每一项都是一个特定长度的折叠历史。

子预测器基类

在子预测器基类中定义了若干信号,并在每个子预测器中都可以访问到,并在其中还进行了若干连线。

其中多数信号都较容易理解 ,我们需要重点关注的是其中每个流水的 pc,这还会涉及到你对于流水线控制信号的掌握。因此接下来,我们将会介绍在子预测器中需要关注的流水线控制信号的含义,以及 s1_pc, s2_pc, s3_pc 信号的含义。

其中流水线控制信号共分为 3 组:

  • fire 信号 (s0, s1, s2, s3)
  • redirect 信号 (s2, s3)
  • ready 信号 (s1, s2, s3)

子预测器基类中的 pc 信号共有四组,s0_pc_dup, s1_pc_dup, s2_pc_dup, s3_pc_dup。每组信号中有多个 pc 信号,他们完全相同,为考虑一些其他因素所复制。因此我们可单纯把他们看做 s0_pc, s1_pc, s2_pc, s3_pc

他们的用法可参照下图:

他们与流水线控制信号的关系是:

  • s0_pc 直接由输入接口中的 in.s0_pc 连接而来
  • s0_fire 生效时,下一周期 s1_pc 会输出 s0_pc 的值
  • s1_fire 生效时,下一周期 s2_pc 会输出 s1_pc 的值
  • s2_fire 生效时,下一周期 s3_pc 会输出 s2_pc 的值

也就是说,fire 信号是会影响到下一个周期的数据是否有效,比如 s0_fire 信号会影响 s1 流水的数据是否有效,s1_fire 信号会影响到 s2 流水的数据是否有效。

fire 信号是否有效取决于本流水级数据是否有效 以及 下一流水级是否 ready。例如 s1_fire 信号有效的条件必须包含 s1 阶段数据有效,以及子预测器输出的 s2_ready 信号为有效,此时便可认为,s1 阶段数据处理完成,并且 s2 阶段就绪,下一周期数据将被直接送入 s2 阶段。

因此在子预测器中,以 s1 阶段为例,s1_ready 可以阻塞数据进入 s1 阶段,当 s1_ready 生效时,下一周期 s1 阶段的数据便会生效。而 s1_fire 有效的同时,说明 s1 阶段数据已经生效,预测器也已经将 s1 阶段的结果生成,下一周期将直接被送入 s2 阶段。

redirect 信号则相对明确。以 s2 为例,当 s2_redirect 有效时,说明 s2_fire 生效的同时 s2 预测结果与上周期 s1 预测结果不同。

最后修改 October 27, 2024: Fix typo (e95831c)