In SystemVerilog testbench generator class - 如何生成无限长的数据流

In SystemVerilog testbench generator class - how to generate infinitely long data stream

在我能在互联网上找到的所有 SystemVerilog 测试平台中,生成器 class 总是生成固定数量的样本并将它们发送到邮箱。驱动程序读取邮箱并通过操作接口信号生成适当的序列

一个这样的生成器,取自 [1](第 1.3 章,第 4 段)并简化为要点,例如:

    class generator;
      rand transaction trans;
      mailbox gen2driv;
      int  repeat_count; 
     
      function new(mailbox gen2driv);
        this.gen2driv = gen2driv;
      endfunction
       
      task main();
        repeat(repeat_count) begin
          trans = new();
          if( !trans.randomize() ) $fatal("Gen:: trans randomization failed");
          gen2driv.put(trans);
        end
      endtask
       
    endclass

这个生成repeat_count个样本并发送到邮箱。

然而,在某些情况下,用户想要生成无限数据流,因为测试平台模拟不会因缺少输入数据而终止,而是会因验证发生在未来某处未知时间的情况。

扩展上述示例以将 repeat(repeat_count) begin 替换为 forever begin 将不起作用。模拟器在尝试将无限数量的样本放入邮箱时在循环中冻结。由于 main 任务的执行是一个阻塞动作,驱动程序的信号发生器永远不会被执行,整个模拟停滞。

所以我的问题是:如何正确定义一个可以发送无限数据流的生成器class?

我正在寻找类似于 pythonic yield 和生成器函数的行为。然而,这需要驱动程序和生成器之间进行一些通信。那么这样的生成器模型应该不是很适合SV吧?

[1] https://verificationguide.com/systemverilog-examples/systemverilog-testbench-example-01

您要问的正是 UVM sequence/driver 机制的工作原理。在驱动程序准备好并要求驱动一个项目之前,生成器不会进行任何随机化。

但是您可以简单地通过构造边界为 1 的邮箱来接近 UVM 的作用。然后主循环中的 put(trans) 阻塞,直到驱动程序执行 get() .那么邮箱里总会有一笔交易等待下一个驱动周期。

您可以在主任务的某处添加等待语句,例如 wait(gen2driv.num()<pause_threshold);。这将阻止生成器添加更多事务,直到驱动程序有机会使用它。

task main();
  forever begin
    wait(gen2driv.num()<pause_threshold);
    trans = new();
    if( !trans.randomize() ) $fatal("Gen:: trans randomization failed");
    gen2driv.put(trans);
  end
endtask