Part 7 · Environment & Tests · Intermediate
build_phase Plusarg Read: Parse Before Env Consumes cfg
Lifecycle timing for plusarg parsing so cfg is fully resolved before env and agent build_phase get paths run.
Parse window and ordering
Plusargs must be resolved in base_test::build_phase before env creation and before config_db consumers read cfg. Late parsing causes silent defaults or race-like mismatches.
[TEST][UVM][ENV] build_phase order (required)
1) super.build_phase(phase)
2) cfg = env_cfg::type_id::create()
3) cfg.apply_defaults()
4) configure_from_plusargs() <-- CLI resolved here
5) optional cfg.randomize()
6) uvm_config_db::set(this, "env*", "cfg", cfg)
7) env = my_env::type_id::create("env", this)
env.build_phase -> get cfg (already complete)function void build_phase(uvm_phase phase);
super.build_phase(phase);
cfg = env_cfg::type_id::create("cfg");
cfg.apply_defaults();
configure_from_plusargs();
if (!cfg.randomize())
`uvm_fatal("CFG", "cfg randomize failed")
uvm_config_db#(env_cfg)::set(this, "env*", "cfg", cfg);
log_resolved_cfg();
env = my_env::type_id::create("env", this);
endfunctionKey takeaways
Parsing after env creation is too late — components may read stale cfg.
apply_defaults() first, then plusargs override defaults explicitly.
Log cfg snapshot immediately after parse for triage.
Common pitfalls
Creating env before config_db set completes.
Parsing plusargs in run_phase when build_phase already consumed cfg.
Child test overriding build_phase without preserving parse order.
connect_phase and run_phase boundaries
After build_phase, treat cfg as immutable unless you have a documented late-override policy.
Immutability policy
[TEST] cfg lifecycle
build_phase: cfg writable (defaults + plusargs + randomize)
connect_phase: cfg read-only for env/agents
run_phase: scenario hooks only; no CLI re-parseIf a knob must change at run_phase, use a virtual hook — not new plusarg reads.
Env should copy cfg fields it needs in build_phase, not hold a mutable handle.
Document any exception paths (e.g., debug plusarg dump) explicitly.
Late-read anti-pattern
// BAD: agent reads plusarg directly in connect_phase
function void connect_phase(uvm_phase phase);
string s;
if ($value$plusargs("SEQ_COUNT=%d", cfg.seq_count)) ; // too late, wrong layer
endfunction// GOOD: agent uses cfg from config_db in build_phase
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(env_cfg)::get(this, "", "cfg", cfg))
`uvm_fatal("CFG", "missing env_cfg")
endfunctionCommon pitfalls
Agents calling $value$plusargs — breaks single-parser policy.
Mutable cfg handles shared without copy-on-build semantics.
Randomize after env creation — env sees pre-random values.