• 电力电子转战数字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()实现
    1. class comp1 extends uvm_component;
    2. `uvm_component_utils (comp1)//注册组件;new函数必须只有两个参数
    3. function new (string name=:comp1", uvm_component parent=null);//parent是指上一层,当前实例是谁例化的,谁就是这个实例parent
    4. super.new(name, parent);//继承父类new函数
    5. $display($sformatf("%s is created", name));//已例化当前类
    6. endfunction : new
    7. function void build_phase (uvm_phase phase);
    8. super.build_phase (phase);
    9. endfunction: build_phase
    10. endclass

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

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

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

    1. class obj1 extends uvm_object;
    2. `uvm_object_utils (obj1)
    3. function new (string name="obj1");//object只有一个参数
    4. super.new(name);
    5. $display ($sformatf("%s is created",name));
    6. endfunction: new
    7. endclass
    8. comp1 c1, c2;
    9. obj1 o1,o2;
    10. initial begin
    11. c1 = new ("c1");//任何对象的例化最终都是通过new()函数来实现,sv的方法
    12. o1 = new ("o1");
    13. c2 = comp1::type_id::create ("c2",null);//这个也是例化的写法,factory提供的方法
    14. o2 = obj1::type_id::create("o2");
    15. end

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

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

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

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

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

    例码如下.

    1. module factory_override;
    2. import uvm_pkg::*;//可直接import和include,编译器已经包含了
    3. `inculde "uvm_macros.svh"
    4. class comp1 extends uvm_component;//1声明
    5. `uvm_component_utils(comp1)//2注册
    6. function new (string name="comp1", uvm_component parent= null);//3new函数
    7. super.new(name, parent);
    8. $display ($sformatf("comp1::%s is created", name));
    9. endfunction
    10. virtual function void hello (string name);//virtual是关键
    11. $display ( $sformatf("comp1:: %s is said hello!", name);
    12. endfunction
    13. endclass
    14. class comp2 extends comp1;//要覆盖的类一定要继承于被覆盖的类
    15. `uvm_component_utils(comp2)
    16. function new (string name="comp2", uvm_component parent= null);
    17. super.new(name, parent);
    18. $display ($sformatf("comp2::%s is created", name));
    19. endfunction
    20. function void hello (string name);
    21. $display ( $sformatf("comp2:: %s is said hello!", name);
    22. endfunction
    23. endclass
    24. comp1 c1, c2;//两个句柄都是comp1的类型
    25. initial begin
    26. comp1::type_id::set_type_override (comp2::get_type());//调用覆盖函数,如上段例码
    27. c1= new("c1");//例化c1(comp1),没有通过工厂。打印comp1::c1 is created,
    28. c2= comp2::type_id::creare("c2",null);//工厂创建的对象,create返回一个comp2句柄给c2
    29. //但是c2是comp1的句柄,却指向了comp2类型的对象。这里就是子类句柄覆盖父类句柄。所以必须是继承关系
    30. //用工厂注册,就一定要用工厂来创建,达到便利的目的
    31. //打印comp1::c2 is created,comp2::c2 is created
    32. c1.hello("c1");//调用comp1的hello,打印 comp1::c1 is said hello
    33. c2.hello("c2");//调用comp2的hello,打印 comp2::c2 is said hello
    34. end
    35. endmodule

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

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

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

    1. class box extends uvm_object;
    2. int volume=120;
    3. color_t color = white;
    4. string name= "box";
    5. `uvm_object_utils_begin(box)//注册box的同时
    6. `uvm_filed_int(volume, UVM_ALL_ON)//声明了会参与到object数据操作的成员变量
    7. `uvm_filed_enum(color_t, color, UVM_ALL_ON)
    8. `uvm_filed_string(name, UVM_ALL_ON)//默认采取UVM_ALL_ON和UVM_DEFAULT,所有操作方法都打开
    9. `uvm_object_utils_end
    10. ......
    11. endclass
    12. box b1, b2;
    13. initial begin//声明过的成员变量将在数据操作时自动参与进来
    14. b1 = new("box1");
    15. b1.volume = 80;
    16. b1.color = black;
    17. b2 = new();
    18. b2.copy(b1);//否则不会自动参与数据的操作,要自己定义数据操作方法
    19. b2.name = "box2";
    20. end

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

    什么是uvm_object?

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

    uvm_object有哪些方法可以使用?

    copy,clone,compare,pare,pack和unpack

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

    1. typedef enum {RED, WHITE, BLACK} color_t;
    2. class box extends uvm_object;
    3. int volume=120;
    4. color_t color=WHITE;
    5. string name="box";
    6. `uvm_objext_utils(box)
    7. function new(string name="name");
    8. super.new(name);
    9. this.name=name;
    10. endfunction
    11. endclass
    12. initial begin
    13. b1=new("box1");
    14. b2=b1;
    15. b2.name="box2";
    16. $display("b1 name is %s", b1.name);
    17. $display("b2 name is %s", b2.name);
    18. end
    19. //结果如下
    20. //b1 name is box2
    21. //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对象

    1. box b1, b2;
    2. uvm_comparer cmpr;
    3. initial begin
    4. ...
    5. cmpr=new();
    6. cmpr.show_max=10;
    7. if(!b2.compare(b1)) begin
    8. ... 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机制?

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

    1. uvm_config_db#(T)::set(uvm_component cntxt, string inst_name, string field_name, T value);
    2. // 传递一个实例句柄进来 实例名称 实例中的变量名 值
    3. //第一个参数表示当前层次,如果是最高层可以是null,也可以uvm_root::get()
    4. 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

    例码如下:先声明接口,

    1. interface intf1;
    2. logic enable=0;
    3. endinterface
    4. class comp1 extends uvm_component;
    5. `uvm_componnet_utils(comp1)
    6. virtual intf1 vif;//拿到intf1的指针
    7. ......
    8. function void build_phase (uvm_phase phase);
    9. if(!uvm_config_db#(virtual intf1)::get(this, "", "vif", vif)) begin
    10. //this表示当前的comp1(uvm_top.root.test.c1.vif),没有实例,变量是vif字符串要加“”,
    11. `uvm_error("GETVIF", "no virtual interface is assigned")
    12. end
    13. `uvm_info("SETVAL", $sformatf("vif.enable is %b befor set", vif.enable), UVM_LOW)
    14. vif.enable=1;
    15. `uvm_info("SETVAL", $sformatf("vif.enable is %b after set", vif.enable), UVM_LOW )
    16. endfunction
    17. endclass
    18. class test1 extends uvm_test;
    19. `uvm_component_utils(test1)
    20. comp1 c1;
    21. ...
    22. endclass
    23. intf1 intf();
    24. initial begin
    25. uvm_config_db#(virtual intf1)::set(uvm_root::get(), "uvm_test_top.c1", "vif", intf);
    26. //先set进intf1中,等下就get出来
    27. run_test("test1");//root->test->c1->vif,分别对应set中的4个参数
    28. end

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

    位置:build_phase

    1. class comp1 extends uvm_component;
    2. `uvm_component_utils(comp1)
    3. int val1 = 1;
    4. string str1 = "null";
    5. ......
    6. function void build_phase (uvm_phase phase);
    7. `uvm_info("SETVAL", $sformatf("val1 is %d before get", val1), UVM_LOW)
    8. `uvm_info("SETVAL", $sformatf("str1 is %s before get", str1), UVM_LOW)
    9. uvm_config_db#(int)::get(this, "", "val1", val1);//把配置好的get进来
    10. uvm_config_db#(string)::get(this, "", "str1", str1);
    11. `uvm_info("SETVAL", $sformatf("val1 is %d after get", val1), UVM_LOW)
    12. `uvm_info("SETVAL", $sformatf("str1 is %s after get", str1), UVM_LOW)
    13. endfunction
    14. endclass
    15. class test1 extends uvm_test;
    16. `uvm_component_utils(test1)
    17. comp1 c1;
    18. ......
    19. function void build_phase (uvm_phase phase);
    20. uvm_config_db#(int)::set(this, "c1", "val1", 100);//先set再例化
    21. uvm_config_db#(string)::set(this, "c1", "str1", "comp1");
    22. c1=comp1::type_id::create("c1", this);
    23. endfunction
    24. endclass

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

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

    位置:build_phase

    1. class config1 extends uvm_object;
    2. int val1=1;
    3. int str1="null";
    4. `uvm_object_utils(config1)
    5. ......
    6. endclass
    7. class comp1 extends uvm_component;
    8. `uvm_component_utils(comp1)
    9. config1 cfg;
    10. ......
    11. function void build_phase(uvm_phase phase)
    12. uvm_object tmp;
    13. uvm_config_db#(uvm_object)::get(this, "", "cfg", tmp);//得到的tmp是父类句柄
    14. void'($cast(cfg, tmp));//传递的类型要保持一致!!
    15. `uvm_info("SETVAL", $sformatf("cfg.val1 is %d after get", cfg.val1), UVM_LOW)
    16. `uvm_info("SETVAL", $sformatf("cfg.str1 is %s after get", cfg.str1), UVM_LOW)
    17. endfunction
    18. endclass
    19. class test1 extends uvm_test;
    20. `uvm_component_utils(test1)
    21. comp1 c1,c2;
    22. config cfg1, cfg2;
    23. ......
    24. function void build_phase(uvm_phase phase);
    25. cfg1= config1::type_id::create("cfg1");
    26. cfg2= config2::type_id::create("cfg2");
    27. cfg1.val1=30;
    28. cfg1.str1="c1";
    29. cfg2.val1=50;
    30. cfg2.str1="c2";
    31. uvm_config_db#(uvm_object)::set(this, "c1", "cfg", cfg1);//类型从int换成object
    32. uvm_config_db#(uvm_object)::set(this, "c2", "cfg", cfg2);
    33. c1=comp1::type_id::create("c1", this);
    34. c2=comp2::type_id::create("c2", this);
    35. endfunction
    36. endclass

    如何运行uvm仿真?

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

    1. initial begin
    2. t1 = new();
    3. t2 = new();
    4. tests["mcdf_data_consistence_basic_test"] = t1;
    5. tests["mcdf_full_random_test"] = t2;
    6. if($value$plusargs("TESTNAME=%s", name)) begin
    7. if(tests.exists(name)) begin
    8. tests[name].set_interface(chnl0_if, chnl1_if, chnl2_if, reg_if, arb_if, fmt_if, mcdf_if);
    9. tests[name].run();
    10. end
    11. else begin
    12. $fatal($sformatf("[ERRTEST], test name %s is invalid, please specify a valid name!", name));
    13. end
    14. end
    15. else begin
    16. $display("NO runtime optiont +TESTNAME=xxx is configured, and run default test mcdf_data_consistence_basic_test");
    17. tests["mcdf_data_consistence_basic_test"].set_interface(chnl0_if, chnl1_if, chnl2_if, reg_if, arb_if, fmt_if, mcdf_if);
    18. tests["mcdf_data_consistence_basic_test"].run();
    19. end
    20. end

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

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

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

    实验任务

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

    1. class trans extends uvm_object;
    2. bit[31:0] data;
    3. `uvm_object_utils(trans)
    4. function new(string name = "trans");
    5. super.new(name);
    6. `uvm_info("CREATE", $sformatf("trans type [%s] created", name), UVM_LOW)
    7. endfunction
    8. endclass
    9. class object_create extends top;
    10. trans t1, t2, t3, t4;
    11. `uvm_component_utils(object_create)
    12. function new(string name = "object_create", uvm_component parent = null);
    13. super.new(name, parent);
    14. endfunction
    15. function void build_phase(uvm_phase phase);
    16. uvm_factory f = uvm_factory::get(); // get singleton factory
    17. super.build_phase(phase);
    18. t1 = new("t1"); // direct construction
    19. t2 = trans::type_id::create("t2", this); // common method
    20. void'($cast(t3,f.create_object_by_type(trans::get_type(), get_full_name(), "t3")));
    21. // factory method用工厂提供的方法create_object_by_type()来创建对象
    22. void'($cast(t4,create_object("trans", "t4"))); // 用component预定义的方法来创建对象
    23. endfunction
    24. endclass

    1.2 同上,在component_create

    1. class unit extends uvm_component;
    2. `uvm_component_utils(unit)
    3. function new(string name = "unit", uvm_component parent = null);
    4. super.new(name, parent);
    5. `uvm_info("CREATE", $sformatf("unit type [%s] created", name), UVM_LOW)
    6. endfunction
    7. endclass
    8. class component_create extends top;
    9. unit u1, u2, u3, u4;
    10. `uvm_component_utils(component_create)
    11. function new(string name = "component_create", uvm_component parent = null);
    12. super.new(name, parent);
    13. endfunction
    14. function void build_phase(uvm_phase phase);
    15. uvm_factory f = uvm_factory::get(); // get singleton factory
    16. super.build_phase(phase);
    17. u1 = new("u1"); // direct construction
    18. u2 = unit::type_id::create("u2", this); // common method
    19. void'($cast(u3,f.create_component_by_type(unit::get_type(), get_full_name(), "u3", this))); // factory method
    20. void'($cast(u4,create_component("unit", "u4"))); // pre-defined method inside component
    21. endfunction
    22. 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()

    1. class bad_trans extends trans;
    2. bit is_bad = 1;
    3. `uvm_object_utils(bad_trans)
    4. function new(string name = "trans");
    5. super.new(name);
    6. `uvm_info("CREATE", $sformatf("bad_trans type [%s] created", name), UVM_LOW)
    7. endfunction
    8. endclass
    9. class object_override extends object_create;
    10. `uvm_component_utils(object_override)
    11. function new(string name = "object_override", uvm_component parent = null);
    12. super.new(name, parent);
    13. endfunction
    14. function void build_phase(uvm_phase phase);
    15. set_type_override_by_type(trans::get_type(), bad_trans::get_type());
    16. super.build_phase(phase);
    17. endfunction
    18. endclass

    1.4 覆盖1.2,用big_unit覆盖unit

    1. class big_unit extends unit;
    2. bit is_big = 1;
    3. `uvm_component_utils(big_unit)
    4. function new(string name = "bit_unit", uvm_component parent = null);
    5. super.new(name, parent);
    6. `uvm_info("CREATE", $sformatf("big_unit type [%s] created", name), UVM_LOW)
    7. endfunction
    8. endclass
    9. class component_override extends component_create;
    10. `uvm_component_utils(component_override)
    11. function new(string name = "component_override", uvm_component parent = null);
    12. super.new(name, parent);
    13. endfunction
    14. function void build_phase(uvm_phase phase);
    15. set_type_override("unit", "big_unit");//!!!!!!!!!!!!!!!!!!!!!!
    16. super.build_phase(phase);
    17. endfunction
    18. endclass

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

    1. class trans extends uvm_object;
    2. bit[31:0] addr;
    3. bit[31:0] data;
    4. op_t op;
    5. string name;
    6. `uvm_object_utils_begin(trans)
    7. `uvm_field_int(addr, UVM_ALL_ON)
    8. `uvm_field_int(data, UVM_ALL_ON)
    9. `uvm_field_enum(op_t, op, UVM_ALL_ON)
    10. `uvm_field_string(name, UVM_ALL_ON)
    11. `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()

    1. class object_methods_test extends uvm_test;
    2. `uvm_component_utils(object_methods_test)
    3. function new(string name = "object_methods_test", uvm_component parent = null);
    4. super.new(name, parent);
    5. endfunction
    6. function void build_phase(uvm_phase phase);
    7. super.build_phase(phase);
    8. endfunction
    9. task run_phase(uvm_phase phase);
    10. trans t1, t2;
    11. bit is_equal;
    12. phase.raise_objection(this);
    13. t1 = trans::type_id::create("t1");
    14. t1.data = 'h1FF;
    15. t1.addr = 'hF100;
    16. t1.op = WRITE;
    17. t1.name = "t1";
    18. t2 = trans::type_id::create("t2");
    19. t2.data = 'h2FF;
    20. t2.addr = 'hF200;
    21. t2.op = WRITE;
    22. t2.name = "t2";
    23. is_equal = t1.compare(t2);//调用比较函数
    24. uvm_default_comparer.show_max = 10;//通过全局控制对象设置最大比较次数
    25. is_equal = t1.compare(t2);
    26. if(!is_equal)
    27. `uvm_warning("CMPERR", "t1 is not equal to t2")
    28. else
    29. `uvm_info("CMPERR", "t1 is equal to t2", UVM_LOW)
    30. `uvm_info("COPY", "Before uvm_object copy() taken", UVM_LOW)
    31. t1.print();
    32. t2.print();
    33. `uvm_info("COPY", "After uvm_object t2 is copied to t1", UVM_LOW)
    34. t1.copy(t2);//也是直接调用即可
    35. t1.print();
    36. t2.print();
    37. `uvm_info("CMP", "Compare t1 and t2", UVM_LOW)
    38. is_equal = t1.compare(t2);
    39. if(!is_equal)
    40. `uvm_warning("CMPERR", "t1 is not equal to t2")
    41. else
    42. `uvm_info("CMPERR", "t1 is equal to t2", UVM_LOW)
    43. #1us;
    44. phase.drop_objection(this);
    45. endtask
    46. endclass

    2.4 回调函数do_compare

    1. typedef enum {WRITE, READ, IDLE} op_t;
    2. class trans extends uvm_object;
    3. bit[31:0] addr;
    4. bit[31:0] data;
    5. op_t op;
    6. string name;
    7. `uvm_object_utils_begin(trans)
    8. `uvm_field_int(addr, UVM_ALL_ON)
    9. `uvm_field_int(data, UVM_ALL_ON)
    10. `uvm_field_enum(op_t, op, UVM_ALL_ON)
    11. `uvm_field_string(name, UVM_ALL_ON)
    12. `uvm_object_utils_end
    13. function new(string name = "trans");
    14. super.new(name);
    15. `uvm_info("CREATE", $sformatf("trans type [%s] created", name), UVM_LOW)
    16. endfunction
    17. //自定义回调函数,在上面的代码中执行完compare立即会执行以下的do_compare
    18. function bit do_compare(uvm_object rhs, uvm_comparer comparer);
    19. trans t;
    20. do_compare = 1;
    21. void'($cast(t, rhs));
    22. if(addr != t.addr) begin
    23. do_compare = 0;
    24. `uvm_warning("CMPERR", $sformatf("addr %8x != %8x", addr, t.addr))
    25. end
    26. if(data != t.data) begin
    27. do_compare = 0;
    28. `uvm_warning("CMPERR", $sformatf("data %8x != %8x", data, t.data))
    29. end
    30. if(op != t.op) begin
    31. do_compare = 0;
    32. `uvm_warning("CMPERR", $sformatf("op %s != %8x", op, t.op))
    33. end
    34. if(addr != t.addr) begin
    35. do_compare = 0;
    36. `uvm_warning("CMPERR", $sformatf("name %8x != %8x", name, t.name))
    37. end
    38. endfunction
    39. endclass

    3.1 定义comp中的4个phase

    build_phase中例化对象

    1. class comp2 extends uvm_component;
    2. `uvm_component_utils(comp2)
    3. function new(string name = "comp2", uvm_component parent = null);
    4. super.new(name, parent);
    5. `uvm_info("CREATE", $sformatf("unit type [%s] created", name), UVM_LOW)
    6. endfunction
    7. function void build_phase(uvm_phase phase);
    8. super.build_phase(phase);
    9. `uvm_info("BUILD", "comp2 build phase entered", UVM_LOW)
    10. `uvm_info("BUILD", "comp2 build phase exited", UVM_LOW)
    11. endfunction
    12. function void connect_phase(uvm_phase phase);
    13. super.connect_phase(phase);
    14. `uvm_info("CONNECT", "comp2 connect phase entered", UVM_LOW)
    15. `uvm_info("CONNECT", "comp2 connect phase exited", UVM_LOW)
    16. endfunction
    17. task run_phase(uvm_phase phase);
    18. super.run_phase(phase);
    19. `uvm_info("RUN", "comp2 run phase entered", UVM_LOW)
    20. `uvm_info("RUN", "comp2 run phase entered", UVM_LOW)
    21. endtask
    22. function void report_phase(uvm_phase phase);
    23. super.report_phase(phase);
    24. `uvm_info("REPORT", "comp2 report phase entered", UVM_LOW)
    25. `uvm_info("REPORT", "comp2 report phase exited", UVM_LOW)
    26. endfunction
    27. endclass
    28. class comp3 extends uvm_component;
    29. `uvm_component_utils(comp3)
    30. function new(string name = "comp3", uvm_component parent = null);
    31. super.new(name, parent);
    32. `uvm_info("CREATE", $sformatf("unit type [%s] created", name), UVM_LOW)
    33. endfunction
    34. function void build_phase(uvm_phase phase);
    35. super.build_phase(phase);
    36. `uvm_info("BUILD", "comp3 build phase entered", UVM_LOW)
    37. `uvm_info("BUILD", "comp3 build phase exited", UVM_LOW)
    38. endfunction
    39. function void connect_phase(uvm_phase phase);
    40. super.connect_phase(phase);
    41. `uvm_info("CONNECT", "comp3 connect phase entered", UVM_LOW)
    42. `uvm_info("CONNECT", "comp3 connect phase exited", UVM_LOW)
    43. endfunction
    44. task run_phase(uvm_phase phase);
    45. super.run_phase(phase);
    46. `uvm_info("RUN", "comp3 run phase entered", UVM_LOW)
    47. `uvm_info("RUN", "comp3 run phase entered", UVM_LOW)
    48. endtask
    49. function void report_phase(uvm_phase phase);
    50. super.report_phase(phase);
    51. `uvm_info("REPORT", "comp3 report phase entered", UVM_LOW)
    52. `uvm_info("REPORT", "comp3 report phase exited", UVM_LOW)
    53. endfunction
    54. endclass
    55. class comp1 extends uvm_component;
    56. comp2 c2;
    57. comp3 c3;
    58. `uvm_component_utils(comp1)
    59. function new(string name = "comp1", uvm_component parent = null);
    60. super.new(name, parent);
    61. `uvm_info("CREATE", $sformatf("unit type [%s] created", name), UVM_LOW)
    62. endfunction
    63. function void build_phase(uvm_phase phase);
    64. super.build_phase(phase);
    65. `uvm_info("BUILD", "comp1 build phase entered", UVM_LOW)
    66. c2 = comp2::type_id::create("c2", this);
    67. c3 = comp3::type_id::create("c3", this);
    68. `uvm_info("BUILD", "comp1 build phase exited", UVM_LOW)
    69. endfunction
    70. function void connect_phase(uvm_phase phase);
    71. super.connect_phase(phase);
    72. `uvm_info("CONNECT", "comp1 connect phase entered", UVM_LOW)
    73. `uvm_info("CONNECT", "comp1 connect phase exited", UVM_LOW)
    74. endfunction
    75. task run_phase(uvm_phase phase);
    76. super.run_phase(phase);
    77. `uvm_info("RUN", "comp1 run phase entered", UVM_LOW)
    78. `uvm_info("RUN", "comp1 run phase entered", UVM_LOW)
    79. endtask
    80. function void report_phase(uvm_phase phase);
    81. super.report_phase(phase);
    82. `uvm_info("REPORT", "comp1 report phase entered", UVM_LOW)
    83. `uvm_info("REPORT", "comp1 report phase exited", UVM_LOW)
    84. endfunction
    85. endclass

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

    4.2 从test配置对象到c1和c2

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

    在顶层test中set

    1. class uvm_config_test extends uvm_test;
    2. comp1 c1;
    3. config_obj cfg;
    4. `uvm_component_utils(uvm_config_test)
    5. function new(string name = "uvm_config_test", uvm_component parent = null);
    6. super.new(name, parent);
    7. endfunction
    8. function void build_phase(uvm_phase phase);
    9. super.build_phase(phase);
    10. `uvm_info("BUILD", "uvm_config_test build phase entered", UVM_LOW)
    11. cfg = config_obj::type_id::create("cfg");
    12. cfg.comp1_var = 100;
    13. cfg.comp2_var = 200;
    14. //在这里配置
    15. uvm_config_db#(config_obj)::set(this, "*", "cfg", cfg);
    16. uvm_config_db#(int)::set(this, "c1", "var1", 10);
    17. uvm_config_db#(int)::set(this, "c1.c2", "var2", 20);
    18. c1 = comp1::type_id::create("c1", this);
    19. `uvm_info("BUILD", "uvm_config_test build phase exited", UVM_LOW)
    20. endfunction
    21. task run_phase(uvm_phase phase);
    22. super.run_phase(phase);
    23. `uvm_info("RUN", "uvm_config_test run phase entered", UVM_LOW)
    24. phase.raise_objection(this);
    25. #1us;
    26. phase.drop_objection(this);
    27. `uvm_info("RUN", "uvm_config_test run phase exited", UVM_LOW)
    28. endtask
    29. endclass

    在对应的class中get

    1. class config_obj extends uvm_object;
    2. int comp1_var;
    3. int comp2_var;
    4. `uvm_object_utils(config_obj)
    5. function new(string name = "config_obj");
    6. super.new(name);
    7. `uvm_info("CREATE", $sformatf("config_obj type [%s] created", name), UVM_LOW)
    8. endfunction
    9. endclass
    10. class comp2 extends uvm_component;
    11. int var2;
    12. virtual uvm_config_if vif;
    13. config_obj cfg;
    14. `uvm_component_utils(comp2)
    15. function new(string name = "comp2", uvm_component parent = null);
    16. super.new(name, parent);
    17. var2 = 200;
    18. `uvm_info("CREATE", $sformatf("unit type [%s] created", name), UVM_LOW)
    19. endfunction
    20. function void build_phase(uvm_phase phase);
    21. super.build_phase(phase);
    22. `uvm_info("BUILD", "comp2 build phase entered", UVM_LOW)
    23. //配置接口
    24. if(!uvm_config_db#(virtual uvm_config_if)::get(this, "", "vif", vif))
    25. `uvm_error("GETVIF", "no virtual interface is assigned")
    26. `uvm_info("GETINT", $sformatf("before config get, var2 = %0d", var2), UVM_LOW)
    27. //配置变量
    28. uvm_config_db#(int)::get(this, "", "var2", var2);
    29. `uvm_info("GETINT", $sformatf("after config get, var2 = %0d", var2), UVM_LOW)
    30. uvm_config_db#(config_obj)::get(this, "", "cfg", cfg);
    31. `uvm_info("GETOBJ", $sformatf("after config get, cfg.comp2_var = %0d", cfg.comp2_var), UVM_LOW)
    32. `uvm_info("BUILD", "comp2 build phase exited", UVM_LOW)
    33. endfunction
    34. endclass
    35. class comp1 extends uvm_component;
    36. int var1;
    37. comp2 c2;
    38. config_obj cfg;
    39. virtual uvm_config_if vif;
    40. `uvm_component_utils(comp1)
    41. function new(string name = "comp1", uvm_component parent = null);
    42. super.new(name, parent);
    43. var1 = 100;
    44. `uvm_info("CREATE", $sformatf("unit type [%s] created", name), UVM_LOW)
    45. endfunction
    46. function void build_phase(uvm_phase phase);
    47. super.build_phase(phase);
    48. `uvm_info("BUILD", "comp1 build phase entered", UVM_LOW)
    49. if(!uvm_config_db#(virtual uvm_config_if)::get(this, "", "vif", vif))
    50. `uvm_error("GETVIF", "no virtual interface is assigned")
    51. `uvm_info("GETINT", $sformatf("before config get, var1 = %0d", var1), UVM_LOW)
    52. uvm_config_db#(int)::get(this, "", "var1", var1);
    53. `uvm_info("GETINT", $sformatf("after config get, var1 = %0d", var1), UVM_LOW)
    54. uvm_config_db#(config_obj)::get(this, "", "cfg", cfg);
    55. `uvm_info("GETOBJ", $sformatf("after config get, cfg.comp1_var = %0d", cfg.comp1_var), UVM_LOW)
    56. c2 = comp2::type_id::create("c2", this);
    57. `uvm_info("BUILD", "comp1 build phase exited", UVM_LOW)
    58. endfunction
    59. endclass
  • 相关阅读:
    计算机视觉—车道线检测
    大黑书《离散数学及其应用》之Dijkstra算法
    Windows 11 有望支持苹果 M1 Mac?微软和高通的秘密协议即将到期
    SSM框架学习——MyBatis Plus
    【linux命令讲解大全】016 .Git:分布式版本控制系统的先驱和常用命令清单(五)
    重新安装mysql时,Windows Service Name已经被占用了怎么办
    ppt背景图片怎么设置?6步教你快速搞定!
    设计模式-观察者模式(Observer)
    并发容器详解
    网络安全-HSRP协议
  • 原文地址:https://blog.csdn.net/weixin_39668316/article/details/126064196