【问题标题】:Concurrent Assertion - UVM test dependency并发断言 - UVM 测试依赖
【发布时间】:2016-01-15 22:39:30
【问题描述】:

我想编写并发断言,该断言在从 UVM 测试台对 DUT 执行一些寄存器写入后开始。

class test extends uvm_test;
bit flag;
task run_phase(uvm_phase phase);
//call register write task , data is chosen in a random fashion
write(addr,data);
flag = 1;    // flag gives the time when the register is written.
// after this task the assertions must start depending on data.
endtask
endclass

module top();
//instantiate dut, interface and other stuff

property p1(logic a,logic [4:0] b,logic flag,logic c);
disable iff(!reset || b[i] == 1 || !flag)
/* 
default register value is 0, enable assertion only if 0 is written into it. 
(0 is for enabling certain feature in DUT and by-default it is enabled. 
1 is for disabling that feature. Assertion must never be enabled if b[i] contains 1)
*/
@(posedge clk)
a == 0 |-> $stable(c);
endproperty

assert property p1(dut_top.path_to_dut_signal,uvm_test_top.data,uvm_test_top.flag,dut_top.path_to_dut_other_signal); // gives compile error
// basically I need here dut's signal and the data written to register

// call run_test and set config_db for interface here
initial
begin
// ... run_test 
end

这会导致 跨模块引用 编译错误,因为 uvm_test_top 是在运行时创建的,我猜断言输入是在编译时设置的。

因此,我为此找到了一些解决方法。

在全局空间中声明一些临时变量和标志变量如下:

bit flag;   // in global space
logic [4:0] temp;
class test extends uvm_test;
task run_phase(uvm_phase phase);
//call register write task 
write(addr,data);
temp=data, flag=1;
// after this task the assertions must start depending on temp.
endtask
endclass

/** In top, **/

property p1(logic a,logic [4:0] b,logic flag,logic c);
disable iff(!reset || b[i] == 0 || flag ==0)
@(posedge clk)
a == 0 |-> $stable(c);
endproperty

assert property p1(dut_top.path_to_dut_signal,temp,flag,dut_top.path_to_dut_other_signal); 
// solves the error

这里使用了两个全局空间变量;最好避免。

无论哪种方式,我都可以将这些变量放在顶部并在测试中通过 $root 访问它们。但是,我不喜欢使用 $root 来解决可重用性和包问题(如果我的顶级名称发生更改,或者编写了单独的断言模块,测试会出错)。

我想知道有没有其他更好的方法来完成这个?这样我可以延迟断言的执行。即使我将它延迟 1timestamp,我也会对 uvm_test_top 进行评估(听起来很疯狂..!!)。

另外,我不想使用接口信号,因为 DUT 与协议无关,它可以支持基于 `ifdefs 的不同接口。 (其实这也是另一种解决方法!!)

非常感谢任何帮助。

【问题讨论】:

    标签: system-verilog assertions uvm system-verilog-assertions


    【解决方案1】:

    我能想到的最便携的事情是在您的 SVA 接口/模块/检查器中声明一个事件,该事件会在有趣的寄存器写入发生时发出信号:

    interface sva_checker(...);
      event register_written;
    
      property my_prop;
        register_written |-> ...
      endproperty
    endinterface
    

    这样你只在寄存器写入发生后触发你的属性。您也无需根据协议信号确定寄存器写入何时发生,因为您将依赖来自测试平台的信息。

    现在有趣的部分是从您的 UVM 测试台触发此事件。首先,您需要将此接口传递给您的 UVM 测试平台。如果这是您拥有的唯一界面,那么这很容易。你只需做一个配置数据库集和相应的获取:

    // in top or wherever you instantiate your SVA checker
    uvm_config_db #(virtual sva_checker)::set(...);
    
    // in your UVM TB
    uvm_config_db #(virtual sva_checker)::get(..., sva_checker);
    

    现在在您的代码中,您可以在知道您写入寄存器后触发事件:

    task run_phase(uvm_phase phase);
      //call register write task , data is chosen in a random fashion
      write(addr,data);
      -> sva_checker.register_written;
      // after this task the assertions must start depending on data.
    endtask
    

    这样您就不会使用任何分层路径,也不会遇到可重用性问题。

    附:我会考虑将 UVM 寄存器包用于寄存器。这样您就可以做到这一点,以便在写入寄存器后自动触发此事件,而无需手动调用它。

    【讨论】:

    • 感谢@Tudor。我从没想过将 SVA 转换为 interface..!!有几点要说清楚。 首先,我了解了如何将 SVA 接口传递给测试和事件触发逻辑。但是,event 只会在整个仿真过程中触发 一次,因此只会触发一次断言(而不是在寄存器写入后的每个时钟脉冲上)。此外,编译问题;因为**多个时序表达式**(时钟边沿和事件)不能在属性中使用。所以,我更喜欢使用变量bit register_written 而不是event register_written
    • 其次,这不是UVM-RAL的write方法,只是testbench-defined的write任务;我想这个信息应该没有什么区别。我为此制作了一个伪代码,使用位而不是事件(事件按预期抛出编译错误)。链接位于EDAPlayground
    猜你喜欢
    • 2017-02-24
    • 2017-08-30
    • 1970-01-01
    • 2013-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-05
    相关资源
    最近更新 更多