Part 9 · Register Model (RAL) · Intermediate

config_db Sharing: Multi-Level Env, One Model

How to keep a single reg_model handle across test, chip_env, and block_env hierarchy layers.

One model handle across hierarchy

Large environments often include test -> chip_env -> subsystem_env -> block_env. If each layer creates its own reg_model instance, frontdoor and mirror state diverge immediately.

Use uvm_config_db to pass one canonical reg_model handle down the hierarchy so every component references the same object tree.

diagram
[UVM][RAL] hierarchical sharing pattern

test_top
  │ creates reg_model once
  ▼
chip_env
  │ get reg_model from config_db
  │ set same handle to subsystems
  ▼
subsystem_env
  │ get same handle
  │ set same handle to block envs
  ▼
block_env/reg_env
  │ get same handle
  └ bind maps, adapters, predictors

All components point to one model instance.
  • Create-once at top, consume-everywhere below is the safest ownership model.

  • Log object handles at each level during bring-up to prove identity equality.

  • Never hide fallback local model creation without a warning/fatal policy.


Reference implementation across three levels

test class (producer)

systemverilog
class soc_reg_test extends uvm_test;
  `uvm_component_utils(soc_reg_test)
  chip_env     env;
  soc_reg_root reg_model;

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    env       = chip_env::type_id::create("env", this);
    reg_model = soc_reg_root::type_id::create("reg_model");
    reg_model.build();
    reg_model.lock_model();

    // publish globally for env tree
    uvm_config_db#(soc_reg_root)::set(this, "env*", "reg_model", reg_model);
  endfunction
endclass

chip_env (pass-through owner)

systemverilog
class chip_env extends uvm_env;
  `uvm_component_utils(chip_env)
  subsystem_env ss0, ss1;
  soc_reg_root  reg_model;

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    ss0 = subsystem_env::type_id::create("ss0", this);
    ss1 = subsystem_env::type_id::create("ss1", this);

    if (!uvm_config_db#(soc_reg_root)::get(this, "", "reg_model", reg_model))
      `uvm_fatal("RAL_CFG", "chip_env missing shared reg_model")

    // republish same handle downward
    uvm_config_db#(soc_reg_root)::set(this, "ss0*", "reg_model", reg_model);
    uvm_config_db#(soc_reg_root)::set(this, "ss1*", "reg_model", reg_model);
  endfunction
endclass

reg_env (consumer)

systemverilog
class reg_env extends uvm_env;
  `uvm_component_utils(reg_env)
  soc_reg_root reg_model;

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    if (!uvm_config_db#(soc_reg_root)::get(this, "", "reg_model", reg_model))
      `uvm_fatal("RAL_CFG", "reg_env did not receive shared reg_model")
  endfunction
endclass

Identity checks and anti-patterns

Identity assertion helper

systemverilog
function void check_model_identity(string who, soc_reg_root m);
  if (m == null)
    `uvm_fatal("RAL_CFG", {who, ": reg_model is null"})
  `uvm_info("RAL_CFG", $sformatf("%s reg_model handle=%0p", who, m), UVM_LOW)
endfunction

Anti-pattern: silent local fallback

systemverilog
// Avoid this pattern in deep envs:
if (!uvm_config_db#(soc_reg_root)::get(this, "", "reg_model", reg_model)) begin
  // BAD: creates hidden second model and causes divergence
  reg_model = soc_reg_root::type_id::create("reg_model_local");
  reg_model.build();
  reg_model.lock_model();
end
diagram
[UVM][RAL] divergence symptom map

Symptom: block_env mirror differs from test mirror
Likely cause: multiple model instances

Symptom: one reg sequence works in ss0 but fails in ss1
Likely cause: ss1 created its own fallback model

Symptom: predictor appears connected but mirror checks still stale
Likely cause: predictor bound to different model instance

Key takeaways

  • Multi-level envs must share exactly one reg_model instance.

  • Use config_db get/fatal pattern; avoid silent local creation.

  • Print and compare object handles during bring-up to prove identity.

Common pitfalls

  • Creating local fallback model in a lower env after get() failure.

  • Publishing to a narrow path that misses some children.

  • Sharing root model but accidentally binding predictor to a clone map.