System verilog 并发断言-UVM测试依赖项

System verilog 并发断言-UVM测试依赖项,system-verilog,assertions,uvm,system-verilog-assertions,System Verilog,Assertions,Uvm,System Verilog Assertions,我想写并发断言,它在从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 writ

我想写并发断言,它在从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
这里使用了两个全局空间变量;最好避免这样做

无论哪种方式,我都可以在top中获取这些变量,并在test中通过$root访问它们。但是,我不喜欢使用$root来解决可重用性和软件包问题(如果我的名字改变了,或者编写了用于断言的seprate模块,测试将得到一个错误)

我想知道有没有其他更好的方法来实现这一点?这样我就可以延迟断言的执行。即使我把它延迟了1个时间戳,我也会进入uvm_测试(听起来很疯狂…!!)

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


非常感谢您的帮助。

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

interface sva_checker(...);
  event register_written;

  property my_prop;
    register_written |-> ...
  endproperty
endinterface
这样,您只能在寄存器写入发生后触发属性。您也不需要根据协议信号计算寄存器写入何时发生,因为您将依赖于测试台上的信息

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测试台触发此事件。首先,您需要将此接口传递给您的UVM测试台。如果这是您仅有的接口,那么它就相当简单。只需执行配置数据库集和相应的get:

// 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寄存器包来登记。通过这种方式,您可以在寄存器写入后自动触发此事件,而无需手动调用它。

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

interface sva_checker(...);
  event register_written;

  property my_prop;
    register_written |-> ...
  endproperty
endinterface
这样,您只能在寄存器写入发生后触发属性。您也不需要根据协议信号计算寄存器写入何时发生,因为您将依赖于测试台上的信息

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测试台触发此事件。首先,您需要将此接口传递给您的UVM测试台。如果这是您仅有的接口,那么它就相当简单。只需执行配置数据库集和相应的get:

// 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转换为接口。。!!有几点需要澄清。首先,我了解如何将SVA接口传递给测试和事件触发逻辑。但是,
事件
在整个模拟过程中将只触发一次,此后只触发断言一次(而不是在寄存器写入后的每个时钟脉冲上)。此外,汇编问题;因为**多个计时表达式**(时钟边缘和事件)不能在属性中使用。因此,我更喜欢使用变量
位寄存器_write
而不是
事件寄存器_write
;我想这些信息应该没什么区别。我已经为此编写了一个伪代码,使用bit而不是event(event按预期抛出编译错误)。链接位于。谢谢@Tudor。我从来没有想过要将SVA转换为接口。。!!有几点需要澄清。首先,我了解如何将SVA接口传递给测试和事件触发逻辑。但是,
事件
在整个模拟过程中将只触发一次,此后只触发断言一次(而不是在寄存器写入后的每个时钟脉冲上)。此外,汇编问题;因为**多个计时表达式**(时钟边缘和事件)不能在属性中使用。因此,我更喜欢使用变量
位寄存器_write
而不是
事件寄存器_write
;我想这些信息应该没什么区别。我已经为此编写了一个伪代码,使用bit而不是event(event按预期抛出编译错误)。链接可从以下网址获得:。