Part 2 · Phases & Lifecycle · Intermediate
TLM Port Binding: Driver, Sequencer, and Export Chains
Canonical port.connect patterns — seq_item_port/export, hierarchical exports, and imp binding rules.
The driver-sequencer link
The driver's seq_item_port connects to the sequencer's seq_item_export so the driver can pull sequence items via get_next_item()/item_done().
class my_agent extends uvm_agent;
my_driver drv;
my_sequencer sqr;
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
if (cfg.is_active == UVM_ACTIVE) begin
if (drv == null || sqr == null)
`uvm_fatal("CONNECT", "active agent missing drv/sqr")
drv.seq_item_port.connect(sqr.seq_item_export);
end
endfunction
endclass[PHASE][UVM] seq_item binding chain
sequencer driver
seq_item_export ◄────── seq_item_port
▲
│ get_next_item() / item_done()
│
sequence running on sequencer
connect_phase establishes this link onceKey takeaways
seq_item_port connects to seq_item_export — not port-to-port directly.
Only active agents need driver-sequencer binding.
Defensive null checks turn cryptic failures into clear fatals.
Common pitfalls
Connecting seq_item_port to seq_item_port — wrong TLM pairing.
Connecting before super.connect_phase.
Re-connecting same port in multiple phases — double-bind error.
Export and imp hierarchies
Higher-level components expose exports that forward to child imps — common in layered agents and env wrappers.
Port → export → imp chain
// child driver has seq_item_port
// child sequencer has seq_item_export
// agent may expose a hierarchical export (optional pattern)
class my_agent extends uvm_agent;
uvm_seq_item_pull_port#(my_item) seq_item_port;
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
if (cfg.is_active == UVM_ACTIVE)
drv.seq_item_port.connect(sqr.seq_item_export);
// expose upward for env-level sequences (optional):
seq_item_port.connect(sqr.seq_item_export);
endfunction
endclass[PHASE][UVM] TLM pairing cheat sheet
seq_item_port → seq_item_export
analysis_port → analysis_export → analysis_imp
get_port → get_export → get_imp
put_port → put_export → put_imp
Never: port → port (without export/imp)Multi-agent env binding
class my_env extends uvm_env;
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
foreach (agents[i]) begin
if (agents[i].cfg.is_active == UVM_ACTIVE)
agents[i].drv.seq_item_port.connect(agents[i].sqr.seq_item_export);
end
endfunction
endclassPrefer agent-internal drv-sqr connect — env stays thin.
Env-level connect is for cross-agent analysis and v_sqr mapping.
Loop connects must guard null for passive or disabled agents.
[PHASE] binding ownership
agent owns: drv ↔ sqr internal link
env owns: mon.ap fanout, v_sqr map, cross-agent taps
test owns: rare top-level taps onlyCommon pitfalls
Env rewiring agent internals — breaks agent reuse as VIP.
Export bind without child imp — incomplete chain.
Parameterized port types mismatched at connect — compile error.