Part 3 · Factory & Configuration · Intermediate
Typed Config Patterns: Objects, Scalars, Enums, and Virtual Handles
Production patterns for passing config objects, integers, enums, strings, and virtual interface handles through config_db.
Config object pattern
The most maintainable pattern: one typed uvm_object per subsystem, set once from test, get once in agent/env.
class apb_config extends uvm_object;
`uvm_object_utils(apb_config)
uvm_active_passive_enum is_active = UVM_ACTIVE;
int unsigned num_wait_states = 2;
bit enable_coverage = 1;
virtual apb_if vif;
function new(string name = "apb_config"); super.new(name); endfunction
endclass
// test build_phase
apb_config acfg = apb_config::type_id::create("acfg");
acfg.is_active = UVM_ACTIVE;
uvm_config_db#(apb_config)::set(this, "env.apb", "cfg", acfg);
// agent build_phase
if (!uvm_config_db#(apb_config)::get(this, "", "cfg", cfg))
`uvm_fatal("CFG", "apb_config not set")[CONFIG] config object vs scattered scalars
scattered scalars:
set "timeout", set "is_active", set "enable_cov" separately
→ fragile, hard to validate, no single print summary
config object:
one set/get of apb_config
→ typed, printable, randomizable, versionableScalar and enum patterns
typedef enum { MODE_SAFE, MODE_PERF, MODE_STRESS } test_mode_e;
// set from test
uvm_config_db#(test_mode_e)::set(this, "env", "mode", MODE_STRESS);
uvm_config_db#(int)::set(this, "env.*", "seed_tag", 42);
// get in env
test_mode_e mode;
int seed_tag = 0;
void'(uvm_config_db#(test_mode_e)::get(this, "", "mode", mode));
void'(uvm_config_db#(int)::get(this, "", "seed_tag", seed_tag));Enum types must use the same typedef on both set and get sides.
Use int for simple knobs; config objects for multi-field policy.
String fields work but prefer enums for finite policy sets.
Virtual interface handle pattern
// [HDL] top publishes before run_test
uvm_config_db#(virtual apb_if)::set(null, "uvm_test_top.env.apb.*", "vif", apb_if_i);
// [UVM] driver consumes in build_phase
virtual apb_if vif;
if (!uvm_config_db#(virtual apb_if)::get(this, "", "vif", vif))
`uvm_fatal("NOVIF", $sformatf("vif not set for %s", get_full_name()))[HDL][CONFIG][UVM] vif typing rules
set type: virtual apb_if
get type: virtual apb_if ✓
set type: virtual apb_if
get type: virtual apb_if.drv_mp ✗ (different type)
parameterized if: parameter values must match exactlyKey takeaways
Prefer typed config objects over many independent scalar sets.
Virtual interface types must match exactly including modports.
Validate config objects after get — check required fields.
Common pitfalls
Setting base config type, getting derived type — type mismatch.
Parameterized interface with different parameter values — silent fail.
Sharing one config object handle mutated by multiple components.