🐛 Fixes in branch logic

This commit is contained in:
Florian Zaruba 2017-06-21 20:26:06 +02:00
parent 34519aa8d0
commit 0d2851770b
5 changed files with 19 additions and 8 deletions

View file

@ -303,7 +303,7 @@ module ariane
.NR_WB_PORTS ( NR_WB_PORTS )
)
issue_stage_i (
.flush_unissued_instr_i ( flush_unissued_instr_i ),
.flush_unissued_instr_i ( flush_unissued_instr_ctrl_id ),
.flush_i ( flush_ctrl_id ),
.decoded_instr_i ( issue_entry_id_issue ),

View file

@ -131,17 +131,18 @@ module branch_unit (
end
end
end
// to resolve the branch in ID -> only do this if this was indeed a branch (hence vald_i is asserted)
// to resolve the branch in ID
resolve_branch_o = 1'b1;
// the other case would be that this instruction was no branch but branch prediction thought that it was one
// this is essentially also a mis-predict
end else if (fu_valid_i && branch_predict_i.valid) begin
end else if (fu_valid_i && branch_predict_i.valid && branch_predict_i.predict_taken) begin
// re-set the branch to the next PC
resolved_branch_o.is_mispredict = 1'b1;
resolved_branch_o.target_address = next_pc;
// clear this entry so that we are not constantly mis-predicting
resolved_branch_o.clear = 1'b1;
resolved_branch_o.valid = 1'b1;
resolve_branch_o = 1'b1;
end
end
// use ALU exception signal for storing instruction fetch exceptions if

View file

@ -68,6 +68,7 @@ module controller (
if (sfence_vma_i) begin
flush_pcgen_o = 1'b1;
flush_if_o = 1'b1;
flush_unissued_instr_o = 1'b1;
flush_id_o = 1'b1;
flush_ex_o = 1'b1;
flush_tlb_o = 1'b1;
@ -79,6 +80,7 @@ module controller (
if (flush_csr_i) begin
flush_pcgen_o = 1'b1;
flush_if_o = 1'b1;
flush_unissued_instr_o = 1'b1;
flush_id_o = 1'b1;
flush_ex_o = 1'b1;
end
@ -91,6 +93,7 @@ module controller (
// for the PC GEN stage but instead tells it to take the PC we gave it
flush_pcgen_o = 1'b0;
flush_if_o = 1'b1;
flush_unissued_instr_o = 1'b1;
flush_id_o = 1'b1;
flush_ex_o = 1'b1;
end
@ -102,6 +105,7 @@ module controller (
// don't flush pcgen as we want to take the exception
flush_pcgen_o = 1'b0;
flush_if_o = 1'b1;
flush_unissued_instr_o = 1'b1;
flush_id_o = 1'b1;
flush_ex_o = 1'b1;
end

View file

@ -107,8 +107,14 @@ module issue_stage #(
if (resolve_branch_i) begin
unresolved_branch_n = 1'b0;
end
// if the instruction is valid and it is a control flow instruction
if (decoded_instr_valid_i && is_ctrl_flow_i) begin
// if the instruction is valid, it is a control flow instruction and the issue stage acknowledged its dispatch
// set the unresolved branch flag
if (issue_ack_iro_sb && decoded_instr_valid_i && is_ctrl_flow_i) begin
unresolved_branch_n = 1'b1;
end
// if we predicted a taken branch this means that we need to stall issue for one cycle to resolve the
// branch, otherwise we might issue a wrong instruction
if (issue_ack_iro_sb && decoded_instr_i.bp.valid && decoded_instr_i.bp.predict_taken) begin
unresolved_branch_n = 1'b1;
end
// if we are requested to flush also flush the unresolved branch flag because either the flush

View file

@ -88,8 +88,8 @@ module scoreboard #(
issue_instr_o.trans_id = issue_pointer_q;
// we are ready if we are not full and don't have any unresolved branches, but it can be
// the case that we have an unresolved branch which is cleared in that cycle (resolved_branch_i == 1)
issue_instr_valid_o = decoded_instr_valid_i && !unresolved_branch_i && !issue_full;
decoded_instr_ack_o = issue_ack_i;
issue_instr_valid_o = decoded_instr_valid_i && !unresolved_branch_i;
decoded_instr_ack_o = issue_ack_i && !issue_full;
end
// maintain a FIFO with issued instructions
@ -102,7 +102,7 @@ module scoreboard #(
issue_pointer_n = issue_pointer_q;
// if we got a acknowledge from the issue stage, put this scoreboard entry in the queue
if (issue_instr_valid_o) begin
if (decoded_instr_valid_i && decoded_instr_ack_o) begin
// the decoded instruction we put in there is valid (1st bit)
// increase the issue counter
issue_cnt++;