UVM实战指南(7)

2019-08-30 16:37

但是,如果当需要子组件的port/export能够被外部看到的时候,该如何处理呢?这种情况下,需要通过将子组件的port连接到父组件的port上,将子组件的export连接到父组件的export上。

实例4-8: 连接子组件的port到父组件的port

class parent_producer extends uvm_component; uvm_blocking_put_port #(simple_packet) put_port; producer child_producer_inst;

function new(string name, uvm_component parent); put_port = new(\

child_producer_inst = new(\ endfunction

virtual function void connect();

child_producer_inst.put_port.connect(put_port); endfunction endclass

通用的规则是:当连接子组件的port到父组件的时候,子组件port的connect函数被调用,其调用参数是父组件的port.

实例4-9: 连接子组件的export到父组件的export

class parent_consumer extends uvm_component;

uvm_blocking_put_export #(simple_packet) put_export; consumer child_consumer_inst;

function new(string name, uvm_component parent); put_export = new(\

child_consumer_inst = new(\endfunction

virtual function void connect();

put_export.connect(child_consumer_inst.put_export); endfunction endclass

通用的规则是:当连接子组件的export到父组件的export时,父组件export的connect函数被调用,其调用参数是子组件的export. 请注意此方式和上述的子组件port和父组件port的连接方式不同。

4.6.1.5 使用uvm_tlm_fifo

在最前面的生产者/消费者示例1中,在生产者中有一个进程,而消费者中没有任何进程。消费者中的put方法在生产者的put方法被调用的时候执行。

接下来的生产者/消费者的示例2中,消费者中有一个进程,消费者有一个get port用来获得封包。(生产者中没有进程)

我们有可能会遇到这种情况:需要将示例1中的生产者组件和示例2中的消费者组件相连接。

如何做到这两个组件相连接呢?一个非常常用的方法是使用UVM的uvm_tlm_fifo来完成。 uvm_tlm_fifo是一个参数化的FIFO(先进先出队列),此FIFO同时拥有put export和get export. uvm_tlm_fifo实例化的参数就是需要在此FIFO中存储的数据对象类型。其构造函数的参数代表了此FIFO的最大深度(缺省值是1). 实例4-10: uvm_tlm_fifo的使用

class producer_consumer_2 extends uvm_component; producer producer_inst; consumer_2 consumer2_inst;

uvm_tlm_fifo #(simple_packet) fifo_inst; // fifo stores simple_packets

function new(string name, uvm_component parent); producer_inst = new(\ consumer2_inst = new(\

fifo_inst = new(\this, 16); // set fifo depth to 16 endfunction

virtual function void connect();

producer_inst.put_port.connect(fifo_inst.put_export); consumer2_inst.get_port.connect(fifo_inst.get_export); endfunction endclass

运行此模块时,生产者组件中的进程创建封包,同时将封包放入FIFO, 消费者组件在调用get方法的时候取出封包。

由于FIFO的使用,这两个进程的同步耦合关系被分开。每个进程的执行都可以任意延时,使用FIFO以及阻塞性put/get调用可以确保没有任何封包丢失。许多验证环境建模时,对延时不敏感的特性以及确保事务(封包)能够完好不丢失传送的特性是非常需要的。UVM的TLM使得对此类系统建模非常容易。 FIFO连接的图形化示意如下:

图4-4: 使用uvm_tlm_fifo

4.6.1.6 分析port和分析export(analysis port/analysis export)

到目前为止,put/get port要求在仿真开始之前必须有且只有一个export与之相连接。如果port没有连接,UVM会报告错误信息,要求你将之相连。

有时候,我们需要构建类似监控器(monitor)的组件,需要将一个port要么不连接,要么连接到一个或者多个组件上。这是因为监控器一般在整个验证环境中是被动组件,他们不会影响仿真激励的产生,也不会影响DUT(被测试模块)的同步关系。监控器只是被动的收集事务数据,并将之发送给其他已经注册的需要此数据的组件。

分析port因此应运而生。分析port和其他TLM port类似,但是允许将其空接,也允许连接任意多个分析export。

图4-5: 分析端口通讯

对那些熟悉回调(callback)的人来说,分析port本质上就是结构化的回调函数(使用port连接的回调)

每个分析port有一个void类型的write()函数,其参数是一个transaction(事务)。每个分析port将维护一个与之相连接的分析export列表。当write方法以某个transaction作为参数被调用的时候,分析port将使用相同的transaction参数调用每个与之相连的分析port中的write函数。因为write方法是一个函数(function),所以分析port的write函数将不会被阻塞,直接返回。另外,由于此write方法是一个void类型,在write函数返回后将不会传递任何状态给组件。对包含分析port的组件的整体影响来说,可以不必去知道和关心与此分析port相连接的任何组件。 实例4-11: 使用分析port的监控器(Monitor)

class packet_monitor extends uvm_component;

uvm_analysis_port #(simple_packet) analysis_port;

function new(string name, uvm_component parent); analysis_port = new(\ endfunction

virtual task run();

simple_packet p = new();

.. // reassemble packet here from lower level protocol analysis_port.write(p); // write the collected packet to the analysis port endtask endclass

实例4-12: 使用分析export的组件

class packet_checker extends uvm_component;

uvm_analysis_imp #(simple_packet, packet_checker) analysis_export;

function new(string name, uvm_component parent); analysis_export = new(\ endfunction

function void write (simple_packet p);

// check the packet here endfunction endclass

这两个组件可以在父组件中被创建,然后使用UVM通用的TLM连接规则将分析port和分析exort相连接。上面提到,既然分析port允许多个分析export与之相连,可以例化多个具有分析export的组件,将他们连接到packet_monitor组件的分析port上。 有时候,通过分析port传送的交易不能够马上被与之相连的下游组件处理,这些交易需要存储一段时间之后才能够被消耗处理掉。比如,当记分牌组件需要将DUT产生的真实封包和参考模型产生的封包进行比较的情形。在这种情况下,由于DUT需要延时,从参考模型产生的封包需要存储下来。

uvm_tlm_fifo能够在需要的时候存储封包,似乎可以很好的解决上述问题。然而,uvm_tlm_fifo并没有一个分析export,所以不能直接将它连接到分析port上去。一个重要的原因是:在分析export中对write方法的实现要求传递transaction之后马上返回,但是如果FIFO是有限的固定深度,就不是总能够满足这一点。UVM使用

uvm_tlm_analysis_fifo来解决此问题。uvm_tlm_analysis_port拥有一个分析export,因此可以直接和分析port相连,并且它的FIFO具有无限深度,所以write方法调用可以立即成功返回。

4.6.1.7 `uvm_*_imp_decl宏

有些情形,组件需要对相同的接口拥有多种实现。例如一个记分牌类需要对多个接口(比如两个input和一个output)进行监测。在这种情况下,必须提供处理多个接口的方法。有3种潜在的解决方案:

? ?

为每个特定的接口创建一个组件来实现.

如果每个接口的交易类型相同,可以使用一个实现;这个需要交易对象提供一个可以区分其来源的机制.

对每个port创建_imp类型,每个_imp类型调用不同的功能实现函数.

?

在UVM中,由于使用了`uvm_*_imp_decl宏,使得第3种方式最简单。这些宏用来创建新的实现类型,用来转到不同的实现函数。比如,使用`uvm_analysis_imp_decl(_1),将会得到一个uvm_analysis_imp_1 #(type T)的类实现,此类中实现了对函数write_1的实现。

小技巧: `uvm_*_imp_decl宏的使用准则:


UVM实战指南(7).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:《苹果树上的外婆》整本书读书规划

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: