From 7196d3307433c1c9245dd8f1a7675441ea29189b Mon Sep 17 00:00:00 2001 From: liangkangnan Date: Fri, 11 Jun 2021 09:44:26 +0800 Subject: [PATCH] rtl: add static branch predict unit Signed-off-by: liangkangnan --- rtl.flist | 1 + rtl/core/bpu.sv | 62 ++++++++++++++++++++++++++++++++++++++++ rtl/core/exu.sv | 23 ++++++++++++--- rtl/core/exu_dispatch.sv | 2 ++ rtl/core/ifu.sv | 13 +++++++++ 5 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 rtl/core/bpu.sv diff --git a/rtl.flist b/rtl.flist index 41f9b22..8c74c7a 100644 --- a/rtl.flist +++ b/rtl.flist @@ -21,6 +21,7 @@ ../rtl/core/rst_gen.sv ../rtl/core/tinyriscv_core.sv ../rtl/core/tracer.sv +../rtl/core/bpu.sv ../rtl/debug/jtag_def.sv ../rtl/debug/jtag_tap.sv diff --git a/rtl/core/bpu.sv b/rtl/core/bpu.sv new file mode 100644 index 0000000..00d4c6c --- /dev/null +++ b/rtl/core/bpu.sv @@ -0,0 +1,62 @@ + /* + Copyright 2021 Blue Liang, liangkangnan@163.com + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +`include "defines.sv" + +// 静态分支预测模块 +module bpu( + + input wire clk, + input wire rst_n, + + input wire[31:0] inst_i, + input wire inst_valid_i, + input wire[31:0] pc_i, + + output wire prdt_taken_o, + output wire[31:0] prdt_addr_o + + ); + + wire[6:0] opcode = inst_i[6:0]; + + wire opcode_1100011 = (opcode == 7'b1100011); + wire opcode_1101111 = (opcode == 7'b1101111); + + wire inst_type_branch = opcode_1100011; + wire inst_jal = opcode_1101111; + + wire[31:0] inst_b_type_imm = {{20{inst_i[31]}}, inst_i[7], inst_i[30:25], inst_i[11:8], 1'b0}; + wire[31:0] inst_j_type_imm = {{12{inst_i[31]}}, inst_i[19:12], inst_i[20], inst_i[30:21], 1'b0}; + + wire prdt_taken = (inst_type_branch & inst_b_type_imm[31]) | inst_jal; + + reg[31:0] prdt_imm; + + always @ (*) begin + prdt_imm = inst_b_type_imm; + + case (1'b1) + inst_type_branch: prdt_imm = inst_b_type_imm; + inst_jal: prdt_imm = inst_j_type_imm; + default: ; + endcase + end + + assign prdt_taken_o = inst_valid_i ? prdt_taken : 1'b0; + assign prdt_addr_o = pc_i + prdt_imm; + +endmodule diff --git a/rtl/core/exu.sv b/rtl/core/exu.sv index 0cce2f7..e5ba6b1 100644 --- a/rtl/core/exu.sv +++ b/rtl/core/exu.sv @@ -77,6 +77,8 @@ module exu( ); + wire[31:0] next_pc = dec_pc_i + 4'h4; + // dispatch to ALU wire[31:0] alu_op1_o; wire[31:0] alu_op2_o; @@ -106,6 +108,7 @@ module exu( wire bjp_op_bltu_o; wire bjp_op_bge_o; wire bjp_op_bgeu_o; + wire bjp_op_jalr_o; // dispatch to MULDIV wire req_muldiv_o; wire[31:0] muldiv_op1_o; @@ -184,6 +187,7 @@ module exu( .bjp_op_bltu_o(bjp_op_bltu_o), .bjp_op_bge_o(bjp_op_bge_o), .bjp_op_bgeu_o(bjp_op_bgeu_o), + .bjp_op_jalr_o(bjp_op_jalr_o), // dispatch to MULDIV .req_muldiv_o(req_muldiv_o), .muldiv_op1_o(muldiv_op1_o), @@ -357,7 +361,7 @@ module exu( .csr_reg_wdata_i(csr_rdata_i), .req_bjp_i(req_bjp_o), .bjp_reg_we_i(bjp_op_jump_o), - .bjp_reg_wdata_i(next_pc_i), + .bjp_reg_wdata_i(next_pc), .bjp_reg_waddr_i(rd_waddr_i), .rd_we_i(rd_we_i), .rd_waddr_i(rd_waddr_i), @@ -369,10 +373,21 @@ module exu( assign reg_we_o = commit_reg_we_o & (~int_stall_i); - wire inst_jump = bjp_cmp_res_o | bjp_op_jump_o | sys_op_fence_o; - assign jump_flag_o = (inst_jump & (~int_stall_i)) | int_assert_i; + // jal + wire prdt_taken = ((~bjp_op_jalr_o) & bjp_op_jump_o) | + // bxx & imm[31] + (req_bjp_o & (~bjp_op_jump_o) & dec_imm_i[31]); + + // bxx分支预测错误 + wire prdt_taken_error = prdt_taken & (~bjp_cmp_res_o) & req_bjp_o & (~bjp_op_jump_o); + + wire inst_jump = (bjp_cmp_res_o & (~prdt_taken)) | + (bjp_op_jump_o & (~prdt_taken)) | + sys_op_fence_o; + assign jump_flag_o = ((inst_jump | prdt_taken_error) & (~int_stall_i)) | int_assert_i; assign jump_addr_o = int_assert_i? int_addr_i: - sys_op_fence_o? next_pc_i: + sys_op_fence_o? next_pc: + prdt_taken_error? next_pc: bjp_res_o; assign hold_flag_o = muldiv_stall_o | mem_stall_o; diff --git a/rtl/core/exu_dispatch.sv b/rtl/core/exu_dispatch.sv index 8f7192d..5b6cc8d 100644 --- a/rtl/core/exu_dispatch.sv +++ b/rtl/core/exu_dispatch.sv @@ -58,6 +58,7 @@ module exu_dispatch( output wire bjp_op_bltu_o, output wire bjp_op_bge_o, output wire bjp_op_bgeu_o, + output wire bjp_op_jalr_o, // dispatch to MULDIV output wire req_muldiv_o, @@ -152,6 +153,7 @@ module exu_dispatch( assign bjp_op_bge_o = bjp_info[`DECINFO_BJP_BGE]; assign bjp_op_bgeu_o = bjp_info[`DECINFO_BJP_BGEU]; assign req_bjp_o = op_bjp; + assign bjp_op_jalr_o = bjp_op1_rs1; // MULDIV info wire op_muldiv = (disp_info_grp == `DECINFO_GRP_MULDIV); diff --git a/rtl/core/ifu.sv b/rtl/core/ifu.sv index 6e717be..d8a78d0 100644 --- a/rtl/core/ifu.sv +++ b/rtl/core/ifu.sv @@ -48,6 +48,8 @@ module ifu( reg[1:0] state; reg[1:0] next_state; + wire prdt_taken; + wire[31:0] prdt_addr; always @ (posedge clk or negedge rst_n) begin if (!rst_n) begin @@ -90,6 +92,7 @@ module ifu( wire fetch_addr_en = instr_req_o & instr_gnt_i & (~stall_i[`STALL_PC]); assign fetch_addr_d = flush_i? flush_addr_i: + prdt_taken? prdt_addr: stall_i[`STALL_PC]? fetch_addr_q: inst_valid? fetch_addr_q + 4'h4: fetch_addr_q; @@ -106,4 +109,14 @@ module ifu( assign instr_addr_o = {fetch_addr_d[31:2], 2'b00}; assign pc_o = fetch_addr_q; + bpu u_bpu( + .clk(clk), + .rst_n(rst_n), + .inst_i(instr_rdata_i), + .inst_valid_i(inst_valid), + .pc_i(fetch_addr_q), + .prdt_taken_o(prdt_taken), + .prdt_addr_o(prdt_addr) + ); + endmodule