Part 2 · Phases & Lifecycle · Intermediate

Why connect_phase Is Bottom-Up

The ordering guarantee behind bottom-up connect: child ports first, parent assembly second, and safe fanout wiring.

Child ports must exist first

A parent connects to child ports. Bottom-up connect ensures every leaf port, export, and imp is initialized before the parent reaches into the subtree.

diagram
[PHASE][UVM] bottom-up traversal

Step 1:   drv.connect_phase()   (leaf — local ports ready)
Step 2:   mon.connect_phase()
Step 3:   sqr.connect_phase()
Step 4: agent.connect_phase()   (wires drv ↔ sqr)
Step 5:     sb.connect_phase()  (leaf imp ready)
Step 6:   env.connect_phase()   (wires mon.ap  sb, cov)
Step 7: test.connect_phase()    (optional top-level wiring)

Rule: child N must finish connect before parent N-1 starts
systemverilog
class my_agent extends uvm_agent;
  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);
  endfunction
endclass

Key takeaways

  • Bottom-up connect mirrors the dependency direction of TLM binding.

  • Leaf components expose ports; parents stitch subgraphs together.

  • Agent connect runs before env connect so agent-internal links are done.

Common pitfalls

  • Env connect assuming agent-internal drv-sqr link not yet made.

  • Parent connect running custom child connect out of order.

  • Expecting sibling connect order among agents — not guaranteed.


Bottom-up enables safe fanout

Analysis fanout from monitor to multiple subscribers requires each imp to exist before the env connects the broadcast port.

Fanout wiring order

systemverilog
class my_env extends uvm_env;
  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    // agt.mon.ap exists (agent built + agent connect done)
    agt.mon.ap.connect(sb.act_imp);
    agt.mon.ap.connect(cov.analysis_export);
    agt.mon.ap.connect(tlm_fifo.analysis_export);
  endfunction
endclass
diagram
[PHASE][UVM] analysis broadcast model

monitor.ap.write(txn)
    ├─► scoreboard.imp
    ├─► coverage.imp
    └─► tlm_fifo.imp

Each imp must exist before ap.connect(imp)
Bottom-up connect guarantees imp components initialized

Virtual sequencer mapping timing

  • Virtual sequencer is a component — its build_phase creates it.

  • Env connect_phase assigns agt.sqr handles to v_sqr fields.

  • This is handle assignment, not port.connect().

systemverilog
function void connect_phase(uvm_phase phase);
  super.connect_phase(phase);
  v_sqr.tx_sqr = agt_tx.sqr;
  v_sqr.rx_sqr = agt_rx.sqr;
endfunction
diagram
[PHASE] bottom-up + virtual sequencer

1) agt_tx.sqr exists (build)
2) agt_tx.connect wires drv-sqr (bottom-up leaf first)
3) env.connect assigns v_sqr.tx_sqr = agt_tx.sqr
4) virtual sequences can start on v_sqr.tx_sqr in run_phase

Common pitfalls

  • Assigning null sequencer handle — active/passive mismatch in build.

  • Connecting analysis before subscriber imp is built.

  • Mapping v_sqr in build_phase — sequencers may not exist yet.