Part 2 · Phases & Lifecycle · Intermediate
Structural Sanity: Invariants Before Time 0
Assertion patterns for agent counts, mandatory connections, config presence, and passive/active consistency at elaboration.
What to assert at elaboration
Structural sanity checks catch integration mistakes before run_phase spends simulation time. Focus on existence, counts, and cfg consistency — not protocol behavior.
[PHASE][UVM] structural invariant categories
EXISTENCE: required components built (mon, sb, v_sqr)
COUNT: cfg.num_agents == built agents
MODE: active/passive consistent with handles
CONFIG: mandatory cfg/vif fields non-null
MAPPING: v_sqr sub-sequencer handles set for active agentsfunction void assert_structural_sanity();
if (cfg == null)
`uvm_fatal("SANITY", "cfg null at elaboration")
if (vif == null)
`uvm_fatal("SANITY", "vif null at elaboration")
if (cfg.is_active == UVM_ACTIVE && sqr == null)
`uvm_fatal("SANITY", "active agent without sequencer")
endfunction
function void end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
assert_structural_sanity();
endfunctionKey takeaways
Assert structure, not protocol — protocol checks belong in run_phase.
Fatal early on null cfg/vif — cheapest failures to diagnose.
Keep sanity functions reusable across agent variants.
Common pitfalls
Asserting transaction content at elaboration — no transactions yet.
Same fatal message for different failures — ambiguous triage.
Sanity only in test — agent problems found too late.
Sanity library patterns
Centralize common checks in env base classes and agent base classes for consistent regression behavior.
Reusable sanity package
class uvm_structural_sanity;
static function void check_agent(uvm_agent agt, uvm_active_passive_e expected);
if (agt == null) `uvm_fatal("SANITY", "agent null")
// delegate to agent-specific checks via virtual method
agt.check_elaboration_state(expected);
endfunction
endclass[PHASE] sanity ownership
agent.check_elaboration_state:
mon/drv/sqr vs active mode
env.check_elaboration_state:
agent array vs cfg bitmap
sb/cov optional presence
test.check_elaboration_state:
topology print
global override auditSeverity policy
Fatal: null mandatory handle, active agent missing driver.
Error: count mismatch, unexpected optional component.
Warning: passive agent with unexpected drv (legacy code path).
virtual function void check_elaboration_state(uvm_active_passive_e expected);
if (cfg.is_active != expected)
`uvm_warning("SANITY",
$sformatf("%s: cfg mode %s != expected %s",
get_full_name(), cfg.is_active.name(), expected.name()))
endfunction[PHASE][UVM] sanity → debug correlation
SANITY fatal "vif null"
→ build_phase config_db get failure
→ check top module set and agent get path
SANITY fatal "active without sqr"
→ build conditional branch bug
→ check cfg.is_active at build vs elaborationCommon pitfalls
Over-asserting VIP internals — breaks reuse across projects.
Sanity that depends on run_phase state — wrong phase.
No severity policy — all warnings ignored in CI.