diff --git a/src/ariane.sv b/src/ariane.sv index 1a2abc6e5..cda25df5d 100644 --- a/src/ariane.sv +++ b/src/ariane.sv @@ -206,6 +206,10 @@ module ariane // * -> CTRL logic flush_csr_ctrl; + logic flush_unissued_instr_ctrl_id; + logic flush_scoreboard_ctrl_id; + logic flush_ctrl_if; + // TODO: Preliminary signal assignments logic flush_tlb; assign flush_tlb = 1'b0; @@ -232,7 +236,7 @@ module ariane // IF // --------- if_stage if_stage_i ( - .flush_i ( flush ), + .flush_i ( flush_ctrl_if ), .req_i ( fetch_enable ), .if_busy_o ( ), // ? .id_ready_i ( ready_id_if ), @@ -269,6 +273,8 @@ module ariane id_stage_i ( .test_en_i ( test_en_i ), .flush_i ( flush ), + .flush_unissued_instr_i ( flush_unissued_instr_ctrl_id ), + .flush_scoreboard_i ( flush_scoreboard_ctrl_id ), .instruction_i ( instr_rdata_if_id ), .instruction_valid_i ( instr_valid_if_id ), .is_compressed_i ( is_compressed_if_id ), @@ -434,11 +440,18 @@ module ariane logic branchpredict_i; controller controller_i ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .flush_commit_i ( flush_commit_i ), - .flush_csr_i ( flush_csr_ctrl ), - .branchpredict_i ( branchpredict ) + .flush_bp_o ( ), + .flush_scoreboard_o ( flush_scoreboard_ctrl_id ), + .flush_unissued_instr_o ( flush_unissued_instr_ctrl_id ), + .flush_if_o ( flush_ctrl_if ), + .flush_id_o ( ), + .flush_ex_o ( ), + + .flush_ready_lsu_i ( ), + .flush_commit_i ( flush_commit_i ), + .flush_csr_i ( flush_csr_ctrl ), + .branchpredict_i ( branchpredict ), + .* ); diff --git a/src/controller.sv b/src/controller.sv index 2510caf7e..4dd49968c 100644 --- a/src/controller.sv +++ b/src/controller.sv @@ -23,12 +23,30 @@ module controller ( input logic clk_i, // Clock input logic rst_ni, // Asynchronous reset active low - input logic flush_commit_i, // flush request from commit stage in + output logic flush_bp_o, // flush branch prediction data structures + output logic flush_unissued_instr_o, + output logic flush_scoreboard_o, + output logic flush_if_o, + output logic flush_id_o, + output logic flush_ex_o, + + input logic flush_ready_lsu_i, // we need to wait for this signal from LSU + input logic flush_commit_i, // flush request from commit stage in input logic flush_csr_i, input branchpredict branchpredict_i ); + assign flush_bp_o = 1'b0; -// flush on mispredict + always_comb begin : flush_ctrl + flush_unissued_instr_o = 1'b0; + flush_scoreboard_o = 1'b0; + flush_if_o = 1'b0; + // flush on mispredict + if (branchpredict_i.is_mispredict) begin + flush_unissued_instr_o = 1'b1; + flush_if_o = 1'b1; + end -// flush on exception + end + // flush on exception endmodule diff --git a/src/id_stage.sv b/src/id_stage.sv index ec57bfd69..ed8c964c7 100644 --- a/src/id_stage.sv +++ b/src/id_stage.sv @@ -28,6 +28,8 @@ module id_stage #( input logic test_en_i, // Test Enable input logic flush_i, + input logic flush_unissued_instr_i, + input logic flush_scoreboard_i, // from IF input logic [31:0] instruction_i, input logic instruction_valid_i, @@ -167,7 +169,7 @@ module id_stage #( scoreboard_i ( .full_o ( full ), - .flush_i ( flush_i ), + .flush_i ( flush_scoreboard_i ), .rd_clobber_o ( rd_clobber_sb_iro ), .rs1_i ( rs1_iro_sb ), .rs1_o ( rs1_sb_iro ), diff --git a/src/if_stage.sv b/src/if_stage.sv index bf63d94dd..12e7d1ac6 100644 --- a/src/if_stage.sv +++ b/src/if_stage.sv @@ -97,8 +97,8 @@ module if_stage ( // Pre-fetch buffer, caches a fixed number of instructions prefetch_buffer prefetch_buffer_i ( .clk ( clk_i ), - .rst_n ( rst_ni ), - + .rst_n ( rst_ni ), + .flush_i ( flush_i ), .req_i ( req_i ), .branch_i ( branch_req ), // kill everything @@ -209,24 +209,38 @@ module if_stage ( end else begin - offset_fsm_cs <= offset_fsm_ns; - branch_valid_q <= branch_valid_n; - predict_address_q <= predict_address_n; - predict_taken_q <= predict_taken_n; + if (flush_i) begin + // offset FSM state + offset_fsm_cs <= IDLE; + instr_valid_id_o <= 1'b0; + instr_rdata_id_o <= '0; + illegal_c_insn_id_o <= 1'b0; + is_compressed_id_o <= 1'b0; + pc_id_o <= '0; + ex_o <= '{default: 0}; + branch_valid_q <= 1'b0; + predict_address_q <= 64'b0; + predict_taken_q <= 1'b0; + end else begin - if (if_valid) begin - instr_valid_id_o <= 1'b1; - instr_rdata_id_o <= instr_decompressed; - illegal_c_insn_id_o <= illegal_c_insn; - is_compressed_id_o <= instr_compressed_int; - pc_id_o <= pc_if_o; - ex_o.cause <= 64'b0; // TODO: Output exception - ex_o.tval <= 64'b0; // TODO: Output exception - ex_o.valid <= 1'b0; // TODO: Output exception - end else if (clear_instr_valid_i) begin - instr_valid_id_o <= 1'b0; + offset_fsm_cs <= offset_fsm_ns; + branch_valid_q <= branch_valid_n; + predict_address_q <= predict_address_n; + predict_taken_q <= predict_taken_n; + + if (if_valid) begin + instr_valid_id_o <= 1'b1; + instr_rdata_id_o <= instr_decompressed; + illegal_c_insn_id_o <= illegal_c_insn; + is_compressed_id_o <= instr_compressed_int; + pc_id_o <= pc_if_o; + ex_o.cause <= 64'b0; // TODO: Output exception + ex_o.tval <= 64'b0; // TODO: Output exception + ex_o.valid <= 1'b0; // TODO: Output exception + end else if (clear_instr_valid_i) begin + instr_valid_id_o <= 1'b0; + end end - end end diff --git a/src/pcgen.sv b/src/pcgen.sv index d5619d69d..ac67543fc 100644 --- a/src/pcgen.sv +++ b/src/pcgen.sv @@ -84,6 +84,12 @@ module pcgen ( end // 1.Debug + // 3. Control flow change request + if (branchpredict_i.is_mispredict) begin + set_pc_n = 1'b1; + // we already got the correct target address + npc_n = branchpredict_i.target_address; + end // 2. Exception if (ex_i.valid) begin npc_n = trap_vector_base_i; diff --git a/src/prefetch_buffer.sv b/src/prefetch_buffer.sv index 86b520cc6..fc47edbe4 100644 --- a/src/prefetch_buffer.sv +++ b/src/prefetch_buffer.sv @@ -26,6 +26,7 @@ module prefetch_buffer ( input logic clk, input logic rst_n, + input logic flush_i, input logic req_i, @@ -97,11 +98,8 @@ module prefetch_buffer //--------------- assign fetch_addr = {instr_addr_q[63:2], 2'b00} + 64'd4; + assign fifo_clear = branch_i || flush_i; - always_comb - begin - fifo_clear = branch_i; - end //------------------------- // Instruction fetch FSM diff --git a/src/scoreboard.sv b/src/scoreboard.sv index d789c767a..697762bda 100644 --- a/src/scoreboard.sv +++ b/src/scoreboard.sv @@ -29,7 +29,8 @@ module scoreboard #( input logic clk_i, // Clock input logic rst_ni, // Asynchronous reset active low output logic full_o, // We can't take anymore data - input logic flush_i, + input logic flush_i, // flush whole scoreboard + input logic flush_unissued_instr_i, // list of clobbered registers to issue stage output fu_t [31:0] rd_clobber_o, @@ -199,8 +200,12 @@ always_comb begin : push_instruction_and_wb end end end - - // flush signal + // flush all instructions which are not issued, e.g. set the top pointer back to the issue pointer + // -> everything we decoded so far was garbage + if (flush_unissued_instr_i) begin + top_pointer_n = issue_pointer_q; + end + // flush signal, e.g.: flush everything we need to backtrack after an exception if (flush_i) mem_n = '{default: 0}; @@ -246,6 +251,10 @@ always_comb begin : issue_instruction issue_pointer_n = issue_pointer_q + 1; end + // if we are flushing we should not issue the current instruction + if (flush_unissued_instr_i) + issue_instr_valid_o = 1'b0; + end // commit instruction: remove from scoreboard, advance pointer @@ -279,7 +288,10 @@ always_ff @(posedge clk_i or negedge rst_ni) begin : sequential top_pointer_q <= top_pointer_n; mem_q <= mem_n; if (decoded_instr_valid_i && ~full_o) // only advance if we decoded instruction and we are not full - top_pointer_qq <= top_pointer_q; + if (flush_unissued_instr_i) + top_pointer_qq <= top_pointer_n; + else + top_pointer_qq <= top_pointer_q; end end