Part 6 · Agents & Protocol IP · Intermediate
cfg Active/Passive Switch: Runtime Policy Through Configuration
Reliable switch mechanics using cfg objects, config_db injection, and validation hooks to keep mode transitions deterministic across tests.
Switch design principles
The active/passive switch should be deterministic per test run. Choose mode in build configuration, not ad hoc during run_phase, so topology and ownership stay stable.
Expose switch policy through cfg fields, then validate resolved outcomes before simulation traffic begins.
[UVM][AGT] deterministic switch model
input knobs:
cfg.is_active
env-level defaults
test-level overrides
decision point:
agent build_phase
output:
fixed component topology for entire run[VIP] switch policy table
test type suggested mode
------------------------------------------------------------
protocol directed stimulus ACTIVE
software boot observability PASSIVE
mixed emulation bring-up mostly PASSIVE
single-interface fault isolation ACTIVE for target, PASSIVE for observersResolve mode once before topology is built.
Keep switch inputs explicit and reviewable.
Avoid dynamic mode mutation inside running phases.
Configuration plumbing patterns
A common approach is env-owned cfg creation plus test-owned policy updates. This keeps object lifetimes clear and minimizes config_db string fragility.
class chip_env extends uvm_env;
`uvm_component_utils(chip_env)
apb_agent_cfg apb_cfg;
apb_agent apb_agt;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
apb_cfg = apb_agent_cfg::type_id::create("apb_cfg");
apb_cfg.is_active = UVM_ACTIVE; // env default
apb_cfg.vif = apb_vif;
uvm_config_db#(apb_agent_cfg)::set(this, "apb_agt", "cfg", apb_cfg);
apb_agt = apb_agent::type_id::create("apb_agt", this);
endfunction
endclassclass fw_boot_test extends uvm_test;
`uvm_component_utils(fw_boot_test)
chip_env env;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
env = chip_env::type_id::create("env", this);
// Switch APB agent to monitor-only in this scenario
env.apb_cfg.is_active = UVM_PASSIVE;
endfunction
endclass[AGT] plumbing do/don't
do:
pass cfg object through config_db once
mutate cfg field in tests for scenario policy
keep mode close to related knobs
don't:
duplicate mode in both cfg and raw config_db key
mix enum and integer representations
apply late overrides after agent buildOne cfg object per agent instance keeps policy coherent.
Test-level switch should modify cfg before child builds occur.
Avoid dual-source mode knobs that can diverge.
Validation gates and policy assertions
Add reusable validation helpers to enforce legal mode combinations. This turns integration mistakes into immediate build failures.
function void validate_agent_modes();
if (cpu_apb_cfg.is_active == UVM_PASSIVE && requires_tb_boot_sequence)
`uvm_fatal("MODE", "cpu_apb must be ACTIVE for tb boot sequence")
if (dma_axi_cfg.is_active == UVM_ACTIVE && firmware_also_drives_dma)
`uvm_fatal("MODE", "dma_axi cannot be ACTIVE when firmware owns DMA traffic")
endfunction[SOC] policy validation examples
rule A:
control plane bus active in directed register tests
rule B:
DUT-master interfaces remain passive during firmware tests
rule C:
no interface has more than one active driver owner
rule D:
critical monitors always instantiated regardless of mode[VIP][AGT] pre-run mode report
agent instance resolved mode owner
--------------------------------------------------------
cpu_apb_agent ACTIVE testbench
dma_axi_agent PASSIVE firmware/DUT
pcie_rc_agent ACTIVE testbench
noc_stream_agent[0..3] PASSIVE DUT fabric
print this table every run for reproducibilityConvert mode assumptions into explicit validation checks.
Emit a mode report table before run_phase starts.
Fail fast on ownership conflicts instead of warning.
Switch-related debugging patterns
Most switch bugs are precedence bugs. Investigate where final mode was set last, then verify that component creation matched that resolved value.
[UVM] precedence debug trail
1) cfg constructor default
2) env-level assignment
3) test-level assignment
4) config_db set/get path
5) agent build log
6) topology print
first unexpected value identifies culprit layer[AGT] signature failures
symptom likely root cause
----------------------------------------------------------------
agent logs ACTIVE but no driver exists stale cfg pointer / wrong instance path
agent logs PASSIVE unexpectedly broad wildcard override
topology mismatch with logs multiple cfg objects for one instance
mode differs across reruns non-deterministic late assignment`uvm_info("MODE_TRACE",
$sformatf("instance=%s cfg=%p mode=%s",
get_full_name(), cfg, cfg.is_active.name()),
UVM_MEDIUM)Key takeaways
Active/passive switching should be build-time deterministic and policy-driven.
Cfg-object plumbing with early overrides yields stable, auditable behavior.
Validation gates catch illegal ownership combinations before stimulus runs.
Precedence tracing resolves most switch bugs quickly.
Common pitfalls
Late mode mutation after build causing topology/config disagreement.
Overlapping wildcard config_db rules with unclear specificity.
Maintaining separate mode copies in multiple objects.
Treating ownership conflicts as warnings instead of hard failures.