基于RISC-V 的四路组相联结构的分支目标缓存设计
张帅 李艳 王子健 陈佳
1. 武汉第二船舶设计研究所 湖北武汉 430025 2. 武汉晴川学院 湖北武汉 430204 ;3. 中国地质大学 湖北武汉 430074
1 基于 RISC-V 的 BTB 结构
条件跳转指令以及直接跳转指令的跳转目标地址只有两种情况,一种是当分支指令不发生跳转时,跳转目标地址为当前指令 PC 地址 + 指令字节数;另一种是分支指令发生跳转时,跳转目标地址为当前PC 地址 + 地址偏移量。地址偏移量为指令中携带的立即数,因此对于直接跳转的分支指令来说,其跳转目标地址不会发生改变。只需用一个表格记录下各直接跳转指令的跳转目标地址,在下一次执行该指令时,通过 PC 地址对表格进行查找即可得到预测的跳转目标地址,这个表格就叫做BTB,其结构如图1 所示。
图 1 BTB 结构

BTB 本质上是一个 Cache,使用 PC 地址作为索引地址 Index。由于 BTB容量有限,只能使用 PC 地址部分位作为索引,因此 BTB 存在索引地址相同但是 PC 地址不同的指令索引到同一个表项的情况,影响 BTB 的预测准确率。故 BTB 中除了记录分支目标地址(Branch Target Address,BTA)外,还存放着 PC 地址的部分位作为标签 Tag,用于区分不同的指令,并且 BTB中还有一个表示该表项是否有用的Valid 位。在预测时,利用PC 索引BTB,读出表项中预测结果,之后将表项中的 Tag 位与 PC 地址部分位进行比较,若两者相匹配且该表项 Valid 部分为 1 则表示命中,即当前预测目标跳转地址有效。未命中则预测跳转目标地址为 PC+4 ,即顺序取指的下一条指令地址。
在更新时,若 BTB 命中且预测正确则不对表项进行更新,若预测错误,一般存在两种情况:一种是方向预测错误,即该分支上一次跳转,但本次不跳转,这种情况一般是循环程序的最后一次循环,更新是仅将 Valid 置 0,表示该分支不跳转;另一种情况是跳转目标地址错误,即不同分支指令索引到同一个表项,此时会将新的目标跳转地址写入到 BTB 对应表项中。若BTB 未命中,且该分支指令实际结果为跳转,则开辟一个新表项,将分支指令的跳转目标地址以及由 PC 地址的部分位构成的 Tag 写入 BTB,并且将Valid 置 1。分支指令实际结果不跳转则不对 BTB 表项进行更新,仅对实际结果为跳转的分支指令进行记录,如此就能在相同的存储空间下预测更多跳转的分支指令。
2 四路组相联结构的 BTB
面向单目标分支的 BTB 结构,存在多条分支指令索引到同一个表项的情况,导致 BTB 中的目标地址频繁被更换。为此,本文采用四路组相联结构的 BTB,将每一个分支指令对应的表项化为多个组,其中每组具有 4 路,可以存放4 条不同分支指令的跳转目标地址,其结构如图2 所示。
本文在传统四路组相联结构的 BTB 基础上加入了由两位计数器构成的最近最少使用(Least Recently Used,LRU)计数器,以及位宽为 2,表示该分支指令类型的 Type 位。LRU 计数器的作用是统计出 4 路中最近最久未使用的表项,在多于 4 条分支指令索引到同一组时,将其淘汰。若每个表项存储完整的跳转目标地址,会占用较多存储空间,因此使用 Type 位来表示该分支指令类型为 RISC-V32I 指令集中 B、I、J 的哪一种,Type 在 B 类型的分支指令时,保存为 2 进制的 01,为 I 类指令时为二进制的 10,J 类型为二进制的 11。根据不同指令类型,仅将立即数表示的地址偏移量记录到BTB 中,三种类型的分支指令中J 型指令的立即数最长为20bit,为方便记录,每个表项用来记录立即数的存储空间均为 20 位。当表项命中时,先按照分支指令类型对指令偏移量进行扩展,之后加上 PC 地址生成预测跳转目标地址。这样就不需要保存全部的跳转目标地址,有效节省了 BTB 的存储空间。但会增加一次加法计算,造成额外的路径延迟,相对于更加重要的面积指标,在可接受的范围之内。
本文所设计的四路组相联结构的 BTB 在预测时,首先利用 PC 地址低10bit 作为组索引,同时访问组内四路 BTB 对应的表项;之后利用 PC 地址的剩余部分分别与组内 4 路 BTB 中的 Tag 部分进行比较,若有一路匹配且匹配路中的 Valid 为 1 则表示命中,按照分支指令类型将匹配路中的立即数进行扩展后加上当前 PC 地址作为预测跳转目标地址。若组内 4 路 Tag 均不匹配或存在匹配的路但是该路 Valid 位为 0,则表示 BTB 未命中,此时默认分支指令不发生跳转,跳转目标地址为 PC 地址加上指令字节数。本文四路组相联结构 BTB 更新逻辑,当四路组相联结构 BTB 未命中时,如果分支指令实际结果为跳转,则在 4 路中 LRU 计数值最大(最近最少使用)的一路中开辟一个新表项。若 4 路 LRU 计数值均为最大(例如初始化时 LRU 计数器均设为最大),则默认在第一路中开辟新表项,写入分支指令类型、地址偏移量以及Tag,同时还会将Valid 位置1,表示该表项结果有效。与此同时,新开辟表项的 LRU 计数器还会初始化为最新。如果分支指令的实际结果为不跳转则不对BTB 进行更新。
当四路组相联结构 BTB 命中时,若实际结果为跳转且 BTB 的预测结果与实际跳转目标地址一致,说明当前分支指令预测正确,将提供预测那一路的 LRU 计数器更新为最新,表示该表项最近被使用。若预测地址与实际跳转目标地址不一致,则说明存在多个分支索引到同一个表项的情况,此时会在 4 路中 LRU 最大的那一路中开辟新的表项,并且将该路 LRU 初始化为最新,其余路的 LRU 计数器各加一,表示其余路被使用的情况。若实际结果为不跳转,将提供预测那一路表项的Valid 位置零,表示该分支不跳转,表项内其余分支指令信息保持不变。只有当该分支指令再次跳转时,才在更新时将Valid 重新置1。
图2 四路组相联结构的BTB

3 总结
本文设计的四路组相联结构的 BTB 对于跳转目标地址固定的条件跳转指令以及直接跳转指令能够提供非常有效的预测,显著提高处理器的执行效率。然而,对于跳转目标地址经常发生变化的间接跳转指令(例如由JARL 模拟的子程序返回指令 RET),仍然无法提供准确的预测。这是因为间接跳转指令的目标地址通常依赖于运行时的计算结果,具有较大的不确定性,导致BTB 难以进行有效的预测。