【学习e200处理器日志】万事开头难—取指操作

文章目录

        本系列是为了记录在学习《手把手教你设计CPU——RISC-V处理器》的过程中的一些新的以及思考,同时把一些内容进行了简化便于理解,如果小伙伴对处理器感兴趣的话务必拜读一下,能够让你对处理器架构有一个大体的了解。


一、取指的特点

        处理器执行的汇编指令流示例如下图所示,指令在存储器中的地址叫指令PC。取指是处理器核按PC值对应的存储器地址从存储器读取指令的过程。取指目标是快速连续不断地从存储器取指令供处理器核执行。

        在取指操作时,有下面几个要点:

        非分支跳转指令:如图中从PC值为Ox80002150至Ox8000215e处的指令,处理器按顺序执行,指令PC逐条连续增加,取指时按顺序从存储器读取指令。

        分支跳转指令:执行分支跳转指令,若条件成立则跳转到不连续的PC值处,如从PC值为Ox80002160处的bne指令,条件满足时跳转到PC为Ox80002150处,取指时需从新PC值对应的存储器地址读取指令。

        指令编码长度:指令编码长度可不相等,有16位、32位等,32位指令对应的PC地址可能与32位地址边界不对齐,如Ox8000217a处的32位指令。

        因此,为了达到快以及连续不断的目的,再取地址的过程中,要尽量在一个周期内完成取指操作,同时如果遇到地址不对其的情况,也应该使用特殊方法实现地址拼接。


二、快速取指的方法

首先就要在SDRAM上入手,需要有一个能够快速的,点对点直接连接的SDRAM模块,这样能够实现低延时的读取数据,这里有两个方法:ITCM以及I-Cache。

2.1 ITCM

        ITCM即指令紧耦合存储器,配置容量较小(一般几十KB)、通常用SRAM的存储器存储指令,在物理上靠近处理器核且专属于它,访问延迟小(通常一个时钟周期)。其缺点是用地址区间寻址,无法像缓存映射无限大存储器空间,只能用于存放容量有限的关键程序指令 。

2.2 I-Cache

        I-Cache即指令缓存,利用软件程序的时间和空间局部性,将大容量外部指令存储器空间动态映射到有限容量的指令缓存,以最小化访问指令存储器的平均延迟。但缓存容量有限,缓存未命中时需从外部存储器存取数据,会造成较长延迟。


三、非对其指令对其操作

3.1 普通指令的非对齐

        在普通指令按顺序取指(地址连续增长)时,可用剩余缓存(Leftover Buffer)保存上次取指令后未用完的比特位供下次用。从ITCM取出32位指令字却只用到低16位,原因可能有两种:

        一是用此次低16位与上次高16位组成32位指令;

        二是指令本身就是16位宽,仅需低16位。

        未使用的16位可暂存于剩余缓存,待下个周期取出新32位指令字后,拼接成32位指令字 。

3.2 分支跳转指令的非对齐

        对于分支跳转指令,若跳转目标地址与32位地址边界不对齐,但是剩余缓存仅在按顺序取指时才能发挥作用。常见解决方法是用多体(Bank)化的SRAM存储指令,如采用奇偶交错方式,用两块32位宽的SRAM交错存储,两个连续的32位指令字会分别存于不同SRAM。


四、分支指令的处理

4.1 无条件跳转/分支

        该指令是一定会发生跳转的指令,分为直接跳转间接跳转。直接跳转是指令有jal。间接跳转是jalr,起两者的区别是后者有两个操作数。用于从一个操作数索引的地址进行跳转。其中RISC-V为了简化取指,只保留了这两个无条件跳转指令。

4.2 有条件跳转/分支

        该指令同样也分为间接以及直接操作,与无条件的特点相同。其中有条件与无条件的区别在于分支跳转有6个条件指令。比如比大小之类的,需要处理完后符合条件才能跳转。


五、分支预测        

        为了能够让处理器快速运转,引入了一个分支预测的概念,相当于预判下一步是否要跳转,方便提前做好准备。预测也分为静态预测和动态预测。

5.1 静态预测

        静态预测是简单的“方向”预测方法,不依赖指令执行和历史信息,仅靠分支指令自身信息预测。

        简单的静态预测总认为分支指令不跳转(相当于完全不预测),取指单元顺取分支指令下一条。执行阶段发现需跳转则冲刷流水线重新取指。为弥补性能损失,很多早期RISC架构采用“分支延迟槽”,即分支指令后紧跟的一条或多条指令不受跳转影响,所在位置称分支延迟槽,其中指令不会因冲刷流水线被丢弃重取。但是随着分支预测计数的成熟,分支延迟槽带来的便捷变得微不足道,因此这里舍弃了该方法。

        另一种常见静态预测方法,对向后跳转(目标PC值小于当前分支指令PC值)预测为跳,向前跳转预测为不跳。依据是实际汇编程序中向后分支跳转多于向前跳转,如for循环生成的汇编指令常用向后跳转分支指令 。

5.2 动态预测

        动态预测依赖已执行指令的历史信息和分支指令自身信息综合进行“方向”预测。

        一比特饱和计数器:最简单的分支“方向”动态预测器,每次分支指令执行后用其记录上次“方向”,下次预测永远采用上次记录的“方向”,结构简单但预测精度不如“两比特饱和计数器”。

        两比特饱和计数器:最常见的分支“方向”动态预测器,执行分支指令后按特定状态机转换。根据状态预测跳转方向,预测出错则更改状态机状态,因有4个状态具有切换缓冲,在复杂程序流中预测精度更高 。但处理器指令流中有众多不同分支指令,为每条指令分配专有“两比特饱和计数器”硬件资源开销大,只能用有限个组成表格,通过某种寻址方式索引表项的计数器,由此会出现不同分支指令指向同一表项的别名重合问题 。

        这里有两个概念需要注意一下:

        表格:是由有限个“两比特饱和计数器”组织而成的数据结构。将有限数量的“两比特饱和计数器”组合成一个表格形式,用于对众多分支指令进行预测,每条分支指令通过某种寻址方式来索引表格中的某个表项的“两比特饱和计数器” 以实现预测 。

        别名:指的是别名重合(Aliasing)现象。因为表格中的表项数目有限,不同的分支指令在通过寻址方式索引表格中的“两比特饱和计数器”时,很多不同的分支指令会不可避免地指向同样的表项,这种情况就被称为别名重合,这里的“别名” 强调的是不同分支指令对应到了同一个“两比特饱和计数器”表项的现象 。

        目前一般使用各种不同的动态分支预测算法,通俗地讲就是通过采用不同的表格组织方式(控制表格大小)和索引方式(防止别名重合),来提供更高的预测精准率。有下面几种算法:

        单级预测器是将有限个“两比特饱和计数器”直接组织成一维的预测器表格,直接用PC值的一部分进行索引。“单级”指索引仅采用指令本身的PC值。此方法简单易行,但索引机制简单,分支预测精度不如两级预测器 。

        两级预测器也叫相关预测器,将有限个“两比特饱和计数器”组织成PHT(模式历史表),用分支跳转历史作为PHT索引,如用n个比特记录历史可索引2的n次方个表项。分支历史分局部历史(每个分支指令自身跳转历史)和全局历史(所有分支指令跳转历史)。(这一部分了解就行)

5.3 预测地址

        确定了预测的方向,接下来就是预测跳转的地址。因为在处理器中,解码、确定分支类型以及确定分支跳转地址是不可能在一个周期完成的,为了提高速度需要对分支地址进行预测。下面有三种方法

        BTB(分支目标缓存):用有限容量缓存保存近期执行的分支指令PC值及其跳转目标地址,取指时对比PC值,匹配则预测为分支指令并采用对应跳转地址。

        RAS(返回地址堆栈):用有限容量硬件堆栈(“先进后出”结构)存储函数调用返回地址。函数调用时将当前PC值压入堆栈,函数返回时弹出,为返回的分支跳转指令预测目标地址。因为在处理器中跳转和返回几乎是成对出现的,在跳转实记录当前的地址,在下一次跳转大概率就是调转回此地址。

        在RISC-V架构中对此有明确规定,如使用jal指令且目标寄存器索引值rd等于x1或者x5时需进行RAS压栈;使用jalr指令时,根据所使用寄存器值(rs1、rd)不同,明确规定了相应的RAS压栈或出栈行为,其规则如下所示。这里相当于明确指定了什么情况下是函数调用,什么情况下是跳转回去,该方法最大程度提高RAS的预测准确性。

        Indirect BTB(间接BTB):专为间接跳转/分支指令设计,类似普通BTB但存储更多历史目标地址,通过高级索引方法匹配,结合了BTB和动态两级预测器技术。假设你每天下班回家的路线(间接跳转)可能变化(有时去超市,有时去健身房):如果某天发现“周三下班后常去健身房”,Indirect BTB 会记录这一模式。下次遇到“周三下班”,直接预测去健身房。


六、RISC-V取指的特点

        为提高代码密度,RISC-V定义了可选的压缩指令子集,支持该子集会出现32位和16位指令混合的情况。所有RISC-V指令编码的最低几位专门用于编码指令长度。把指令长度指示码置于最低位,方便取指逻辑在顺序取指时快速译码指令长度,极大简化硬件设计,如取到16位指令字时就能判断指令长度,无需等另一半16位取到再译码 。


七、E200取指模块的实现

        下面这张图表示取指模块在e200系统中的位置,在下面的图就是取指系统的细分:

        E200 IFU架构主要功能包括对取回地址进行简单译码(Mini-Decode)、简单分支预测(Simple-BPU)、生成取指的PC(PC生成)、根据PC地址访问ITCM(BIU地址判断和ICB总线控制)

        然后是每一个部分的功能讲解:Mini_Decode部分,用于判断指令的简单性质,比如指令长度以及指令是否为跳转指令;Simple_BPU部分,该模块主要用于分支预测;PC生成部分主要用于生成下一个PC取值的地址,由分支预测以及编码器等共同控制;地址判断和ICB总线控制部分,用于设计IFU和ITCM以及BIU均使用的ICB接口,并且包含非对其访问逻辑功能。

7.1 Mini_Decode

        这模块没什么好说的,需要注意的一点是该模块通过例化调用完整的Decode模块,并将其不相关的输入信号接零、输出信号悬空,让综合工具优化掉无关逻辑,形成Mini-Decode。只输出了其指令长度以及一些分支跳转类型的信息。

7.2 Simple_BPU

        Simple_BPU部分实现逻辑细节:

JAL指令(无条件跳转)

        目标地址计算:JAL指令的目标地址是基于当前程序计数器(PC)和指令中的偏移量计算得出的。

JALR指令(寄存器间接跳转)

        rs1 == x0的情况:目标地址是寄存器x0的值加上偏移量。

        rs1 == x1的情况:如果寄存器x1没有未完成的依赖(即没有在执行中的指令使用x1作为目的寄存器),则直接使用x1的值计算目标地址。

        依赖检查:OTIF空,操作转发队列(OTIF)为空,说明没有在飞的操作需要x1的值;IR无x1作为目的寄存器:当前指令寄存器(IR)中的指令没有将x1作为目的寄存器,说明x1的值不会被当前指令修改。依赖存在时:如果x1有未完成的依赖,BPU会停止指令获取单元(IFU)直到依赖清除。

        rs1 != x0或x1的情况:由于目标地址需要从寄存器xN中获取,而xN可能有未完成的操作,因此需要等待执行单元(EXU)处理完成。这会导致指令获取停顿,造成一个时钟周期的性能损失。

Bxxx指令(条件分支)

        向后跳转(例如循环体):预测为预取(taken),如果分支指令是向后跳转(例如循环体),BPU会预测分支将被预取,从而提前获取目标地址的指令。目标地址基于当前PC和偏移量计算得出。

        向前跳转(例如条件分支进入新的代码路径):预测为不预取(not-taken),如果分支指令是向前跳转(例如条件分支进入新的代码路径),BPU会预测分支不被预取,继续顺序执行当前路径的指令。同样基于当前PC和偏移量计算得出。

7.3 PC生成

PC生成逻辑负责产生下一个待取指令的PC,不同情形处理方式不同:

reset后首次取指:使用蜂鸟E200 CPU - TOP层输入信号pc_rstvec指示的值作为首次取指PC,用户可在SoC层集成时赋值控制复位默认值。

顺序取指:16位指令,下一条指令PC为当前PC + 2;32位指令,下一条指令PC为当前PC + 4 。

分支指令:采用Simple - BPU预测的跳转目标地址。

来自EXU的流水线冲刷:使用EXU送来的新PC 。

7.4 BIU地址判断和ICB总线控制

        ICB总线在后续章节会给出,这里介绍一下地址处理的几个细节:

        利用SRAM的Hold-up特点(上次访问后输出值会保持到下次读写),因为ITCM宽度64位,在顺序取指时,IFU每次取32位,可能连续在同一Lane访问,利用Hold-up特性可避免重复打开SRAM,节省动态功耗。

        顺序取指且32位指令非对齐跨越64位边界时,将前次SRAM输出的高16位存入剩余缓存,发起新访问后与新返回的低16位拼接成32位指令,一个周期可完成,无性能损失。

        非顺序取指且地址非对齐跨越64位边界时,需连续两次访问ITCM,第一次读回的高16位存入剩余缓存,与第二次读回的低16位拼接成32位指令,需两个周期,会造成一个周期性能损失。但是这点性能无关紧要。

7.5 ITCM

        使用ITCM来作为指令的存储区域,可以做到快速的取指,其次峰鸟E200 IFU能够在一个周期内连贯完成指令读取、部分译码、分支预测以及生成下一条待取指令的PC等操作,理论上能够实现连续不断 。

7.6 BIU

        如果取指令的地址不落 ITCM所在的区间,IFU则会通过BIU访问外部的存储器,这个和ITCM在后续的章节会介绍。


总结

这里我直接放书中的原话了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值