2022.11.22
今天开始学习张强作者的《UVM实战》,感觉很有意思,讲的非常清楚,推荐大家去看看。
1、通过在new
函数时指定parent
参数来形成树形结构
只有uvm_component
派生的类,才有节点。
2、phase机制自动执行
build_phase
的内容,一般有:利用config_db set/get
传递参数;实例化成员变量。
build_phase
是一个function,不消耗仿真时间;main_phase
是一个task,消耗仿真时间
两大特性带来的限制:
uvm_component:只能使用copy函数,不能使用clone函数。
因为clone出来的实例没有指定parent参数
除派生自uvm_component
类之外的类都是派生自uvm_object
的类
1、uvm_sequence_item
:产生transaction
为什么不从uvm_transaction类直接去产生transaction?
uvm_sequence_item派生于uvm_transaction,但前者添加了更多函数和变量、任务,直接从前者派生可以直接使用这些。
uvm_sequence和uvm_sequencer,以及uvm_sequence_item的区别?
sequence
:object类,生命周期较短,sequence_item的组合
sequencer
:component类,存在于整个仿真期间,调度其中的sequence和driver之间的传输
2、uvm_sequence
:sequence是sequence_item的组合,将transaction发送给sequencer
3、config
:规范验证平台的行为方式
把所有的参数放到一个object中,然后使用config_db进行配置
4、uvm_reg_item
:派生自uvm_sequence_item,用于reference model
5、uvm_phase
:控制uvm_component的行为
记住每个组件的功能
(1)driver(参数化类):主动向sequencer索要sequence_item,即transaction。并将sequence_item的信息驱动到DUT的端口上。相当于完成从transaction到signal端口级别的转换。默认RSP=REQ
//driver的端口
uvm_seq_item_pull_port #(REQ, RSP) seq_item_port(可以get和put)
uvm_analysis_port #(RSP) rsp_port(广播模式,一对多,广播response)
//sequencer的端口
uvm_seq_item_pull_imp #(REQ, RSP, this_type) seq_item_export(名字叫export,实际上是imp类型)
uvm_analysis_export #(RSP) rsp_export(代表中间节点,因为sequencer里面有个rsp tlm fifo,export连接到内部的imp端口。没有req的端口,不会对request缓存)
//连接
driver::seq_item_port.connect(sequencer::seq_item_export)
driver::rsp_port.connect(sequencer::rsp_export)
seq_item_port所支持的方法/任务(重要):
get_next_item
(output REQ req_arg):blocking的方法等待从sequence获得下一个itemtry_next_item
(output REQ req_arg):nonblocking的方法等待从sequence获得下一个item,返回的结果是null,表示没有准备好item_done
(input RSP rsp_arg = null):通知sequence item已经消化完毕,也可以选择性传递responsewait_for_sequences
():等待当前的sequence直到产生下一个item。和2配合起来就是1的作用has_do_available
():如果当前的sequence准备好且可以获取下一个item则返回1,否则0put_response
(input RSP rsp_arg):采取nonblocking的方式发送response,成功返回1,否则为0。可以独立地发送responseget/peek/put
():put是采用blocking的方式把response发送给sequence(这三个是由于此处端口继承于TLM 端口,所以继承了响应的方法)(2)sequence:包含一些item/transaction
create_item
()创建request item对象start_item
()准备发送item。立即返回的,是非阻塞类型
随机处理
。一定要在发送之前做完finish_item
()完成item发送。不是立即返回的,是阻塞类型,要等待driver发送出来的item_doneresponse item
.如果item_done传递了rsp,那么久需要配对使用,也是阻塞的item在start_item之后,因为挂载在了sequencer的上面,所以会通过句柄调用sequencer的send_request
和wait_for_item_done
函数,同时这两个又会去调用driver的函数,连接起来。
(3)sequencer(参数化类):负责调度sequence与driver之间的传输。
没有指明传输的transaction类型的话,缺省就是uvm_sequence_item类型,是父类类型,因此后续存在类型转换,父类句柄指向子类的对象, 将REQ转换为子类的item类型,才能获取有效的成员数据。
(4)monitor:没有增加任何新的成员和方法,继承自uvm_component,但是基本没有任何扩展功能,就是为了完善UVM验证的树形结构,使验证环境完善而已。
(5)agent(is_active枚举变量):包括driver和monitor。继承自uvm_component,但是基本上没有任何扩展。
(6)reference model:uvm里没有定义这个类,通常定义referrence model继承自uvm_component,可以用systemverilog或者DPI等接口调用其它语言,来完成与DUT相同的功能。
(7)scoreboard:负责比较referrence model与monitor分别发送过来的数据,根据比较结果判断DUT是否验证成功的工作。继承自uvm_component,但是基本没有任何扩展功能。
(8)env:继承自uvm_component,但是基本上没有任何扩展,封装固定不变的component。
(9)test:uvm_test里,都要实例化uvm_env。继承自uvm_component,但是基本上没有任何扩展。
(10)root:uvm_top
是uvm_root
类唯一的实例,所在的域是uvm_pkg
,是全局变量,可以通过uvm_root::get()
函数来获取句柄。uvm_top是所有test组件的顶层(parent是null,默认是uvm_top)
头文件
'include "uvm_macros.svh"
//加载所有uvm宏
import uvm_pkg:: *;
//加载所有uvm类
uvm_object_utils
:把一个直接或间接继承自uvm_object的类,注册到factory里。
uvm_object_utils_begin
:主要是配合field_automation
机制
uvm_object_utils_end
:主要是配合field_automation机制
uvm_object_param_utils
:把一个直接或间接继承自uvm_object的带参数的类,注册到factory里。
get_parent():当前实例的parent,每个component只有一个parent,但是可以有多个child
get_child(string name):获取child的parent
get_children(ref uvm_component children[$]):得到所有child
get_first_child
get_next_child
get_num_children:数量
get_full_name()
:在driver中使用得到的是——uvm_test_top.env.i_agt.drv
'uvm_field_int/real/string/event/object/enum
动态静态数组、队列中就没有real和event类型
常用函数:
copy:B.copy(A),复制
clone
print
compare:相同为1,不同为0
pack pack_bytes pack_bits pack_ints
unpack…
1、信息显示冗余度级别 verbosity(整数): 低于设置值的都会显示
UVM_NONE = 0,表示没有filter可以过滤,表示最重要
UVM_LOW = 100,表示很难滤除,则表示该条信息很重要,low以及low以下的会被打印出来
UVM_MEDIUM = 200
UVM_HIGH = 300,表示很高,很容易滤除
UVM_FULL = 400
UVM_DEBUG = 500
2、uvm_action_type:不同的位偏移,所以用或连接在一起
UVM_NO_ACTION = 6’b000000 不做任何操作
UVM_DISPLAY = 6’b000001 输出显示
UVM_LOG = 6’b000010 输出到日志文件
UVM_COUNT = 6’b000100 计数
UVM_EXIT = 6’b001000 直接退出
UVM_CALL_HOOK = 6’b010000 调用回调函数
UVM_STOP = 6’b100000 停止仿真,进入命令行交互模式
3、相关函数:
get_report_verbosity_level
:得到某个component的冗余度阈值
set_report_verbosity_level
:设置,由于牵扯到层次,需要在connect phase及之后使用
set_report_verbosity_level_hier
:递归设置,他和以下层次的都设置
set_report_id_verbosity
:区分不同id的冗余度
可以通过命令行设置
+UVM_VERBOSITY = UVM_HIGH
:
error达到一定数量停止仿真:build phase中设置,其他phase也可以
set_report_max_quit_count(5)
对warning进行计数
drv.set_report_severity_action
(UVM_WARNING, UVM_DISPLAY | UVM_COUNT)
设置断点
drv.set_report_severity_action
(UVM_WARNING, UVM_DISPLAY | UVM_STOP)
在UVM验证平台间传递参数
uvm_config_db #(int) :: set(this, "env.i_agt.drv", "num", 100)
第一个+第二个参数是目标路径,第二个参数是相对于此实例的相对路径
第三个参数是要set值得名称,set和get中要一样,才能找到
第四个参数是要设置的值
uvm_config_db #(int) :: get(this, " ", "num", num)
第一个参数都必须是component实例的指针
在top_db中设置virtual interface的时候,第一个参数为null
原因:top-db不是类,无法使用component实例的指针,所以使用null。null相当于uvm_root :: get( )
,这样得到的就是uvm_top
。
第二个参数:uvm_test_top.env.i_agt.drv
super.build_phase( )
,在这里会自动指向get语句第一:优先级
第二:时间先后顺序,以最近的为准。build_phase是自上之下执行,以此来判断
check_config_usage( )
:显示出截止到此函数调用,哪些参数被设置过但是没有读取。在connect_phase
中调用。
print_config(1)
:1表示递归查询,0表示显示当前component的信息
遍历验证平台的所以结点,找出哪些设置信息是可见的。在connect_phase
中调用。
命令行:+UVM_CONFIG_DB_TRACE
可以把变量写到config的包里面,这个config继承于uvm_object
类
首先,uvm_config_db去get的时候拿到的是uvm_object类,要转换为子类,才能使用子类的成员变量。
而在顶层环境中,要先创建这个config包,然后set给component,之后才能根据配置进行创建实例。必须要先set再创建实例
内置了UVM世界核心的组件和方法,独立于object和component之外,仿真开始时自动例化一次。该类并非uvm_component或uvm_object,它并没有例化在UVM环境中,而是独立于UVM环境之外。
uvm_factory
:唯一,用来做注册、覆盖和例化report_serve
:全局,用来做消息统筹和报告tr_database
:全局,记录transaction,方便调试get_root
:返回当前UVM环境的结构顶层对象这个核心组件如同一个随时待命的仆人,做好服务的准备。理论上,用户可以获取核心服务类中的任何一个对象,例如uvm_default_factory对象,继而直接利用factory来实现创建和覆盖。当然,创建和覆盖也可以由其它方式完成。
1、什么是UVM?UVM的优势有哪些?
UVM(通用验证方法)是一种用于验证数字设计标准化的简单方法。
优势:
2.uvm_component和uvm_object之间有何区别?
或者我们已经拥uvm_object,为什么我们需要uvm_component这种实际派生自的uvm_object类?
uvm_component
派生于uvm_object
,作为组件,准静态实体,存在于整个仿真周期,生命周期较长;而object类在需要时创建,从一个 组件到另一个组件然后消失,生命周期较短,动态实体。3、为什么build_phase是自顶而下而connect_phase是自底而上?
connect_phase旨在用于在组件之间建立TLM类型的连接,这就是它在构建阶段之后发生的原因。它自底而上工作,以便在设计层次结构中获得正确的实现,如果从上到下工作,这是不可能的。