Part 10 · Advanced Topics · Intermediate
build_phase Parsing Discipline: Timing, Ownership, and Safety
Ensuring CLI values are parsed early, propagated correctly, and consumed deterministically across UVM phases.
Why build_phase is the right parsing window
Most runtime knobs affect component construction and configuration. Therefore parsing should happen before or during build-phase, not deep in run-phase after behavior has already diverged.
Late parsing creates split-brain configuration: some components use defaults from build_phase while others consume CLI values later, producing inconsistent and hard-to-replay behavior.
Legend: [UVM] [ADV]
[UVM] phase ordering relevant to CLI knobs
start_of_simulation
▲
build_phase <- parse + validate + publish config
connect_phase <- consume wiring knobs if needed
end_of_elaboration
run_phase <- use resolved values only (no primary parsing)Primary parsing belongs in a deterministic early lifecycle point.
Run-phase should consume final values, not decide them.
Treat parse location as architecture, not convenience.
Centralized parsing ownership model
Assign one component (usually test or env root) as parsing owner. That owner parses once, validates once, and publishes typed config to all consumers.
class base_test extends uvm_test;
`uvm_component_utils(base_test)
cli_cfg cfg;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
cfg = cli_cfg::type_id::create("cfg");
parse_cli(cfg);
validate_cfg(cfg);
log_cfg(cfg);
// Publish to env descendants
uvm_config_db#(cli_cfg)::set(this, "env*", "cli_cfg", cfg);
endfunction
endclass[ADV] ownership matrix
Responsibility Preferred owner
--------------------------------------------------------
parse raw command line test/env root
validate ranges/enums test/env root utility
publish typed config config_db at root scope
consume operational values env/agent/components
log resolved configuration root + optional local echoAvoid parsing inside many leaf components.
Use typed config objects instead of many scalar config_db keys when possible.
Keep parser and validator reusable across tests.
Consumption patterns and defensive checks
Consumers should assume config might be missing if ownership contracts are violated, and fail with actionable diagnostics rather than continuing silently.
class traffic_agent extends uvm_agent;
`uvm_component_utils(traffic_agent)
cli_cfg cfg;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(cli_cfg)::get(this, "", "cli_cfg", cfg))
`uvm_fatal("CFG", "cli_cfg not found; parsing owner not configured?")
`uvm_info("CFG", $sformatf(
"agent sees NUM_TXN=%0d BURST_MAX=%0d MODE=%s",
cfg.num_txn, cfg.burst_max, cfg.traffic_mode), UVM_LOW)
endfunction
endclass[UVM] defensive consumption checklist
[ ] get() return value checked
[ ] fatal on missing critical configuration
[ ] local echo logging for high-impact knobs
[ ] no fallback to hidden defaults without warning
[ ] build-phase only, not deferred to run-phaseFail fast for missing mandatory config objects.
Allow defaults only for explicitly optional knobs.
Echo resolved values near the point of use for easier triage.
Late-parse failure modes and recovery
If a project already parses late, migrate incrementally: introduce early parsing while preserving old hooks behind warnings, then remove late hooks once consumers are converted.
[ADV] common late-parse failure modes
Failure mode Observable symptom
--------------------------------------------------------------------------
mixed defaults and CLI values inconsistent behavior across components
replay mismatch same command does not reproduce result
phase-order race intermittent config visibility
hidden override in run_phase hard-to-explain seed-dependent drift[UVM] phased recovery plan
Step 1: add root build-phase parser + logger
Step 2: publish typed config object in config_db
Step 3: migrate one consumer at a time to typed get()
Step 4: warn on legacy late parsing path
Step 5: remove legacy path after two stable release cyclesKey takeaways
Parse CLI in build-phase under a single owner for determinism.
Publish typed configuration and require explicit consumer checks.
Late parsing creates replay and consistency failures; retire it gradually with warnings.
Configuration lifecycle discipline is as important as parser syntax.
Common pitfalls
Parsing custom args independently in multiple components.
Allowing run-phase parsing to mutate behavior after build decisions.
Using silent defaults for missing critical command-line configuration.