Part 4 · TLM & Analysis · Intermediate
Unconnected Port Detection: UVM_WARNING Patterns and print_connections()
How to detect and diagnose missing TLM links with UVM warnings, topology printouts, and endpoint-local assertions.
What unconnected means in practice
A TLM connection is valid only when producer and consumer endpoints are connected through matching port/export/imp topology before run-time traffic starts.
When this is broken, UVM may emit a UVM_WARNING for some endpoint classes, but not all cases are fatal. The safest approach is to enforce explicit connection checks.
[UVM][TLM] canonical point-to-point chain
producer.put_port --> parent.put_export --> consumer.put_imp
[TLM] initiator [TLM] bridge [TLM] target
if any arrow is missing:
- calls may block forever (blocking put/get)
- item may never reach sink
- warnings may be non-fatal[MON][TLM][SB] analysis broadcast chain
monitor.ap.write(txn)
│
├─> scoreboard.analysis_export
└─> coverage.analysis_export
if no subscribers:
write(txn) returns immediately, data is dropped silentlyUnconnected blocking ports can hang threads; unconnected analysis ports can silently drop data.
Connection bugs are best found in connect_phase, not after random stimulus.
Detect absence of links explicitly with endpoint checks and audit logs.
Using print_connections() effectively
Most TLM endpoint classes provide diagnostics that summarize current fanout/fanin. Use these right after connect_phase to confirm expected topology.
class my_env extends uvm_env;
`uvm_component_utils(my_env)
my_monitor mon;
my_scoreboard sb;
my_cov cov;
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
mon.ap.connect(sb.analysis_export);
mon.ap.connect(cov.analysis_export);
endfunction
function void end_of_elaboration_phase(uvm_phase phase);
super.end_of_elaboration_phase(phase);
mon.ap.print_connections();
endfunction
endclass[UVM] expected connection audit (conceptual)
mon.ap:
fanout = 2
-> sb.analysis_export
-> cov.analysis_export
unexpected examples:
fanout = 0 // silent analysis drop risk
fanout = 1 // one consumer missing
wrong endpoint // connected to unintended componentfunction void verify_analysis_wiring();
int n = mon.ap.size(); // typical analysis_port fanout query
if (n == 0) begin
`uvm_fatal("TLM_CONN", "monitor.ap has zero subscribers")
end
`uvm_info("TLM_CONN", $sformatf("monitor.ap subscribers=%0d", n), UVM_LOW)
endfunctionRun connection dumps at end_of_elaboration for stable hierarchy names.
Use fail-fast checks for must-have links such as monitor->scoreboard.
Keep expected fanout counts documented and asserted.
Detecting direction and hierarchy mistakes
Another common failure is connecting incompatible endpoint roles (port-to-port, imp-to-imp) or skipping hierarchy pass-through exports.
[TLM] role compatibility quick guide
legal:
port -> export
export -> export
export -> imp
port -> imp (in some direct forms)
illegal / suspicious:
port -> port
imp -> imp
write() endpoint used for put/get path// BAD: forgot intermediate export hookup
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
// child_mon.ap should connect to parent export first.
// child_mon.ap.connect(parent_ap_export); // missing
parent_ap_export.connect(sb.analysis_export);
endfunction// GOOD: full chain is explicit and auditable
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
child_mon.ap.connect(parent_ap_export);
parent_ap_export.connect(sb.analysis_export);
endfunctionValidate full source-to-sink chain, including parent exports.
Check endpoint role compatibility when refactoring hierarchy.
Avoid hidden connect logic in utility methods without logging.
Pre-run connection gate
Treat connectivity as a regression gate: if required links are absent, fail before run_phase. This avoids wasting simulation on invalid topology.
function void start_of_simulation_phase(uvm_phase phase);
super.start_of_simulation_phase(phase);
audit_tlm_links();
endfunction
function void audit_tlm_links();
if (drv.seq_item_port.size() == 0)
`uvm_fatal("TLM_AUDIT", "driver.seq_item_port is unconnected")
if (mon.ap.size() == 0)
`uvm_fatal("TLM_AUDIT", "monitor.ap has no subscribers")
mon.ap.print_connections();
endfunction[UVM][TLM] gate checklist
required checks before run:
- sequencer <-> driver seq_item path connected
- monitor analysis fanout >= 1
- expected analysis sinks present by name
- no known warning IDs suppressed for connection errorsKey takeaways
Use print_connections and explicit fanout checks together.
Fail early for mandatory links; do not rely on warnings alone.
Direction/hierarchy mistakes are easier to catch with role-based audits.
Connection gating at start_of_simulation saves debug time.
Common pitfalls
Assuming connect_phase code is correct without post-connect verification.
Treating fanout > 0 as sufficient when specific sinks are required.
Suppressing connection warning IDs globally in regressions.
Allowing testbench to continue after known unconnected critical links.