config_db机制详解

本文介绍 UVM 中 config_db 的使用方法,包括 set 和 get 的位置选择、多个层次 set 的优先级、常见使用场景及实战代码分析。通过具体例子说明如何在不同组件间传递配置信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、前言:

在跟着路科视频学习UVM时,学的有点快,没有仔细搞清楚,用的时候就不知道具体在哪里设置set哪里设置get,今天再继续学一学。

2、config_db机制

1、set与get各自用该放在哪里

set与get一般都成对出现。

set:自顶层向下set,如从top_tb向driver设置参数,即在top_tb中set。

uvm_config_db#(int)::set(this, "env.agt.drv", "num", 100);

第一个参数this与第二个参数“env.agt.drv”——构成目标路径;因此也可以为(this.env, "agt.drv", "num", 100)

第三个参数是传给该路径的哪个成员;

第四个参数是要设置的值。

get:从底层向顶层get,如从driver中的build_phase使用get。

uvm_config_db#(int)::get(this, "","num", pre_num);

第一个参数必须是uvm_component实例的指针,第二个参数是相对此实例的路径。一般的,如果第一个参数被设置成this,第二个参数可以是一个空的字符串。

第三个参数要与set中的第三个参数严格一致。

第四个参数是要设置的值。

有些情况下get可以省略:

这里的关键在于:build_phase中的super.build_phase语句,当执行到driver的的super.build_phase时,会自动执行get语句。

class my_driver extends uvm_driver#(my_transaction);

   virtual my_if vif;

   int pre_num;
   `uvm_component_utils_begin(my_driver)
      `uvm_field_int(pre_num, UVM_ALL_ON)
   `uvm_component_utils_end

   function new(string name = "my_driver", uvm_component parent = null);
      super.new(name, parent);
      pre_num = 3;
   endfunction

   virtual function void build_phase(uvm_phase phase);
      `uvm_info("my_driver", $sformatf("before super.build_phase, the num is %0d", pre_num), UVM_LOW) 
      super.build_phase(phase);
      `uvm_info("my_driver", $sformatf("after super.build_phase, the num is %0d", pre_num), UVM_LOW) 
      if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))
         `uvm_fatal("my_driver", "virtual interface must be set for vif!!!")
   endfunction

   extern task main_phase(uvm_phase phase);
   extern task drive_one_pkt(my_transaction tr);
endclass

这种做法的前提是:

1)my_driver必须使用宏注册。

2)num必须使用uvm_field_int宏注册。

3)在调用set函数时,set函数的第三个参数必须要与get函数中变量的名字相一致,必须为num。

2、当多个层次多次发送set时,最终得到哪个

1)先以时间为准,最近收到的具有最高权威;

2)当收到时间相同时,层次越高,优先级越低。例如,uvm_test_top与env都对driver进行了设置,则使用uvm_test_top的设置。

3、config_db的set和get一般都用在build_phase阶段

check_config_usage可以显示截至到此函数调用时有哪些参数时被设置过但是却没有被获取过。此函数一般在connect_phase被调用。

4、config_db使用场景

1)传递virtual interface到环境中。一般driver、moniter与DUT连接时使用config_db传递virtual interface。SV中层次化的interface的索引传递,不利于软件环境的封装和复用。

2)设置单一变量值,例如int、string、enum。

3)传递配置对象(config object)到环境。

5、实战

1)运行代码

interface uvm_config_if;
  logic [31:0] addr;
  logic [31:0] data;
  logic [ 1:0] op;
endinterface

package uvm_config_pkg;
  import uvm_pkg::*;
  `include "uvm_macros.svh"
  
  class config_obj extends uvm_object;
    int comp1_var;
    int comp2_var;
    `uvm_object_utils(config_obj)
    function new(string name = "config_obj");
      super.new(name);
      `uvm_info("CREATE", $sformatf("config_obj type [%s] created", name), UVM_LOW)
    endfunction
  endclass
  
  class comp2 extends uvm_component;
    int var2;
    virtual uvm_config_if vif;  
    config_obj cfg; 
    `uvm_component_utils(comp2)
    function new(string name = "comp2", uvm_component parent = null);
      super.new(name, parent);
      var2 = 200;
      `uvm_info("CREATE", $sformatf("unit type [%s] created", name), UVM_LOW)
    endfunction
    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      `uvm_info("BUILD", "comp2 build phase entered", UVM_LOW)
      //TODO-4.1
      //Please get the interface and check if it is got
         if(!uvm_config_db#(virtual uvm_config_if)::get(this, "", "vif", vif))
        `uvm_error("GETVIF", "no virtual interface is assigned")
      `uvm_info("GETINT", $sformatf("before config get, var2 = %0d", var2), UVM_LOW)
      //TODO-4.3
      //Please get the var2 from config_db
	  uvm_config_db#(int)::get(this, "", "var2", var2);
      `uvm_info("GETINT", $sformatf("after config get, var2 = %0d", var2), UVM_LOW)
      
      //TODO-4.2
      //Please get the config object
	  uvm_config_db#(config_obj)::get(this, "", "cfg", cfg);
      `uvm_info("GETOBJ", $sformatf("after config get, cfg.comp2_var = %0d", cfg.comp2_var), UVM_LOW)     
      
      `uvm_info("BUILD", "comp2 build phase exited", UVM_LOW)
    endfunction
  endclass

  class comp1 extends uvm_component;
    int var1;
    comp2 c2;
    config_obj cfg; 
    virtual uvm_config_if vif;
    `uvm_component_utils(comp1)
    function new(string name = "comp1", uvm_component parent = null);
      super.new(name, parent);
      var1 = 100;
      `uvm_info("CREATE", $sformatf("unit type [%s] created", name), UVM_LOW)
    endfunction
    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      `uvm_info("BUILD", "comp1 build phase entered", UVM_LOW)
      //TODO-4.1
      //Please get the interface and check if it is got
        if(!uvm_config_db#(virtual uvm_config_if)::get(this, "","vif",vif))
		`uvm_error("GERINT","no virtual interface is assigned")
      `uvm_info("GETINT", $sformatf("before config get, var1 = %0d", var1), UVM_LOW)
      //TODO-4.3
      //Please get the var1 from config_db
	  uvm_config_db#(int)::get(this,"","var1",var1);
      `uvm_info("GETINT", $sformatf("after config get, var1 = %0d", var1), UVM_LOW)
      
      //TODO-4.2
      //Please get the config object
	  uvm_config_db#(config_obj)::get(this,"","cfg",cfg);
      `uvm_info("GETOBJ", $sformatf("after config get, cfg.comp1_var = %0d", cfg.comp1_var), UVM_LOW)
      
      c2 = comp2::type_id::create("c2", this);
      `uvm_info("BUILD", "comp1 build phase exited", UVM_LOW)
    endfunction
  endclass

  class uvm_config_test extends uvm_test;
    comp1 c1;
    config_obj cfg;
    `uvm_component_utils(uvm_config_test)
    function new(string name = "uvm_config_test", uvm_component parent = null);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      `uvm_info("BUILD", "uvm_config_test build phase entered", UVM_LOW)
      
      cfg = config_obj::type_id::create("cfg");
      cfg.comp1_var = 100;
      cfg.comp2_var = 200;
      //TODO-4.2
      //Please config the object to c1 and c2 by config_db
      uvm_config_db#(config_obj)::set(this,"*","cfg",cfg);
	  
      //TODO-4.3
      //Please config the c1.var1=20, c2.var2=20 by config_db
      uvm_config_db#(int)::set(this,"c1","var1",10);
	  uvm_config_db#(int)::set(this,"c1.c2","var2",20);
      c1 = comp1::type_id::create("c1", this);
      `uvm_info("BUILD", "uvm_config_test build phase exited", UVM_LOW)
    endfunction
    task run_phase(uvm_phase phase);
      super.run_phase(phase);
      `uvm_info("RUN", "uvm_config_test run phase entered", UVM_LOW)
      phase.raise_objection(this);
      #1us;
      phase.drop_objection(this);
      `uvm_info("RUN", "uvm_config_test run phase exited", UVM_LOW)
    endtask
  endclass
endpackage

module uvm_config;

  import uvm_pkg::*;
  `include "uvm_macros.svh"
  import uvm_config_pkg::*;
  
  uvm_config_if if0();
  
  //TODO-4.1
  //Please set interface to the c1 and c2 in the environment
  initial begin
    uvm_config_db#(virtual uvm_config_if)::set(uvm_root::get(),"uvm_test_top.*","vif",if0);
    run_test(""); // empty test name
  end

endmodule

2)代码结构层次:实线代表componen 虚线代表object,橙色为变量

 3)代码运行结果

 

 4)总结:

(1)接口传递一定要在run_test之前;

(2)config_db操作要在c1、c2例化之前,例化前设置才能够创建实例后,将变量值设置进去。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值