RISC-V执行级设计
RISC-V 执行级设计
32 Shifter Design
RV-32IM
需要实现的移位操作不包括循环移位,只包括:逻辑左移、逻辑右移和算数右移。
若使用移位寄存器来实现移位,每个周期移位是固定的,因此需要多个周期才可以完成移位操作。
上图是一个由 4 个 D
触发器构成的简单向右移位寄存器,数据从移位寄存器的左端输入,每个触发器的内容在时钟的上升沿将数据传到下一个触发器。
在 ALU 种需要多数据进行多位移位的操作,采用移位寄存器一次只能移动移位,效率太低;桶形移位器采用组合逻辑的方式来实现同时移动多位,在效率上优势极大。因此桶形移位器常被用在于 ALU 中实现移位。
- din:待移位待输入数据
- shift: 移位待位数,有效范围为\([0, \log N-1]\)
- Left/Right: 左移或者右移
- Arith/Logic:算数右移/逻辑右移
- dout:移位后的数据
以 4bits din 的 barrlShifter 为例,其 Schematic 如下:
- 对于 Nbits 的输入数据,其需要的选择器一共有\(\log N\)层,每一层共有 N 个选择器,其中第一层选择是否移位 1bit,第二层选择是否移位 2bits,...。
- 对每一个 4 选 1 选择器,其 00 和 10 输入选择未移位后的数据;01 选择右移的数据、11 选择左移的数据。
对跳转指令的处理
EXE Stage 需要对
jalr和b-type(beq, bne, blt, bltu, bge, bgeu)做分支预测的判断,如果判断分支预测错误,EXE 需要向 IF 发送正确的 re direction_pc, taken 信号,以及冲刷流水线
| 跳转预测 | 跳转确认 | 跳转 PC 计算 | pc=pc+4 | |
|---|---|---|---|---|
| JAL | SBP | 不需要确认 | SBP | IF->ID->EXE |
| JALR | SBP | 不需要确认 | PC=alu_result & ~1 | IF->ID->EXE |
| Branch | SBP | ALU 确认跳转方向 | SBP | IF->ID->EXE |
- JAL 指令: SBP 可以 100%预测其跳转的方向和 PC,ALU 不需要做额外的计算
- JALR 指令: 当 SBP 判断
jarl指令不跳转时,SBP 100%是判断错误了,因此需要 ALU 计算 redirection_pc 和 taken - B-type 指令: SBP 不可以 100%预测跳转方向,但是可以 100%计算出重定向 PC,需要 ALU 判断跳转方向是否正确
JALR 指令
- 如果 SBP 可以预测
jalr指令,则 EXE Stage 需要 flush 掉jalr指令后续的 2 条 prefetch 指令 - 如果 SBP 不可以预测
jalr指令,则 EXE Stage 需要计算重定向 pc,并且 flush 掉jalr指令后 3 条指令
1 | else if(jalr_d_i) begin |
B-type 指令
由于 IF Stage 中,prefetch 提前 2 个 cycle 给出了取指 pc,所以当 ID 译码判别出一条 b-type 指令之后,该指令后续两条指令都 100%会被取出且送到 ID Stage;ID stage 的重定向 PC 需要 2 个 cycle 才可以取出对应的指令送到 ID 进行译码.
- sbp 预测 taken==0,alu 判断 taken==0
- sbp 预测 taken==0 的时候,ID 不会给 IF 发送重定向 rediction_pc, beq 后续第三条指令会被取入
- alu 判断 taken==0,alu 什么也不用做
- sbp 预测 taken==0,alu 判断 taken==1
- sbp 预测 taken==0 的时候,ID 不会给 IF 发送重定向 rediction_pc, beq 后续第三条指令会被取入
- alu 判断 taken==1,需要冲刷掉 prefetch 的 2 条指令和顺序取指的 1 条指令,具体表现为设置 IF/ID, ID/EXE, EXE/MEM pipeline register flush=1
- 并且 alu 需要向 IF 发送 rediction_pc 为跳转目标
- sbp 预测 taken==1,alu 判断 taken==0
- sbp 预测 taken==1 的时候,ID 会给 IF 发送重定向 rediction_pc,IF 在 2 个 cycle 之后会将 rediction_pc 对应的指令送到 ID
- alu 判断 taken==0,需要冲刷掉 rediction_pc 对应的这条指令,具体表现为设置 ID/IF pipeline register flush=1
- 并且 alu 需要向 IF 发送 rediction_pc 为顺序取指 pc
- sbp 预测 taken==1,alu 判断 taken==1
- sbp 预测 taken==1 的时候,ID 会给 IF 发送重定向 rediction_pc,IF 在 2 个 cycle 之后会将 rediction_pc 对应的指令送到 ID
- alu 判断 taken==1,说明 ID 重定向是对的,此时需要冲刷掉 b-type 指令后面 prefetch 的 2 条指令, 具体表现为设置 ID/EXE, EXE/MEM pipeline register flush=1
1 | // pipelineEXE.v |
仿真结果
jalr 存在数据依赖
1 | .text # Define beginning of text section |
期待运行过程:
counter ==1: 复位
counter ==2: pc=0x000000000
counter ==3: 从 I-Memory 取出第一条指令:
addi x5, x6, 4counter ==4: 指令
addi x5, x6 ,4进入到 ID 开始译码counter ==5: 指令
addi x1, x1, 1进入到 ID 开始译码counter ==6: 指令
nop进入到 ID 开始译码counter ==7: 指令
nop进入到 ID 开始译码counter ==8: 指令
nop进入到 ID 开始译码counter ==9: 指令
jr x2进入到 ID 开始译码, SBP 判断跳转存在数据依赖, 不跳转counter ==10:
addi x2, x2, 2进入 ID 开始译码此时
jr x2属于 EXE Stage,ALU 判断 SBP 对jr的判断错误ALU 计算 rediction_pc
counter ==11:
addi x3, x3, 2进入 ID 开始译码ALU pipeline register 输出 redirection 信号和 redirection_pc,IF 级取指 pc 变成 0x000000000
ALU pipeline register 输出 flush 信号,冲刷掉
addi x2, x2, 2,addi x3, x3, 3和addi x4, x4, 4指令
counter ==12: 按照 0x 000000000 从 I-Memory 取出指令
addi x5, x6, 4从`counter==3开始循环:addi->addi->nop->nop->nop->jr
jalr 不存在数据依赖
1 | .text # Define beginning of text section |
期待运行过程:
- counter ==1: 复位
- counter ==2: pc=0x000000000
- counter ==3: 从 I-Memory
取出第一条指令:
addi x5, x6, 4 - counter ==4: 指令
addi x5, x6 ,4进入到 ID 开始译码 - counter ==5: 指令
addi x1, x1, 1进入到 ID 开始译码 - counter ==6: 指令
nop进入到 ID 开始译码 - counter ==7: 指令
nop进入到 ID 开始译码 - counter ==8: 指令
nop进入到 ID 开始译码 - counter ==9: 指令
jr x0进入到 ID 开始译码, SBP 判断跳转不存在数据依赖, 预测跳转 - counter ==10:
addi x2, x2, 2指令进入 ID 开始译码- ID pipeline register 输出 prediction_pc, IF 取指 pc=0x00000000
jr x0进入 EXE Stage,ALU 判断 SBP 预测正确,不产生重定向 pc,产生 flush 信号
- counter ==11:
addi x3, x3, 3指令进入 ID 开始译码- EXE pipeline register 输出 flush
信号,刷新掉
addi x2, x2, 2和addi x3, x3, 3指令 - 从 I-Memory 取出指令
addi x5, x6, 4从counter==3开始循环:addi, addi, nop, nop, nop, jr
B-Type 指令仿真
sbp not taken, alu not taken
1 | .text # Define beginning of text section |
期待运行过程:addi, addi, nop, nop, nop, beq, addi, addi, addi, j
sbp not taken, alu taken
1 | .text # Define beginning of text section |
期待运行过程:addi, addi, nop, nop, nop, bne, j
sbp taken, alu not taken
1 | .text # Define beginning of text section |
期待运行过程:addi, addi, nop, nop, nop, bge, addi, addi, addi, j
sbp taken, alu taken
1 | .text # Define beginning of text section |
期待运行过程:addi, addi, nop, nop, nop, bltu, addi, addi
混合指令
1 | .text # Define beginning of text section |
期待运行过程:addi, addi, nop, nop, nop, beq, bne, j, j, j
流水线冲刷总结
冲刷 IF/ID pipeline register 的情况
jal指令由 id stage 冲刷 IF/IDjalr指令 sbp 判断 not taken,由 exe stage 产生 redirection_pc,冲刷 IF/IDb-type指令,sbp not taken, alu takenb-type指令,sbp taken, alu not taken
冲刷 ID/EXE pipeline register 的情况
jal指令由 id stage 冲刷 ID/EXEjalr指令由 exe stage 冲刷 ID/EXEb-type指令,sbp not taken, alu takenb-type指令,sbp taken, alu taken
冲刷 EXE/MEM pipeline register 的情况
jalr指令由 exe stage 冲刷 ID/EXEb-type指令,sbp not taken, alu takenb-type指令,sbp taken, alu taken
