Part 2 · Phases & Lifecycle · Intermediate
build_phase Hub: Top-Down Construction and Configuration
Hub - top-down ordering rationale, factory create patterns, config_db gets, conditional construction, full walkthrough, and build-phase debug checklists.
Overview
build_phase is where the UVM component tree materializes . Every parent creates its children, every component reads its configuration, and factory overrides take effect — all before a single TLM port is connected.
The phase runs top-down so parents exist before children build, which is the only safe order for hierarchical construction and config distribution.
Sub-lessons in this topic
build-top-down-why - why parent-before-child ordering is non-negotiable.
factory-create-pattern - type_id::create() and override timing.
config-db-get-build - canonical get patterns and path discipline.
conditional-construction - active/passive and feature-gated builds.
build-phase-walkthrough - end-to-end build timeline on a real env.
build-phase-debug - symptom-first triage for construction failures.
[PHASE][UVM] build_phase position
uvm_root
└─ uvm_test_top (test)
└─ env
├─ agent[0]
│ ├─ driver
│ ├─ monitor
│ └─ sequencer
├─ scoreboard
└─ coverage
TRAVERSAL: top-down (parent build_phase before child)
TIME: zero (function phase)
JOBS: create children, get config, apply factory overridesfunction void build_phase(uvm_phase phase);
super.build_phase(phase); // always first
// 1) get config / vif from config_db
// 2) register factory overrides (tests, before super in child)
// 3) create children via type_id::create()
// NEVER: connect ports, drive pins, consume time
endfunctionKey takeaways
build_phase answers: what components exist and with what configuration?
Top-down traversal guarantees parents can create children safely.
Factory create and config_db gets are the two core build mechanisms.
Common pitfalls
Using new() instead of type_id::create() — overrides silently ignored.
Connecting TLM ports in build_phase — endpoints may not exist yet.
Registering factory overrides after super.build_phase — too late.
Build-phase contract
Treat build_phase as a strict contract: structure only, zero simulation time, no wiring.
Allowed vs forbidden
[PHASE][UVM] build_phase rules
ALLOWED:
super.build_phase(phase)
uvm_config_db::get / set (with care)
type_id::create() for children
factory set_type_override / set_inst_override
structural if/else from cfg
FORBIDDEN:
#delay, wait(), @(event)
port.connect() / export.bind()
sequence.start()
direct pin drive on vifEvery component override must call super.build_phase first.
Overrides registered before create() affect that create() call.
Gets must match the set path, instance name, and type exactly.
[PHASE] build → connect handoff
build_phase delivers:
- complete component tree
- resolved cfg objects
- factory-substituted types
connect_phase expects:
- all endpoints exist (non-null handles)
- no new components created
- topology stable for wiringCommon pitfalls
Lazy-creating components in run_phase — breaks connect and topology print.
Mixing config push and component create without documented order.
Skipping super.build_phase — field automation and callbacks missed.