蜂鸟E203 硬件学习-两级流水线的实现(三)

(二)EXU模块
EXU段包括指令译码,指令派发,指令发射,指令执行,内存操作,数据写回。而E203是简单的顺序单发射,顺序执行,顺序写回类型的处理器。

  • 将IFU通过IR寄存器发送给EXU的指令进行译码和派遣。
  • 通过译码出的操作数寄存器索引(Index)读取Regfile(如图中RD-Regfile)
  • 维护指令的数据相关性(如OITF)
  • 将指令派遣(Dispatch)给不同的运算单元执行(ALU、Long-Pipes、LSU、以及EAI)
  • 将指令交付(检查指令分支预测是否正确,是否产生中断和异常)
  • 将指令运算的结果写回Regfile(WB ARB)

在这里插入图片描述
(1)EXU译码模块(e203_exu_decode.v)
译码模块的输入信号来自于IR阶段,包含当前需要译码的指令,执行PC,预测结果,非对齐和存储器访问错误。
在这里插入图片描述
在这里插入图片描述
首先根据最后两个比特位判断当前译码指令是RV32还是RV16,再根据指令格式,产生不同的指令类型信息。如:寄存堆的索引和控制信号,跳转类型和所需计算的信息。
在这里插入图片描述
输出dec_info包含很多模块的控制信息,有BJP单元的控制信息,ALU单元的控制信息,CSR单元的控制信息,乘除单元的控制信息,AGU单元的控制信息。同时还要生成后面执行所需要的各类型立即数,当执行的指令为非法指令时,译码器模块还将产生各类型的异常指令异常信息。
在这里插入图片描述
(2)整数通用寄存器组(e203_exu_regfile.v)
RISC-V的整数指令都是单操作数或者两操作数指令,且蜂鸟E203属于单发射的微架构,因此Regfile模块只需要支持最多两个读端口;而蜂鸟E203的写回策略是按照顺序每次写回一条指令,因此只需要支持一个写端口。
在这里插入图片描述
除了x0,写端口逻辑将输入的结果寄存器索引和各自的寄存器号进行比较,产生写使能信号,被使能的通用寄存器将数据写入寄存器。
为减少功耗,读端口的寄存器索引信号被专门的寄存器寄存,只有再执行需要读操作数的指令时才会被加载(否则保持不变)。
通用寄存器的个数与实现方式均可配置:

  • 针对RV32I定制32个,针对RV16E定制16个
  • 通用寄存器可以用锁存器Latch实现,锁存器能够显著减少Regfile的面积与功耗,但是也会给ASIC带来一些困难;通用寄存器也可以用D Filp-Flops(DFF)实现。
    在这里插入图片描述
    (3)CSR寄存器 (e203_exu_csr.v)
    在RISC-V架构中定义了一些控制和状态寄存器,用于配置或者记录一些运行状态。可通过CSRRW,CSRRS,CSRRC,CSRRWI,CSRRSI,CSRRCI指令进行读写访问。其端口类型主要CSR的读写索引、数据、使能接口、软件,外部,定时器中断输入,遇到异常或中断时CSR所需要保留的信息输入,进入中断或从中断回复所需要的跳转地址信息,各类型中断使能输出,DEBUG寄存器相关信息。
    CSR中实现机器模式下的中断控制:
  • 使能寄存器MIE
  • 中断等待pending寄存器MIP
  • 中断程序入口地址,进入中断程序时用于保留现场的栈指针寄存器SCRATCH
  • 保存中断返回地址寄存器MEPC
  • 保存异常原因的寄存器MCAUSE
  • 保存异常信息寄存器,出现非法指令,保存非法指令;如果是异常地址,保存相关地址信息(BARADDR/MTAVL)
  • 同时内部还有一些只读寄存器,主要是为了识别内核中的一些信息,例如MISA,MVENDORID,MIMPID等寄存器。

(4)指令发射派遣(e203_exu_disp)
dispatch或者issue是一个概念,即表示指令通过译码且从寄存器组中读取操作数后派发到不同的运算单元执行的过程。
(1)根据蜂鸟的设计,指令在派发之后上一级的结果已经写入寄存器堆中,而且源操作数的读取采用异步逻辑,所以不会发射WAR(读后写)的数据依赖关系。The instruction after dispatched must have already have operand fetched, so here is no any WAR dependency happened.
(2) 蜂鸟属于单发射顺序执行顺序提交内核,所以在ALU执行之间也不会存在WAW的数据依赖关系,The ALU-instruction are dispatched and executed in-order inside ALU, so there is no any WAW dependency happened among ALU instructions( Note: LSU since its AGU is handled inside ALU, so it is treated as a ALU instruction)
对于非ALU执行有通过OIFT内部的两级循环队列进行跟踪,顺序执行,所以在非ALU指令之间也不会存在WAW问题。The non-ALU-instruction are all tracked by OITF, and must be write-back in-order, so it is like ALU in-ordered. So there is no any WAW dependency happened among non-ALU instructions.
(3)所以数据依赖性只剩下:

  • RAW:若当前待派遣的为ALU执行指令,与OITF的待写回数据发送RAW,必须等待暂停;但是由于蜂鸟是二级流水线,ALU与ALU指令不会发送RAW数据依赖,因为源操作数为异步读取,上一条执行的执行结果已经写回寄存器堆准备就绪,而非ALU指令与上一个ALU指令也不存在RAW数据依赖,但是如果是三级流水线则必须检查;
  • WAW(The WAW between ALU an non-ALU instructions):Since the ALU instruction handled by ALU may surpass non-ALU OITF instructions so we must check this.

综上,在蜂鸟的流水线,“正在派遣的指令”只可能与“尚未执行完毕的长指令之间产生RAW和WAW相关性。

Dispatch模块和ALU之间的接口采用valid-ready模式的握手信号
在这里插入图片描述
传递指令信息
在这里插入图片描述
(5)OITF(Outstanding Instructions Track FIFO)模块(e203_exu_oitf.v)
OITF模块主要用于流水线的冲突检测,维护长指令的执行队列,默认深度为2级。流水线冲突检测主要根据DISP模块输入的待派发指令的相关源操作数和目的操作寄存器与OITF执行队列中长指令的目的寄存器进行比较,判断是否发生RAW或者WAW数据依赖问题。
在这里插入图片描述
OITF本质是一个FIFO,FIFO的深度默认为2个表项;在流水线的派遣(Dispatch),每次派遣一个长指令,则会在OITF中分配一个表项(Entry),在这个表项中会存储该长指令的源操作数寄存器索引和结果寄存器索引。
在流水线的写回(write-back)点,每次按顺序写回一个长指令之后,就会将此指令在OITF中的表项去除,即从其FIFO退出,如何保证长指令能够按顺序写回,也需要借助于OITF的功能。
在这里插入图片描述
(6)ALU模块
在这里插入图片描述
蜂鸟ALU单元包含了5个功能单元,且共享一个运算数据通路:

  • 多周期乘除器(Regular-ALU)(主要负责乘法和除法的执行)
  • load/store地址生成器(Address Generation Unit,AGU)(主要负责Load、Store和A 扩展指令的地址生成)
  • 普通的ALU指令运算器(主要负责普通的ALU指令(如逻辑运算,加减法,移位等指令))
  • 分支预测指令的解析(Branch and Jump resovle,BJP)(主要负责Branch和Jump指令的结果解析和执行)
  • CSR寄存器的读写控制(CSR-CTRL)
    在这里插入图片描述
    ALU模块会根据译码模块传递的DECINFO信息,选择将运算数据派发到内部5个子执行单元,各单元执行完成后将结果通过一个并行的多路选择器进行输出。在蜂鸟中,各执行的子单元只是将派发的decinfo进行解析,生成相应的操作请求,如(alu_req_alu,bjp_req_alu)等,再将内部相应生成的操作数发送到DPATH模块进行计算,通过复用可以减小整个模块的面积;蜂鸟的乘除法操作是在相应的MULDIV模块独立完成的,但也会在DPATH模块中进行简单的处理操作。
    1、普通ALU运算(e203_exu_alu_rglr)
    通过输入的源操作数和 decinfo 信息, 解析生成相应的运算请求信号,运算类型标识信号,运算源操作数。并将相关生成数据传递给 DPATH 模块进行运算,读取运算结果,待提交写回。在这里插入图片描述
    2、访存地址生成(e203_exu_alu_lsuagu.v)
    在这里插入图片描述
    3、分支预测解析(e203_exu_alu_bjp.v)
    因为蜂鸟支持静态的指令分支预测,所以对于分支指令的预测结果需要在 EXU 段进行验证,并且将预测的结果,和真实的判断结果发送给交付模块。 BJP 模块的逻辑判断操作是使用 dpath 内部的逻辑运算硬件,不会增加的额外的硬件开销。同时 Jalr 指令的跳转执行时在 EXU 完成, BJP 模块也会计算跳转指令相应的跳转地址信息传送给提交段。在这里插入图片描述
    4、Csrctrl模块(e203_exu_alu_csrctrl.v)
    整个 CSR 模块根据判断 CSR 模块握手成功,对 CSR 模块进行读写访问操作,模块的输入信号主要就是 CSR指令所需要的源操作数,以及 decinfo 传递的执行类别信息。 输出信号主要就是 CSR 模块的索引,读写控制信号,读出/写回数据。
    5、MULDIV模块(e203_exu_alu_muldiv.v)
    MDV采用基4的Booth算法

(7)commit 提交
处理器commit常用策略:

  • commit通常为顺序判定,理论上只有前一条指令完成commit,才会轮到后一条指令。

  • 影响指令commit的因素有:
    (1)中断,异常,分支预测指令(流水线crush)
    (2)在某些指令集中存在条件码,相等于每条指令都需要判断执行,只有条件码满足才会commit,否则只会取消自己,不会对流水线有影响

  • 可以选择一个周期交付一条指令,也可以选择一个周期交付多条指令

  • 交付可以在不同的流水线位置完成

而RISC-V有两个显著的特征:

  • 没有条件码
  • 所有的运算指令都不会产生异常

所以在RISC-V架构中只需处理分支预测错误,以及中断和异常所造成后续指令的取消(蜂鸟将commit阶段放在执行阶段之后)

对于普通的单周期指令,其”交付“和”写回“在”执行“的同一周期内完成。而对于执行周期超过一个周期的多周期指令而言,”交付“同样在”执行“阶段,但是”写回“在后续的周期完成。

  • 有的长指令(如EAI协处理器指令和Load Store指令)也会在写回时产生错误异常,但是着两种异常可以当作异步异常来处理。
  • 而所有其他的常规多周期指令,RISC-V规定不会产生异常。

(8)写回
蜂鸟写回模块的数据源只有 ALU 执行结果的数据和长周期指令执行结果的数据(LONGGPWBACK 模块)。
而 ALU 指令写回只有在没有长周期指令写回时才可以被写回寄存器堆,即长周期指令的结果写回要比 ALU 指令的结果写回拥有更高的优先级。如果指令本身是不需要写回的指令,那么就不会发生提交写回申请,一旦在 EXU 段发生异常,那么执行的结果也不会被提交写回,严格保证寄存器堆中数据的正确性。

发布了54 篇原创文章 · 获赞 4 · 访问量 1021

猜你喜欢

转载自blog.csdn.net/buzhiquxiang/article/details/103693770