cva6架构研究(Frontend-issue)

  • 总体设计

Ariane处理器是一个开源的顺序单发射64位处理器(也可以配置成32位处理器),实现了RV64GC指令集。它有六级流水:

PC Generation

Instruction Fetch

Instruction Decode

Issue Stage

Execute Stage

Commit Stage

 

图 1 Ariane内核结构

其中,前两级流水被称为处理器的前端,后四级流水被称为处理器的后端。Ariane处理器的目标是在合理的速度和IPCInstruction per Cycle)下,运行一个完整的操作系统。为了达到期望的速度,cva6内核采用了6级流水线的设计。在访问命中的情况下,IMEML1 ICache的访问延时为1 cycleDMEML1 DCache的访问延时为3 cycle.

  • Frontend

2.1 PC Generation

2.1.1 PC生成

PC程序计数器,负责产生下一个程序地址,进行逻辑寻址,如果逻辑到物理的映射改变了,指令应该刷新流水线和TLBTLB是缓存PTEcachePTE是用于存储物理存储器和虚拟存储器映射的多级页表中的表项。

Next PC的来源如下:

(0)Default assignment/replay instruction,

(1)Branch Predict taken,分支预测

如果BHT和BTB在一个正确的PC上预测出了一个分支,PC Gen会将下一个 PC值设置为上述分支预测到的地址,并通知IF阶段。在后续的不同阶段都需要通知 (例如在对预测失败进行纠正时)。

(2)Control flow change request (misprediction),控制流变更请求(预测失败)

如果分支预测器预测错误,就会发生控制流更改请求。预测失败可能是预测错误,也可能出现分支无法识别的情况,需要清洗流水线,获取正确的地址。

(3) Return from environment call,从环境呼叫返回

(4) Exception/Interrupt,异常/中断

如果发生异常(或中断),PC Gen将生成下一个PC作为traps向量基地址的一部分。根据处理器的工作模式(ariane目前不支持cva6用户模式异常),traps向量基地址可能会不同。CSR单元会找出traps的位置,并计算出正确的地址传输给PC Gen

(5)Pipeline Flush because of CSR side effects,CSR段异常进行流水线冲洗

(6)Debug

Debug优先级最高,因为它可以中断任何控制流请求。它也是控制流更改的唯一来源,实际上可以同时发生任何其他强制控制流更改。调试单元报告更改PC的请求以及更改CPUPC

 

图 2 PC生成

2.1.2 Branch Prediction

分支预测之所以能够实现,是由分支指令的特性决定的,因为分支预测本质上是对分支指令的结果进行预测,而在一般的RISC指令集中,

分支指令包含两个要素:

1、方向,对于一个分支指令来说,它的方向只可能有两种,一种是发生跳转(taken),另一种是不发生跳转(not taken)。

2、目标地址,目标地址在指令中有两种存在形式。

1PC relative,也称做直接跳转(direct)。在指令中直接以立即数的形式给出一个相对于PC的偏移值(offset),当前分支指令的PC值(或者分支指令的下一条指令的PC值)加上这个偏移值就可以得到分支指令的目标地址。

2Absolute,也称做间接跳转(indirect)。分支指令的目标地址来自于一个通用寄存器的值,这个寄存器的编号由指令给出。由于寄存器的值是会经常变化的,因此这种类型的分支指令很难对目标地址进行预测,但程序当中大部分间接跳转的分支指令都是用来调用子程序的Call/Return类型的指令,而这种类型的指令由于有着很强的规律性,是容易被预测的。

2.1.2.1分支历史表

PHT(Pattern History Table,分支历史表)(ariane这个部件称为BHT(Branch History Table))是一个包含部分PC值对应的两位饱和计数器的值的表格,一般是在流水线的提交(Commit)阶段更新,即在分支指令要离开流水线的时候进行更新。所有的分支预测数据结构都驻留PHT中。它用PC的适当位数索引,包含关于预测目标地址的信息,以及可配置宽度饱和计数器(saturation counter)(默认为2)的结果,其预测结果用于后续阶段的跳转(或不跳转)。 compress字段用于16位压缩指令集实现分支时候使用。

 

图 3 PHT预测原理图

 

图 4 PHT电路链接关系

2.1.2.2分支指令的方向预测

两位饱和计数器是一种分支方向预测的实现方法,根据前两次的执行结构预测本次的方向,是一种很简单的分支预测方法。

 

图 5 二位饱和计数器

在图中,PHT是一个表格,在其中存放着所有PC值所对应的两位饱和计数器的值,例如图4.10中使用PC值当中的k位来寻址PHT,因此PHT的大小就是2^k x 2bit。

 

图 6 PHT方向预测结构图

对于分支指令有规律的(如TNTNTN),可以使用一个分支历史寄存器(Branch History Register,BHR)来记录一条分支指令在过去的历史状态进行分支预测。其他分支方向预测的实现方式还有基于全局历史的分支预测、竞争的分支预测。

2.1.2.2分支指令的目标地址预测

对于直接跳转(PC-relative)类型的分支指令来说,它的目标地址有两种情况:

(1)不发生跳转,目标地址 = 当前分支指令的PC值 + Sizeof(fetch group)。

(2)发生跳转,目标地址 = 当前分支指令的PC值 + Sign_extend(offset)。

BTB

由于分支预测是基于PC值进行的,不可能对每一个PC值都记录下它的目标地址,所以一般都使用Cache的形式,使多个PC值共用一个空间来存储目标地址,这个Cache称为BTB(Branch Target Buffer,分支目标缓冲区),图表示了采用直接映射结构的BTB的示意图。

 

图 7 BTB预测原理图

图 8 BTB电路链接关系

多个PC共用一个空间来存储目标地址,会用Tag来区分。除了提供预测结果外,BTB还会更新其错误预测的信息。

寻址位数Index为2,取PC[3:2]。

 Tag位数32-2-2=28位。

分支结果和分支目标地址在相同的运算单元中计算,因此对目标地址的错误预测与对分支方向的错误预测代价相当。在PHT中,多个PC共用会出现干扰,这种情况称为别名(aliasing)。为了防止别名发生(或者至少使它更不可能发生),需要使用一些标记位,并在每次访问时进行比较。 tag、index和offset三者组合就可以确定一个唯一的地址了。因此,当我们根据地址中index位找到cache line后,取出当前cache line对应的tag,然后和地址中的tag进行比较,如果相等,这说明cache命中。如果不相等,说明当前cache line存储的是其它地址的数据,这就是cache缺失(cache miss)。

对于间接跳转。CALL指令一般用于调用子程序。一条CALL指令调用的子程序是固定的,也就是说一条CALL指令对应的目标地址是固定的,因此可以使用BTB对CALL指令的目标地址进行预测,如图4.38所示给出了一个例子。

图 9 printf指令调用

但是对于一个子函数来说,例如printf函数,有很多地方都可以调用它,因此printf函数执行到最后一条Return指令的时候,返回的地方是会变化的。正因为Return指令的目标地址是不确定的,因此无法使用BTB对它的目标地址进行预测,但是可以看出,Return指令的目标地址总是等于最近一次执行的CALL指令的下一条指令的地址,如图所示。

  图 10 return/cell指令调用

根据Return指令的上述特点,可以设计一个存储器,保存最近执行的CALL指令的下一条指令的地址,这个存储器是后进先出的,称之为RAS(Return Address Stack)

RAS(Return Address Stack,返回地址堆栈),在间接跳转指令中,大部分都是对子程序调用的CALL/Return指令,在这部分的分支预测中,子程序的嵌套使用RAS进行存储和返回。

2.2 Instruction Fetch

2.2.1取指

指令取指阶段IF从PC Gen阶段获取其信息。此信息包括关于分支预测的信息,当前PC值,以及该请求是否有效(valid)等。IF阶段请求MMUPC的基础上进行虚拟地址到物理地址的转换,并调用I$(指令缓存,ICache)接口。

IF阶段向I$接口发出信号,表示它想要对内存进行取指请求。根据I$的状态,可以允许或不允许。如果允许,指令会被放入缓存FIFO中。cva6允许I$中最多有2件未完成的事务,如果多于2件,IF阶段则不会向PC Gen发送新的请求。

2.2.2 Instruction Scan

该子模块旨在对指令类型做一个初步的判断,是纯组合逻辑。

图 12 instr_scan代码接口

以instr_scan代码为例进行说明,输入为指令,输出是对指令类型的判断:

代码路径:core/frontend/instr_scan.sv

 

2.2.3 Instruction Queue

该队列用于处理器前端的IF阶段和后端的ID阶段之间的指令通信,解耦合(使得两者关联性下降),将指令前端和处理器后端分开。

由于压缩指令的存在,取指可能最多存在两条指令(两个完整16位指令)。同时该队列还实现了一个并串转换,使得后端只处理一条指令,与压缩指令相关。指令队列中内部有两个FIFOfifo_instr用来存指令,fifo_address用来存分支预测的地址。该指令队列用了Replay机制。

Replay机制:如果取指之后指令队列满了,没有成功放入队列中,那么处理器的IF阶段会选择重新取指。

queue深度可以从02**32任意取值,cva6中设置深度为4,数据宽度默认32bitaddress queue数据宽度为64bit

三、Instruction Decode

指令解码是处理器后端的第一个流水线阶段。它的主要目的是从IF阶段获得的数据流中提取指令,解码后发送到Issue(发射)阶段。

随着压缩指令的引入,ID阶段变得更加复杂:它必须搜索传入的数据流寻找潜在的指令,重新对齐,并(在压缩指令的情况下)解压缩它们。此外,我们将在此阶段结束时知道被解码的指令是否为分支指令,它将此信息送到Issue(发射)阶段。

3.1 Instruction Re-aligner

这个模块的输入是32-bit对齐的cache block,其功能是从中提取出指令。由于cva6支持压缩指令集,所以一次输入中最多可以包含两条指令:

图 13 5种指令情况

如上图所示,一个cache block内的指令有可能出现以下5种情况:

1、输入的cache block是一条完整的32bit指令。

2、输入的cache block的位域[31:16]是一条32bit指令的低16bit;位域[15:0]是一条32bit指令的高16bit。

3、输入的cache block的位域[31:16]是一条32bit指令的低16bit;位域[15:0]是一条完整的16bit指令。

4、输入的cache block的位域[31:16]是一条完整的16bit指令;位域[15:0]是一条32bit指令的高16bit。

5、输入的cache block的位域[31:16]是一条完整的16bit指令;位域[15:0]是一条完整的16bit指令。

如果上一条是Branch指令且发生了跳转(taken),我们有可能需要从一个非32-bit对齐(但是16-bit对齐)的地址进行取指。

 

图 14 连续指令出现的4种情况

如上所述,指令重对齐模块检查传入的数据流是否压缩指令。压缩指令的最后一位不等于11,而普通32位指令的最后两位为11。解码阶段的复杂性主要来自:压缩指令会使普通指令32bit不对齐(16bit是对齐的)。这可能在指令完全解码之前进行两次内存访问,因此,我们需要确保指令FIFO有足够的空间来保存指令的第二部分。因此,指令重对齐模块需要跟踪前一条指令是未对齐的还是被压缩的,以正确地决定如何处理即将到来的指令。

在cva6代码中,重排列模块被放在Frontend。

图 15 instr_re_aligner链接关系

 

3.2 Compressed Decoder

对于压缩指令集,还需要解压所有的压缩指令。通过组合电路来完成,该电路将一个16位的压缩指令扩展到其等效的32位。所有的压缩指令都有一个等价的32位指令

图 16 compressed decode接口

compressed_decoder:检查它们是否被压缩,如果被压缩则进行扩展

完全组合逻辑,根据instr[1:0]直接判断是否为压缩指令并进行扩展输出。对应压缩指令在文件riscv_pkg.sv

      

3.3 Decoder

解码器会接收原始指令数据,或接收16位对应的未压缩等价指令(该模块会根据情况对指令进行保存,同样会接收16位压缩指令,用于保存),并解码它们。它将原始比特转换为Ariane中最基本的控制结构,即scoreboard 记分牌):

PC:指令PC

FU:使用功能单元

OP:各功能单元要执行的操作

RS1:注册源地址1

RS2:注册源地址2

RD:注册目的地址

Result:对于未完成的指令,该字段还保存立即指令

Valid:结果有效

Use I Immediate: 我们应该使用立即操作符作为操作数b吗?

Use Z Immediate:将立即数z作为操作数a

Use PC:如果我们需要使用PC作为操作数a,则异常中设置PC

Exception:发生异常

Branch predict:分支预测scoreboard数据结构

Is compressed:表示压缩指令,如果需要进行跳转,则在提交阶段需要此信息,例如:+4,+2

图 17 Decoder链接关系

四、Issue Stage

Issue(发射)阶段的目的是接收解码后的指令并将其发送给各个功能单元(FU,Functional Unit)。此外,Issue(发射)阶段跟踪所有发出的指令、功能单元状态并接收来自执行阶段的回写数据。

 

图 18 Issue链接关系

Issue(发射)阶段包含CPU的寄存器文件。通过使用scoreboard,记录发出了哪些指令、指令所在的功能单元以及指令回写到哪个寄存器。如果将执行大致分为四步:发射、读源操作数、执行、写回目的操作数。那么Issue stage负责处理其中三步:发射、读源操作数、写回目的操作数。

 

图 19 Issue包含的3个阶段

图 20 re_name--Scoreboard--issue_read_operands

4.1 Issue

当Issue(发射)阶段得到一个新的解码指令时,它检查所需的功能单元是否空闲或将在下一个周期中空闲。然后它检查它的源操作数是否可用、当前有无其他被发射的指令会写入相同的目的寄存器,即检查是否存在:

信号名称

信号功能描述

结构冒险

对应的FU是否空闲、或者是否即将在下个cycle空闲。

RAW数据冒险

源操作数是否已经准备好了

WAW数据冒险

是否没有其他正在发射的指令会写回到同一个目的寄存器

控制冒险

Issue stage追踪指令以保证没有发射未解决的分支指令。此处逻辑在目前的硬件上需要简化。我们一次只允许执行一条分支指令,这种做法使得在发生分支误预测的时候能很容易地恢复。

ariane处理器的寄存器重命名尚在开发中,虽然REG_ADDR_SIZE = 6,但实际上最高位恒为0,相当于只有32个物理寄存器。

Issue Stage与多个FU独立地通信。具体来说,Issue Stage需要监控FUs的valid、ready信号,无条件地接受并存储FU的写回的数据。指令按顺序发射,每个FUs的写回可能是乱序的。因此,需要为不同的问题阶段分配ID(称为事务ID)。ID类似于记分牌将存储这条指令的结果的唯一位置。ID(有足够的位来唯一地表示记分牌中的每个槽,与其他数据一起传递给相应的功能单元。

这种方案允许FUs的操作完全独立于发射逻辑。它们可以以不同的顺序返回不同的事务。只要在结果旁边显示了对应的ID,Scoreboard就知道把它们放在哪里。这种方案甚至允许FUs缓冲并完全乱序地处理对它们有意义的结果。(与寄存器重命名操作有关)rename代码目前未完善。

4.2 Read Operands

读操作数和发射指令在同一个流水级进行,但可以把他们抽象成两个不同阶段。Scoreboard知道哪个寄存器会被写入,它可以处理操作数之间的转发路径(forwarding path)。Cva6的设计目标是使两条指令之间没有气泡。操作数会来自于寄存器,或者转发路径(Scoreboard通过查询“rd_clobber”信号可以处理forwarding path)。

 

操作数选择逻辑是经典的优先级选择,scoreboard的结果优先于寄存器,因为功能单元总是产生最新的结果。为了获得正确的寄存器值,我们需要轮询Scoreboard的两个源操作数。在read operands中定义了逻辑寄存器,目前使用32个(有支持64个逻辑寄存器的结构):

GPR(通用逻辑寄存器):

位宽:64

读口:2

写口:2

x0固定为0

FPR(浮点逻辑寄存器):

位宽:64

读口:3(针对混合乘加指令)

写口:2

4.3 Scoreboard

Scoreboard通过FIFO实现,具有一个读端口和一个写端口,具有有效和确认信号。如果Scoreboard尚未满,指令解码将直接写入Scoreboard。Commit(提交)阶段查找已经完成的指令并更新体系结构状态。这意味着发生异常(exception),会更新寄存器或CSR文件。scoreboard 会在流水线中进一步进行增量处理,目的是跟踪所有解码、发出和提交的指令。scoreboard 条目控制操作数的选择、分派和执行。

 

图 21 scoreboard-commit

 

图 22 scoreboard-Issue

图 23 scoreboard的更新

 

图 24 scoreboard的输出信号

目前学到这里了,在知乎上也有一个很心细的博主,在我学习期间给了我很大帮助,里面的内容包含更多细节和基础知识:Ariane处理器源码剖析(一):Introduction - 知乎

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
The RISC-V CVA6 core is a compact, low-power processor core that is designed to be used in microcontrollers and other embedded systems. It is based on the RISC-V ISA (Instruction Set Architecture), which is an open, royalty-free standard that allows anyone to design and implement their own processor cores. The CVA6 core is designed to be highly configurable, allowing users to customize it to meet their specific needs. It supports the RV32I base instruction set, as well as a number of optional extensions, including the M (integer multiplication and division) extension, the F (single-precision floating-point) extension, and the D (double-precision floating-point) extension. One of the key features of the CVA6 core is its low power consumption. It is designed to be used in battery-powered devices and other low-power applications, and it includes a number of power-saving features, such as dynamic voltage and frequency scaling, that help to reduce power consumption even further. The CVA6 core is also highly scalable, making it suitable for use in a wide range of applications. It can be used as a standalone processor in a microcontroller or embedded system, or it can be integrated into a larger system-on-chip (SoC) design. Overall, the RISC-V CVA6 core is an excellent choice for anyone looking for a low-power, highly configurable processor core for use in microcontrollers and other embedded systems. Its open, royalty-free design makes it an attractive alternative to proprietary processor architectures, and its high level of configurability makes it easy to customize to meet specific application requirements.

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值