消息机制
消息的处理是由uvm_report_handler类来完成的,而每一个uvm_report_object类中都有一个uvm_report_handler实例。而上面的uvm_report_object消息处理方或者uvm_component处理方法,都是针对于这些uvm_report_handler做出的配置。除了上面的常见使用方法,用户还可以做出更高级的消息控制流程。
仿真停止控制
上面的例码中,UVM_ERROR信息之所以不会导致仿真停止,是因为max_quit_count的默认值为0。如果用户做出设定,那么就可以完成关于仿真停止的控制。例如在build_phase函数中调用set_max_quit_count(10)来指定max_quit_count。而做出的这一操作,无论发生在哪一个层次,都是对uvm_pkg中的共享变量uvm_report_server做出的操作。所以,考虑到build phase中层次从上到下的构建顺序,建议用于只在test层中调用函数set_max_quit_count,防止底层调用函数时的配置覆盖。
消息回调函数
有时候在处理信息时,用户还希望做出额外的处理,这时候回调函数就显得很有必要了。uvm_report_object类提供了下面的回调函数满足用户更多的需求:
- function bit report_hook(string id, string message, int verbosity, string filename, int line);
- function bit report_info_hook(string id, string message, int verbosity, string filename, int line);
- function bit report_warning_hook(string id, string message, int verbosity, string filename, int line);
- function bit report_error_hook(string id, string message, int verbosity, string filename, int line);
- function bit report_fatal_hook(string id, string message, int verbosity, string filename, int line);
report_hook函数则对所有的通过结合在设置消息处理时的UVM_CALL_HOOK,结合用户自定义的回调函数,就可以实现更丰富的配置。在调用回调函数时,首先会调用report_hook()函数,接下来才视severity级别来选择更细致的回调函数report_SEVERITY_hook()。默认情况下,report_hook()函数返回值为1,进而再转入severity hook函数。如果report_hook()函数由用户自定义, 且返回0的话,那么后续的severity hook函数也不会再执行。下面是一段关于消息回调函数应用的例码:
module report_hook;
import uvm_pkg::*;
`include "uvm_macros.svh"
class test1 extends uvm_test;
integer f;
`uvm_component_utils(test1)
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
set_report_severity_action(UVM_ERROR, UVM_DISPLAY | UVM_CALL_HOOK);
set_report_verbosity_level(UVM_LOW);
endfunction
task run_phase(uvm_phase phase);
uvm_report_info("RUN", "info1", UVM_MEDIUM);
uvm_report_info("RUN", "info2", UVM_LOW);
uvm_report_warning("RUN", "warning1", UVM_LOW);
uvm_report_error("RUN", "error1", UVM_LOW);
uvm_report_error("RUN", "error2", UVM_HIGH);
uvm_report_error("RUN", "error3", UVM_LOW);
endtask
function void report_phase(uvm_phase phase);
$fclose(f);
endfunction
function bit report_hook(string id, string message, int verbosity, string filename, int line);
uvm_report_info("RPTHOOK", $sformatf("%s : %s", id, message), UVM_LOW);
return 1;
endfunction
function bit report_error_hook(string id, string message, int verbosity, string filename, int line);
uvm_report_info("ERRHOOK", $sformatf("%s : %s", id, message), UVM_LOW);
return 1;
endfunction
endclass
initial begin
run_test("test1");
end
endmodule
输出结果:
UVM_INFO @ 0: reporter [RNTST] Running test test1...
UVM_INFO @ 0: uvm_test_top [RUN] info2
UVM_WARNING @ 0: uvm_test_top [RUN] warning1
UVM_INFO @ 0: uvm_test_top [RPTHOOK] RUN : error1
UVM_INFO @ 0: uvm_test_top [ERRHOOK] RUN : error1
UVM_ERROR @ 0: uvm_test_top [RUN] error1
UVM_INFO @ 0: uvm_test_top [RPTHOOK] RUN : error3
UVM_INFO @ 0: uvm_test_top [ERRHOOK] RUN : error3
UVM_ERROR @ 0: uvm_test_top [RUN] error3
除了每一个uvm_report_object中都内置一个uvm_report_handler实例之外,所有的uvm_report_handler实例也都需要依赖于uvm_pkg中uvm_report_server的唯一实例,但是该实例并没有作为全局变量,直接暴露给用户,需要用户自行调用uvm_report_server::get_server()方法来获取。uvm_report_server是一个全局的消息处理设备,用来处理从所有uvm_report_hanlder中产生的消息。这个唯一的report server之所以没有暴露在uvm_pkg中供用户使用,一个原因在于对于消息的处理方式,用户可以通过uvm_report_object和uvm_component提供的消息处理函数完成,而不必要对uvm_report_server做出额外的配置。