Wednesday, October 26, 2016

UVM Configuration DB.

Concepts
  • Share information between
    • Test
      • Top environment
        • sub environment
          • agents
            • sequencers
            • monitors
            • drivers
  • Need a consistent way of storing shared data 
  • Need simple, flexible access from anywhere
  • Need automatic access (done by uvm_component::build_phase())
  • Compare to traditional
    • enclosing pushes
    • ex. env.m_this_config = m_cfg
How to Use
  • Share the information of Physical IFs (between DUT and uvm_test)
    • Put into configuration db at top test module and get it in
      uvm_env.uvm_agent
      uvm_env.uvm_agent.uvm_driver
      uvm_env.uvm_agent.uvm_sequencer
      uvm_env.uvm_agent.uvm_monitor
  • Share DUT specific information

Syntax
//
// UVM 1.1
set_config_int(...) => uvm_config_db#(uvm_bitstream_t)::set(cntxt,...)
set_config_string(...) => uvm_config_db#(string)::set(cntxt,...)
set_config_object(...) => uvm_config_db#(uvm_object)::set(cntxt,...)
//
// UVM 1.2
// type T=int
// class uvm_config_db#(type T=int) extends uvm_resource_db#(T)
//
//                   context, inst,  key,   value   
uvm_config_db#(T)::set(cntxt,"inst","field",value); // modify central entries
uvm_config_db#(T)::get(cntxt,"inst","field",value); // update local variabbles
// There is a uvm11-to-uvm12.pl conversion script
uvm_config_db#(T)::exists(cntxt,"inst","field");
uvm_config_db#(T)::wait_modified(cntxt,"inst","field");

// For objects use this
set_config_object::set(this,"env.agent1","config", m_config);
// For enums use this
set_config_int::set(this,"env.agent1","bus_sz", SZ_128 );

// cntxt must be of type uvm_component, null or uvm_root::get()
// m_config: recommend to use uvm_object and $cast 
// Examples:
uvm_config_db#(T)::set(uvm_root::get(),”test1.env.agent1”, ”config”, m_config);
uvm_config_db#(T)::set(this,”env.agent*”,”config”, m_config);
uvm_config_db#(T)::set(null,”*”,”global_cfg”, m_global_cfg);

// to fetch the entry
if (!uvm_config_db#(uvm_object)::get(this, "","config",m_config)) begin
   `uvm_fatal(...) 
end
// check if it exists
if(!uvm_config_db#(int)::exists(this,"","low_power_mode")) begin 
   // do something interesting
end

// To automate field configuration
// Use uvm_config_object typedef
// Use uvm_object and $cast to concrete type for get()
function void uvm_component::build_phase(...); 
   // find fields, do get(), $cast
   apply_config_settings(...); 
endfunction

// Gotchas: 1. Don't miss field-macro
//         2. Make sure it's not UVM_READONL
/          3. remember to use super.build

class my_comp extends uvm_component;
   `uvm_component_utils_begin(my_comp)
      `uvm_field_int(my_field,UVM_DEFAULT) 
      `uvm_field_object(my_special,(UVM_DEFAULT|UVM_READONLY))
      `uvm_field_object(my_config,UVM_DEFAULT)  

      function void build_phase(...);
         super.build_phase(...);
         ...
      endfunction

// Using uvm_object and $cast in set() and get()
my_config m_config;
   ...
uvm_config_object::set(..., m_config);

uvm_object tmp;
uvm_config_object::get(..., tmp); 
$cast(m_config, tmp); // back to original type

// Using enums (can be int, uvm_bitstream_t or uvm_integral_t
my_enum_t m_bus_sz;
uvm_config_int::set(... , "m_bus_sz", SZ16);

int tmp;
uvm_config_int::get(... ,"m_bus_sz", tmp)
m_bus_sz = my_enum_t'(tmp); // back to original type

// Recommend use the factory 
m_srio_config = uvc_srio_config::type_id::create("m_srio_config");


Hierarchy of Configuration Objects
class top_env_config extends uvm_object; 
   env1_config m_env1_config; 
   env2_config m_env2_config;
   ...
endclass

class env1_config extends uvm_object;
   int some_var;
   int some_other_var;
   agent1_config m_agent1_config;
   agent2_config m_agent2_config;
   ... 
endclass

class top_env extends uvm_env;
   env1 m_env1;
   env2 m_env2;
   top_env_config m_config;
   ...
   'uvm_component_utils_begin(top_env)
      'uvm_field_object(m_config, UVM_DEFAULT)
   'uvm_component_utils_end

   function build_phase();
      super.build_phase();
      set_config_object(this, "env1","m_config",
                       m_config.m_env1_config);
      set_config_object(this, "env2","m_config",
                       m_config.m_env2_config);
      m_env1 = env1::type_id::create("m_env1");
      m_env2 = env2::type_id::create("m_env2");
   endfunction
endclass

// Next Level Down
class env1 extends uvm_env; 
   env1_config m_config;
   ...
   'uvm_component_utils_begin(top_env)
      'uvm_field_object(m_config, UVM_DEFAULT)
   'uvm_component_utils_end

   function void build_phase();
      super.build_phase();
      set_config_object(this, "m_agent1","m_config",
                m_config.m_agent1_config); 
      set_config_object(this, "m_agent2","m_config",
                m_config.m_agent2_config); 
      m_agent1 = env1::type_id::create("m_agent1"); 
      m_agent2 = env2::type_id::create("m_agent2");
   endfunction
endclass


Turn on the debugging in simulation

% sim_cmd +UVM_TESTNAME=my_test +UVM_CONFIG_DB_TRACE


No comments:

Post a Comment