• UVM 事务级建模TLM 单向/多向通信 端口 FIFO通信


    事务级建模 TLM(transaction level modeling):

    TLM通信是基于组件请求的发起和响应,组件之间涉及事务(transaction, trans)的传输,如sequencer与driver、monitor与scoreboard、monitor与coverage model。TLM仅仅适用于component之间的连接

    TLM在各组件之间建立一个专用通道,让信息只在这个通道里流动,因此避免了全局变量,public成员变量和config机制通讯时带来的不便

    TLM port

    数据流方法 put/get/transport

    TLM通信通信类型: put/get/transport

    put操作: 组件 A 将一个 transaction 交给组件 B
    在这里插入图片描述

    get 操作(拿回来一个transaction):是组件 A 向组件 B 请求一个transaction
    在这里插入图片描述
    对于get系列端口,有get()、try_get() 和 can_get() 等操作

    • get() 是一个阻塞调用,如果FIFO中没有transsaction,任务get()将等待
    • try_get() 是一个非阻塞调用,没从FIFO中拿到transaction,也会立即返回,try_get()的返回值指示是否返回成功,事务立即可用,则将其写入输出参数并返回 1;否则,不修改输出参数并返回 0。
    • can_get() 是否可以提供新事务,返回 1,否则返回 0。均不修改输出参数

    transport 操作(先丢出去然后再拿回来一个transaction):组件 A 将一个 transaction 交给组件 B,然后向组件 B 请求一个 transaction

    在这里插入图片描述

    peek:initiator 向 target 索取 trans 的复制

    参考链接 https://verificationacademy.com/verification-methodology-reference/uvm/docs_1.2/html/

    在这里插入图片描述


    组件的通信端口阻塞性:

    连接端口实现通信

    • 发起通信请求的组件是initiator,响应请求的组件就是target

    • blocking(阻塞)与 nonblocking(非阻塞)

    • 阻塞 (函数只有在得到结果之后才会返回):阻塞 PUT 表示 A 将该 transaction 交给 B后,等待 B 接收完成。

    • 非阻塞 (函数没得到结果立刻返回):非阻塞 PUT 表示 A 将该 transaction 交给 B后,PUT不再等待 B 接收完成


    控制流 port 、export 与 imp

    表示从initiator向target发起的请求的传输方向

    • port:表示请求的发送方,initiator 中的端口常为 port
    • export:表示请求的中转方,在 initiator 和 target 的中间层端口常为 export
    • imp:即 import,表示请求的接收方,target中的端口常为 imp
      在这里插入图片描述
      如图,组件1和组件2有两对端口建立通信,第一对端口是put型、第二对端口是get型

    根据 uvm_阻塞性_数据流_控制流 组合成 端口类:

    例如端口类 uvm_blocking_put_port、uvm_nonblocking_get_imp 等等

    • 端口类 不是object类,也不是component类,而是uvm_void,创建的时候要用new(),而不是type_id::create()
    • 用new()创建对象可以放在func new()中,也可以放在build_phase中
    • 用type_id::create()创建对象只能放在build_phase中
    • 在创建组件的时候,一定要用type_id::create(),提供override的可能,还可以实现字符串的层次化

    建立 TLM port 单向通信步骤

    • 定义TLM传输的数据类型trans
    • 确定TLM通信的initiator component 和 target component,并且initiator、target和中间层,在各自的build_phase中使用new函数,分别例化port端口、相同类型的imp端口 和 相同类型的export端口
    • 在target实现该端口的数据流方法
    • initiator和target的上层,在connect_phase使用connect方法建立连接
    • initiator在run_phase调用相应的数据流方法,注意initiator调用的数据流方法是在target内实现的数据流方法

    在这里插入图片描述
    1.定义 transaction 事务类型

    class trans1 extends uvm_sequence_item;			//定义事务类型
    	rand int id;
    	rand int data;
    	...
    endclass
    
    class trans2 extends uvm_sequence_item;
    	int id;
    	int data;
    	...
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.确定TLM通信的 initiator component 和 target component,在各自build_phase中使用new函数,分别例化端口

    注意端口是uvm_void, uvm_void的例化方式只能是new(string name, uvm_component parent);不能用factory(create)机制例化,会编译报错!!!

    // 定义 initiator component
    
    class comp1 extends uvm_component;
    	`uvm_component_utils(comp1)			// component注册uvm 			
    	
    	uvm_blocking_put_port#(trans1) bp_port;				//initiator声明端口,类型为阻塞的put,用于发送trans1。 port端口传入1个参数(trans)
    	uvm_nonblocking_get_port#(trans2) ng_port;			//initiator声明端口,类型为非阻塞的get,用于请求trans2
    	
    	function void build_phase(uvm_phase phase);   // 在build_phase中使用new函数,例化端口, uvm_void的例化方式只能是new
    		super.build_phase(phase);
    		bp_port = new("bp_port",this);			//initiator例化端口,注意不继承于uvm_object或uvm_component,不可用factory机制例化!!!
    		ng_port = new("ng_port",this);			//initiator例化端口,注意继承于uvm_object或uvm_component,不可用factory机制例化!!!
    		...
    	endfunction
    	
    	task run_phase(uvm_phase phase);   // 在run_phase调用相应的数据流方法:put/get/transport
    		trans1 t1;
    		trans2 t2;
    		fork
    			repeat(5) begin
    				t1 = trans1::type_id_create("t1");    // component用create例化,并随机化trans
    				assert(t1.randomize());    //用断言检查随机化,随机化成功,函数返回1;失败返回0
    				bp_port.put(t1);					// 端口调用方法put
    			end
    			forever begin
    				if(ng_port.try_get(t2))				// 端口调用get的非阻塞方法 try_get,没拿到transaction,也会立即返回,
    					break;
    			end
    		join
    	endtask
    	
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    initiator调用的数据流方法put/get/transport,是在target内实现的数据流方法

    // 定义 target component
    
    class comp2 extends uvm_component;
    	`uvm_component_utils(comp2)		// component注册uvm
    	
    	uvm_blocking_put_imp#(trans1,comp2) bp_imp;		// target声明端口imp,imp端口传入两个参数(trans,comp)
    	uvm_nonblocking_get_imp#(trans2,comp2) ng_imp;	// target声明端口imp
    	trans1 tq[$];									// target数据缓存 队列
    	
    	function void build_phase(uvm_phase phase);    // 在build_phase中使用new函数,例化端口
    		super.build_phase(phase);
    		bp_imp = new("bp_imp",this);				//target例化端口
    		ng_imp = new("ng_imp",this);				//target例化端口
    		...
    	endfunction
    	
    	// initiator调用的数据流方法put/get/transport,是在target内实现的数据流方法
    	task put(trans1 t);
    		tq.push_back(t);     // target被发送数据流, 数据缓存队列收下trans1
    	endtask
    	function bit try_get(output trans2 t);			// target 被请求数据流, 对于target来说,是output
    		...
    	endfunction
    	function bit can_get();						// target 被询问是否可以请求数据流
    		return (tq.size() > 0);   // 从initiator接收到的trans1放进了队列,队列里有数据,则可以返回
    	endfunction
    	
    endclass	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    3.在env的build_phase例化initiator component 和 target component,在connect_phase使用connect方法建立连接,连接 initiator component 和 target component

    class env extends uvm_env;
    	`uvm_component_utils(env);     // component注册uvm
    	
    	comp1 c1;	  // 声明 initiator component 和 target component
    	comp2 c2;
    	
    	function void build_phase(uvm_phase phase);
    		super.build_phase(phase);
    		c1 = comp1::type_id::create("c1",this);    // 例化compoent组件用create
    		c2 = comp2::type_id::create("c2",this);
    		...
    	endfunction
    	
    	function void connect_phase(uvm_phase phase);		// 在connect_phase使用connect方法连接initiator端口连接target端口
    		super.connect_phase(phase);
    		c1.bp_port.connect(c2.bp_imp);    // initiator.port_put端口.连接(target.imp_put端口)
    		c1.ng_port.connect(c2.ng_imp);    // initiator.port_get端口.连接(target.imp_get端口)
    		...
    	endfunction
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    单向通信补充情况:

    • PORT to PORT
      UVM支持带层次的连接关系;PORT与PORT之间的连接不止局限于两层,可以有无限多层
      port to port
    • EXPORT to EXPORT
      UVM也支持EXPORT与EXPORT之间的连接;EXPORT与EXPORT之间的连接也不只限于两层,也可以有无限多层
      在这里插入图片描述

    TLM 多向通信(multi-directional communication)

    多向通信指的是,如果initiator与target之间的相同TLM端口超过一个时的处理解决办法。
    在这里插入图片描述

    对于端口的例化可以给不同的名字,而连接也可以通过不同的名字来索引,但是问题在于comp2中需要实现两个task put(trans t)。因为不同的端口组之间要求在imp端口一侧实现专属的方法,这种要求造成了暂时的方法命名冲突,即无法在comp2中定义两个同名的put任务。

    UVM通过延伸的端口宏声明方式来解决这一问题: 在全局通过宏注册后缀,例化加了后缀的新类型端口

    // 定义 initiator
    
    class comp1 extends uvm_component;
    	`uvm_component_utils(comp1)
    	
    	uvm_blocking_put_port#(trans1) bp_port1;				
    	uvm_blocking_put_port#(trans2) bp_port2;	
    				
    	function void build_phase(uvm_phase phase);
    		super.build_phase(phase);
    		bp_port1 = new("bp_port1",this);		// build_phase中new例化端口port	
    		bp_port2 = new("bp_port2",this);			
    		...
    	endfunction
    	
    	task run_phase(uvm_phase phase);
    		trans1 t1;
    		repeat(5) begin
    			t1 = trans1::type_id_create("t1");      // run_phase中create例化组件initiator
    			assert(t1.randomize());
    			bp_port1.put(t1);					// initiator端口调用方法put。注意了,此处依然是put!!不是put1、也不是put2!!!
    			bp_port2.put(t1);
    		end
    	endtask
    	
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    注意initiator调用的数据流方法名称不会改变!!
    对于comp1调用put方法而言,它只需要选择bp_port1或者bp_port2,而不需要更替put方法名,即仍然按照put()来调用而不是put_p1或者put_p2。

    // 定义 target 
    
    `uvm_blocking_put_imp_decl(1);   //宏注册后缀,之后就有了uvm_blocking_put_imp1#(T, IMP)类型,数据流方法也变成put1
    `uvm_blocking_put_imp_decl(2);	 //注册了后缀2
    
    class comp2 extends uvm_component;
    	`uvm_component_utils(comp2)
    	
    	uvm_blocking_put_imp1#(trans1,comp2) bp_imp1;	//看后缀	
    	uvm_blocking_put_imp2#(trans1,comp2) bp_imp2;		
    	trans1 tq[$];	
    										
    	function void build_phase(uvm_phase phase);
    		super.build_phase(phase);
    		bp_imp1 = new("bp_imp1",this);				
    		bp_imp2 = new("bp_imp2",this);				
    		...
    	endfunction
    	
    	// 不同的端口组之间在imp端口一侧实现专属的方法,即不同名的put
    	task put1(trans1 t);	// 看后缀	
    		tq.push_back(t);
    	endtask
    	task put2(trans1 t);
    		tq.push_back(t);
    	endtask
    	
    endclass	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    通过这种方式,用户只需要在例化多个imp端口的组件中,实现不同名称的方法,与imp类型名保持一致。而对于port端口一侧的组件,则不需关心调用的方法名称,因为该名称并不会发生改变。所以,通过这种方式,可以解决多向通信的需要,而防止通信方法名的冲突。


    一对一单向数据流 全部的通信端口

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    常见的PORT,EXPORT和IMP端口

    //:PORT:UVM源代码
    uvm_blocking_put_port#(T);
    uvm_nonblocking_put_port#(T);
    uvm_put_port#(T);
    uvm_blocking_get_port#(T);
    uvm_nonblocking_get_port#(T);
    uvm_get_port#(T);
    uvm_blocking_peek_port#(T);
    uvm_nonblocking_peek_port#(T);
    uvm_peek_port#(T);
    uvm_blocking_get_peek_port#(T);
    uvm_nonblocking_get_peek_port#(T);
    uvm_get_peek_port#(T);
    uvm_blocking_transport_port#(REQ, RSP);
    uvm_nonblocking_transport_port#(REQ, RSP);
    uvm_transport_port#(REQ, RSP);
    
    EXPORT:UVM源代码
    uvm_blocking_put_export#(T);
    uvm_nonblocking_put_export#(T);
    uvm_put_export#(T);
    uvm_blocking_get_export#(T);
    uvm_nonblocking_get_export#(T);
    uvm_get_export#(T);
    uvm_blocking_peek_export#(T);
    uvm_nonblocking_peek_export#(T);
    uvm_peek_export#(T);
    uvm_blocking_get_peek_export#(T);
    uvm_nonblocking_get_peek_export#(T);
    uvm_get_peek_export#(T);
    uvm_blocking_transport_export#(REQ, RSP);
    uvm_nonblocking_transport_export#(REQ, RSP);
    uvm_transport_export#(REQ, RSP);
    
    IMP:UVM源代码
    uvm_blocking_put_imp#(T, IMP);
    uvm_nonblocking_put_imp#(T, IMP);
    uvm_put_imp#(T, IMP);
    uvm_blocking_get_imp#(T, IMP);
    uvm_nonblocking_get_imp#(T, IMP);
    uvm_get_imp#(T, IMP);
    uvm_blocking_peek_imp#(T, IMP);
    uvm_nonblocking_peek_imp#(T, IMP);
    uvm_peek_imp#(T, IMP);
    uvm_blocking_get_peek_imp#(T, IMP);
    uvm_nonblocking_get_peek_imp#(T, IMP);
    uvm_get_peek_imp#(T, IMP);
    uvm_blocking_transport_imp#(REQ, RSP, IMP);
    uvm_nonblocking_transport_imp#(REQ, RSP, IMP);
    uvm_transport_imp#(REQ, RSP, IMP);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    TLM analysis port

    在这里插入图片描述


    端口

    在这里插入图片描述

    UVM中有两种特殊端口:analysis_port 和 analysis_export

    • 默认情况下这两个端口可以连接多个IMP,也就是默认情况下是一对多通讯
    • 而 put, get 默认情况下是一对一通信,所以这两个端口更像广播
    • analysis_port 可以同时和多个 IMP 进行通信,但IMP的类型必须是 uvm_analysis_imp 类型,否则会报 error

    无阻塞

    • put, get 都有阻塞和非阻塞的区分,但 analysis_port 和 analysis_export 端口没有

    数据流方法

    只有write (广播)

    • analysis_port 和 analysis_export 只有一种操作:write 。所以在 analysis_imp 所在的 component 里必须定义一个名字为 write(Tt) 的函数,注意是函数不耗时
    • 如果一个 component 里需要定义两个 write 函数,则需要使用 uvm_analysis_imp_decl 宏来解决,类名后缀的注册`uvm_analysis_imp_decl(SFX)

    FIFO通信

    UVM提供的继承自uvm_component的类uvm_tlm_analysis_fifo类实例化后就是一种FIFO,它可以让通信的两个component都作为initiator,这来自于FIFO上的众多imp型端口。

    FIFO的本质是一块缓存(使用mailbox实现)加上两个IMP(虽然关键字是export但实质还是IMP)

    直接通信
    在这里插入图片描述
    使用FIFO通信
    使用FIFO通信
    uvm_tlm_analysis_fifo #(T)
    在这里插入图片描述

    TLM FIFO中的get方法和peek方法,try_get有什么区别?

    • get()操作将从TLM FIFO中返回一个事务(如果可用),并从FIFO中删除该事务。如果FIFO中没有可用的事务,它将阻塞并等待,直到FIFO至少有一个事务
    • peek()操作将从TLM FIFO中返回一个事务(如果可用),而不会实际从FIFO中删除该项目。它也是一个阻塞调用,如果FIFO没有可用的条目,它将等待
    • try_get()是一个非阻塞调用,即使FIFO中没有可用的事务,它也会立即返回。try_get()的返回值指示是否返回成功。

    在这里插入图片描述

    • FIFO上拥有transport之外的12种IMP,用于分别和相应的PORT和EXPORT连接
    • 除此外还有put_ap和get_ap,当FIFO上的blocking_put_export或者put_export被连接到一个blocking_put_port或者put_port上时,FIFO内部定义的put任务被调用,这个put任务把传递过来的transaction放在FIFO的缓存里,同时,把这个transaction通过put_ap使用write函数发送出去
    • Analysis FIFO含有uvm_analysis_port类对象put_ap和get_ap,说明Anylsis FIFO也可作为initiator向其他target做广播,支持一对多广播通信
    • Analysis FIFO相连的initiator每次调用put或get数据流方法时,FIFO就会调用write广播,看源码
    • 除了put_ap和get_ap,其他端口虽都以_export结尾,但实际上都是imp类型的
    // `uvm_tlm_analysis_fifo #(T)源码
    //...\questasim64_2020.1\verilog_src\uvm-1.2\src\tlm1\uvm_tlm_fifos.svh
    
    class uvm_tlm_fifo #(type T=int) extends uvm_tlm_fifo_base #(T);
      ...
      virtual task put( input T t );
        m.put( t );
        put_ap.write( t );					//广播
      endtask
    
      virtual task get( output T t );
        m_pending_blocked_gets++;
        m.get( t );
        m_pending_blocked_gets--;
        get_ap.write( t );					//广播
      endtask
      ...
    endclass
    
    class uvm_tlm_analysis_fifo #(type T = int) extends uvm_tlm_fifo #(T);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    查看FIFO内部数据方法

    //...\questasim64_2020.1\verilog_src\uvm-1.2\src\tlm1\uvm_tlm_fifos.svh
    class uvm_tlm_fifo #(type T=int) extends uvm_tlm_fifo_base #(T);
    
      function new(string name, uvm_component parent = null, int size = 1); //创建函数,size可指定FIFO容量,0为无限大小
      virtual function int used();			//返回FIFO中存储的trans的个数
      virtual function bit is_empty();		//FIFO是否空
      virtual function bit is_full();		//FIFO是否满
      virtual function void flush();		//清空FIFO
      endfunction
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    FIFO建立通信和调用

    • FIFO还是直接使用IMP通信:在用FIFO通信的方法中,完全隐蔽了这个UVM中特有,而TLM中根本就没有的东西,用户可以完全不关心IMP。因此,对用户来讲,只需要知道analysis_port,blocking_get_port即可,这大大简化了初学者的工作量,尤其是在scoreboard中面临多个IMP时,这种优势更加明显。但是FIFO连接的方式增加了env中代码的复杂度,尤其当连接的端口数量众多时,这个缺点更加明显

    将需要发送trans的component内创建put_port端口,需要接受trans的component内创建get_port端口,再在上层component创建一个Anylsis FIFO,将三者连接即可

    如下例子,monitor将数据广播给scoreboard
    1. 在 monitor 创建 uvm_analysis_port#(trans) ,analysis_port 用于 initiator 广播

    // monitor组件
    
    class monitor extends uvm_monitor;
    	`uvm_component_utils(monitor)       // 注册component
    	
    	virtual reg_intf 			vif;
    	uvm_analysis_port#(trans) 	a_port;
    	...
    	function void build_phase(uvm_phase phase);     // build_phase中new例化端口port	
    		super.build_phase(phase);
    		ap = new("ap",this);				// 
    		if(!uvm_config_db#(virtual reg_intf)::get(this,"","vif",vif))
    			uvm_report_error("INTF",$sformatf("%s gets interface failed",get_full_name()),UVM_NONE);
    	endfunction
    	
    	task run_phase(uvm_phase phase);
    		forever begin
    			trans t;
    			t = trans::type_id::create("t");   // 在run_phase中create例化transaction
    			@(posedge vif.clk iff(vif.mon_ck.cmd != IDLE))
    			t.cmd = vif.mon_ck.cmd;
    			t.cmd_addr = vif.mon_ck.cmd_addr;
    			a_port.write(t);
    		end
    	endtask
    	
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    2.在scoreboard 例化 uvm_blocking_get_port(trans), uvm_blocking_get_port 用于 target 主动请求数据

    // scoreboard组件
    
    class scoreboard extends uvm_scoreboard;
    	`uvm_component_utils(scoreboard)
    	
    	uvm_blocking_get_port bg_port;
    	...
    	function void build_phase(uvm_phase phase);
    		super.build_phase(phase);
    		bg_port = new("bg_port",this);    // build_phase中new例化端口port	
    	endfunction
    	
    	task run_phase(uvm_phase phase);
    		forever begin
    			trans t;     // 在run_phase中声明trans,并接收
    			bg_port.get(t);
    			...
    		end
    	endtask
    	
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    3.在monitor和scb的上层env,例化uvm_tlm_analysis_fifo#(trans),建立FIFO通信
    uvm_tlm_analysis_fifo#(trans) 端口也不属于component,在build_phase中new例化

    // env
    
    class env extends uvm_env;
    	`uvm_component_utils(env)
    	
    	uvm_tlm_analysis_fifo#(trans) 	agt_scb_fifo;    
    	agent 							agt;
    	scoreboard 						scb;
    	...
    	function void build_phase(uvm_phase phase);
    		super.build_phase(phase);
    		agt_scb_fifo = new("agt_scb_fifo",this);     // build_phase中new例化FIFO端口	
    		...
    	endfunction
    	
    	function void connect_phase(uvm_phase phase);   //在connect_phase与FIFO连接
    		agt.mon.a_port.connect(agt_scb_fifo.analysis_export);   // agt的mon的ap连接fifo的analysis_export
    		scb.bg_port.connect(agt_scb_fifo.blocking_get_export);  // scb的bp连接fifo的blocking_get_export
    		...
    	endfunction
    	
    endclass
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述


    TIPs:

    analysis port和TLM port有什么区别?analysis FIFO和TLM FIFO的区别是什么?何时使用analysis FIFO 和 TLM FIFO?

    • TLM port/FIFOs用于具有使用put/get方法建立的通信通道的两个组件之间的事务级通信。
    • analysis port/FIFOs是另一种事务性通信通道,用于组件将事务广播给多个组件。
    • TLM port/FIFO用于driver和sequencer之间的连接,而analysis port/FIFOs用于monitor广播事务,这些事务可由scoreboard或覆盖率收集组件接收。
  • 相关阅读:
    Git学习笔记4
    如何写一份高可读性的软件工程设计文档
    Himall商城字符串帮助类获得指定顺序的字符在字符串中的位置索引
    jquery 分页兼容i7,i8浏览器
    科学计算三维可视化笔记(第七周 运算)
    AUTOSAR汽车电子嵌入式编程精讲300篇-基于 FIFO 和优先级序列 CAN 总线系统(续)
    (八)、基于 LangChain 实现大模型应用程序开发 | 基于知识库的个性化问答 (检索 Retrieval)
    SpringBoot自定义starter
    Salesforce ServiceCloud考证学习(5)
    初识C语言
  • 原文地址:https://blog.csdn.net/qq_40456702/article/details/126682331