Part 11 · Senior Prep · Intermediate

Reuse Config Strategy: cfg Objects and Hierarchy Scoping

Config-driven reuse across hierarchy levels — cfg object layering, config_db scoping, is_active propagation, and plusarg mapping without leaking VIP internals.

Config as the reuse API

The cfg object is the only configuration path into a VIP. Integrators set knobs via config_db; they never poke agent internals.

diagram
[ARCH][SENIOR][UVM] config layering

chip_cfg
  ├─ cpu_subsys_cfg
  │     └─ bus_cfg (is_active=PASSIVE)
  └─ io_subsys_cfg
        └─ pin_agent_cfg (is_active=ACTIVE)

test.build_phase:
  create chip_cfg
  apply level-specific defaults
  uvm_config_db::set(this, "*", "cfg", chip_cfg)
systemverilog
class chip_cfg extends uvm_object;
  `uvm_object_utils(chip_cfg)
  cpu_subsys_cfg cpu_cfg;
  io_subsys_cfg  io_cfg;

  function void apply_soc_defaults();
    cpu_cfg.bus_cfg.is_active = UVM_PASSIVE;
    io_cfg.pin_cfg.is_active  = UVM_ACTIVE;
    cpu_cfg.bus_cfg.enable_scoreboard = 0;  // chip SB owns checking
  endfunction

  function void apply_block_defaults();
    cpu_cfg.bus_cfg.is_active = UVM_ACTIVE;
    cpu_cfg.bus_cfg.enable_scoreboard = 1;
  endfunction
endclass

Key takeaways

  • Cfg layering mirrors hierarchy — chip_cfg wraps subsys_cfg wraps block cfg.

  • apply_*_defaults() encodes level-specific policy in one place.

  • config_db scoping with wildcards must be documented and tested.

Common pitfalls

  • Flat cfg with 200 fields and no hierarchy grouping.

  • Plusargs parsed inside agent instead of test pushing cfg.

  • Multiple config_db sets overwriting same field without clear precedence.


config_db scoping patterns

Senior config strategy defines exact set/get paths and validates them in smoke tests.

Scoping conventions

diagram
[ARCH][SENIOR][UVM] config_db scoping rules

test  env:
  set(this, "env", "cfg", chip_cfg)

env  agents:
  set(this, "agt*", "cfg", bus_cfg)  // wildcard for all agents

agent get:
  get(this, "", "cfg", cfg)  // relative to agent instance

rule: set always above get in build_phase order
systemverilog
function void build_phase(uvm_phase phase);
  super.build_phase(phase);
  chip_cfg cfg = chip_cfg::type_id::create("cfg");
  cfg.apply_soc_defaults();
  cfg.apply_plusarg_overrides();  // test owns plusarg → cfg mapping
  uvm_config_db#(chip_cfg)::set(this, "env", "cfg", cfg);
  env = chip_env::type_id::create("env", this);
endfunction

Plusarg mapping policy

  • Only test (or base_test) parses plusargs into cfg fields.

  • Agents read cfg — never call uvm_cmdline_processor directly.

  • Document every plusarg in test README with default and valid range.

  • Smoke test verifies plusarg override reaches agent cfg.

systemverilog
function void apply_plusarg_overrides();
  int tmp;
  if ($value$plusargs("ACTIVE=%d", tmp))
    cpu_cfg.bus_cfg.is_active = uvm_active_passive_enum'(tmp);
endfunction
bash
# verify config propagation
simv +UVM_TESTNAME=chip_test +ACTIVE=0 -l cfg_passive.log
grep "is_active=PASSIVE" cfg_passive.log

Common pitfalls

  • Agent reading plusargs — breaks reuse at different hierarchy levels.

  • Wildcard set too broad — unintended agents receive wrong cfg.

  • Cfg object shared by reference mutated by one agent affecting all.