From 71eea966cb59b0e096139f1092625040b73727a0 Mon Sep 17 00:00:00 2001 From: Greg Chadwick Date: Mon, 1 Jul 2024 14:09:43 +0100 Subject: [PATCH] [dv] Add riscv_rf_ctrl_intg_test This tests new hardening added to the register file around read and write control signals. --- .../riscv_dv_extension/testlist.yaml | 15 ++++ dv/uvm/core_ibex/tb/core_ibex_tb_top.sv | 6 ++ dv/uvm/core_ibex/tests/core_ibex_test_lib.sv | 72 +++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml b/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml index 6f24e9256b..a73e7f8681 100644 --- a/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml +++ b/dv/uvm/core_ibex/riscv_dv_extension/testlist.yaml @@ -689,6 +689,21 @@ rtl_params: SecureIbex: 1 +- test: riscv_rf_ctrl_intg_test + description: > + Randomly corrupt one of the register file write and read enables signals in the middle of program execution + iterations: 15 + gen_test: riscv_rand_instr_test + gen_opts: > + +instr_cnt=10000 + +num_of_sub_program=5 + +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_params: + SecureIbex: 1 + - test: riscv_icache_intg_test description: > Randomly corrupt the instruction cache once in the middle of program execution diff --git a/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv b/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv index a0e88710a7..931bd8e0b4 100644 --- a/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv +++ b/dv/uvm/core_ibex/tb/core_ibex_tb_top.sv @@ -157,10 +157,16 @@ module core_ibex_tb_top; .core_sleep_o (dut_if.core_sleep ) ); + `define IBEX_RF_PATH core_ibex_tb_top.dut.u_ibex_top.gen_regfile_ff.register_file_i + // We should never see any alerts triggered in normal testing `ASSERT(NoAlertsTriggered, !dut_if.alert_minor && !dut_if.alert_major_internal && !dut_if.alert_major_bus, clk, !rst_n) `DV_ASSERT_CTRL("tb_no_alerts_triggered", core_ibex_tb_top.NoAlertsTriggered) + `DV_ASSERT_CTRL("tb_rf_rd_mux_a_onehot", + `IBEX_RF_PATH.gen_rdata_mux_check.u_rdata_a_mux.SelIsOnehot_A) + `DV_ASSERT_CTRL("tb_rf_rd_mux_b_onehot", + `IBEX_RF_PATH.gen_rdata_mux_check.u_rdata_b_mux.SelIsOnehot_A) assign dut.u_ibex_top.u_ibex_core.u_fcov_bind.rf_we_glitch_err = dut.u_ibex_top.rf_alert_major_internal; diff --git a/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv b/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv index 40a17f30ea..1dd2305eee 100644 --- a/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv +++ b/dv/uvm/core_ibex/tests/core_ibex_test_lib.sv @@ -199,6 +199,78 @@ 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) + `uvm_component_new + + uvm_report_server rs; + + virtual task send_stimulus(); + 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; + string ctrl_signals[]; + int unsigned ctrl_signal_idx; + string top_path = "core_ibex_tb_top.dut.u_ibex_top"; + string ibex_rf_path = {top_path, ".gen_regfile_ff.register_file_i"}; + + ctrl_signals = { + "we_a_dec", + "gen_rdata_mux_check.raddr_onehot_a", + "gen_rdata_mux_check.raddr_onehot_b" + }; + + `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]); + + vseq.start(env.vseqr); + clk_vif.wait_n_clks(rnd_delay); + + `uvm_info(`gfn, $sformatf("Reading value of %s", glitch_path), UVM_LOW) + `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;) + + 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); + + // 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!") + + // Release glitch. + `DV_CHECK_FATAL(uvm_hdl_release(glitch_path)) + `uvm_info(`gfn, $sformatf("Releasing force of %s", glitch_path), UVM_LOW) + + // Re-enable TB assertion for alerts. + `DV_ASSERT_CTRL_REQ("tb_no_alerts_triggered", 1'b1) + + // Complete the test at this point because cosimulation does not model faults so will cause + // a mis-match and a test failure. + rs = uvm_report_server::get_server(); + rs.report_summarize(); + $finish(); + endtask +endclass + // Test that corrupts the instruction cache and checks that an appropriate alert occurs. class core_ibex_icache_intg_test extends core_ibex_base_test;