Part 6 · Agents & Protocol IP · Intermediate
Multi-Interface Environments: Composing Heterogeneous Protocol Agents
Patterns for integrating APB, AXI, and streaming agents in one environment with consistent cfg ownership, analysis routing, and cross-protocol checking.
Composition objectives
Real chips combine control buses, memory fabrics, and streaming data paths. A multi-interface environment should preserve protocol-specific correctness while offering coherent top-level control.
Key goals are consistent cfg ownership, deterministic mode selection, and clear analysis routing into cross-protocol scoreboards.
[SOC][ENV] heterogeneous topology
soc_env
apb_ctrl_agent [VIP][AGT] (cfg/status)
axi_mem_agent [VIP][AGT] (bulk memory traffic)
stream_video_agent [VIP][AGT] (pixel/data stream)
xproto_scoreboard (cross-interface correlation)
coverage_hub (unified coverage subscribers)[ENV] ownership model
env owns:
cfg creation
vif binding
agent instantiation
connect_phase routing
tests own:
scenario-specific cfg overrides
sequence orchestration for active agentsKeep protocol engines isolated while standardizing env orchestration.
Use explicit ownership boundaries for cfg and mode control.
Design analysis topology for both per-protocol and cross-protocol checks.
Build/connect template
A repeatable build/connect template helps scale multi-interface environments and reduces integration mismatches.
class soc_env extends uvm_env;
`uvm_component_utils(soc_env)
apb_agent apb_agt;
axi_agent axi_agt;
stream_agent strm_agt;
apb_cfg apb_cfg_h;
axi_cfg axi_cfg_h;
stream_cfg strm_cfg_h;
xproto_scoreboard xsb;
function void build_phase(uvm_phase phase);
super.build_phase(phase);
apb_cfg_h = apb_cfg::type_id::create("apb_cfg_h");
axi_cfg_h = axi_cfg::type_id::create("axi_cfg_h");
strm_cfg_h = stream_cfg::type_id::create("strm_cfg_h");
apb_cfg_h.vif = apb_vif;
axi_cfg_h.vif = axi_vif;
strm_cfg_h.vif = strm_vif;
uvm_config_db#(apb_cfg)::set(this, "apb_agt", "cfg", apb_cfg_h);
uvm_config_db#(axi_cfg)::set(this, "axi_agt", "cfg", axi_cfg_h);
uvm_config_db#(stream_cfg)::set(this, "strm_agt", "cfg", strm_cfg_h);
apb_agt = apb_agent::type_id::create("apb_agt", this);
axi_agt = axi_agent::type_id::create("axi_agt", this);
strm_agt = stream_agent::type_id::create("strm_agt", this);
xsb = xproto_scoreboard::type_id::create("xsb", this);
endfunctionfunction void connect_phase(uvm_phase phase);
super.connect_phase(phase);
apb_agt.mon.ap.connect(xsb.apb_in);
axi_agt.mon.ap.connect(xsb.axi_in);
strm_agt.mon.ap.connect(xsb.stream_in);
endfunction[ENV] build/connect guardrails
1) validate all cfg/vif handles before create
2) keep one config_db set per agent path
3) centralize analysis wiring in connect_phase
4) emit startup summary for modes and bindingsTemplate-driven build/connect reduces heterogeneous integration risk.
Route monitor outputs to explicit scoreboard inputs per protocol.
Validate cfg and vif readiness before agent creation.
Cross-protocol checking patterns
Many SoC properties span protocols, such as APB config programming followed by AXI or stream behavior changes. Cross-protocol scoreboards should align these timelines.
[XPROTO] example check scenario
APB write:
cfg.frame_size = N
expectation:
subsequent stream packets respect size N
also:
AXI buffer traffic volume reflects configured mode[SCOREBOARD] correlation inputs
apb_in:
configuration timeline events
axi_in:
memory movement events
stream_in:
output payload events
correlator:
joins events by time window + channel context[VIP][SOC] cross-protocol pitfalls
pitfall:
comparing events without synchronization window
pitfall:
assuming instant config effect with pipeline latency
pitfall:
ignoring reset boundaries between protocol domainsModel expected cross-protocol latency windows explicitly.
Correlate with protocol-domain context and reset phase.
Separate per-protocol checks from cross-protocol causal checks.
Scalability and maintenance patterns
As interface count grows, adopt naming conventions, shared helper utilities, and generated connectivity maps to keep environment maintainable.
[ENV] scalability practices
- stable naming convention per protocol/instance
- cfg creation helpers per protocol family
- interface binding maps in one location
- auto-generated connection reports at startup
- per-interface health counters[DEBUG] multi-interface symptom map
symptom likely area
----------------------------------------------------------------
one protocol silent, others active vif binding or mode issue
cross-protocol checks flaky timing window mis-modeling
scoreboard overload/perf drop excessive transaction cloning/logging
inconsistent startup behavior non-deterministic cfg override order[RELEASE] maintenance checklist
1) update env docs when adding new interfaces
2) add smoke tests per new protocol instance
3) verify connection reports include new channels
4) review cross-protocol checks for new dependenciesKey takeaways
Multi-interface environments need standardized orchestration plus protocol specialization.
Explicit build/connect templates improve reliability at scale.
Cross-protocol checks should model causal timing and reset context.
Scalability depends on naming discipline and generated observability artifacts.
Common pitfalls
Manual per-instance wiring without consistency checks.
Cross-protocol assertions that ignore pipeline/latency realities.
Letting cfg override order vary across tests.
Under-documenting interface additions and breaking integration silently.