或者用户只希望重载其中某个指定的driver对象,使用:
set_inst_override_by_type(\driver::get_type());
用工厂创建对象的方式不仅仅局限在组件中使用,对于对象(object)以及序列项
(sequence_item)也极其重要。为了完成验证计划而对数据项进行重载的场景我们会在稍后的UVM接口章节进一步讨论。 使用工厂的步骤如下: 1.
在工厂中注册所有的类
这个动作通过对UVM对象和UVM组件分别使用宏`uvm_object_utils和`uvm_component_utils来自动完成. 2.
使用create() API来创建UVM对象和UVM组件,此API对UVM对象和UVM组件一样
my_driver = driver::type_id::create(\3.
使用类型或者实例重载函数,将基类型用继承类型覆盖,请记住此动作一定要在对象创建之前.
UVM工厂还有许多其他功能,比如,可以使用字符串通配符进行实例重载;软重载(如果其他重载存在则忽略此重载);等等。更多细节请参考UVM用户指南。
下面的例子演示了和前例相同的功能,但是使用工厂取代繁琐的手工编码的方式。 实例4-16: UVM工厂的使用
此例子定义了一个state组件,以及floria和new_york两个子组件。我们演示工厂如何通过调用create()和类型重载来创建和分配state。 1. 2. 3. 4. 5. 6. 7. 8.
class state extends uvm_component; `uvm_component_utils(state)
function new(string name, uvm_component parent); super.new(name, parent); endfunction : new
function void end_of_elaboration(); this.print();
endfunction : end_of_elaboration
9. endclass : state
10. class florida extends state; 11. `uvm_component_utils(florida)
12. function new(string name, uvm_component parent); 13. super.new(name, parent); 14. endfunction : new 15. endclass : florida
16. class new_york extends state; 17. `uvm_component_utils(new_york)
18. function new(string name, uvm_component parent); 19. super.new(name, parent); 20. endfunction : new 21. endclass : new_york 22. state my_state1, my_state2; 23. // Start UVM Phases 24. initial begin
25. my_state1 = state::type_id::create(―my_state1‖, null);
26. `uvm_info(“INFO1”,{ my_state1.type=”, my_state1.get_type_name()},
UVM_LOW)
27. // set factory to allocate new_york state whenever a state is created
28. factory.set_type_override_by_type(state::get_type(), new_york::get_type()); 29. my_state2 = state::type_id::create(“my_state2”, null);
30. `uvm_info(“INFO2”,{“my_state2.type=”,my_state2.get_type_name()},UVM_LO
W)
31. #100 $finish; 32. end
第1行:定义了state基类
第10-21行: 从state组件继承得到florida和new_york组件. 第22行: 声明了两个state句柄state1和state2.
第25-26行: 使用工厂API函数state::type_id::create(...)来创建state1组件. 由于没有使用工厂进行重载,26行中将会使用创建state对象以及打印state信息。 第28行: 当需要创建state的时候,工厂将返回new_york子类型。 第29:行 使用工厂来创建state.
第30行: 组件的的名称将打印为new_york. 运行结果输出:
UVM_INFO ./test.sv(51) @ 0: reporter [INFO1] my_state1.type=state UVM_INFO ./test.sv(54) @ 0: reporter [INFO2] my_state2.type=new_york
注意: 使用工厂来创建UVM对象和UVM组件的重要性怎样强调都不过分. 对于某些用户而言,工厂可能是一个新概念,但是工厂使用很简单,它的实现已经内建在UVM的库中.
4.8 UVM消息机制
当开发使用验证环境的时候,用户需要打印一些信息以及错误消息。可能要跟踪某个可疑组件的消息,或者过滤掉某些不关心的错误。Verilog的$display函数不允许非侵入性的消息过滤和消息控制(译者注:非侵入指不影响不改变原程序的实现细节)。如果使用命令行或者使用TCL运行时的指令来改变信息输出级别,将不需要重新编译和构建设计模块来观察不同级别的跟踪信息。UVM报告服务内建在所有的组件中,从uvm_report_object类继承而来。此项服务也可以用在SystemVerilog模块、SystemVerilog接口和SystemVerilog程序中.此机制为多种需求提供了一个简单的解决方案,能够通过标志,参数,和用户自定义钩子(hook)来定制。
4.8.1 UVM消息API
消息服务提供的程序接口如下:
uvm_report_info(string id, string message, int verbosity = UVM_MEDIUM, string filename = “”, int line = 0);
uvm_report_warning(string id, string message, int verbosity = UVM_MEDIUM, string filename = “”, int line = 0);
uvm_report_error(string id, string message, int verbosity = UVM_LOW, string filename = “”, int line = 0);
uvm_report_fatal(string id, string message, int verbosity = UVM_NONE, string filename = “”, int line = 0); 他们对应于以下宏:
`uvm_info(string id, string message, int verbosity) `uvm_warning(string id, string message) `uvm_error(string id, string message) `uvm_fatal(string id, string message)
建议使用宏,因为它会在执行复杂的字符串操作之前进行检查是否需要进行输出。宏也会自动的增加参数文件名和行号。
string id可以用来过滤。冗余级别(verbosity)是一个整数,代表消息的相对重要性级别。如果它的值小于或等于当前冗余级别,那么消息报告将输出。例如,如果当前冗余基别设置为100, 所有编码为101以及更高的消息都将不被打印输出。 枚举类型uvm_verbosity提供了一些标准的冗余级别,包括:
UVM_NONE=0, UVM_LOW=100, UVM_MEDIUM=200, UVM_HIGH=300, UVM_FULL=400, UVM_DEBUG=500.
注意: 当使用消息宏的时候,对warning(警告)、error(错误)、fatal(致命错误),冗余级别将被忽略。这是为了防止一些隐藏的BUG来改变冗余级别。保留其冗余级别的参数是为了向后兼容。如果希望关闭警告、错误、致命错误信息,可以通过设定动作为UVM_NOACTION. 例如,为了关闭组件mycomp中id为MYTAG,冗余级别是UVM_ERROR的这类消息输出,可以在测试向量中执行如下命令:
mycomp.set_report_severity_id_action(UVM_ERROR, “MYTAG”, UVM_NO_ACTION);
4.8.2 UVM消息的使用规则:
? ?
使用宏和使用函数的运行时特性有很大不同,尽可能使用宏。
为了更方便的控制测试向量中多个组件的消息输出,仅仅使用预定义的枚举类型,并且运用对这些冗余级别的标准解释。解释如下:
o o o
UVM_NONE—不可屏蔽的关键消息
UVM_LOW—可屏蔽消息,在仿真过程中极少输出(比如,复位结束) UVM_MEDIUM—对每个数据项或者序列(sequence)仅仅发生一次的短消息。
o UVM_HIGH—更详细的数据项信息,包括打印封包的值,以及子交易(sub-transaction)的细节信息。
o UVM_FULL—剩下的部分,包括特定方法内的消息打印(为了跟踪此方法的算法流程)
o
?
UVM_DEBUG—调试(debug)模式下的调试信息。
对于信息消息,建议使用get_type_name()的值作为\的参数。这样就比较容易在仿真过程中知道不同的组件各产生了多少消息,也可以很快很清晰的判断是否所有的组件都工作正常。这样的用法也满足消息可以根据类型进行过滤。
? 有时候,对某些特殊的项目以及特定的测试需求,用户需要忽略掉警告信息。对于错误相关的消息报告(警告、错误、致命错误),请使用同一的名字作为\参数,这样就容易对错误信息的忽略进行精细控制。
4.8.3 修改消息输出冗余级别
有3种方式来改变冗余级别:
?
命令行方式(和仿真器相关). 举例如下: % irun … +UVM_VERBOSITY=UVM_NONE
? 在SystemVerilog中执行命令:
set_report_verbosity_level_hier(UVM_MEDIUM);
? TCL(运行时)指令:
uvm_message uvm_test_top.uart_ctrl_tb.apb0 UVM_FULL
注意: Changing通过命令行或者运行时TCL来改变冗余级别,以看到不同的跟踪消息记录,并不需要我们对设计进行重新编译和构建。
也可以在非对象类相关的代码中使用此消息宏. 下面实例模块的在initial块中直接使用消息宏:
实例4-17: Using the Info Message within Modules 1. 2. 3. 4. 5. 6. 7. 8.
module test; import uvm_pkg::*; `include \ initial begin
uvm_report_info(\ `uvm_info(\ end
endmodule : test
输出如下::
-------------------------------------------------------------------------- UVM_INFO @ 0: reporter [TEST] I am in the top-level test
UVM_INFO ./messages.sv(13) @ 0: reporter [TEST] I am in the top-level test --------------------------------------------------------------------------
4.9 回调(Callbacks)