You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UVM中uvm_analysis_imp与uvm_tlm_analysis_fifo的区别、适用场景及替代疑问

问题1:uvm_analysis_imp与uvm_tlm_analysis_fifo的区别及适用场景

核心区别

特性uvm_analysis_impuvm_tlm_analysis_fifo
本质被动TLM端口,需用户实现write回调方法封装了uvm_analysis_imp和FIFO的组件,自带存储
数据存储无内置存储,仅做转发/即时处理内置FIFO队列,可缓存事务
连接支持支持多个uvm_analysis_port连接(一对多)通常一对一连接(发送端→FIFO,接收端从FIFO取数)
处理时机事务到达时立即执行write方法(同步处理)接收端可异步从FIFO取数,无需实时响应

示例代码

多监视器→单记分板(用uvm_analysis_imp)

// 记分板实现imp及write方法
class scoreboard extends uvm_scoreboard;
  uvm_analysis_imp#(transaction, scoreboard) analysis_imp;

  function new(string name = "scoreboard", uvm_component parent=null);
    super.new(name, parent);
    analysis_imp = new("analysis_imp", this);
  endfunction

  // 必须实现的write回调
  virtual function void write(transaction tr);
    `uvm_info(get_type_name(), $sformatf("Received trans: data=0x%0h", tr.data), UVM_MEDIUM)
    // 此处做数据比对、统计等逻辑
  endfunction
endclass

// 监视器(多个实例可连接到同一记分板)
class monitor extends uvm_monitor;
  uvm_analysis_port#(transaction) analysis_port;

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

  task run_phase(uvm_phase phase);
    forever begin
      transaction tr = transaction::type_id::create("tr");
      // 总线采集逻辑...
      analysis_port.write(tr); // 发送事务到记分板
    end
  endtask
endclass

// 环境中连接多监视器到单记分板
class env extends uvm_env;
  monitor mon1, mon2;
  scoreboard sb;

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    mon1.analysis_port.connect(sb.analysis_imp);
    mon2.analysis_port.connect(sb.analysis_imp);
  endfunction
endclass

监视器→记分板异步处理(用uvm_tlm_analysis_fifo)

适用于记分板处理速度慢,需要缓存事务的场景:

// 带FIFO的记分板
class scoreboard extends uvm_scoreboard;
  uvm_tlm_analysis_fifo#(transaction) analysis_fifo;

  function new(string name = "scoreboard", uvm_component parent=null);
    super.new(name, parent);
    analysis_fifo = new("analysis_fifo", this);
  endfunction

  task run_phase(uvm_phase phase);
    transaction tr;
    forever begin
      analysis_fifo.get(tr); // 阻塞等待FIFO中有数据
      `uvm_info(get_type_name(), $sformatf("Fetched trans from FIFO: data=0x%0h", tr.data), UVM_MEDIUM)
      // 耗时处理逻辑...
    end
  endtask
endclass

// 环境中连接
class env extends uvm_env;
  monitor mon;
  scoreboard sb;

  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    mon.analysis_port.connect(sb.analysis_fifo.analysis_export);
  endfunction
endclass

问题2:是否可以用uvm_analysis_imp替代uvm_tlm_analysis_fifo?

可以,但需要自行实现缓存逻辑。uvm_analysis_imp本身没有存储功能,若要模拟FIFO的缓存效果,需在write方法中手动维护队列或其他存储结构,并在接收端线程中异步取数。

示例(手动实现缓存):

class scoreboard extends uvm_scoreboard;
  uvm_analysis_imp#(transaction, scoreboard) analysis_imp;
  transaction tr_queue[$]; // 手动维护缓存队列

  function new(string name = "scoreboard", uvm_component parent=null);
    super.new(name, parent);
    analysis_imp = new("analysis_imp", this);
  endfunction

  virtual function void write(transaction tr);
    tr_queue.push_back(tr); // 事务到来时存入队列
  endfunction

  task run_phase(uvm_phase phase);
    transaction tr;
    forever begin
      wait(tr_queue.size() > 0);
      tr = tr_queue.pop_front();
      // 处理事务...
    end
  endtask
endclass

这种方式等价于uvm_tlm_analysis_fifo的核心功能,但uvm_tlm_analysis_fifo已经封装了get/peek/try_get等方法,以及满/空状态判断,无需重复造轮子。

问题3:如何在两者间做选择?

按以下优先级判断:

  1. 多发送端场景:必须用uvm_analysis_imp,因为它支持多个analysis_port同时连接,而uvm_tlm_analysis_fifo通常只适配一对一连接。
  2. 需要异步/缓存处理:优先选uvm_tlm_analysis_fifo,它自带FIFO存储,省去手动维护缓存的代码,且支持灵活的取数时机(如peek查看数据不删除、try_get非阻塞取数)。
  3. 一对一实时处理:两种都可,若只需即时处理事务,uvm_analysis_imp更轻量;若后续可能需要缓存扩展,uvm_tlm_analysis_fifo更具扩展性。

内容的提问来源于stack exchange,提问作者Kiran Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 23:52:35