Cookbook :: Configuring Per Sequence

While going through UVM Cookbook I observe the following code ::


`include "uvm_pkg.sv"
`include "uvm_macros.svh" 

 import uvm_pkg::*;
  
  class my_bus_config  extends  uvm_object ;

    //  Factory Registration and Std 3 line  Object Constructor

     bit [4:0] enable_error_injection ;

  endclass

  class my_bus_seq extends uvm_sequence ;
  
    string scope_name = "";
    
    //  Factory Registration and Std 3 line  Object Constructor
  
    task body();
     my_bus_config m_config;
  
       if( scope_name == "" ) begin
         scope_name = get_full_name();  //  this is { sequencer.get_full_name() , get_name() }
        `uvm_info( get_name(),$sformatf(" scope_name  is  %0s ",scope_name),UVM_NONE ) 
       end
  
       if( !uvm_config_db #( my_bus_config )::get( null , scope_name , "my_bus_config" , m_config ) ) 
        begin
         `uvm_error(get_name(),$sformatf(" Unable to  Fetch ") )
        end
       else  begin

        `uvm_info( get_name(),$sformatf(" m_config.enable_error_injection is  %0d ",m_config.enable_error_injection ),UVM_NONE ) 

        end
  
     endtask
  
  endclass

  class  my_agent  extends  uvm_agent ;
   
      typedef uvm_sequencer  seqr ;

      seqr  seqr_h ; 

     //  Factory Registration and Std 3 line  Component  Constructor

     function  void  build_phase ( uvm_phase phase ) ;
          seqr_h  = seqr::type_id::create("seqr_h",this) ;
     endfunction

  endclass

  class  my_env  extends  uvm_env ;

      my_agent  agent1 ;

     //  Factory Registration and Std 3 line  Component  Constructor

     function  void  build_phase ( uvm_phase phase ) ;

       my_bus_config  agent1_config ,  agent1_error_config ;
        
        agent1 = my_agent::type_id::create("agent1",this) ;
               
               agent1_config = my_bus_config::type_id::create("agent1_config") ;

               agent1_config.enable_error_injection = 0 ; 
         
               agent1_error_config = my_bus_config::type_id::create("agent1_error_config") ;

               agent1_error_config.enable_error_injection = 10 ; 
      
      `ifdef M1  //  Reverse  Order  of  set  of  Cookbook  

        // sequences with "error" in their name will enable error injection
         uvm_config_db #( my_bus_config )::set( this , "agent1.seqr_h.error*" , "my_bus_config" , agent1_error_config );      //  [A1]

        // most sequences do not enable error injection
         uvm_config_db #( my_bus_config )::set( this , "agent1*" , "my_bus_config" , agent1_config );                         //  [B1]

      `else     //  Same  Order  of  set  as   Cookbook 

        // most sequences do not enable error injection
         uvm_config_db #( my_bus_config )::set( this , "agent1*" , "my_bus_config" , agent1_config );                         // [A2]
        
        // sequences with "error" in their name will enable error injection
         uvm_config_db #( my_bus_config )::set( this , "agent1.seqr_h.error*" , "my_bus_config" , agent1_error_config );      // [B2]
   
      `endif

     endfunction

     task main_phase( uvm_phase phase ) ;
         my_bus_seq  normal_seq = my_bus_seq::type_id::create("normal_seq");
         my_bus_seq  error_seq = my_bus_seq::type_id::create("error_seq");

        phase.raise_objection( this ) ; 

         fork
          
           normal_seq.start( agent1.seqr_h ) ;
           
           error_seq.start( agent1.seqr_h ) ;

         join  
        
        phase.drop_objection( this ) ; 

     endtask

  endclass

  module  Cookbook_Configuring_Per_Sequence_Configuration ;

      initial  run_test("my_env" ) ;

  endmodule


Without any define I Observe ::

UVM_INFO @ 0: reporter [RNTST] Running test my_env…
UVM_INFO @ 0: uvm_test_top.agent1.seqr_h@@normal_seq [normal_seq] scope_name is uvm_test_top.agent1.seqr_h.normal_seq
UVM_INFO @ 0: uvm_test_top.agent1.seqr_h@@normal_seq [normal_seq] m_config.enable_error_injection is 0
UVM_INFO @ 0: uvm_test_top.agent1.seqr_h@@error_seq [error_seq] scope_name is uvm_test_top.agent1.seqr_h.error_seq
UVM_INFO @ 0: uvm_test_top.agent1.seqr_h@@error_seq [error_seq] m_config.enable_error_injection is 10

[Q1] How is the sequence able to fetch the appropriate configuration ? How do statements [A2] and [B2] impact the get Calls ?

With [A2] argument ‘inst_name’ “agent1*” covers “agent1.seqr_h.error*” right ?

With +define+M1 I Observe ::

UVM_INFO @ 0: reporter [RNTST] Running test my_env…
UVM_INFO @ 0: uvm_test_top.agent1.seqr_h@@normal_seq [normal_seq] scope_name is uvm_test_top.agent1.seqr_h.normal_seq
UVM_INFO @ 0: uvm_test_top.agent1.seqr_h@@normal_seq [normal_seq] m_config.enable_error_injection is 0
UVM_INFO @ 0: uvm_test_top.agent1.seqr_h@@error_seq [error_seq] scope_name is uvm_test_top.agent1.seqr_h.error_seq
UVM_INFO @ 0: uvm_test_top.agent1.seqr_h@@error_seq [error_seq] m_config.enable_error_injection is 0

[Q2] Why does the Output differ in this case ? How do statements [A1] and [B1] impact the get Calls ?

Thanks

In reply to TC_2017:

When doing multiple calls to uvm_config_db::set() from the same component, last write wins. In [Q1] The first set() is broadcast to “agent1*”, then the second set() is a more specific string “agent1.seqr_h.error*”.

It might help to think of a list of strings pushed to the front of a queue for every call to set(). Then each call to get() scans the queue from front to back to find a string match with the scope name provided with the get. The first match gets the config_db setting associated with that string’s setting.

When you reverse the setting in [Q2], it’s going to find the match with “agent1*” first and never match the “agent1.seqr_h.error*” setting.

So the more specific string setting must come before the less specific string setting.

In reply to dave_59:

When you are using the same order for prinzing in both branches you can see the same result.
Find below a working code:

`include "uvm_macros.svh" 
 import uvm_pkg::*;
 
  class my_bus_config  extends  uvm_object ;
 
    //  Factory Registration and Std 3 line  Object Constructor
     `uvm_object_utils(my_bus_config)

     bit [4:0] enable_error_injection ;

     function new(string name = "");
       super.new(name);
     endfunction  
 
  endclass
 
  class my_bus_seq extends uvm_sequence ;
 
     `uvm_object_utils(my_bus_seq)

    string scope_name = "";
 
     function new(string name = "");
       super.new(name);
     endfunction  
 
    task body();
     my_bus_config m_config;
 
       if( scope_name == "" ) begin
         scope_name = get_full_name();  //  this is { sequencer.get_full_name() , get_name() }
        `uvm_info( get_name(),$sformatf(" scope_name  is  %0s ",scope_name),UVM_NONE ) 
       end
 
       if( !uvm_config_db #( my_bus_config )::get( null , scope_name , "my_bus_config" , m_config ) ) 
        begin
         `uvm_error(get_name(),$sformatf(" Unable to  Fetch ") )
        end
       else  begin
 
        `uvm_info( get_name(),$sformatf(" m_config.enable_error_injection is  %0d ",m_config.enable_error_injection ),UVM_NONE ) 
 
        end
 
     endtask
 
  endclass
 
  class  my_agent  extends  uvm_agent ;
 
     `uvm_component_utils(my_agent)
      typedef uvm_sequencer  seqr ;
 
      seqr  seqr_h ; 
 
     //  Factory Registration and Std 3 line  Component  Constructor
     function new(string name, uvm_component parent);
       super.new(name, parent);
     endfunction  
 
     function  void  build_phase ( uvm_phase phase ) ;
          seqr_h  = seqr::type_id::create("seqr_h",this) ;
     endfunction
 
  endclass
 
  class  my_env  extends  uvm_env ;
 
     `uvm_component_utils(my_env)
      my_agent  agent1 ;
 
     function new(string name, uvm_component parent);
       super.new(name, parent);
     endfunction  
 
     //  Factory Registration and Std 3 line  Component  Constructor
 
     function  void  build_phase ( uvm_phase phase ) ;
 
       my_bus_config  agent1_config ,  agent1_error_config ;
 
        agent1 = my_agent::type_id::create("agent1",this) ;
 
               agent1_config = my_bus_config::type_id::create("agent1_config") ;
 
               agent1_config.enable_error_injection = 0 ; 
 
               agent1_error_config = my_bus_config::type_id::create("agent1_error_config") ;
 
               agent1_error_config.enable_error_injection = 10 ; 
 
      `ifdef M1  //  Reverse  Order  of  set  of  Cookbook  
 
        // sequences with "error" in their name will enable error injection
         uvm_config_db #( my_bus_config )::set( this , "agent1.seqr_h.error*" , "my_bus_config" , agent1_error_config );      //  [A1]
 
        // most sequences do not enable error injection
         uvm_config_db #( my_bus_config )::set( this , "agent1.seqr_h.normal*" , "my_bus_config" , agent1_config );                         //  [B1]
 
      `else     //  Same  Order  of  set  as   Cookbook 
 
        // sequences with "error" in their name will enable error injection
         uvm_config_db #( my_bus_config )::set( this , "agent1.seqr_h.error*" , "my_bus_config" , agent1_error_config);      // [B2]
 
        // most sequences do not enable error injection
         uvm_config_db #( my_bus_config )::set( this , "agent1.seqr_h.normal*" , "my_bus_config" , agent1_config );                         // [A2]
 
      `endif
 
     endfunction
 
     task run_phase( uvm_phase phase ) ;
         my_bus_seq  normal_seq = my_bus_seq::type_id::create("normal_seq");
         my_bus_seq  error_seq = my_bus_seq::type_id::create("error_seq");
 
        phase.raise_objection( this ) ; 
 
         fork
 
           normal_seq.start( agent1.seqr_h ) ;
 
           error_seq.start( agent1.seqr_h ) ;
 
         join  
 
        phase.drop_objection( this ) ; 
 
     endtask
 
  endclass
 
  module  Cookbook_Configuring_Per_Sequence_Configuration ;
 
      initial  run_test("my_env" ) ;
 
  endmodule