mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-25 06:27:22 -04:00
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:
parent
5171ee79f0
commit
b22a6a10de
8 changed files with 293 additions and 244 deletions
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
@ -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:;
|
||||||
|
|
|
@ -110,7 +110,8 @@ 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 instr_is_compressed_id;
|
||||||
logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage
|
logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage
|
||||||
logic illegal_insn_id; // ID stage sees an illegal instruction
|
logic illegal_insn_id; // ID stage sees an illegal instruction
|
||||||
logic [31:0] pc_if; // Program counter in IF stage
|
logic [31:0] pc_if; // Program counter in IF stage
|
||||||
|
@ -118,9 +119,10 @@ module ibex_core #(
|
||||||
|
|
||||||
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
|
pc_sel_e pc_mux_id; // Mux selector for next PC
|
||||||
exc_pc_sel_e exc_pc_mux_id; // Mux selector for exception PC
|
exc_pc_sel_e exc_pc_mux_id; // Mux selector for exception PC
|
||||||
exc_cause_e exc_cause; // Exception cause + IRQ ID for vectorized interrupt lines
|
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;
|
||||||
|
@ -168,7 +170,8 @@ module ibex_core #(
|
||||||
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;
|
||||||
|
@ -196,12 +199,13 @@ module ibex_core #(
|
||||||
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;
|
||||||
|
@ -315,10 +318,8 @@ module ibex_core #(
|
||||||
// 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 ),
|
|
||||||
`endif
|
|
||||||
.illegal_c_insn_id_o ( illegal_c_insn_id ),
|
.illegal_c_insn_id_o ( illegal_c_insn_id ),
|
||||||
.pc_if_o ( pc_if ),
|
.pc_if_o ( pc_if ),
|
||||||
.pc_id_o ( pc_id ),
|
.pc_id_o ( pc_id ),
|
||||||
|
@ -368,6 +369,8 @@ module ibex_core #(
|
||||||
// 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_rdata_c_i ( instr_rdata_c_id ),
|
||||||
|
.instr_is_compressed_i ( instr_is_compressed_id ),
|
||||||
.instr_req_o ( instr_req_int ),
|
.instr_req_o ( instr_req_int ),
|
||||||
|
|
||||||
// Jumps and branches
|
// Jumps and branches
|
||||||
|
@ -381,7 +384,6 @@ module ibex_core #(
|
||||||
.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 ),
|
||||||
|
|
||||||
|
@ -407,12 +409,13 @@ module ibex_core #(
|
||||||
// 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 ),
|
||||||
|
.csr_mtval_o ( csr_mtval ),
|
||||||
.illegal_csr_insn_i ( illegal_csr_insn_id ),
|
.illegal_csr_insn_i ( illegal_csr_insn_id ),
|
||||||
|
|
||||||
// LSU
|
// LSU
|
||||||
|
@ -424,7 +427,7 @@ module ibex_core #(
|
||||||
.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 ),
|
||||||
|
@ -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 ),
|
||||||
|
@ -571,6 +574,7 @@ module ibex_core #(
|
||||||
.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 ),
|
||||||
|
@ -596,14 +600,15 @@ module ibex_core #(
|
||||||
.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 ),
|
||||||
|
.csr_mtval_i ( csr_mtval ),
|
||||||
.illegal_csr_insn_o ( illegal_csr_insn_id ),
|
.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 ),
|
||||||
|
@ -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
|
||||||
|
|
|
@ -66,9 +66,9 @@ 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
|
||||||
|
@ -76,7 +76,7 @@ module ibex_cs_registers #(
|
||||||
// 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
|
||||||
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 ),
|
||||||
|
|
|
@ -40,37 +40,38 @@ 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
|
||||||
|
@ -79,6 +80,7 @@ module ibex_if_stage #(
|
||||||
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
|
||||||
|
@ -214,12 +216,12 @@ 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 )
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
|
@ -52,10 +52,12 @@ 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,
|
||||||
|
@ -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,7 +358,6 @@ 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)
|
||||||
|
@ -357,7 +367,6 @@ module ibex_load_store_unit (
|
||||||
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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue