UVM基础-TLM机制底层逻辑和用法

1.1 概念和思想

       要搞懂TLM,首先要搞懂TLM是什么,TLM全称为Transaction Level Modeling,事务级建模,也就是UVM验证方法学的灵魂-通过事务级模型,模拟DUT处理的功能,以更高层级的抽象方法验证DUT底层电路的功能正确性。因此,基于UVM验证方法学的验证环境中,数据包在各个组件之间的流通显得尤为重要。

       作为一门面向对象的编程语言,传统System Verilog也提供了两个进程或者两个组件(class)之间的通信方法-event,mailbox,Semaphore等语法支撑两个组件之间的通信,或者使用全局变量(public)来让两个组件都能够访问到这个变量,来实现组件间信息的获取功能。但UVM考虑了环境的可移植性和重用性,在此基础上发展而来TLM机制。

1.2 动作的发起者和被动接受者

       TLM初步建模,两个组件之间的通信可以抽象为如图1.2.1所示的模型:

 

 

图1.2.1 TLM建模

       想象一个场景,如果组件A想要从组件B中获取数据包,那么首先在组件A上要有一个用于建立通信的端口,TLM中称之为Port,而组件B上也要有一个相应的端口,用于首发数据,此处暂且称之为Export,因为时组件A想要从组件B中获取数据,或者说组件A想要把数据发给组件B,在此场景下,组件A做为通信过程中的动作发起者,也可以理解为是组件A向组件B发起一个命令,告知其此时有数据包要发给你,或者你要向我发送数据。那么此时就衍生出图1.2.2所示的控制命令传输方向和数据传输方向。

图1.2.2 数据/命令传输方向

       图1.2.2 a所示,组件A如果想将自己的数据包传输给组件B,那么组件A就是此次通信事件中的动作发起者,命令传输方向由A到B,数据传输方向也是由A到B,TLM称之为put操作;图1.2.2 b所示,组件A如果想要组件B回传一个B的数据包,那么在这种场景下,命令传输方向仍然是A到B,但是数据的传输方向则变成了由组件B到组件A,TLM称之为get操作。不论哪种方式,在传输的过程中,组件A永远扮演动作发起者的角色,而组件B只能被动接受组件A的命令。

       当然,UVM中的TLM机制还提供了另外一种可能的场景,也就是双向数据场景,TLM称之为Transport,如图1.2.3所示。

图1.2.3 transport场景

       Transport场景下,组件A要求其先向组件B发送一个数据包,发送完毕后,要求B再返回一个数据包到组件A,类似与一次握手,数据传输方向在t时刻由A到B,在t+dt时刻由B到A,但是命令的发起者仍然是组件A,组件B只能被动接受A的动作,即接收A传来的数据,同时向A再发送一个数据,TLM称这种操作为Transport操作。

       另外,除了put,get,transport操作外,在每种操作下,TLM还提供了每种操作可能具备的特点,即blocking的还是nonblocking的,blocking英文直译为“阻塞的”,也就是说,如果当前通信动作没有完成,是要一直等当前操作完成之后,才可以进行新的操作,或者进行组件内部的其他操作,如处理其他数据,或进入其他进程;而non-blocking则是blocking的反义,理解为“非阻塞”,即如果当前通信操作没有完成,可以进行其他新的操作。

       举一个blocking和nonblocking的例子,想象一个场景,组件A想要发送一个数据包给组件B,那么在某个时刻下,组件B可能并没有时间立刻去处理A发来的数据,此时组件A可以选择等待B接受了数据后,在进行后续操作,也可以选择直接返回,不向B发送当前数据,等待后续重新发送,或者放弃。那么前者即为blocking场景,后者为nonblocking场景。

 

       基于前两节讨论的内容,UVM TLM机制下提供了针对不同场景的端口组件,用户可以将端口实例化到各自的验证环境组件中,在高层节点完成组件上各端口的连接关系,即可实现组件通信。

2.1 Port端口的类型

       针对put操作,get操作,transport操作,以及当前操作时blocking的,还是非blocking的,针对port端口,也就是动作的发起者,在整个TLM组件中优先级最高,TLM提供了如下表2.1所示的组件:

表2.1 port端口的组件类型

组件名

含义

uvm_blocking_put_port#(T)

put操作,阻塞端口

uvm_nonblocking_put_port#(T)

put操作,非阻塞端口

uvm_put_port#(T)

put操作,既可以用于阻塞,又可以用于非阻塞端口

uvm_blocking_get _port#(T)

get操作,阻塞端口

uvm_nonblocking_get_port#(T)

get操作,非阻塞端口

uvm_get_port#(T)

get操作,既可以用于阻塞,又可以用于非阻塞端口

uvm_blocking_peek_port#(T)

peek操作,阻塞端口

uvm_nonblocking_peek_port#(T)

peek操作,非阻塞端口

uvm_peek_port#(T)

peek操作,既可以用于阻塞,又可以用于非阻塞端口

uvm_blocking_get_peek_port#(T)

get和peek操作,阻塞端口

uvm_nonblock_get_peek_port#(T)

getpeek操作,非阻塞端口

uvm_get_peek_port#(T)

get和peek操作,既可以用于阻塞,又可以用于非阻塞端口

uvm_blocking_transport_port#(REQ, RSP)

transport操作,阻塞端口

uvm_nonblocking_transport_port#(REQ, RSP)

transport操作,非阻塞端口

uvm _transport_port#(REQ, RSP)

transport操作,既可以用于阻塞,又可以用于非阻塞端口

       端口的类型是一个参数化类,在实际使用的时候传递的参数为uvm_transaction,也就是验证环境中的数据包。

在表2.1中可以看到,除了put,get,transport操作之外,TLM还提供了peek操作和get结合peek类型的端口,peek操作实际上和get操作是类似的,唯一的差别在于,peek操作下,假设动作发起者A想要从组件B中拿数据包,peek操作会使B在回传数据包的同时,在自己本地再备份一个相同的数据包,以便自身使用或者发生异常的回传,实际上为组件之间的通信增加了一种容错机制,get peek类型的端口,则说明这种端口兼具get操作和peek操作。

       除了blocking类型的端口和nonblocking类型的端口之外,TLM还提供了既能做blocking操作,又能做nonblocking操作的uvm_xxx_port,不声明blocking或者nonblocking的端口类型,说明阻塞和非阻塞兼具。

2.2 Export端口的类型

       同理,针对TLM中优先级第二高的通信类型组件Export,基于各种操作和通信场景特点,TLM提供了如下表2.2所示的组件:

表2.2 export端口的组件类型

组件名

含义

uvm_blocking_put_export#(T)

put操作,阻塞端口

uvm_nonblocking_put_export#(T)

put操作,非阻塞端口

uvm_put_export#(T)

put操作,既可以用于阻塞,又可以用于非阻塞端口

uvm_blocking_get _export#(T)

get操作,阻塞端口

uvm_nonblocking_get_export#(T)

get操作,非阻塞端口

uvm_get_export#(T)

get操作,既可以用于阻塞,又可以用于非阻塞端口

uvm_blocking_peek_export#(T)

peek操作,阻塞端口

uvm_nonblocking_peek_export#(T)

peek操作,非阻塞端口

uvm_peek_export#(T)

peek操作,既可以用于阻塞,又可以用于非阻塞端口

uvm_blocking_get_peek_export#(T)

get和peek操作,阻塞端口

uvm_nonblock_get_peek_export#(T)

getpeek操作,非阻塞端口

uvm_get_peek_export#(T)

get和peek操作,既可以用于阻塞,又可以用于非阻塞端口

uvm_blocking_transport_export#(REQ, RSP)

transport操作,阻塞端口

uvm_nonblocking_transport_export#(REQ, RSP)

transport操作,非阻塞端口

uvm _transport_export#(REQ, RSP)

transport操作,既可以用于阻塞,又可以用于非阻塞端口

       同理,在表1.3.2中可以看到,除了put,get,transport操作之外,TLM还提供了peek操作和get结合peek类型的端口,两种操作的异同和port端口是一样的,此处不再赘述。

       同样的,除了blocking类型的端口和nonblocking类型的端口之外,export也具备既能做blocking操作,又能做nonblocking操作的uvm_xxx_export,不声明blocking或者nonblocking的端口类型,说明阻塞和非阻塞兼具。

       正如1.2节所描述的内容,uvm的TLM机制中存在动作的发起者和被动接受者关系,因此,TLM各类型的端口存在优先级,命令只能从优先级高的端口流向优先级低的端口,优先级顺序为Port优先级高于Export,Export高于IMP,对于IMP,后文马上会讲到,此处可以暂时理解为是TLM提供的另一种端口类型,优先级最低。

       组件的连接关系,也只能从高优先级的组件连接到低优先级的端口组件,箭头指向低优先级端口组件,也就是说,低优先级组件,也就是类的句柄要作为参数传递给高优先级组件的connect函数,这个关系在端口连接关系章节会详细阐明底层逻辑,此处先说明上述结论。

2.3 IMP端口的类型

       除了port和export之外,TLM还提供了另一种通信端口,作为连接的终点,IMP存在的重要作用,是将端口和被动接受者本身绑定在一起,从而实现数据包在两个组件之间的传递。针对这一层关系,后文会详细介绍,本小节先说明TLM中IMP端口的类型,如表2.3所示。

表2.3 IMP端口的组件类型

组件名

含义

uvm_blocking_put_imp #(T, IMP)

put操作,阻塞端口

uvm_nonblocking_put_imp #(T, IMP)

put操作,非阻塞端口

uvm_put_imp #(T, IMP)

put操作,既可以用于阻塞,又可以用于非阻塞端口

uvm_blocking_get_imp #(T, IMP)

get操作,阻塞端口

uvm_nonblocking_get_imp #(T, IMP)

get操作,非阻塞端口

uvm_get_imp #(T, IMP)

get操作,既可以用于阻塞,又可以用于非阻塞端口

uvm_blocking_peek_imp #(T, IMP)

peek操作,阻塞端口

uvm_nonblocking_peek_imp #(T, IMP)

peek操作,非阻塞端口

uvm_peek_imp #(T, IMP)

peek操作,既可以用于阻塞,又可以用于非阻塞端口

uvm_blocking_get_peek_imp#(T, IMP)

get和peek操作,阻塞端口

uvm_nonblock_get_peek_imp#(T, IMP)

getpeek操作,非阻塞端口

uvm_get_peek_ imp#(T, IMP)

get和peek操作,既可以用于阻塞,又可以用于非阻塞端口

uvm_blocking_transport_imp #(REQ, RSP, IMP)

transport操作,阻塞端口

uvm_nonblocking_transport_imp #(REQ, RSP, IMP)

transport操作,非阻塞端口

uvm _transport_imp #(REQ, RSP, IMP)

transport操作,既可以用于阻塞,又可以用于非阻塞端口

       IMP的操作和类型,与port以及export一样,此处不再赘述。

       细心的读者可以看到,IMP端口的声明,参数化类比port和export多了一个参数,UVM源码中写为IMP,实际上,这个类要传递将imp端口例化在组件中的具体组件名,也就是组件类的句柄,如下图实例化IMP的代码块:

1.	class B extend uvm_component;
2.	      `uvm_component_utils(B)
3.	      uvm_blocking_put_imp(my_transaction, B) my_imp;
4.	
5.	      extern function void build_phase(uvm_phase phase);
6.	.......
7.	endclass
8.	
9.	function void B::build_phase(uvm_phase phase);
10.	      super.build_phase(phase);
11.	      my_imp = new("my_imp", this);
12.	      ......
13.	endfunction:build_phase

    在申明uvm_blocking_put_imp的时候,将组件B的句柄,作为参数传递给uvm_blocking_put_imp中。实际上,在一次通信过程中,动作发起者组件A在调用put方法的时候,本质上是调用的组件B内部的put方法,才能将组件数据包A传递给组件B。至于为什么要这样做,会在第三章组件端口的连接关系中详细说明,此处先说明结论:

         在一次通信过程中,动作发起者发送数据的操作,最终会调用被动接受者内部的函数,这个过程是以IMP端口类型为纽带联系的,可以这么理解:port和export连接为组件A和B之间的通信提供了一扇门,和一个管道,而具体发送和接受数据的过程,要依赖imp与被动组件之间的交互,imp作为数据传输过程中的动力源而存在,因此,一个连接的终点,一定是一个IMP。

         读者可以尝试,只有port和export的连接,在仿真过程中,会报错,因为没有imp的内置动力源触发将数据包在动作发起者和动作接收者之间传递。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值