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
9 changes: 9 additions & 0 deletions rtl/cv32e40x_alignment_buffer.sv
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ module cv32e40x_alignment_buffer import cv32e40x_pkg::*;
output logic [31:0] fetch_branch_addr_o,
output logic fetch_ptr_access_o,
input logic fetch_ptr_access_i,
output privlvl_t fetch_priv_lvl_o,
input privlvl_t fetch_priv_lvl_i,

// Resp interface
input logic resp_valid_i,
Expand All @@ -56,6 +58,7 @@ module cv32e40x_alignment_buffer import cv32e40x_pkg::*;
input logic instr_ready_i,
output inst_resp_t instr_instr_o,
output logic [31:0] instr_addr_o,
output privlvl_t instr_priv_lvl_o,
output logic instr_is_clic_ptr_o, // True CLIC pointer after taking a CLIC SHV interrupt
output logic instr_is_mret_ptr_o, // CLIC pointer due to restarting pionter fetch during mret
output logic instr_is_tbljmp_ptr_o,
Expand Down Expand Up @@ -580,4 +583,10 @@ module cv32e40x_alignment_buffer import cv32e40x_pkg::*;

// Signal that a pointer is about to be fetched
assign fetch_ptr_access_o = (ctrl_fsm_i.pc_set && (ctrl_fsm_i.pc_set_clicv || ctrl_fsm_i.pc_set_tbljmp));

// Set privilege level to prefetcher
assign fetch_priv_lvl_o = PRIV_LVL_M;

// Set privilege level to IF stage
assign instr_priv_lvl_o = fetch_priv_lvl_i;
endmodule
3 changes: 3 additions & 0 deletions rtl/cv32e40x_core.sv
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ module cv32e40x_core import cv32e40x_pkg::*;

logic [31:0] pc_if; // Program counter in IF stage
logic ptr_in_if; // IF stage contains a pointer
privlvl_t priv_lvl_if; // IF stage privilege level

// Jump and branch target and decision (EX->IF)
logic [31:0] jump_target_id;
Expand Down Expand Up @@ -463,6 +464,7 @@ module cv32e40x_core import cv32e40x_pkg::*;
.csr_mtvec_init_o ( csr_mtvec_init_if ),
.if_busy_o ( if_busy ),
.ptr_in_if_o ( ptr_in_if ),
.priv_lvl_if_o ( priv_lvl_if ),

.first_op_o ( first_op_if ),
.last_op_o ( last_op_if ),
Expand Down Expand Up @@ -817,6 +819,7 @@ module cv32e40x_core import cv32e40x_pkg::*;
.etrigger_wb_o ( etrigger_wb ),
.pc_if_i ( pc_if ),
.ptr_in_if_i ( ptr_in_if ),
.priv_lvl_if_i ( priv_lvl_if ),
.lsu_valid_ex_i ( lsu_valid_ex ),
.lsu_addr_ex_i ( lsu_addr_ex ),
.lsu_we_ex_i ( lsu_we_ex ),
Expand Down
57 changes: 29 additions & 28 deletions rtl/cv32e40x_cs_registers.sv
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*;
// Debug
input logic [31:0] pc_if_i,
input logic ptr_in_if_i,
input privlvl_t priv_lvl_if_i,
output logic trigger_match_if_o,
output logic trigger_match_ex_o,
output logic etrigger_wb_o,
Expand Down Expand Up @@ -1499,48 +1500,48 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*;
)
debug_triggers_i
(
.clk ( clk ),
.rst_n ( rst_n ),
.clk ( clk ),
.rst_n ( rst_n ),

// CSR inputs write inputs
.csr_wdata_i ( csr_wdata_int),
.tselect_we_i ( tselect_we ),
.tdata1_we_i ( tdata1_we ),
.tdata2_we_i ( tdata2_we ),
.tdata3_we_i ( tdata3_we ),
.tinfo_we_i ( tinfo_we ),
.tcontrol_we_i ( tcontrol_we ),
.csr_wdata_i ( csr_wdata_int ),
.tselect_we_i ( tselect_we ),
.tdata1_we_i ( tdata1_we ),
.tdata2_we_i ( tdata2_we ),
.tdata3_we_i ( tdata3_we ),
.tinfo_we_i ( tinfo_we ),
.tcontrol_we_i ( tcontrol_we ),

// CSR read data outputs
.tselect_rdata_o ( tselect_rdata ),
.tdata1_rdata_o ( tdata1_rdata ),
.tdata2_rdata_o ( tdata2_rdata ),
.tdata3_rdata_o ( tdata3_rdata ),
.tinfo_rdata_o ( tinfo_rdata ),
.tcontrol_rdata_o ( tcontrol_rdata),
.tselect_rdata_o ( tselect_rdata ),
.tdata1_rdata_o ( tdata1_rdata ),
.tdata2_rdata_o ( tdata2_rdata ),
.tdata3_rdata_o ( tdata3_rdata ),
.tinfo_rdata_o ( tinfo_rdata ),
.tcontrol_rdata_o ( tcontrol_rdata ),

// IF stage inputs
.pc_if_i ( pc_if_i ),
.ptr_in_if_i ( ptr_in_if_i ),
.priv_lvl_if_i ( PRIV_LVL_M ),
.pc_if_i ( pc_if_i ),
.ptr_in_if_i ( ptr_in_if_i ),
.priv_lvl_if_i ( priv_lvl_if_i ),

// LSU inputs
.lsu_valid_ex_i ( lsu_valid_ex_i),
.lsu_addr_ex_i ( lsu_addr_ex_i ),
.lsu_we_ex_i ( lsu_we_ex_i ),
.lsu_be_ex_i ( lsu_be_ex_i ),
.priv_lvl_ex_i ( PRIV_LVL_M ),
.lsu_valid_ex_i ( lsu_valid_ex_i ),
.lsu_addr_ex_i ( lsu_addr_ex_i ),
.lsu_we_ex_i ( lsu_we_ex_i ),
.lsu_be_ex_i ( lsu_be_ex_i ),
.priv_lvl_ex_i ( id_ex_pipe_i.priv_lvl ),

// WB inputs
.priv_lvl_wb_i ( PRIV_LVL_M ),
.priv_lvl_wb_i ( ex_wb_pipe_i.priv_lvl ),

// Controller inputs
.ctrl_fsm_i ( ctrl_fsm_i ),
.ctrl_fsm_i ( ctrl_fsm_i ),

// Trigger match outputs
.trigger_match_if_o ( trigger_match_if_o ),
.trigger_match_ex_o ( trigger_match_ex_o ),
.etrigger_wb_o ( etrigger_wb_o )
.trigger_match_if_o ( trigger_match_if_o ),
.trigger_match_ex_o ( trigger_match_ex_o ),
.etrigger_wb_o ( etrigger_wb_o )
);


Expand Down
4 changes: 3 additions & 1 deletion rtl/cv32e40x_ex_stage.sv
Original file line number Diff line number Diff line change
Expand Up @@ -356,12 +356,14 @@ module cv32e40x_ex_stage import cv32e40x_pkg::*;
ex_wb_pipe_o.first_op <= 1'b0;
ex_wb_pipe_o.last_op <= 1'b0;
ex_wb_pipe_o.abort_op <= 1'b0;

ex_wb_pipe_o.priv_lvl <= PRIV_LVL_M;
end
else
begin
if (ex_valid_o && wb_ready_i) begin
ex_wb_pipe_o.instr_valid <= 1'b1;

ex_wb_pipe_o.priv_lvl <= id_ex_pipe_i.priv_lvl;
ex_wb_pipe_o.last_op <= last_op_o;
ex_wb_pipe_o.first_op <= first_op_o;
ex_wb_pipe_o.abort_op <= id_ex_pipe_i.abort_op; // MPU exceptions and watchpoint triggers have WB timing and will not impact ex_wb_pipe.abort_op
Expand Down
2 changes: 2 additions & 0 deletions rtl/cv32e40x_id_stage.sv
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,7 @@ module cv32e40x_id_stage import cv32e40x_pkg::*;
id_ex_pipe_o.xif_en <= 1'b0;
id_ex_pipe_o.xif_meta <= '0;

id_ex_pipe_o.priv_lvl <= PRIV_LVL_M;
id_ex_pipe_o.illegal_insn <= 1'b0;

id_ex_pipe_o.rf_we <= 1'b0;
Expand All @@ -568,6 +569,7 @@ module cv32e40x_id_stage import cv32e40x_pkg::*;
end else begin
// normal pipeline unstall case
if (id_valid_o && ex_ready_i) begin
id_ex_pipe_o.priv_lvl <= if_id_pipe_i.priv_lvl;
id_ex_pipe_o.instr_valid <= 1'b1;
id_ex_pipe_o.last_op <= last_op_o;
id_ex_pipe_o.first_op <= first_op_o;
Expand Down
12 changes: 10 additions & 2 deletions rtl/cv32e40x_if_stage.sv
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ module cv32e40x_if_stage import cv32e40x_pkg::*;
output logic csr_mtvec_init_o, // Tell CS regfile to init mtvec
output logic if_busy_o, // Is the IF stage busy fetching instructions?
output logic ptr_in_if_o, // The IF stage currently holds a pointer
output privlvl_t priv_lvl_if_o, // Privilege level of the instruction currently in IF

output logic first_op_o,
output logic last_op_o,
Expand Down Expand Up @@ -98,6 +99,7 @@ module cv32e40x_if_stage import cv32e40x_pkg::*;
logic prefetch_valid;
logic prefetch_ready;
inst_resp_t prefetch_instr;
privlvl_t prefetch_priv_lvl;

logic prefetch_is_clic_ptr;
logic prefetch_is_mret_ptr;
Expand Down Expand Up @@ -195,6 +197,7 @@ module cv32e40x_if_stage import cv32e40x_pkg::*;
.prefetch_valid_o ( prefetch_valid ),
.prefetch_instr_o ( prefetch_instr ),
.prefetch_addr_o ( pc_if_o ),
.prefetch_priv_lvl_o ( prefetch_priv_lvl ),
.prefetch_is_clic_ptr_o ( prefetch_is_clic_ptr ),
.prefetch_is_mret_ptr_o ( prefetch_is_mret_ptr ),
.prefetch_is_tbljmp_ptr_o ( prefetch_is_tbljmp_ptr ),
Expand All @@ -219,7 +222,7 @@ module cv32e40x_if_stage import cv32e40x_pkg::*;
assign core_trans.addr = prefetch_trans_addr;
assign core_trans.dbg = ctrl_fsm_i.debug_mode_if;
assign core_trans.prot[0] = 1'b0; // Transfers from IF stage all instruction fetches
assign core_trans.prot[2:1] = PRIV_LVL_M; // Machine mode
assign core_trans.prot[2:1] = prefetch_priv_lvl; // Machine mode
assign core_trans.memtype = 2'b00; // memtype is assigned in the MPU, tie off.

cv32e40x_mpu
Expand Down Expand Up @@ -325,6 +328,9 @@ module cv32e40x_if_stage import cv32e40x_pkg::*;
// Set flag to indicate that instruction/sequence will be aborted due to known exceptions or trigger match
assign abort_op_o = instr_decompressed.bus_resp.err || (instr_decompressed.mpu_status != MPU_OK) || trigger_match_i;

// Signal current privilege level of IF
assign priv_lvl_if_o = prefetch_priv_lvl;

// Populate instruction meta data
// Fields 'compressed' and 'tbljmp' keep their old value by default.
// - In case of a table jump we need the fields to stay as 'compressed=1' and 'tbljmp=1'
Expand All @@ -350,6 +356,7 @@ module cv32e40x_if_stage import cv32e40x_pkg::*;
if_id_pipe_o.pc <= '0;
if_id_pipe_o.illegal_c_insn <= 1'b0;
if_id_pipe_o.compressed_instr <= '0;
if_id_pipe_o.priv_lvl <= PRIV_LVL_M;
if_id_pipe_o.trigger_match <= 1'b0;
if_id_pipe_o.xif_id <= '0;
if_id_pipe_o.ptr <= '0;
Expand All @@ -362,11 +369,12 @@ module cv32e40x_if_stage import cv32e40x_pkg::*;
if (if_valid_o && id_ready_i) begin
if_id_pipe_o.instr_valid <= 1'b1;
if_id_pipe_o.instr_meta <= instr_meta_n;

// seq_valid implies no illegal instruction, sequencer successfully decoded an instruction.
// compressed decoder will still raise illegal_c_insn as it doesn't (currently) recognize Zc push/pop/dmove
if_id_pipe_o.illegal_c_insn <= seq_valid ? 1'b0 : illegal_c_insn;


if_id_pipe_o.priv_lvl <= prefetch_priv_lvl;
if_id_pipe_o.trigger_match <= trigger_match_i;
if_id_pipe_o.xif_id <= xif_id;
if_id_pipe_o.last_op <= last_op_o;
Expand Down
9 changes: 8 additions & 1 deletion rtl/cv32e40x_prefetch_unit.sv
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ module cv32e40x_prefetch_unit import cv32e40x_pkg::*;
output logic prefetch_valid_o,
output inst_resp_t prefetch_instr_o,
output logic [31:0] prefetch_addr_o,
output privlvl_t prefetch_priv_lvl_o,
output logic prefetch_is_clic_ptr_o,
output logic prefetch_is_mret_ptr_o,
output logic prefetch_is_tbljmp_ptr_o,
Expand All @@ -70,6 +71,8 @@ module cv32e40x_prefetch_unit import cv32e40x_pkg::*;
logic [31:0] fetch_branch_addr;
logic fetch_ptr_access;
logic fetch_ptr_resp;
privlvl_t fetch_priv_lvl_access;
privlvl_t fetch_priv_lvl_resp;



Expand All @@ -92,7 +95,8 @@ module cv32e40x_prefetch_unit import cv32e40x_pkg::*;
.fetch_ready_o ( fetch_ready ),
.fetch_ptr_access_i ( fetch_ptr_access ),
.fetch_ptr_access_o ( fetch_ptr_resp ),

.fetch_priv_lvl_access_i ( fetch_priv_lvl_access),
.fetch_priv_lvl_access_o ( fetch_priv_lvl_resp ),
.trans_valid_o ( trans_valid_o ),
.trans_ready_i ( trans_ready_i ),
.trans_addr_o ( trans_addr_o )
Expand Down Expand Up @@ -121,6 +125,8 @@ module cv32e40x_prefetch_unit import cv32e40x_pkg::*;
.fetch_branch_addr_o ( fetch_branch_addr ),
.fetch_ptr_access_o ( fetch_ptr_access ),
.fetch_ptr_access_i ( fetch_ptr_resp ),
.fetch_priv_lvl_o ( fetch_priv_lvl_access ),
.fetch_priv_lvl_i ( fetch_priv_lvl_resp ),

.resp_valid_i ( resp_valid_i ),
.resp_i ( resp_i ),
Expand All @@ -132,6 +138,7 @@ module cv32e40x_prefetch_unit import cv32e40x_pkg::*;
.instr_ready_i ( prefetch_ready_i ),
.instr_instr_o ( prefetch_instr_o ),
.instr_addr_o ( prefetch_addr_o ),
.instr_priv_lvl_o ( prefetch_priv_lvl_o ),
.instr_is_clic_ptr_o ( prefetch_is_clic_ptr_o ),
.instr_is_mret_ptr_o ( prefetch_is_mret_ptr_o ),
.instr_is_tbljmp_ptr_o ( prefetch_is_tbljmp_ptr_o)
Expand Down
11 changes: 9 additions & 2 deletions rtl/cv32e40x_prefetcher.sv
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
// //
////////////////////////////////////////////////////////////////////////////////

module cv32e40x_prefetcher
module cv32e40x_prefetcher import cv32e40x_pkg::*;
#(
parameter bit SMCLIC = 1'b0
)
Expand All @@ -52,6 +52,8 @@ module cv32e40x_prefetcher
output logic fetch_ready_o,
input logic fetch_ptr_access_i, // Access is data access (CLIC) // todo: add similar for table jump
output logic fetch_ptr_access_o, // Handshake is for a pointer access (CLIC and Zc)
input privlvl_t fetch_priv_lvl_access_i, // Priv level of access
output privlvl_t fetch_priv_lvl_access_o, // Priv level for the (fetch_valid_i && fetch_ready_o) handshake, indicating privilege level of the requested instruction.

// Transaction request interface
output logic trans_valid_o, // Transaction request valid (to bus interface adapter)
Expand All @@ -61,13 +63,13 @@ module cv32e40x_prefetcher

);

import cv32e40x_pkg::*;

prefetch_state_e state_q, next_state;

// Transaction address
logic [31:0] trans_addr_q, trans_addr_incr;
logic trans_ptr_access_q;
privlvl_t trans_priv_lvl_q;

// Increment address (address will be made word aligned at core level)
assign trans_addr_incr = {trans_addr_q[31:1], 1'b0} + 32'd4;
Expand All @@ -86,6 +88,7 @@ module cv32e40x_prefetcher
next_state = state_q;
trans_addr_o = trans_addr_q;
fetch_ptr_access_o = trans_ptr_access_q;
fetch_priv_lvl_access_o = trans_priv_lvl_q;

case(state_q)
// Default state (pass on branch target address or transaction with incremented address)
Expand All @@ -96,9 +99,11 @@ module cv32e40x_prefetcher
if (fetch_branch_i) begin
trans_addr_o = fetch_branch_addr_i;
fetch_ptr_access_o = fetch_ptr_access_i;
fetch_priv_lvl_access_o = fetch_priv_lvl_access_i;
end else begin
trans_addr_o = trans_addr_incr;
fetch_ptr_access_o = 1'b0; // No incremental pointer fetches
fetch_priv_lvl_access_o = fetch_priv_lvl_access_i;
end
end
if ((fetch_branch_i) && !(trans_valid_o && trans_ready_i)) begin
Expand All @@ -114,6 +119,7 @@ module cv32e40x_prefetcher
// yet have its target address accepted by the bus interface adapter.
trans_addr_o = fetch_branch_i ? fetch_branch_addr_i : trans_addr_q;
fetch_ptr_access_o = fetch_branch_i ? fetch_ptr_access_i : trans_ptr_access_q;
fetch_priv_lvl_access_o = fetch_branch_i ? fetch_priv_lvl_access_i : trans_priv_lvl_q;
if (trans_valid_o && trans_ready_i) begin
// Transaction with branch target address has been accepted. Start regular prefetch again.
next_state = IDLE;
Expand Down Expand Up @@ -143,6 +149,7 @@ module cv32e40x_prefetcher
if (fetch_branch_i || (trans_valid_o && trans_ready_i)) begin
trans_addr_q <= trans_addr_o;
trans_ptr_access_q <= fetch_ptr_access_o;
trans_priv_lvl_q <= fetch_priv_lvl_access_o;
end
end
end
Expand Down
5 changes: 5 additions & 0 deletions rtl/include/cv32e40x_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -1074,6 +1074,7 @@ typedef struct packed {
logic [31:0] pc;
logic [15:0] compressed_instr;
logic illegal_c_insn;
privlvl_t priv_lvl;
logic trigger_match;
logic [31:0] xif_id; // ID of offloaded instruction
logic [31:0] ptr; // Flops to hold 32-bit pointer
Expand Down Expand Up @@ -1143,6 +1144,8 @@ typedef struct packed {
instr_meta_t instr_meta;
logic instr_valid; // instruction in EX is valid

privlvl_t priv_lvl;

// eXtension interface
logic xif_en; // Instruction has been offloaded via eXtension interface
xif_meta_t xif_meta; // xif meta struct
Expand Down Expand Up @@ -1184,6 +1187,8 @@ typedef struct packed {
logic instr_valid; // instruction in WB is valid
logic illegal_insn;

privlvl_t priv_lvl;

logic sys_en;
logic sys_dret_insn;
logic sys_ebrk_insn;
Expand Down