UVM Overriding

Hi,

I am trying to override the Configuration objects inside env, but they don’t seem to be overriding… I am not sure, if I am missing something here…

Here’s code:


program top;

import uvm_pkg::*;
`include "uvm_macros.svh"

class cfg extends uvm_object;
  rand bit [1:0] i_type;

  `uvm_object_utils_begin(cfg);
  `uvm_field_int (i_type, UVM_ALL_ON|UVM_DEEP)
  `uvm_object_utils_end

  function new(string name="cfg");
    super.new(name);
  endfunction : new
endclass

class c_0 extends cfg;
  `uvm_object_utils(c_0);
  constraint i_type_c { i_type == 2'b00; }
  function new(string name="cfg_0");
    super.new(name);
  endfunction : new
endclass

class c_1 extends cfg;
  `uvm_object_utils(c_1);
  constraint i_type_c { i_type == 2'b01; }
  function new(string name="cfg_1");
    super.new(name);
  endfunction : new
endclass

class c_2 extends cfg;
  `uvm_object_utils(c_2);
  constraint i_type_c { i_type == 2'b10; }
  function new(string name="cfg_2");
    super.new(name);
  endfunction : new
endclass

class c_3 extends cfg;
  `uvm_object_utils(c_3);
  constraint i_type_c { i_type == 2'b11; }
  function new(string name="cfg_3");
    super.new(name);
  endfunction : new
endclass

class env extends uvm_env;
  `uvm_component_utils(env);
  cfg m_cfg;

  function new(string name="env", uvm_component parent=null);
    super.new(name,parent);
  endfunction : new

  function void build_phase(uvm_phase phase);
  if (uvm_config_db#(cfg)::get(get_parent(), get_name(), "cfg", m_cfg)) begin
     `uvm_info("build_phase", "Using test case provided cfg", UVM_LOW)
     m_cfg.print();
  end
  else begin
    `uvm_info("build_phase", "External cfg not provided for cfg, creating default cfg.", UVM_LOW)
    m_cfg = cfg::type_id::create("cfg");
    m_cfg.print();
  end
  endfunction
endclass

class test extends uvm_test;
  cfg my_c0;
  cfg my_c1;
  cfg my_c2;
  cfg my_c3;

  env my_env[4];

  `uvm_component_utils(test)

  function new(string name="test", uvm_component parent=null);
    super.new(name,parent);
  endfunction : new

  function void build_phase(uvm_phase phase);
  super.build_phase(phase);
  // factory.set_inst_override_by_name( "cfg",
  //                                    "my_c2",
  //                                    "uvm_test_top.my_env[2]");
  set_inst_override_by_type("my_env[0].cfg",
                               cfg::get_type(),
                               c_0::get_type());
  set_inst_override_by_type("my_env[1].cfg",
                               cfg::get_type(),
                               c_1::get_type());
  set_inst_override_by_type("my_env[2].cfg",
                               cfg::get_type(),
                               c_2::get_type());
  set_inst_override_by_type("my_env[3].cfg",
                               cfg::get_type(),
                               c_3::get_type());
 
  my_c0 = cfg::type_id::create("my_c0");
  my_c1 = cfg::type_id::create("my_c1");
  my_c2 = cfg::type_id::create("my_c2");
  my_c3 = cfg::type_id::create("my_c3");

  uvm_config_db#(cfg)::set(this, "my_env[0]", "cfg", this.my_c0);
  uvm_config_db#(cfg)::set(this, "my_env[1]", "cfg", this.my_c1);
  uvm_config_db#(cfg)::set(this, "my_env[2]", "cfg", this.my_c2);
  uvm_config_db#(cfg)::set(this, "my_env[3]", "cfg", this.my_c3);

  my_env[0] = env::type_id::create("my_env[0]", this);
  my_env[1] = env::type_id::create("my_env[1]", this);
  my_env[2] = env::type_id::create("my_env[2]", this);
  my_env[3] = env::type_id::create("my_env[3]", this);
  endfunction
 
  function void end_of_elaboration_phase(uvm_phase phase);
  super.end_of_elaboration_phase(phase);
  factory.print();
  endfunction

endclass

class my_test extends test;

  `uvm_component_utils(my_test)

  function new(string name="my_test", uvm_component parent=null);
    super.new(name,parent);
  endfunction : new

endclass

  initial begin
    run_test("my_test");
  end
endprogram

Synopsys Outputs:
UVM_INFO @ 0: reporter [RNTST] Running test my_test…
UVM_INFO top.sv(60) @ 0: uvm_test_top.my_env[0] [build_phase] Using test case provided cfg

Name Type Size Value

my_c0 cfg - @470 ← Here:: Type ‘cfg’ should have been ‘c_0’
i_type integral 2 'h0

UVM_INFO top.sv(60) @ 0: uvm_test_top.my_env[1] [build_phase] Using test case provided cfg

Name Type Size Value

my_c1 cfg - @471 ← Here:: Type ‘cfg’ should have been ‘c_1’
i_type integral 2 'h0

UVM_INFO top.sv(60) @ 0: uvm_test_top.my_env[2] [build_phase] Using test case provided cfg

Name Type Size Value

my_c2 cfg - @472 ← Here:: Type ‘cfg’ should have been ‘c_2’
i_type integral 2 'h0

UVM_INFO top.sv(60) @ 0: uvm_test_top.my_env[3] [build_phase] Using test case provided cfg

Name Type Size Value

my_c3 cfg - @473 ← Here:: Type ‘cfg’ should have been ‘c_3’
i_type integral 2 'h0

Factory Configuration (*)

Instance Overrides:

Requested Type Override Path Override Type


cfg uvm_test_top.my_env[0].cfg c_0
cfg uvm_test_top.my_env[1].cfg c_1
cfg uvm_test_top.my_env[2].cfg c_2
cfg uvm_test_top.my_env[3].cfg c_3

No type overrides are registered with this factory

All types registered with the factory: 44 total
(types without type names will not be printed)

Type Name

c_0
c_1
c_2
c_3
cfg
env
my_test
test
(*) Types with no associated type name will be printed as

— UVM Report Summary —

** Report counts by severity
UVM_INFO : 5
UVM_WARNING : 0
UVM_ERROR : 0
UVM_FATAL : 0
** Report counts by id
[RNTST] 1
[build_phase] 4

Look out for “Here” in the results. I am expecting the type to change to c_0/1/2/3.

Your env::build_phase() has a bug.

Also, you are describing two different methods to populate the config objects:
(1) use config_db to set and get a pre-created config object from the test
(2) have the env construct it’s own default config object with cfg::type_id::create(“cfg”)

With method (1), the objects you are creating in your test class, are all of type ‘cfg’ (no type overrides on those, they are locally created, and then they are passed in via the config_db set/get. They are picked up OK by your env but they are still of type ‘cfg’ and your overrides are not going to affect them

With method (2), you have a bug in env::build_phase():

  • you call cfg::type_id::create(“cfg”)
  • this means - ask the factory for type ‘cfg’ to create an instance called ‘cfg’ with parent NULL.
    You need to specify parent ‘this’ otherwise the name lookup will not match.
  • change it to cfg::type_id::create(“cfg”,this)
    (and comment out the 4 config_db…set(…) lines in your test to try it out

In reply to gordon:

Thank you Gordon!!!

I followed the approach-2.

Specifying “this” worked, as intended.

Vivek