上述函数都是在connect_phase及后面的phase使用
设置UVM_ERROR到达一定数量结束仿真
set_report_max_quit_count(int) 设成0就是无论多少error都不退出
get_report_max_quit_count() 返回如果是0,说明无论多少error都不退出 设置在main_phase前调用。
simv +UVM_MAX_QUIT_COUNT=10
3.4.4 3.4.5 3.4.6 3.4.7 我觉得应该用不大到,就不做笔记了
3.5 config_db机制
uvm_config_db#(类型)::set/get(component指针,”…”,”变量名字”,para4) 都是4个参数:
第一个参数是一个component指针,如果是null的话,相当于uvm_root::get() 第二个参数是个路径字符串, 第一和第二两个参数组和成一个完整的路径 第三个参数对于set、get要完全一致,是变量名字 set的para4是数值,get的para4是变量
component中的成员变量如果:
1) component用uvm_component_utils宏注册 2) 变量用field-automation宏注册
3) component的build_phase函数里有super.build_phase(phase) 那么可以省略get语句
跨层次多重set的时候,看set的第一个参数,层级越高,优先级越高。 调用set的时候,第一个参数尽量使用this 同层次设置的时候是时间优先
非直线设置的时候注意 第一和第二参数的使用,如果需要parent指针,则要用this.m_parent
config_db机制支持通配符,但是作者不推荐使用通配符。 但是在对sequence的成员set的时候需要用通配符(6.6.1章节)。 使用如下函数调试 config_db
check_config_usage() print_config(1/0) 这两个函数在connect_phase函数中调 simv +UVM_CONFIG_DB_TRACE
注意:第二个参数设置错误不会报错!!------- config_db机制务必要注意参数的书写。
第4章 UVM中的TLM1.0通信
TLM 是Transaction Level Modeling缩写
这章要搞清楚 port export imp fifo以及几种操作function/task 和对应component中要实现的function/task
下面的箭头方向都是控制流的方向,不是数据流方向。
我觉得作为一个VMM用户会觉得TLM有点难理解,总想用VMM_CHANNEL去套,结果把自己搞晕。像port等其实是调imp所在component的task/function.
我看UVM源代码里有一个uvm_seq_item_pull_port的class,它的基类是uvm_port_base. 在uvm_driver的成员seq_item_port就是这个类型的。 与它对应的是uvm_seq_item_pull_imp,uvm_sequencer的成员seq_item_export就是这种类型。在my_agent.sv中会connect它们。
4.2端口互连
port是动作的发起者,export是动作接收者,但是需要以一个imp来结束。 可以port?export?imp port?port?imp 也可以port?imp export?imp
port?imp用的较多,port?port?imp可以用port指针赋值来实现port?port(4.3.2章节)
操作:
put get/peek transport, transport相当于一次put+一次get
peek和get的不同(4.3.4章节): 使用uvm_tlm_analysis_fifo的时候,get任务会使fifo中少一个transaction;而peek任务是fifo把transaction复制一份发出,内部缓存中的transaction不会减少。----- 一般情况下peek完以后,还得调get。
上述操作都有阻塞和非阻塞之分。 port export imp的类型也有blocking和nonblocking之分。 port/export/imp类型: put/get/peek/get_peek/transport blocking/nonblocking/不区分blocking-nonblocking之分
imp要多一个参数,除了声明transaction类型(或者REQ RSP类型)以外,还要声明实现这个接口的component
connect的一定是同类型的port/export/imp
TLM的关键在于“与imp对应的component中task/function的实现”。 假设A_port.connect(B_imp),那么需要实现的task/function为:
A_port nonblocking_put put blocking_transport nonblocking_transport transport get_peek B_imp nonblocking_put_imp put blocking_transport nonblocking_transport transport get_peek Task/function put transport transport get peek Function try_put can_put try_put can_put nb_transport nb_transport try_get can_get try_peek can_peek uvm_blocking_put_port uvm_blocking_put_imp put get/peek/get_peek和put类似, 上述task或function必须要实现,如果用不到就写个空函数(章节4.2.9)。
注意 上述task或者function的参数。 put是一个transaction参数,get/peek是output的transaction参数,transport是一个req参数一个output的rsq参数。
连接用connect函数实现,从名字就可以看出来,这个必须在connect_phase中调。
4.3通信方式
这节应该是本章重点。 实际使用中用analysis_port?analysis_imp 还是 port?tlm_analysis_fifo?port 可以根据实际情况自己决定。
analysis_port(analysis_export)可以连接多个imp(一对多的通信) ?? put和get系列端口与相应imp的通信通常是一对一的(可以一对多,但是本书没有给出一对多的例子 4.2.1章节有介绍)。 analysis_port(analysis_export)更像是一个广播
analysis_port(analysis_export)没有阻塞和非阻塞的概念。它是一个广播,不等与它相连的其他端口的响应。
analysis_port(analysis_export)必须连的imp是analysis_imp. analysis_imp所在的component必须定义个write的function --------- 注意:是function
代码示例:4.3.1示例代码的analysis_port文件夹
component C和B的代码基本一致。 env的connect_phase函数里做connect:
component中有多个imp的时候,如何实现write函数?
4.3.2给的例子中,scoreboard有两个imp,分别从output_agent和reference-model的analysis_port获取transaction,然后做compare. 这个时候需要用:
`uvm_analysis_imp_decl(_标记) 这个macro,然后“write”函数变成 “write_标记()”函数,analysis_port所在component不用变,还是调write()函数即可。 代码示例如下:
使用macro声明
write函数变名字
analysis_port所在component实现不变。
使用uvm_analysis_fifo(uvm_tlm_analysis_fifo), analysis_fifo的本质是一块缓存+两个imp. 用fifo来实现 port?fifo?port
使用fifo最重要的是 选好两端的port类型,然后根据选好的两端port类型,来选择fifo上要连接的imp/export fifo本身实现了write() put() get() peek()等一系列的function/task,在两端port所在的component中直接调就可以。
连接在fifo两端的都是port,所以connect函数的起点是两端。 4.3.3的示例代码:
可以看到env里声明的几个fifo都是connect_phase函数中connect函数括号里的参数。