24.类的继承关系
1.uvm_object是UVM中最基本的类,几乎所有的类都继承于它,包括uvm_component
2.uvm_component有两大特性是uvm_object所没有的
一是通过在new的时候指定parent参数来形成一种树形的组织结构;
二是phase的自动执行;
25.完整的UVM树![](https://i-blog.csdnimg.cn/blog_migrate/471045d3f3b2ddbd2c8ddbddea832d97.png)
1.所有的UVM树的结点都是由uvm_component组成的,只有基于 uvm_component派生的类才可能成为UVM树的结点
2.uvm_component是从uvm_object派生来的。从理论上来说,uvm_component应该具有uvm_object的所有的行为特征。
但是,由于uvm_component是作为UVM树的结点存在的,这一特性使得它失去了uvm_object的某些特征,例如无法使用clone函数。
3.UVM树根是uvm_top,它是uvm_root的唯一实例;同时也是一个全局变量,可以直接使用
26.常用的component类
1.uvm_driver:
与 uvm_component相比,uvm_driver多了几个成员变量;
向sequencer索要sequence_item(transaction),并且将 sequence_item里的信息驱动到DUT的端口上,完成从transaction级别到DUT能够接受的端口级别信息的转换
2.uvm_monitor:
与uvm_component相比,uvm_monitor几乎没有做任何扩充;
monitor做的事情与driver相反,driver向DUT的pin上发送数据,而 monitor则是从DUT的pin上接收数据,并且把接收到的数据转换成transaction级别的sequence_item,再把转换后的数据发送给 scoreboard,供其比较
3.uvm_sequencer:
与uvm_component相比,uvm_sequencer做了很多拓展;
4.uvm_scoreboard:
与uvm_component相比,uvm_scoreboard几乎没有做任何扩充;
scoreboard的功能就是比较reference model和monitor分别发送 来的数据,根据比较结果判断DUT是否正确工作;
5.uvm_agent:
与uvm_component相比,uvm_agent的最大改动 在于引入了一个变量is_active;
它只是把driver、monitor和sequencer封装在一起,根据参数值来决定是只实例化monitor还是要同时实例化其余组件;
27.常用的object类
1.uvm_sequence_item:
所有的transaction要从该类派生,虽然该类派生自uvm_transaction,但是相比uvm_transaction添加了很多实用的成员变量和方法,所以transaction不能直接派生自uvm_transaction反而要从uvm_sequence_item派生;
2.uvm_sequence:
所有的sequence要从该类派生,sequence是sequence_item的组合。
3.config:
区别于config_db,config指的是把所有的参数放在一个object中,然后通过config_db的方式设置给所有需要这些参数的component。
4.uvm_phase
主要作用为控制uvm_component的行为方式,使得uvm_component平滑地在各个不同的 phase之间依次运转
5.寄存器模型相关
28.层次结构相关函数
1.get_parent
get_parent函数,用于得到当前实例的parent;
2.get_children
得到所有的child;
29.field automation
`define uvm_field_int(ARG,FLAG) `define uvm_field_real(ARG,FLAG) `define uvm_field_enum(T,ARG,FLAG) `define uvm_field_object(ARG,FLAG) `define uvm_field_event(ARG,FLAG) `define uvm_field_string(ARG,FLAG)
上述几个宏分别用于要注册的字段是整数、实数、枚举类型、直接或间接派生自uvm_object的类型、事件及字符串类型。除了枚举类型,都是两个参数。对于枚举类型来说,需要有三个参数。
除此之外,field automation还支持动态数组、队列、联合数组等。
30.field automation
主要提供了如下函数
1.copy
copy函数用于实例的复制
2.compare
compare函数用于比较两个实例是否一样
3.pack_bytes
pack_bytes函数用于将所有的字段打包成byte流
打包顺序与宏声明顺序一致
4.unpack_bytes
unpack_bytes函数用于将一个byte流逐一恢复到某个类的实例中
5.print
print函数用于打印所有的字段
6.clone
clone = copy + new component不支持clone
field automation机制还提供自动得到使用config_db::set设置的参数的功能
31.相关的宏
1.uvm_object(component)_utils_begin
需要使用field_automation机制时,需要使用此宏;
2.uvm_object(component)_utils_end
与1成对出现,作为factory注册结束的标志;
filed_automation机制对于uvm_component来说最大的意义不在于此,而在于可以自动地使用config_db来得到某些变量的值
32.打印信息的控制
设置冗余度
1.set_report_verbosity_level
set_report_verbosity_level函数来设置某个特定component的默认冗余度阈值
有可递归函数
2.+UVM_VERBOSITY=HIGH
命令行参数会把整个验证平台的冗余度阈值设置为UVM_HIGH,相当于在base_test中调用了递归函数;
设置计数
3.set_report_max_quit_count
当uvm_fatal出现时,表示出现了致命错误,仿真会马上停止;
uvm同样支持UVM_ERROR达到一定数量时结束仿真;
4.set_report_severity_action
可以将UVM_WARNING也加入计数;
设置打印
5.set_report_severity_file
输出信息分类输出到不同的日志文件
33.config_db
1.uvm_macros.svh文件通过include语句包含进来。这是UVM中的一个文件,里面包含了众多的宏定义,只需要包含一次
2.import语句将整个uvm_pkg导入验证平台中。只有导入了这个库,编译器在编译my_driver.sv文件时才会识别其中的 uvm_driver等类名
34.TLM通信(transaction level modeling 事务级建模)
1.利用TLM通信实现不同组件之间的联系;
2.TLM中常用的操作有:
put:通信发起者A把一个transaction发给B;
get:通信发起者A向B索取一个transaction;
transport:相当于1次put+1次get,A向B提交1个request,B返回给A1个response;
3.put、get和transport操作都有阻塞和非阻塞之分;
以关键字blocking和nonblocking关键字区分,对于名称中不含这两者的,可以表示这个端口既可以用作阻塞,也可以用作非阻塞;
4.优先级:port>export>import
只有高优先级的端口才能向低优先级的端口发起操作;
5.UVM中使用connect函数来建立连接关系,只有发起者才能调用connect;
6.默认min_size=max_size,只能连接一个EXPORT;
function new(string name, uvm_component parent, int min_size = 1; int max_size = 1);
7.只有IMP才能作为连接关系的终点;
如果是PORT或者EXPORT作为终点,则会报错;
8.当A_port的类型是nonblocking_put,B_imp的类型是nonblocking_put时,那么就要在B中定义一个名字为try_put的函数和一个名为can_put的函数;
9.当A_port的类型是put,B_imp的类型是put时,那么就要在B中定义3个接口,一个是put任务/函数,一个是try_put函数,一个是can_put函数;
若不使用can_put,依然需要定义一个名字为can_put的函数,这个函数可以是一个空函数
35.analysis端口
1.除了PORT、EXPORT、IMP之外,还有两种特殊端口:analysis_port/export
2.与put/get系列端口的区别:
一个analysis_port可以连接多个IMP,更像是一个广播;
对于analysis_port/export来说,没有阻塞和非阻塞的概念;
3.对于analysis_port和 analysis_export来说,只有一种操作:write。在analysis_imp所在的component,必须定义一个名字为write的函数
4.一个analysis_port可以和多个IMP连接通信,但是IMP的类型必须是uvm_analysis_imp,否则会报错;
5.某个组件有超过1个以上的analysis_imp时,使用宏uvm_analysis_imp_decl添加后缀
只要完成后缀的声明,并在write 后面添加上相应的后缀就可以正常工作了
36.使用FIFO通信
1.fifo的本质是一块缓存加两个IMP;
2.FIFO中的端口名中有关键字export,但是其类型却是IMP
3.使用fifo通信的好处
不必在imp的component中写write函数
fifo的存在隐藏了imp
4.除transport系列外的12种IMP,还有put_ap和get_ap两个端口。
当FIFO上的put_export被连接到一个put_port上时,FIFO内部被定义的put任务被调用,这个put任务把传递过来的transaction放在FIFO内部的缓存里,同时,把这个transaction通过put_ap使用write函数发送出去
5.FIFO内部的缓存,使用SystemVerilog中的mailbox来实现;
6.FIFO的类型有两种,uvm_tlm_analysis_fifo和uvm_tlm_fifo。
唯一差别在于前者有一个 analysis_export端口,并且有一个write函数,而后者没有
7.使用fifo还是IMP?
用FIFO通信的方法中,完全隐藏了IMP,大大简化了初学者的工作量。
尤其是在面临多个IMP,且需要为IMP声明一个后缀时,这种优势更加明显。
FIFO连接的方式增加了env中代码的复杂度;
对于使用端口数组的情况,FIFO要优于IMP;
综上:见仁见智,看个人习惯以及实际情况;
37.UVM中的phase![](https://i-blog.csdnimg.cn/blog_migrate/dfdb80ae5b2b81a120b1132f1a1e14e1.png)
38.task phase和function phase
1.如37所示,灰色部分为task phase,白色部分为function phase。
上述phase会按照图中的顺序自上而下自动执行;
2.对于function phase来说,在同一时间只有一个phase在执行;
对task phase来说,run_phase和pre_reset_phase等12个小的phase并行运行;
后者称为动态运行( run- time)的phase
3.这么多phase,除了方便验证人员将不同的代码写在不同的phase外,还有利于其他验证 方法学向UVM迁移;
4.为什么引入12个小的phase?
分成小的phase是为了实现更加精细化的控制;
reset、configure、main、shutdown通常模拟DUT的正常工作方式,在reset_phase对DUT进行复位、初始化等操作,在configure_phase则进行DUT的配置,DUT的运行主要在main_phase完成,shutdown_phase则是做一些与DUT断电相关的操作;
39.phase的执行顺序
1.除了build phase、final phase,其余的function phase都是自底向上;
2.uvm_object的实例化,可以在任何phase完成;
3.对于同一层次的、具有兄弟关系的component,按照字典序的;
4.对于叔侄关系的component,UVM采用的深度优先的原则。
5.run_phase——自下而上的启动,同时在运行;
40. super.phase
1.对于build_phase来说,uvm_component对其做的最重要的事情就是自动获取通过config_db::set设置的参数;
2.除了build phase外,uvm在其他phase中几乎没有做任何相关的事;
但是建议加上super,出于代码规范;
41.build阶段出现UVM_ERROR停止仿真
1.在仿真过程中,出现uvm_fatal直接退出;
2.在end_of_elaboration_phase及其前的phase中出现UVM_ERROR也会退出放这个吧;
在大型设计中,这一特性非常有用,将所有类似的问题一次性暴露出来,一次性修复,这会极大缩减时间,提高效率;
42.phase的跳转
1.jump函数
jump函数的参数必须是一个uvm_phase类型的变量
2.哪些phase可以作为jump的参数
uvm_pre_reset_phase::get()后的所有phase都可以
3.向前跳转
只能是main_phase前的动态运行phase中的一个
4.向后跳转
除了动态运行的phase外,还可以是function phase。
43.超时退出
1.通过uvm_root的set_timeout函数可以设置超时时间;
2.第一个参数是要设置的时间,第二个参数是否可以被其后的set_timeout覆盖;
3.默认超时退出时间是9200s,通过宏UVM_DEFAULT_TIMEOUT来指定;
44.domain
1.domain是UVM中一个用于组织不同组件的概念
2.默认情况,验证平台所有component都位于一个名字为common_domain的domain中;
3.domain只能隔离run-time的phase,对于其他phase,其实还是同步的,即两个domain的run_phase依然是同步的,其他的function phase也是同步的;
4.多domain中phase的跳转将只局限于某一domain中;