Part 7 · Environment & Tests · Intermediate
Env Composition Debug: Symptom-First Integration Triage
Debugging environment composition failures using ordered boundary checks from build, connect, activity policy, and checker ingestion.
Triage order
Debug composition in fixed order: creation, configuration, connectivity, activity policy, then checker ingestion. Ordered triage avoids random fixes.
[ENV][UVM][CHECK] triage matrix
symptom: null handle fatal
-> missing create or bad factory override
symptom: monitor logs but no scoreboard hits
-> connect graph missing
symptom: vseq starts but no drive
-> sequencer handle or active policy issue
symptom: intermittent checker mismatch
-> race/ordering or mutable transaction bugtask env_composition_smoke(env_top env_h);
if (env_h == null) `uvm_fatal("SMOKE", "env null")
if (env_h.sb == null) `uvm_fatal("SMOKE", "scoreboard null")
if (env_h.v_sqr == null) `uvm_fatal("SMOKE", "virtual sqr null")
if (env_h.ap_link_count == 0) `uvm_fatal("SMOKE", "no analysis links")
`uvm_info("SMOKE", "env composition baseline passed", UVM_LOW)
endtaskKey takeaways
Ordered boundary checks localize failures quickly.
Most composition failures are wiring or policy mismatches, not DUT bugs.
One smoke test should gate all larger regressions.
Common pitfalls
Jumping straight to waveform debug without topology validation.
Treating intermittent failures as randomness instead of policy drift.
Skipping negative tests for missing config and missing links.
Applied Patterns
Build a deterministic debug packet that every failing seed prints so failures can be compared side by side.
[ENV] debug packet
required fields:
test name
seed
active/passive matrix
created component count
analysis link count
scoreboard ingest counters
coverage sample counters
first error timestamp
goal:
reduce each failure to one broken boundaryfunction void print_debug_packet();
`uvm_info("ENV_PKT",
$sformatf("seed=%0d created=%0d links=%0d sb_hits=%0d cov_hits=%0d",
$get_initial_random_seed(), created_cnt, ap_link_count, sb_hits, cov_hits),
UVM_LOW)
endfunctionStandard debug packets make cross-seed comparison practical.
Counters should be cheap enough to leave enabled by default.
Escalate only after baseline packet fields are validated.
Integration Drilldown
Use a compact fail-injection suite that breaks one boundary at a time and validates error messages.
[CHECK] fail-injection suite
inject A: remove one ap.connect
inject B: force passive on driving agent
inject C: drop env cfg object
inject D: disable scoreboard subscriber
expected:
each injection maps to one explicit fatalKey takeaways
Fail-injection keeps diagnostics honest as the env evolves.
Common pitfalls
Allowing vague fatals that require deep wave spelunking.