Skip to content

Commit

Permalink
Merge pull request #454 from silabs-oivind/merge_from_cv32e40x
Browse files Browse the repository at this point in the history
Merge from cv32e40x
  • Loading branch information
Silabs-ArjanB committed May 16, 2023
2 parents f56bd5d + fbbbc57 commit 8d049d2
Show file tree
Hide file tree
Showing 33 changed files with 412 additions and 133 deletions.
13 changes: 7 additions & 6 deletions bhv/cv32e40s_rvfi.sv
Expand Up @@ -30,7 +30,7 @@ module cv32e40s_rvfi
input logic rst_ni,

// Non-pipeline Probes
if_c_obi.monitor m_c_obi_instr_if,
cv32e40s_if_c_obi.monitor m_c_obi_instr_if,

//// IF Probes ////
input logic if_valid_i,
Expand Down Expand Up @@ -1289,11 +1289,12 @@ module cv32e40s_rvfi
// If the 2nd transfer in a split misaligned is blocked (by debug watchpoint, mpu or alignment check), the corresponding bits in rmask/wmaks will be cleared
if (!lsu_split_2nd_xfer_wb) begin
// 1st transfer of a split misaligned, or the only transfer in case of a single transfer
rvfi_mem_rmask[ (4*(memop_cnt+1))-1 -: 4] <= mem_access_blocked_wb ? '0 : mem_rmask [STAGE_WB];
rvfi_mem_wmask[ (4*(memop_cnt+1))-1 -: 4] <= mem_access_blocked_wb ? '0 : mem_wmask [STAGE_WB];
rvfi_mem_addr [(32*(memop_cnt+1))-1 -: 32] <= ex_mem_trans.addr;
rvfi_mem_wdata[(32*(memop_cnt+1))-1 -: 32] <= ex_mem_trans.wdata;
rvfi_mem_prot [ (3*(memop_cnt+1))-1 -: 3] <= ex_mem_trans.prot;
rvfi_mem_rmask[ (4*(memop_cnt+1))-1 -: 4] <= mem_access_blocked_wb ? '0 : mem_rmask [STAGE_WB];
rvfi_mem_wmask[ (4*(memop_cnt+1))-1 -: 4] <= mem_access_blocked_wb ? '0 : mem_wmask [STAGE_WB];
rvfi_mem_addr [(32*(memop_cnt+1))-1 -: 32] <= ex_mem_trans.addr;
rvfi_mem_wdata[(32*(memop_cnt+1))-1 -: 32] <= ex_mem_trans.wdata;
// Using (2*memop_cnt+memop_cnt) rather than 3*memop_cnt. This is a workaround to avoid blackboxed multiplier in the slice boundary calculations
rvfi_mem_prot [(2*memop_cnt + memop_cnt) +: 3] <= ex_mem_trans.prot;
end
else if (lsu_split_2nd_xfer_wb && mem_access_blocked_wb) begin
// 2nd transfer of a split misaligned is blocked. Clear related bits in rmask/wmask
Expand Down
6 changes: 3 additions & 3 deletions bhv/cv32e40s_rvfi_instr_obi.sv
Expand Up @@ -39,7 +39,7 @@ module cv32e40s_rvfi_instr_obi import cv32e40s_pkg::*; import cv32e40s_rvfi_pkg:
input logic prefetch_trans_ready_i,
input logic prefetch_resp_valid_i,

if_c_obi.monitor m_c_obi_instr_if,
cv32e40s_if_c_obi.monitor m_c_obi_instr_if,

output rvfi_obi_instr_t obi_instr // OBI address and response phase packet aligned to IF timing
);
Expand Down Expand Up @@ -111,14 +111,14 @@ module cv32e40s_rvfi_instr_obi import cv32e40s_pkg::*; import cv32e40s_rvfi_pkg:
// trans_accepted is based on the core side control signals from the MPU.
// When there is no MPU fault, trans_accepted will have the same timing as
// m_c_obi_instr_if.s_req.req, since the control signals are passed directly through the MPU,
// and cv32e40x_instr_obi_interface will be in TRANSPARENT mode (trans_ready_o == 1'b1).
// and cv32e40s_instr_obi_interface will be in TRANSPARENT mode (trans_ready_o == 1'b1).
// Upon MPU fault, req_payload will be undefined.
assign fifo_req_push = trans_accepted;

// Push OBI response phase signals into FIFO when response is valid.
// response_valid is based on the core side control signal from the MPU.
// When there is no MPU fault, response_valid will have the same timing as
// m_c_obi_instr_if.s_rvalid.rvalid, since this signal is passed directly through cv32e40x_instr_obi_interface and the MPU.
// m_c_obi_instr_if.s_rvalid.rvalid, since this signal is passed directly through cv32e40s_instr_obi_interface and the MPU.
// Upon MPU fault, resp_payload will be undefined, with the exception of resp_payload.mpu_status
assign fifo_resp_push = response_valid;

Expand Down
2 changes: 1 addition & 1 deletion bhv/rvfi_sim_trace.sv → bhv/cv32e40s_rvfi_sim_trace.sv
Expand Up @@ -27,7 +27,7 @@
// //
////////////////////////////////////////////////////////////////////////////////

module rvfi_sim_trace
module cv32e40s_rvfi_sim_trace
import cv32e40s_rvfi_pkg::*;
#(parameter string ITB_PLUSARG = "itb_file",
parameter string LOGFILE_PATH_PLUSARG = "log_file",
Expand Down
3 changes: 2 additions & 1 deletion bhv/cv32e40s_wrapper.sv
Expand Up @@ -532,7 +532,7 @@ endgenerate
`ifndef FORMAL
bind cv32e40s_rvfi:
rvfi_i
rvfi_sim_trace
cv32e40s_rvfi_sim_trace
tracer_i(.*);
`endif

Expand All @@ -549,6 +549,7 @@ endgenerate
.obi_instr_rptr_q_inc(rvfi_i.rvfi_instr_obi_i.rptr_q_inc),
.obi_instr_rptr_q(rvfi_i.rvfi_instr_obi_i.rptr_q),
.pc_ex_i (core_i.id_ex_pipe.pc),
.m_c_obi_data_if (core_i.m_c_obi_data_if),
.*);

`endif // `ifndef COREV_ASSERT_OFF
Expand Down
4 changes: 2 additions & 2 deletions cv32e40s_manifest.flist
Expand Up @@ -29,7 +29,7 @@
+incdir+${DESIGN_RTL_DIR}/../sva

${DESIGN_RTL_DIR}/include/cv32e40s_pkg.sv
${DESIGN_RTL_DIR}/if_c_obi.sv
${DESIGN_RTL_DIR}/cv32e40s_if_c_obi.sv
${DESIGN_RTL_DIR}/../bhv/include/cv32e40s_rvfi_pkg.sv
${DESIGN_RTL_DIR}/../bhv/cv32e40s_wrapper.sv
${DESIGN_RTL_DIR}/cv32e40s_align_check.sv
Expand Down Expand Up @@ -88,4 +88,4 @@ ${DESIGN_RTL_DIR}/../bhv/cv32e40s_sim_clock_gate.sv
${DESIGN_RTL_DIR}/../bhv/cv32e40s_rvfi_instr_obi.sv
${DESIGN_RTL_DIR}/../bhv/cv32e40s_rvfi_data_obi.sv
${DESIGN_RTL_DIR}/../bhv/cv32e40s_rvfi.sv
${DESIGN_RTL_DIR}/../bhv/rvfi_sim_trace.sv
${DESIGN_RTL_DIR}/../bhv/cv32e40s_rvfi_sim_trace.sv
2 changes: 1 addition & 1 deletion docs/user_manual/source/exceptions_interrupts.rst
Expand Up @@ -72,7 +72,7 @@ Non Maskable Interrupts

Non Maskable Interrupts (NMIs) update ``mepc``, ``mcause`` and ``mstatus`` similar to regular interrupts.
However, as the faults that result in NMIs are imprecise, the contents of ``mepc`` is not guaranteed to point to the instruction after the faulted load or store.
The ``minsttatus`` CSR (which exists only if ``CLIC`` == 1) is not impacted by NMIs.
The ``mintstatus`` CSR (which exists only if ``CLIC`` == 1) is not impacted by NMIs.

.. note::

Expand Down
34 changes: 22 additions & 12 deletions rtl/cv32e40s_alu.sv
Expand Up @@ -71,6 +71,8 @@ module cv32e40s_alu import cv32e40s_pkg::*;
output logic [31:0] div_op_b_shifted_o
);

localparam RV32B_ZBS = (B_EXT == ZBA_ZBB_ZBS) || (B_EXT == ZBA_ZBB_ZBC_ZBS);

logic [31:0] operand_a_rev;
logic [31:0] operand_b_rev;

Expand Down Expand Up @@ -159,7 +161,9 @@ module cv32e40s_alu import cv32e40s_pkg::*;
ALU_B_BSET,
ALU_B_BCLR,
ALU_B_BINV : begin
shifter_aa = 32'h1;
if (RV32B_ZBS) begin
shifter_aa = 32'h1;
end
end
default: ;
endcase
Expand All @@ -175,17 +179,23 @@ module cv32e40s_alu import cv32e40s_pkg::*;
shifter_tmp = shifter_shamt[0] ? {shifter_tmp[62:0], shifter_tmp[63:63]} : shifter_tmp;
end

always_comb begin
shifter_result = shifter_tmp[31:0];

unique case (operator_i)
ALU_B_BEXT : shifter_result = 32'h1 & shifter_tmp[31:0];
ALU_B_BSET : shifter_result = operand_a_i | shifter_tmp[31:0];
ALU_B_BCLR : shifter_result = operand_a_i & ~shifter_tmp[31:0];
ALU_B_BINV : shifter_result = operand_a_i ^ shifter_tmp[31:0];
default: ;
endcase
end
generate
if (RV32B_ZBS) begin : gen_shift_zbs
always_comb begin
shifter_result = shifter_tmp[31:0];

unique case (operator_i)
ALU_B_BEXT : shifter_result = 32'h1 & shifter_tmp[31:0];
ALU_B_BSET : shifter_result = operand_a_i | shifter_tmp[31:0];
ALU_B_BCLR : shifter_result = operand_a_i & ~shifter_tmp[31:0];
ALU_B_BINV : shifter_result = operand_a_i ^ shifter_tmp[31:0];
default: ;
endcase
end
end else begin : gen_shift_nozbs
assign shifter_result = shifter_tmp[31:0];
end
endgenerate

assign div_op_b_shifted_o = shifter_tmp[31:0];

Expand Down
2 changes: 1 addition & 1 deletion rtl/cv32e40s_controller.sv
Expand Up @@ -132,7 +132,7 @@ module cv32e40s_controller import cv32e40s_pkg::*;
input logic wb_valid_i, // WB stage is done

// Data OBI interface monitor
if_c_obi.monitor m_c_obi_data_if,
cv32e40s_if_c_obi.monitor m_c_obi_data_if,

// Outputs
output ctrl_byp_t ctrl_byp_o,
Expand Down
6 changes: 3 additions & 3 deletions rtl/cv32e40s_controller_bypass.sv
Expand Up @@ -203,9 +203,9 @@ module cv32e40s_controller_bypass import cv32e40s_pkg::*;
((id_ex_pipe_i.alu_jmp && id_ex_pipe_i.alu_en && !id_ex_pipe_i.last_sec_op && id_ex_pipe_i.instr_valid));


// Stall ID when WFI or WFE is active in EX.
// Prevent load/store following a WFI or WFE in the pipeline
assign ctrl_byp_o.wfi_wfe_stall = (id_ex_pipe_i.sys_en && (id_ex_pipe_i.sys_wfi_insn || id_ex_pipe_i.sys_wfe_insn) && id_ex_pipe_i.instr_valid);
// Stall ID when instruction that can trigger sleep (e.g. WFI or WFE) is active in EX.
// Prevent load/store following a sleep instruction in the pipeline
assign ctrl_byp_o.sleep_stall = (id_ex_pipe_i.sys_en && (id_ex_pipe_i.sys_wfi_insn || id_ex_pipe_i.sys_wfe_insn) && id_ex_pipe_i.instr_valid);

// Stall ID when mnxti CSR is accessed in EX
// This is needed because the data bypass from EX uses csr_rdata, and for mnxti this is actually mstatus and not the result
Expand Down
8 changes: 4 additions & 4 deletions rtl/cv32e40s_controller_fsm.sv
Expand Up @@ -130,7 +130,7 @@ module cv32e40s_controller_fsm import cv32e40s_pkg::*;
input logic fencei_flush_ack_i,

// Data OBI interface monitor
if_c_obi.monitor m_c_obi_data_if
cv32e40s_if_c_obi.monitor m_c_obi_data_if
);

// FSM state encoding
Expand Down Expand Up @@ -684,7 +684,7 @@ module cv32e40s_controller_fsm import cv32e40s_pkg::*;
// - If not checking for id_stage_haltable for interrupts and debug, the core could end up in a situation where it tries to create a bubble
// by halting ID, but the condition disallowing interrupt or debug will not disappear until the sequence currently handled by the ID stage
// is done. This would create an unrecoverable deadlock.
ctrl_fsm_o.halt_id = (ctrl_byp_i.jalr_stall || ctrl_byp_i.load_stall || ctrl_byp_i.csr_stall || ctrl_byp_i.wfi_wfe_stall || ctrl_byp_i.mnxti_id_stall) ||
ctrl_fsm_o.halt_id = (ctrl_byp_i.jalr_stall || ctrl_byp_i.load_stall || ctrl_byp_i.csr_stall || ctrl_byp_i.sleep_stall || ctrl_byp_i.mnxti_id_stall) ||
((pending_interrupt || pending_nmi || pending_nmi_early) && debug_interruptible && id_stage_haltable) ||
((pending_async_debug || pending_sync_debug) && id_stage_haltable);

Expand Down Expand Up @@ -1272,8 +1272,8 @@ module cv32e40s_controller_fsm import cv32e40s_pkg::*;
end

// Wakeup from sleep
assign ctrl_fsm_o.wake_from_sleep = pending_nmi || irq_wu_ctrl_i || pending_async_debug || debug_mode_q || (wfe_in_wb && wu_wfe_i); // Only WFE wakes up for wfe_wu_i
assign ctrl_fsm_o.debug_wfi_wfe_no_sleep = debug_mode_q || dcsr_i.step;
assign ctrl_fsm_o.wake_from_sleep = pending_nmi || irq_wu_ctrl_i || pending_async_debug || debug_mode_q || (wfe_in_wb && wu_wfe_i); // Only WFE wakes up for wfe_wu_i
assign ctrl_fsm_o.debug_no_sleep = debug_mode_q || dcsr_i.step;

////////////////////
// Flops //
Expand Down
4 changes: 2 additions & 2 deletions rtl/cv32e40s_core.sv
Expand Up @@ -382,8 +382,8 @@ module cv32e40s_core import cv32e40s_pkg::*;
logic lfsr_shift_id;

// Internal OBI interfaces
if_c_obi #(.REQ_TYPE(obi_inst_req_t), .RESP_TYPE(obi_inst_resp_t)) m_c_obi_instr_if();
if_c_obi #(.REQ_TYPE(obi_data_req_t), .RESP_TYPE(obi_data_resp_t)) m_c_obi_data_if();
cv32e40s_if_c_obi #(.REQ_TYPE(obi_inst_req_t), .RESP_TYPE(obi_inst_resp_t)) m_c_obi_instr_if();
cv32e40s_if_c_obi #(.REQ_TYPE(obi_data_req_t), .RESP_TYPE(obi_data_resp_t)) m_c_obi_data_if();

// Connect toplevel OBI signals to internal interfaces
assign instr_req_o = m_c_obi_instr_if.s_req.req;
Expand Down
6 changes: 0 additions & 6 deletions rtl/cv32e40s_cs_registers.sv
Expand Up @@ -1313,12 +1313,6 @@ module cv32e40s_cs_registers import cv32e40s_pkg::*;
end
end

CSR_MINTSTATUS: begin
if (CLIC) begin
mintstatus_we = 1'b1;
end
end

CSR_MINTTHRESH: begin
if (CLIC) begin
mintthresh_we = 1'b1;
Expand Down
2 changes: 1 addition & 1 deletion rtl/cv32e40s_data_obi_interface.sv
Expand Up @@ -58,7 +58,7 @@ module cv32e40s_data_obi_interface import cv32e40s_pkg::*;
input xsecure_ctrl_t xsecure_ctrl_i,

// OBI interface
if_c_obi.master m_c_obi_data_if
cv32e40s_if_c_obi.master m_c_obi_data_if
);


Expand Down
16 changes: 8 additions & 8 deletions rtl/cv32e40s_i_decoder.sv
Expand Up @@ -30,8 +30,8 @@
module cv32e40s_i_decoder import cv32e40s_pkg::*;
#(
parameter bit CLIC = 1
)
(
)
(
// from IF/ID pipeline
input logic [31:0] instr_rdata_i,

Expand All @@ -40,9 +40,9 @@ module cv32e40s_i_decoder import cv32e40s_pkg::*;
input privlvl_t priv_lvl_i, // Priviledge level for ID stage
input mstatus_t mstatus_i,
output decoder_ctrl_t decoder_ctrl_o
);
);

localparam CUSTOM_EXT = 1;
localparam CUSTOM_EXT = 1;

always_comb
begin
Expand Down Expand Up @@ -335,8 +335,8 @@ module cv32e40s_i_decoder import cv32e40s_pkg::*;
if((priv_lvl_i == PRIV_LVL_U) && mstatus_i.tw) begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end else begin
// Suppressing WFI in case of ctrl_fsm_i.debug_wfi_wfe_no_sleep to prevent sleeping when not allowed.
decoder_ctrl_o.sys_wfi_insn = ctrl_fsm_i.debug_wfi_wfe_no_sleep ? 1'b0 : 1'b1;
// Suppressing WFI in case of ctrl_fsm_i.debug_no_sleep to prevent sleeping when not allowed.
decoder_ctrl_o.sys_wfi_insn = ctrl_fsm_i.debug_no_sleep ? 1'b0 : 1'b1;
end
end

Expand All @@ -345,8 +345,8 @@ module cv32e40s_i_decoder import cv32e40s_pkg::*;
if((priv_lvl_i == PRIV_LVL_U) && mstatus_i.tw) begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
end else begin
// Suppressing WFI in case of ctrl_fsm_i.debug_wfi_wfe_no_sleep to prevent sleeping when not allowed.
decoder_ctrl_o.sys_wfe_insn = ctrl_fsm_i.debug_wfi_wfe_no_sleep ? 1'b0 : 1'b1;
// Suppressing WFE in case of ctrl_fsm_i.debug_no_sleep to prevent sleeping when not allowed.
decoder_ctrl_o.sys_wfe_insn = ctrl_fsm_i.debug_no_sleep ? 1'b0 : 1'b1;
end
end else begin
decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
Expand Down
27 changes: 0 additions & 27 deletions rtl/cv32e40s_id_stage.sv
Expand Up @@ -115,7 +115,6 @@ module cv32e40s_id_stage import cv32e40s_pkg::*;
localparam REG_D_LSB = 7;

logic [31:0] instr;
logic [15:0] c_instr; // Compressed instruction

// Register Read/Write Control
logic [1:0] rf_re; // Decoder only supports rs1, rs2
Expand Down Expand Up @@ -185,8 +184,6 @@ module cv32e40s_id_stage import cv32e40s_pkg::*;
logic [31:0] imm_u_type;
logic [31:0] imm_uj_type;
logic [31:0] imm_z_type;
logic [31:0] imm_ciw_type;
logic [31:0] imm_cl_type;

// Branch target address
logic [31:0] bch_target;
Expand Down Expand Up @@ -229,7 +226,6 @@ module cv32e40s_id_stage import cv32e40s_pkg::*;
assign lfsr_shift_o = (id_valid_o && ex_ready_i) && (if_id_pipe_i.instr_meta.dummy || if_id_pipe_i.instr_meta.hint) && last_sec_op;

assign instr = if_id_pipe_i.instr.bus_resp.rdata;
assign c_instr = if_id_pipe_i.compressed_instr;

// Immediate extraction and sign extension
assign imm_i_type = { {20 {instr[31]}}, instr[31:20] };
Expand All @@ -238,27 +234,6 @@ module cv32e40s_id_stage import cv32e40s_pkg::*;
assign imm_u_type = { instr[31:12], 12'b0 };
assign imm_uj_type = { {12 {instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0 };

// Immediate extraction and sign extension (compressed instructions)
assign imm_ciw_type = { 22'b0, c_instr[10:7], c_instr[12:11], c_instr[5], c_instr[6], 2'b0 };
assign imm_cl_type = { 25'b0, c_instr[5], c_instr[12:10], c_instr[6], 2'b0 };

/*
assign imm_cfldsp_type = {22'b0, c_instr[4:2], c_instr[12], c_instr[6:5], 3'b0};
assign imm_caddi_type = {{22{c_instr[12]}}, c_instr[12:12], c_instr[4:3], c_instr[5:5], c_instr[2:2], c_instr[6:6], 4'b0};
assign imm_clwsp_type = {24'b0, c_instr[3:2], c_instr[12:12], c_instr[6:4], 2'b0};
assign imm_cld_type = {24'b0, c_instr[6:5], c_instr[12:10], 3'b0};
assign imm_cswsp_type = {24'b0, c_instr[8:7], c_instr[12:9], 2'b0};
assign imm_fsdp_type = {24'b0, c_instr[9:7], c_instr[12:10], 2'b0};
assign imm_csrli_type = {26'b0, c_instr[12:12], c_instr[6:2]};
assign imm_candi_type = {{26{c_instr[12]}}, c_instr[12:12], c_instr[6:2]};
assign imm_cbeq_type = {{23{c_instr[12]}}, c_instr[12:12], c_instr[6:5], c_instr[2:2], c_instr[11:10], c_instr[4:3], 1'b0};
assign imm_clui_type = {{14{c_instr[12]}}, c_instr[12:12], c_instr[6:2], 12'b0};
assign imm_clsb_type = {28'd0, c_instr[10], c_instr[6:5], c_instr[11]};
assign imm_clsh_type = {27'd0, c_instr[11:10], c_instr[6:5], 1'b0};
*/



// Immediate for CSR manipulation (zero extended)
assign imm_z_type = { 27'b0, instr[REG_S1_MSB:REG_S1_LSB] };

Expand Down Expand Up @@ -366,8 +341,6 @@ module cv32e40s_id_stage import cv32e40s_pkg::*;
IMMB_S: imm_b = imm_s_type;
IMMB_U: imm_b = imm_u_type;
IMMB_PCINCR: imm_b = if_id_pipe_i.instr_meta.compressed ? 32'h2 : 32'h4;
IMMB_CIW: imm_b = imm_ciw_type;
IMMB_CL: imm_b = imm_cl_type;
default: imm_b = imm_i_type;
endcase
end
Expand Down
4 changes: 2 additions & 2 deletions rtl/if_c_obi.sv → rtl/cv32e40s_if_c_obi.sv
Expand Up @@ -24,7 +24,7 @@
//
// The 'c' in the interface names means 'Compressed'
// since this interface is a subset of the full OBI spec.
interface if_c_obi import cv32e40s_pkg::*;
interface cv32e40s_if_c_obi import cv32e40s_pkg::*;
#(
parameter type REQ_TYPE = obi_inst_req_t,
parameter type RESP_TYPE = obi_inst_resp_t
Expand All @@ -49,4 +49,4 @@ interface if_c_obi import cv32e40s_pkg::*;
s_gnt, s_rvalid, resp_payload
);

endinterface : if_c_obi
endinterface : cv32e40s_if_c_obi
2 changes: 1 addition & 1 deletion rtl/cv32e40s_if_stage.sv
Expand Up @@ -70,7 +70,7 @@ module cv32e40s_if_stage import cv32e40s_pkg::*;


// Instruction bus interface
if_c_obi.master m_c_obi_instr_if,
cv32e40s_if_c_obi.master m_c_obi_instr_if,

output if_id_pipe_t if_id_pipe_o, // IF/ID pipeline stage
output logic [31:0] pc_if_o, // Program counter
Expand Down
2 changes: 1 addition & 1 deletion rtl/cv32e40s_instr_obi_interface.sv
Expand Up @@ -57,7 +57,7 @@ module cv32e40s_instr_obi_interface import cv32e40s_pkg::*;
input xsecure_ctrl_t xsecure_ctrl_i,

// OBI interface
if_c_obi.master m_c_obi_instr_if
cv32e40s_if_c_obi.master m_c_obi_instr_if
);


Expand Down

0 comments on commit 8d049d2

Please sign in to comment.