Part 4 · TLM & Analysis · Intermediate

Environment Connection Patterns: Practical Port/Export/Imp Wiring

Common environment-level wiring blueprints for point-to-point paths, analysis fan-out, and layered hierarchy composition.

Pattern 1: canonical point-to-point agent path

A common pattern is sequence/producer side calling through a port, optional agent export as public boundary, and driver/consumer imp as terminal endpoint.

diagram
[UVM][TLM] point-to-point template

producer.port
   -> agent.req_export
   -> driver.req_imp

Characteristics:
  single provider chain
  deterministic flow control
  clear ownership boundaries
systemverilog
class my_agent extends uvm_agent;
  `uvm_component_utils(my_agent)
  my_driver drv;
  my_producer prod;
  uvm_blocking_put_export #(req_t) req_export;

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    drv = my_driver::type_id::create("drv", this);
    prod = my_producer::type_id::create("prod", this);
    req_export = new("req_export", this);
  endfunction

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    prod.req_port.connect(req_export);
    req_export.connect(drv.req_imp);
  endfunction
endclass
  • Keep each point-to-point path visually traceable from caller to terminal imp.

  • Use exports at agent boundaries to avoid exposing private child handles.

  • Add one smoke sequence that exercises each bound path during bring-up.


Pattern 2: monitor analysis fan-out

Analysis paths are the canonical one-to-many pattern. A monitor publishes once and many subscribers consume independently.

diagram
[MON][UVM][TLM] analysis fan-out

monitor.analysis_port
   -> env.analysis_export
   -> scoreboard.analysis_imp
   -> coverage_sub.analysis_imp
   -> logger_sub.analysis_imp

One write(), multiple observers, no backpressure.
systemverilog
function void env::connect_phase(uvm_phase phase);
  super.connect_phase(phase);

  mon.ap.connect(ap_export);
  ap_export.connect(sb.analysis_imp);
  ap_export.connect(cov.analysis_imp);
  ap_export.connect(log.analysis_imp);
endfunction
diagram
[TLM] fan-out design reminders

- analysis subscribers should be side-effect isolated
- no subscriber should assume it is sole consumer
- ordering among subscribers should not affect correctness
- use tags/time for cross-subscriber correlation
  • Use analysis for observation networks; avoid forcing put/get fan-out.

  • Subscribers should tolerate independent activation and ordering variations.

  • Keep monitor payload rich enough for scoreboard and coverage needs together.


Pattern 3: layered env -> subsystem -> agent wiring

Large SoC benches use layered composition. Each layer publishes minimal boundary endpoints and forwards downward in connect_phase. This keeps integration modular.

diagram
[UVM][TLM] layered hierarchy blueprint

top_env.req_export
   -> periph_ss.req_export
   -> uart_agent.req_export
   -> uart_driver.req_imp

top_env.obs_export
   <- periph_ss.obs_export
   <- uart_agent.mon_ap (analysis write source)
systemverilog
function void top_env::connect_phase(uvm_phase phase);
  super.connect_phase(phase);
  req_export.connect(periph_ss.req_export);
  periph_ss.obs_export.connect(obs_export);
endfunction

function void periph_ss::connect_phase(uvm_phase phase);
  super.connect_phase(phase);
  req_export.connect(uart_agt.req_export);
  uart_agt.mon_ap.connect(obs_export);
endfunction
diagram
[TLM] layered wiring rules

1) each layer exposes only needed public endpoints
2) each connection declared at ownership layer
3) no top-level direct bind to deep private children
4) diagram both command and observation paths
  • Layered endpoints prevent tight coupling between top env and deep agent internals.

  • Keep request and observation path naming separate to avoid role confusion.

  • Require subsystem-level topology review before large integration merges.


Pattern 4: debug-first wiring discipline

Connection bugs are cheaper to catch with topology probes than with full regression failures. Add minimal diagnostics that confirm each chain is alive before heavy stimulus.

diagram
[UVM][TLM] pre-regression checks

check A: all expected connect calls executed
check B: no unresolved endpoint warnings
check C: one deterministic transaction reaches terminal imp
check D: one monitor write reaches all intended subscribers
systemverilog
task env_smoke_seq::body();
  req_t r;
  r = req_t::type_id::create("r");
  r.id = 1;
  p_sequencer.req_port.put(r);
  // Expect terminal imp and scoreboard observation logs.
endtask
diagram
[TLM] maintainability checklist for env wiring

- endpoints named by role and payload domain
- connect_phase grouped by communication path
- hierarchy diagrams updated when topology changes
- one smoke test per major path (cmd, rsp, analysis)

Key takeaways

  • Use repeatable wiring templates to keep large environments understandable.

  • Point-to-point and analysis fan-out should use their natural TLM families.

  • Layered exports provide modular integration without exposing private internals.

  • Topology smoke tests catch miswires earlier than functional regressions.

Common pitfalls

  • Copy-paste connect blocks without updating endpoint families/types.

  • Deep direct binds that bypass published subsystem interfaces.

  • No early smoke path checks before long randomized runs.

  • Combining command and analysis paths under ambiguous endpoint names.