UVM Tutorial for Candy Lovers – 34. Component Override

Some people told me that sour-chocolate actually tastes good and there are many recipes for sour cream chocolate cake. I understand that people have different tastes, so decided to replace our scoreboard with more liberal one. This article shows how to override a component.

New Scoreboard

This is our new scoreboard that respects any tastes. For those of you who want to see the original scoreboard, please see this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class jelly_bean_liberal_scoreboard extends jelly_bean_sb_subscriber;
  `uvm_component_utils( jelly_bean_liberal_scoreboard )
 
  function new( string name, uvm_component parent );
    super.new( name, parent );
  endfunction: new
 
  virtual function void write( jelly_bean_transaction t );
    if ( t.taste == YUMMY ) begin
      `uvm_info( "write", { "I know you like this.", t.convert2string() }, UVM_LOW )
    end else begin
      `uvm_info( "write", { "I know you don't like this.", t.convert2string() }, UVM_LOW )
    end
  endfunction: write  
endclass: jelly_bean_liberal_scoreboard

Now, let’s replace our old scoreboard with this.

Type Override

There are several ways to override a component using its type.

uvm_component_registry#(T,Tname)::set_type_override(override_type)

The first method is using the uvm_component_registry. I think this is the easiest way to override a component type. The line 8 instructs that the factory to override the jelly_bean_sb_subscriber with the jelly_bean_liberal_scoreboard.

1
2
3
4
5
6
7
8
9
10
11
12
class jelly_bean_test extends uvm_test;
  `uvm_component_utils( jelly_bean_test )
 
  jelly_bean_env jb_env;
 
  function void build_phase( uvm_phase phase );
    super.build_phase( phase );
    jelly_bean_sb_subscriber::type_id::set_type_override( jelly_bean_liberal_scoreboard::get_type() );    jb_env = jelly_bean_env::type_id::create( .name( "jb_env" ), .parent( this ) );    
  endfunction: build_phase
  // ...
endclass: jelly_bean_test

uvm_component::set_type_override_by_type(original_type, override_type)

The second method is using the set_type_override_by_type function of the uvm_component. Although the syntax is different, what it does is basically the same as the first method.

1
2
3
4
5
6
7
8
9
10
11
12
class jelly_bean_test extends uvm_test;
  `uvm_component_utils( jelly_bean_test )
 
  jelly_bean_env jb_env;
 
  function void build_phase( uvm_phase phase );
    super.build_phase( phase );
    set_type_override_by_type( jelly_bean_sb_subscriber::get_type(), jelly_bean_liberal_scoreboard::get_type() );    jb_env = jelly_bean_env::type_id::create( .name( "jb_env" ), .parent( this ) );    
  endfunction: build_phase
  // ...
endclass: jelly_bean_test

uvm_factory.set_type_override_by_type(original_type, override_type)

The third method is using the set_type_override_by_type function of the uvm_factory. Actually the above two methods we have seen are merely convenience functions for this third method. The line 7 gets the current factory, and the line 10 calls the function of the factory.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class jelly_bean_test extends uvm_test;
  `uvm_component_utils( jelly_bean_test )
 
  jelly_bean_env jb_env;
 
  function void build_phase( uvm_phase phase );
    uvm_factory factory = uvm_coreservice_t::get().get_factory(); 
    super.build_phase( phase );
    factory.set_type_override_by_type( jelly_bean_sb_subscriber::get_type(), jelly_bean_liberal_scoreboard::get_type() );    jb_env = jelly_bean_env::type_id::create( .name( "jb_env" ), .parent( this ) );    
  endfunction: build_phase
  // ...
endclass: jelly_bean_test

uvm_component::set_type_override(original_type_name, override_type_name)

The fourth method is using the set_type_override function of the uvm_component. Unlike the above three methods, this function takes two strings.

The first three methods above take uvm_object_wrapper as their argument(s).

1
2
3
4
5
6
7
8
9
10
11
12
class jelly_bean_test extends uvm_test;
  `uvm_component_utils( jelly_bean_test )
 
  jelly_bean_env jb_env;
 
  function void build_phase( uvm_phase phase );
    super.build_phase( phase );
    set_type_override( jelly_bean_sb_subscriber::type_name, jelly_bean_liberal_scoreboard::type_name );    jb_env = jelly_bean_env::type_id::create( .name( "jb_env" ), .parent( this ) );    
  endfunction: build_phase
  // ...
endclass: jelly_bean_test

The type_name represents the type name which was created by the `uvm_component_utils macro. In our case, jelly_bean_sb_subscriber::type_name is "jelly_bean_sb_subscriber", and jelly_bean_liberal_scoreboard::type_name is "jelly_bean_liberal_scoreboard".

The `uvm_component_utils macro creates the type_name, but `uvm_component_param_utils macro does not. You need to create your own type_name variable and get_type_name function in the latter case.

uvm_factory.set_type_override_by_name(original_type_name, override_type_name)

The last method is using the set_type_override_by_name function of the uvm_factory. Actually the fourth method above is a convenience function of this method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class jelly_bean_test extends uvm_test;
  `uvm_component_utils( jelly_bean_test )
 
  jelly_bean_env jb_env;
 
  function void build_phase( uvm_phase phase );
    uvm_factory factory = uvm_coreservice_t::get().get_factory(); 
    super.build_phase( phase );
    factory.set_type_override_by_name( jelly_bean_sb_subscriber::type_name, jelly_bean_liberal_scoreboard::type_name );    jb_env = jelly_bean_env::type_id::create( .name( "jb_env" ), .parent( this ) );    
  endfunction: build_phase
  // ...
endclass: jelly_bean_test

Instance Override

You can override a specific component instance, instead of replacing all the components of the same type. Similar to the type override, there are five different methods.

uvm_component_registry#(T,Tname)::set_inst_override(override_type, inst_path, parent)

The first method is using the uvm_component_registry. I think this is the easiest way to override a component instance. The line 8 instructs that the factory to override the jelly_bean_sb_subscriber with the jelly_bean_liberal_scoreboard. We specified the instance path ("jb_env.jb_sb") relative to the jelly_bean_test‘s hierarchical instance path.

1
2
3
4
5
6
7
8
9
10
11
12
class jelly_bean_test extends uvm_test;
  `uvm_component_utils( jelly_bean_test )
 
  jelly_bean_env jb_env;
 
  function void build_phase( uvm_phase phase );
    super.build_phase( phase );
    jelly_bean_sb_subscriber::type_id::set_inst_override( jelly_bean_liberal_scoreboard::get_type(), "jb_env.jb_sb", this );    jb_env = jelly_bean_env::type_id::create( .name( "jb_env" ), .parent( this ) );    
  endfunction: build_phase
  // ...
endclass: jelly_bean_test

uvm_component::set_inst_override_by_type(relative_inst_path, original_type, override_type)

The second method is using the set_inst_override_by_type function of the uvm_component. Although the syntax is different, what it does is basically the same as the first method.

1
2
3
4
5
6
7
8
9
10
11
12
class jelly_bean_test extends uvm_test;
  `uvm_component_utils( jelly_bean_test )
 
  jelly_bean_env jb_env;
 
  function void build_phase( uvm_phase phase );
    super.build_phase( phase );
    set_inst_override_by_type( "jb_env.jb_sb",  jelly_bean_sb_subscriber::get_type(), jelly_bean_liberal_scoreboard::get_type() );    jb_env = jelly_bean_env::type_id::create( .name( "jb_env" ), .parent( this ) );    
  endfunction: build_phase
  // ...
endclass: jelly_bean_test

uvm_factory.set_inst_override_by_type(original_type, override_type, full_inst_path)

The third method is using the set_inst_override_by_type function of the uvm_factory. Actually the above two methods we have seen are merely convenience functions for this third method. The line 7 gets the current factory, and the line 10 calls the function of the factory. Note that the function takes the full hierarchical instance path as the third argument. We created the full path by concatenating the two paths.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class jelly_bean_test extends uvm_test;
  `uvm_component_utils( jelly_bean_test )
 
  jelly_bean_env jb_env;
 
  function void build_phase( uvm_phase phase );
    uvm_factory factory = uvm_coreservice_t::get().get_factory(); 
    super.build_phase( phase );
    factory.set_inst_override_by_type( jelly_bean_sb_subscriber::get_type(), jelly_bean_liberal_scoreboard::get_type(), { get_full_name(), ".jb_env.jb_sb" } );    jb_env = jelly_bean_env::type_id::create( .name( "jb_env" ), .parent( this ) );    
  endfunction: build_phase
  // ...
endclass: jelly_bean_test

uvm_component::set_inst_override(relative_inst_path, original_type_name, override_type_name)

The fourth method is using the set_inst_override function of the uvm_component. Unlike the above three methods, this function takes three strings.

The first three methods above take uvm_object_wrapper as their type argument(s).

1
2
3
4
5
6
7
8
9
10
11
12
class jelly_bean_test extends uvm_test;
  `uvm_component_utils( jelly_bean_test )
 
  jelly_bean_env jb_env;
 
  function void build_phase( uvm_phase phase );
    super.build_phase( phase );
    set_inst_override( "jb_env.jb_sb", jelly_bean_sb_subscriber::type_name, jelly_bean_liberal_scoreboard::type_name );    jb_env = jelly_bean_env::type_id::create( .name( "jb_env" ), .parent( this ) );    
  endfunction: build_phase
  // ...
endclass: jelly_bean_test

The type_name represents the type name which was created by the `uvm_component_utils macro. In our case, jelly_bean_sb_subscriber::type_name is "jelly_bean_sb_subscriber", and jelly_bean_liberal_scoreboard::type_name is "jelly_bean_liberal_scoreboard".

The `uvm_component_utils macro creates the type_name, but `uvm_component_param_utils macro does not. You need to create your own type_name variable and get_type_name function in the latter case.

uvm_factory.set_inst_override_by_name(original_type_name, override_type_name, full_inst_path)

The last method is using the set_inst_override_by_name function of the uvm_factory. Actually the fourth method above is a convenience function of this method. Similar to the third method above, we created the full path by concatenating the two paths.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class jelly_bean_test extends uvm_test;
  `uvm_component_utils( jelly_bean_test )
 
  jelly_bean_env jb_env;
 
  function void build_phase( uvm_phase phase );
    uvm_factory factory = uvm_coreservice_t::get().get_factory(); 
    super.build_phase( phase );
    factory.set_inst_override_by_name( jelly_bean_sb_subscriber::type_name, jelly_bean_liberal_scoreboard::type_name, { get_full_name(), ".jb_env.jb_sb" } );    jb_env = jelly_bean_env::type_id::create( .name( "jb_env" ), .parent( this ) );    
  endfunction: build_phase
  // ...
endclass: jelly_bean_test

I covered five different methods to override a type, and another five methods to override an instance. Personally, I use the first methods because they are the simplest. I hope this article clarified the difference of each method.

EDA Playground

As always you can view and run the code on EDA Playground.

4 thoughts on “UVM Tutorial for Candy Lovers – 34. Component Override”

  1. Hi Keisuke,

    Thank you very much for your post, it is always helpful.

    I show may code only use the code as follows, which type should it be? I think it is different from your code, is “jelly_bean_sb_subscriber::type_id::” must have? for my understanding, it is necessary for component override. Please correct me.

    set_type_override_by_type(bird::get_type(), parrot::get_type())

    2. What is the difference between uvm_factory. * and uvm_component.* .

    jelly_bean_sb_subscriber::type_id::set_type_override
    vs.
    factory.set_type_override_by_name

    3. in the initial begin, we could also use factory.set_type_override_by_type()…

    Do we need to have uvm_factory factory = uvm_coreservice_t::get().get_factory(); somewhere in the top?

    Best,

      1. If you call set_type_override_by_type from within a subclass of uvm_component, you don’t need to qualify it with uvm_component::.
      2. jelly_bean_sb_subscriber::type_id::set_type_override calls uvm_factory.set_type_override_by_type.
      3. In UVM 1.1, the uvm_factory.svh instantiates the singleton factory called factory, so you can use it without getting the factory by yourself. However, if you use UVM 1.2, you need to get the factory by yourself.
  2. Hi,

    The article is very informative. Could you kindly explain the difference between set_inst_override_by_type and set_inst_override_by_name?

    Thanks,
    Kumar

Leave a Reply to Keisuke Shimizu Cancel reply

Your email address will not be published. Required fields are marked *