Part 7 · Environment & Tests · Intermediate
Environment Composition Hub: Scaling Reusable Env Topologies
Hub - env wrapper role, multi-agent build strategy, connect-phase wiring, hierarchy scaling, passive/active mixes, and debug workflow for integrated environments.
Overview
A reusable uvm_env composes agents, checkers, and infrastructure so tests can focus on scenario intent. Composition quality controls bring-up speed, debug cost, and regression stability.
Think in layers: protocol islands become agent wrappers , wrappers become sub-envs , and sub-envs become top-level environments.
Sub-lessons in this topic
env-wrapper-role - defining wrapper ownership and composition boundaries.
multi-agent-build - deterministic build patterns for many agent instances.
connect-phase-wiring - legal connect_phase graph and fan-out discipline.
env-hierarchy-scaling - naming, configuration, and hierarchy growth patterns.
passive-active-mix - per-instance activity policy in one shared environment.
env-composition-debug - symptom-first triage for composition failures.
[ENV][UVM][CHECK] composition map
test
|
+-- env_top
+-- ctrl_agt (active)
+-- data_agt[] (active/passive by role)
+-- mon_only_agt (passive)
+-- sb
+-- cov
+-- v_sqr
build_phase:
create wrappers/components
connect_phase:
wire analysis graph + seq ports
run_phase:
tests run vseq policy
env is plumbing, test is policyclass env_top extends uvm_env;
`uvm_component_utils(env_top)
ctrl_agent ctrl_agt;
data_agent data_agts[int];
env_scoreboard sb;
env_coverage cov;
virtual_sqr v_sqr;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
ctrl_agt = ctrl_agent::type_id::create("ctrl_agt", this);
sb = env_scoreboard::type_id::create("sb", this);
cov = env_coverage::type_id::create("cov", this);
v_sqr = virtual_sqr::type_id::create("v_sqr", this);
endfunction
endclassKey takeaways
Composition quality determines whether tests remain lightweight and readable.
Stable build/connect contracts are required for scalable testbench reuse.
Debuggability improves when env boundaries are explicit and consistent.
Common pitfalls
Embedding scenario choices directly in env build logic.
Mixing connect and build responsibilities in ad-hoc ways.
Allowing unnamed hierarchy growth without clear ownership.
Applied Patterns
Use a fixed composition playbook so every new sub-env follows the same ownership, wiring, and debug contracts.
[ENV][UVM][CHECK] env composition checklist
ownership:
env owns components
test owns scenario policy
build discipline:
type_id::create for all leaf components
config pulls centralized in build
connect discipline:
all analysis fanout in connect_phase
all seqr/driver hookups in connect_phase
observability:
counters in scoreboards/subscribers
report_phase health summary
scaling:
indexed instance naming conventions
per-instance config objectsfunction void report_phase(uvm_phase phase);
`uvm_info("ENV_HEALTH",
$sformatf("agents=%0d ap_links=%0d active=%0d passive=%0d",
agent_count, ap_link_count, active_count, passive_count),
UVM_LOW)
endfunctionTreat composition changes as API changes that affect all tests.
Keep hierarchy naming deterministic for debug and factory overrides.
Record active/passive policy per instance in one visible place.
Integration Drilldown
Before promoting a new env branch, run one minimal vseq plus one stress vseq to validate that every component is created, connected, and observable.
[ENV] pre-merge drills
1) smoke: single transaction path
2) dual-agent overlap traffic
3) passive monitor-only mode
4) random reset insertion
5) report_phase counter audit
pass criteria:
no null handles
no missing writes
no orphan subscribersKey takeaways
A repeatable drilldown prevents hidden connect regressions.
Counter-based health checks catch silent composition failures early.
Common pitfalls
Declaring integration done before passive mode is validated.
Skipping report_phase checks because waves look plausible.