Part 6 · Agents & Protocol IP · Intermediate

config_db Wiring: Deterministic Set/Get Paths and Child Propagation

Build robust config_db flow with path hygiene, precedence policy, and guaranteed propagation from env to agent children.

Wiring model and invariants

Reliable config_db wiring follows two invariants: set-before-get and exact-path alignment with hierarchy. Most cfg bugs violate one.

diagram
[UVM][AGT][DRV][TLM] wiring timeline

env.build_phase:
  create cfg
  populate vif/mode/policy
  set cfg on agent instance path
  create agent instance

agent.build_phase:
  get cfg
  validate/normalize
  set cfg for monitor/driver children

child.build_phase:
  get cfg and enforce local requirements
diagram
[config_db] path hygiene checklist

exact path example:
  set(this, "env.bus_agt", "cfg", cfg)

relative child set example:
  set(this, "drv", "cfg", cfg)

anti-pattern:
  set(null, "*", "cfg", cfg)
  // leaks into unrelated instances
  • Name instances predictably to simplify set/get pairing.

  • Use narrow paths over broad wildcards for deterministic behavior.

  • Fail fast when mandatory cfg lookup misses.


End-to-end wiring code

systemverilog
class bus_env extends uvm_env;
  `uvm_component_utils(bus_env)
  bus_agent agt;

  function void build_phase(uvm_phase phase);
    bus_agent_cfg cfg;
    super.build_phase(phase);

    cfg = bus_agent_cfg::type_id::create("cfg");
    cfg.is_active = UVM_ACTIVE;
    cfg.timeout_cycles = 300;

    if (!uvm_config_db#(virtual bus_if)::get(this, "", "bus_vif", cfg.vif))
      `uvm_fatal("NOVIF", "missing bus_vif in bus_env")

    if (!cfg.randomize() with { req_gap_min_cycles <= 2; req_gap_max_cycles <= 8; })
      `uvm_fatal("CFG_RAND", "bus_agent_cfg randomization failed")

    uvm_config_db#(bus_agent_cfg)::set(this, "agt", "cfg", cfg);
    agt = bus_agent::type_id::create("agt", this);
  endfunction
endclass

class bus_agent extends uvm_agent;
  `uvm_component_utils(bus_agent)
  bus_agent_cfg cfg;
  bus_driver drv;
  bus_monitor mon;
  bus_sequencer sqr;

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    if (!uvm_config_db#(bus_agent_cfg)::get(this, "", "cfg", cfg))
      `uvm_fatal("NOCFG", "cfg missing at bus_agent")

    mon = bus_monitor::type_id::create("mon", this);
    uvm_config_db#(bus_agent_cfg)::set(this, "mon", "cfg", cfg);

    if (cfg.is_active == UVM_ACTIVE) begin
      sqr = bus_sequencer::type_id::create("sqr", this);
      drv = bus_driver::type_id::create("drv", this);
      uvm_config_db#(bus_agent_cfg)::set(this, "drv", "cfg", cfg);
    end
  endfunction
endclass
diagram
[UVM][AGT][DRV][TLM] propagation topology

cfg source:
  env per-agent instance

cfg consumers:
  wrapper (mode decisions)
  monitor (always)
  driver/sequencer (active mode)

result:
  one policy view across command and observation paths
  • Forward one cfg handle to all consumers unless isolation is intentional.

  • Do not re-randomize child cfg copies; keep policy coherent.

  • Log resolved cfg after agent get for each instance.


Precedence, overrides, and arrayed agents

Multi-instance benches need explicit precedence contracts and per-index path generation. Otherwise one override silently affects the wrong agent.

systemverilog
foreach (agts[i]) begin
  bus_agent_cfg cfg_i;
  cfg_i = bus_agent_cfg::type_id::create($sformatf("cfg_%0d", i));
  cfg_i.vif = vif_array[i];
  cfg_i.is_active = (i == 0) ? UVM_ACTIVE : UVM_PASSIVE;
  cfg_i.timeout_cycles = 128 + (i * 64);

  uvm_config_db#(bus_agent_cfg)::set(
    this, $sformatf("agts[%0d]", i), "cfg", cfg_i);
  agts[i] = bus_agent::type_id::create($sformatf("agts[%0d]", i), this);
end
diagram
[UVM][AGT][DRV][TLM] precedence ladder

highest:
  path-specific test override

middle:
  env-assigned per-instance cfg field values

lowest:
  cfg class defaults

always:
  print effective values after get/normalize

Key takeaways

  • Path-correct config_db wiring is foundational for deterministic agent behavior.

  • Set-before-get ordering and explicit precedence prevent accidental defaults.

  • Arrayed agents require index-safe path generation and per-instance visibility.

  • Single-source cfg propagation keeps driver and monitor aligned.

Common pitfalls

  • Creating agents before cfg set, causing hidden fallback behavior.

  • Overusing wildcard paths and unintentionally overriding unrelated instances.

  • Per-child reconfiguration that drifts from wrapper policy.

  • No effective cfg logs for multi-instance environments.