UVM-TLM通信

目录

1.TLM通信的意义

2. TLM通信的构成

2.1 端口分类和端口方法

2.2 端口的连接

3. 双向通信

4. analysis_port

5. imp_decl宏


1.TLM通信的意义

在systemverilog中,组件之间的通信需要通过mailbox、event或者semaphore进行。在driver、monitor、scoreboard、reference_model 之间通信,往往需要编写大量的通信相关的代码,同时通信又存在阻塞和非阻塞的概念,这些复杂的通信加上一些全局变量的存在往往会造成逻辑和通信混乱。针对这些情况,UVM增加TLM(transaction level modeling 事务级建模),专门提供端口用于通信,用于数据的传输。

2. TLM通信的构成

TLM由对应的端口和端口方法构成。一般在不同组件中声明端口,然后在更高层将端口相连,并在 imp中调用端口方法实现事务级通信传输。

2.1 端口分类和端口方法

端口分类

port:作为initiator的发起端,initiator凭借port才可以访问target的TLM通信方法。

export:作为initiator和target中间层次的端口。

imp:只能作为target接受request的末端,它无法作为中间层次的端口,所以imp的连接无法再延伸。

在介绍端口方法前,先介绍通信的一些基本概念。在TLM中,通信对象可以分为initiator和target。initiator是通信的发起方,而target端是通信的响应端。按照数据流来分又可以分为producer和consumer,即数据从哪里产生,又流向了哪里。

端口方法

put:A(initiator)把transaction发送给B(target)。数据流向为A=>B,A为producer而B为consumer。

get:A(initiator)向给B(targt)索要transaction。数据流向为A <=B,B为producer而A为consumer。

transport: transport = A + B;即A先put给B,A再从B那边get。initiator都是A。

同时端口又分为阻塞和非阻塞,按照端口分类和端口类型,可以将port分为:

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与port类似,可以看出每个port可以分为阻塞与非阻塞,并都有其对应实现的功能。

2.2 端口的连接

在声明好端口后,要将端口连接才能使端口之间产生联系。在UVM中,用connect函数进行端口连接。如:A.port.connect(B.export)(A是initiator,B是target,只有initiator才能调用connect函数而target作为被连接的参数)。

在端口连接时,port可以连接port、export、imp。 export可以连接export、imp。而imp则作为连接的终点。即port优先级最高,imp优先级最低,优先级高的能连接优先级低的(export不能连接port)。

同时对于TLM通信,连接的终点必须是imp。

在定义imp时(如`uvm_blocking_put_imp#(T,IMP)),会比port和export多一个参数,T是传输的transaction类型,而IMP是UVM实现这个接口的component。实际上,在调用put、get等函数/任务时,TLM只是起一个通道的作用,最终的方法实现还是要由imp所在的component实现。(如同流水线生产中的履带,只是起运输作用,最终产品的加工还是由机器来完成)。

示例:

class A extends uvm_component;
     ……

  `uvm_blocking_put_port#(transaction) A_port;  //port  声明

  function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      A_port = ("A_port",this);                ///port 创建
  endfunction
  
  task run_phase(uvm_phase phase);
    transaction tr;
    super.run_phase(phase);
    phase.raise_objection(this);
    repeat(10) begin
      tr = new("tr");
      assert(tr.randomize());
      A.port.put(tr);                          //调用put函数
      #10;
    end
    phase.drop_objection(this);
  endtask

endclass

class B extends uvm_component;
   ……

  `uvm_blocking_put_imp#(transaction,B) B_imp;

  function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      B_imp = ("B_imp",this);
  endfunction

 function void put(transaction tr);               
    `uvm_info("B","Get a transaciton",UVM_LOW);
     tr.print();
 endtask

endclass 


class y_env extends uvm_env;
    ……
  A  A_inst;
  B  B_inst;

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    A_inst = A::type_id::create("A_inst",this);  //port的例化
    B_inst = B::type_id::create("B_inst",this);
  endfunction

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    A_inst.A_port.connect(B_inst.B_imp);   //port的连接
  endfunction

    ……
endclass

3. 双向通信

双向通信也分为initiator和target,但数据的流向是双向的,双向通信的端口如下:

`uvm_blocking_transport_port;`uvm_nonblocking_transport_port;`uvm_transport_port

示例:

class A extends uvm_component;
     ……

  `uvm_blocking_transport_port#(transaction,transaction) A_transport;  //req,rsp

  function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      A_port = ("A_port",this);                ///port 创建
  endfunction
  
  task run_phase(uvm_phase phase);
    transaction tr;
    super.run_phase(phase);
    phase.raise_objection(this);
    repeat(10) begin
      tr = new("tr");
      assert(tr.randomize());
      A.port.transport(tr,rsp);                          //调用transport
      #10;
    end
    phase.drop_objection(this);
  endtask

endclass

class B extends uvm_component;
   ……

  `uvm_blocking_transport_imp#(transaction,transaction,B) B_imp; //req,rsp, component

  function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      B_imp = ("B_imp",this);
  endfunction

 task transport(transaction  req,ouput transaction rsp);   //定义transport任务
    `uvm_info("B","receive a transaction",UVM_LOW)
    req.print();
    #5;
    rsp = new ("rsp");
 endtask

endclass 


class y_env extends uvm_env;
    ……
  A  A_inst;
  B  B_inst;

  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

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    A_inst.A_transport.connect(B_inst.B_imp);   //port的连接
  endfunction

    ……
endclass

4. analysis_port

之前介绍的port、export、imp在默认情况下都是一个port(export)对一个imp的 ,在UVM中可以通过analysis_port和analysis_export 来实现一对多的通信(一个port对多个imp)。

analysis_port没有阻塞和非阻塞的概念,它本身是广播,不需要与其相连端口的响应,analysis_port可以与多个imp相连,前提是imp类型必须是uvm_analysis_imp。

对于analysis_port,需要在imp所在的component函数中定义一个write函数,当analysis_port广播到imp时,会自动执行imp端口的write函数。

示例:

class A extends uvm_component;
     ……

  `uvm_analysis_port#(transaction) A_ap;  //声明ap端

  function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      A_ap = ("A_ap",this);                ///port 创建
  endfunction
  
  task run_phase(uvm_phase phase);
    transaction tr;
    super.run_phase(phase);
    repeat(10) begin
      tr = new("tr");
      assert(tr.randomize());
      A_ap.write(tr);                          //调用write 函数
      #10;
    end
  endtask

endclass

class C extends uvm_component;
   ……

  `uvm_analysis_imp#(transaction) B_imp; //声明ap_imp

  function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      B_imp = ("B_imp",this);
  endfunction

  function void write (transaction tr);    //定义write函数
    `uvm_info("B","receive a transaction",UMV_LOW)
     tr.print();
  endfunction

 endtask

endclass 

class B extends uvm_component;
   ……

  `uvm_analysis_imp#(transaction) C_imp; //声明ap_imp

  function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      C_imp = ("C_imp",this);
  endfunction

  function void write (transaction tr);    //定义write函数
    `uvm_info("C","receive a transaction",UMV_LOW)
     tr.print();
  endfunction

 endtask

endclass 

class y_env extends uvm_env;
    ……
  A  A_inst;
  B  B_inst;
  C  C_inst;

  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);
    C_inst = C::type_id::create("C_inst",this);
  endfunction

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    A_inst.A_ap.connect(B_inst.B_imp);   //一对多连接
    A_inst.A_ap.connect(C_inst.C_imp);
  endfunction

    ……
endclass

5. imp_decl宏

对于一个component中需要多个imp时,会出现重名的imp以及重名的方法名,为此可以通过`uvm_analysis(可替代)_imp_decl宏来声明,并定义对应的方法名,来避免重名的现象出现。

`uvm_analysis_imp_decl(_mon)   //宏的声明
`uvm_analysis_imp_decl(_mdl)

class scb extends uvm_component;

            ……
    uvm_analysis_imp_mon#(transaction,scb) mon_imp;   //端口声明
    uvm_analysis_imp_mdl#(transaction,mdl) mdl_imp;   

    function write_mon(transaction tr);   //方法声明
            ……
    endfunction

    function write_mdl(transaction);
            ……
    endfuction



endclass

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值