第三章 UVM基础

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第三章 UVM基础相关的知识,希望对你有一定的参考价值。

参考技术A

uvm_object是UVM中最基本的类。

uvm_component有两大特性uvm_object所没有的:(1)通过在new的时候指定parent参数来形成一种属性的组织结构;(2)有phase的自动执行特点。

只有基于uvm_component派生的类才可能成为UVM树的结点。




除了driver, monitor, agent, model, scoreboard, env, test之外的几乎所有的类,本质上都是uvm_object,如sequence, sequence_item, transaction, config等。


uvm_sequence_item :所有transaction要从uvm_sequence_iem派生。 uvm_sequence_item是从uvm_transaction派生而来的,它相比uvm_transaction添加了很多实用的成员变量和函数/任务。

uvm_sequence :所有sequence要从uvm_sequence派生,sequence就是sequence_item的组合。

config :所有的config一般直接从uvm_object派生,其主要功能就是规范验证平台的行为方式。config是把所有参数放在一个object中,然后通过config_db的方式设置给所有需要这些参数的component。

uvm_reg_item :派生自uvm_sequence_item,用于register model中。

uvm_reg_map, uvm_mem, uvm_reg_field, uvm_reg, uvm_reg_file, uvm_reg_block 等与寄存器相关的众多的类都是派生自uvm_object,它们都是用于register model。

uvm_phase :派生自uvm_object,主要作用为控制uvm_component的行为方式,使得uvm_component平滑地在各个不同的phase之间依次运转。


uvm_driver :所有的driver都要派生自uvm_driver。driver的主要功能就是向sequencer索要sequence_item(transaction),并且将sequence_item里的信息驱动到DUT的端口上,这相当于 完成了从transaction级别到DUT能接受的端口级别信息的转换 。与uvm_component相比,uvm_driver多了如下几个成员变量:

            uvm_seq_item_pull_port    #(REQ, RSP)    seq_item_port;

            uvm_seq_item_pull_port    #(REQ, RSP)    seq_item_prod_if;

            uvm_analysis_port    #(RSP)    rsp_port;

            REQ    req;

            RSP    rsp;


uvm_monitor :所有的monitor都要派生自uvm_monitor。monitor从DUT的pin上接收数据,并且把接收到的数据转换成transaction级别的sequence_item,再把转换后的数据发送给scoreboard,供其比较。与uvm_component相比,uvm_monitor几乎没有做任何扩充。

uvm_sequencer :所有的sequencer都要派生自uvm_sequencer。sequencer的功能就是组织管理sequence,当driver要求数据时,它就把sequence生成的sequence_item转发个driver。与uvm_component相比,uvm_sequencer做了相当多的扩展。

uvm_scoreboard :一般的scoreboard都要派生自uvm_scoreboard。uvm_scoreboard几乎没有在uvm_component的基础上做扩展。

reference model :直接派生自uvm_component。

uvm_agent :所有agent派生自uvm_agent。它把driver和monitor封装在一起。与uvm_component相比,uvm_agent的最大改动在于引进了一个变量is_active。

uvm_env :所有的env都要派生自uvm_env。env将验证平台上用到的固定不变的component都封装在一起。uvm_env没有在uvm_component的基础上做过多扩展。

uvm_test :所有的测试用例都要派生自uvm_test或其派生类,不同的测试用例之间差异很大。uvm_env没有在uvm_component的基础上做任何扩展。


在UVM中与uvm_object相关的factory宏有如下几个:

            uvm_object_utils :用于把一个直接或间接派生自uvm_object的类注册到factory中。

            uvm_object_param_utils :用于把一个直接或间接派生自uvm_object的参数化的类注册到factory中。

            uvm_object_utils_begin :当需要使用field_automation机制时,需要使用此宏。

            uvm_object_param_utils_begin

            uvm_object_utils_end :与uvm_object_*_begin成对出现,facotry注册的结束标志。


在UVM中与uvm_component相关的factory宏有如下几个:

            uvm_component_utils

            uvm_component_param_utils

            uvm_component_utils_begin :在component中使用field_automation机制,可以自动地使用config_db来得到某些变量的值。

            uvm_component_param_utils_begin

            uvm_component_utils_end


uvm_component无法使用 clone 函数,但是可以使用 copy 函数。 (clone = new + copy)

位于同一个父结点下的不同component,在实例化时不能使用相同的名字。





UVM中真正的树根是一个称为uvm_top的东西。uvm_top是一个全局变量,它时uvm_root的一个实例(而且也是唯一一个实例),而uvm_root派生自uvm_component,uvm_top的parent是null。

如果一个component在实例化时,其parent被设置为null,那么这个component的parent将会被系统设置为uvm_root的实例uvm_top。还可以使用如下方式得到它的指针:

            uvm_root top;

            top = uvm_root::get();

UVM提供了一系列的接口函数用于访问UVM树中的结点:

            get_parent()

            get_child(string name) :name表示此child的实例在实例化时指定的名字。

            uvm_component array[$]

             get_children(array)

            get_num_children()



`define uvm_field_**_**(ARG, FLAG)


copy 函数:

            B.copy(A):把实例A复制到B实例中,B必须已经使用new函数分配好了内存空间。

compare 函数:

            A.compare(B) or B.compare(A)。

pack_bytes 函数:

            用于将所有字段打包成byte流。

unpack_bytes 函数:

            用于将一个byte流逐一恢复到某个类的实例中。

pack 函数:

            用于将所有的字段打包成bit流。

unpack 函 数:

            用于将一个bit流逐一恢复到某个类的实例中。

pack_ints 函数

unpack_ints 函数

print 函数

clone 函数

UVM的标志位本身是一个17bit的数字:




在打印信息之前,UVM会比较要显示信息的冗余度级别与默认的冗余度阈值。如果小于等于阈值,就会显示。默认的冗余度阈值时UVM_MEDIUM,所有低于等于UVM_MEDIUM的信息都会被打印出来。

get_report_verbosity_level 函数:得到某个component的冗余度阈值。

set_report_verbosity_level 函数:设置某个特定的component的默认冗余度阈值。由于需要牵扯到层次引用,所以需要在connect_phase及之后的phase才可以调用这个函数。如果不牵扯到任何层次引用,就可以在之前调用。

set_report_verbosity_level_hier 函数:设置某个component及其以下所有的component的冗余度阈值。

set_report_id_verbosity 函数:根据不同的uvm_info宏的id来设置冗余度阈值。

set_report_id_verbosity_hier 函数

UVM支持在命令行中设置冗余度阈值:

            <sim command> +UVM_VERBOSITY=UVM_HIGH

            <sim command> +UVM_VERBOSITY=HIGH        

            将整个验证平台的冗余度阈值设置为UVM_HIGH。


set_report_severity_override(UVM_WARNING, UVM_ERROR);

set_report_severity_id_override(UVM_WARNING, "my_driver", UVM_ERROR);

命令行中实现:

            <sim command> +uvm_set_severity=<comp>,<id>,<current severity>,<new severity>


set_report_max_quit_count(number);


set_report_severity_action(UVM_WARNING, UVM_DISPLAY | UVM_COUNT):把UVM_WARNING加入计数目标。

set_report_severity_action_hier(UVM_WARNING, UVM_DISPLAY | UVM_COUNT);

set_report_severity_action(UVM_ERROR, UVM_DISPLAY):把UVM_ERROR从统计计数目标中移除。

set_report_id_action("my_drv", UVM_DISPLAY | UVM_COUNT):对某个特定的ID进行计数。把ID为my_drv的所有信息加入到计数中,UVM_INFO, UVM_WARNING, UVM_ERROR, UVM_FATAL。

set_report_severity_id_action(UVM_WARNING, "my_driver", UVM_DISPLAY | UVM_COUNT);

......

命令行中设置技术目标:

            <sim command> +uvm_set_action=<comp>,<id>,<severity>,<action>

当程序执行到断点处时,停止仿真,进入交互模式,从而进行调试。

"base_test.sv"

virtual function void connect_phase(uvm_phase phase);

    env.i_agt.drv.set_report_severity_action(UVM_WARNING, UVM_DISPLAY | UVM_STOP);

...

当env.i_agt.drv中出现UVM_WARNIN时,立即停止仿真,进入交互模式。

命令行中设置UVM断电:

            <sim command> +uvm_set_action="uvm_test_top.env.i_agt_drv,my_driver,UVM_WARNING,UVM_DISPLAY | UVM_STOP"





变量名与其实例化时传递的名字不一致的情况应该尽量避免。


config_db机制用于在UVM验证平台间传递参数,set函数和get函数通常成对出现。


在某些情况下,可以省略get语句:

(1)必须使用uvm_component_utils宏注册;(2)变量必须使用uvm_field宏注册;(3)在调用set函数的时候,set函数的第三个参数必须要与get函数中的变量名字相一致。


UVM规定层次越高,它的优先级越高。越靠近根结点uvm_top,其层次越高,set函数的优先级也越高。

寄信人的层次相同时,比较寄信的时间。

在调用set函数时其第一个参数应该尽量使用this。在无法使用this指针的情况下(如在top_tb中),使用null或者uvm_root::get()。



非直线的设置,如在scoreboard中对driver的某些变量使用config_db机制进行设置:

            uvm_config_db#(int)::set(this.m_parent, "i_agt.drv", "pre_num", 200);

            or

            uvm_config_db#(int)::set(uvm_root::get(), "uvm_test_top.env.i_agt.drv", "pre_num", 200);


非直线的获取,如在reference model中获取其他component设置给my_driver的参数的值:

            void\'(uvm_config_db#(int)::get(this.m_parent, "i_agt.drv", "pre_num", drv_pre_num));

            or

            void\'(uvm_config_db#(int)::get(uvm_root::get(), "uvm_test_top.env.i_agt.drv", "pre_num", drv_pre_num));


不推荐使用通配符。


如果set函数的第二个参数设置错误,不会给出错误信息。

check_config_usage()函数可以显示出截止到此函数调用时有哪些参数是被设置过但是却没有被获取过,此函数一般在connect_phase被调用。


print_config(1):参数1表示递归的查询,参数0只显示当前component的信息。

print_config会遍历整个验证平台的所有节点,找出哪些被设置过的信息对于它们是可见的。

命令行参数:

            <sim command> +UVM_CONFIG_DB_TRACE

以上是关于第三章 UVM基础的主要内容,如果未能解决你的问题,请参考以下文章

UVM系统验证基础知识0(Questasim搭建第一个UVM环境)

从零开始,搭建一个简单的UVM验证平台

UVM Primer - OOP基础 - 定义类

1.小白学uvm验证 - UVM搭建环境验证的主要框架和基本组成

自学uvm需要多长时间

Linux系列基础版第三章 Shell基础知识