Add static branch prediction
This commit is contained in:
parent
276688f9ef
commit
6c964c75e5
8 changed files with 84 additions and 18 deletions
23
rv32.sv
23
rv32.sv
|
|
@ -41,6 +41,9 @@ module rv32 (
|
|||
logic mem_stall;
|
||||
logic mem_flush;
|
||||
|
||||
/* fetch -> decode control */
|
||||
logic fetch_branch_predicted_taken;
|
||||
|
||||
/* fetch -> decode data */
|
||||
logic [31:0] fetch_pc;
|
||||
logic [31:0] fetch_instr;
|
||||
|
|
@ -53,6 +56,7 @@ module rv32 (
|
|||
logic decode_mem_fence_unreg;
|
||||
|
||||
/* decode -> execute control */
|
||||
logic decode_branch_predicted_taken;
|
||||
logic decode_valid;
|
||||
logic [4:0] decode_rs1;
|
||||
logic [4:0] decode_rs2;
|
||||
|
|
@ -82,6 +86,7 @@ module rv32 (
|
|||
logic [11:0] decode_csr;
|
||||
|
||||
/* execute -> mem control */
|
||||
logic execute_branch_predicted_taken;
|
||||
logic execute_valid;
|
||||
logic execute_mem_read;
|
||||
logic execute_mem_write;
|
||||
|
|
@ -103,7 +108,7 @@ module rv32 (
|
|||
logic mem_rd_write;
|
||||
|
||||
/* mem -> fetch control */
|
||||
logic mem_branch_taken;
|
||||
logic mem_branch_mispredicted;
|
||||
|
||||
/* mem -> writeback data */
|
||||
logic [31:0] mem_rd_value;
|
||||
|
|
@ -126,7 +131,7 @@ module rv32 (
|
|||
|
||||
.execute_mem_fence_in(execute_mem_fence),
|
||||
|
||||
.mem_branch_taken_in(mem_branch_taken),
|
||||
.mem_branch_mispredicted_in(mem_branch_mispredicted),
|
||||
|
||||
.instr_read_in(instr_read_out),
|
||||
.instr_ready_in(instr_ready_in),
|
||||
|
|
@ -157,11 +162,14 @@ module rv32 (
|
|||
.flush_in(fetch_flush),
|
||||
|
||||
/* control in (from mem) */
|
||||
.branch_taken_in(mem_branch_taken),
|
||||
.branch_mispredicted_in(mem_branch_mispredicted),
|
||||
|
||||
/* control out (to memory bus) */
|
||||
.instr_read_out(instr_read_out),
|
||||
|
||||
/* control out */
|
||||
.branch_predicted_taken_out(fetch_branch_predicted_taken),
|
||||
|
||||
/* data in (from mem) */
|
||||
.branch_pc_in(mem_branch_pc),
|
||||
|
||||
|
|
@ -183,6 +191,9 @@ module rv32 (
|
|||
.stall_in(decode_stall),
|
||||
.flush_in(decode_flush),
|
||||
|
||||
/* control in (from fetch) */
|
||||
.branch_predicted_taken_in(fetch_branch_predicted_taken),
|
||||
|
||||
/* control in (from writeback) */
|
||||
.rd_in(mem_rd),
|
||||
.rd_write_in(mem_rd_write),
|
||||
|
|
@ -202,6 +213,7 @@ module rv32 (
|
|||
.mem_fence_unreg_out(decode_mem_fence_unreg),
|
||||
|
||||
/* control out */
|
||||
.branch_predicted_taken_out(decode_branch_predicted_taken),
|
||||
.valid_out(decode_valid),
|
||||
.rs1_out(decode_rs1),
|
||||
.rs2_out(decode_rs2),
|
||||
|
|
@ -239,6 +251,7 @@ module rv32 (
|
|||
.flush_in(execute_flush),
|
||||
|
||||
/* control in */
|
||||
.branch_predicted_taken_in(decode_branch_predicted_taken),
|
||||
.valid_in(decode_valid),
|
||||
.rs1_in(decode_rs1),
|
||||
.rs2_in(decode_rs2),
|
||||
|
|
@ -276,6 +289,7 @@ module rv32 (
|
|||
.writeback_rd_value_in(mem_rd_value),
|
||||
|
||||
/* control out */
|
||||
.branch_predicted_taken_out(execute_branch_predicted_taken),
|
||||
.valid_out(execute_valid),
|
||||
.mem_read_out(execute_mem_read),
|
||||
.mem_write_out(execute_mem_write),
|
||||
|
|
@ -300,6 +314,7 @@ module rv32 (
|
|||
.flush_in(mem_flush),
|
||||
|
||||
/* control in */
|
||||
.branch_predicted_taken_in(execute_branch_predicted_taken),
|
||||
.valid_in(execute_valid),
|
||||
.read_in(execute_mem_read),
|
||||
.write_in(execute_mem_write),
|
||||
|
|
@ -319,7 +334,7 @@ module rv32 (
|
|||
|
||||
/* control out */
|
||||
.valid_out(mem_valid),
|
||||
.branch_taken_out(mem_branch_taken),
|
||||
.branch_mispredicted_out(mem_branch_mispredicted),
|
||||
.rd_out(mem_rd),
|
||||
.rd_write_out(mem_rd_write),
|
||||
|
||||
|
|
|
|||
|
|
@ -29,26 +29,30 @@ endmodule
|
|||
|
||||
module rv32_branch_unit (
|
||||
/* control in */
|
||||
input predicted_taken_in,
|
||||
input [1:0] op_in,
|
||||
|
||||
/* data in */
|
||||
input [31:0] result_in,
|
||||
|
||||
/* control out */
|
||||
output logic taken_out
|
||||
output logic mispredicted_out
|
||||
);
|
||||
logic non_zero;
|
||||
logic taken;
|
||||
|
||||
assign non_zero = |result_in;
|
||||
|
||||
always_comb begin
|
||||
case (op_in)
|
||||
`RV32_BRANCH_OP_NEVER: taken_out = 0;
|
||||
`RV32_BRANCH_OP_ZERO: taken_out = ~non_zero;
|
||||
`RV32_BRANCH_OP_NON_ZERO: taken_out = non_zero;
|
||||
`RV32_BRANCH_OP_ALWAYS: taken_out = 1;
|
||||
`RV32_BRANCH_OP_NEVER: taken = 0;
|
||||
`RV32_BRANCH_OP_ZERO: taken = ~non_zero;
|
||||
`RV32_BRANCH_OP_NON_ZERO: taken = non_zero;
|
||||
`RV32_BRANCH_OP_ALWAYS: taken = 1;
|
||||
endcase
|
||||
end
|
||||
|
||||
assign mispredicted_out = taken != predicted_taken_in;
|
||||
endmodule
|
||||
|
||||
`endif
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ module rv32_decode (
|
|||
input stall_in,
|
||||
input flush_in,
|
||||
|
||||
/* control in (from fetch) */
|
||||
input branch_predicted_taken_in,
|
||||
|
||||
/* control in (from writeback) */
|
||||
input [4:0] rd_in,
|
||||
input rd_write_in,
|
||||
|
|
@ -30,6 +33,7 @@ module rv32_decode (
|
|||
output logic mem_fence_unreg_out,
|
||||
|
||||
/* control out */
|
||||
output logic branch_predicted_taken_out,
|
||||
output logic valid_out,
|
||||
output logic [4:0] rs1_out,
|
||||
output logic [4:0] rs2_out,
|
||||
|
|
@ -161,6 +165,7 @@ module rv32_decode (
|
|||
|
||||
always_ff @(posedge clk) begin
|
||||
if (!stall_in) begin
|
||||
branch_predicted_taken_out <= branch_predicted_taken_in;
|
||||
valid_out <= valid;
|
||||
rs1_out <= rs1;
|
||||
rs2_out <= rs2;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ module rv32_execute (
|
|||
input flush_in,
|
||||
|
||||
/* control in */
|
||||
input branch_predicted_taken_in,
|
||||
input valid_in,
|
||||
input [4:0] rs1_in,
|
||||
input [4:0] rs2_in,
|
||||
|
|
@ -50,6 +51,7 @@ module rv32_execute (
|
|||
input [31:0] writeback_rd_value_in,
|
||||
|
||||
/* control out */
|
||||
output logic branch_predicted_taken_out,
|
||||
output logic valid_out,
|
||||
output logic mem_read_out,
|
||||
output logic mem_write_out,
|
||||
|
|
@ -147,6 +149,7 @@ module rv32_execute (
|
|||
|
||||
always_ff @(posedge clk) begin
|
||||
if (!stall_in) begin
|
||||
branch_predicted_taken_out <= branch_predicted_taken_in;
|
||||
valid_out <= valid_in;
|
||||
mem_read_out <= mem_read_in;
|
||||
mem_write_out <= mem_write_in;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ module rv32_fetch (
|
|||
input flush_in,
|
||||
|
||||
/* control in (from mem) */
|
||||
input branch_taken_in,
|
||||
input branch_mispredicted_in,
|
||||
|
||||
/* data in (from mem) */
|
||||
input [31:0] branch_pc_in,
|
||||
|
|
@ -19,9 +19,12 @@ module rv32_fetch (
|
|||
/* data in (from memory bus) */
|
||||
input [31:0] instr_read_value_in,
|
||||
|
||||
/* control out */
|
||||
/* control out (to memory bus) */
|
||||
output logic instr_read_out,
|
||||
|
||||
/* control out */
|
||||
output logic branch_predicted_taken_out,
|
||||
|
||||
/* data out */
|
||||
output logic [31:0] pc_out,
|
||||
output logic [31:0] instr_out,
|
||||
|
|
@ -32,14 +35,45 @@ module rv32_fetch (
|
|||
logic [31:0] next_pc;
|
||||
logic [31:0] pc;
|
||||
|
||||
assign pc = branch_taken_in ? branch_pc_in : next_pc;
|
||||
logic sign;
|
||||
logic [31:0] imm_j;
|
||||
logic [31:0] imm_b;
|
||||
logic [7:0] opcode;
|
||||
|
||||
logic branch_predicted_taken;
|
||||
logic [31:0] branch_offset;
|
||||
|
||||
assign pc = branch_mispredicted_in ? branch_pc_in : next_pc;
|
||||
assign instr_read_out = 1;
|
||||
assign instr_address_out = pc;
|
||||
|
||||
assign sign = instr_read_value_in[31];
|
||||
assign imm_j = {{12{sign}}, instr_read_value_in[19:12], instr_read_value_in[20], instr_read_value_in[30:25], instr_read_value_in[24:21], 1'b0};
|
||||
assign imm_b = {{20{sign}}, instr_read_value_in[7], instr_read_value_in[30:25], instr_read_value_in[11:8], 1'b0};
|
||||
assign opcode = instr_read_value_in[7:0];
|
||||
|
||||
always_comb begin
|
||||
case ({opcode, sign})
|
||||
{`RV32_OPCODE_JAL, 1'bx}: begin
|
||||
branch_predicted_taken = 1;
|
||||
branch_offset = imm_j;
|
||||
end
|
||||
{`RV32_OPCODE_BRANCH, 1'b1}: begin
|
||||
branch_predicted_taken = 1;
|
||||
branch_offset = imm_b;
|
||||
end
|
||||
default: begin
|
||||
branch_predicted_taken = 0;
|
||||
branch_offset = 32'd4;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (!stall_in) begin
|
||||
branch_predicted_taken_out <= branch_predicted_taken;
|
||||
instr_out <= instr_read_value_in;
|
||||
next_pc <= pc + 4;
|
||||
next_pc <= pc + branch_offset;
|
||||
pc_out <= pc;
|
||||
|
||||
if (flush_in)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ module rv32_hazard_unit (
|
|||
|
||||
input execute_mem_fence_in,
|
||||
|
||||
input mem_branch_taken_in,
|
||||
input mem_branch_mispredicted_in,
|
||||
|
||||
input instr_read_in,
|
||||
input instr_ready_in,
|
||||
|
|
@ -56,10 +56,10 @@ module rv32_hazard_unit (
|
|||
assign fetch_flush_out = 0;
|
||||
|
||||
assign decode_stall_out = execute_stall_out;
|
||||
assign decode_flush_out = fetch_stall_out || mem_branch_taken_in;
|
||||
assign decode_flush_out = fetch_stall_out || mem_branch_mispredicted_in;
|
||||
|
||||
assign execute_stall_out = mem_stall_out;
|
||||
assign execute_flush_out = decode_stall_out || mem_branch_taken_in;
|
||||
assign execute_flush_out = decode_stall_out || mem_branch_mispredicted_in;
|
||||
|
||||
assign mem_stall_out = mem_wait_for_bus;
|
||||
assign mem_flush_out = execute_stall_out;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ module rv32_mem (
|
|||
input flush_in,
|
||||
|
||||
/* control in */
|
||||
input branch_predicted_taken_in,
|
||||
input valid_in,
|
||||
input read_in,
|
||||
input write_in,
|
||||
|
|
@ -34,7 +35,7 @@ module rv32_mem (
|
|||
|
||||
/* control out */
|
||||
output logic valid_out,
|
||||
output logic branch_taken_out,
|
||||
output logic branch_mispredicted_out,
|
||||
output logic [4:0] rd_out,
|
||||
output logic rd_write_out,
|
||||
|
||||
|
|
@ -54,13 +55,14 @@ module rv32_mem (
|
|||
/* branch unit */
|
||||
rv32_branch_unit branch_unit (
|
||||
/* control in */
|
||||
.predicted_taken_in(branch_predicted_taken_in),
|
||||
.op_in(branch_op_in),
|
||||
|
||||
/* data in */
|
||||
.result_in(result_in),
|
||||
|
||||
/* control out */
|
||||
.taken_out(branch_taken_out)
|
||||
.mispredicted_out(branch_mispredicted_out)
|
||||
);
|
||||
|
||||
assign branch_pc_out = branch_pc_in;
|
||||
|
|
|
|||
|
|
@ -54,4 +54,7 @@
|
|||
|
||||
`define RV32_INSTR_NOP 32'bxxxxxxx_xxxxx_00000_xxx_00000_0010011
|
||||
|
||||
`define RV32_OPCODE_JAL 7'b1101111
|
||||
`define RV32_OPCODE_BRANCH 7'b1100011
|
||||
|
||||
`endif
|
||||
|
|
|
|||
Loading…
Reference in a new issue