昆明湖 BPU 模块文档
术语说明
表 1.1 术语说明
| 缩写 | 全称 | 描述 |
|---|---|---|
| BPU | Branch Prediction Unit | 分支预测单元 |
| IFU | Instruction Fetch Unit | 取指单元 |
| FTQ | Fetch Target Queue | 取指目标队列 |
| uFTB | Micro Fetch Target Buffer | 微取值目标缓冲 |
| FTB | Fetch Target Buffer | 取指目标缓冲 |
| TAGE | TAgged GEometric length predictor | 一种条件分支预测器 |
| SC | statistical corrector predictor | 一种用于在统计偏向情况下纠正 TAGE 预测的条件分支预测器 |
| ITTAGE | Indirect Target TAgged GEometric length predictor | 一种用于预测间接跳转指令目标地址的分支预测器 |
| RAS | Return Address Stack | 一种用于预测调用(CALL)指令返回地址的分支预测器 |
设计规格
- 支持一次生成一个分支预测块及其对应预测器附加信息
- 支持无空泡的简单预测
- 支持多种精确预测器及覆盖机制
- 支持训练预测器
- 支持分支历史信息维护及误预测恢复
- 支持 topdown 性能事件的统计
功能描述
功能概述
BPU 模块接收来自模块外部后端执行单元及后续流水级的重定向信号,按照地址采用多种预测器为当前 PC 值开始的位置生成预测块及生成 该预测块时各预测器内部的 meta 信息,传递给后续取指目标队列(FTQ)存储,预测块供取指单元(IFU)使用,meta 信息供未来训练恢复预测器使用。其中,BPU 模块使用全相连 uFTB 作为 next line predictor,生成理想条件下延迟仅 1 周期的无空泡简单预测结果,该结果会 被直接作为输出传递到 FTQ。与此同时,这一基础预测结果还将在 BPU 后续流水线内流动,供高级预测部件使用以提供更为精确的预测结果。一旦高级预测器在后续流水级的预测结果与已有结果不一致,就将会使用高级预测器结果作为新的输出更新后续 FTQ 中存储预测块结果 并重定向 s0 级 PC,清空新结果流水级之前的流水级的错误路径结果。针对不同种类的指令预测的信息也有不同,条件分支指令的目标地址由 uFTB 提供,需要预测其方向;无条件直接跳转指令的目标地址由 uFTB 提供,不需要做任何特别的结果预测;间接跳转指令的跳转方向不需要预测,但 uFTB 提供的跳转地址结果并不一定正确,需要预测。
BPU 内的高级预测器包括 FTB、TAGE-SC、ITTAGE 和 RAS。其中,FTB 负责维护预测块的起始地址,终止地址,所含分支指令 PC 地址、类型( 是否 branch、是否 jalr、是否 jal、是否 call、是否 return)、基础的方向结果。TAGE-SC 是条件分支指令的主预测器,ITTAGE 用于预测 间接跳转指令。RAS 负责预测 return 类型的间接跳转指令跳转地址。
预测单元内多种预测器使用了分支预测历史作为预测条件,为提高历史与执行真实轨迹的匹配度,分支预测历史也会随预测结果做推测更新。全局分支历史在 BPU 顶层使用多个更新源进行更新维护,维护时会按照 TAGE、SC 和 ITTAGE 预测需要的长度进行维护,不同分支历史长 度的分支历史维护算法一致。具体地,TAGE 使用的分支历史长度有 8、13、32、119;ITTAGE 使用的历史长度有 4,8,13,16,32;SC 使用的历史长度有 0,4,10,16。分支预测历史在 BPU 模块顶层统一维护,更新源按照优先级从低到高依次为 s0 阻塞暂存的分支历史、利用 s1 预测结果更新的分支历史、利用 s2 预测结果更新的分支历史、利用 s3 预测结果更新的分支历史和 BPU 外部重定向的分支历史。每个分支历 史的具体维护策略为:
s0 阻塞暂存的分支历史:不进行任何主动的更新,始终与最新全局折叠历史保持一致。
s1 预测结果更新的分支历史:利用 s1 阶段的分支预测结果在随流水线传递来的
s0 全局折叠历史上更新。具体地,将预测结果根据位于的分支预测 slot shift 进全局分支历史,在 0 号 slot 则直接 shift 进去,在 1 号 slot 则 shift 进去 0(slot 0 没有 taken)和当前预测结果。
s2 预测结果更新的分支历史:利用 s2 阶段的分支预测结果在随流水线传递来的
s1 全局折叠历史上更新。更新算法与 s1 相同。s2 的更新仅在 s2 预测结果与之前 s1 不同时生效。
s3 更新策略与 s1、s2 相同,更新仅在 s3 结果与之前 s1 或 s2 不同时生效。
重定向的分支历史更新仅在发生重定向时进行,根据重定向信息中 addIntoHist 信号情况,分别将传回的分支历史直接或添加重定向对应 分支指令的方向结果后用于更新 BPU 的全局分支历史。
为保证较为准确的预测结果,各分支预测器都需要不断使用最新的执行结果训练预测器。具体地,更新的预测块及做出该预测时各预测器内部状态的 meta 信息将会在 FTQ 模块内生成并传递回 BPU 单元供各预测器更新内部状态。
分支预测并不能保证结果正确性,在预测结果与真实状态不符时,需要将状态恢复到使用错误预测而更新的状态之前,主要为分支历史的恢复及预测块起始地址的重定向。
分支预测块及 meta 信息生成
分支预测块思想
分支预测的目的是对执行流中存在的分支指令跳转方向与目标进行预测以在真实执行当前指令前推测地生成后续取指的 PC 范围信息以保证指令的连续供应。
一个分支预测块内包含了本分支预测块有效位(BranchPredictionBundle.valid)、起始地址、完整预测结果、FTB 项、折叠的分支历史 、RAS 预测器栈顶等信息。其中,完整预测结果在第一流水级来自 uFTB,后续来自 FTB 等高级预测器,FTB 项来自 uFTB 与 FTB 读出结果。
完整预测结果内记录了分支指令跳转方向、块内记录的分支指令信息是否有效(slot_valids,即是否存在该分支指令,一个 valid 对应一个 slot,一个 slot 对应一条预测块内的分支指令,共计 2 个 slot,其中最后一个 slot 可能记录块内第二条分支指令或一条无条件跳转/间接跳转指令)、分支指令目标、jalr 指令目标、分支指令块内偏移、无跳转时指令块结束地址、结束地址是否有误(块起始地址大于结束地 址,表明存在 false hit)、最后一条分支指令类型、最后一条指令是否为 RVI 的 call 指令、第二个分支指令 slot 是否记录分支指令而非无条件/间接跳转指令、是否命中等信息。如前所属,分支预测块内最多出现 2 条分支指令/1 条分支指令+1 条无条件跳转指令,当预测块内实际记录指令数超出该限制时,后续 FTQ 模块会将其拆分。此外,若分支预测块内不存在分支指令或未超出分支指令数量限制但达到了分支 预测块的最大宽度(32B)也将被截断。
FTB 项内记录了项是否有效(FTB 采用直接映射方式,若读地址不曾被写入则该标记无效)、第一个分支指令 slot、结尾的分支/跳转共用 slot、结束地址、指令类型、最后一条指令为 RVI call 指令、是否总是跳转等信息。FTB 项可被用于生成完整预测结果。
分支预测块生成
分支预测块中基础的 PC 信息最初由模块外传入的复位地址指定,随后处理器运行过程中正常情况下不断按照预测块的跳转地址推测更新,在遇到误预测时,PC 值将依据 redirect 通道所给值更新。next line 的完整预测结果由 uFTB 模块读出。完整预测结果中,FTB 项由 FTQ 模块 根据以往训练结果生成,条件分支指令的跳转方向由 uFTB 生成并在后续由 TAGE-SC 预测器更新,间接跳转指令的跳转地址由 uFTB 生成并在 后续由 ITTAGE 预测器更新,RAS 预测器会针对 return 类型的间接跳转指令覆盖 ITTAGE 的预测结果。被覆盖的结果仅体现在预测器输出,不 会立刻反向反馈给结果被覆盖的预测器更新内部状态。
meta 信息生成
各预测器为便于自身的更新,会将做出预测时预测器内部状态信息(例如作出该预测时命中预测表序号、命中 index)作为 meta 信息和预 测结果一同随流水线传递。
无空泡简单预测
uFTB 作为 BPU 的 next line predictor,为处理器作出无空泡的基础预测以连续生成下一个推测 PC 值。
uFTB 请求接收
每次 1 阶段请求有效时,截取传入预测块起始 PC 的 16 到 1 位生成 tag 发送给本模块内的全相连 uFTB 用于读取 FTB 项,FTB 项记录内容如前所述 。uFTB 内有 32 项使用寄存器搭建的全相连结构。由于使用寄存器实现,各项可在当拍根据其中存储数据是否有效及存储的 tag 值是否与传 入信息匹配来生成本项是否命中的信号及读出的 FTB 项数据并返回到 uFTB 层次。
uFTB 数据读取与返回
在当拍,uFTB 存储体已返回命中信号及读出数据。在本阶段将会从返回的命中信号中选出至多一命中项并利用该命中项生成预测结果,生成完整预测结果的算法在后续 FTB 模块有详细叙述,这里 uFTB 有一额外补充的 counter 机制,为 uFTB 内每一项内至多 2 条分支指令增加一个 2 位宽 counter,若 counter 大于 1 或 FTB 项内 always_taken 有效(后者机制也存在于 FTB 模块中)则预测结果为跳转。此外,本级的命中信号及选出的命中路编号还被作为本预测器的 meta 信息等待其他预测器一起进入 s3 阶段时送出预测器,随最终预测结果一起存储到 FTQ。本预 测器在 2、3 阶段没有其他额外动作。
uFTB 数据更新
当该预测块对应指令全部提交时,由 FTQ 传入 BPU 一直连到本模块的 update 通道中将包含 FTQ 模块根据指令提交信息更新的 FTB 项。由于全相连 uFTB 全部采用寄存器搭建存储体,写操作不会影响并行的读操作,传来的更新信息将始终用于更新。在更新通道有效时,在当拍将利用传入的更新 pc 值生成 tag 与 uFTB 内现有各项匹配并生成是否匹配及匹配的路信号。在下一拍,若存在已有匹配,将拉高匹配路的写入信号 ,否则利用伪 LRU 替换算法选出一待替换路拉高对应路写入信号,写入数据即为更新的 FTB 项。
针对每个分支指令的 counter 维护也在 update 通道拉高时一并更新,在 update 通道拉高下一拍,更新 FTB 项内跳转的分支指令及其之前的分支指令对应的 counter。若 taken 则 counter+1,若不 taken 则 counter-1,如达到饱和(0 或全 1)则维持当前值不变。
伪 LRU 算法也需要数据更新,其共有两个数据源,其一为作出预测时命中的路编码,其二为 uFTB 更新时要写入的路编码,若其中任意有效 ,则利用其信息更新伪 LRU 状态,当都有效时一拍内使用组合逻辑依次使用两信息更新。
多种高级预测器及覆盖机制
各高级预测器输出的结果将与之前流水级生成并随流水线传递来的结果(uFTB 的 minimal 结果或之后流水级由 FTB 提供的完成结果)比较,如有不同将以较新结果冲刷流水线。
Composer
Composer 是一个用于组合多个预测器的模块。在本项目中,其组合了 uFTB、FTB、TAGE-SC、ITTAGE 和 RAS 五个预测器,并对外抽象成了一 个三级流水覆盖预测器。Composer 中的各个预测器可以通过写自定义寄存器 sbpctl 来实现开关,可以按需使用预测器。在检测到来自外部的重定向后,Composer 会把重定向请求发送给各预测器,以用于恢复推测更新的元素。在预测块所有指令提交后,Composer 中的各预测器会进行训练。最终,Composer 将三级预测结果输出至 Predictor。各预测器的 meta 信息在本模块拼接在一起传递给 FTQ,FTQ 返回的训练用 meta 信息也在本模块内拆分后发送给各模块。
起始 PC 的配置
Composer 的 IO 接口 io_reset_vector 可以实现起始 PC 的配置。只需要将期望的起始 PC 传递给该 IO 即可。
与预测器的连接
Composer 将 uFTB、FTB、TAGE-SC、ITTAGE 和 RAS 五个预测器连接起来。共有三个分支预测器的流水级,每个预测器的相同流水级从前向后 以组合逻辑连接,且每个预测器是固定延迟的,到那个流水级就一定完成预测,所以 Composer 的只需要在对应流水级输出对应预测器的预测结果即可。
预测器的开关
通过 Zicsr 指令,我们可以读写 sbpctl 这一自定义 CSR 来控制 Composer 中的各预测器的使能。sbpctl[6:0]代表了{LOOP, RAS, SC, TAGE, BIM, BTB, uFTB}这七个预测器的使能。其中,高电平代表使能,低电平代表未使能。具体地,spbctl 这一 CSR 的值通过 Composer 的 IO 接口 io_ctrl_*传入各个预测器,并由各预测器负责使能的实现。当前架构中未加入 Loop 和 BIM 两预测器,因此对应位无效。
重定向的恢复
Composer 通过 io_s2_redirect、io_s3_redirect 和 io_redirect_*等 IO 端口接收重定向请求。这些请求被发送给其各个预测器,用于恢复推测更新的元素,如 RAS 栈顶项等。
FTB
FTB 暂存 FTB 项,为后续的 TAGE、ITTAGE、SC、RAS 等高级预测器提供更为精确的分支指令位置、类型、目标地址等分支预测块关键信息, 也为总是跳转的分支指令提供基础的方向预测。FTB 模块内有一 FTBBank 模块负责 FTB 项的实际存储,模块内使用了一块多路 SRAM 作为存储 器。SRAM 规格格式详见后续。
请求接收
0 阶段时,FTB 模块向内部 FTBBank 发送读请求,其请求 pc 值为 s0 传入的 PC。
数据读取与返回
在发送请求的下一拍也就是预测器的 1 阶段,将暂存从 FTB SRAM 中读出的多路信号。
再下一拍也就是预测器的 2 阶段,从暂存数据中根据各路的 tag 和实际请求时由 PC 高位生成 tag 的匹配情况生成命中信号并在命中时选出命 中 FTB 数据。若存在 hit 请求,则返回值为选出的 FTB 项及命中的路信息,若未 hit,则输出数据无意义。
FTBBank 模块读出的数据在 FTB 模块内作为 2 阶段的预测结果传递给 BPU 后续预测器的 s2 阶段以获取分支指令类型、PC 信息,此外这一读出的结果还会被暂存到 FTB 模块内,在 3 阶段作为预测结果以组合逻辑传递给后续预测器。若 FTB 命中,则读出的命中路编号与命中信息、周期 数等也会随流水线向后传递,最终若该预测块未被流水线中途冲刷,则在 s3 作为 meta 信息传递给后续 FTQ 模块,其中周期数仅在仿真环境 用于性能统计,在 FPGA 等环境不存在。
此外,若 FTB 项内记录的有效分支指令存在 always taken 标志,表示该分支指令历史上不曾有非跳转情况,则 2 阶段的预测结果中对应 br_taken_mask 也在本模块内直接拉高处理,直接预测该分支指令跳转,不再使用其他高级预测器的预测结果。
TAGE-SC
TAGE-SC 是南湖架构条件分支的主预测器,属于精确预测器(Accurate Predictor,简称 APD)。
其中 TAGE 利用历史长度不同的多个预测表,可以挖掘极长的分支历史信息;SC 是统计校正器。
TAGE 由一个基预测表和多个历史表组成,基预测表用 PC 索引,而历史表用 PC 和一定长度的分支历史折叠后的结果异或索引,不同历 史表使用的分支历史长度不同。在预测时,还会用 PC 和每个历史表对应的分支历史的另一种折叠结果异或计算 tag,与表中读出的 tag 进行匹配,如果匹配成功则该表命中。最终的结果取决于命中的历史长度最长的预测表的结果。
当 SC 认为 TAGE 有较大的概率误预测时,它会反转最终的预测结果。
在南湖架构中,每次预测最多同时预测 2 条条件分支指令。在访问 TAGE 的各个历史表时,用预测块的起始地址作为 PC,同时取出两个预测结果,它们所用的分支历史也是相同的。
TAGE 预测时序
TAGE 是高精度条件分支方向预测器。使用不同长度的分支历史和当前 PC 值寻址多个 SRAM 表,当在多个表中出现命中时,优先选择命中的历史长度最长的对应表项的预测结果作为最终结果。
TAGE 需要 2 拍延迟:
- 0 拍生成 SRAM 寻址用 index。index 的生成过程就是把折叠历史和 pc 异或,折叠历史的管理不在 ITTAGE 和 TAGE 内部,而在 BPU
- 1 拍读出结果
- 2 拍输出预测结果
TAGE:折叠历史
TAGE 类预测器的每一个历史表都有一个特定的历史长度,为了与 PC 异或后进行历史表的索引,很长的分支历史序列需要被分成很多段,然后全部异或起来。每一段的长度一般等于历史表深度的对数。由于异或的次数一般较多,为了避免预测路径上多级异或的时延,我们会直接存储折叠后的历史。由于不同长度历史折叠方式不同 ,所需折叠历史的份数等于 (历史长度,折叠后长度) 元组去重后的个数。在更新一位历史时只需要把折叠前的最老的那一位和最新的一位异或到相应的位置,再做一个移位操作即可。
TAGE:备选预测逻辑
实现了 USE_ALT_ON_NA 寄存器,动态决定是否在最长历史匹配结果信心不足时使用备选预测。在实现中处于时序考虑,始终用基预测表的结果作为备选预测,这带来的准确率损失很小。
SC:时序
一些应用上,一些分支行为与分支历史或路径相关性较弱,表现出一个统计上的预测偏向性。对于这些分支,相比 TAGE,使用计数器捕捉统计偏向的方法更为有效。TAGE 在预测非常相关的分支时非常有效,TAGE 未能预测有统计偏向的分支,例如只对一个方向有小偏差,但 与历史路径没有强相关性的分支。
统计校正的目的是检测不太可靠的预测并将其恢复,来自 TAGE 的预测以及分支信息(地址、全局历史、全局路径、局部历史)被呈现给统计校正预测器,其决定是否反转预测。SC 负责预测具有统计偏向的条件分支指令并在该情形下反转 TAGE 预测器的结果。
SC 的预测算法依赖 TAGE 里面的是否有历史表 hit 的信号 provided,以及 provider 的预测结果 taken,从而来决定 SC 自己的预测。provided 是使用 SC 预测的必要条件之一,provider 的 taken 作为 choose bit,选出 SC 最终的预测,这是因为 SC 在 TAGE 预测结果不同的场景下可能有不同的预测。
SC 需要 3 拍延迟:
- 0 拍生成寻址 index 得到 s0_idx,index 的生成过程就是把折叠历史和 pc 异或,折叠历史的管理不在 ITTAGE 和 TAGE 内部,而在 BPU 里
- 1 拍读出 SCTable 对应 s0_idx 的计数器数据 s1_scResps
- 2 拍根据 s1_scResps 选择是否需要反转预测结果
- 3 拍输出完整的预测结果
ITTAGE
ITTAGE 接收来自 BPU 内部的预测请求,其内部由一个基预测表和多个历史表组成,每个表项中都有一个用于存储间接跳转指令目标地址的 字段。基预测表用 PC 索引,而历史表用 PC 和一定长度的分支历史折叠后的结果异或索引,不同历史表使用的分支历史长度不同。在预测时,还会用 PC 和每个历史表对应的分支历史的另一种折叠结果异或计算 tag,与表中读出的 tag 进行匹配,如果匹配成功则该表命中。最终的结果取决于命中的历史长度最长的预测表的结果。最终,ITTAGE 将预测结果输出至 composer。
间接跳转指令的预测
ITTAGE 用于预测间接跳转指令。普通分支指令和无条件跳转指令的跳转目标直接编码于指令中,便于预测,而间接跳转指令的跳转地址 来自运行时可变的寄存器,从而有多种可能选择,需要根据分支历史对其作出预测。为此,ITTAGE 的每个表项在 TAGE 表项的基础上加 入了所预测的跳转地址项,最后输出结果为选出的命中预测跳转地址而非选出的跳转方向。由于每个 FTB 项仅存储至多一条间接跳转指 令信息,ITTAGE 预测器每周期也最多预测一条间接跳转指令的目标地址。
ITTAGE 需要 3 拍延迟:
- 0 拍生成寻址 index
- 1 拍读出数据
- 2 拍选出命中结果
- 3 拍输出
折叠分支历史
历史表有特定的历史长度,为了与 PC 异或后进行历史表的索引,很长的分支历史序列需要被分成很多段,然后全部异或起来。每一段的长度一般等于历史表深度的对数。由于异或的次数一般较多,为了避免预测路径上多级异或的时延,我们会直接存储折叠后的历史。由于不同长度历史折叠方式不同,所需折叠历史的份数等于 (历史长度,折叠后长度) 元组去重后的个数。在更新一位历史时只需要把折叠前 的最老的那一位和最新的一位异或到相应的位置,再做一个移位操作即可。
RAS
RAS 使用栈结构来预测函数调用与返回这类具有成对匹配特性的执行流的返回地址。其中调用(push/call)类指令的特征为目标寄存器地址为 1 或 5 的 jal/jalr 指令。返回(ret)类指令的特征为源寄存器为 1 或 5 的 jalr 指令。这类指令为无条件跳转指令,其类型、所在块内偏 移量已在 FTB 中读出。
在实现中,RAS 预测器在 s2 和 s3 两阶段提供预测结果。
2 阶段结果
在 2 阶段,由于 s3 阶段还可能存在预测结果需要更新,当前 FTB 项并不一定为最终执行路径,此时作出的预测推测了此时 3 阶段预测结果( 也即前一个预测块)不会刷新当前流水级内的预测起始地址。若 2 阶段从 FTB 传来的 FTB 项有效且其中存在 push 类(call)指令,则将该指 令之后下一指令的 PC 值压入 RAS 栈;若 s2 阶段传来 FTB 项有效且其中存在 pop 类(return)指令,则将当前栈顶的地址作为结果返回并对结 果出栈。
在 RAS 栈模块内,上述行为分别体现为,在 push 操作时,如当前地址和栈顶地址不同,则压栈一个新项目,其对应计数器为 0,否则将栈顶项的计数器增加 1。两操作都需将这一顶部信息设置为写 bypass 项以供当前读操作使用。在 pop 操作时,若当前栈顶项计数器为 0,则栈顶 指针减 1,若计数器大于 0,则将计数器减 1。为时序优化考虑,写入到 RAS 栈内的数据将会延迟一拍后写入,考虑到可能存在本拍写入的数据下一拍需要获取读数据的情况,设计了写 bypass 机制,准备写入的数据将在本拍首先用于更新写 bypass 相关的项,包括写操作指针及写操作数据。下一拍要求读取的指针若与写 bypass 记录的指针位置匹配,则使用 bypass 值,否则使用真正的栈顶值。
3 阶段结果
在 3 阶段,2 阶段曾发生过的推测 push/pop 操作记录会随流水线传递过来,3 阶段会根据 3 阶段 FTB 项(此时不再存在后续流水级,也即能进 入 3 阶段的 FTB 项不会被后续流水级冲刷)结果以与 2 阶段相同逻辑生成 push/pop 控制信号,若发现 2 阶段推测结果与 3 阶段判定结果不同, 即 RAS 位于 2 阶段时,当时 3 阶段预测冲刷过 BPU 流水线,则 2 阶段做出的预测结果所基于的情况已经发生变化,对 RAS 栈的操作不正确,需要仿照误预测进行状态恢复,具体细节见后。
预测器训练
预测器作出的每一个预测,在其中所有指令都成功提交后会由 FTQ 生成预测块更新信息,与传递到 FTQ 的各预测器 meta 信息一起送回预测器进行训练。
预测器训练数据接收
从 FTQ 传入的预测器训练数据在 BPU 模 FTB 项、更新 PC 等其他信号一起传递给各预测器。各预测器视其时序压力再暂存 update 信号或立刻进 行
FTB
FTB 项的更新具体逻辑详见 FTQ 模块。
收到 update 请求后,FTB 模块会根据 meta 信息中记录的这一预测做出时原来的读取结果是否 hit 决定更新时机。若 meta 中显示做出预测时 hit,则在本拍立刻更新将新的 FTB 数据写入 SRAM,否则需要延迟 2 周期等待读出 FTB 内现有结果决定写入路后才可更新。
在 FTBBank 内部,当存在更新请求时,该模块行为也因立即更新和推迟更新两情况而有所不同。立即更新时,FTBBank 内的 SRAM 写通道拉高,按照给定的信息完成写入。推迟 2 周期更新时,FTBBank 首先收到一个 update 的读请求且优先级高于普通预测的读请求,而后下一拍读出数据,选出给定地址命中的路编码传递给外部 FTB 模块(命中场景:两次针对这一 FTB 项的请求,第一次请求未命中,它更新之前发生了第 二次访问,当前第一次的更新已完成,此更新为第二次对应的更新)。而若这一拍未命中,则下一拍需要写入到在读出 FTB 项后一拍由路选取算法分配的路中。路选取规则为,若所有路均已写满,则使用替换算法(此处为伪 LRU,详见 ICache 文档)选取要替换的路,否则选取 一空路。
Composer
Composer 通过 IO 端口 io_update_*将训练信号发送给其各个预测器。总的来说,为防止错误执行路径对预测器内容的污染,各部分预测器在预测块的所有指令提交后进行训练。它们的训练内容来自自身的预测信息和预测块中指令的译码结果和执行结果,它们会被从 FTQ 中 读出,并送回 BPU。其中,自身的预测信息会在预测后打包传进 FTQ 中存储;指令的译码结果来自 IFU 的预译码模块,在取到指令后写回 FTQ;而执行结果来自各个执行单元。
TAGE-SC & ITTAGE
表项中包含一个 useful 域,它的值不为 0 表示该项是一个有用的项,便不会被训练时的分配算法当作空项分配出去。在训练时,用一个饱 和计数器动态监测分配的成功/失败次数,当分配失败的次数足够多,计数器达到饱和时,把所有的 useful 域清零。
RAS
当 RAS 在 2 阶段的推测结果与 3 阶段不同或之前的预测结果遇到了 redirect,需要恢复状态。其中,redirect 信息在实际恢复前被暂存到 RAS 内寄存器,延迟一拍再更新。3 阶段检测到不同的下一拍完成更新。若为 redirect 中的 call 误预测(出错指令预译码为 call 类型指令)或 3 阶段的 push 操作不匹配,则进行 recover_push 操作,将原来错误 pop 的 RAS 栈顶重新 push 进去。若为 redirect 中的 ret 误预测(出错指令预译码为 pop 指令)或 3 阶段的 pop 操作不匹配,则进行 recover_pop 操作,弹出 RAS 栈顶本应弹出的地址。栈指针在 redirect 时恢复为 redirect 传来的栈指针,否则为当前值。栈顶在 redirect 恢复时恢复为 redirect 传来的栈顶项,否则为当前值,恢复的新地址在 redirect 时为 redirect 信号下一条指令的值,否则为 2 阶段推测值。
在 RAS 栈内部,状态恢复时同样生成 push、pop 等操作,这类操作的处理方式与前述 2 阶段相同,此处仅列举存在不同的情况。在 push 操作 且非分配新项的情况下,若处于 recover 状态,sp、栈顶指针、顶部返回地址要设置为更新值。在 pop 操作且当前栈顶计数器非 0 时,so、 栈顶指针、顶部返回地址要设置为更新值。在既非 push 也非 pop 时,需要恢复 sp、栈顶指针、顶部返回地址同时处理写 bypass。
分支历史信息维护
推测更新
在流水级中预测器生成推测结果后,后续请求所用的分支历史也将包含这一推测值以提高预测准确率。
redirect 恢复
在遇到分支预测错误时,分支历史也被一并恢复到出错状态前,这样可以保证分支历史的准确度。
topdown 性能分析事件统计
在 BPU 流水级中预测器生成推测结果可能因为各种原因阻塞,而阻塞可能最终导致处理器整体的流水线空泡。为对性能瓶颈进行较为准确 的分析定位,昆明湖架构增加了 topdown 性能计数器,收集流水线中各流水级的空泡/阻塞信息并将指令提交时空泡(实际提交指令数与发射数理想值间差值)归因到具体的模块,从而实现对瓶颈部件的定位。上述性能分析建模方法细节详见 Intel 发表的论文《A Top-Down method for performance analysis and counters architecture》。在 BPU 可以统计到的阻塞事件包括因各预测器误预测恢复所引入的流水线空泡、因后端访存违例恢复所引入的流水线空泡、因 BPU 内部 override 预测刷新较老预测结果所引入的流水线空泡、因分支指令训练预 测器而阻塞 BPU 所引入的流水线空泡和因 FTQ 满无法接收新的分支预测块阻塞 BPU 所引入的流水线空泡。在 BPU 内不处理各空泡原因间的优先级,而只是在符合对应的统计条件时将空泡控制信号拉高并随处理器流水线传递。
目前 BPU 内有 FTB(含 uFTB 和主 FTB)、TAGE、SC、ITTAGE 和 RAS 共计 5 种预测器。Topdown 将分支误预测原因细分到以上 5 个预测器。具体地 ,将每个误预测空泡分解到各预测器的条件为:
- FTB:发生了分支指令相关的重定向且误预测的指令在对应预测块的 FTB 内并没有记录
- TAGE:发生了分支指令相关的重定向且误预测的指令在对应预测块的 FTB 内有记录,但 SC 预测器并未给出对应的预测
- SC:发生了分支指令相关的重定向且误预测的指令在对应预测块的 FTB 内有记录,同时 SC 预测器给出了对应的预测结果
- ITTAGE:发生了分支指令相关的重定向,误预测的指令为 jalr 指令但不是 return 指令且在 FTB 项中命中
- RAS:发生了分支指令相关的重定向。误预测指令为 return 指令(一类特殊的 jalr 指令,详见后续 RAS 模块说明)。
后端访存违例恢复所引入的流水线空泡判断条件为后端发来的重定向信号指示重定向来自访存违例。
BPU 内部 override 引入的流水线空泡有两个可能的来源,分别为 BPU 第 2 和第 3 流水级的重定向信号。
因分支预测器训练而引入的流水线空泡有 3 个可能的来源,分别为 BPU 第 1,2 和 3 流水线的 ready 信号。上述 ready 信号为 BPU 内各预测器的 ready 信号取或操作的结果。
因 FTQ 满而引入的流水线空泡判断条件为 BPU 发往 FTQ 模块的握手接口 ready 信号拉低。
对分支误预测和访存违例所导致的空泡,其将被标记在当前 BPU 各流水级的 topdown 信号中。对 BPU 内部 overrride 引入的空泡,其将被标记在 override 当前所在流水级和更早流水级,而不影响比这一 override 更早的预测块所在流水级。对分支预测器训练所导致的空泡处理类似 BPU override。
总体设计
整体框图
接口时序
BPU 到 FTQ 接口时序

上图展示了 BPU 到 FTQ 的预测结果接口时序。图中针对 0x1FFFF80020 起始地址的预测结果在流水线内 1、2、3 阶段分别输出,若结果与之前 流水级不一致则 redirect 信号拉高表明需要刷新预测流水线。
FTQ 到 BPU redirect 接口时序

上图展示了 FTQ 到 BPU 的 redirect 接口时序,redirect 核心信号为 cfiUpdate_target,其指定了 redirect 的目标地址为 0x200000109a。
FTQ 到 BPU update 接口时序

上图展示了 FTQ 到 BPU 的 update 接口时序,这一更新是为 0x2000000e00 开始预测块准备的,其目标跳转地址为 0x200000e0e。
寄存器配置
| 寄存器 | 地址 | 复位值 | 属性 | 描述 |
|---|---|---|---|---|
| sbpctl | 0x5C0 | 64'd0 | RW | bit0: uFTB 使能信号 bit1: FTB 使能信号 bit2: BIM 使能信号(保留) bit3: TAGE 使能信号 bit4: SC 使能信号 bit5: RAS 使能信号 bit6: loop 预测器使能信号(保留) |
注:RO——只读寄存器;RW——可读可写寄存器。
参考文档
- Reinman G, Austin T, Calder B. A scalable front-end architecture for fast instruction delivery[J]. ACM SIGARCH Computer Architecture News, 1999, 27(2): 234-245.
- Perais A, Sheikh R, Yen L, et al. Elastic instruction fetching[C]//2019 IEEE International Symposium on High Performance Computer Architecture (HPCA). IEEE, 2019: 478-490.
- Software Optimization Guide for AMD Family 19h Processors (PUB), Chap. 2.8.1.5, https://www.amd.com/system/files/TechDocs/56665.zip
- Seznec A, Michaud P. A case for (partially) TAgged GEometric history length branch prediction[J]. The Journal of Instruction-Level Parallelism, 2006, 8: 23.
- Seznec A. A 256 kbits l-tage branch predictor[J]. Journal of Instruction-Level Parallelism (JILP) Special Issue: The Second Championship Branch Prediction Competition (CBP-2), 2007, 9: 1-6.
- Seznec A. A new case for the tage branch predictor[C]//Proceedings of the 44th Annual IEEE/ACM International Symposium on Microarchitecture. 2011: 117-127.
- Seznec A. The O-GEHL branch predictor[J]. The 1st JILP Championship Branch Prediction Competition (CBP-1), 2004.
- Jiménez D A, Lin C. Dynamic branch prediction with perceptrons[C]//Proceedings HPCA Seventh International Symposium on High-Performance Computer Architecture. IEEE, 2001: 197-206.
- Seznec A. A 64-Kbytes ITTAGE indirect branch predictor[C]//JWAC-2: Championship Branch Prediction. 2011.