UVM: Configuration Database - IKSciting
1765
post-template-default,single,single-post,postid-1765,single-format-standard,bridge-core-2.8.7,qodef-qi--no-touch,qi-addons-for-elementor-1.7.1,qode-page-transition-enabled,ajax_fade,page_not_loaded,,qode-title-hidden,qode_grid_1300,footer_responsive_adv,qode-content-sidebar-responsive,qode-theme-ver-27.1,qode-theme-bridge,qode_header_in_grid,wpb-js-composer js-comp-ver-6.6.0,vc_responsive,elementor-default,elementor-kit-838

Configuration Database

UVM configuration database, 즉, uvm_config_db는 testbench component 간 data를 주고 받을 때 사용되는 interface 방식 중 한 가지다. 일반적으로 가장 많이 사용되는 method인 setget의 동작과 prototype은 다음과 같다.

  • set – “cntxt 내 inst_name에 위치한 field_name이라는 이름의 data를 value의 값으로 set 해!”
  • get – “cntxt 내 inst_name에 위치한 field_name이라는 이름의 data를 value에 get 해!”

static function void set(uvm_component cntxt, string inst_name, string field_name, T value)
static function bit get(uvm_component cntxt, string inst_name, string field_name, inout T value)

uvm_config_db에 의해 set 된 database는 look-up table 형태로 관리되어 이를 기반으로 get 하게 된다. 이해를 돕기 위해 아래 그림과 code를 참고하자. Test에서 env에 2개, agent에 1개의 data를 set 하고 env와 agent에서 각각 get 하는 process를 나타낸다. 참고로 아래 simulation log는 Command Line Processors for Debugging 페이지에서 소개한 +UVM_CONFIG_DB_TRACE 옵션을 적용하여 출력한 결과로, configuration process에 대한 추가적인 정보를 확인하고자 할 때 도움이 된다.

UVM configuration database uvm_config_db
class my_test extends uvm_test;

  // ...

  function void build_phase(uvm_phase phase);
    // ...
    
    // set configuration database of type int on env
    uvm_config_db#(int)::set(this, "env", "my_int", 1024);
    
    // set configuration database of type string on env
    uvm_config_db#(string)::set(this, "env", "my_string", "hello world");
    
    // set configuration database of type string on agent
    uvm_config_db#(string)::set(this, "env.agent", "my_string", "foo bar");
  endfunction: build_phase

endclass: my_test
class my_env extends uvm_env;
  
  // ...

  function void build_phase(uvm_phase phase);
    // ...
    
    // get configuration database of type int from env
    if (!uvm_config_db#(int)::get(this, "", "my_int", my_int)) begin
      my_int = -1;
    end
      
    // get configuration database of type string from env
    if (!uvm_config_db#(string)::get(this, "", "my_string", my_string)) begin
      my_string = "undefined";
    end
    
    `uvm_info(get_type_name(), $sformatf("my_int = %1d", my_int), UVM_MEDIUM)
    `uvm_info(get_type_name(), $sformatf("my_string = %s", my_string), UVM_MEDIUM)
  endfunction: build_phase
  
endclass: my_env
class my_agent extends uvm_agent;
  
  // ...

  function void build_phase(uvm_phase phase);
    // ...
    
    // get configuration database of type string from agent
    if (!uvm_config_db#(string)::get(this, "", "my_string", my_string)) begin
      my_string = "undefined";
    end
    
    `uvm_info(get_type_name(), $sformatf("my_string = %s", my_string), UVM_MEDIUM)
  endfunction: build_phase
  
endclass: my_agent
UVM_INFO @ 0: reporter [CFGDB/SET] Configuration 'uvm_test_top.env.my_int' (type int) set by uvm_test_top = (int) 1024
UVM_INFO @ 0: reporter [CFGDB/SET] Configuration 'uvm_test_top.env.my_string' (type string) set by uvm_test_top = (string) "hello world"
UVM_INFO @ 0: reporter [CFGDB/SET] Configuration 'uvm_test_top.env.agent.my_string' (type string) set by uvm_test_top = (string) "foo bar"
UVM_INFO @ 0: reporter [CFGDB/GET] Configuration 'uvm_test_top.env.my_int' (type int) read by uvm_test_top.env = (int) 1024
UVM_INFO @ 0: reporter [CFGDB/GET] Configuration 'uvm_test_top.env.my_string' (type string) read by uvm_test_top.env = (string) "hello world"
UVM_INFO @ 0: uvm_test_top.env [env] my_int = 1024
UVM_INFO @ 0: uvm_test_top.env [env] my_string = hello world
UVM_INFO @ 0: reporter [CFGDB/GET] Configuration 'uvm_test_top.env.agent.my_string' (type string) read by uvm_test_top.env.agent = (string) "foo bar"
UVM_INFO @ 0: uvm_test_top.env.agent [agent] my_string = foo bar

위에서 보는 것과 같이 set 할 때는 cntxt를 통해 database를 사용할 instance의 parent hierarchical path를 지정하고, inst_name을 통해 해당 instance의 name을 지정한다. 결국 cntxt와 inst_name이 함께 하나의 instance를 가리킨다고 보면 된다. 문법상으로는 instance 지정 시 임의의 instance를 지정할 수 있고, wildcard를 이용하여 여러 instance에, 심지어는 전역에 set 할 수도 있지만, 의도치 않은 오동작을 방지하기 위하여 실제로 database를 사용할 instance를 가리키도록 coding 하는 것이 좋다. 특히 전역에 database를 set 하게 되면, database의 크기가 큰 경우 performance drop으로 이어질 수 있다. 마찬가지로 get 할 때도 database를 가져올 대상 instance가 get을 call 하는 instance와 일치하는 것이 좋다.

또한 get은 성공 여부에 따라 0 또는 1의 값을 반환하게 되는데, 이 반환값을 확인하여 실패 시 적절한 조치를 취하도록 coding 하는 것이 권장된다. 예를 들어 virtual interface를 get 하는 것과 같이 실패가 critical 한 경우 `uvm_fatal을 이용하여 simulation을 종료시키고, 그렇지 않은 경우 의미 있는 default 값을 assign 하도록 한다.

// not recommended
uvm_config_db#(uvm_bitstream_t)::get(this, "", "is_active", is_active);
void'(uvm_config_db#(virtual my_if)::get(this, "", "my_vif", my_vif));
// recommended
if (!uvm_config_db#(uvm_bitstream_t)::get(this, "", "is_active", is_active)) begin
  is_active = UVM_ACTIVE;
end
if (!uvm_config_db#(virtual my_if  )::get(this, "", "my_vif", my_vif)) begin
  `uvm_fatal(get_name(), "virtual interface not set")
end

마지막으로 uvm_config_db와 유사한 uvm_resource_db에 대한 설명은 Resource Database 페이지를 참고하되, 가급적 uvm_resource_db 대신 uvm_config_db를 사용하는 것이 좋다.

References

8 Comments

Post A Comment