[UVM]UVM中的analysis port 和analysis export

本文详细解析了UVM(通用验证方法学)中analysisport与analysisexport的区别及应用,阐述了一对多通信机制,对比了与port和export的差异,包括操作类型、阻塞特性等,并提供了实例代码展示多个IMP与analysisport的连接,以及如何处理多个uvm_analysis_imp共存的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

UVM中的analysis port 和analysis export

一、analysis port 和analysis export與port 和export的區別

  • 都是用于传递transaction
  • analysis port(analysis export)与IMP 之间的通信是一种一对多的通信,而PORT 和EXPORT 与IMP 的通信是一种一对一的通信
  • PORT 和EXPORT,有put,get,transport 操作,一个PORT 要么是put_port,要么是get_port,要么是transport_port,不可能是三者兼有。但是对于analysis port(analysis export)来说,它只有一种操作write。write 的意思就是广播一下,剩下的事情就与他无关了。
  • 作为PORT 和EXPORT,都有阻塞和非阻塞的区分。相应的put,get,transport 操作也分成了阻塞和非阻塞的。但是对于analysis port 和analysis export 来说,没有阻塞和非阻塞的概念。因为它本身就是广播,不必等待与其相连的其它port的响应。所以不存在阻塞和非阻塞。

         

二、一个analysis port和多个IMP相连接进行通信的例子

2.1.analysis_port A

class component_a extends uvm_component;
  
  transaction                         trans;
  //Step-1. Declaring analysis port
  uvm_analysis_port#(transaction)     analysis_port_a;
  
  `uvm_component_utils(component_a)
  
  //---------------------------------------
  // Constructor
  //---------------------------------------
  function new(string name, uvm_component parent);
    super.new(name, parent);
    
    //Step-2. Creating analysis port
    analysis_port_a = new("analysis_port_a", this);
  endfunction : new
  //---------------------------------------
  // run_phase
  //---------------------------------------
  virtual task run_phase(uvm_phase phase);
    phase.raise_objection(this);
    
    trans = transaction::type_id::create("trans", this);
    //void'(trans.randomize());
    assert(trans.randomize());
    `uvm_info(get_type_name(), $sformatf(" tranaction randomized"),UVM_LOW)
    `uvm_info(get_type_name(), $sformatf(" Printing trans, \n %s", trans.sprint()), UVM_LOW)
                                              
    `uvm_info(get_type_name(),$sformatf(" Before calling port write method"), UVM_LOW)
    //Ste-3. Calling write method
    analysis_port_a.write(trans);
    `uvm_info(get_type_name(), $sformatf(" After  calling port write method"), UVM_LOW)
    
    phase.drop_objection(this);
  endtask : run_phase
endclass : component_a

2.2.analysis_imp B(需要寫写一个write任务)

class component_b extends uvm_component;
  
  transaction trans;
  //Step-1. Declaring analysis imp port
  uvm_analysis_imp#(transaction,component_b)         analysis_imp_b; 
  `uvm_component_utils(component_b)
  
  //---------------------------------------
  // Constructor
  //---------------------------------------
  function new(string name, uvm_component parent);
    super.new(name, parent);
    //Step-2. Creating analysis imp_port
    analysis_imp_b = new("analysis_imp_b", this);
  endfunction : new
  
  //---------------------------------------
  // Analysis Imp port write method
  //---------------------------------------
  //Step-3. Implementing write method
  virtual function void write(transaction trans);
    `uvm_info(get_type_name(), $sformatf(" Inside write method. Recived trans On Analysis Imp Port"), UVM_LOW)
                                          
    `uvm_info(get_type_name(), $sformatf(" Printing trans, \n %s", trans.sprint()), UVM_LOW)
                                          
  endfunction
endclass : component_b

2.3.analysis_imp D(需要重寫写一个write任务)

class component_d extends uvm_component;
  
  transaction                                     trans;
  //Step-1. Declaring analysis imp port
  uvm_analysis_imp#(transaction,component_b)      analysis_imp_d; 
  `uvm_component_utils(component_d)
  
  //---------------------------------------
  // Constructor
  //---------------------------------------
  function new(string name, uvm_component parent);
    super.new(name, parent);
    //Step-2. Creating analysis imp_port
    analysis_imp_d = new("analysis_imp_d", this);
  endfunction : new
  
  //---------------------------------------
  // Analysis Imp port write method
  //---------------------------------------
  //Step-3. Implementing write method
  virtual function void write(transaction trans);
    `uvm_info(get_type_name(), $sformatf(" Inside write method. Recived trans On Analysis Imp Port"), UVM_LOW)
                                          
    `uvm_info(get_type_name(), $sformatf(" Printing trans, \n %s", trans.sprint()), UVM_LOW)
                                          
  endfunction
endclass : component_d

2.4.Component C

class C extends uvm_component;
  component_a             a;
  component_b             b;
  component_d             d;

  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    a = component_a::type_id::create(“a”, this);
    b = component_b::type_id::create(“b”, this);
    d = component_d::type_id::create(“d”, this);
  endfunction

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    a.analysis_port_a.connect(b.analysis_imp_b);
    a.analysis_port_a.connect(d.analysis_imp_d);
  endfunction

endclass

三、一個component中有多个uvm_analysis_imp存在的情况

        

       通常,在monitor和scoreboard之间的通信,采用一个analysis port和一个anslysis imp相连的方式实现。我们知道,对于一个analysis imp来说,必须在其实例化的uvm_component定义一个write的task。

       如果scoreboard除了接收monitor的数据之外,还要接受reference model的数据。相应的scoreboard就要再添加一个uvm_analysis_imp的IMP,如model_imp。此时问题就出现了,这个新的IMP也要有一个write任务与其对应,因为很明显,我们对接收到的两路数据的处理是不一样的。但是write只有一个,怎么办?

       UVM考虑到了这种情况,它采用如下的方式处理:

`uvm_analysis_imp_decl(_monitor)

3.1、一個component中有“多個”write任務的案例

  • 在write_model()方法中,可以做decoder
  • 对covergroup进行采样
`uvm_analysis_imp_decl(_model)

class scoreboard extends uvm_scoreboard;

  uvm_analysis_imp_monitor#(mac_transaction, scoreboard)     monitor_imp;
  uvm_analysis_imp_model#(mac_transaction, scoreboard)       model_imp;

  task write_monitor(mac_transaction tr);
    //do something on tr
  endtask

  task write_model(mac_transaction tr);
    //do something on tr
  endtask

endclass
  • 通过宏`uvm_analysis_imp_decl,声明了两个后缀_monitor和_model。UVM会根据这两个后缀内建两个新的imp:uvm_analysis_imp_monitor和uvm_analysis_imp_model。
  • 当与uvm_analysis_imp_monitor相连接的analysis port执行write任务时,会自动调用write_monitor任务,
  • 而与uvm_analysis_imp_model相连的analysis port执行write任务时,则会自动调用write_mondel任务。
  • 所以,只要把后缀声明了,把write后面添加上相应的后缀就可以正常工作了。
  • 注意:在PORT側,執行的都是write這個task

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

元直数字电路验证

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值