blob: d9c8131b361013da44091611697ca17733f8de2a [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
module tb;
// dep packages
import uvm_pkg::*;
import dv_utils_pkg::*;
import tl_agent_pkg::*;
import chip_env_pkg::*;
import chip_common_pkg::*;
import top_pkg::*;
import top_earlgrey_pkg::*;
import chip_test_pkg::*;
import xbar_test_pkg::*;
import mem_bkdr_util_pkg::mem_bkdr_util;
// macro includes
`include "uvm_macros.svh"
`include "dv_macros.svh"
`include "chip_hier_macros.svh" // TODO: Deprecate this.
// interfaces
// Legacy clk_rst_if to satisfy our CIP base classes. DO NOT USE it in test sequences.
//
// This interface has an active clock driver, but the clock port is not connected to anything. The
// reset port is passive and is connected to the chip's POR_N port. The reset port is active only
// in `xbar_mode`, because a different UVM environment is in use, which does not have the chip_if.
// For the regular chip tests, the chip_if is used exclusively to drive all chip's ports.
//
// The bogus active clock is made to match the chip's main clock frequency. This is done to
// ensure compatibility with the CIP / DV lib base sequence classes which assume certain things.
// This clk_rst_if (which is available in the chip env as cfg.clk_rst_vif) should not be used to
// wait for clock events. Most tests will not require an external clock source - they will use
// internally generated clock provided by AST.
//
// Note that attempting to drive the external clock / power on reset using this interface will
// vacuously return instead of throwing an error. This is done to support the our base classes.
// To do so, the test sequences must use chip_vif.ext_clk_if and chip_vif.por_n_if respectively.
wire clk, rst_n;
clk_rst_if clk_rst_if(.clk(clk), .rst_n(rst_n));
// TODO: Absorb this functionality into chip_if.
bind dut ast_supply_if ast_supply_if (
.clk(top_earlgrey.clk_aon_i),
.core_sleeping_trigger(top_earlgrey.rv_core_ibex_pwrmgr.core_sleeping),
.low_power_trigger(`PWRMGR_HIER.pwr_rst_o.reset_cause == pwrmgr_pkg::LowPwrEntry)
);
// TODO: Absorb this functionality into chip_if.
bind dut ast_ext_clk_if ast_ext_clk_if ();
// TODO: Absorb this functionality into chip_if.
alert_esc_if alert_if[NUM_ALERTS](.clk (`ALERT_HANDLER_HIER.clk_i),
.rst_n(`ALERT_HANDLER_HIER.rst_ni));
for (genvar i = 0; i < NUM_ALERTS; i++) begin : gen_connect_alert_rx
assign alert_if[i].alert_rx = `ALERT_HANDLER_HIER.alert_rx_o[i];
end
bind chip_earlgrey_asic chip_if chip_if();
`ifdef DISABLE_ROM_INTEGRITY_CHECK
chip_earlgrey_asic #(
// This is to be used carefully, and should never be on for synthesis.
// It causes many rom features to be disabled, including the very slow
// integrity check, so full chip simulation runs don't do it for each
// reset.
.SecRomCtrlDisableScrambling(1'b1)
) dut (
`else
chip_earlgrey_asic dut (
`endif
// Dedicated Pads
.POR_N(dut.chip_if.dios[top_earlgrey_pkg::DioPadPorN]),
.USB_P(dut.chip_if.dios[top_earlgrey_pkg::DioPadUsbP]),
.USB_N(dut.chip_if.dios[top_earlgrey_pkg::DioPadUsbN]),
.CC1(dut.chip_if.dios[top_earlgrey_pkg::DioPadCc1]),
.CC2(dut.chip_if.dios[top_earlgrey_pkg::DioPadCc2]),
.FLASH_TEST_VOLT(dut.chip_if.dios[top_earlgrey_pkg::DioPadFlashTestVolt]),
.FLASH_TEST_MODE0(dut.chip_if.dios[top_earlgrey_pkg::DioPadFlashTestMode0]),
.FLASH_TEST_MODE1(dut.chip_if.dios[top_earlgrey_pkg::DioPadFlashTestMode1]),
.OTP_EXT_VOLT(dut.chip_if.dios[top_earlgrey_pkg::DioPadOtpExtVolt]),
.SPI_HOST_D0(dut.chip_if.dios[top_earlgrey_pkg::DioPadSpiHostD0]),
.SPI_HOST_D1(dut.chip_if.dios[top_earlgrey_pkg::DioPadSpiHostD1]),
.SPI_HOST_D2(dut.chip_if.dios[top_earlgrey_pkg::DioPadSpiHostD2]),
.SPI_HOST_D3(dut.chip_if.dios[top_earlgrey_pkg::DioPadSpiHostD3]),
.SPI_HOST_CLK(dut.chip_if.dios[top_earlgrey_pkg::DioPadSpiHostClk]),
.SPI_HOST_CS_L(dut.chip_if.dios[top_earlgrey_pkg::DioPadSpiHostCsL]),
.SPI_DEV_D0(dut.chip_if.dios[top_earlgrey_pkg::DioPadSpiDevD0]),
.SPI_DEV_D1(dut.chip_if.dios[top_earlgrey_pkg::DioPadSpiDevD1]),
.SPI_DEV_D2(dut.chip_if.dios[top_earlgrey_pkg::DioPadSpiDevD2]),
.SPI_DEV_D3(dut.chip_if.dios[top_earlgrey_pkg::DioPadSpiDevD3]),
.SPI_DEV_CLK(dut.chip_if.dios[top_earlgrey_pkg::DioPadSpiDevClk]),
.SPI_DEV_CS_L(dut.chip_if.dios[top_earlgrey_pkg::DioPadSpiDevCsL]),
.IOR8(dut.chip_if.dios[top_earlgrey_pkg::DioPadIor8]),
.IOR9(dut.chip_if.dios[top_earlgrey_pkg::DioPadIor9]),
.AST_MISC(dut.chip_if.ast_misc),
// Muxed Pads
.IOA0(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoa0]),
.IOA1(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoa1]),
.IOA2(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoa2]),
.IOA3(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoa3]),
.IOA4(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoa4]),
.IOA5(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoa5]),
.IOA6(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoa6]),
.IOA7(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoa7]),
.IOA8(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoa8]),
.IOB0(dut.chip_if.mios[top_earlgrey_pkg::MioPadIob0]),
.IOB1(dut.chip_if.mios[top_earlgrey_pkg::MioPadIob1]),
.IOB2(dut.chip_if.mios[top_earlgrey_pkg::MioPadIob2]),
.IOB3(dut.chip_if.mios[top_earlgrey_pkg::MioPadIob3]),
.IOB4(dut.chip_if.mios[top_earlgrey_pkg::MioPadIob4]),
.IOB5(dut.chip_if.mios[top_earlgrey_pkg::MioPadIob5]),
.IOB6(dut.chip_if.mios[top_earlgrey_pkg::MioPadIob6]),
.IOB7(dut.chip_if.mios[top_earlgrey_pkg::MioPadIob7]),
.IOB8(dut.chip_if.mios[top_earlgrey_pkg::MioPadIob8]),
.IOB9(dut.chip_if.mios[top_earlgrey_pkg::MioPadIob9]),
.IOB10(dut.chip_if.mios[top_earlgrey_pkg::MioPadIob10]),
.IOB11(dut.chip_if.mios[top_earlgrey_pkg::MioPadIob11]),
.IOB12(dut.chip_if.mios[top_earlgrey_pkg::MioPadIob12]),
.IOC0(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoc0]),
.IOC1(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoc1]),
.IOC2(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoc2]),
.IOC3(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoc3]),
.IOC4(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoc4]),
.IOC5(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoc5]),
.IOC6(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoc6]),
.IOC7(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoc7]),
.IOC8(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoc8]),
.IOC9(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoc9]),
.IOC10(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoc10]),
.IOC11(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoc11]),
.IOC12(dut.chip_if.mios[top_earlgrey_pkg::MioPadIoc12]),
.IOR0(dut.chip_if.mios[top_earlgrey_pkg::MioPadIor0]),
.IOR1(dut.chip_if.mios[top_earlgrey_pkg::MioPadIor1]),
.IOR2(dut.chip_if.mios[top_earlgrey_pkg::MioPadIor2]),
.IOR3(dut.chip_if.mios[top_earlgrey_pkg::MioPadIor3]),
.IOR4(dut.chip_if.mios[top_earlgrey_pkg::MioPadIor4]),
.IOR5(dut.chip_if.mios[top_earlgrey_pkg::MioPadIor5]),
.IOR6(dut.chip_if.mios[top_earlgrey_pkg::MioPadIor6]),
.IOR7(dut.chip_if.mios[top_earlgrey_pkg::MioPadIor7]),
.IOR10(dut.chip_if.mios[top_earlgrey_pkg::MioPadIor10]),
.IOR11(dut.chip_if.mios[top_earlgrey_pkg::MioPadIor11]),
.IOR12(dut.chip_if.mios[top_earlgrey_pkg::MioPadIor12]),
.IOR13(dut.chip_if.mios[top_earlgrey_pkg::MioPadIor13])
);
`define SIM_SRAM_IF u_sim_sram.u_sim_sram_if
// Instantiate & connect the simulation SRAM inside the CPU (rv_core_ibex) using forces.
bit en_sim_sram = 1'b1;
wire sel_sim_sram = !dut.chip_if.stub_cpu & en_sim_sram;
sim_sram u_sim_sram (
.clk_i (sel_sim_sram ? `CPU_HIER.clk_i : 1'b0),
.rst_ni (`CPU_HIER.rst_ni),
.tl_in_i (tlul_pkg::tl_h2d_t'(`CPU_HIER.u_tlul_req_buf.out_o)),
.tl_in_o (),
.tl_out_o (),
.tl_out_i ()
);
initial begin
void'($value$plusargs("en_sim_sram=%0b", en_sim_sram));
if (!dut.chip_if.stub_cpu && en_sim_sram) begin
`SIM_SRAM_IF.start_addr = SW_DV_START_ADDR;
force `CPU_HIER.u_tlul_rsp_buf.in_i = u_sim_sram.tl_in_o;
end
end
// Bind the SW test status interface directly to the sim SRAM interface.
bind `SIM_SRAM_IF sw_test_status_if u_sw_test_status_if (
.addr (tl_h2d.a_address),
.data (tl_h2d.a_data[15:0]),
.fetch_en (dut.chip_if.pwrmgr_cpu_fetch_en),
.*
);
// Bind the SW logger interface directly to the sim SRAM interface.
bind `SIM_SRAM_IF sw_logger_if u_sw_logger_if (
.addr (tl_h2d.a_address),
.data (tl_h2d.a_data),
.*
);
initial begin
// IO Interfaces
uvm_config_db#(virtual chip_if)::set(null, "*.env", "chip_vif", dut.chip_if);
// SW logger and test status interfaces.
uvm_config_db#(virtual sw_test_status_if)::set(
null, "*.env", "sw_test_status_vif", `SIM_SRAM_IF.u_sw_test_status_if);
uvm_config_db#(virtual sw_logger_if)::set(
null, "*.env", "sw_logger_vif", `SIM_SRAM_IF.u_sw_logger_if);
// AST supply interface.
uvm_config_db#(virtual ast_supply_if)::set(
null, "*.env", "ast_supply_vif", dut.ast_supply_if);
// AST io clk blocker interface.
uvm_config_db#(virtual ast_ext_clk_if)::set(
null, "*.env", "ast_ext_clk_vif", dut.ast_ext_clk_if);
// Format time in microseconds losing no precision. The added "." makes it easier to determine
// the order of magnitude without counting digits, as is needed if it was formatted as ps or ns.
$timeformat(-6, 6, " us", 13);
run_test();
end
for (genvar i = 0; i < NUM_ALERTS; i++) begin : gen_alert_vif
initial begin
uvm_config_db#(virtual alert_esc_if)::set(null, $sformatf("*.env.m_alert_agent_%0s",
LIST_OF_ALERTS[i]), "vif", alert_if[i]);
end
end
`undef SIM_SRAM_IF
// Instantitate the memory backdoor util instances.
if (`PRIM_DEFAULT_IMPL == prim_pkg::ImplGeneric) begin : gen_generic
initial begin
chip_mem_e mem;
mem_bkdr_util m_mem_bkdr_util[chip_mem_e];
`uvm_info("tb.sv", "Creating mem_bkdr_util instance for flash 0 data", UVM_MEDIUM)
m_mem_bkdr_util[FlashBank0Data] = new(
.name ("mem_bkdr_util[FlashBank0Data]"),
.path (`DV_STRINGIFY(`FLASH0_DATA_MEM_HIER)),
.depth ($size(`FLASH0_DATA_MEM_HIER)),
.n_bits($bits(`FLASH0_DATA_MEM_HIER)),
.err_detection_scheme(mem_bkdr_util_pkg::EccHamming_76_68),
.system_base_addr (top_earlgrey_pkg::TOP_EARLGREY_EFLASH_BASE_ADDR));
`MEM_BKDR_UTIL_FILE_OP(m_mem_bkdr_util[FlashBank0Data], `FLASH0_DATA_MEM_HIER)
`uvm_info("tb.sv", "Creating mem_bkdr_util instance for flash 0 info", UVM_MEDIUM)
m_mem_bkdr_util[FlashBank0Info] = new(
.name ("mem_bkdr_util[FlashBank0Info]"),
.path (`DV_STRINGIFY(`FLASH0_INFO_MEM_HIER)),
.depth ($size(`FLASH0_INFO_MEM_HIER)),
.n_bits($bits(`FLASH0_INFO_MEM_HIER)),
.err_detection_scheme(mem_bkdr_util_pkg::EccHamming_76_68),
.system_base_addr (top_earlgrey_pkg::TOP_EARLGREY_EFLASH_BASE_ADDR));
`MEM_BKDR_UTIL_FILE_OP(m_mem_bkdr_util[FlashBank0Info], `FLASH0_INFO_MEM_HIER)
`uvm_info("tb.sv", "Creating mem_bkdr_util instance for flash 1 data", UVM_MEDIUM)
m_mem_bkdr_util[FlashBank1Data] = new(
.name ("mem_bkdr_util[FlashBank1Data]"),
.path (`DV_STRINGIFY(`FLASH1_DATA_MEM_HIER)),
.depth ($size(`FLASH1_DATA_MEM_HIER)),
.n_bits($bits(`FLASH1_DATA_MEM_HIER)),
.err_detection_scheme(mem_bkdr_util_pkg::EccHamming_76_68),
.system_base_addr (top_earlgrey_pkg::TOP_EARLGREY_EFLASH_BASE_ADDR +
top_earlgrey_pkg::TOP_EARLGREY_EFLASH_SIZE_BYTES / flash_ctrl_pkg::NumBanks));
`MEM_BKDR_UTIL_FILE_OP(m_mem_bkdr_util[FlashBank1Data], `FLASH1_DATA_MEM_HIER)
`uvm_info("tb.sv", "Creating mem_bkdr_util instance for flash 1 info", UVM_MEDIUM)
m_mem_bkdr_util[FlashBank1Info] = new(
.name ("mem_bkdr_util[FlashBank1Info]"),
.path (`DV_STRINGIFY(`FLASH1_INFO_MEM_HIER)),
.depth ($size(`FLASH1_INFO_MEM_HIER)),
.n_bits($bits(`FLASH1_INFO_MEM_HIER)),
.err_detection_scheme(mem_bkdr_util_pkg::EccHamming_76_68),
.system_base_addr (top_earlgrey_pkg::TOP_EARLGREY_EFLASH_BASE_ADDR +
top_earlgrey_pkg::TOP_EARLGREY_EFLASH_SIZE_BYTES / flash_ctrl_pkg::NumBanks));
`MEM_BKDR_UTIL_FILE_OP(m_mem_bkdr_util[FlashBank1Info], `FLASH1_INFO_MEM_HIER)
`uvm_info("tb.sv", "Creating mem_bkdr_util instance for I cache way 0 tag", UVM_MEDIUM)
m_mem_bkdr_util[ICacheWay0Tag] = new(
.name ("mem_bkdr_util[ICacheWay0Tag]"),
.path (`DV_STRINGIFY(`ICACHE0_TAG_MEM_HIER)),
.depth ($size(`ICACHE0_TAG_MEM_HIER)),
.n_bits($bits(`ICACHE0_TAG_MEM_HIER)),
.err_detection_scheme(mem_bkdr_util_pkg::EccInv_28_22));
`MEM_BKDR_UTIL_FILE_OP(m_mem_bkdr_util[ICacheWay0Tag], `ICACHE0_TAG_MEM_HIER)
`uvm_info("tb.sv", "Creating mem_bkdr_util instance for I cache way 1 tag", UVM_MEDIUM)
m_mem_bkdr_util[ICacheWay1Tag] = new(
.name ("mem_bkdr_util[ICacheWay1Tag]"),
.path (`DV_STRINGIFY(`ICACHE1_TAG_MEM_HIER)),
.depth ($size(`ICACHE1_TAG_MEM_HIER)),
.n_bits($bits(`ICACHE1_TAG_MEM_HIER)),
.err_detection_scheme(mem_bkdr_util_pkg::EccInv_28_22));
`MEM_BKDR_UTIL_FILE_OP(m_mem_bkdr_util[ICacheWay1Tag], `ICACHE1_TAG_MEM_HIER)
`uvm_info("tb.sv", "Creating mem_bkdr_util instance for I cache way 0 data", UVM_MEDIUM)
m_mem_bkdr_util[ICacheWay0Data] = new(
.name ("mem_bkdr_util[ICacheWay0Data]"),
.path (`DV_STRINGIFY(`ICACHE0_DATA_MEM_HIER)),
.depth ($size(`ICACHE0_DATA_MEM_HIER)),
.n_bits($bits(`ICACHE0_DATA_MEM_HIER)),
// The line size is 2x 32 bits and ECC is applied separately at the 32-bit word level.
.err_detection_scheme(mem_bkdr_util_pkg::EccInv_39_32));
`MEM_BKDR_UTIL_FILE_OP(m_mem_bkdr_util[ICacheWay0Data], `ICACHE0_DATA_MEM_HIER)
`uvm_info("tb.sv", "Creating mem_bkdr_util instance for I cache way 1 data", UVM_MEDIUM)
m_mem_bkdr_util[ICacheWay1Data] = new(
.name ("mem_bkdr_util[ICacheWay1Data]"),
.path (`DV_STRINGIFY(`ICACHE1_DATA_MEM_HIER)),
.depth ($size(`ICACHE1_DATA_MEM_HIER)),
.n_bits($bits(`ICACHE1_DATA_MEM_HIER)),
// The line size is 2x 32 bits and ECC is applied separately at the 32-bit word level.
.err_detection_scheme(mem_bkdr_util_pkg::EccInv_39_32));
`MEM_BKDR_UTIL_FILE_OP(m_mem_bkdr_util[ICacheWay1Data], `ICACHE1_DATA_MEM_HIER)
`uvm_info("tb.sv", "Creating mem_bkdr_util instance for OTP", UVM_MEDIUM)
m_mem_bkdr_util[Otp] = new(
.name ("mem_bkdr_util[Otp]"),
.path (`DV_STRINGIFY(`OTP_MEM_HIER)),
.depth ($size(`OTP_MEM_HIER)),
.n_bits($bits(`OTP_MEM_HIER)),
.err_detection_scheme(mem_bkdr_util_pkg::EccHamming_22_16));
`MEM_BKDR_UTIL_FILE_OP(m_mem_bkdr_util[Otp], `OTP_MEM_HIER)
`uvm_info("tb.sv", "Creating mem_bkdr_util instance for RAM", UVM_MEDIUM)
m_mem_bkdr_util[RamMain0] = new(
.name ("mem_bkdr_util[RamMain0]"),
.path (`DV_STRINGIFY(`RAM_MAIN_MEM_HIER)),
.depth ($size(`RAM_MAIN_MEM_HIER)),
.n_bits($bits(`RAM_MAIN_MEM_HIER)),
.err_detection_scheme(mem_bkdr_util_pkg::EccInv_39_32),
.system_base_addr (top_earlgrey_pkg::TOP_EARLGREY_RAM_MAIN_BASE_ADDR));
`MEM_BKDR_UTIL_FILE_OP(m_mem_bkdr_util[RamMain0], `RAM_MAIN_MEM_HIER)
`uvm_info("tb.sv", "Creating mem_bkdr_util instance for RAM RET", UVM_MEDIUM)
m_mem_bkdr_util[RamRet0] = new(
.name ("mem_bkdr_util[RamRet0]"),
.path (`DV_STRINGIFY(`RAM_RET_MEM_HIER)),
.depth ($size(`RAM_RET_MEM_HIER)),
.n_bits($bits(`RAM_RET_MEM_HIER)),
.err_detection_scheme(mem_bkdr_util_pkg::EccInv_39_32),
.system_base_addr (top_earlgrey_pkg::TOP_EARLGREY_RAM_RET_AON_BASE_ADDR));
`MEM_BKDR_UTIL_FILE_OP(m_mem_bkdr_util[RamRet0], `RAM_RET_MEM_HIER)
`uvm_info("tb.sv", "Creating mem_bkdr_util instance for ROM", UVM_MEDIUM)
m_mem_bkdr_util[Rom] = new(
.name ("mem_bkdr_util[Rom]"),
.path (`DV_STRINGIFY(`ROM_MEM_HIER)),
.depth ($size(`ROM_MEM_HIER)),
.n_bits($bits(`ROM_MEM_HIER)),
`ifdef DISABLE_ROM_INTEGRITY_CHECK
.err_detection_scheme(mem_bkdr_util_pkg::ErrDetectionNone),
`else
.err_detection_scheme(mem_bkdr_util_pkg::EccInv_39_32),
`endif
.system_base_addr (top_earlgrey_pkg::TOP_EARLGREY_ROM_BASE_ADDR));
`MEM_BKDR_UTIL_FILE_OP(m_mem_bkdr_util[Rom], `ROM_MEM_HIER)
`uvm_info("tb.sv", "Creating mem_bkdr_util instance for OTBN IMEM", UVM_MEDIUM)
m_mem_bkdr_util[OtbnImem] = new(.name ("mem_bkdr_util[OtbnImem]"),
.path (`DV_STRINGIFY(`OTBN_IMEM_HIER)),
.depth ($size(`OTBN_IMEM_HIER)),
.n_bits($bits(`OTBN_IMEM_HIER)),
.err_detection_scheme(mem_bkdr_util_pkg::EccInv_39_32));
`MEM_BKDR_UTIL_FILE_OP(m_mem_bkdr_util[OtbnImem], `OTBN_IMEM_HIER)
`uvm_info("tb.sv", "Creating mem_bkdr_util instance for OTBN DMEM", UVM_MEDIUM)
m_mem_bkdr_util[OtbnDmem0] = new(.name ("mem_bkdr_util[OtbnDmem0]"),
.path (`DV_STRINGIFY(`OTBN_DMEM_HIER)),
.depth ($size(`OTBN_DMEM_HIER)),
.n_bits($bits(`OTBN_DMEM_HIER)),
.err_detection_scheme(mem_bkdr_util_pkg::EccInv_39_32));
`MEM_BKDR_UTIL_FILE_OP(m_mem_bkdr_util[OtbnDmem0], `OTBN_DMEM_HIER)
mem = mem.first();
do begin
if (mem inside {[RamMain1:RamMain15]} ||
mem inside {[RamRet1:RamRet15]} ||
mem inside {[OtbnDmem1:OtbnDmem15]}) begin
mem = mem.next();
continue;
end
uvm_config_db#(mem_bkdr_util)::set(
null, "*.env", m_mem_bkdr_util[mem].get_name(), m_mem_bkdr_util[mem]);
mem = mem.next();
end while (mem != mem.first());
end
end : gen_generic
// Kill "strong" assertion properties in these scopes at the end of simulation.
//
// At the end of the simulation, these assertions start (i.e. the antecedent is true) but before
// the consequent property is satisfied (which happens a few clocks later), the simulation ends
// via $finish, causing the simulation to report a failure. It is safe to kill these assertions
// because they have already succeeded several times during the course of the simulation.
// TODO: Find a more robust way to turn off these assertions at the end of simulation.
//
// This does not apply to VCS. Here'e the relevant note from VCS documentation that explains
// why:
// In VCS, strong and weak properties are not distinguished in terms of their reporting at the end
// of simulation. In all cases, if a property evaluation attempt did not complete evaluation, it
// is reported as unfinished evaluation attempt, and allows you to decide whether it is a failure
// or a success.
`ifndef VCS
final begin
$assertkill(0, prim_reg_cdc);
$assertkill(0, sha3pad);
end
`endif
initial begin
fork
// See chip_padctrl_attributes_vseq for more details.
forever @dut.chip_if.chip_padctrl_attributes_test_sva_disable begin
if (dut.chip_if.chip_padctrl_attributes_test_sva_disable) begin
$assertoff(0, dut.top_earlgrey.u_flash_ctrl);
$assertoff(0, dut.top_earlgrey.u_gpio);
$assertoff(0, dut.top_earlgrey.u_i2c0);
$assertoff(0, dut.top_earlgrey.u_i2c1);
$assertoff(0, dut.top_earlgrey.u_i2c2);
$assertoff(0, dut.top_earlgrey.u_pinmux_aon);
$assertoff(0, dut.top_earlgrey.u_spi_device);
$assertoff(0, dut.top_earlgrey.u_spi_host0);
$assertoff(0, dut.top_earlgrey.u_spi_host1);
$assertoff(0, dut.top_earlgrey.u_sysrst_ctrl_aon);
$assertoff(0, dut.top_earlgrey.u_uart0);
$assertoff(0, dut.top_earlgrey.u_uart1);
$assertoff(0, dut.top_earlgrey.u_uart2);
$assertoff(0, dut.top_earlgrey.u_uart3);
$assertoff(0, dut.top_earlgrey.u_usbdev);
end else begin
$asserton(0, dut.top_earlgrey.u_flash_ctrl);
$asserton(0, dut.top_earlgrey.u_gpio);
$asserton(0, dut.top_earlgrey.u_i2c0);
$asserton(0, dut.top_earlgrey.u_i2c1);
$asserton(0, dut.top_earlgrey.u_i2c2);
$asserton(0, dut.top_earlgrey.u_pinmux_aon);
$asserton(0, dut.top_earlgrey.u_spi_device);
$asserton(0, dut.top_earlgrey.u_spi_host0);
$asserton(0, dut.top_earlgrey.u_spi_host1);
$asserton(0, dut.top_earlgrey.u_sysrst_ctrl_aon);
$asserton(0, dut.top_earlgrey.u_uart0);
$asserton(0, dut.top_earlgrey.u_uart1);
$asserton(0, dut.top_earlgrey.u_uart2);
$asserton(0, dut.top_earlgrey.u_uart3);
$asserton(0, dut.top_earlgrey.u_usbdev);
end
end
// See chip_sw_sleep_pin_mio_dio_val_vseq for more details.
forever @dut.chip_if.chip_sw_sleep_pin_mio_dio_val_sva_disable begin
if (dut.chip_if.chip_sw_sleep_pin_mio_dio_val_sva_disable) begin
$assertoff(0, dut.top_earlgrey.u_spi_device);
end else begin
$asserton(0, dut.top_earlgrey.u_spi_device);
end
end
join
end
// Control assertions in the DUT with UVM resource string "dut_assert_en".
`DV_ASSERT_CTRL("dut_assert_en", tb.dut)
// XBAR mode.
//
// XBAR mode uses a different UVM environment than the full chip. It requires the POR to be driven
// using a clk_rst_if instance. The `xbar_mode` plusarg is used to switch between the two
// environments. It is declared as type `logic` so that a wait statement can be used in other
// initial blocks to wait for its value to stabilize after a plusarg lookup.
logic xbar_mode;
initial begin
if (!$value$plusargs("xbar_mode=%0b", xbar_mode)) xbar_mode = 0;
clk_rst_if.set_active(.drive_clk_val(1 /* bogus clock */), .drive_rst_n_val(xbar_mode));
uvm_config_db#(virtual clk_rst_if)::set(null, "*.env*", "clk_rst_vif", clk_rst_if);
end
assign dut.POR_N = xbar_mode ? rst_n : 1'bz;
assign rst_n = xbar_mode ? 1'bz : dut.chip_if.dios[top_earlgrey_pkg::DioPadPorN];
`include "../autogen/tb__xbar_connect.sv"
`include "../autogen/tb__alert_handler_connect.sv"
endmodule