Add mtval CSR

`mtval` can provide additional information to trap handlers.
In case of load/store errors, it holds the failing address.
For illegal instruction exceptions, it holds the illegal instruction.
This commit is contained in:
Pirmin Vogel 2019-06-27 11:41:23 +01:00
parent 5171ee79f0
commit b22a6a10de
8 changed files with 293 additions and 244 deletions

View file

@ -26,6 +26,8 @@ Ibex implements all the Control and Status Registers (CSRs) listed in the follow
+---------+--------------------+--------+-----------------------------------------------+ +---------+--------------------+--------+-----------------------------------------------+
| 0x342 | ``mcause`` | RW | Machine Trap Cause | | 0x342 | ``mcause`` | RW | Machine Trap Cause |
+---------+--------------------+--------+-----------------------------------------------+ +---------+--------------------+--------+-----------------------------------------------+
| 0x343 | ``mtval`` | WARL | Machine Trap Value Register |
+---------+--------------------+--------+-----------------------------------------------+
| 0x7B0 | ``dcsr`` | RW | Debug Control and Status Register | | 0x7B0 | ``dcsr`` | RW | Debug Control and Status Register |
+---------+--------------------+--------+-----------------------------------------------+ +---------+--------------------+--------+-----------------------------------------------+
| 0x7B1 | ``dpc`` | RW | Debug PC | | 0x7B1 | ``dpc`` | RW | Debug PC |
@ -117,6 +119,21 @@ Reset Value: ``0x0000_0000``
| 4:0 | R | **Exception Code** | | 4:0 | R | **Exception Code** |
+-------+-----+------------------------------------------------------------------+ +-------+-----+------------------------------------------------------------------+
Machine Trap Value (mtval)
--------------------------
CSR Address: ``0x343``
Reset Value: ``0x0000_0000``
When an exception is encountered, this register can hold exception-specific information to assist software in handling the trap.
* In the case of errors in the load-store unit ``mtval`` holds the address of the transaction causing the error.
* If this transaction is misaligned, ``mtval`` holds the address of the missing transaction part.
* In the case of illegal instruction exceptions, ``mtval`` holds the actual faulting instruction.
For all other exceptions, ``mtval`` is 0.
.. _csr-mhartid: .. _csr-mhartid:

View file

@ -45,8 +45,10 @@ module ibex_controller (
input logic csr_status_i, // decoder has CSR status instr input logic csr_status_i, // decoder has CSR status instr
// from IF/ID pipeline // from IF/ID pipeline
input logic instr_valid_i, // instruction coming from IF/ID stage input logic instr_valid_i, // instr from IF-ID reg is valid
// is valid input logic [31:0] instr_i, // instr from IF-ID reg, for mtval
input logic [15:0] instr_compressed_i, // instr from IF-ID reg, for mtval
input logic instr_is_compressed_i, // instr from IF-ID reg is compressed
// from prefetcher // from prefetcher
output logic instr_req_o, // start fetching instructions output logic instr_req_o, // start fetching instructions
@ -58,6 +60,7 @@ module ibex_controller (
output ibex_defines::exc_pc_sel_e exc_pc_mux_o, // IF stage selector for exception PC output ibex_defines::exc_pc_sel_e exc_pc_mux_o, // IF stage selector for exception PC
// LSU // LSU
input logic [31:0] lsu_addr_last_i, // for mtval
input logic load_err_i, input logic load_err_i,
input logic store_err_i, input logic store_err_i,
@ -92,10 +95,11 @@ module ibex_controller (
output logic csr_save_if_o, output logic csr_save_if_o,
output logic csr_save_id_o, output logic csr_save_id_o,
output ibex_defines::exc_cause_e csr_cause_o,
output logic csr_restore_mret_id_o, output logic csr_restore_mret_id_o,
output logic csr_restore_dret_id_o, output logic csr_restore_dret_id_o,
output logic csr_save_cause_o, output logic csr_save_cause_o,
output ibex_defines::exc_cause_e csr_cause_o,
output logic [31:0] csr_mtval_o,
// stall signals // stall signals
output logic halt_if_o, output logic halt_if_o,
@ -154,16 +158,14 @@ module ibex_controller (
csr_save_if_o = 1'b0; csr_save_if_o = 1'b0;
csr_save_id_o = 1'b0; csr_save_id_o = 1'b0;
csr_restore_mret_id_o = 1'b0; csr_restore_mret_id_o = 1'b0;
csr_restore_dret_id_o = 1'b0; csr_restore_dret_id_o = 1'b0;
csr_save_cause_o = 1'b0; csr_save_cause_o = 1'b0;
csr_cause_o = EXC_CAUSE_INSN_ADDR_MISA; // = 6'h00
csr_mtval_o = '0;
exc_cause_o = EXC_CAUSE_INSN_ADDR_MISA; // = 6'h00 exc_cause_o = EXC_CAUSE_INSN_ADDR_MISA; // = 6'h00
exc_pc_mux_o = EXC_PC_IRQ; exc_pc_mux_o = EXC_PC_IRQ;
csr_cause_o = EXC_CAUSE_INSN_ADDR_MISA; // = 6'h00
pc_mux_o = PC_BOOT; pc_mux_o = PC_BOOT;
pc_set_o = 1'b0; pc_set_o = 1'b0;
@ -342,7 +344,7 @@ module ibex_controller (
pc_set_o = 1'b1; pc_set_o = 1'b1;
exc_pc_mux_o = EXC_PC_DBD; exc_pc_mux_o = EXC_PC_DBD;
csr_save_if_o = 1'b1; csr_save_if_o = 1'b1;
debug_csr_save_o = 1'b1; debug_csr_save_o = 1'b1;
csr_save_cause_o = 1'b1; csr_save_cause_o = 1'b1;
@ -433,6 +435,7 @@ module ibex_controller (
end end
exc_cause_o = EXC_CAUSE_ILLEGAL_INSN; exc_cause_o = EXC_CAUSE_ILLEGAL_INSN;
csr_cause_o = EXC_CAUSE_ILLEGAL_INSN; csr_cause_o = EXC_CAUSE_ILLEGAL_INSN;
csr_mtval_o = instr_is_compressed_i ? {16'b0, instr_compressed_i} : instr_i;
end end
mret_insn_i: begin mret_insn_i: begin
//mret //mret
@ -492,6 +495,7 @@ module ibex_controller (
exc_pc_mux_o = EXC_PC_LOAD; exc_pc_mux_o = EXC_PC_LOAD;
exc_cause_o = EXC_CAUSE_LOAD_ACCESS_FAULT; exc_cause_o = EXC_CAUSE_LOAD_ACCESS_FAULT;
csr_cause_o = EXC_CAUSE_LOAD_ACCESS_FAULT; csr_cause_o = EXC_CAUSE_LOAD_ACCESS_FAULT;
csr_mtval_o = lsu_addr_last_i;
end end
store_err_q: begin store_err_q: begin
pc_mux_o = PC_EXCEPTION; pc_mux_o = PC_EXCEPTION;
@ -501,6 +505,7 @@ module ibex_controller (
exc_pc_mux_o = EXC_PC_STORE; exc_pc_mux_o = EXC_PC_STORE;
exc_cause_o = EXC_CAUSE_STORE_ACCESS_FAULT; exc_cause_o = EXC_CAUSE_STORE_ACCESS_FAULT;
csr_cause_o = EXC_CAUSE_STORE_ACCESS_FAULT; csr_cause_o = EXC_CAUSE_STORE_ACCESS_FAULT;
csr_mtval_o = lsu_addr_last_i;
end end
default:; default:;

View file

@ -109,18 +109,20 @@ module ibex_core #(
// IF/ID signals // IF/ID signals
logic instr_valid_id; logic instr_valid_id;
logic [31:0] instr_rdata_id; // Instruction sampled inside IF stage logic [31:0] instr_rdata_id; // Instruction sampled inside IF stage
logic is_compressed_id; logic [15:0] instr_rdata_c_id; // Compressed instruction sampled inside IF stage
logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage logic instr_is_compressed_id;
logic illegal_insn_id; // ID stage sees an illegal instruction logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage
logic [31:0] pc_if; // Program counter in IF stage logic illegal_insn_id; // ID stage sees an illegal instruction
logic [31:0] pc_id; // Program counter in ID stage logic [31:0] pc_if; // Program counter in IF stage
logic [31:0] pc_id; // Program counter in ID stage
logic clear_instr_valid; logic clear_instr_valid;
logic pc_set; logic pc_set;
pc_sel_e pc_mux_id; // Mux selector for next PC
exc_pc_sel_e exc_pc_mux_id; // Mux selector for exception PC pc_sel_e pc_mux_id; // Mux selector for next PC
exc_cause_e exc_cause; // Exception cause + IRQ ID for vectorized interrupt lines exc_pc_sel_e exc_pc_mux_id; // Mux selector for exception PC
exc_cause_e exc_cause; // Exception cause
logic lsu_load_err; logic lsu_load_err;
logic lsu_store_err; logic lsu_store_err;
@ -129,7 +131,7 @@ module ibex_core #(
logic is_decoding; logic is_decoding;
logic data_misaligned; logic data_misaligned;
logic [31:0] misaligned_addr; logic [31:0] lsu_addr_last;
// Jump and branch target and decision (EX->IF) // Jump and branch target and decision (EX->IF)
logic [31:0] jump_target_ex; logic [31:0] jump_target_ex;
@ -147,7 +149,7 @@ module ibex_core #(
logic [31:0] alu_operand_a_ex; logic [31:0] alu_operand_a_ex;
logic [31:0] alu_operand_b_ex; logic [31:0] alu_operand_b_ex;
logic [31:0] alu_adder_result_ex; // Used to forward computed address to LSU logic [31:0] alu_adder_result_ex; // Used to forward computed address to LSU
logic [31:0] regfile_wdata_ex; logic [31:0] regfile_wdata_ex;
// Multiplier Control // Multiplier Control
@ -167,8 +169,9 @@ module ibex_core #(
csr_num_e csr_addr; csr_num_e csr_addr;
logic [31:0] csr_rdata; logic [31:0] csr_rdata;
logic [31:0] csr_wdata; logic [31:0] csr_wdata;
logic illegal_csr_insn_id; // CSR access to non-existent register, logic illegal_csr_insn_id; // CSR access to non-existent register,
// with wrong priviledge level, or missing write permissions // with wrong priviledge level,
// or missing write permissions
// Data Memory Control // Data Memory Control
logic data_we_ex; logic data_we_ex;
@ -190,18 +193,19 @@ module ibex_core #(
logic data_valid_lsu; logic data_valid_lsu;
// Signals between instruction core interface and pipe (if and id stages) // Signals between instruction core interface and pipe (if and id stages)
logic instr_req_int; // Id stage asserts a req to instruction core interface logic instr_req_int; // Id stage asserts a req to instruction core interface
// Interrupts // Interrupts
logic m_irq_enable; logic m_irq_enable;
logic [31:0] mepc, depc; logic [31:0] mepc, depc;
logic csr_save_cause;
logic csr_save_if; logic csr_save_if;
logic csr_save_id; logic csr_save_id;
exc_cause_e csr_cause;
logic csr_restore_mret_id; logic csr_restore_mret_id;
logic csr_restore_dret_id; logic csr_restore_dret_id;
logic csr_save_cause;
exc_cause_e csr_cause;
logic [31:0] csr_mtval;
// debug mode and dcsr configuration // debug mode and dcsr configuration
dbg_cause_e debug_cause; dbg_cause_e debug_cause;
@ -221,7 +225,6 @@ module ibex_core #(
// RISC-V Formal Interface signals // RISC-V Formal Interface signals
`ifdef RVFI `ifdef RVFI
logic [31:0] rvfi_insn_opcode; logic [31:0] rvfi_insn_opcode;
logic [15:0] compressed_instr;
logic rvfi_valid_int; logic rvfi_valid_int;
logic [4:0] rvfi_rs1_addr_id; logic [4:0] rvfi_rs1_addr_id;
logic [4:0] rvfi_rs2_addr_id; logic [4:0] rvfi_rs2_addr_id;
@ -296,52 +299,50 @@ module ibex_core #(
.DmHaltAddr ( DmHaltAddr ), .DmHaltAddr ( DmHaltAddr ),
.DmExceptionAddr ( DmExceptionAddr ) .DmExceptionAddr ( DmExceptionAddr )
) if_stage_i ( ) if_stage_i (
.clk_i ( clk ), .clk_i ( clk ),
.rst_ni ( rst_ni ), .rst_ni ( rst_ni ),
// boot address (trap vector location) // boot address (trap vector location)
.boot_addr_i ( boot_addr_i ), .boot_addr_i ( boot_addr_i ),
// instruction request control // instruction request control
.req_i ( instr_req_int ), .req_i ( instr_req_int ),
// instruction cache interface // instruction cache interface
.instr_req_o ( instr_req_o ), .instr_req_o ( instr_req_o ),
.instr_addr_o ( instr_addr_o ), .instr_addr_o ( instr_addr_o ),
.instr_gnt_i ( instr_gnt_i ), .instr_gnt_i ( instr_gnt_i ),
.instr_rvalid_i ( instr_rvalid_i ), .instr_rvalid_i ( instr_rvalid_i ),
.instr_rdata_i ( instr_rdata_i ), .instr_rdata_i ( instr_rdata_i ),
// outputs to ID stage // outputs to ID stage
.instr_valid_id_o ( instr_valid_id ), .instr_valid_id_o ( instr_valid_id ),
.instr_rdata_id_o ( instr_rdata_id ), .instr_rdata_id_o ( instr_rdata_id ),
.is_compressed_id_o ( is_compressed_id ), .instr_rdata_c_id_o ( instr_rdata_c_id ),
`ifdef RVFI .instr_is_compressed_id_o ( instr_is_compressed_id ),
.instr_rdata_compressed_o ( compressed_instr ), .illegal_c_insn_id_o ( illegal_c_insn_id ),
`endif .pc_if_o ( pc_if ),
.illegal_c_insn_id_o ( illegal_c_insn_id ), .pc_id_o ( pc_id ),
.pc_if_o ( pc_if ),
.pc_id_o ( pc_id ),
// control signals // control signals
.clear_instr_valid_i ( clear_instr_valid ), .clear_instr_valid_i ( clear_instr_valid ),
.pc_set_i ( pc_set ), .pc_set_i ( pc_set ),
.exception_pc_reg_i ( mepc ), // exception return address .exception_pc_reg_i ( mepc ), // exception return address
.depc_i ( depc ), // debug return address .depc_i ( depc ), // debug return address
.pc_mux_i ( pc_mux_id ), // sel for pc multiplexer .pc_mux_i ( pc_mux_id ), // sel for pc multiplexer
.exc_pc_mux_i ( exc_pc_mux_id ), .exc_pc_mux_i ( exc_pc_mux_id ),
.exc_vec_pc_mux_i ( exc_cause ), .exc_vec_pc_mux_i ( exc_cause ),
// Jump targets // Jump targets
.jump_target_ex_i ( jump_target_ex ), .jump_target_ex_i ( jump_target_ex ),
// pipeline stalls // pipeline stalls
.halt_if_i ( halt_if ), .halt_if_i ( halt_if ),
.id_ready_i ( id_ready ), .id_ready_i ( id_ready ),
.if_valid_o ( if_valid ), .if_valid_o ( if_valid ),
.if_busy_o ( if_busy ), .if_busy_o ( if_busy ),
.perf_imiss_o ( perf_imiss ) .perf_imiss_o ( perf_imiss )
); );
@ -353,49 +354,50 @@ module ibex_core #(
.RV32E ( RV32E ), .RV32E ( RV32E ),
.RV32M ( RV32M ) .RV32M ( RV32M )
) id_stage_i ( ) id_stage_i (
.clk_i ( clk ), .clk_i ( clk ),
.rst_ni ( rst_ni ), .rst_ni ( rst_ni ),
.test_en_i ( test_en_i ), .test_en_i ( test_en_i ),
// Processor Enable // Processor Enable
.fetch_enable_i ( fetch_enable_i ), .fetch_enable_i ( fetch_enable_i ),
.ctrl_busy_o ( ctrl_busy ), .ctrl_busy_o ( ctrl_busy ),
.core_ctrl_firstfetch_o ( core_ctrl_firstfetch ), .core_ctrl_firstfetch_o ( core_ctrl_firstfetch ),
.is_decoding_o ( is_decoding ), .is_decoding_o ( is_decoding ),
.illegal_insn_o ( illegal_insn_id ), .illegal_insn_o ( illegal_insn_id ),
// Interface to instruction memory // Interface to instruction memory
.instr_valid_i ( instr_valid_id ), .instr_valid_i ( instr_valid_id ),
.instr_rdata_i ( instr_rdata_id ), .instr_rdata_i ( instr_rdata_id ),
.instr_req_o ( instr_req_int ), .instr_rdata_c_i ( instr_rdata_c_id ),
.instr_is_compressed_i ( instr_is_compressed_id ),
.instr_req_o ( instr_req_int ),
// Jumps and branches // Jumps and branches
.branch_decision_i ( branch_decision ), .branch_decision_i ( branch_decision ),
// IF and ID control signals // IF and ID control signals
.clear_instr_valid_o ( clear_instr_valid ), .clear_instr_valid_o ( clear_instr_valid ),
.pc_set_o ( pc_set ), .pc_set_o ( pc_set ),
.pc_mux_o ( pc_mux_id ), .pc_mux_o ( pc_mux_id ),
.exc_pc_mux_o ( exc_pc_mux_id ), .exc_pc_mux_o ( exc_pc_mux_id ),
.exc_cause_o ( exc_cause ), .exc_cause_o ( exc_cause ),
.illegal_c_insn_i ( illegal_c_insn_id ), .illegal_c_insn_i ( illegal_c_insn_id ),
.is_compressed_i ( is_compressed_id ),
.pc_id_i ( pc_id ), .pc_id_i ( pc_id ),
// Stalls // Stalls
.halt_if_o ( halt_if ), .halt_if_o ( halt_if ),
.id_ready_o ( id_ready ), .id_ready_o ( id_ready ),
.ex_ready_i ( ex_ready ), .ex_ready_i ( ex_ready ),
.id_valid_o ( id_valid ), .id_valid_o ( id_valid ),
.alu_operator_ex_o ( alu_operator_ex ), .alu_operator_ex_o ( alu_operator_ex ),
.alu_operand_a_ex_o ( alu_operand_a_ex ), .alu_operand_a_ex_o ( alu_operand_a_ex ),
.alu_operand_b_ex_o ( alu_operand_b_ex ), .alu_operand_b_ex_o ( alu_operand_b_ex ),
.mult_en_ex_o ( mult_en_ex ), .mult_en_ex_o ( mult_en_ex ),
.div_en_ex_o ( div_en_ex ), .div_en_ex_o ( div_en_ex ),
@ -405,63 +407,64 @@ module ibex_core #(
.multdiv_operand_b_ex_o ( multdiv_operand_b_ex ), .multdiv_operand_b_ex_o ( multdiv_operand_b_ex ),
// CSR ID/EX // CSR ID/EX
.csr_access_ex_o ( csr_access_ex ), .csr_access_ex_o ( csr_access_ex ),
.csr_op_ex_o ( csr_op_ex ), .csr_op_ex_o ( csr_op_ex ),
.csr_cause_o ( csr_cause ), .csr_save_if_o ( csr_save_if ), // control signal to save pc
.csr_save_if_o ( csr_save_if ), // control signal to save pc .csr_save_id_o ( csr_save_id ), // control signal to save pc
.csr_save_id_o ( csr_save_id ), // control signal to save pc .csr_restore_mret_id_o ( csr_restore_mret_id ), // control signal to restore pc
.csr_restore_mret_id_o ( csr_restore_mret_id ), // control signal to restore pc .csr_restore_dret_id_o ( csr_restore_dret_id ), // control signal to restore pc
.csr_restore_dret_id_o ( csr_restore_dret_id ), // control signal to restore pc .csr_save_cause_o ( csr_save_cause ),
.csr_save_cause_o ( csr_save_cause ), .csr_cause_o ( csr_cause ),
.illegal_csr_insn_i ( illegal_csr_insn_id ), .csr_mtval_o ( csr_mtval ),
.illegal_csr_insn_i ( illegal_csr_insn_id ),
// LSU // LSU
.data_req_ex_o ( data_req_ex ), // to load store unit .data_req_ex_o ( data_req_ex ), // to load store unit
.data_we_ex_o ( data_we_ex ), // to load store unit .data_we_ex_o ( data_we_ex ), // to load store unit
.data_type_ex_o ( data_type_ex ), // to load store unit .data_type_ex_o ( data_type_ex ), // to load store unit
.data_sign_ext_ex_o ( data_sign_ext_ex ), // to load store unit .data_sign_ext_ex_o ( data_sign_ext_ex ), // to load store unit
.data_reg_offset_ex_o ( data_reg_offset_ex ), // to load store unit .data_reg_offset_ex_o ( data_reg_offset_ex ), // to load store unit
.data_wdata_ex_o ( data_wdata_ex ), // to load store unit .data_wdata_ex_o ( data_wdata_ex ), // to load store unit
.data_misaligned_i ( data_misaligned ), .data_misaligned_i ( data_misaligned ),
.misaligned_addr_i ( misaligned_addr ), .lsu_addr_last_i ( lsu_addr_last ),
.lsu_load_err_i ( lsu_load_err ), .lsu_load_err_i ( lsu_load_err ),
.lsu_store_err_i ( lsu_store_err ), .lsu_store_err_i ( lsu_store_err ),
// Interrupt Signals // Interrupt Signals
.irq_i ( irq_i ), // incoming interrupts .irq_i ( irq_i ), // incoming interrupts
.irq_id_i ( irq_id_i ), .irq_id_i ( irq_id_i ),
.m_irq_enable_i ( m_irq_enable ), .m_irq_enable_i ( m_irq_enable ),
.irq_ack_o ( irq_ack_o ), .irq_ack_o ( irq_ack_o ),
.irq_id_o ( irq_id_o ), .irq_id_o ( irq_id_o ),
// Debug Signal // Debug Signal
.debug_cause_o ( debug_cause ), .debug_cause_o ( debug_cause ),
.debug_csr_save_o ( debug_csr_save ), .debug_csr_save_o ( debug_csr_save ),
.debug_req_i ( debug_req_i ), .debug_req_i ( debug_req_i ),
.debug_single_step_i ( debug_single_step ), .debug_single_step_i ( debug_single_step ),
.debug_ebreakm_i ( debug_ebreakm ), .debug_ebreakm_i ( debug_ebreakm ),
// write data to commit in the register file // write data to commit in the register file
.regfile_wdata_lsu_i ( regfile_wdata_lsu ), .regfile_wdata_lsu_i ( regfile_wdata_lsu ),
.regfile_wdata_ex_i ( regfile_wdata_ex ), .regfile_wdata_ex_i ( regfile_wdata_ex ),
.csr_rdata_i ( csr_rdata ), .csr_rdata_i ( csr_rdata ),
`ifdef RVFI `ifdef RVFI
.rfvi_reg_raddr_ra_o ( rvfi_rs1_addr_id ), .rfvi_reg_raddr_ra_o ( rvfi_rs1_addr_id ),
.rfvi_reg_rdata_ra_o ( rvfi_rs1_data_id ), .rfvi_reg_rdata_ra_o ( rvfi_rs1_data_id ),
.rfvi_reg_raddr_rb_o ( rvfi_rs2_addr_id ), .rfvi_reg_raddr_rb_o ( rvfi_rs2_addr_id ),
.rfvi_reg_rdata_rb_o ( rvfi_rs2_data_id ), .rfvi_reg_rdata_rb_o ( rvfi_rs2_data_id ),
.rfvi_reg_waddr_rd_o ( rvfi_rd_addr_id ), .rfvi_reg_waddr_rd_o ( rvfi_rd_addr_id ),
.rfvi_reg_wdata_rd_o ( rvfi_rd_wdata_id ), .rfvi_reg_wdata_rd_o ( rvfi_rd_wdata_id ),
.rfvi_reg_we_o ( rvfi_rd_we_id ), .rfvi_reg_we_o ( rvfi_rd_we_id ),
`endif `endif
// Performance Counters // Performance Counters
.perf_jump_o ( perf_jump ), .perf_jump_o ( perf_jump ),
.perf_branch_o ( perf_branch ), .perf_branch_o ( perf_branch ),
.perf_tbranch_o ( perf_tbranch ) .perf_tbranch_o ( perf_tbranch )
); );
@ -528,7 +531,7 @@ module ibex_core #(
.adder_result_ex_i ( alu_adder_result_ex), .adder_result_ex_i ( alu_adder_result_ex),
.data_misaligned_o ( data_misaligned ), .data_misaligned_o ( data_misaligned ),
.misaligned_addr_o ( misaligned_addr ), .addr_last_o ( lsu_addr_last ),
// exception signals // exception signals
.load_err_o ( lsu_load_err ), .load_err_o ( lsu_load_err ),
@ -563,57 +566,59 @@ module ibex_core #(
.RV32E ( RV32E ), .RV32E ( RV32E ),
.RV32M ( RV32M ) .RV32M ( RV32M )
) cs_registers_i ( ) cs_registers_i (
.clk_i ( clk ), .clk_i ( clk ),
.rst_ni ( rst_ni ), .rst_ni ( rst_ni ),
// Core and Cluster ID from outside // Core and Cluster ID from outside
.core_id_i ( core_id_i ), .core_id_i ( core_id_i ),
.cluster_id_i ( cluster_id_i ), .cluster_id_i ( cluster_id_i ),
// boot address // boot address
.boot_addr_i ( boot_addr_i ), .boot_addr_i ( boot_addr_i ),
// Interface to CSRs (SRAM like) // Interface to CSRs (SRAM like)
.csr_access_i ( csr_access ), .csr_access_i ( csr_access ),
.csr_addr_i ( csr_addr ), .csr_addr_i ( csr_addr ),
.csr_wdata_i ( csr_wdata ), .csr_wdata_i ( csr_wdata ),
.csr_op_i ( csr_op ), .csr_op_i ( csr_op ),
.csr_rdata_o ( csr_rdata ), .csr_rdata_o ( csr_rdata ),
// Interrupt related control signals // Interrupt related control signals
.m_irq_enable_o ( m_irq_enable ), .m_irq_enable_o ( m_irq_enable ),
.mepc_o ( mepc ), .mepc_o ( mepc ),
// debug // debug
.debug_cause_i ( debug_cause ), .debug_cause_i ( debug_cause ),
.debug_csr_save_i ( debug_csr_save ), .debug_csr_save_i ( debug_csr_save ),
.depc_o ( depc ), .depc_o ( depc ),
.debug_single_step_o ( debug_single_step ), .debug_single_step_o ( debug_single_step ),
.debug_ebreakm_o ( debug_ebreakm ), .debug_ebreakm_o ( debug_ebreakm ),
.pc_if_i ( pc_if ), .pc_if_i ( pc_if ),
.pc_id_i ( pc_id ), .pc_id_i ( pc_id ),
.csr_save_if_i ( csr_save_if ), .csr_save_if_i ( csr_save_if ),
.csr_save_id_i ( csr_save_id ), .csr_save_id_i ( csr_save_id ),
.csr_restore_mret_i ( csr_restore_mret_id ), .csr_restore_mret_i ( csr_restore_mret_id ),
.csr_restore_dret_i ( csr_restore_dret_id ), .csr_restore_dret_i ( csr_restore_dret_id ),
.csr_cause_i ( csr_cause ), .csr_save_cause_i ( csr_save_cause ),
.csr_save_cause_i ( csr_save_cause ), .csr_cause_i ( csr_cause ),
.illegal_csr_insn_o ( illegal_csr_insn_id ), .csr_mtval_i ( csr_mtval ),
.illegal_csr_insn_o ( illegal_csr_insn_id ),
// performance counter related signals // performance counter related signals
.insn_ret_i ( insn_ret ), .insn_ret_i ( insn_ret ),
.id_valid_i ( id_valid ), .id_valid_i ( id_valid ),
.is_compressed_i ( is_compressed_id ), .instr_is_compressed_i ( instr_is_compressed_id ),
.is_decoding_i ( is_decoding ), .is_decoding_i ( is_decoding ),
.imiss_i ( perf_imiss ), .imiss_i ( perf_imiss ),
.pc_set_i ( pc_set ), .pc_set_i ( pc_set ),
.jump_i ( perf_jump ), .jump_i ( perf_jump ),
.branch_i ( perf_branch ), .branch_i ( perf_branch ),
.branch_taken_i ( perf_tbranch ), .branch_taken_i ( perf_tbranch ),
.mem_load_i ( perf_load ), .mem_load_i ( perf_load ),
.mem_store_i ( perf_store ), .mem_store_i ( perf_store ),
.lsu_busy_i ( lsu_busy ) .lsu_busy_i ( lsu_busy )
); );
`ifdef RVFI `ifdef RVFI
@ -672,7 +677,7 @@ module ibex_core #(
always_comb begin always_comb begin
if (is_compressed_id) begin if (is_compressed_id) begin
rvfi_insn_opcode = {16'b0, compressed_instr}; rvfi_insn_opcode = {16'b0, instr_rdata_c_id};
end else begin end else begin
rvfi_insn_opcode = instr_rdata_id; rvfi_insn_opcode = instr_rdata_id;
end end

View file

@ -66,26 +66,26 @@ module ibex_cs_registers #(
input logic csr_save_id_i, input logic csr_save_id_i,
input logic csr_restore_mret_i, input logic csr_restore_mret_i,
input logic csr_restore_dret_i, input logic csr_restore_dret_i,
input ibex_defines::exc_cause_e csr_cause_i,
input logic csr_save_cause_i, input logic csr_save_cause_i,
input logic [31:0] csr_mtval_i,
input ibex_defines::exc_cause_e csr_cause_i,
output logic illegal_csr_insn_o, // access to non-existent CSR, output logic illegal_csr_insn_o, // access to non-existent CSR,
// with wrong priviledge level, or // with wrong priviledge level, or
// missing write permissions // missing write permissions
// Performance Counters // Performance Counters
input logic insn_ret_i, // instr retired in ID/EX stage input logic insn_ret_i, // instr retired in ID/EX stage
input logic id_valid_i, // ID stage is done input logic id_valid_i, // ID stage is done
input logic is_compressed_i, // compressed instr in ID input logic instr_is_compressed_i, // compressed instr in ID
input logic is_decoding_i, // controller is in DECODE state input logic is_decoding_i, // controller is in DECODE state
input logic imiss_i, // instr fetch input logic imiss_i, // instr fetch
input logic pc_set_i, // PC was set to a new value input logic pc_set_i, // PC was set to a new value
input logic jump_i, // jump instr seen (j, jr, jal, jalr) input logic jump_i, // jump instr seen (j, jr, jal, jalr)
input logic branch_i, // branch instr seen (bf, bnf) input logic branch_i, // branch instr seen (bf, bnf)
input logic branch_taken_i, // branch was taken input logic branch_taken_i, // branch was taken
input logic mem_load_i, // load from memory in this cycle input logic mem_load_i, // load from memory in this cycle
input logic mem_store_i, // store to memory in this cycle input logic mem_store_i, // store to memory in this cycle
input logic lsu_busy_i input logic lsu_busy_i
); );
@ -155,6 +155,7 @@ module ibex_cs_registers #(
Status_t mstatus_q, mstatus_n; Status_t mstatus_q, mstatus_n;
logic [31:0] mepc_q, mepc_n; logic [31:0] mepc_q, mepc_n;
logic [31:0] mcause_q, mcause_n; logic [31:0] mcause_q, mcause_n;
logic [31:0] mtval_q, mtval_n;
Dcsr_t dcsr_q, dcsr_n; Dcsr_t dcsr_q, dcsr_n;
logic [31:0] depc_q, depc_n; logic [31:0] depc_q, depc_n;
logic [31:0] dscratch0_q, dscratch0_n; logic [31:0] dscratch0_q, dscratch0_n;
@ -229,6 +230,8 @@ module ibex_cs_registers #(
// mcause: exception cause // mcause: exception cause
CSR_MCAUSE: csr_rdata_int = {mcause_q[5], 26'b0, mcause_q[4:0]}; CSR_MCAUSE: csr_rdata_int = {mcause_q[5], 26'b0, mcause_q[4:0]};
// mtval: trap value
CSR_MTVAL: csr_rdata_int = mtval_q;
CSR_DCSR: csr_rdata_int = dcsr_q; CSR_DCSR: csr_rdata_int = dcsr_q;
CSR_DPC: csr_rdata_int = depc_q; CSR_DPC: csr_rdata_int = depc_q;
@ -283,6 +286,7 @@ module ibex_cs_registers #(
mstatus_n = mstatus_q; mstatus_n = mstatus_q;
mepc_n = mepc_q; mepc_n = mepc_q;
mcause_n = mcause_q; mcause_n = mcause_q;
mtval_n = mtval_q;
dcsr_n = dcsr_q; dcsr_n = dcsr_q;
depc_n = depc_q; depc_n = depc_q;
dscratch0_n = dscratch0_q; dscratch0_n = dscratch0_q;
@ -309,6 +313,9 @@ module ibex_cs_registers #(
// mcause // mcause
CSR_MCAUSE: if (csr_we_int) mcause_n = {csr_wdata_int[31], csr_wdata_int[4:0]}; CSR_MCAUSE: if (csr_we_int) mcause_n = {csr_wdata_int[31], csr_wdata_int[4:0]};
// mtval: trap value
CSR_MTVAL: if (csr_we_int) mtval_n = csr_wdata_int;
CSR_DCSR: begin CSR_DCSR: begin
if (csr_we_int) begin if (csr_we_int) begin
dcsr_n = csr_wdata_int; dcsr_n = csr_wdata_int;
@ -415,6 +422,7 @@ module ibex_cs_registers #(
mstatus_n.mpp = PRIV_LVL_M; mstatus_n.mpp = PRIV_LVL_M;
mepc_n = exception_pc; mepc_n = exception_pc;
mcause_n = csr_cause_i; mcause_n = csr_cause_i;
mtval_n = csr_mtval_i;
end end
end //csr_save_cause_i end //csr_save_cause_i
@ -474,6 +482,7 @@ module ibex_cs_registers #(
}; };
mepc_q <= '0; mepc_q <= '0;
mcause_q <= '0; mcause_q <= '0;
mtval_q <= '0;
dcsr_q <= '{ dcsr_q <= '{
xdebugver: XDEBUGVER_NO, // 4'h0 xdebugver: XDEBUGVER_NO, // 4'h0
cause: DBG_CAUSE_NONE, // 3'h0 cause: DBG_CAUSE_NONE, // 3'h0
@ -492,6 +501,7 @@ module ibex_cs_registers #(
}; };
mepc_q <= mepc_n; mepc_q <= mepc_n;
mcause_q <= mcause_n; mcause_q <= mcause_n;
mtval_q <= mtval_n;
dcsr_q <= dcsr_n; dcsr_q <= dcsr_n;
depc_q <= depc_n; depc_q <= depc_n;
dscratch0_q <= dscratch0_n; dscratch0_q <= dscratch0_n;
@ -532,8 +542,8 @@ module ibex_cs_registers #(
mhpmcounter_incr[7] = jump_i; // num of jumps (unconditional) mhpmcounter_incr[7] = jump_i; // num of jumps (unconditional)
mhpmcounter_incr[8] = branch_i; // num of branches (conditional) mhpmcounter_incr[8] = branch_i; // num of branches (conditional)
mhpmcounter_incr[9] = branch_taken_i; // num of taken branches (conditional) mhpmcounter_incr[9] = branch_taken_i; // num of taken branches (conditional)
mhpmcounter_incr[10] = is_compressed_i // num of compressed instr mhpmcounter_incr[10] = is_decoding_i // num of compressed instr
& id_valid_i & is_decoding_i; & id_valid_i & instr_is_compressed_i;
// inactive counters // inactive counters
for (int unsigned i=3+MHPMCounterNum; i<32; i++) begin : gen_mhpmcounter_incr_inactive for (int unsigned i=3+MHPMCounterNum; i<32; i++) begin : gen_mhpmcounter_incr_inactive

View file

@ -226,6 +226,7 @@ typedef enum logic[11:0] {
// Machine trap handling // Machine trap handling
CSR_MEPC = 12'h341, CSR_MEPC = 12'h341,
CSR_MCAUSE = 12'h342, CSR_MCAUSE = 12'h342,
CSR_MTVAL = 12'h343,
// Debug/trace // Debug/trace
CSR_DCSR = 12'h7b0, CSR_DCSR = 12'h7b0,

View file

@ -53,7 +53,9 @@ module ibex_id_stage #(
// Interface to IF stage // Interface to IF stage
input logic instr_valid_i, input logic instr_valid_i,
input logic [31:0] instr_rdata_i, // comes from pipeline of IF stage input logic [31:0] instr_rdata_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,
output logic instr_req_o, output logic instr_req_o,
// Jumps and branches // Jumps and branches
@ -66,7 +68,6 @@ module ibex_id_stage #(
output ibex_defines::exc_pc_sel_e exc_pc_mux_o, output ibex_defines::exc_pc_sel_e exc_pc_mux_o,
input logic illegal_c_insn_i, input logic illegal_c_insn_i,
input logic is_compressed_i,
input logic [31:0] pc_id_i, input logic [31:0] pc_id_i,
@ -92,12 +93,13 @@ module ibex_id_stage #(
// CSR // CSR
output logic csr_access_ex_o, output logic csr_access_ex_o,
output ibex_defines::csr_op_e csr_op_ex_o, output ibex_defines::csr_op_e csr_op_ex_o,
output ibex_defines::exc_cause_e csr_cause_o,
output logic csr_save_if_o, output logic csr_save_if_o,
output logic csr_save_id_o, output logic csr_save_id_o,
output logic csr_restore_mret_id_o, output logic csr_restore_mret_id_o,
output logic csr_restore_dret_id_o, output logic csr_restore_dret_id_o,
output logic csr_save_cause_o, output logic csr_save_cause_o,
output ibex_defines::exc_cause_e csr_cause_o,
output logic [31:0] csr_mtval_o,
input logic illegal_csr_insn_i, input logic illegal_csr_insn_i,
// Interface to load store unit // Interface to load store unit
@ -109,7 +111,7 @@ module ibex_id_stage #(
output logic [31:0] data_wdata_ex_o, output logic [31:0] data_wdata_ex_o,
input logic data_misaligned_i, input logic data_misaligned_i,
input logic [31:0] misaligned_addr_i, input logic [31:0] lsu_addr_last_i,
// Interrupt signals // Interrupt signals
input logic irq_i, input logic irq_i,
@ -300,7 +302,7 @@ module ibex_id_stage #(
always_comb begin : alu_operand_a_mux always_comb begin : alu_operand_a_mux
unique case (alu_op_a_mux_sel) unique case (alu_op_a_mux_sel)
OP_A_REG_A: alu_operand_a = regfile_data_ra_id; OP_A_REG_A: alu_operand_a = regfile_data_ra_id;
OP_A_FWD: alu_operand_a = misaligned_addr_i; OP_A_FWD: alu_operand_a = lsu_addr_last_i;
OP_A_CURRPC: alu_operand_a = pc_id_i; OP_A_CURRPC: alu_operand_a = pc_id_i;
OP_A_IMM: alu_operand_a = imm_a; OP_A_IMM: alu_operand_a = imm_a;
default: alu_operand_a = 'X; default: alu_operand_a = 'X;
@ -321,7 +323,7 @@ module ibex_id_stage #(
IMM_B_B: imm_b = imm_b_type; IMM_B_B: imm_b = imm_b_type;
IMM_B_U: imm_b = imm_u_type; IMM_B_U: imm_b = imm_u_type;
IMM_B_J: imm_b = imm_j_type; IMM_B_J: imm_b = imm_j_type;
IMM_B_INCR_PC: imm_b = is_compressed_i ? 32'h2 : 32'h4; IMM_B_INCR_PC: imm_b = instr_is_compressed_i ? 32'h2 : 32'h4;
IMM_B_INCR_ADDR: imm_b = 32'h4; IMM_B_INCR_ADDR: imm_b = 32'h4;
default: imm_b = imm_i_type; default: imm_b = imm_i_type;
endcase endcase
@ -331,7 +333,7 @@ module ibex_id_stage #(
assign alu_operand_b = (alu_op_b_mux_sel == OP_B_IMM) ? imm_b : regfile_data_rb_id; assign alu_operand_b = (alu_op_b_mux_sel == OP_B_IMM) ? imm_b : regfile_data_rb_id;
// Signals used by tracer // Signals used by tracer
assign operand_a_fw_id = data_misaligned_i ? misaligned_addr_i : regfile_data_ra_id; assign operand_a_fw_id = data_misaligned_i ? lsu_addr_last_i : regfile_data_ra_id;
assign operand_b_fw_id = regfile_data_rb_id; assign operand_b_fw_id = regfile_data_rb_id;
assign unused_operand_a_fw_id = operand_a_fw_id; assign unused_operand_a_fw_id = operand_a_fw_id;
@ -483,6 +485,9 @@ module ibex_id_stage #(
// from IF/ID pipeline // from IF/ID pipeline
.instr_valid_i ( instr_valid_i ), .instr_valid_i ( instr_valid_i ),
.instr_i ( instr ),
.instr_compressed_i ( instr_rdata_c_i ),
.instr_is_compressed_i ( instr_is_compressed_i ),
// from prefetcher // from prefetcher
.instr_req_o ( instr_req_o ), .instr_req_o ( instr_req_o ),
@ -494,6 +499,7 @@ module ibex_id_stage #(
.exc_cause_o ( exc_cause_o ), .exc_cause_o ( exc_cause_o ),
// LSU // LSU
.lsu_addr_last_i ( lsu_addr_last_i ),
.load_err_i ( lsu_load_err_i ), .load_err_i ( lsu_load_err_i ),
.store_err_i ( lsu_store_err_i ), .store_err_i ( lsu_store_err_i ),
@ -517,12 +523,13 @@ module ibex_id_stage #(
.exc_kill_o ( exc_kill ), .exc_kill_o ( exc_kill ),
// CSR Controller Signals // CSR Controller Signals
.csr_save_cause_o ( csr_save_cause_o ),
.csr_cause_o ( csr_cause_o ),
.csr_save_if_o ( csr_save_if_o ), .csr_save_if_o ( csr_save_if_o ),
.csr_save_id_o ( csr_save_id_o ), .csr_save_id_o ( csr_save_id_o ),
.csr_restore_mret_id_o ( csr_restore_mret_id_o ), .csr_restore_mret_id_o ( csr_restore_mret_id_o ),
.csr_restore_dret_id_o ( csr_restore_dret_id_o ), .csr_restore_dret_id_o ( csr_restore_dret_id_o ),
.csr_save_cause_o ( csr_save_cause_o ),
.csr_cause_o ( csr_cause_o ),
.csr_mtval_o ( csr_mtval_o ),
// Debug Signal // Debug Signal
.debug_cause_o ( debug_cause_o ), .debug_cause_o ( debug_cause_o ),

View file

@ -40,48 +40,50 @@ module ibex_if_stage #(
input logic [31:0] boot_addr_i, input logic [31:0] boot_addr_i,
// instruction request control // instruction request control
input logic req_i, input logic req_i,
// instruction cache interface // instruction cache interface
output logic instr_req_o, output logic instr_req_o,
output logic [31:0] instr_addr_o, output logic [31:0] instr_addr_o,
input logic instr_gnt_i, input logic instr_gnt_i,
input logic instr_rvalid_i, input logic instr_rvalid_i,
input logic [31:0] instr_rdata_i, input logic [31:0] instr_rdata_i,
// Output of IF Pipeline stage
output logic instr_valid_id_o, // instr in IF/ID is valid
output logic [31:0] instr_rdata_id_o, // read instr is sampled and sent
// to ID stage for decoding
output logic is_compressed_id_o, // compressed decoder thinks this is
// a compressed instr
`ifdef RVFI
output logic [15:0] instr_rdata_compressed_o,
`endif
output logic illegal_c_insn_id_o, // compressed decoder thinks this is // Output of IF Pipeline stage
// an invalid instr output logic instr_valid_id_o, // instr in IF-ID is valid
output logic [31:0] instr_rdata_id_o, // instr for ID stage
output logic [15:0] instr_rdata_c_id_o, // compressed instr for ID stage
// (mtval), meaningful only if
// instr_is_compressed_id_o = 1'b1
output logic instr_is_compressed_id_o, // compressed decoder thinks this
// is a compressed instr
output logic illegal_c_insn_id_o, // compressed decoder thinks this
// is an invalid instr
output logic [31:0] pc_if_o, output logic [31:0] pc_if_o,
output logic [31:0] pc_id_o, output logic [31:0] pc_id_o,
// Forwarding ports - control signals // Forwarding ports - control signals
input logic clear_instr_valid_i, // clear instr valid bit in IF/ID input logic clear_instr_valid_i, // clear instr valid bit in IF-ID
input logic pc_set_i, // set the PC to a new value input logic pc_set_i, // set the PC to a new value
input logic [31:0] exception_pc_reg_i, // address used to restore PC when input logic [31:0] exception_pc_reg_i, // PC to restore after handling
// the interrupt/exception is served // the interrupt/exception
input logic [31:0] depc_i, // address used to restore PC when input logic [31:0] depc_i, // PC to restore after handling
// the debug request is served // the debug request
input ibex_defines::pc_sel_e pc_mux_i, // selector for PC multiplexer input ibex_defines::pc_sel_e pc_mux_i, // selector for PC multiplexer
input ibex_defines::exc_pc_sel_e exc_pc_mux_i, // selects ISR address input ibex_defines::exc_pc_sel_e exc_pc_mux_i, // selects ISR address
input ibex_defines::exc_cause_e exc_vec_pc_mux_i, // selects ISR address for vectorized input ibex_defines::exc_cause_e exc_vec_pc_mux_i, // selects ISR address for
// interrupt lines // vectorized interrupt lines
// jump and branch target and decision // jump and branch target and decision
input logic [31:0] jump_target_ex_i, // jump target address input logic [31:0] jump_target_ex_i, // jump target address
// pipeline stall // pipeline stall
input logic halt_if_i, input logic halt_if_i,
input logic id_ready_i, input logic id_ready_i,
output logic if_valid_o, output logic if_valid_o,
// misc signals // misc signals
output logic if_busy_o, // IF stage is busy fetching instr output logic if_busy_o, // IF stage is busy fetching instr
output logic perf_imiss_o // instr fetch miss output logic perf_imiss_o // instr fetch miss
); );
import ibex_defines::*; import ibex_defines::*;
@ -214,13 +216,13 @@ module ibex_if_stage #(
// to ease timing closure // to ease timing closure
logic [31:0] instr_decompressed; logic [31:0] instr_decompressed;
logic illegal_c_insn; logic illegal_c_insn;
logic instr_compressed_int; logic instr_is_compressed_int;
ibex_compressed_decoder compressed_decoder_i ( ibex_compressed_decoder compressed_decoder_i (
.instr_i ( fetch_rdata ), .instr_i ( fetch_rdata ),
.instr_o ( instr_decompressed ), .instr_o ( instr_decompressed ),
.is_compressed_o ( instr_compressed_int ), .is_compressed_o ( instr_is_compressed_int ),
.illegal_instr_o ( illegal_c_insn ) .illegal_instr_o ( illegal_c_insn )
); );
// IF-ID pipeline registers, frozen when the ID stage is stalled // IF-ID pipeline registers, frozen when the ID stage is stalled
@ -228,21 +230,17 @@ module ibex_if_stage #(
if (!rst_ni) begin if (!rst_ni) begin
instr_valid_id_o <= 1'b0; instr_valid_id_o <= 1'b0;
instr_rdata_id_o <= '0; instr_rdata_id_o <= '0;
instr_rdata_c_id_o <= '0;
instr_is_compressed_id_o <= 1'b0;
illegal_c_insn_id_o <= 1'b0; illegal_c_insn_id_o <= 1'b0;
is_compressed_id_o <= 1'b0;
`ifdef RVFI
instr_rdata_compressed_o <= '0;
`endif
pc_id_o <= '0; pc_id_o <= '0;
end else begin end else begin
if (if_valid_o) begin if (if_valid_o) begin
instr_valid_id_o <= 1'b1; instr_valid_id_o <= 1'b1;
instr_rdata_id_o <= instr_decompressed; instr_rdata_id_o <= instr_decompressed;
instr_rdata_c_id_o <= fetch_rdata[15:0];
instr_is_compressed_id_o <= instr_is_compressed_int;
illegal_c_insn_id_o <= illegal_c_insn; illegal_c_insn_id_o <= illegal_c_insn;
is_compressed_id_o <= instr_compressed_int;
`ifdef RVFI
instr_rdata_compressed_o <= fetch_rdata[15:0];
`endif
pc_id_o <= pc_if_o; pc_id_o <= pc_if_o;
end else if (clear_instr_valid_i) begin end else if (clear_instr_valid_i) begin
instr_valid_id_o <= 1'b0; instr_valid_id_o <= 1'b0;

View file

@ -52,17 +52,19 @@ module ibex_load_store_unit (
output logic [31:0] data_rdata_ex_o, // requested data -> to EX output logic [31:0] data_rdata_ex_o, // requested data -> to EX
input logic data_req_ex_i, // data request -> from EX input logic data_req_ex_i, // data request -> from EX
input logic [31:0] adder_result_ex_i, input logic [31:0] adder_result_ex_i, // address computed in ALU -> from EX
output logic data_misaligned_o, // misaligned access detected -> to controller output logic data_misaligned_o, // misaligned access detected -> to controller
output logic [31:0] misaligned_addr_o, output logic [31:0] addr_last_o, // address of last transaction -> to controller
// -> mtval
// -> AGU for misaligned accesses
// exception signals // exception signals
output logic load_err_o, output logic load_err_o,
output logic store_err_o, output logic store_err_o,
// stall signal // stall signal
output logic lsu_update_addr_o, // LSU ready for new data in EX stage output logic lsu_update_addr_o, // LSU ready for new data in EX stage
output logic data_valid_o, output logic data_valid_o,
output logic busy_o output logic busy_o
@ -70,6 +72,7 @@ module ibex_load_store_unit (
logic [31:0] data_addr; logic [31:0] data_addr;
logic [31:0] data_addr_w_aligned; logic [31:0] data_addr_w_aligned;
logic [31:0] addr_last_q, addr_last_n;
// registers for data_rdata alignment and sign extension // registers for data_rdata alignment and sign extension
logic [1:0] data_type_q; logic [1:0] data_type_q;
@ -85,7 +88,6 @@ module ibex_load_store_unit (
logic misaligned_st; // high if we are currently performing the second part logic misaligned_st; // high if we are currently performing the second part
// of a misaligned store // of a misaligned store
logic data_misaligned, data_misaligned_q; logic data_misaligned, data_misaligned_q;
logic increase_address;
typedef enum logic [2:0] { typedef enum logic [2:0] {
IDLE, WAIT_GNT_MIS, WAIT_RVALID_MIS, WAIT_GNT, WAIT_RVALID IDLE, WAIT_GNT_MIS, WAIT_RVALID_MIS, WAIT_GNT, WAIT_RVALID
@ -289,19 +291,26 @@ module ibex_load_store_unit (
endcase //~case(rdata_type_q) endcase //~case(rdata_type_q)
end end
// store last output address for mtval + AGU for misaligned transactions
// do not update in case of errors, mtval needs the failing address
always_comb begin
addr_last_n = addr_last_q;
if (data_req_o & data_gnt_i & ~(load_err_o | store_err_o)) begin
addr_last_n = data_addr_o;
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin if (!rst_ni) begin
ls_fsm_cs <= IDLE; ls_fsm_cs <= IDLE;
addr_last_q <= '0;
rdata_q <= '0; rdata_q <= '0;
data_misaligned_q <= '0; data_misaligned_q <= '0;
misaligned_addr_o <= 32'b0;
end else begin end else begin
ls_fsm_cs <= ls_fsm_ns; ls_fsm_cs <= ls_fsm_ns;
addr_last_q <= addr_last_n;
if (lsu_update_addr_o) begin if (lsu_update_addr_o) begin
data_misaligned_q <= data_misaligned; data_misaligned_q <= data_misaligned;
if (increase_address) begin
misaligned_addr_o <= data_addr;
end
end end
if (data_rvalid_i && !data_we_q) begin if (data_rvalid_i && !data_we_q) begin
// if we have detected a misaligned access, and we are // if we have detected a misaligned access, and we are
@ -333,6 +342,8 @@ module ibex_load_store_unit (
assign misaligned_st = data_misaligned_q; assign misaligned_st = data_misaligned_q;
assign addr_last_o = addr_last_q;
// to know what kind of error to signal, we need to know the type of the transaction to which // to know what kind of error to signal, we need to know the type of the transaction to which
// the outsanding rvalid belongs. // the outsanding rvalid belongs.
assign load_err_o = data_err_i & data_rvalid_i & ~data_we_q; assign load_err_o = data_err_i & data_rvalid_i & ~data_we_q;
@ -347,17 +358,15 @@ module ibex_load_store_unit (
lsu_update_addr_o = 1'b0; lsu_update_addr_o = 1'b0;
data_valid_o = 1'b0; data_valid_o = 1'b0;
increase_address = 1'b0;
data_misaligned_o = 1'b0; data_misaligned_o = 1'b0;
unique case(ls_fsm_cs) unique case(ls_fsm_cs)
// starts from not active and stays in IDLE until request was granted // starts from not active and stays in IDLE until request was granted
IDLE: begin IDLE: begin
if (data_req_ex_i) begin if (data_req_ex_i) begin
data_req_o = data_req_ex_i; data_req_o = data_req_ex_i;
if (data_gnt_i) begin if (data_gnt_i) begin
lsu_update_addr_o = 1'b1; lsu_update_addr_o = 1'b1;
increase_address = data_misaligned;
ls_fsm_ns = data_misaligned ? WAIT_RVALID_MIS : WAIT_RVALID; ls_fsm_ns = data_misaligned ? WAIT_RVALID_MIS : WAIT_RVALID;
end else begin end else begin
ls_fsm_ns = data_misaligned ? WAIT_GNT_MIS : WAIT_GNT; ls_fsm_ns = data_misaligned ? WAIT_GNT_MIS : WAIT_GNT;
@ -369,15 +378,12 @@ module ibex_load_store_unit (
data_req_o = 1'b1; data_req_o = 1'b1;
if (data_gnt_i) begin if (data_gnt_i) begin
lsu_update_addr_o = 1'b1; lsu_update_addr_o = 1'b1;
increase_address = data_misaligned;
ls_fsm_ns = WAIT_RVALID_MIS; ls_fsm_ns = WAIT_RVALID_MIS;
end end
end // WAIT_GNT_MIS end // WAIT_GNT_MIS
// wait for rvalid in WB stage and send a new request if there is any // wait for rvalid in WB stage and send a new request if there is any
WAIT_RVALID_MIS: begin WAIT_RVALID_MIS: begin
//increase_address goes down, we already have the proper address
increase_address = 1'b0;
//tell the controller to update the address //tell the controller to update the address
data_misaligned_o = 1'b1; data_misaligned_o = 1'b1;
data_req_o = 1'b0; data_req_o = 1'b0;