Part 3 · Factory & Configuration · Intermediate
config_db vif Wiring: Paths, Forwarding, and Modports
Detailed config_db wiring for virtual interfaces — path conventions, agent forwarding, modport-specific virtual types, and config-object vif fields.
Path convention reference
[CONFIG] vif path conventions
from top (context=null):
"uvm_test_top.env.apb.*" agent subtree
"uvm_test_top.env" env reads named vif
"uvm_test_top.env.apb.drv" direct to driver (avoid — bypasses agent)
from agent (context=this):
"" get vif set by parent/top
"*" forward to all children
"drv" forward to driver only
field name: "vif" (convention) or "apb_vif" (named, env-level)Modport-specific virtual interfaces
For clocking-block access, publish and consume modport-specific virtual types. The type on set and get must match exactly.
// Publish driver modport from top
uvm_config_db#(virtual apb_if.drv_mp)::set(
null, "uvm_test_top.env.apb.drv", "vif", apb_if_i);
class apb_driver extends uvm_driver;
virtual apb_if.drv_mp vif;
task drive_addr(bit [31:0] addr);
@(vif.cb);
vif.cb.paddr <= addr;
endtask
endclass[HDL][CONFIG][UVM] modport typing
set: virtual apb_if.drv_mp
get: virtual apb_if.drv_mp ✓ clocking block access
set: virtual apb_if
get: virtual apb_if.drv_mp ✗ type mismatch, get fails
pattern: publish modport type matching consumer's access needsVif in config object pattern
Combine vif with other agent policy in a config object — set once, agent reads cfg and extracts vif:
class apb_config extends uvm_object;
`uvm_object_utils(apb_config)
uvm_active_passive_enum is_active = UVM_ACTIVE;
virtual apb_if vif;
int unsigned timeout_ns = 1000;
function new(string name = "apb_config"); super.new(name); endfunction
endclass
// top sets vif into config before run_test
apb_config acfg = apb_config::type_id::create("acfg");
acfg.vif = apb_if_i;
uvm_config_db#(apb_config)::set(null, "uvm_test_top.env.apb", "cfg", acfg);
// agent build_phase
if (!uvm_config_db#(apb_config)::get(this, "", "cfg", cfg))
`uvm_fatal("CFG", "apb_config missing")
vif = cfg.vif;
if (vif == null)
`uvm_fatal("NOVIF", "cfg.vif is null")[CONFIG] vif delivery options
Option A — direct vif set/get:
set(null, path, "vif", if_i) → get("", "vif", vif)
simple, explicit
Option B — vif inside config object:
set(null, path, "cfg", acfg) where acfg.vif = if_i
bundles vif with agent policy, one get()Option A is standard for VIP with minimal config objects.
Option B scales when vif and policy are always set together.
If using Option B, top must assign acfg.vif before set — not in agent.
Key takeaways
Match modport types exactly between set and get.
Agent forwarding with set(this, "*", "vif", vif) is the reuse pattern.
Config object can carry vif — validate cfg.vif != null after get.
Common pitfalls
Publishing full interface type but consuming modport type.
Setting vif on config object in agent instead of top/test.
Forwarding vif before successful get — propagates null to children.