《UVM实战》–张强编著。
uvm,可以理解为,是systemverilog的一个库,一个插件。集成了框架模板和有用函数。所以,学习uvm的前提是systemverilog基础要好。
有一些个人理解,是猜想,后续会不断迭代完善。
文章开始就提供了一个简单的UVM验证平台。网上有case下载资源,可以跑nc、vcs、modelsim仿真。
刚开始,没找网上case下载资源。基于cadence的irun命令,自己搭建了验证环境:
run:
@irun -sv \
-f filelist.f \
-licqueue \
-timescale 1ns/1ps \
-uvm \
-uvmhome $$UVM_HOME \
-input nopack.txt \
-access +rwc
clean:
@rm -rf INCA_libs *.shm *.log *.key
uvm_component/uvm_object等
;扩展类。比如uvm_driver/uvm_monitor/uvm_sequencer/uvm_scoreboard/uvm_object
等等,还有很多。`include "uvm_macros.svh"//这是加载所有uvm宏
import uvm_pkg::*; //这是加载所有uvm类
uvm_driver
中预先定义好了一个任务,叫做main_phase
,UVM
由phase
来管理验证平台的运行。可以简单认为,实现一个driver
,就是实现uvm_driver::main_phase
这个task
任务。get_full_name
函数,只能在component层次代码里调用。`uvm_info("uvm_componet tree!!!",get_full_name(),UVM_LOW);
factory
的实现,就是在自定义扩展类的时候,增加一条宏命令`uvm_component_utils
。在调用类的时候,run_test("classname");
。 my_driver
的描述, top_tb
里的代码段可以很大节省,提高移植性。 my_driver
实例化main_phase
可以简化为run_test("my_driver");
function
或者task
。uvm_component
及其派生类的类,都应该使用uvm_component_utils
宏main_phase
函数,会自动调用执行的。注意要配合objection机制,才能达到期望效果。objection
机制,实现验证平台的关闭。phase
中,UVM会检查是否有objection
被提起(raise_objection
),如果有,那么等待这个objection
被撤销(drop_objection
)后停止仿真;如果没有,则马上结束当前phase。run_test()
理解为创新一个类的实例,并会自动调用main_phase
开始执行。interface
概念工作内容
interface
,跟module同一级;interface
实例化uvm_config_db
机制,set和get两步操作,实现扩展类my_driver
和top_tb的interface
交互。 module top_tb
层次里class my_drivers
层次里。注意引入build_phase
;相对main_phase
,作用是在仿真为0的时刻时执行。uvm_config_db
就是一个参数化的类,#(参数);跟verilog很像。
uvm_test_top.i_agt.drv
里在build_phase块里,增加if(!uvm_config_db#(virtual my_if)::get(this,"","vif",vif)
`uvm_fatal("my_driver","virtual interface must be set for vif!!!")
解释:
当前实例路径下,vif
标记符合;于是把virtual my_if input_if
连接到该实例路径下的vif
8. 搞半天,就是为了实例化的连线方法。应该是为了利用interface的优势。
补充几句:
1. module里可以声明interface;即类interface的句柄化
2. class里不可以
声明interface;即类interface的句柄化。
3. 类class里,使用的是virtual my_if vif;
uvm_seqence_item
派生;uvm_component
和uvm_object
uvm_component
继承自uvm_object
;uvm_object
继承自uvm_void
;uvm_component
两大特性 uvm_component
派生的类,才有节点。uvm_component
的树形结构(每个结点是一个class实例)。uvm_component
才有树形结构,uvm_object
没有?uvm_object
是有生命周期的;uvm_component
没有生命周期。也就是说仿真过程中,uvm_object
在启动后可以finish
;uvm_component
是伴随仿真过程一直要存在的。这也是uvm_component
和uvm_object
的主要区别。uvm_component
的树形结构。uvm_component
树形结构 run_test()
命令,执行的先后顺序依次是:new()-->build_phase-->main_phase
uvm_object
的派生类介绍uvm_sequence_item
sequence_item
的集合。sequence_item
流通在uvm_component
之间。sequencer
继承自component,需要体现在树形结构里。必须
从uvm_sequence_item类派生。sequence的作用,是封装众多的sequence_item。
uvm_config_db
有什么意义?uvm_component
的行为准则。举例:比如规定driver在读取总线时,地址信号持续几个时钟;片选信号从什么时候开始有效等。config_db机制,主要用于UVM验证平台之间传输参数。set和get函数,都是成对出现的。
uvm_config_db
类的参数相关,如下例:uvm_config_db#(virtual my_if)::set(this,"i_agt.drv","vif",input_if)
第四个参数,就是要传递到uvm_test_top.i_agt.drv
的
uvm_config_db#(virtual my_if)::set(this,"","vif",input_if)
总之。需要注意:
- 路径要一致;
- 第一个参数尽量是this,因为有优先级,层次越高,config_db设置的优先级越高;
- 除了第一个参数带来的优先级问题,还有时间越后,config_db设置的优先级越高。
- 第三个参数,是个ID,就是为了在某一个实例层次下,通过ID精确匹配set和get而已。ID可以很随便,但要保证一一对应。
- 第四个参数,set对应的value;get对应的是变量名称。
- `config_db`支持通配符
- `config_db`第二个参数,如果写错,不会有错误报告的。一般使用`check_config_usage`来检查set和get的匹配情况。其中,`check_config_usage`一定要在`build_phase`之后,因为`config_db`在`build_phase`里执行;一般在`connect_phase`里。
- 仿真工具,也可以用参数命令,实现config_db的功能;但只支持int/string的数据类型。
- `config_db`,需要`set/get`成对出现;后文会有更高级的用法,使用`field_automation`来传递component的参数。
sequence_item
,即transaction。并将sequence_item
的信息驱动到DUT的端口上。is_active
。这个is_active
主要作用是让agent判断是否包含driver。因为in_agent
需要driver和monitor;而out_agent
不需要driver,只需要monitor。uvm_component
,但是基本上没有任何扩展。uvm_test
里,都要实例化uvm_env
;uvm_component
,但是基本上没有任何扩展。 'uvm_object_utils
uvm_object
的类,注册到factory里。'uvm_object_param_utils
uvm_object
的带参数的类,注册到factory里。 'uvm_object_utils_begin
…..'uvm_object_utils_end
'uvm_object_param_utils_begin
…..'uvm_object_param_utils_end
field_automation
机制。完全类似于uvm_object
相关宏。
区别只是parent参数不一样。
参数name是uvm树形结构的实例名称。
uvm_root
类实例化的uvm_top
。最后,uvm是不推荐使用new构造函数的。
uvm推荐type_name::type_id::create();
.
uvm_test_top
,而是uvm_top
?uvm_test
类实例化名称叫做uvm_top
,uvm_test
类的定义,包含case相关的参数。
一般由'uvm_component_utils_begin
…..'uvm_component_utils_end
定义。
而uvm_root
类,作用是设置top顶层,以及phase的运行。
个人理解,uvm_test
和uvm_root
可以设置成一个类;因为他们都可以作为最顶层,只能实例化一次。但是uvm的概念,包含可重用性的特点;case不同,uvm_test
会有变化;而uvm_root
是可重用的。
综上理解,顶层设置为uvm_test
,更方便测试环境的可重用。
- uvm_top
是一个全局变量,可以在任一层次,使用下述代码段获取uvm_top
的指针。
uvm_root top;
top=uvm_root::get();
get_children(ref uvm_component children[$]);
get_first_child
get_next_child
get_num_children
get_full_name();
pack_bytes、unpack_bytes
pack、unpack
pack_ints、unpack_ints
run_test()
命令,执行的先后顺序依次是:new()-->build_phase-->main_phase
build_phase
是一个function,不消耗仿真时间;main_phase
是一个task,消耗仿真时间。