From 9c780615a1ac0da95a320f5f48c71a945a7fb8b1 Mon Sep 17 00:00:00 2001 From: Michael Schaffner Date: Tue, 13 Feb 2024 14:52:59 -0800 Subject: [PATCH] [top/dv] Make volatile RAW unlock test parameteric Besides being able to test the volatile RAW unlock mechanism, we should also be able to test whether the case where that mechanism has been disabled in HW. This patch adds a plusarg that allows to parameterize the test with our expectation. In production silicon this mechanism should be disabled, for example. Signed-off-by: Michael Schaffner --- .../data/ip/chip_lc_ctrl_testplan.hjson | 11 ++- hw/top_earlgrey/dv/chip_sim_cfg.hjson | 11 ++- .../dv/env/seq_lib/chip_sw_base_vseq.sv | 36 +++++-- .../chip_sw_lc_volatile_raw_unlock_vseq.sv | 94 +++++++++++-------- 4 files changed, 104 insertions(+), 48 deletions(-) diff --git a/hw/top_earlgrey/data/ip/chip_lc_ctrl_testplan.hjson b/hw/top_earlgrey/data/ip/chip_lc_ctrl_testplan.hjson index 5b8ed309d97ff..a37f8fa181d9e 100644 --- a/hw/top_earlgrey/data/ip/chip_lc_ctrl_testplan.hjson +++ b/hw/top_earlgrey/data/ip/chip_lc_ctrl_testplan.hjson @@ -297,12 +297,21 @@ - Pre-load OTP image with RAW lc_state. - Initiate the LC transition to test_unlocked0 state using the VOLATILE_RAW_UNLOCK mode of operation. + + If this top-level is expected to support VOLATILE_RAW_UNLOCK: + - As part of the transition to test_unlocked0, switch the TAP interface to rv_dm. - Enable ROM execution via rv_dm, and perform POR. - Initiate a second transition to test_unlocked0 using VOLATILE_RAW_UNLOCK. - Verify that the CPU is able to execute. + - Test ext_clk injection before enabling ROM execution. + + If this top-level is NOT expected to support VOLATILE_RAW_UNLOCK: - Test ext_clk injection before enabling ROM execution. + - Check that the VOLATILE_RAW_UNLOCK bit in the transition control register stays 0 + when it is programmed to 1. + - Check that the transition results in a token error (the real RAW unlock transition + expects the unhashed token instead of the hashed token supplied for volatile RAW unlock). ''' features: [ "LC_CTRL.STATE.RAW", diff --git a/hw/top_earlgrey/dv/chip_sim_cfg.hjson b/hw/top_earlgrey/dv/chip_sim_cfg.hjson index 379e254e6a68e..ebf4606cd2aa5 100644 --- a/hw/top_earlgrey/dv/chip_sim_cfg.hjson +++ b/hw/top_earlgrey/dv/chip_sim_cfg.hjson @@ -925,7 +925,11 @@ uvm_test_seq: chip_sw_lc_volatile_raw_unlock_vseq sw_images: ["//sw/device/tests/sim_dv:lc_ctrl_volatile_raw_unlock_test:1:new_rules"] en_run_modes: ["sw_test_mode_test_rom"] - run_opts: ["+use_otp_image=OtpTypeLcStRaw"] + run_opts: [ + "+use_otp_image=OtpTypeLcStRaw", + // We set this to zero if the volatile RAW unlock mechanism is expected + // to be disabled (this should be the case in production silicon). + "+exp_volatile_raw_unlock_en=0"] run_timeout_mins: 120 } { @@ -935,7 +939,10 @@ en_run_modes: ["sw_test_mode_test_rom"] run_opts: [ "+use_otp_image=OtpTypeLcStRaw", - "+chip_clock_source=ChipClockSourceExternal48Mhz"] + "+chip_clock_source=ChipClockSourceExternal48Mhz", + // We set this to zero if the volatile RAW unlock mechanism is expected + // to be disabled (this should be the case in production silicon). + "+exp_volatile_raw_unlock_en=0"] run_timeout_mins: 120 } { diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_base_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_base_vseq.sv index e73670285f225..007c4fbc9cbb5 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_base_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_base_vseq.sv @@ -801,9 +801,18 @@ class chip_sw_base_vseq extends chip_base_vseq; cfg.m_jtag_riscv_agent_cfg.allow_errors = 0; endtask + virtual task wait_lc_token_error(bit allow_err = 1, int max_attempt = 5000); + cfg.m_jtag_riscv_agent_cfg.allow_errors = allow_err; + wait_lc_status(LcTokenError, max_attempt); + cfg.m_jtag_riscv_agent_cfg.allow_errors = 0; + endtask + // Use JTAG interface to transit LC_CTRL from RAW to TEST_UNLOCKED* states // using the VOLATILE_RAW_UNLOCK mode of operation. - virtual task jtag_lc_state_volatile_raw_unlock(chip_jtag_tap_e target_strap); + // If this operation is expected to fail due to the absence of the mechanism in HW, set the + // expect_success argument to 0. + virtual task jtag_lc_state_volatile_raw_unlock(chip_jtag_tap_e target_strap, + bit expect_success = 1); bit [TL_DW-1:0] current_lc_state; bit [TL_DW-1:0] transition_ctrl; bit use_ext_clk = 1'b0; @@ -840,8 +849,15 @@ class chip_sw_base_vseq extends chip_base_vseq; ral.lc_ctrl.transition_ctrl.get_offset(), p_sequencer.jtag_sequencer_h, transition_ctrl); - `DV_CHECK_FATAL(transition_ctrl & (1 << 1), {"VOLATILE_RAW_UNLOCK is not supported by this ", - "top level. Check the SecVolatileRawUnlockEn parameter configuration."}) + // In this case we expect the transition_ctrl bit to stay 0. + if (expect_success) begin + `DV_CHECK_FATAL(transition_ctrl & (1 << 1), {"VOLATILE_RAW_UNLOCK is not supported by this ", + "top level. Check the SecVolatileRawUnlockEn parameter configuration."}) + end else begin + `DV_CHECK_FATAL(!(transition_ctrl & (1 << 1)), {"VOLATILE_RAW_UNLOCK is not expected to be ", + "supported by this top-level. Check the SecVolatileRawUnlockEn parameter ", + "configuration."}) + end if (use_ext_clk) begin wait_lc_ext_clk_switched(); @@ -869,10 +885,16 @@ class chip_sw_base_vseq extends chip_base_vseq; 1); if (target_strap == JtagTapLc) begin - wait_lc_transition_successful(.max_attempt(max_attempt)); - jtag_riscv_agent_pkg::jtag_write_csr(ral.lc_ctrl.claim_transition_if.get_offset(), - p_sequencer.jtag_sequencer_h, - prim_mubi_pkg::MuBi8False); + if (expect_success) begin + wait_lc_transition_successful(.max_attempt(max_attempt)); + jtag_riscv_agent_pkg::jtag_write_csr(ral.lc_ctrl.claim_transition_if.get_offset(), + p_sequencer.jtag_sequencer_h, + prim_mubi_pkg::MuBi8False); + end else begin + // The hashed token should be invalid if volatile unlock is not supported, since the + // regular transition expects that the unhashed token is provided. + wait_lc_token_error(.max_attempt(max_attempt)); + end end else begin cfg.clk_rst_vif.wait_clks($urandom_range(10000, 20000)); end diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_volatile_raw_unlock_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_volatile_raw_unlock_vseq.sv index dec13dd8f1cad..ca9e18e4775e8 100644 --- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_volatile_raw_unlock_vseq.sv +++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_lc_volatile_raw_unlock_vseq.sv @@ -11,8 +11,12 @@ class chip_sw_lc_volatile_raw_unlock_vseq extends chip_sw_base_vseq; // image. bit rom_prod_mode = 1'b0; + // Indicates whether we expect the volatile RAW unlock feature to be enabled in HW or not. + bit exp_volatile_raw_unlock_en = 1'b0; + virtual task pre_start(); void'($value$plusargs("rom_prod_mode=%0d", rom_prod_mode)); + void'($value$plusargs("exp_volatile_raw_unlock_en=%0d", exp_volatile_raw_unlock_en)); cfg.chip_vif.tap_straps_if.drive(JtagTapLc); super.pre_start(); endtask @@ -33,49 +37,63 @@ class chip_sw_lc_volatile_raw_unlock_vseq extends chip_sw_base_vseq; super.body(); - // Since super.body only does backdoor operatoin, + // Since super.body only does backdoor operation, // add wait for clock task before the test uses jtag polling task. wait_rom_check_done(); wait_lc_ready(1); - // VOLATILE_RAW_UNLOCK does not require a reset after completion. - // Applying a reset will move the device back to RAW state in this case. - jtag_lc_state_volatile_raw_unlock(JtagTapRvDm); - reset_jtag_tap(); - - if (rom_prod_mode) begin - // The production ROM is not instrumented to report `sw_test_status`, so - // we wait for the PC to advance before continuing with the test. The - // PC was taken from the ROM disassembly. - `DV_WAIT(cfg.chip_vif.probed_cpu_pc.pc_wb >= 8194) + // If we're expecting the feature to be enabled, the device should boot. + if (exp_volatile_raw_unlock_en) begin + // VOLATILE_RAW_UNLOCK does not require a reset after completion. + // Applying a reset will move the device back to RAW state in this case. + jtag_lc_state_volatile_raw_unlock(.target_strap(JtagTapRvDm), .expect_success(1)); + reset_jtag_tap(); + + if (rom_prod_mode) begin + // The production ROM is not instrumented to report `sw_test_status`, so + // we wait for the PC to advance before continuing with the test. The + // PC was taken from the ROM disassembly. + `DV_WAIT(cfg.chip_vif.probed_cpu_pc.pc_wb >= 8194) + end else begin + // In RAW state the ROM should halt as RomExecEn is not set yet. + `DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInBootRomHalt) + end + + // Use the frontend interface to configure the RomExecEn OTP value. A + // reset is required to have otp_ctrl sample the new OTP value. + `uvm_info(`gfn, "Configuring RomExecEng", UVM_LOW) + jtag_dm_activation_seq.start(p_sequencer.jtag_sequencer_h); + `uvm_info(`gfn, $sformatf("rv_dm_activated: %0d", cfg.m_jtag_riscv_agent_cfg.rv_dm_activated), + UVM_LOW) + cfg.m_jtag_riscv_agent_cfg.is_rv_dm = 1; + jtag_otp_program32(otp_ctrl_reg_pkg::CreatorSwCfgRomExecEnOffset, 1); + + cfg.chip_vif.tap_straps_if.drive(JtagTapLc); + cfg.m_jtag_riscv_agent_cfg.is_rv_dm = 0; + apply_reset(); + reset_jtag_tap(); + + // Wait for `rom_ctrl` to complete the ROM check. This will give the dut + // enough time to configure the TAP interface before any JTAG agents send + // any commands. + wait_rom_check_done(); + + // Second VOLATILE_RAW_UNLOCK does not change the TAP interface to rv_dm + // so that we can check the completion status through that interface. + // After this, the rest of the test should proceed. + jtag_lc_state_volatile_raw_unlock(JtagTapLc); end else begin - // In RAW state the ROM should halt as RomExecEn is not set yet. - `DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInBootRomHalt) + // We expect this to fail in this case. + jtag_lc_state_volatile_raw_unlock(.target_strap(JtagTapLc), .expect_success(0)); end - - // Use the frontend interface to configure the RomExecEn OTP value. A - // reset is required to have otp_ctrl sample the new OTP value. - `uvm_info(`gfn, "Configuring RomExecEng", UVM_LOW) - jtag_dm_activation_seq.start(p_sequencer.jtag_sequencer_h); - `uvm_info(`gfn, $sformatf("rv_dm_activated: %0d", cfg.m_jtag_riscv_agent_cfg.rv_dm_activated), - UVM_LOW) - cfg.m_jtag_riscv_agent_cfg.is_rv_dm = 1; - jtag_otp_program32(otp_ctrl_reg_pkg::CreatorSwCfgRomExecEnOffset, 1); - - cfg.chip_vif.tap_straps_if.drive(JtagTapLc); - cfg.m_jtag_riscv_agent_cfg.is_rv_dm = 0; - apply_reset(); - reset_jtag_tap(); - - // Wait for `rom_ctrl` to complete the ROM check. This will give the dut - // enough time to configure the TAP interface before any JTAG agents send - // any commands. - wait_rom_check_done(); - - // Second VOLATILE_RAW_UNLOCK does not change the TAP interface to rv_dm - // so that we can check the completion status through that interface. - // After this, the rest of the test should proceed. - jtag_lc_state_volatile_raw_unlock(JtagTapLc); - endtask + + task post_start(); + // In case the volatile RAW unlock feature is not supported by HW, the transition is not going + // to succeed and SW will never be able to run. + if (!exp_volatile_raw_unlock_en) begin + override_test_status_and_finish(.passed(1)); + end + super.post_start(); + endtask : post_start endclass