文章目录
前言
传统的SV经常使用 d i s p l a y ( ) 打印信息,而 U V M 含有几个特定的打印方法可以自动详细信息,无需使用 display()打印信息,而UVM含有几个特定的打印方法可以自动详细信息,无需使用 display()打印信息,而UVM含有几个特定的打印方法可以自动详细信息,无需使用display()。
1、component 消息机制
1.1. 消息打印
UVM所有的消息打印方法均来自uvm_report_object类,而uvm_component类又继承于uvm_report_object类,所以所有的component都含有消息打印的方法和设定方法
下面给出常用方法的原型,实际上所有的方法本质都是调用的uvm_report,可查看源码。
//...\questasim64_2020.1\verilog_src\uvm-1.2\src\base\uvm_report_object.svh
class uvm_report_object extends uvm_object; //...
virtual function void uvm_report( uvm_severity severity,
string id,
string message,
int verbosity = (severity == uvm_severity'(UVM_ERROR)) ? UVM_LOW :
(severity == uvm_severity'(UVM_FATAL)) ? UVM_NONE : UVM_MEDIUM,
string filename = "",
int line = 0,
string context_name = "",
bit report_enabled_checked =0);
virtual function void uvm_report_info( string id,
string message,
int verbosity = UVM_MEDIUM,
string filename = "",
int line = 0,
string context_name = "",
bit report_enabled_checked = 0);
virtual function void uvm_report_warning( string id,
string message,
int verbosity = UVM_MEDIUM,
string filename = "",
int line = 0,
string context_name = "",
bit report_enabled_checked = 0);
virtual function void uvm_report_error( string id,
string message,
int verbosity = UVM_LOW,
string filename = "",
int line = 0,
string context_name = "",
bit report_enabled_checked = 0);
virtual function void uvm_report_fatal( string id,
string message,
int verbosity = UVM_NONE,
string filename = "",
int line = 0,
string context_name = "",
bit report_enabled_checked = 0);
//...
endclass
然后对各输入变量作说明
● string id:表示消息打印的ID,可用于告知消息控制方法,要对哪个消息进行控制
● string message:真正要打印的消息
● string filename :打印该消息所在文件名字
● int line:打印该消息所在文件的行号
1.1.1 int verbosity 过滤度
冗余度,或称过滤度,表示消息的过滤等级。过滤等级越高,越容易不显示该消息
依旧以parameter常量的方式表示,定义为
typedef enum{
UVM_NONE = 0,
UVM_LOW = 100,
UVM_MEDIUM = 200,
UVM_HIGH = 300,
UVM_FULL = 400,
UVM_DEBUG = 500
} uvm_verbosity;
每个component都有其 过滤度阈值,默认为UVM_MEDIUM,如果某个消息的过滤度 ≤ 过滤度阈值,就会打印,否则就不打印。
过滤度阈值的 继承
在uvm_component的new方法中,有这样一句
//...\questasim64_2020.1\verilog_src\uvm-1.2\src\base\uvm_component.svh
function uvm_component::new (string name, uvm_component parent);
...
set_report_verbosity_level(parent.get_report_verbosity_level());
...
endfunction
所以有结论子类component在创建时会继承父类component的过滤度阈值。
但注意若某ID的过滤度阈值与 该component的过滤度阈值 不同,则该ID的过滤度阈值不会被继承
例如
class my_test extends uvm_test;
comp c1,c2;
...
function void build_phase(uvm_phase phase);
super.build_phase(phase);
set_report_id_verbosity_hier("create", UVM_NONE);
c1 = comp::type_id::create("c1",this);
c2 = comp::type_id::create("c2",this);
...
endfunction
endclass
class comp extends uvm_component;
function new(string name,uvm_component parent);
super.new(name,parent);
uvm_report_info("create","comp inst is created",UVM_LOW); //会被打印
endfunction
...
endclass
1.1.2. uvm_severity severity 安全级别
以parameter常量的方式表示,有UVM_INFO、UVM_WARNING、UVM_ERROR 和 UVM_FATAL,必须大写
分别对应着uvm_report_info、uvm_report_warning、uvm_report_error和uvm_report_fatal四种方法。
如果安全级别为fatal则都打印消息后,立刻停止仿真
1.1.3. 常见用法
下面给出例子
class my_driver extends uvm_driver;
`uvm_component_utils("my_driver")
function new(string name = "my_driver", uvm_component parent);
super.new(name,parent);
endfunction
virtual task main_phase(uvm_phase phase);
...
uvm_report_info("data1","data is derived", UVM_LOW) //ID为"data1",打印内容为"data is derived",安全级别为UVM_INFO,过滤级别为UVM_LOW
...
endtask
endclass
打印出的信息公式为:UVM_INFO 来源的sv文件(消息语句在该文件的行数)@打印时间: 索引[ID号]打印的信息
例如
UVM_INFO my_driver.sv(20)@48500000:drv[data1]data is drived
`timescale 1ns/1ps表示时延单位是1ns,时间精度是1ps。如果是这样定义的话,则INFO的打印时间就是从仿真开始经过了多少ps
1s = 1,000 ms = 1,000,000 us = 1,000,000,000 ns = 1,000,000,000,000 ps
宏
可以使用宏进行消息打印,但是一定要注意
只有`uvm_info可以设定过滤度,其他严重度的消息宏 不可设定过滤度,且强制为UVM_NONE
不信看源码
//...\questasim64_2020.1\verilog_src\uvm-1.2\src\macros\uvm_message_defines.svh
`define uvm_info(ID, MSG, VERBOSITY) \
begin \
if (uvm_report_enabled(VERBOSITY,UVM_INFO,ID)) \
uvm_report_info (ID, MSG, VERBOSITY, `uvm_file, `uvm_line, "", 1); \
end
`define uvm_warning(ID, MSG) \
begin \
if (uvm_report_enabled(UVM_NONE,UVM_WARNING,ID)) \
uvm_report_warning (ID, MSG, UVM_NONE, `uvm_file, `uvm_line, "", 1); \
end
`define uvm_error(ID, MSG) \
begin \
if (uvm_report_enabled(UVM_NONE,UVM_ERROR,ID)) \
uvm_report_error (ID, MSG, UVM_NONE, `uvm_file, `uvm_line, "", 1); \
end
//...
使用时,可配合get_type_name()以获取打印消息的组件ID,配合$sformat()将消息与变量整合
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
1.2. 消息控制
1.2.1. 过滤度阈值 控制
即对某些component的过滤度阈值进行统一控制,或是对某些component中某些ID的消息打印方法设定过滤度阈值
函数原型,注意uvm_component类在uvm_report_object类的基础上将所有的方法增加了层次回归的设定。
//...\questasim64_2020.1\verilog_src\uvm-1.2\src\base\uvm_report_object.svh
//根据安全级别获取过滤度等级
function int get_report_verbosity_level(uvm_severity severity=UVM_INFO, string id="");
function int get_report_max_verbosity_level();
function void set_report_verbosity_level (int verbosity_level); //设定本component的过滤度阈值
function void set_report_id_verbosity (string id, int verbosity); //设定本component中id的report方法的过滤度阈值
function void set_report_severity_id_verbosity (uvm_severity severity,string id, int verbosity);
//...\questasim64_2020.1\verilog_src\uvm-1.2\src\base\uvm_component.svh
function void set_report_verbosity_level_hier (int verbosity_level); //设定本component及所有孩子的过滤度阈值
function void uvm_component::set_report_id_verbosity_hier( string id, int verbosity); //设定本component及所有孩子的id过滤度阈值
set_report_id_verbosity(id, verbosity);
foreach( m_children[c] )
m_children[c].set_report_id_verbosity_hier(id, verbosity);
endfunction;
function void set_report_severity_id_verbosity_hier (uvm_severity severity,string id, int verbosity);
例子
env.i_agt.drv.get_report_verbosity_level(); //获取drv的过滤度阈值
env.i_agt.drv.set_report_verbosity_level(UVM_HIGH); //drv的过滤度阈值设置为UVM_HIGH
env.i_agt.set_report_verbosity_level_hier(UVM_HIGH); //i_agt及其子节点所有的过滤度阈值均被设置为UVM_HIGH
env.i_agt.set_report_id_verbosity("INFO1",UVM_HIGH); //设置ID为"INFO1"的component的过滤度阈值为UVM_HIGH
env.i_agt.set_report_id_verbosity("INFO2",UVM_HIGH); //获取ID为"INFO2"的component的过滤度阈值为UVM_HIGH
env.set_report_id_verbosity_hier("INFO3",UVM_HIGH); //获取ID为"INFO3"及其子component的的过滤度阈值均为UVM_HIGH
UVM消息机制中,每个component都有相应的过滤度阈值,且不同component之间可以相互设定过滤度阈值
与factory机制是类似的,每个component都有相应的创建函数,且不同component之间可以相互重载创建函数
注意了,上述component过滤度阈值控制只适用于子component,而不适用于object!!!
尽量在connect_phase控制过滤度
先看下面代码,如果只能消除一个注释,标准UVM树各component的过滤度阈值是多少?注意object无过滤度阈值
class my_test extends uvm_test;
env e;
...
function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info("BUILD", "uvm_message_test build phase entered", UVM_LOW)
//set_report_verbosity_level(UVM_NONE); //除了树根,UVM树全部component都为UVM_NONE
//set_report_verbosity_level_hier(UVM_NONE); //除了树根,UVM树全部component都为UVM_NONE
e = env::type_id::create("e", this);
//set_report_verbosity_level(UVM_NONE); //只有uvm_test_top阈值为UVM_NONE,其他component为UVM_MEDIUM
//set_report_verbosity_level_hier(UVM_NONE); //除了树根,UVM树全部component都为UVM_NONE
//set_report_id_verbosity("BUILD",UVM_NONE); //UVM树全部component都为UVM_MEDIUM,只有uvm_test_top中ID为"BUILD"的阈值为UVM_NONE
//set_report_id_verbosity_hier("BUILD",UVM_NONE); //UVM树全部component阈值为UVM_MEDIUM,只有uvm_test_top和e的ID为"BUILD"的阈值为UVM_NONE
`uvm_info("BUILD", "uvm_message_test build phase exited", UVM_LOW)
endfunction
endclass
从上面看,build_phase中在子组件实例化前后进行过滤度阈值控制,会产生不同的效果,在实际操作时非常麻烦。根本原因在于:子component会继承父component的过滤度阈值,但只有在create之后才产生子component
所以为了避免如此麻烦,建议在connect_phase进行过滤度控制。但注意connect_phase是自底向上执行的,而且第一个执行connect_phase的组件不确定
所以如果在test的connect_phase进行过滤度控制,该控制是无法在其他组件的connect_phase中的消息语句实现的。
1.2.2. 文件控制
可将打印的消息保存在日志文件中
//...\questasim64_2020.1\verilog_src\uvm-1.2\src\base\uvm_report_object.svh
function int get_report_file_handle(uvm_severity severity, string id);
function void set_report_default_file (UVM_FILE file);
function void set_report_id_file (string id, UVM_FILE file);
function void set_report_severity_file (uvm_severity severity, UVM_FILE file);
function void set_report_severity_id_file (uvm_severity severity, string id,
UVM_FILE file);
//...\questasim64_2020.1\verilog_src\uvm-1.2\src\base\uvm_component.svh
function void set_report_id_file_hier (string id, UVM_FILE file);
function void set_report_severity_file_hier (uvm_severity severity, UVM_FILE file);
function void set_report_severity_id_file_hier (uvm_severity severity, string id,
UVM_FILE file);
1.2.3. 行为控制
即对消息的行为进行控制,也是通过枚举常量定义的
typedef enum
{
UVM_NO_ACTION = 'b000000, //无动作
UVM_DISPLAY = 'b000001, //显示消息
UVM_LOG = 'b000010, //写入文件
UVM_COUNT = 'b000100, //计数到某数值,并停止仿真
UVM_EXIT = 'b001000, //退出仿真
UVM_CALL_HOOK = 'b010000, //调用回调函数
UVM_STOP = 'b100000 //停止仿真
} uvm_action_type;
各安全级别的默认行为如下表所示,也是通过 或 | 实现动作的合并的
下面给出消息打印的行为控制方法
//...\questasim64_2020.1\verilog_src\uvm-1.2\src\base\uvm_report_object.svh
function int get_report_action(uvm_severity severity, string id);
function void set_report_severity_action (uvm_severity severity,uvm_action action);
function void set_report_id_action (string id, uvm_action action);
function void set_report_severity_id_action (uvm_severity severity,
string id, uvm_action action);
//...\questasim64_2020.1\verilog_src\uvm-1.2\src\base\uvm_component.svh
function void set_report_severity_action_hier (uvm_severity severity,uvm_action action);
function void set_report_id_action_hier (string id, uvm_action action);
function void set_report_severity_id_action_hier (uvm_severity severity,
string id, uvm_action action);
例子
class comp1 extends uvm_component;
`uvm_component_utils(comp1);
function void build_phase(uvm_phase phase);
f = $fopen("logfile",w);
set_report_default_file (f);
set_report_severity_action_hier(UVM_INFO,UVM_DISPLAY|UVL_LOG);
set_report_severity_action_hier(UVM_ERROR,UVM_DISPLAY|UVL_LOG|UVM_COUNT);
endclass
UVM_COUNT
意思是计数结束仿真,可通过如下方法设定所有具有UVM_COUNT行为的的计数阈值,当然UVM_ERROR是默认含有UVM_COUNT行为的
function void set_report_max_quit_count(int max_count);
1.2.4. 安全等级重载
uvm_info,
uvm_warning, uvm_error,
uvm_fatal均可相互重载,涉及到的方法如下
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
env.i_agt.drv.set_report_severity_override(UVM_WARNING, UVM_ERROR); //将drv所有的uvm_warning替换为uvm_error
env.i_agt.drv.set_report_severity_id_override(UVM_WARNING, "my_driver", UVM_ERROR); //加入了id
2. 全局消息机制(包括object和tb)
上面讲的消息打印与控制,都是在component中才可使用,那在tb模块和object类定义内部,如何打印和控制消息呢?
这与component消息机制类似。
2.1. 消息打印
实际上,在uvm_global.svh中就已经定义了所有的消息打印方法,而且是全局的哟(不是类内方法哟)。
源代码如下:
//...\questasim\verilog_src\uvm-1.2\src\base\uvm_globals.svh
function void uvm_report( uvm_severity severity,
string id,
string message,
int verbosity = (severity == uvm_severity'(UVM_ERROR)) ? UVM_LOW :
(severity == uvm_severity'(UVM_FATAL)) ? UVM_NONE : UVM_MEDIUM,
string filename = "",
int line = 0,
string context_name = "",
bit report_enabled_checked = 0);
uvm_root top;
uvm_coreservice_t cs;
cs = uvm_coreservice_t::get();
top = cs.get_root();
top.uvm_report(severity, //本质上调用的是uvm_root:get()!
id, message, verbosity, filename, line, context_name, report_enabled_checked);
endfunction
function void uvm_report_info(string id,
string message,
int verbosity = UVM_MEDIUM,
string filename = "",
int line = 0,
string context_name = "",
bit report_enabled_checked = 0);
function void uvm_report_warning(string id,
string message,
int verbosity = UVM_MEDIUM,
string filename = "",
int line = 0,
string context_name = "",
bit report_enabled_checked = 0);
function void uvm_report_error(string id,
string message,
int verbosity = UVM_LOW,
string filename = "",
int line = 0,
string context_name = "",
bit report_enabled_checked = 0);
function void uvm_report_fatal(string id,
string message,
int verbosity = UVM_NONE,
string filename = "",
int line = 0,
string context_name = "",
bit report_enabled_checked = 0);
也就是说,只要引用了uvm_pkg,就可以在任意地方直接使用uvm_report_info、uvm_report_warning、uvm_report_error和uvm_report_fatal了!
不过从函数内部中可以看到,真正是uvm_root类对象top调用的那四种消息函数,继承于uvm_component的!!!
2.2. 消息控制
很遗憾,在uvm_global.svh中并未定义消息控制方法。
但是uvm_root.svh提供了非常重要的静态方法get()来获取uvm_top对象,即UVM树的树根,该树根是uvm_root类型的,而uvm_root可是继承于uvm_component类的!!
因此在tb或object类定义中,均可使用uvm_root::get()来实现全局消息控制!
此处有一点不太明白的是,uvm_root::get().set_report_verbosity_hier(UVM_NONE);本质上还是调用的uvm_report_object::set_report_verbosity_hier(UVM_NONE);,那为何此处的object内的消息就能过滤?
例如
initial begin
uvm_root::get().set_report_verbosity_hier(UVM_NONE);
uvm_report_info("tb","test is going to run",UVM_LOW); //UVM_LOW > UVM_NONE会被过滤
run_test("my_test");
uvm_report_info("tb","test finished",UVM_LOW); //压根就不会执行这个,因为phase机制最后一句就是$finish()
end
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Starry__/article/details/122931088
————————————————
版权声明:本文为CSDN博主「Starry丶」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Starry__/article/details/122931088