Add static branch prediction

This commit is contained in:
Graham Edgecombe 2017-12-30 13:48:14 +00:00
parent 276688f9ef
commit 6c964c75e5
8 changed files with 84 additions and 18 deletions

23
rv32.sv
View file

@ -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),

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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