Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion rtl/ibex_compressed_decoder.sv
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module ibex_compressed_decoder #(
output logic [31:0] instr_o,
output logic is_compressed_o,
output ibex_pkg::instr_exp_e gets_expanded_o,
input logic flush_expanded_i,
output logic illegal_instr_o
);
import ibex_pkg::*;
Expand Down Expand Up @@ -670,6 +671,8 @@ module ibex_compressed_decoder #(
instr_o = cm_sp_addi(.rlist(instr_i[7:4]),
.spimm(instr_i[3:2]),
.decr(1'b0));
// Ensure the SP adjustment commits atomically with the subsequent micro-ops.
gets_expanded = INSTR_EXPANDED_COMMIT;
if (id_in_ready_i) begin
unique case (instr_i[12:8])
5'b11100: cm_state_d = CmPopZeroA0; // cm.popretz
Expand All @@ -684,6 +687,8 @@ module ibex_compressed_decoder #(
end
CmPopZeroA0: begin
instr_o = cm_zero_a0();
// Ensure the `ret` after is executed atomically with this one.
gets_expanded = INSTR_EXPANDED_COMMIT;
if (id_in_ready_i) begin
cm_state_d = CmPopRetRa;
end
Expand Down Expand Up @@ -712,6 +717,8 @@ module ibex_compressed_decoder #(
// No cm.mvsa01 instruction is active yet; start a new one.
// Move a0 to register indicated by r1s'.
instr_o = cm_mvsa01(.a01(1'b0), .rs(instr_i[9:7]));
// Ensure the second move happens atomically with this one.
gets_expanded = INSTR_EXPANDED_COMMIT;
if (valid_i && id_in_ready_i) begin
cm_state_d = CmMvSecondReg;
end
Expand All @@ -738,6 +745,8 @@ module ibex_compressed_decoder #(
// No cm.mva01s instruction is active yet; start a new one.
// Move register indicated by r1s' into a0.
instr_o = cm_mva01s(.rs(instr_i[9:7]), .a01(1'b0));
// Ensure the second move happens atomically with this one.
gets_expanded = INSTR_EXPANDED_COMMIT;
if (valid_i && id_in_ready_i) begin
cm_state_d = CmMvSecondReg;
end
Expand Down Expand Up @@ -799,7 +808,7 @@ module ibex_compressed_decoder #(
if (!rst_ni) begin
cm_state_q <= CmIdle;
end else begin
cm_state_q <= cm_state_d;
cm_state_q <= flush_expanded_i ? CmIdle : cm_state_d;
end
end

Expand Down
12 changes: 9 additions & 3 deletions rtl/ibex_controller.sv
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ module ibex_controller #(
input logic [31:0] instr_i, // uncompressed instr data for mtval
input logic [15:0] instr_compressed_i, // instr compressed data for mtval
input logic instr_is_compressed_i, // instr is compressed
input ibex_pkg::instr_exp_e instr_gets_expanded_i, // instr expansion state
input logic instr_bp_taken_i, // instr was predicted taken branch
input logic instr_fetch_err_i, // instr has error
input logic instr_fetch_err_plus2_i, // instr error is x32
Expand Down Expand Up @@ -389,8 +390,11 @@ module ibex_controller #(
// interrupt. `trigger_match_i` is not a priority entry into debug mode as it must be ignored
// where control flow changes such that the instruction causing the trigger is no longer being
// executed.
assign enter_debug_mode_prio_d = (debug_req_i | do_single_step_d) & ~debug_mode_q;
assign enter_debug_mode = enter_debug_mode_prio_d | (trigger_match_i & ~debug_mode_q);
// We don't interrupt expanded Zcmp sequences with debug mode entry.
assign enter_debug_mode_prio_d = (debug_req_i | do_single_step_d) & ~debug_mode_q &
!(instr_gets_expanded_i inside {INSTR_EXPANDED, INSTR_EXPANDED_COMMIT});
assign enter_debug_mode = enter_debug_mode_prio_d | (trigger_match_i & ~debug_mode_q) &
!(instr_gets_expanded_i inside {INSTR_EXPANDED, INSTR_EXPANDED_COMMIT});

// Set when an ebreak should enter debug mode rather than jump to exception
// handler
Expand All @@ -410,8 +414,10 @@ module ibex_controller #(
// - while in NMI mode (nested NMIs are not supported, NMI has highest priority and
// cannot be interrupted by regular interrupts),
// - while single stepping.
// - while the atomic committing instructions of a Zcmp sequence.
assign handle_irq = ~debug_mode_q & ~debug_single_step_i & ~nmi_mode_q &
(irq_nm | (irq_pending_i & irq_enabled));
(irq_nm | (irq_pending_i & irq_enabled)) &
!(instr_gets_expanded_i == INSTR_EXPANDED_COMMIT);
Comment thread
gautschimi marked this conversation as resolved.

// generate ID of fast interrupts, highest priority to lowest ID
always_comb begin : gen_mfip_id
Expand Down
1 change: 1 addition & 0 deletions rtl/ibex_core.sv
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,7 @@ module ibex_core import ibex_pkg::*; #(
.instr_rdata_alu_i (instr_rdata_alu_id),
.instr_rdata_c_i (instr_rdata_c_id),
.instr_is_compressed_i(instr_is_compressed_id),
.instr_gets_expanded_i(instr_gets_expanded_id),
.instr_bp_taken_i (instr_bp_taken_id),

// Jumps and branches
Expand Down
5 changes: 4 additions & 1 deletion rtl/ibex_id_stage.sv
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ module ibex_id_stage #(
input logic [31:0] instr_rdata_alu_i, // from IF-ID pipeline registers
input logic [15:0] instr_rdata_c_i, // from IF-ID pipeline registers
input logic instr_is_compressed_i,
input ibex_pkg::instr_exp_e instr_gets_expanded_i,
input logic instr_bp_taken_i,
output logic instr_req_o,
output logic instr_first_cycle_id_o,
Expand Down Expand Up @@ -567,6 +568,7 @@ module ibex_id_stage #(
.instr_i (instr_rdata_i),
.instr_compressed_i (instr_rdata_c_i),
.instr_is_compressed_i (instr_is_compressed_i),
.instr_gets_expanded_i (instr_gets_expanded_i),
.instr_bp_taken_i (instr_bp_taken_i),
.instr_fetch_err_i (instr_fetch_err_i),
.instr_fetch_err_plus2_i(instr_fetch_err_plus2_i),
Expand Down Expand Up @@ -1084,7 +1086,8 @@ module ibex_id_stage #(
(csr_addr_o inside {CSR_MINSTRET, CSR_MINSTRETH});

assign instr_perf_count_id_o = ~ebrk_insn & ~ecall_insn_dec & ~illegal_insn_dec &
~illegal_csr_insn_i & ~instr_fetch_err_i & ~minstret_write;
~illegal_csr_insn_i & ~instr_fetch_err_i & ~minstret_write &
!(instr_gets_expanded_i inside {INSTR_EXPANDED, INSTR_EXPANDED_COMMIT});

// An instruction is ready to move to the writeback stage (or retire if there is no writeback
// stage)
Expand Down
18 changes: 14 additions & 4 deletions rtl/ibex_if_stage.sv
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,12 @@ module ibex_if_stage import ibex_pkg::*; #(
//
// since it does not matter where we decompress instructions, we do it here
// to ease timing closure

// The compressed decoder only has state for the Zcmp expanded instructions. Flush this state if
// there is an exception.
logic flush_expanded;
assign flush_expanded = pc_set_i & (pc_mux_i == ibex_pkg::PC_EXC);

ibex_compressed_decoder #(
.RV32ZC (RV32ZC),
.ResetAll (ResetAll)
Expand All @@ -423,6 +429,7 @@ module ibex_if_stage import ibex_pkg::*; #(
.instr_o (instr_decompressed),
.is_compressed_o(instr_is_compressed),
.gets_expanded_o(instr_gets_expanded),
.flush_expanded_i(flush_expanded),
.illegal_instr_o(illegal_c_insn)
);

Expand Down Expand Up @@ -567,7 +574,8 @@ module ibex_if_stage import ibex_pkg::*; #(
// request, all of which will set branch_req. Also do not check after reset or for dummy
// instructions.
assign prev_instr_seq_d = (prev_instr_seq_q | instr_new_id_d) &
~branch_req & ~if_instr_err & ~stall_dummy_instr & !(instr_gets_expanded == INSTR_EXPANDED);
~branch_req & ~if_instr_err & ~stall_dummy_instr &
!(instr_gets_expanded inside {INSTR_EXPANDED, INSTR_EXPANDED_COMMIT});

always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
Expand Down Expand Up @@ -630,7 +638,8 @@ module ibex_if_stage import ibex_pkg::*; #(
assign instr_skid_en = predict_branch_taken & ~pc_set_i & ~id_in_ready_i & ~instr_skid_valid_q;

assign instr_skid_valid_d = (instr_skid_valid_q & ~id_in_ready_i & ~stall_dummy_instr &
!(instr_gets_expanded == INSTR_EXPANDED)) | instr_skid_en;
!(instr_gets_expanded inside
{INSTR_EXPANDED, INSTR_EXPANDED_COMMIT})) | instr_skid_en;

always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
Expand Down Expand Up @@ -689,7 +698,8 @@ module ibex_if_stage import ibex_pkg::*; #(
assign instr_bp_taken_d = instr_skid_valid_q ? instr_skid_bp_taken_q : predict_branch_taken;

assign fetch_ready = id_in_ready_i & ~stall_dummy_instr &
!(instr_gets_expanded == INSTR_EXPANDED) & ~instr_skid_valid_q;
!(instr_gets_expanded inside {INSTR_EXPANDED, INSTR_EXPANDED_COMMIT}) &
~instr_skid_valid_q;

assign instr_bp_taken_o = instr_bp_taken_q;

Expand All @@ -705,7 +715,7 @@ module ibex_if_stage import ibex_pkg::*; #(
assign if_instr_addr = fetch_addr;
assign if_instr_bus_err = fetch_err;
assign fetch_ready = id_in_ready_i & ~stall_dummy_instr &
!(instr_gets_expanded == INSTR_EXPANDED);
!(instr_gets_expanded inside {INSTR_EXPANDED, INSTR_EXPANDED_COMMIT});
end

//////////
Expand Down
5 changes: 3 additions & 2 deletions rtl/ibex_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,9 @@ package ibex_pkg;
// Compressed instruction expansion
typedef enum logic [1:0] {
INSTR_NOT_EXPANDED,
INSTR_EXPANDED,
INSTR_EXPANDED_LAST
INSTR_EXPANDED, // Executing micro-ops of an expanded instruction
INSTR_EXPANDED_COMMIT, // Micro-ops need to be committed atomically with successor micro-ops
INSTR_EXPANDED_LAST // Last micro-op of an expanded instruction
} instr_exp_e;

// Exception PC mux selection
Expand Down
Loading