(4)UVM TLM通信之端口的互联

UVM TLM通信之端口的互联

PORT与EXPORT的连接

如图所示,ABCD四个端口, 要在A和B之间、C和D之间通信。为了实现这个目标,必须要在A和B之间、C和D之间建立一种连接关系,否则的话,A如何知道是和B通信而不是和C或者D通信呢?所以一定要在通信前建立连接关系
(4)UVM TLM通信之端口的互联
如A要和B通信(A是发起者),那么可以这么写:A.port.connect(B.export),但是不能写成B.export.connect(A.port)。因为在通信的过程中,A是发起者,B是被动承担者。这种通信时的主次顺序也适用于连接时,只有发起者才能调用connect函数,而被动承担者则作为connect的参数

使用上述方式建立A.PORT和B.EXPORT之间的连接关系。A的代码为:

class A extends uvm_component;
   `uvm_component_utils(A)
   uvm_blocking_put_port#(my_transaction) A_port;
   ...
endclass

function void A::build_phase(uvm_phase phase);
   super.build_phase(phase);
   A_port = new("A_port", this);
endfunction

task A::main_phase(uvm_phase phase);
endtask

其中A_port在实例化的时候第一个参数是名字,而第二个参数则是一个uvm_component类型的父结点变量

B的代码类同A,在env中建立两者之间关系的连接如下:

class my_env extends uvm_env;
   A   A_inst;
   B   B_inst;
  ...
   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      A_inst = A::type_id::create("A_inst", this);
      B_inst = B::type_id::create("B_inst", this);
   endfunction
endclass

function void my_env::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   A_inst.A_port.connect(B_inst.B_export);
endfunction

注:PORT和EXPORT恰如一道门,它们只是一个通行的作用,它不可能把一笔transaction存储下来,没有存储作用,除了转发操作之外不作其他操作。因此,这笔transaction一定要由B_export后续的某个组件进行处理。在UVM中,完成这种后续处理的也是一种端口:IMP。

PORT和IMPORT的连接

有了IMP之后,之前的PORT与EXPORT之间的连接就可以实现了。下图为component在连接中的作用
(4)UVM TLM通信之端口的互联
A和B的代码为:

class A extends uvm_component;
   `uvm_component_utils(A)

   uvm_blocking_put_port#(my_transaction) A_port;
...
endclass
...
task A::main_phase(uvm_phase phase);
   my_transaction tr;
   repeat(10) begin
      #10;
      tr = new("tr");
      assert(tr.randomize());
      A_port.put(tr);
   end
endtask
//------------------------------------------------------------------------------------------
class B extends uvm_component;
   `uvm_component_utils(B)

   uvm_blocking_put_export#(my_transaction) B_export;
   uvm_blocking_put_imp#(my_transaction, B) B_imp;
...
endclass

function void B::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   B_export.connect(B_imp);
endfunction

function void B::put(my_transaction tr);
   `uvm_info("B", "receive a transaction", UVM_LOW) 
   tr.print();
endfunction

在B的代码中,关键是要实现一个put函数/任务。如果不实现,将会给出错误提示

在UVM中,只有IMP才能作为连接关系的终点。如果是PORT或者EXPORT作为终点,则会报错。
A_port的put操作最终要落到B的put上。所以在B中要定义一个名字为put的任务/函数。

当B中完成B_imp和put的定义后,在env的connect_phase就需要把Aport和B_imp连接在一起了:

function void my_env::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   A_inst.A_port.connect(B_inst.B_imp);
endfunction

EXPORT和IMP的连接

PORT可以与IMP相连接,同样的EXPORT也可以与IMP相连接,其连接方法与PORT和IMP的连接完全一样。之前完成了EXPORT与IMP的连接,不过在那个连接中EXPORT只是作为中间环节,这里把EXPORT作为连接的起点。

除了A_port变成B_export之外,其他没有任何改变。在B中也必须定义一个名字为put的任务。

PORT和PORT的连接

在之前的连接中,都是不同类型的端口之间连接(PORT与IMP、PORT与EXPORT、EXPORT与IMP),且不存在层次的关系。在UVM中,支持带层次的连接关系,
(4)UVM TLM通信之端口的互联
在上图中,A与C中是PORT,B中是IMP。UVM支持C的PORT连接到A的PORT,并最终连接到B的IMP。
C和A的代码如下:

class C extends uvm_component;
   `uvm_component_utils(C)
   uvm_blocking_put_port#(my_transaction) C_port;
  ...
endclass

task C::main_phase(uvm_phase phase);
   my_transaction tr;
   repeat(10) begin
      #10;
      tr = new("tr");
      assert(tr.randomize());
      C_port.put(tr);
   end
endtask
//-------------------------------------------------------------------------------------------
class A extends uvm_component;
   `uvm_component_utils(A)

   C C_inst;
   uvm_blocking_put_port#(my_transaction) A_port;
...
endclass

function void A::build_phase(uvm_phase phase);
   super.build_phase(phase);
   A_port = new("A_port", this);
   C_inst = C::type_id::create("C_inst", this);
endfunction

function void A::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   C_inst.C_port.connect(this.A_port);
endfunction

task A::main_phase(uvm_phase phase);

endtask

其他代码仅需修改端口类型,其他均相同;

PORT与PORT之间的连接不只局限于两层,可以有无限多层。

EXPORT和EXPORT的连接

在下图中,A中是PORT,B与C中是EXPORT,B中还有一个IMP。UVM支持C的EXPORT连接到B的EXPORT,并最终连接到B的IMP。
(4)UVM TLM通信之端口的互联
A、B代码同前,C的代码和env代码如下:

class C extends uvm_component;
   `uvm_component_utils(C)
   B B_inst;
   uvm_blocking_put_export#(my_transaction) C_export;
...
endclass

function void C::build_phase(uvm_phase phase);
   super.build_phase(phase);
   C_export = new("C_export", this);
   B_inst = B::type_id::create("B_inst", this); 
endfunction

function void C::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   this.C_export.connect(B_inst.B_export);
endfunction

task C::main_phase(uvm_phase phase);
endtask
//-------------------------------------------------------------------------------------------
function void my_env::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   A_inst.A_port.connect(C_inst.C_export);
endfunction

同样的,EXPORT与EXPORT之间的连接也不只局限于两层,也可以有无限多层

这篇笔记参考《UVM实战》、《芯片验证漫游指南》和某验证视频整理而成,仅作学习心得交流,如果涉及侵权烦请请告知,我将第一时间处理。

上一篇:Nginx-正向代理实现


下一篇:DLT698.45之数据类型(Connect)