SimpleScalar中分支预测与实例源代码

本文详细介绍了SimpleScalar中分支预测的实现,包括二级分支预测、二位饱和计数器预测模式及其参数配置。讨论了Gag、Gap、Pag和Pap四种不同的预测类型,并解释了如何利用移位寄存器和PHT表进行分支预测。此外,还概述了分支预测器的创建、配置输出、状态输出以及预测和更新过程。
摘要由CSDN通过智能技术生成
支持的分支预测类型
l 二级分支预测 :也就是通过移位寄存器(一级)和PHT表(二级),在PHT表中根据2位饱和计数器分析当前分支的跳转情况。
参数:   N —— 一级入口数目
        W —— 移位寄存器的宽度
        M —— 二级入口数目
对于 Gag :三个参数值为别为:1   2^W
    Gap: 三个参数值为别为: 1   M
(只有一个移位寄存器,因此N为1,又因为当只有一个PHT表,因此,Gag中M是2^w,此时,通过移位寄存器,查找PHT表,得到分支情况;而在Gap中,不同的分支有不同的PHT表,因此需要利用分支指令的地址获取多个PHT表中的其中一个,因此M = K*2^w,其中的K应该是设定的PHT表的个数,而且,K应该是2的指数级)
    Pag:三个参数值为别为: N  W  2^W
    Pap:三个参数值为别为: N  W  M
(此时,将同时利用分支指令的地址索引移位寄存器和PHT表,如果是PAG,那么,利用分支指令地址索引多个移位寄存器,获取的值再去索引PHT表,获取跳转情况,如果是PAP,则同时利用分支指令地址索引移位寄存器和PHT表,得到跳转情况)。
  二位饱和计数预测模式
支持的预测方式是当  XX = 0X时不跳转
                 XX = 1X时跳转
                 预测不跳转
                 预测跳转
分支预测的各参数定义
1) 定义了分支预测的类型
enum bpred_class{ }
2) 定义了BTB(分支目的缓冲)表的结构
书中定义的BTB表含有三个部分:分支指令的地址,分支跳转的目的地址,以及预测结果
这儿的结构中定义了四个部分:分支指令的地址;针对当前地址的OP;如果分支跳转,那么跳转的目的地地址;以及形成BTB表的链表结构(双向链表)
3) 定义了二位饱和计数的预测结构,考虑到二级分支预测也使用了二位饱和计数器,因此利用union定义了各部分:
class -说明是二级分支预测还是bimod预测;
然后如果是bimod,那么需要定义一个计数器结构,即:bimod.size和bimod->table;
如果是二级分支预测,需要定义的类型为:寄存器的个数,PHT表的个数,移位寄存器中保存的分支历史长度;把分支历史和分支地址是否XOR的标志;指向历史表的指针和指向PHT表中的指针;
4) 定义了分支预测器:
  定义分支预测的类型,以及指向的相应的预测器元素;
  定义了BTB表的组数,以及BTB组中的相联程度,以及BTB表
  定义了返回栈:返回栈的大小,返回栈的栈顶,而返回栈也是利用了BTB的结构
  同时还定义了多个计数:方向预测的正确性(向前,向后——是否跳转)、地址预测的正确性(不仅是向前向后正确,还要有地址的正确。等等结构。
  这儿不仅预测分支指令,其中还包括了程序间调用的返回等。
5) 定义了预测更新的消息
然后是各函数的声明
1)  创建分支预测器
2)  创建了分支方向预测器
3)  分支预测器配置的输出
4)  分支预测状态的输出
5)  在数据库(sdb)中存储分支预测的信息
6)  在主要的地点存储分支信息
7)  利用分支预测器处理下一条指令
8)  预防因为前瞻执行导致的错误
9)  对分支预测器中若干元素的更新
10) 为了调试导出分支预测器的信息。
各函数的具体说明
1)  创建一个分支预测器
   看这个函数需要先看一下创建分支方向预测器的函数
   根据class,首先创建分支方向预测器(包括二级、bimod等方向预测器)
   然后继续根据分支预测器的类型class,分配返回栈
   首先看一下BTB表的结构,如果BTB表大小为0或者不是2的指数倍,不行。然后根据BTB表的组×相联 分配空间
   接下来把各项BTB结构挂接成为链表
   在分配完BTB之后,分配返回栈结构。而返回栈其实就是一个数组
2)  创建一个分支方向预测器
   首先分配一个结构大小的空间
   然后是说明当前要创建的分支方向预测器的类型(class)
   接下来是根据class按需要给其中的参数赋值:
   如果是二级分支预测:参数有:
    一级的大小(即移位寄存器有几个)
    二级的大小(即PHT表的个数)
    移位寄存器的大小(0<SIZE<=30)
    是否需要分支指令地址与移位寄存器XOR
  根据移位寄存器的大小分配合适的int空间
  根据PHT表的大小分配合适的unsigned char空间
  然后要在PHT表中初始化预测信息,这儿是初始为1-2-1-2的格式
  如果是2位饱和计数器的预测:参数都类似
3)  输出分支方向预测器的配置信息
4)  输出分支预测器的配置信息
5)  以及预测的一些信息
6)  然后是保存sdb中分支预测的信息
7)  关键地区的信息,不重要。
8)  预测一个分支的方向
  首先给的参数的选择的方向预测器的类型class和该分支的指令地址。函数处理过程中,首先让分支指令地址右移2位,与移位寄存器做与 得到当前有效的
   而l2index则是获取当前移位寄存器中的值
反正现在知道l2index是获取2位饱和计数器的值的索引的。
   这儿是考虑了如果有多个移位寄存器时的情况,因为l1size是移位寄存器的个数,不是移位寄存器的宽度。因此如果是Ga*的话,l1index=0。然后,l2index只是获取了如果有多个移位寄存器的话的其中之一。
   如果需要移位寄存器中的数和分支地址做XOR的话(也就是哪个什么很精确的分支预测法),这儿考虑了。
   是直接取得二位饱和计数器中的值,用到了一个BIMOD_HASH的宏,而在有很多2位的饱和计数器时,通过BIMOD_HASH宏获取其中的一个,可以看出,是把多个2位计数器听过HASH链表连接的。
9)  预测下一条指令的地址
注意,这儿是考虑了所有的指令,不仅仅是分支指令,即代码中的获取指令操作码的宏。
在这儿的预测中,首先是预测一下分支的方向,得到pdir1的结果。然后是对分支指令的跳转地址的预测。由于是预测条件分支,也就是说,非条件分支是不预测的。在这儿,先看一下对返回栈的处理。
        先得到返回栈的栈顶。
        然后如果指令的返回指令,即过程调用的return,那么目的地址就是栈里面的地址。
              然后如果指令是函数调用指令,那么则把返回地址值压入栈中
              然后如果两者都不是,就先查找BTB表,由于BTB可能是组相联,因此先找到组数,然后找具体的BTB入口。
如果在BTB中没有找到相应的指令地址,那么根据前面的pdir,分析是不是跳转,即只能给出方向
10)              为了防止分支预测出现错误,和推测执行情况下,程序的问题,在预测的分支处保存当前的返回栈地址
11)              对分支预测的各个参数的更新。
首先是判断是不是分支指令。
如果是分支指令,而且地址也对,那么预测正确数+1,否则是方向+1
这个函数是当分支指令执行完毕之后处理的。但不是很明白其中的stateful 预测是什么意思。针对BTB表的处理是有的更新,没有的话利用LRU替换。 

以下是我写的一个模拟器的代码中的分支预测代码

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值