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
33 changes: 32 additions & 1 deletion rtl/cv32e40x_alignment_buffer.sv
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ module cv32e40x_alignment_buffer import cv32e40x_pkg::*;
// Controller fsm inputs
input ctrl_fsm_t ctrl_fsm_i,

// Privilige level control
input privlvlctrl_t priv_lvl_ctrl_i,

// Branch control
input logic [31:0] branch_addr_i,
output logic prefetch_busy_o,
Expand Down Expand Up @@ -104,6 +107,9 @@ module cv32e40x_alignment_buffer import cv32e40x_pkg::*;
// resp_valid gated while flushing
logic resp_valid_gated;

// Privilege level for the IF stage
privlvl_t instr_priv_lvl_q;

// CLIC vectoring
// Flag for signalling that results is a CLIC function pointer
logic is_clic_ptr_q;
Expand Down Expand Up @@ -624,7 +630,32 @@ module cv32e40x_alignment_buffer import cv32e40x_pkg::*;
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;
// Privilege level must be updated immediatly to allow the
// IF stage to do access permission checks with the correct privilege level
//
// When an mret is in the ID stage, a jump is performed and the privilege level may be changed.
// When the privilege level changes, priv_lvl_ctrl_i.priv_lvl_set is 1, and the new privilege level
// is visible on priv_lvl_ctrl_i.priv_lvl. When priv_lvl_set is 0, the privilege level
// as seen from the WB stage (flop output) is visible on priv_lvl_ctrl_i.priv_lvl.
//
// This means that in the time between the mret jump and privilege level change in ID and the time when
// the mret retires in WB, the old privilege level is visible on pvi_lvl_ctrl_i.priv_lvl.
// To ensure the correct privilege level for prefetches, the alignment_buffer remembers the last commanded
// privilege level in the instr_priv_lvl_q flops.
assign fetch_priv_lvl_o = priv_lvl_ctrl_i.priv_lvl_set ? priv_lvl_ctrl_i.priv_lvl:
instr_priv_lvl_q;

// Privilege level for the IF stage
always_ff @(posedge clk, negedge rst_n) begin
if (!rst_n) begin
instr_priv_lvl_q <= PRIV_LVL_M;
end
else begin
if (priv_lvl_ctrl_i.priv_lvl_set) begin
instr_priv_lvl_q <= priv_lvl_ctrl_i.priv_lvl;
end
end
end

// Set privilege level to IF stage
assign instr_priv_lvl_o = fetch_priv_lvl_i;
Expand Down
11 changes: 11 additions & 0 deletions rtl/cv32e40x_core.sv
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,9 @@ module cv32e40x_core import cv32e40x_pkg::*;
logic csr_wr_in_wb_flush;
logic csr_irq_enable_write;

privlvl_t priv_lvl_lsu;
privlvlctrl_t priv_lvl_if_ctrl;

privlvl_t priv_lvl;

logic csr_mnxti_read;
Expand Down Expand Up @@ -502,6 +505,9 @@ module cv32e40x_core import cv32e40x_pkg::*;
.if_valid_o ( if_valid ),
.id_ready_i ( id_ready ),

// Privilege level
.priv_lvl_ctrl_i ( priv_lvl_if_ctrl ),

// eXtension interface
.xif_compressed_if ( xif_compressed_if ),
.xif_offloading_id_i ( xif_offloading_id )
Expand Down Expand Up @@ -705,6 +711,9 @@ module cv32e40x_core import cv32e40x_pkg::*;
.lsu_align_status_1_o ( lsu_align_status_wb),
.lsu_atomic_1_o ( lsu_atomic_wb ),

// Privilege level
.priv_lvl_lsu_i ( priv_lvl_lsu ),

// Valid/ready
.valid_0_i ( lsu_valid_ex ), // First LSU stage (EX)
.ready_0_o ( lsu_ready_0 ),
Expand Down Expand Up @@ -831,6 +840,8 @@ module cv32e40x_core import cv32e40x_pkg::*;
.mtvec_mode_o ( mtvec_mode ),
.mtvt_addr_o ( mtvt_addr ),

.priv_lvl_if_ctrl_o ( priv_lvl_if_ctrl ),
.priv_lvl_lsu_o ( priv_lvl_lsu ),
.priv_lvl_o ( priv_lvl ),

// ID/EX pipeline
Expand Down
10 changes: 8 additions & 2 deletions rtl/cv32e40x_cs_registers.sv
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*;
output logic [MTVT_ADDR_WIDTH-1:0] mtvt_addr_o,

output privlvl_t priv_lvl_o,
output privlvlctrl_t priv_lvl_if_ctrl_o,
output privlvl_t priv_lvl_lsu_o,

// ID/EX pipeline
input id_ex_pipe_t id_ex_pipe_i,
Expand Down Expand Up @@ -243,9 +245,8 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*;
logic [31:0] mtval_n, mtval_rdata; // No CSR module instance
logic mtval_we; // Not used in RTL (used by RVFI)

privlvl_t priv_lvl_n, priv_lvl_q, priv_lvl_rdata; // todo: Use the priv_* signals as much as possible as in the 40S
privlvl_t priv_lvl_n, priv_lvl_q, priv_lvl_rdata;
logic priv_lvl_we;
logic [1:0] priv_lvl_q_int;

// Detect JVT writes (requires pipeline flush)
logic csr_wr_in_wb;
Expand Down Expand Up @@ -1470,7 +1471,12 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*;
assign mhartid_rdata = mhartid_i;
assign mconfigptr_rdata = 32'h0;

// Only machine mode is supported
assign priv_lvl_rdata = PRIV_LVL_M;
assign priv_lvl_q = PRIV_LVL_M;
assign priv_lvl_lsu_o = PRIV_LVL_M;
assign priv_lvl_if_ctrl_o.priv_lvl = PRIV_LVL_M;
assign priv_lvl_if_ctrl_o.priv_lvl_set = 1'b0;

// dcsr_rdata factors in the flop outputs and the nmip bit from the controller
assign dcsr_rdata = DEBUG ? {dcsr_q[31:4], ctrl_fsm_i.pending_nmi, dcsr_q[2:0]} : 32'h0;
Expand Down
4 changes: 4 additions & 0 deletions rtl/cv32e40x_if_stage.sv
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ module cv32e40x_if_stage import cv32e40x_pkg::*;
output logic if_valid_o,
input logic id_ready_i,

// Privilege mode
input privlvlctrl_t priv_lvl_ctrl_i,

// eXtension interface
cv32e40x_if_xif.cpu_compressed xif_compressed_if, // XIF compressed interface
input logic xif_offloading_id_i // ID stage attempts to offload an instruction
Expand Down Expand Up @@ -200,6 +203,7 @@ module cv32e40x_if_stage import cv32e40x_pkg::*;
.rst_n ( rst_n ),

.ctrl_fsm_i ( ctrl_fsm_i ),
.priv_lvl_ctrl_i ( priv_lvl_ctrl_i ),

.branch_addr_i ( {branch_addr_n[31:1], 1'b0} ),

Expand Down
5 changes: 4 additions & 1 deletion rtl/cv32e40x_load_store_unit.sv
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ module cv32e40x_load_store_unit import cv32e40x_pkg::*;
output align_status_e lsu_align_status_1_o, // Alignment status (for atomics), WB timing
output lsu_atomic_e lsu_atomic_1_o, // Is there an atomic in WB, and of which type.

// Privilege mode
input privlvl_t priv_lvl_lsu_i,

// Handshakes
input logic valid_0_i, // Handshakes for first LSU stage (EX)
output logic ready_0_o, // LSU ready for new data in EX stage
Expand Down Expand Up @@ -211,7 +214,7 @@ module cv32e40x_load_store_unit import cv32e40x_pkg::*;
trans.we = id_ex_pipe_i.lsu_we;
trans.size = id_ex_pipe_i.lsu_size;
trans.wdata = id_ex_pipe_i.operand_c;
trans.mode = PRIV_LVL_M; // Machine mode
trans.mode = priv_lvl_lsu_i;
trans.dbg = ctrl_fsm_i.debug_mode;

trans.atop = id_ex_pipe_i.lsu_atop;
Expand Down
2 changes: 2 additions & 0 deletions rtl/cv32e40x_prefetch_unit.sv
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ module cv32e40x_prefetch_unit import cv32e40x_pkg::*;
input logic rst_n,

input ctrl_fsm_t ctrl_fsm_i,
input privlvlctrl_t priv_lvl_ctrl_i,

input logic [31:0] branch_addr_i,

Expand Down Expand Up @@ -114,6 +115,7 @@ module cv32e40x_prefetch_unit import cv32e40x_pkg::*;
.rst_n ( rst_n ),

.ctrl_fsm_i ( ctrl_fsm_i ),
.priv_lvl_ctrl_i ( priv_lvl_ctrl_i ),

.branch_addr_i ( branch_addr_i ),
.prefetch_busy_o ( prefetch_busy_o ),
Expand Down
6 changes: 6 additions & 0 deletions rtl/include/cv32e40x_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,12 @@ typedef enum logic[1:0] {

parameter privlvl_t PRIV_LVL_LOWEST = PRIV_LVL_M;

// Struct used for setting privilege level
typedef struct packed {
logic priv_lvl_set;
privlvl_t priv_lvl;
} privlvlctrl_t;

// Machine Vendor ID - OpenHW JEDEC ID is '2 decimal (bank 13)'
parameter MVENDORID_OFFSET = 7'h2; // Final byte without parity bit
parameter MVENDORID_BANK = 25'hC; // Number of continuation codes
Expand Down