lab3
TLM单向通信和多项通信
- TLM通信结构
- 连接端口时,是initiator(左边)调用connect函数,里边参数为target(右边)。
- port和export端口,只需要指定transaction参数类型;而声明imp端口,则需要同时指定transaction参数类型以及所在的component类型。
- **多向通信时,imp一端要声明端口宏来解决。**即让不同端口对应不同名的任务,来解决方法名的冲突问题。
//端口宏声明
`uvm_blocking_put_imp_decl(_chnl0)
`uvm_blocking_put_imp_decl(_chnl1)
`uvm_blocking_put_imp_decl(_chnl2)
//imp端口声明
uvm_blocking_put_imp_chnl0 #(mon_data_t, mcdf_checker) chnl0_bp_imp;
uvm_blocking_put_imp_chnl1 #(mon_data_t, mcdf_checker) chnl1_bp_imp;
uvm_blocking_put_imp_chnl2 #(mon_data_t, mcdf_checker) chnl2_bp_imp;
//在new函数中例化端口
chnl0_bp_imp = new("chnl0_bp_imp", this);
chnl1_bp_imp = new("chnl1_bp_imp", this);
chnl2_bp_imp = new("chnl2_bp_imp", this);
TLM通信管道
- 使用port、export、import后,还需自己在target一端调用具体的get/peek/put()方法,那么有没有既可以使用TLM端口,又不用自己去实现具体的方法呢?——有!那就是TLM通信管道!
- TLM通信管道的作用:可以不用在target一端实现传输方法,同时也能享受TLM的好处。
其分类如下:
1、TLM FIFO
- consumer在没有分析transaction时,希望先存储到本地FIFO中,稍后使用。uvm_tlm_fifo类是一个新组件,继承于uvm_componnet类,预先内置了多个端口以及实现了多个对应方法,用户无需自己实现这些方法,同时又能够享受TLM端口的好处。(注意,uvm_tlm_fifo只是声明了这些端口,当我们要使用的时候还是要例化的)
2、analysis端口
-
如果数据源端发生变化需要通知和它关联的多个组件,就可以用到analysis端口,可以满足一端到多端的通信。分类有:uvm_analysis_port、uvm_analysis_export、uvm_analysis_imp。
-
这是从一个initiator端到多个target端的方式。analysis port采用的是“push"模式,也就是从initiator端调用多个target端的write函数实现数据传输。
-
在initiator调用write函数时,实际上是通过循环的方式将所有连接的target内置的write函数进行调用。由于函数是立即返回的,所以无论连接多少个target,initiator端调用write函数总是可以立即返回。
-
和单一端口函数调用不同的是,即使没有和target相连,调用write函数时也不会发生错误。
-
analysis_port/analysis_export和port/export端口的区别:
1、可连接imp数量analysis_port、analysis_export更像是一个广播,可以一对多。
2、方法区别analysis_port、analysis_export没有阻塞、非阻塞的概念,因为本身就是广播,不必等待相连端口的响应(感觉也可以理解为非阻塞,因为马上返回)
analysis_port、analysis_export只有write一种操作,而port、export端口有put/get/peek等操作。
3、analysis TLM FIFO
- uvm_tlm_analysis_fifo继承于uvm_tlm_fifo,既有面向单一TLM端口的数据缓存特性,又可以实现一对多通信。
- 将initiator的analysis port连接到tlm_analysis_fifo的get_export端口,这样数据可以从initiator发起,写入到各个tlm_analysis_fifo的缓存中。
- 将多个target的get_port连接到tlm_analysis_fifo的get_export,注意保持端口类型的匹配,这样从target一侧只需要调用get方法就可以得到先前存储在tlm_analysis_fifo中的数据。
UVM回调类
-
callback机制必要性
-
callback机制的最大用处就是提高验证平台的可重用性。 很多情况下, 验证人员期望在一个项目中开发的验证平台能够用于另外一个项目。 但是, 通常来说, 完全的重用是比较难实现的, 两个不同的项目之间或多或少会有一些差异。 如果把两个项目不同的地方使用callback函数来做, 而把相同的地方写成一个完整的env, 这样重用时, 只要改变相关的callback函数,env可完全的重用。
-
例如,对于VIP( Verification Intellectual Property) 来说, 一个很容易预测到的需求是在driver中, 在发送transaction之前, 用户可能会针对transaction做某些动作, 因此应该提供一个pre_tran的接口, 如用户A可能在pre_tran中将要发送内容的最后4个字节设置为发送的包的序号, 这样在包出现比对错误时, 可以快速地定位, B用户可能在整个包发送之前先在线路上发送几个特殊的字节, C用户可能将整个包的长度截去一部分, D用户……总之不同的用户会有不同的需求。 正是callback机制的存在, 满足了这种需求, 扩大了VIP的应用范围。
-
工厂机制的override是为了覆盖,而callback是为了延伸。
-
声明一个回调类cb_mcdf_tast(继承于uvm_callback),在各个test中便可绑定、插入该回调类中的回调函数。
-
三步骤:
-
1、定义callback类:class cb1 extends uvm_callback;
-
2、绑定及插入callback:绑定及插入cb(在要预留callback函数/任务接口的类中调用uvm_register_cb进行绑定,并在调用callback函数/任务接口的函数/任务中, 使用uvm_do_callbacks宏来插入cb)
绑定:`uvm_register_cb(comp1,cb1) ;
插入: `uvm_do_callbacks(comp1,cb1,do_trans(d));
这里的cb1是类名,也就是还没创建该回调类的对象实例,还不能用。
-
3、添加callback:`uvm_callbacks #(comp1)::add(c1,m_cb1);c1和m_cb1都是实例名。已创建实例,可以调用回调函数了。
-
-
UVM仿真控制函数
- mcdf_base_test添加新的phase函数end_of_elaboration_phase(),用来在编译结束后的配置工作。-
- uvm_root::get().set_report_verbosity_level_hier(UVM_HIGH);——将信息的冗余度设低,依次来允许更多的低级别的信息打印出来。
- uvm_root::get().set_report_max_quit_count(1);——设置uvm_error数量超出指定值时结束仿真。
- uvm_root::get().set_timeout(10ms);——设置仿真最大时间。