UVM

您所在的位置:网站首页 sv是设定值吗 UVM

UVM

2024-06-25 05:59| 来源: 网络整理| 查看: 265

文章目录 一、组件配置机制uvm_config_db1.1.virtual interface的传递(重要)1.2.配置单一变量1.3.config object对象传递(重要)2.4.配置说明 二、配置机制的调试三、关于uvm_resource_db的使用说明

一、组件配置机制uvm_config_db

   在验证环境的创建过程build_phase中,除了组件的实例化,配置也是必不可少的。为了验证环境的复用性,通过外部的参数配置,使得环境在创建时可以根据不同的参数来选择创建的组件类型、组件实例数目、组件之间的连接以及组件之间的运行模式等。UVM提供了uvm_config_db配置类以及几种方便的变量设置方法来实现仿真时的环境控制,常见的uvm_config_db类的使用方式包括:

传递virtual interface到环境中; 配置单一变量值,例如int、string、enum等; 传递配置对象(config_object)到环境; 1.1.virtual interface的传递(重要)

   虽然SV可以通过层次化的interface的索引完成传递,但是这种传递方式不利于软件环境的封装和复用。通过使用uvm_config_db配置机制来传递接口,可以将接口的传递与获取彻底分离开。    接口传递从硬件世界到UVM环境可以通过uvm_config_db来实现,在实现过程中应当注意:

接口传递应发生在run_test()之前。这保证了在进入build_phase之前,virtual interface已经被传递到uvm_config_db中。用户应当把interface与virtual interface区分开来,在传递过程中的类型应当为virtual interface,即实际接口的句柄。 interface intf1; //接口定义 logic enable = 0; endinterface class comp1 extends uvm_component; //组件配置接口 `uvm_component_utils(comp1) virtual intf1 vif; //接口声明 ... function void build_phase(uvm_phase phase); if(!uvm_config_db #(virtual intf1)::get(this,"","vif",vif)) begin //**3. 获取配置接口vif = intf** `uvm_error("GETVIF","no virtual interface is assigned") end `uvm_info("SETVAL",$sformatf("vif.enable is %b before 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(); //**1. 接口配置前,例化借口** initial begin uvm_config_db #(virtual intf1)::set(uvm_root::get(),"uvm_test_top.c1","vif",intf) //**2. 启动接口配置** run_test("test1"); //在run_test()之前完成接口配置 end

输出结果:

UVM_INFO @ 0: reporter [RNTST] Running test test1... UVM_INFO @ 0: uvm_test_top.c1 [SETVAL] vif.enable is 0 before set UVM_INFO @ 0: uvm_test_top.c1 [SETVAL] vif.enable is 1 before set 1.2.配置单一变量

  在各个test中,可以在build_phase阶段对底层组件的各个变量加以配置,进而在环境例化之前完成配置,使得环境可以按照预期运行。

class comp1 extends uvm_component; //组件 `uvm_component_utils(comp1) int val1 = 1; string str1 = "null"; ... function void build_phase(uvm_phase phase); //在build_phase阶段进行配置 `uvm_info("SETVAL",$sformatf("val1 is %d before get",val1),UVM_LOW) `uvm_info("SETVAL",$sformatf("str1 is %d 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 %d 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"); endfunction endclass

输出结果

UVM_INFO @ 0: uvm_test_top.c1 [SETVAL] val1 is 1 before get UVM_INFO @ 0: uvm_test_top.c1 [SETVAL] str1 is null before get UVM_INFO @ 0: uvm_test_top.c1 [SETVAL] val1 is 100 after get UVM_INFO @ 0: uvm_test_top.c1 [SETVAL] str1 is comp1 after get 1.3.config object对象传递(重要)

  在test配置中,需要配置的参数不只是数量多,可能还分属于不同的组件。对这么多层次的变量做出类似上边的单一变量传递,需要更多的代码,容易出错且不易复用。如果整合各个组件中的变量,将其放置在一个uvm_object中,再对中心化的配置对象进行传递,将有利于整体环境的修改维护,体改代码的复用性。

class config1 extends uvm_object; //**1. 创建一个配置类,将需要配置的变量放于其中** `uvm_object_utils(config1) int val1 = 1; int str1 = "null"; ... 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); //**3. 获取变量配置** void`($cast(cfg,tmp)); //类型转韩,将传到tmp中的值赋给cfg `uvm_info("SETVAL",$sformatf("cfg.val1 is %d after get",cfg.val1),UVM_LOW) `uvm_info("SETVAL",$sformatf("cfg.str1 is %d after get",cfg.str1),UVM_LOW) endfunction endclass class test1 extends uvm_test; //测试用例层, 启动配置 `uvm_component_utils(test1) comp1 c1, c2; config1 cfg1, cfg2; ... function void build_phase(uvm_phase phase); cfg1 = config1::type_id::create("cfg1"); cfg2 = config1::type_id::create("cfg2"); c1 = comp1::type_id::create("c1"); c2 = comp1::type_id::create("c2"); //创建对象 cfg1.val1 = 30; cfg1.str1 = "c1"; cfg2.val1 = 50; cfg2.str1 = "c2"; uvm_config_db #(uvm_object)::set(this,"c1","cfg",cfg1); //**2. 启动变量配置** uvm_config_db #(uvm_object)::set(this,"c2","cfg",cfg2); //启动变量配置 endfunction endclass

输出结果

UVM_INFO @ 0: uvm_test_top.c1 [SETVAL] cfg.val1 is 30 after get UVM_INFO @ 0: uvm_test_top.c1 [SETVAL] cfg.str1 is c1 after get UVM_INFO @ 0: uvm_test_top.c2 [SETVAL] cfg.val1 is 50 after get UVM_INFO @ 0: uvm_test_top.c2 [SETVAL] cfg.str1 is c2 after get 2.4.配置说明

  通过UVM配置机制,设置对象的变量;

uvm_config_db #(type)::get( //type类型可以是int、string等类型,也可以是接口interface、对象object等类型 uvm_component context, //组件中的目标,常设置为this(针对类),或者null(非类,如module模块) string instance_name, //路径索引,相对于第一个参数的相对路径 string field_name, inout T variable //2. **底层获取变量值,即variable = field_name,**如果不设置,变量保持原始值 ); uvm_config_db #(type)::set( //set()与get()中的类型type应该保持一致 uvm_component context, //组件中的目标,常设置为this(针对类),或者null(非类,如module模块) string instance_name, //路径索引(set操作的目标组件实例名) string field_name, T value //1. **顶层设置变量值,即field_name = value** ); 在使用set()/get()方法时,传递的参数类型应当保持一致。对于uvm_object等实例的传递,如果get类型和set类型不一致,应当首先通过$cast()完成类型转换,再对类型转换后的对象进行操作。在参数传递时,“”表示默认当前层次,也可以使用通配符 * 来表示任意层次。需要注意“*.comp”与“*comp”的区别,前者表示在当前层次下所有名称为“comp”的组件,而后者表示包括当前层次以及当前层次以下所有名为“comp”的组件。在module环境中使用uvm_config_db::set(),则传递的第一个参数一般用来表示当前的层次(用this表示),此时第二个参数为相对路径;如果当前层次为最高层,用户可以设置为null(module模块,非类不可以用this),此时第二个参数为绝对路径(uvm_test_top.xxx);也可以设置为uvm_root::get()来表示uvm_root的全局顶层实例。在使用uvm_config_db::get()方法时,添加便于调式的语句。例如通过UVM报告信息得知get()方法中配置的变量是否从uvm_config_db获取到,如果没有获取到,是否采取其他必要措施。在set()方法第一个参数使用当前层次的前提下,对于同一组件的同一变量,如果有多个高层组件对该变量进行配置,那么较高层组件的配置会覆盖较低层的配置;但是如果是同一层次组件对该变量进行配置时,应当遵循后面的配置覆盖前面的配置。 二、配置机制的调试

  由于配置类型信息types在set()/get()方法使用中如果不匹配,EDA工具在get()时并不会报错,因此需要手动添加调试信息。常见方法如下:

检查read_by_name/_type()或者get()函数的返回值,如果获取不到,打印错误信息; if(!uvm_config_db #(int unsigned)::get(this,"","item_count",item_count)) `uvm_info("SETVAL",$sformatf("item_count isnot available for %s",this.get_full_name),UVM_LOW) 使用仿真命令选项,跟踪set()和get()信息; +UVM_CONFIG_DB_TRACE+UVM_RESOURCE_DB_TRACE 三、关于uvm_resource_db的使用说明

  对变量的配置除了采用uvm_config_db之外,还可以采用uvm_resource_db进行配置。二者之间是继承关系,uvm_resource_db是父类,uvm_config_db是子类。   uvm_resource_db虽然也是一种用来共享数据的类,但是与uvm_config_db相比,有 一个缺点就是层次的缺失和因此带来的自顶向下的配置覆盖关系的缺失。

  因此应该养成使用uvm_config_db的习惯,原因如下:

uvm_resource_db采用的是“last write wins”即对同一配置,最后写入的有效;而uvm_config_db采取的是“parent wins”,它会按照层次采取最顶层配置优先。uvm_resource_db给人带来的困惑是,如果高层次和低层次都对同一配置变量进行写入,那么在build阶段,由于采取的是top_down的执行顺序,低层次的配置写入发生在最后,反而会作为有效值写入。因此uvm_resource_db无法实现层次化的覆盖,这不利于集成和复用。

因此实际使用中,应该尽可能的只是用uvm_config_db::set()/get()方法,依赖它们就可以完成配置,并且有利于环境的集成和复用。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3