电力电子转战数字IC20220729day59——uvm入门实验1

 

目录

实验目标

问题清单

UVM的核心基类有哪些?

什么是工厂?

工厂的注册、创建、覆盖机制是如何实现的?

什么是域的自动化?如何实现?

什么是uvm_object?

uvm_object有哪些方法可以使用?

具体地,对于方法compare如何写?uvm_pkg例化的对应全局数据操作配置成员是什么?

具体地,print呢?

什么是phase机制?

phase机制有哪些phase,执行顺序又是如何?

什么是config机制?

如何用config实现接口的传递(方式1)?

如何用config实现变量配置(方式2)?

如何用config实现对象配置(方式3)?

如何运行uvm仿真?

uvm的消息管理机制是怎么样的?

实验任务

1.1 在object_create中用多种方法创建对象

1.2 同上,在component_create

1.3 覆盖1.1,用bad_trans覆盖trans

1.4 覆盖1.2,用big_unit覆盖unit

2.1 在注册的时候,声明域的自动化

2.2 uvm_object::compare()

2.3 uvm_pkg中的全局控制对象uvm_default_comparer

2.5 2.6 uvm_object::print()和copy()

2.4 回调函数do_compare

3.1 定义comp中的4个phase

4.1 配置接口到c1和c2并检查是否得到

4.2 从test配置对象到c1和c2

4.3 在顶层uvm_config_test配置变量c1和c2中的var


实验目标

 

问题清单

UVM的核心基类有哪些?

  • factory类(2)
  • transaction类和sequence类(3)
  • 结构创建类(4)
  • 环境组件类env component(5)
  • 通信管道类(6)
  • 信息报告类(7)
  • 寄存器模型类(8)
  • 线程同步类(9)
  • 事务接口类(10)

什么是工厂?

  • 工厂是为了更方便的替换验证环境中的实例或注册了的类型,带来配置的灵活性

工厂的注册、创建、覆盖机制是如何实现的?

首先是`uvm_component_utils()注册;然后是new函数,第二个参数是parent,必须调用super.new();最后是build_phase()函数,也是必须调用super.build_phase(p)函数

  • 一旦注册,type_id::create()函数就可以通过uvm_factory::create_component_by_type()实现
class comp1 extends uvm_component;
`uvm_component_utils (comp1)//注册组件;new函数必须只有两个参数
function new (string name=:comp1", uvm_component parent=null);//parent是指上一层,当前实例是谁例化的,谁就是这个实例parent
	super.new(name, parent);//继承父类new函数
	$display($sformatf("%s is created", name));//已例化当前类
endfunction : new
function void build_phase (uvm_phase phase);
	super.build_phase (phase);
endfunction: build_phase
endclass

然后是利用工厂创建对象,也就是例化:

例化component用c2 = comp1::type_id::create ("c2",null);也是两个参数

例化object用o2 = obj1::type_id::create("o2");

class obj1 extends uvm_object;
`uvm_object_utils (obj1)
function new (string name="obj1");//object只有一个参数
	super.new(name);
	$display ($sformatf("%s is created",name));
endfunction: new
endclass

comp1 c1, c2;
obj1 o1,o2;
initial begin
c1 = new ("c1");//任何对象的例化最终都是通过new()函数来实现,sv的方法
o1 = new ("o1");
c2 = comp1::type_id::create ("c2",null);//这个也是例化的写法,factory提供的方法
o2 = obj1::type_id::create("o2");
end

最后就是覆盖了,两种覆盖方法如下

set_inst_override ( uvm_object_wrapper override_type, string inst_path);
//uvm_object_wrapper override_type是注册过后的某一个类在工厂中注册时的句柄,用new_type::get_type()找到

一般用这种 

set_type_override ( uvm_object_wrapper override_type);

覆盖机制只会影响通过工厂注册并且例化的对象

调用覆盖函数用comp2覆盖com1的函数如下

orig_type::type_id::set_type_override (new_type::get_type())
//typedef            静态函数               静态函数
//用new_type新类型替换原来的类型orig_type::type_id

例码如下.

module factory_override;
import uvm_pkg::*;//可直接import和include,编译器已经包含了
`inculde "uvm_macros.svh"

class comp1 extends uvm_component;//1声明
`uvm_component_utils(comp1)//2注册

function new (string name="comp1", uvm_component parent= null);//3new函数
	super.new(name, parent);
	$display ($sformatf("comp1::%s is created", name));
	endfunction

virtual function void hello (string name);//virtual是关键
	$display ( $sformatf("comp1:: %s is said hello!", name);
endfunction
endclass

class comp2 extends comp1;//要覆盖的类一定要继承于被覆盖的类
`uvm_component_utils(comp2)

function new (string name="comp2", uvm_component parent= null);
	super.new(name, parent);
	$display ($sformatf("comp2::%s is created", name));
	endfunction

function void hello (string name);
	$display ( $sformatf("comp2:: %s is said hello!", name);
endfunction
endclass

comp1 c1, c2;//两个句柄都是comp1的类型
initial begin
comp1::type_id::set_type_override (comp2::get_type());//调用覆盖函数,如上段例码
c1= new("c1");//例化c1(comp1),没有通过工厂。打印comp1::c1 is created,
c2= comp2::type_id::creare("c2",null);//工厂创建的对象,create返回一个comp2句柄给c2
//但是c2是comp1的句柄,却指向了comp2类型的对象。这里就是子类句柄覆盖父类句柄。所以必须是继承关系
//用工厂注册,就一定要用工厂来创建,达到便利的目的
//打印comp1::c2 is created,comp2::c2 is created
c1.hello("c1");//调用comp1的hello,打印 comp1::c1 is said hello
c2.hello("c2");//调用comp2的hello,打印 comp2::c2 is said hello
end

endmodule

什么是域的自动化?如何实现?

今后会参与到的对象拷贝、克隆、打印等操作的成员变量

注册的时候顺便声明,就可以直接使用uvm_object预定义的一些方法

class box extends uvm_object;
int volume=120;
color_t color = white;
string name= "box";
`uvm_object_utils_begin(box)//注册box的同时
	`uvm_filed_int(volume, UVM_ALL_ON)//声明了会参与到object数据操作的成员变量
	`uvm_filed_enum(color_t, color, UVM_ALL_ON)
	`uvm_filed_string(name, UVM_ALL_ON)//默认采取UVM_ALL_ON和UVM_DEFAULT,所有操作方法都打开
`uvm_object_utils_end
......
endclass

box b1, b2;
initial begin//声明过的成员变量将在数据操作时自动参与进来
b1 = new("box1");
b1.volume = 80;
b1.color = black;
b2 = new();
b2.copy(b1);//否则不会自动参与数据的操作,要自己定义数据操作方法
b2.name = "box2";
end

 域的类型及其对应的宏声明非常多,还有数据操作列表,这里有两个图,就省略了

什么是uvm_object?

见类库地图,几乎是所有核心基类的最顶层

uvm_object有哪些方法可以使用?

copy,clone,compare,pare,pack和unpack

关于复制的例码,句柄赋值给另一个句柄b2,此时两个句柄指向同一个对象box,在b2句柄中修改name,box中也被修改,打印出来的是同一个name

typedef enum {RED, WHITE, BLACK} color_t;
class box extends uvm_object;
	int volume=120;
	color_t color=WHITE;
	string name="box";
	`uvm_objext_utils(box)
	function new(string name="name");
		super.new(name);
		this.name=name;
	endfunction
endclass

initial begin
	b1=new("box1");
	b2=b1;
	b2.name="box2";
	$display("b1 name is %s", b1.name);
	$display("b2 name is %s", b2.name);
end

//结果如下
//b1 name is box2
//b2 name is box2

具体地,对于方法compare如何写?uvm_pkg例化的对应全局数据操作配置成员是什么?

function bit compare(uvm_object rhs, uvm_compare compare=null); 不做额外配置的话,第二个参数可以忽略,采用默认的比较配置

uvm_package::uvm_default_comparer 最大输出错误比较信息(show_max)是1,当错误发生后不再进行后续比较

如果不用默认,可以创建一个uvm_comparer对象,如下;也可以修改uvm_comparer对象

box b1, b2;
uvm_comparer cmpr;
initial begin
...
	cmpr=new();	
	cmpr.show_max=10;
	if(!b2.compare(b1)) begin
	... end

具体地,print呢?

调用uvm_object::print()函数时自动打印出来

全局对象:uvm_default_printer,d和p中间可以加上tree、line、table,打印的方式

字符串返回信息uvm_object::sprint(),自定义回调函数do_print()

什么是phase机制?

对于验证环境层次化,保证例化先后关系的机制

phase机制有哪些phase,执行顺序又是如何?

只有build是自顶向下的执行

只有uvm_component及其子类才会按照图中的顺序执行,component!!!

只有run_phase是task,可以耗时,可以完成一些等待、激励、采样的任务

runphase通常需要组织的序列:上电;复位;reg配置;发送主要测试内容;等待dut完成测试

run_phase还有12个分支phase(reset,config,main,shutdown及其前后),并行执行。不要用

什么是config机制?

为了验证环境的复用性,配置更细致的环境调节中的变量,在仿真时通过变量设置来修改环境。在不破坏原有结构的前提去改变验证环境。

uvm_config_db#(T)::set(uvm_component cntxt, string inst_name, string field_name, T value);
//                       传递一个实例句柄进来         实例名称       实例中的变量名     值
//第一个参数表示当前层次,如果是最高层可以是null,也可以uvm_root::get()
uvm_config_db#(T)::get(uvm_component cntxt, string inst_name, string field_name, inout T value);
  • 方法:uvm_config_db配置类,几种方便的变量设置方法
    • 使用方式1:传递virtual interface到环境中,连接软件和硬件世界
    • 使用方式2:设置单一变量值
    • 使用方式3:传递配置对象config object到环境
  • 先配置,后例化
  • 也就是,可以配置接口,可以配置变量,更可以配置对象

如何用config实现接口的传递(方式1)?

位置:在run_test()之前

类型:interface和virtual interface

例码如下:先声明接口,

interface intf1;
logic enable=0;
endinterface

class comp1 extends uvm_component;
	`uvm_componnet_utils(comp1)
	virtual intf1 vif;//拿到intf1的指针
	......
	function void build_phase (uvm_phase phase);
	if(!uvm_config_db#(virtual intf1)::get(this, "", "vif", vif)) begin
	//this表示当前的comp1(uvm_top.root.test.c1.vif),没有实例,变量是vif字符串要加“”,
	`uvm_error("GETVIF", "no virtual interface is assigned")
	end
	`uvm_info("SETVAL", $sformatf("vif.enable is %b befor set", vif.enable), UVM_LOW)
	vif.enable=1;
	`uvm_info("SETVAL", $sformatf("vif.enable is %b after set", vif.enable), UVM_LOW )
	endfunction
endclass

class test1 extends uvm_test;
	`uvm_component_utils(test1)
	comp1 c1;
	...
endclass

intf1 intf();
initial begin
uvm_config_db#(virtual intf1)::set(uvm_root::get(), "uvm_test_top.c1", "vif", intf);
//先set进intf1中,等下就get出来
run_test("test1");//root->test->c1->vif,分别对应set中的4个参数
end

如何用config实现变量配置(方式2)?

位置:build_phase

class comp1 extends uvm_component;
	`uvm_component_utils(comp1)
	int val1 = 1;
	string str1 = "null";
	......
	function void build_phase (uvm_phase phase);
		`uvm_info("SETVAL", $sformatf("val1 is %d before get", val1), UVM_LOW)
		`uvm_info("SETVAL", $sformatf("str1 is %s before get", str1), UVM_LOW)
		uvm_config_db#(int)::get(this, "", "val1", val1);//把配置好的get进来
		uvm_config_db#(string)::get(this, "", "str1", str1);
		`uvm_info("SETVAL", $sformatf("val1 is %d after get", val1), UVM_LOW)
		`uvm_info("SETVAL", $sformatf("str1 is %s after get", str1), UVM_LOW)
	endfunction

endclass

class test1 extends uvm_test;
`uvm_component_utils(test1)
comp1 c1;
......
function void build_phase (uvm_phase phase);
uvm_config_db#(int)::set(this, "c1", "val1", 100);//先set再例化
uvm_config_db#(string)::set(this, "c1", "str1", "comp1");
c1=comp1::type_id::create("c1", this);
endfunction
endclass

如何用config实现对象配置(方式3)?

目的:将需要配置的参数变量放到一个uvm_object中,一次配置完毕

位置:build_phase

class config1 extends uvm_object;
	int val1=1;
	int str1="null";
	`uvm_object_utils(config1)
	......
endclass

class comp1 extends uvm_component;
	`uvm_component_utils(comp1)
	config1 cfg;
	......
	function void build_phase(uvm_phase phase)
	uvm_object tmp;
	uvm_config_db#(uvm_object)::get(this, "", "cfg", tmp);//得到的tmp是父类句柄
	void'($cast(cfg, tmp));//传递的类型要保持一致!!
	`uvm_info("SETVAL", $sformatf("cfg.val1 is %d after get", cfg.val1), UVM_LOW)
	`uvm_info("SETVAL", $sformatf("cfg.str1 is %s after get", cfg.str1), UVM_LOW)
	endfunction
endclass

class test1 extends uvm_test;
	`uvm_component_utils(test1)
	comp1 c1,c2;
	config cfg1, cfg2;
	......
	function void build_phase(uvm_phase phase);
	cfg1= config1::type_id::create("cfg1");
	cfg2= config2::type_id::create("cfg2");
	cfg1.val1=30;
	cfg1.str1="c1";
	cfg2.val1=50;
	cfg2.str1="c2";
	uvm_config_db#(uvm_object)::set(this, "c1", "cfg", cfg1);//类型从int换成object
	uvm_config_db#(uvm_object)::set(this, "c2", "cfg", cfg2);
	c1=comp1::type_id::create("c1", this);
	c2=comp2::type_id::create("c2", this);
	endfunction
endclass

如何运行uvm仿真?

之前的SV实验使用的是$sformatf()系统函数

initial begin 
    t1 = new();
    t2 = new();
    tests["mcdf_data_consistence_basic_test"] = t1;
    tests["mcdf_full_random_test"] = t2;
    if($value$plusargs("TESTNAME=%s", name)) begin
      if(tests.exists(name)) begin
        tests[name].set_interface(chnl0_if, chnl1_if, chnl2_if, reg_if, arb_if, fmt_if, mcdf_if);
        tests[name].run();
      end
      else begin
        $fatal($sformatf("[ERRTEST], test name %s is invalid, please specify a valid name!", name));
      end
    end
    else begin
      $display("NO runtime optiont +TESTNAME=xxx is configured, and run default test mcdf_data_consistence_basic_test");
      tests["mcdf_data_consistence_basic_test"].set_interface(chnl0_if, chnl1_if, chnl2_if, reg_if, arb_if, fmt_if, mcdf_if);
      tests["mcdf_data_consistence_basic_test"].run();
    end
  end

方式1:通过uvm_pkg提供的全局函数run_test()来指定运行某一个uvm_test,都继承于uvm_test

方式2:就是上面例码的+UVM_TESTNAME=<test_name>

uvm的消息管理机制是怎么样的?

实验任务

1.1 在object_create中用多种方法创建对象

class trans extends uvm_object;
    bit[31:0] data;
    `uvm_object_utils(trans)
    function new(string name = "trans");
      super.new(name);
      `uvm_info("CREATE", $sformatf("trans type [%s] created", name), UVM_LOW)
    endfunction
  endclass

class object_create extends top;
    trans t1, t2, t3, t4;
    `uvm_component_utils(object_create)
    function new(string name = "object_create", uvm_component parent = null);
      super.new(name, parent);
    endfunction    
    function void build_phase(uvm_phase phase);
      uvm_factory f = uvm_factory::get(); // get singleton factory
      super.build_phase(phase);
t1 = new("t1"); // direct construction
t2 = trans::type_id::create("t2", this); // common method
void'($cast(t3,f.create_object_by_type(trans::get_type(), get_full_name(), "t3"))); 
// factory method用工厂提供的方法create_object_by_type()来创建对象
void'($cast(t4,create_object("trans", "t4"))); // 用component预定义的方法来创建对象
    endfunction
  endclass

1.2 同上,在component_create

class unit extends uvm_component;
    `uvm_component_utils(unit)
    function new(string name = "unit", uvm_component parent = null);
      super.new(name, parent);
      `uvm_info("CREATE", $sformatf("unit type [%s] created", name), UVM_LOW)
    endfunction
  endclass

class component_create extends top;
    unit u1, u2, u3, u4;
    `uvm_component_utils(component_create)
    function new(string name = "component_create", uvm_component parent = null);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      uvm_factory f = uvm_factory::get(); // get singleton factory
		  super.build_phase(phase);
u1 = new("u1"); // direct construction
u2 = unit::type_id::create("u2", this); // common method
void'($cast(u3,f.create_component_by_type(unit::get_type(), get_full_name(), "u3", this))); // factory method
void'($cast(u4,create_component("unit", "u4"))); // pre-defined method inside component
    endfunction
  endclass

1.3 覆盖1.1,用bad_trans覆盖trans

和上面的方法set_type_override ( uvm_object_wrapper override_type);有一点区别的是这里是用set_type_override_by_type ( uvm_object_wrapper override_type, new_type::get_type());

想要表示type类型都要调用原来类型中的::get_type()

class bad_trans extends trans;
    bit is_bad = 1;
    `uvm_object_utils(bad_trans)
    function new(string name = "trans");
      super.new(name);
      `uvm_info("CREATE", $sformatf("bad_trans type [%s] created", name), UVM_LOW)
    endfunction
  endclass

class object_override extends object_create;
    `uvm_component_utils(object_override)
    function new(string name = "object_override", uvm_component parent = null);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      set_type_override_by_type(trans::get_type(), bad_trans::get_type());
      super.build_phase(phase);
    endfunction
  endclass

1.4 覆盖1.2,用big_unit覆盖unit

class big_unit extends unit;
    bit is_big = 1;
    `uvm_component_utils(big_unit)
    function new(string name = "bit_unit", uvm_component parent = null);
      super.new(name, parent);
      `uvm_info("CREATE", $sformatf("big_unit type [%s] created", name), UVM_LOW)
    endfunction
  endclass

class component_override extends component_create;
    `uvm_component_utils(component_override)
    function new(string name = "component_override", uvm_component parent = null);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      set_type_override("unit", "big_unit");//!!!!!!!!!!!!!!!!!!!!!!
      super.build_phase(phase);
    endfunction
  endclass

2.1 在注册的时候,声明域的自动化

class trans extends uvm_object;
    bit[31:0] addr;
    bit[31:0] data;
    op_t op;
    string name;
    `uvm_object_utils_begin(trans)
      `uvm_field_int(addr, UVM_ALL_ON)
      `uvm_field_int(data, UVM_ALL_ON)
      `uvm_field_enum(op_t, op, UVM_ALL_ON)
      `uvm_field_string(name, UVM_ALL_ON)
    `uvm_object_utils_end

2.2 uvm_object::compare()

function bit compare (uvm_object rhs, uvm_comparer comparer=null)

直接调用对应对象.compare(待比较对象句柄)

2.3 uvm_pkg中的全局控制对象uvm_default_comparer

2.5 2.6 uvm_object::print()和copy()

class object_methods_test extends uvm_test;
    `uvm_component_utils(object_methods_test)
    function new(string name = "object_methods_test", uvm_component parent = null);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
    endfunction
    task run_phase(uvm_phase phase);
      trans t1, t2;
      bit is_equal;
      phase.raise_objection(this);
      t1 = trans::type_id::create("t1");
      t1.data = 'h1FF;
      t1.addr = 'hF100;
      t1.op = WRITE;
      t1.name = "t1";
      t2 = trans::type_id::create("t2");
      t2.data = 'h2FF;
      t2.addr = 'hF200;
      t2.op = WRITE;
	    t2.name = "t2";
  is_equal = t1.compare(t2);//调用比较函数
  uvm_default_comparer.show_max = 10;//通过全局控制对象设置最大比较次数
  is_equal = t1.compare(t2);
  
  if(!is_equal)
    `uvm_warning("CMPERR", "t1 is not equal to t2")
  else
    `uvm_info("CMPERR", "t1 is equal to t2", UVM_LOW)
    
  `uvm_info("COPY", "Before uvm_object copy() taken", UVM_LOW)
  t1.print();
  t2.print();
  `uvm_info("COPY", "After uvm_object t2 is copied to t1", UVM_LOW)
  t1.copy(t2);//也是直接调用即可
  t1.print();
  t2.print();
  `uvm_info("CMP", "Compare t1 and t2", UVM_LOW)
  is_equal = t1.compare(t2);
  if(!is_equal)
    `uvm_warning("CMPERR", "t1 is not equal to t2")
  else
    `uvm_info("CMPERR", "t1 is equal to t2", UVM_LOW)       
  
  #1us;
      phase.drop_objection(this);
    endtask
  endclass

2.4 回调函数do_compare

typedef enum {WRITE, READ, IDLE} op_t;  

  class trans extends uvm_object;
    bit[31:0] addr;
    bit[31:0] data;
    op_t op;
    string name;
    `uvm_object_utils_begin(trans)
      `uvm_field_int(addr, UVM_ALL_ON)
      `uvm_field_int(data, UVM_ALL_ON)
      `uvm_field_enum(op_t, op, UVM_ALL_ON)
      `uvm_field_string(name, UVM_ALL_ON)
    `uvm_object_utils_end
    function new(string name = "trans");
      super.new(name);
      `uvm_info("CREATE", $sformatf("trans type [%s] created", name), UVM_LOW)
    endfunction
//自定义回调函数,在上面的代码中执行完compare立即会执行以下的do_compare
function bit do_compare(uvm_object rhs, uvm_comparer comparer);
trans t;
do_compare = 1;
void'($cast(t, rhs));
if(addr != t.addr) begin
  do_compare = 0;
  `uvm_warning("CMPERR", $sformatf("addr %8x != %8x", addr, t.addr))
end
if(data != t.data) begin
  do_compare = 0;
  `uvm_warning("CMPERR", $sformatf("data %8x != %8x", data, t.data))
end
if(op != t.op) begin
  do_compare = 0;
  `uvm_warning("CMPERR", $sformatf("op %s != %8x", op, t.op))
end
if(addr != t.addr) begin
  do_compare = 0;
  `uvm_warning("CMPERR", $sformatf("name %8x != %8x", name, t.name))
end
endfunction
  endclass

3.1 定义comp中的4个phase

build_phase中例化对象

class comp2 extends uvm_component;
    `uvm_component_utils(comp2)
    function new(string name = "comp2", uvm_component parent = null);
      super.new(name, parent);
      `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)
      `uvm_info("BUILD", "comp2 build phase exited", UVM_LOW)
    endfunction
    function void connect_phase(uvm_phase phase);
      super.connect_phase(phase);
      `uvm_info("CONNECT", "comp2 connect phase entered", UVM_LOW)
      `uvm_info("CONNECT", "comp2 connect phase exited", UVM_LOW)
    endfunction
    task run_phase(uvm_phase phase);
      super.run_phase(phase);
      `uvm_info("RUN", "comp2 run phase entered", UVM_LOW)
      `uvm_info("RUN", "comp2 run phase entered", UVM_LOW)
    endtask
    function void report_phase(uvm_phase phase);
      super.report_phase(phase);
      `uvm_info("REPORT", "comp2 report phase entered", UVM_LOW)
      `uvm_info("REPORT", "comp2 report phase exited", UVM_LOW)   
    endfunction
  endclass
  
  class comp3 extends uvm_component;
    `uvm_component_utils(comp3)
    function new(string name = "comp3", uvm_component parent = null);
      super.new(name, parent);
      `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", "comp3 build phase entered", UVM_LOW)
      `uvm_info("BUILD", "comp3 build phase exited", UVM_LOW)
    endfunction
    function void connect_phase(uvm_phase phase);
      super.connect_phase(phase);
      `uvm_info("CONNECT", "comp3 connect phase entered", UVM_LOW)
      `uvm_info("CONNECT", "comp3 connect phase exited", UVM_LOW)
    endfunction
    task run_phase(uvm_phase phase);
      super.run_phase(phase);
      `uvm_info("RUN", "comp3 run phase entered", UVM_LOW)
      `uvm_info("RUN", "comp3 run phase entered", UVM_LOW)
    endtask
    function void report_phase(uvm_phase phase);
      super.report_phase(phase);
      `uvm_info("REPORT", "comp3 report phase entered", UVM_LOW)
      `uvm_info("REPORT", "comp3 report phase exited", UVM_LOW)   
    endfunction
  endclass
  
  class comp1 extends uvm_component;
    comp2 c2;
    comp3 c3;
    `uvm_component_utils(comp1)
    function new(string name = "comp1", uvm_component parent = null);
      super.new(name, parent);
      `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)
      c2 = comp2::type_id::create("c2", this);
      c3 = comp3::type_id::create("c3", this);
      `uvm_info("BUILD", "comp1 build phase exited", UVM_LOW)
    endfunction
    function void connect_phase(uvm_phase phase);
      super.connect_phase(phase);
      `uvm_info("CONNECT", "comp1 connect phase entered", UVM_LOW)
      `uvm_info("CONNECT", "comp1 connect phase exited", UVM_LOW)
    endfunction
    task run_phase(uvm_phase phase);
      super.run_phase(phase);
      `uvm_info("RUN", "comp1 run phase entered", UVM_LOW)
      `uvm_info("RUN", "comp1 run phase entered", UVM_LOW)
    endtask
    function void report_phase(uvm_phase phase);
      super.report_phase(phase);
      `uvm_info("REPORT", "comp1 report phase entered", UVM_LOW)
      `uvm_info("REPORT", "comp1 report phase exited", UVM_LOW)   
    endfunction
  endclass

4.1 配置接口到c1和c2并检查是否得到

4.2 从test配置对象到c1和c2

4.3 在顶层uvm_config_test配置变量c1和c2中的var

在顶层test中set

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;
//在这里配置
uvm_config_db#(config_obj)::set(this, "*", "cfg", cfg);
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

在对应的class中get

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)
//配置接口
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)
//配置变量
uvm_config_db#(int)::get(this, "", "var2", var2);
      `uvm_info("GETINT", $sformatf("after config get, var2 = %0d", var2), UVM_LOW)
     
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)
      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, var1 = %0d", var1), UVM_LOW)
      uvm_config_db#(int)::get(this, "", "var1", var1);
      `uvm_info("GETINT", $sformatf("after config get, var1 = %0d", var1), UVM_LOW)
      
      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
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值