Skip to content
Open
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
2 changes: 0 additions & 2 deletions doc/02_user/integration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ The configuration dependent primitives are:
Required where ``ICache == 1`` and ``SecureIbex == 1``.
* ``prim_lfsr`` - Linear feedback shift register, used for pseudo random number generation for dummy instruction insertion.
Required where ``SecureIbex == 1``.
* ``prim_onehot_check`` - Checks a onehot signal is correct, for detecting fault injection attacks.
Required where ``SecureIbex == 1``.
* ``prim_secded_X`` - Various primitives to encode and decode SECDED (Single Error Correct, Double Error Detect) error detection and correction codes.
Required where ``SecureIbex == 1``.

Expand Down
4 changes: 2 additions & 2 deletions doc/03_reference/coverage_plan.rst
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ For more detail about each security countermeasure in Ibex see :ref:`security`

* ``cp_lockstep_err`` - Lockstep glitch fault seen.

* ``cp_rf_we_glitch_err`` - Register file write enable glitch fault seen.
* ``cp_rf_glitch_err`` - Register file fault seen.

* ``cp_pc_mismatch_err`` - PC mismatch error seen.

Expand All @@ -360,7 +360,7 @@ The mapping between security countermeasures and coverpoints that demonstrate it
+--------------------------------+-------------------------------------------------------+
| DATA_REG_SW.INTEGRITY | ``cp_rf_a_ecc_err`` ``cp_rf_b_ecc_err`` |
+--------------------------------+-------------------------------------------------------+
| DATA_REG_SW.GLITCH_DETECT | ``cp_rf_we_glitch_err`` |
| DATA_REG_SW.GLITCH_DETECT | ``cp_rf_glitch_err`` |
+--------------------------------+-------------------------------------------------------+
| LOGIC.SHADOW | ``cp_lockstep_err`` |
+--------------------------------+-------------------------------------------------------+
Expand Down
4 changes: 2 additions & 2 deletions dv/uvm/core_ibex/fcov/core_ibex_fcov_if.sv
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ interface core_ibex_fcov_if import ibex_pkg::*; (
id_stall_type_last_valid;

// V2S Related Probes for Top-Level
logic rf_we_glitch_err;
logic rf_glitch_err;
logic lockstep_glitch_err;

logic imem_single_cycle_response, dmem_single_cycle_response;
Expand Down Expand Up @@ -493,7 +493,7 @@ interface core_ibex_fcov_if import ibex_pkg::*; (
`DV_FCOV_EXPR_SEEN(mem_store_ecc_err, load_store_unit_i.store_resp_intg_err_o)

`DV_FCOV_EXPR_SEEN(lockstep_err, lockstep_glitch_err)
`DV_FCOV_EXPR_SEEN(rf_we_glitch_err, rf_we_glitch_err)
`DV_FCOV_EXPR_SEEN(rf_glitch_err, rf_glitch_err)
`DV_FCOV_EXPR_SEEN(pc_mismatch_err, if_stage_i.pc_mismatch_alert_o)

cp_fetch_enable: coverpoint fetch_enable_i {
Expand Down
3 changes: 0 additions & 3 deletions dv/uvm/core_ibex/ibex_dv.f
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@
${LOWRISC_IP_DIR}/ip/prim/rtl/prim_secded_39_32_dec.sv
${LOWRISC_IP_DIR}/ip/prim/rtl/prim_secded_72_64_enc.sv
${LOWRISC_IP_DIR}/ip/prim/rtl/prim_secded_72_64_dec.sv
${LOWRISC_IP_DIR}/ip/prim/rtl/prim_onehot_check.sv
${LOWRISC_IP_DIR}/ip/prim/rtl/prim_onehot_enc.sv
${LOWRISC_IP_DIR}/ip/prim/rtl/prim_onehot_mux.sv

// ibex CORE RTL files
+incdir+${PRJ_DIR}/rtl
Expand Down
6 changes: 3 additions & 3 deletions dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -709,9 +709,9 @@
rtl_params:
SecureIbex: 1

- test: riscv_rf_ctrl_intg_test
- test: riscv_rf_addr_intg_test
description: >
Randomly corrupt one of the register file write and read enables signals in the middle of program execution
Randomly corrupt one of the register file addresses in the middle of program execution
iterations: 15
gen_test: riscv_rand_instr_test
gen_opts: >
Expand All @@ -720,7 +720,7 @@
+gen_all_csrs_by_default=1
+add_csr_write=MSTATUS,MEPC,MCAUSE,MTVAL,0x7c0,0x7c1
+no_csr_instr=0
rtl_test: core_ibex_rf_ctrl_intg_test
rtl_test: core_ibex_rf_addr_intg_test
rtl_params:
SecureIbex: 1

Expand Down
19 changes: 2 additions & 17 deletions dv/uvm/core_ibex/tb/core_ibex_tb_top.sv
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,8 @@ module core_ibex_tb_top;
end

`ifndef DV_FCOV_DISABLE
assign dut.u_ibex_top.u_ibex_core.u_fcov_bind.rf_we_glitch_err =
dut.u_ibex_top.rf_alert_major_internal;

assign dut.u_ibex_top.u_ibex_core.u_fcov_bind.rf_glitch_err =
dut.u_ibex_top.alert_major_internal_o;
assign dut.u_ibex_top.u_ibex_core.u_fcov_bind.lockstep_glitch_err =
dut.u_ibex_top.lockstep_alert_major_internal;
`endif
Expand Down Expand Up @@ -383,20 +382,6 @@ module core_ibex_tb_top;
unused_assert_connected = 1;
end

// Disable the assertion for onehot check in case WrenCheck (set by SecureIbex) is enabled.
if (SecureIbex) begin : gen_disable_onehot_check
assign dut.u_ibex_top.gen_regfile_ff.register_file_i.gen_wren_check.u_prim_onehot_check.
unused_assert_connected = 1;
end

// Disable the assertion for onehot check in case RdataMuxCheck (set by SecureIbex) is enabled.
if (SecureIbex) begin : gen_disable_rdata_mux_check
assign dut.u_ibex_top.gen_regfile_ff.register_file_i.gen_rdata_mux_check.
u_prim_onehot_check_raddr_a.unused_assert_connected = 1;
assign dut.u_ibex_top.gen_regfile_ff.register_file_i.gen_rdata_mux_check.
u_prim_onehot_check_raddr_b.unused_assert_connected = 1;
end

ibex_pkg::ctrl_fsm_e controller_state;
logic controller_handle_irq;
ibex_pkg::irqs_t ibex_irqs, last_ibex_irqs;
Expand Down
71 changes: 51 additions & 20 deletions dv/uvm/core_ibex/tests/core_ibex_test_lib.sv
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,15 @@ class core_ibex_rf_intg_test extends core_ibex_base_test;
int rnd_delay;
bit port_idx;
string port_name;
int unsigned lockstep_delay;

vseq.start(env.vseqr);

// Pick port to corrupt.
port_idx = $urandom_range(1);
port_name = port_idx ? "rf_rdata_b_ecc" : "rf_rdata_a_ecc";
port_name = port_idx ? "rf_rdata_b" : "rf_rdata_a";

lockstep_delay = read_data("gen_lockstep.u_ibex_lockstep.LockstepOffset");

`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(rnd_delay, rnd_delay > 1000; rnd_delay < 10_000;)
clk_vif.wait_n_clks(rnd_delay);
Expand Down Expand Up @@ -182,8 +185,8 @@ class core_ibex_rf_intg_test extends core_ibex_base_test;
// Determine whether an alert is expected: if the instruction is valid.
exp_alert = read_data("u_ibex_core.instr_valid_id");

// Schedule a simulation step so the DUT can react.
#1step;
// Wait LockstepOffset cycles before reading the error.
clk_vif.wait_n_clks(lockstep_delay);

// Check if the major alert matches our expectation.
alert_major_internal = read_data("alert_major_internal_o");
Expand All @@ -205,8 +208,8 @@ class core_ibex_rf_intg_test extends core_ibex_base_test;

endclass

class core_ibex_rf_ctrl_intg_test extends core_ibex_base_test;
`uvm_component_utils(core_ibex_rf_ctrl_intg_test)
class core_ibex_rf_addr_intg_test extends core_ibex_base_test;
`uvm_component_utils(core_ibex_rf_addr_intg_test)
`uvm_component_new

uvm_report_server rs;
Expand All @@ -215,23 +218,47 @@ class core_ibex_rf_ctrl_intg_test extends core_ibex_base_test;
int rnd_delay;
int unsigned bit_idx;
logic [31:0] orig_val, glitch_val;
logic alert_major_internal;
string glitch_path, alert_major_internal_path;
logic [1:0] ecc_err;
string glitch_path, ecc_alert_path, lockstep_delay_path;
string trgt_core_path[];
string ctrl_signals[];
string err_signals[];
int unsigned ctrl_signal_idx;
int unsigned trgt_core_idx;
string top_path = "core_ibex_tb_top.dut.u_ibex_top";
// Main core signals.
string ibex_rf_path = {top_path, ".gen_regfile_ff.register_file_i"};
// Shadow core signals.
string lockstep_path = {top_path, ".gen_lockstep.u_ibex_lockstep"};
string shdw_ecc_path = {lockstep_path, ".u_shadow_core.gen_regfile_ecc"};
string shdw_rf_path = {lockstep_path, ".gen_shadow_regfile_ff.register_file_shadow_i"};
// The lockstep delay.
int unsigned lockstep_delay;

trgt_core_path = {
ibex_rf_path,
shdw_rf_path
};

ctrl_signals = {
"we_a_dec",
"gen_rdata_mux_check.raddr_onehot_a",
"gen_rdata_mux_check.raddr_onehot_b"
"raddr_a_i",
"raddr_b_i"
};

err_signals = {
"rf_ecc_err_a",
"rf_ecc_err_b"
};

`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(trgt_core_idx, trgt_core_idx < trgt_core_path.size();)
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(ctrl_signal_idx, ctrl_signal_idx < ctrl_signals.size();)
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(rnd_delay, rnd_delay > 1000; rnd_delay < 10_000;)

glitch_path = $sformatf("%s.%s", ibex_rf_path, ctrl_signals[ctrl_signal_idx]);
glitch_path = $sformatf("%s.%s", trgt_core_path[trgt_core_idx], ctrl_signals[ctrl_signal_idx]);

// Read the lockstep delay.
lockstep_delay_path = $sformatf("%s.%s", lockstep_path, "LockstepOffset");
`DV_CHECK_FATAL(uvm_hdl_read(lockstep_delay_path, lockstep_delay));

vseq.start(env.vseqr);
clk_vif.wait_n_clks(rnd_delay);
Expand All @@ -240,27 +267,31 @@ class core_ibex_rf_ctrl_intg_test extends core_ibex_base_test;
`DV_CHECK_FATAL(uvm_hdl_read(glitch_path, orig_val));
`uvm_info(`gfn, $sformatf("Read %x", orig_val), UVM_LOW)

`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(bit_idx, bit_idx < 32;)
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(bit_idx, bit_idx < 5;)

glitch_val = orig_val;
glitch_val[bit_idx] = ~glitch_val[bit_idx];

// Disable TB assertion for alerts.
`DV_ASSERT_CTRL_REQ("tb_no_alerts_triggered", 1'b0)
// Disable one-hot check assertions for RF muxes
`DV_ASSERT_CTRL_REQ("tb_rf_rd_mux_a_onehot", 1'b0)
`DV_ASSERT_CTRL_REQ("tb_rf_rd_mux_b_onehot", 1'b0)

`uvm_info(`gfn, $sformatf("Forcing %s to value 'h%0x", glitch_path, glitch_val), UVM_LOW)
`DV_CHECK_FATAL(uvm_hdl_force(glitch_path, glitch_val));

// Leave glitch applied for one clock cycle.
clk_vif.wait_n_clks(1);
// Determine how long it takes until the error gets noticed.
if (trgt_core_idx == 0) begin
// When we are faulting the main core RF, it takes lockstep_delay until we detect the fault.
// This is because the shadow core ECC checker is responsible for detecting the fault.
clk_vif.wait_n_clks(lockstep_delay);
end else begin
// When we are faulting the shadow core RF, the fault is immediately detected.
#1step;
end

// Check that the alert matches our expectation.
alert_major_internal_path = $sformatf("%s.alert_major_internal_o", top_path);
`DV_CHECK_FATAL(uvm_hdl_read(alert_major_internal_path, alert_major_internal))
`DV_CHECK_FATAL(alert_major_internal, "Major alert did not fire!")
ecc_alert_path = $sformatf("%s.%s", shdw_ecc_path, err_signals[ctrl_signal_idx]);
`DV_CHECK_FATAL(uvm_hdl_read(ecc_alert_path, ecc_err))
`DV_CHECK_FATAL(|ecc_err, "ECC alert did not fire!")

// Release glitch.
`DV_CHECK_FATAL(uvm_hdl_release(glitch_path))
Expand Down
Loading
Loading