Part 6 · Agents & Protocol IP · Intermediate
Analysis Port Fanout: Scalable Observation Architecture
Design one-to-many fanout from the agent analysis port, with ingestion discipline, clone policy, and optional consumer gating.
Why fanout is default
One monitor stream should feed all passive consumers: scoreboard, coverage, predictors, debug traces. This minimizes coupling and keeps monitor focused on protocol reconstruction.
[UVM][AGT][CHECK] fanout graph
agent.ap
├─► scoreboard.actual_in
├─► coverage.analysis_export
├─► predictor.analysis_export
└─► trace.analysis_export[AGT] scaling property
add/remove consumers:
env connect changes only
monitor implementation:
unchangedDesign wrappers with fanout in mind from day one.
Keep monitor output type stable for downstream compatibility.
Avoid hardcoding consumer-specific logic in monitor.
Subscriber ingestion discipline
Fanout works at scale when consumers keep write() lightweight and queue work for later processing.
class usb_cov_sub extends uvm_subscriber #(usb_item);
`uvm_component_utils(usb_cov_sub)
usb_item q[$];
int unsigned seen;
function void write(usb_item t);
if (t == null) return;
q.push_back(t.clone());
seen++;
endfunction
task run_phase(uvm_phase phase);
forever begin
wait (q.size() > 0);
sample_cov(q.pop_front());
end
endtask
endclass[CHECK] fast write pattern
write():
validate -> clone -> queue -> return
run_phase:
heavy compare/sample/reportClone before mutation to avoid cross-consumer side effects.
Track per-consumer counters for health checks.
Throttle optional debug subscribers when performance matters.
Environment fanout wiring pattern
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
usb_agt.ap.connect(sb.actual_in);
usb_agt.ap.connect(cov.analysis_export);
usb_agt.ap.connect(pred.analysis_export);
if (cfg.enable_trace)
usb_agt.ap.connect(trace.analysis_export);
endfunction[UVM][AGT] optional consumer gating
always-on:
scoreboard, coverage
feature-gated:
trace, verbose protocol logs, advanced metricsKey takeaways
Agent analysis fanout is the scalable default observability architecture.
Consumer write paths should ingest quickly and avoid heavy inline work.
Clone policy and counters make fanout behavior deterministic and debuggable.
Environment-owned consumer wiring preserves monitor neutrality.
Common pitfalls
Coupling monitor to specific scoreboard/coverage implementation details.
Mutating shared transaction objects without clone discipline.
No counters, making fanout breaks hard to localize.
Treating analysis fanout as a command channel with backpressure expectations.