blob: e1cbbe15c0cbfd3df8be0eb005ce31ba375a4b52 [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_rom_e2e_jtag_inject_vseq extends chip_sw_base_vseq;
`uvm_object_utils(chip_sw_rom_e2e_jtag_inject_vseq)
`uvm_object_new
virtual task pre_start();
cfg.chip_vif.tap_straps_if.drive(JtagTapRvDm);
super.pre_start();
endtask
virtual task body();
string elf_file = {cfg.sw_images[SwTypeDebug], ".elf"};
logic [BUS_DW-1:0] value_q[$];
jtag_rv_debugger_pkg::abstract_cmd_err_e abs_status;
byte status;
logic [BUS_AW-1:0] sram_program_sp, sram_program_gp, sram_program_start;
super.body();
cfg.sw_test_status_vif.can_pass_only_in_test = 0;
// The steps in this test closely follow the gdb steps, which is embedded directly into the
// bazel BUILD file located at sw/device/silicon_creator/rom/e2e/BUILD as the variable
// `SRAM_JTAG_INJECTION_GDB_SCRIPT`. It is passed as argument to the
// `opentitan_gdb_fpga_cw310_test` target `sram_program_fpga_cw310_test_otp_<lc_state>`.
// Let the chip power up and allow the ROM to execute upto an arbitrary point.
`DV_WAIT(cfg.chip_vif.pwrmgr_fast_pwr_state_active)
begin
uint32_t cpu_cycles;
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(cpu_cycles,
cpu_cycles dist {
0 :/ 3,
[1:1000] :/ 3,
[1000:10000] :/ 2,
[10000:20000] :/ 2
};
)
cfg.chip_vif.cpu_clk_rst_if.wait_clks(cpu_cycles);
end
// Halt the CPU.
cfg.debugger.set_elf_file(elf_file);
cfg.debugger.set_dmactive(1);
cfg.debugger.set_haltreq(1);
cfg.debugger.wait_cpu_halted();
cfg.debugger.set_haltreq(0);
`uvm_info(`gfn, "Disable the watchdog timer", UVM_LOW)
cfg.debugger.mem_read(.addr(ral.aon_timer_aon.wdog_ctrl.get_address()),
.value_q(value_q),
.status(status));
`DV_CHECK_EQ(status, 0)
void'(ral.aon_timer_aon.wdog_ctrl.predict(.value(value_q[0]), .kind(UVM_PREDICT_DIRECT)));
if (`gmv(ral.aon_timer_aon.wdog_ctrl.enable)) begin
`uvm_info(`gfn, "WDOG is enabled. Disabling it", UVM_LOW)
cfg.debugger.mem_write(.addr(ral.aon_timer_aon.wdog_ctrl.get_address()),
.value_q({0}),
.status(status));
`DV_CHECK_EQ(status, 0)
`uvm_info(`gfn, "Reset the WDOG count", UVM_LOW)
cfg.debugger.mem_write(.addr(ral.aon_timer_aon.wdog_count.get_address()),
.value_q({0}),
.status(status));
`DV_CHECK_EQ(status, 0)
`uvm_info(`gfn, "Clear the interrupt (if any) by writing to INTR_STATE", UVM_LOW)
cfg.debugger.mem_write(.addr(ral.aon_timer_aon.intr_state.get_address()),
.value_q({0}),
.status(status));
`DV_CHECK_EQ(status, 0)
end else begin
`uvm_info(`gfn, "WDOG is not enabled.", UVM_LOW)
end
// See additional notes on the PMP configuration in the GDB script referenced above.
`uvm_info(`gfn, "Configure the PMP unit", UVM_LOW)
// "Write "L NAPOT X W R" to pmp{0,1,2,3}cfg in pmpcfg0. Crucially, this value is no less
// permissive than whatever the current value is."
cfg.debugger.abstract_cmd_reg_write(.regno(dm::CSR_PMPCFG0), .value_q({'h9f9f9f9f}),
.status(abs_status));
`DV_CHECK_EQ(abs_status, jtag_rv_debugger_pkg::AbstractCmdErrNone)
cfg.debugger.abstract_cmd_reg_write(.regno(dm::CSR_PMPADDR0), .value_q({'hffffffff}),
.status(abs_status));
`DV_CHECK_EQ(abs_status, jtag_rv_debugger_pkg::AbstractCmdErrNone)
begin
longint unsigned addr, size;
bit result;
result = dv_utils_pkg::sw_symbol_get_addr_size(.elf_file(elf_file),
.symbol("_stack_end"), .does_not_exist_ok(0), .addr(addr), .size(size));
`DV_CHECK(result)
sram_program_sp = BUS_AW'(addr);
result = dv_utils_pkg::sw_symbol_get_addr_size(.elf_file(elf_file),
.symbol("__global_pointer$"), .does_not_exist_ok(0), .addr(addr), .size(size));
`DV_CHECK(result)
sram_program_gp = BUS_AW'(addr);
result = dv_utils_pkg::sw_symbol_get_addr_size(.elf_file(elf_file),
.symbol("sram_main"), .does_not_exist_ok(0), .addr(addr), .size(size));
`DV_CHECK(result)
sram_program_start = BUS_AW'(addr);
end
`uvm_info(`gfn, "Load the SRAM program onto the device", UVM_LOW)
cfg.debugger.load_image(.vmem_file({cfg.sw_images[SwTypeDebug], ".32.vmem"}),
.addr(sram_program_start));
`uvm_info(`gfn, "Update registers before calling functions", UVM_LOW)
cfg.debugger.abstract_cmd_reg_write(.regno(jtag_rv_debugger_pkg::RvCoreCsrGprSp),
.value_q({sram_program_sp}),
.status(abs_status));
`DV_CHECK_EQ(abs_status, jtag_rv_debugger_pkg::AbstractCmdErrNone)
cfg.debugger.abstract_cmd_reg_write(.regno(jtag_rv_debugger_pkg::RvCoreCsrGprGp),
.value_q({sram_program_gp}),
.status(abs_status));
`DV_CHECK_EQ(abs_status, jtag_rv_debugger_pkg::AbstractCmdErrNone)
`uvm_info(`gfn, "Invalidate the icache", UVM_LOW)
cfg.debugger.call(.symbol("icache_invalidate"));
`uvm_info(`gfn, "Call sram_main (it writes the PASS pattern to the DV monitor)", UVM_LOW)
cfg.debugger.call(.symbol("sram_main"), .noreturn_function(1));
endtask
endclass