blob: 93c0d2f19e78ecfe6b6566463461dda3484a74b6 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
class chip_sw_exit_test_unlocked_bootstrap_vseq extends chip_sw_base_vseq;
`uvm_object_utils(chip_sw_exit_test_unlocked_bootstrap_vseq)
`uvm_object_new
rand int unlocked_idx;
constraint idx_c {
unlocked_idx inside {[0:7]};
}
rand bit [7:0] lc_exit_token[TokenWidthByte];
virtual task dut_init(string reset_kind = "HARD");
bit [TokenWidthBit-1:0] otp_exit_token_bits;
super.dut_init(reset_kind);
// make sure we are in one of the unlocked states
cfg.mem_bkdr_util_h[Otp].otp_write_lc_partition_state(UnlockedStates[unlocked_idx].lc_state);
// backdoorload the otp tokens and associated digest
otp_exit_token_bits = dec_otp_token_from_lc_csrs(lc_exit_token);
cfg.mem_bkdr_util_h[Otp].otp_write_secret0_partition(
'0, otp_exit_token_bits);
//ensure rom_exec_en is 0, so that flash is never reached
cfg.mem_bkdr_util_h[Otp].write32(otp_ctrl_reg_pkg::CreatorSwCfgRomExecEnOffset, 0);
endtask
// reset jtag interface
virtual task reset_jtag_tap();
cfg.m_jtag_riscv_agent_cfg.in_reset = 1;
#1000ns;
cfg.m_jtag_riscv_agent_cfg.in_reset = 0;
endtask
virtual task body();
bit err = 0;
jtag_riscv_dm_activation_seq jtag_dm_activation_seq =
jtag_riscv_dm_activation_seq::type_id::create("jtag_dm_activation_seq");
super.body();
// The test sequence needs to ensure rom has halted first.
`DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInBootRomHalt)
// Now program ROM_EXEC_EN for next power cycle.
cfg.chip_vif.tap_straps_if.drive(JtagTapRvDm);
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);
// Reset tap interface for switch.
reset_jtag_tap();
// Prepare LC JTAG interface
cfg.chip_vif.tap_straps_if.drive(JtagTapLc);
cfg.clk_rst_vif.wait_clks(10);
cfg.m_jtag_riscv_agent_cfg.is_rv_dm = 0;
for (int i = 0; i < TokenWidthByte; i++) begin
`uvm_info(`gfn, $sformatf("LC exit token 0x%x", lc_exit_token[i]), UVM_MEDIUM)
end
// TODO: Should consider applying a random large delay here to simulate different
// host side timing.
// Transition device into production state.
jtag_lc_state_transition(UnlockedStates[unlocked_idx].dec_lc_state,
DecLcStProd, {<<8{lc_exit_token}});
// LC state transition requires a chip reset.
`uvm_info(`gfn, "Applying reset after lc transition", UVM_LOW)
apply_reset();
// setup triggers to bootstrap during the second run
cfg.chip_vif.sw_straps_if.drive({3{1'b1}});
`DV_WAIT(cfg.sw_test_status_vif.sw_test_status == SwTestStatusInBootRom)
// bootstrap the same image
spi_device_load_bootstrap({cfg.sw_images[SwTypeTestSlotA], ".64.vmem"});
endtask : body
task post_start();
// Disconnect straps driving so that subsequent tests can make use of this interface
// without any assumptions.
cfg.chip_vif.sw_straps_if.disconnect();
endtask : post_start
endclass : chip_sw_exit_test_unlocked_bootstrap_vseq