Skip to content
Snippets Groups Projects
Commit 203ee4e9 authored by Alban Gruin's avatar Alban Gruin
Browse files

fixup! frontend: disable branch prediction, mkII

parent 68232c03
No related branches found
No related tags found
No related merge requests found
......@@ -136,11 +136,11 @@ module frontend import ariane_pkg::*; #(
// unconditional jumps with known target -> immediately resolved
assign is_jump[i] = instruction_valid[i] & (rvi_jump[i] | rvc_jump[i]);
// unconditional jumps with unknown target -> BTB
assign is_jalr[i] = instruction_valid[i] & ~is_return[i] & ~is_call[i] & (rvi_jalr[i] | rvc_jalr[i] | rvc_jr[i]);
assign is_jalr[i] = instruction_valid[i] & (rvi_jalr[i] | rvc_jalr[i] | rvc_jr[i]);
end
logic should_stall;
assign should_stall = (stalling_q | (|is_branch) | (|is_return) | (|is_jalr)) & (!resolved_branch_i.valid);
assign should_stall = (stalling_q | (|is_branch) | (|is_jalr)) & (!resolved_branch_i.valid || (resolved_branch_i.cf_type == Jump));
// taken/not taken
always_comb begin
......@@ -150,15 +150,19 @@ module frontend import ariane_pkg::*; #(
predict_address = '0;
bp_valid = 1'b0;
if (!should_stall) begin
if (replay) begin
stalling_d = 1'b0;
end else if (!stalling_q || (resolved_branch_i.valid && resolved_branch_i.cf_type != Jump)) begin
stalling_d = 1'b0;
for (int unsigned i = 0; i < INSTR_PER_FETCH; i++) begin
unique case ({is_branch[i] | is_return[i] | is_jalr[i], is_jump[i]})
cf_type[i] = ariane_pkg::NoCF;
unique case ({is_branch[i] | is_jalr[i], is_jump[i]})
2'b00:;
2'b01: begin
if (!(|taken_rvi_cf) && !(|taken_rvc_cf))
predict_address = addr[i] + (taken_rvc_cf[i] ? rvc_imm[i] : rvi_imm[i]);
predict_address = addr[i] + (rvc_jump[i] ? rvc_imm[i] : rvi_imm[i]);
taken_rvi_cf[i] = rvi_jump[i];
taken_rvc_cf[i] = rvc_jump[i];
......@@ -166,6 +170,9 @@ module frontend import ariane_pkg::*; #(
bp_valid = 1'b1;
end
2'b10: begin
if (!(|taken_rvi_cf) && !(|taken_rvc_cf))
predict_address = addr[i] + 'h4;
taken_rvi_cf[i] = 1'b1;
taken_rvc_cf[i] = 1'b1;
bp_valid = 1'b1;
......@@ -180,13 +187,13 @@ module frontend import ariane_pkg::*; #(
assign is_mispredict = resolved_branch_i.valid & resolved_branch_i.is_mispredict;
// Cache interface
assign icache_dreq_o.req = instr_queue_ready & (!should_stall);
assign if_ready = icache_dreq_i.ready & instr_queue_ready;
assign icache_dreq_o.req = instr_queue_ready & (!should_stall | replay);
assign if_ready = icache_dreq_i.ready & instr_queue_ready & (!should_stall);
// We need to flush the cache pipeline if:
// 1. We mispredicted
// 2. Want to flush the whole processor front-end
// 3. Need to replay an instruction because the fetch-fifo was full
assign icache_dreq_o.kill_s1 = is_mispredict | flush_i | replay;
assign icache_dreq_o.kill_s1 = is_mispredict | flush_i;
// if we have a valid branch-prediction we need to only kill the last cache request
// also if we killed the first stage we also need to kill the second stage (inclusive flush)
assign icache_dreq_o.kill_s2 = icache_dreq_o.kill_s1 | bp_valid;
......@@ -220,35 +227,33 @@ module frontend import ariane_pkg::*; #(
npc_d = npc_q;
end
if (!should_stall) begin
// 0. Branch Prediction
if (bp_valid) begin
fetch_address = predict_address;
npc_d = predict_address;
end
// 1. Default assignment
if (if_ready) npc_d = {fetch_address[riscv::VLEN-1:2], 2'b0} + 'h4;
// 2. Replay instruction fetch
if (replay) npc_d = replay_addr;
// 3. Control flow change request
if (is_mispredict) npc_d = resolved_branch_i.target_address;
// 4. Return from environment call
if (eret_i) npc_d = epc_i;
// 5. Exception/Interrupt
if (ex_valid_i) npc_d = trap_vector_base_i;
// 6. Pipeline Flush because of CSR side effects
// On a pipeline flush start fetching from the next address
// of the instruction in the commit stage
// we came here from a flush request of a CSR instruction or AMO,
// as CSR or AMO instructions do not exist in a compressed form
// we can unconditionally do PC + 4 here
// TODO(zarubaf) This adder can at least be merged with the one in the csr_regfile stage
if (set_pc_commit_i) npc_d = pc_commit_i + {{riscv::VLEN-3{1'b0}}, 3'b100};
// 7. Debug
// enter debug on a hard-coded base-address
if (set_debug_pc_i) npc_d = ArianeCfg.DmBaseAddress[riscv::VLEN-1:0] + dm::HaltAddress[riscv::VLEN-1:0];
icache_dreq_o.vaddr = fetch_address;
// 0. Branch Prediction
if (bp_valid) begin
fetch_address = predict_address;
npc_d = predict_address;
end
// 1. Default assignment
if (if_ready) npc_d = {fetch_address[riscv::VLEN-1:2], 2'b0} + 'h4;
// 2. Replay instruction fetch
if (replay) npc_d = replay_addr;
// 3. Control flow change request
if (is_mispredict) npc_d = resolved_branch_i.target_address;
// 4. Return from environment call
if (eret_i) npc_d = epc_i;
// 5. Exception/Interrupt
if (ex_valid_i) npc_d = trap_vector_base_i;
// 6. Pipeline Flush because of CSR side effects
// On a pipeline flush start fetching from the next address
// of the instruction in the commit stage
// we came here from a flush request of a CSR instruction or AMO,
// as CSR or AMO instructions do not exist in a compressed form
// we can unconditionally do PC + 4 here
// TODO(zarubaf) This adder can at least be merged with the one in the csr_regfile stage
if (set_pc_commit_i) npc_d = pc_commit_i + {{riscv::VLEN-3{1'b0}}, 3'b100};
// 7. Debug
// enter debug on a hard-coded base-address
if (set_debug_pc_i) npc_d = ArianeCfg.DmBaseAddress[riscv::VLEN-1:0] + dm::HaltAddress[riscv::VLEN-1:0];
icache_dreq_o.vaddr = fetch_address;
end
logic [FETCH_WIDTH-1:0] icache_data;
......@@ -281,7 +286,11 @@ module frontend import ariane_pkg::*; #(
end else icache_ex_valid_q <= ariane_pkg::FE_NONE;
// save the uppermost prediction
end
stalling_q <= stalling_d;
if (flush_i)
stalling_q <= 1'b0;
else
stalling_q <= stalling_d;
end
end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment