【学习e200处理器日志】蕃始者实繁,克缉毒董事—交付

系列文章目录

【学习e200处理器日志】执行力是关键—执行操作

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



前言

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


一、交付、取消、冲刷的简介

在处理器流水线中,交付和取消是确保高效且正确指令执行的关键机制,同时这两者的产生也会与流水线冲刷相联系。

1.1 交付(Commit)

交付是指一条指令在经过预测执行后,确认其指令是正确的,并被真正执行,进而影响处理器的状态。其发生在一个确定的阶段(通常在执行之后),当分支跳跃指令的预测被证实正确时,表示该指令能够真正的被运行,因此进行交付。因此其作用在于确保指令正确执行,允许流水线继续处理后续指令,提升处理效率。

1.2 取消(Cancel)

取消是指当一条指令的预测执行结果错误时,所有相关后续指令被终止执行。其与交付是一个相对的概念,在分支预测错误时触发,取消会导致预测执行的指令结果被丢弃,不会影响处理器状态。

1.3 冲刷

冲刷指的是处理器流水线冲刷 。 当处理器流水线需要将没有“交忖”的后续指令全都“取消”掉时,就会造成“流水线冲刷” ,就像水流一样将流水线重新冲刷干净,之后重新开始取新的指令。

二、处理器中交付的常用策略

处理器“交忖”的实现非常依赖、具体的微架构,常见的实现策略简述如下。

  1. 无论有多少个流水线,交付总是一条一条指令的运行,理论上讲只有前面的交付了后面的才可以交付。
  2. 影响指令“交付”的因素通常包括以下情形。
  • 中断,异常,分支预测指令。
    这些情形往往会造成流水线冲刷,即将后续所有的指令流都取消掉。
  • 条件码(Conditional Code)
    因此对于每条指令,只有其条件码满足条件为真才会“交付”,否则会被“取消”。
  1. 处理器通过性能架构可以选择一个周期“交付” 一条指令或者一个周期“交 付”多条指令。
  2. 在不同的微架构中,"交付”可以在不同的流水线位置完成 。
  • 在“执行”阶段进行“交付
  • 在“写回”阶段进行“交付”
  • 在重排序交付队列( Re-Order Commit Queue )中进行
    对于高性能的超标量处理器而言,往往是乱序执行乱序写回,写回往往会使用 ROB或者纯物理寄存器的方式,因此,往往会配备一个较深的重排序交付队列 用来缓存乱序执行的指令信息,并对其按序进行“交付" 。

三、E200对于交付功能的简化

主要简化方向有以下几点:

  1. 指令没有条件码,因此不会出现因为条件不行而取消的现象 。
  2. 所有的运算指令都不会产生异常。因为其在很多处理上都取消了运行中的异常,比如出发操作上的被除数为0

综上,在该处理器中只会出现两种取消的情况:

  • 分支预测指令错误预测造成的后续指令流取消。
  • 中断和异常造成的后续指令流取消。

四、E200交付功能硬件的实现

下面是E200内部交付硬件存在的位置:

需要注意对于分支预测错误的分支指令自身和遭遇了中断或者异常的指令自身而言, 仍然是属于成功“交付”的指令,因为它们自身己经被真正执行且对处理器的状态真正地产生了影响。

4.1 分支预测指令的处理

在该模块中,这些条件跳转指令需要经过“比较”运算才能确定最终是否真的需要跳转,而“比较 ”运算需由“执行”阶段的ALU完成。下面是该模块的输入输出端口:

端口名称方向功能描述
bjp_i_valid输入分支预测指令的有效性信号
bjp_i_ready输出表示接收方已准备好接收分支预测指令
bjp_i_rs1输入第一个操作数寄存器值
bjp_i_rs2输入第二个操作数寄存器值
bjp_i_imm输入立即数,用于计算分支目标地址
bjp_i_pc输入当前指令的程序计数器值
bjp_i_info输入包含分支预测相关信息
bjp_o_valid输出提交结果的有效性信号
bjp_o_ready输入表示接收方已准备好接收提交结果
bjp_o_wbck_wdat输出JAL和JALR指令的写回数据
bjp_o_wbck_err输出写回操作的错误指示
bjp_o_cmt_bjp输出表示分支预测指令已被处理
bjp_o_cmt_mret输出机器返回指令的提交确认
bjp_o_cmt_dret输出调试返回指令的提交确认
bjp_o_cmt_fencei输出FENCE.I同步指令的提交确认
bjp_o_cmt_prdt输出表示分支预测的准确性
bjp_o_cmt_rslv输出表示分支预测的最终状态
bjp_req_alu_op1输出提供给ALU的第一个操作数
bjp_req_alu_op2输出提供给ALU的第二个操作数
bjp_req_alu_cmp_eq输出等于比较操作符指示
bjp_req_alu_cmp_ne输出不等于比较操作符指示
bjp_req_alu_cmp_lt输出小于比较操作符指示
bjp_req_alu_cmp_gt输出大于比较操作符指示
bjp_req_alu_cmp_ltu输出小于无符号比较操作符指示
bjp_req_alu_cmp_gtu输出大于无符号比较操作符指示
bjp_req_alu_add输出加法操作请求指示
bjp_req_alu_cmp_res输入ALU的比较操作结果
bjp_req_alu_add_res输入ALU的加法操作结果

下面是代码中对于处理类型的判断,可以看出一共有6种类型:

  • beq (两个整数操作数等于则跳转)
  • bne (两个整数不相等则 跳转)
  • blt (第一个有符号数小于第 二 个有符号数则跳转)
  • bltu (第一个无符号数小于第二个无符号数则跳转)
  • bge (第一个有符号数大于等于第二个有符号数则跳转)
  • bgeu (第一 个无符号数大于等于第 二个无符号数则跳转)

下面是将每一个类型从info总线中提取出来。

  assign bjp_req_alu_cmp_eq  = bjp_i_info [`E203_DECINFO_BJP_BEQ  ]; 
  assign bjp_req_alu_cmp_ne  = bjp_i_info [`E203_DECINFO_BJP_BNE  ]; 
  assign bjp_req_alu_cmp_lt  = bjp_i_info [`E203_DECINFO_BJP_BLT  ]; 
  assign bjp_req_alu_cmp_gt  = bjp_i_info [`E203_DECINFO_BJP_BGT  ]; 
  assign bjp_req_alu_cmp_ltu = bjp_i_info [`E203_DECINFO_BJP_BLTU ]; 
  assign bjp_req_alu_cmp_gtu = bjp_i_info [`E203_DECINFO_BJP_BGTU ]; 

将预测和真实的跳转结果发送给支付模块。

  • 如果是无条件跳转(JMP)指令则一定会跳
  • 如果是条件跳转(Conditional Branch)则会使用ALU运算数据通路进行比较运算的结果
  assign bjp_o_cmt_prdt  = bjp_i_bprdt;
  assign bjp_o_cmt_rslv  = jump ? 1'b1 : bjp_req_alu_cmp_res;

然后在ALU模块中使用异或操作进行比较,使用加法器进行大小的比较(下面是异或的代码):

  //
  // Impelment the XOR-er
  //
  // The XOR-er will be reused to handle the XOR and compare op

  wire [`E203_XLEN-1:0] xorer_in1;
  wire [`E203_XLEN-1:0] xorer_in2;

  wire xorer_op = 
               op_xor
                   // The compare eq or ne instruction
             | (op_cmp_eq | op_cmp_ne); 

     // Make sure to use logic-gating to gateoff the 
  assign xorer_in1 = {`E203_XLEN{xorer_op}} & misc_op1;
  assign xorer_in2 = {`E203_XLEN{xorer_op}} & misc_op2;

  wire [`E203_XLEN-1:0] xorer_res = xorer_in1 ^ xorer_in2;
     // The OR and AND is too light-weight, so no need to gate off
  wire [`E203_XLEN-1:0] orer_res  = misc_op1 | misc_op2; 
  wire [`E203_XLEN-1:0] ander_res = misc_op1 & misc_op2; 

4.2 交付模块的实现

ALU在计算出是否需要跳转的结果之后,发送给“交付”模块 。根据预测以及实际的跳转结果来判断是否需要进行流水线冲刷,交付模块的输入输出端口如下所示:

端口名称方向功能描述
cmt_i_valid输入提交信息有效性信号,用于指示指令是否有效
cmt_i_ready输出提交信息接收准备信号,表示接收方准备接收指令
cmt_i_rv32输入用于指示是否是32位指令集
cmt_i_dret输入调试返回指令信号,用于表示执行的是dret指令
cmt_i_mret输入机器返回指令信号,用于表示执行的是mret指令
cmt_i_fencei输入FENCE.I指令信号,用于同步指令执行
cmt_i_bjp输入分支预测指令信号,用于表示分支指令是否预测
cmt_i_bjp_prdt输入分支预测的预测值,指示预测是true还是false
cmt_i_bjp_rslv输入分支预测的解决值,指示最终的分支预测结果
cmt_i_pc输入提交指令时的程序计数器值,用于定位指令地址
cmt_i_imm输入分支指令的立即数值,用于分支计算
csr_epc_r输入当前异常程序计数器值,用于处理中断或异常
csr_dpc_r输入当前调试程序计数器值,用于调试目的
nonalu_excpirq_flush_req_raw输入原始的异常或中断清除请求信号
brchmis_flush_ack输入分支错误清除确认信号,用于表示分支错误已清除
brchmis_flush_req输出分支错误清除请求信号,用于触发分支错误清除
brchmis_flush_add_op1输出分支错误清除操作数1,用于计算清除地址操作数
brchmis_flush_add_op2输出分支错误清除操作数2,用于计算清除地址操作数
brchmis_flush_pc输出分支错误清除程序计数器,用于指示分支错误地址
cmt_mret_ena输出机器返回启用信号,用于触发机器返回指令执行
cmt_dret_ena输出调试返回启用信号,用于触发调试返回指令执行
cmt_fencei_ena输出FENCE.I启用信号,用于同步指令的执行

下面表示的是是否需要流水线冲刷,这里比较预测值和实际值是否相等。

  wire brchmis_need_flush = (
        (cmt_i_bjp & (cmt_i_bjp_prdt ^ cmt_i_bjp_rslv)) 
	...

这里是对冲刷结果的目标地址进行分析,如果是预测了需要跳转,但是实际结果显示不需要跳转,的新PC指向此跳转指令的下一个指令(通过位数分别设置为 PC+4 以及PC+2 );如果是预测了不需要跳转,但是实际结果显示需要跳转,则重新取指的新 PC 指向此跳转指令跳转目标地址。

  assign brchmis_flush_pc = 
                          (cmt_i_fencei | (cmt_i_bjp & cmt_i_bjp_prdt)) ? (cmt_i_pc + (cmt_i_rv32 ? `E203_PC_SIZE'd4 : `E203_PC_SIZE'd2)) :
                          (cmt_i_bjp & (~cmt_i_bjp_prdt)) ? (cmt_i_pc + cmt_i_imm[`E203_PC_SIZE-1:0]) :
                          cmt_i_dret ? csr_dpc_r :
                                       csr_epc_r ;

五、多周期指令的交付

多周期指令会导致其写回要在多个周期后完成,但是交付依旧在执行阶段进行交付。

六、总结

这里我依旧放书中的原话:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值