在监视每个时间步后,如何保证检查器运行

发布于 2025-02-12 01:52:33 字数 1769 浏览 4 评论 0原文

我有几个代理商都有自己的显示器和分析端口连接到检查器。 Checker的组织如下所示,每个check()函数以特定顺序为每个周期。这样做是为了处理在同一周期中获得输入和输出TXN的情况(设计具有“旁路”逻辑,以立即在同一周期中输出其在输入上看到的TXN)。

如果我们使用设计#2(下图),则不能保证我们将首先处理Input_TXN,因此,如果我们碰巧首先处理output_txn,则断言可以发射,因为它不知道该input_txn中有一个input_txn相同的周期。我已经成功地使用了设计#1来处理在同一周期中获得输入和输出TXN的情况。但是,我现在意识到这仍然不能保证正确工作,因为模拟器有可能在output_agent的run_phase()之后执行Checker的run_phase(),但是在input_agent的run_phase()之前,我可以找到同样的问题。

我真正想要的几乎是每个时间段的“ check_phase”,因此我可以保证所有代理监视器在当前的时间步中完成了在检查器开始执行之前执行的。是否有任何方法可以保证在当前时间步中所有其他过程之后的检查器执行?

ps,我不是在寻找有关如何改善检查器的建议,这只是我为轻松传达问题的实际测试台的非常愚蠢的版本。

## 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


## 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

I have several agents each with their own monitor and analysis ports connected to a checker. The checker is organized like below where it calls each check() function every cycle in a specific order. This is done this way to handle the case where we get an input and output txn in the same cycle (design has "bypass" logic to immediately output the txn it sees on its input in the same cycle).

If we go with design #2 (below), there is no guarantee that we will process the input_txn first, so if we happen to process the output_txn first, the assertion could fire because it doesn't know that there was an input_txn in the same cycle. I have had success using Design #1 to handle the case where we get an input and output txn in the same cycle; however I now realize this is still not guaranteed to work correctly because it's possible that the simulator could execute the checker's run_phase() after the output_agent's run_phase() but before the input_agent's run_phase(), and I could get the same issue.

What I really want is almost a "check_phase" for each timestep, so I can guarantee all agents monitors' have finished executing in the current timestep before the checker starts executing. Is there any way to guarantee the checker executes after all other processes in the current timestep?

P.S. I'm not looking for advice on how to improve my checker, this is just a very dumbed down version of my actual testbench I made to easily convey the problem I have.

## 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


## 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

陌上青苔 2025-02-19 01:52:33

由于您对输入和输出都使用FIFO,因此您应该能够使用此简单设计:

class my_checker extends uvm_component;
    //boiler plate uvm...
    input_txn_c  txni;
    output_txn_c txno;

    task run_phase();
        forever begin
            // Wait until there is an input transaction: txni
            input_analysis_fifo.get(txni);

            // Wait until there is an output transaction: txno
            output_analysis_fifo.get(txno);

            // Now there is a pair of transactions to compare: txni vs. txno
            // call compare function...
        end
    endtask

    // compare function...
endclass

由于get呼叫正在阻止,您只需要等到输入交易,然后等待直到您有输出交易。他们是否到达相同的时间步中都没关系。一旦有一个内/输出对,您可以调用比较函数。

我认为您不需要检查每对的交易数量。如果需要,您可以检查FIFO在测试结束时是否仍然有任何内容。

Since you use a FIFO for both the input and output, you should be able to use this simple design:

class my_checker extends uvm_component;
    //boiler plate uvm...
    input_txn_c  txni;
    output_txn_c txno;

    task run_phase();
        forever begin
            // Wait until there is an input transaction: txni
            input_analysis_fifo.get(txni);

            // Wait until there is an output transaction: txno
            output_analysis_fifo.get(txno);

            // Now there is a pair of transactions to compare: txni vs. txno
            // call compare function...
        end
    endtask

    // compare function...
endclass

Since the get calls are blocking, you just need to wait until you have an input transaction, then wait until you have an output transaction. It does not matter if they arrive in the same timestep. Once you have an in/out pair, you can call your compare function.

I don't think you need to check the transaction count for every pair. If you want, you could check if the FIFO's still have anything in them at the end of the test.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文