RISC-V 分支预测

分支预测




一、分支指令类型

1.无条件跳转/分支指令,指无需判断一定会发生跳转的指令。分为以下两种情况:
—-无条件直接跳转;指跳转的目标地址从指令编码中的立即数可以直接计算出,RSIC-V中的jal指令便属于无条件直接跳转指令。如下图所示,指令直接跳转到pc=80000132处。

80000000: a00d   jal  800000132 <reset_vector>

—-无条件间接跳转;是指目标地址需要从寄存器索引的操作数中计算出来。RSIC-V中的jalr指令,便属于无条件间接跳转指令。jalr rd, rs1, imm ; jalr指令使用12位立即数(有符号数)作为偏移量,与操作数寄存器rs1中的值相加得到最终的跳转目标地址。
2.带条件跳转/分支指令,指需要判断条件决定是否发生跳转的指令。RSIC-V架构中,有6条带条件分支指令,带条件的分支指令与普通的运算指令一样直接使用两个整数操作数,然后对其进行比较,如果比较条件满足,则进行跳转。

二、分支预测

×××分支预测的必要性:无条件跳转/分支指令一定会发生跳转无需进行判断;对于带条件跳转/分支指令而言,流水线在取指令阶段无法得知该指令的条件是否成立,因此无法确定是跳还是不跳,理论上只有在执行阶段完成之后,才能解析出最终的跳转结果。假设处理器将取指暂停,一直等到执行阶段完成后才继续取指,则会造成大量的流水线空泡期,进而影响其性能。
分支预测的过程中要解决两个问题:预测方向;预测跳转的地址。对于方向的预测可以分为静态预测和动态预测。

1.静态预测(方向)

静态分支预测仅依靠这条分支指令本身的信息进行预测,与任何曾经执行过的指令信息和历史信息无关。常见的静态预测方法BTFN(back taken,forward not taken),即对于向后的指令跳转预测为跳,向前的跳转则预测为不跳。向后跳转指跳转的目标地址(PC值)比当前分支指令的PC值要小。

2.0动态预测(方向)

动态预测是指依赖已经执行过的指令的历史信息和分支指令本身的信息综合进行“方向”预测。常见的分支方向动态预测器:
—-一比特饱和计数器,每次分支指令执行之后,便使用此计数器记录上次的“方向”。预测机制是:下一次分支指令永远采用上次记录的“方向”作为本次的预测。结构简单,但是预测精度不如两比特饱和计数器。
—-两比特饱和计数器,每次分支指令执行之后,对应的状态机会发生转换。预测机制,当目前状态为“强不需要跳转(strongly not taken)”或者“弱不需要跳转(weakly not taken)”时,预测该指令的方向为”不需要跳转(not taken)“;当目前状态为”弱需要跳转(weakly taken)”或者”强需要跳转(strongly taken)“时,预测该指令的方向为“需要跳转(taken)”。每次预测错误便会向相反的方向更改状态机状态,总共对应有上述4个状态。对应的动态分支算法有一级预测器、两级预测器。

2.0.1一级预测器

将有限个“两比特饱和计数器”组织成一堆的表格,称为预测器表格(predictor table),并直接使用PC值的一部分进行索引。“一级”是指其索引仅仅采用指令本身的PC值。虽然简单易行,但是其索引机制过于简单,很多不同的分支指令都会指向同样的表项(比如不同的PC之间某些位相同)。并且由于没有考虑到分支指令的上下文执行历史,分支预测的精度不如两级预测器。

2.0.1两级预测器

两级预测器也称为相关预测器,对于每条分支指令而言,将有限个“两比特饱和计数器”组织成PHT(Pattern History Table)。使用该分支跳转的历史(Branch History)作为PHT的索引。分支历史又可以分为局部历史和全局历史。局部分支预测器会使用分立的局部历史缓存来保存不同指令的分支历史,每个局部历史缓存有自己对应的PHT。全局分支预测器则仅使用分支指令共享的全局历史缓存,它的弊端是无法区分单独每个分支指令的历史,不同的指令会互相冲击,优势是比较节省资源。

3.0预测地址

1.BTB(Branch Target Buffer)分支目标缓存,是指使用容量有限的缓存保存最近执行过的分支指令PC值,以及它们的跳转目标地址。对于后续需要取指的每条PC值,将其与BTB中存储的的各个PC值进行比较,如果出现匹配,则预测这是一条分支指令,并使用其对应存储的跳转目标地址作为预测的跳转地址。它的一个缺点是对于间接跳转/分支指令的预测效果并不理想。这主要是由于间接跳转/分支的目标地址是使用寄存器索引的操作数计算所得,而寄存器中的值随着程序执行可能每次都不一样,因此BTB中存储的上次跳转的目标地址并不一定等于本次跳转的目标值。
2.RAS(Return Address Stack)返回地址堆栈,是指使用容量有限的硬件堆栈来存储函数调用的返回地址。间接跳转/分支可以用于函数的调用和返回。而函数的调用和返回在程序中往往是成对出现的,因此可以在函数调用时将当前PC值加4(或者2) 。即将其顺序执行的下一条指令的PC值压入RAS堆栈中,等到函数返回(使用分支跳转指令)时将RAS中的值弹出,这样就可以快速地为该函数返回的分支跳转指令预测目标地址。
3.间接BTB是指专门为间接跳转/分支指令而设计的BTB,域普通BTB类似,存储较多的历史目标地址,但是通过高级的索引方法进行匹配(而不是简单的PC值比较),结合了BTB和动态两级预测器的技术,能够提供较高跳转目标地址预测成功率。缺点是硬件开销大,只有在高级的处理器中才会使用。

3.1 RSIC-V取指简化

××规整的指令编码格式
××指令长度指示码放于低位
××简单的分支跳转指令
××没有分支延迟槽指令
××提供明确的静态分支预测依据
××提供明确的RAS依据

3.2 RAS依据

RAS用于函数返回地址的预测,但是RAS需要能够明确判定什么指令属于“函数调用”类性的分支跳转指令从而进行压栈,什么指令属于“函数返回”类型的分支跳转指令从而进行出栈。
RSIC-V架构规定,如果使用jal指令且目标寄存器索引值rd等于x1或x5,则属于需要进行RAS压栈;
如果使用jalr指令(jalr rd, rs1,imm),则按照使用的寄存器值(rs1和rd)的不同,明确规定相应的RAS压栈或者出栈行为。(图中的link表示x1或x5)。

rdrs1rs1=rdRAS action
!link!link-none
!linklink-pop
link!link-push
linklink0push and pop
linklink1push

3.2RIC-V调用约定

ABI(application binary interface):应用程序二进制接口

寄存器ABI名字描述在调用中是否保留
x0zero(零)硬件连线0
x1ra返回地址No
x2sp栈指针Yes
x3gp全局指针
x4tp线程指针
x5-7t0-2临时寄存器No
x8s0/fp保存寄存器/帧指针Yes
x9s1保存寄存器Yes
x10-11a0-1函数参数/返回值No
x12-17a2-7函数参数No
x18-27s2-11保存寄存器Yes
x28-31t3-6临时寄存器No
f0-7ft0-7浮点临时寄存器No
f8-9fs0-1浮点保存寄存器Yes
f10-11fa0-1浮点参数/返回值No
f12-17fa2-7浮点参数No
f18-27fs2-11浮点保存寄存器Yes
f28-31ft8-11浮点临时寄存器No

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值