分支预测

来源:互联网 发布:mac 查看隐藏磁盘分区 编辑:程序博客网 时间:2024/04/20 07:53

支持的分支预测类型

l         二级分支预测 :也就是通过移位寄存器(一级)和PHT表(二级),在PHT表中根据2位饱和计数器分析当前分支的跳转情况。

参数:   N —— 一级入口数目

              W —— 移位寄存器的宽度

              M —— 二级入口数目

对于       Gag :三个参数值为别为: 1   W  2^W

          Gap: 三个参数值为别为: 1   W  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表,得到跳转情况)。

l         二位饱和计数预测模式

支持的预测方式是当  XX = 0X时不跳转

                                   XX = 1X时跳转

l         预测不跳转
l         预测跳转

分支预测的各参数定义
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替换。

       

       

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替换。

       

       

分支预测的各参数定义
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替换。

       

       

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替换。

       

       

原创粉丝点击