16.6布尔值表达式
表达式的计算结果是布尔值,其解释方式和在过程if语句的条件下解释表达式的方式相同,如果表达式计算为x,z,0,则会解释为错误,否则为真。
并发断言中出现的表达式应满足以下规则:
(1)表达式应产生与整型兼容的类型,只要整个表达式与整型兼容,子表达式不需满足此要求;
(2)为断言表达式求值,而采样的动态数组、队列和关联数组的元素可能会从数组中删除,或者在求值断言表达式之前,数组可能会调整大小;
(3)出现在过程并发断言中的表达式可以引用自动变量,否则,并发断言中的表达式不得引用自动变量;
(4)表达式不得引用非静态类属性或方法;
(5)表达式不得引用chandle数据类型的变量;
(6)以局部变量作为variable_lvalue的序列匹配项可以使用C赋值、递增和递减运算符,否则,表达式的计算不得有任何副作用(例如,不允许使用递增和递减运算符);
(7)出现在表达式的函数不得包含输出或ref参数(const ref可以);
(8) 函数应是自动(或不保留状态信息)且没有副作用的。
访问大型数据结构时应小心,尤其是在并发断言中的大型动态数据结构,某些类型的访问可能需要创建整个数据结构的副本,这可能会导致严重的性能损失,下例例子说明,怎样需要复制完整数据结构。
在p1中断言只能对q的单个字节进行采样,且该字节的位置是固定的,然而在p2中,将有多个活动线程可能有不同的l_b值,这增加了确定要对q的哪些字节进行采样的难度,并可能导致对所有q进行采样。
bit a;
integer b;
byte q[$];
property p1;
$rose(a) |-> q[0];
endproperty
property p2;
integer l_b;
($rose(a), l_b = b) |-> ##[3:10] q[l_b];
endproperty
并发断言中布尔值表达式发生在两个地方:
(1)序列或属性表达式;
(2)在顶层disable iff分句或默认disable iff声明中,指定断言推断的禁用条件。
用于定义序列和属性表达式的布尔值表达式,应在所有变量的采样值上进行计算,但是,上述规则不适用于时钟事件中的表达式。
在禁用条件中的表达式使用变量(未采样)的当前值进行计算,且会包含布尔值触发(triggered)的方法序列,它们不包含对局部变量或者匹配(matched)方法序列的任何引用。
基于时间值执行检的查断言,应在相同上下文捕捉时间值,不推荐在断言外捕捉时间,应在断言中使用局部变量捕捉时间,下面这个例子说明,在不同环境下捕捉时间会产生怎样的错误:
bit count[2:0];
realtime t;
initial count = 0;
always @(posedge clk) begin
if (count == 0) t = $realtime; //capture t in a procedural context
count++;
end
property p1;
@(posedge clk)
count == 7 |-> $realtime – t < 50.5;
endproperty
property p2;
realtime l_t;
@(posedge clk)
(count == 0, l_t = $realtime) ##1 (count == 7)[->1] |->
$realtime – l_t < 50.5;
endproperty
在属性p1中,基于count的当前值在过程上下文捕捉时间值t,在断言中,根据count的采样值,在断言上下文中时间值t和由$realtime返回的时间值作比较,在这两种情况下,$realtime返回当前时间值;因此,在不同上下文捕捉的时间值之间的比较会产生不同结果,不一致性导致p1的计算检查8个clk周期(而不是预期的7个周期)之间经过的时间量。在属性p2中,两个时间值都在断言上下文中捕获,这种情况会产生一致的结果。