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

如何保证UVM每时间步checker在所有monitor执行完成后运行

UVM验证环境checker同周期调度顺序问题解决方案

问题背景

现有UVM验证环境包含多个带monitor和analysis port的agent,所有agent的analysis port均连接至checker组件,用于适配设计自带的旁路逻辑(输入端口检测到事务后同一周期直接输出),处理同周期同时出现input_txn与output_txn的场景。
两类常见checker架构均存在调度风险:

Design 1:单进程顺序检查

class my_checker extends uvm_component;
  //boiler plate uvm...
  task run_phase();
    forever begin
      check_inputs();
      check_outputs();
      @(posedge vinft.clk);
    end
  endtask

  function check_inputs();
    input_txn_c txn;
    if (input_analysis_fifo.try_get(txn)) begin // non-blocking try_get()
      //do check
      pending_txn_cnt++;
    end
  endfunction

  function check_outputs();
    output_txn_c txn;
    if (output_analysis_fifo.try_get(txn)) begin //non-blocking try_get()
      assert(pending_txn_cnt > 0);
      pending_txn_cnt--;
    end
  endfunction
endclass

该架构固定先检查输入再检查输出,同周期事务处理逻辑符合预期,但存在执行顺序风险:仿真器可能在output_agent的run_phase执行完成后、input_agent的run_phase执行前就调度checker的run_phase,导致断言误触发。

Design 2:并行进程检查

class my_checker extends uvm_component;
  //boiler plate uvm...
  task run_phase();
    fork
      check_inputs();
      check_outputs();
    join_none
  endtask

  task check_inputs();
    input_txn_c txn;
    forever begin
      input_analysis_fifo.get(txn); //blocking get()
      //do check
      pending_txn_cnt++;
    end
  endtask

  task check_outputs();
    output_txn_c txn;
    forever begin
      output_analysis_fifo.get(txn); //blocking get
      assert(pending_txn_cnt > 0);
      pending_txn_cnt--;
    end
  endtask
endclass

该架构通过fork-join_none并行启动输入、输出检查进程,无法保证input_txn被优先处理:若output_txn先被处理,断言会因未识别到同周期存在input_txn而误触发。

解决方案

UVM没有内置自动实现「当前时间步所有monitor执行完成后再启动checker」的专属机制,但可以通过UVM原生同步原语零侵入实现每周期专属检查屏障效果,完全规避进程调度顺序不确定导致的断言误触发问题,核心是用uvm_barrier做显式的每周期同步屏障,从根源上消除同时间槽内的进程调度不确定性,不需要修改现有checker的检查逻辑。

具体实现步骤

  • 在验证环境顶层(env层)例化一个uvm_barrier实例:
    • 将屏障的等待阈值设置为需要同步的monitor总数量(比如输入agent monitor+输出agent monitor共2个,阈值就设为2)
    • 开启屏障的自动重置属性,保证每次放行后计数自动清零,适配逐周期同步的需求
  • 修改所有参与同步的monitor采样逻辑:
    每个monitor的run_phase中,在时钟沿完成信号采样、事务组包、调用analysis_port.write(txn)将事务发送到checker侧的analysis fifo之后,立刻调用barrier.wait_for(),进入等待状态,等其他所有monitor完成当前周期的事务发送操作。
  • 修改checker的run_phase触发逻辑:
    移除原有直接等待posedge clk就执行检查的逻辑,改为先等待barrier.wait_for(),等屏障放行(即所有monitor都已将当前周期的事务写入fifo)之后,再按固定顺序调用check_inputs()、check_outputs()完成当前周期检查,之后等待下一个时钟沿进入下一轮循环即可。

方案优势

  • 彻底规避Design 2架构下并行进程调度顺序不确定、输出事务被优先处理的问题,检查顺序完全可控
  • 彻底规避Design 1架构下checker被优先调度、monitor还未写入当前周期事务就启动检查的问题,所有fifo读操作都在所有monitor事务发送完成后执行
  • 不依赖仿真器的特定调度规则,在所有主流UVM仿真器下行为一致
  • 不需要修改现有的事务检查逻辑,仅调整检查启动的同步时机,完全适配旁路逻辑同周期输入输出检查需求

不建议依赖#0延迟、修改phase调度优先级这类隐式方法实现顺序控制,这类方法在不同仿真器、不同编译选项下可能出现行为差异,稳定性远低于显式屏障同步。


内容的提问来源于stack exchange,提问作者Melandru's Square

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 23:12:17