Skip to content

Commit 3131672

Browse files
committed
SVA [*] for sequence operands
This implements the SVA operator op[*x:y] for the case when op is a sequence.
1 parent f20c412 commit 3131672

File tree

5 files changed

+48
-30
lines changed

5 files changed

+48
-30
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
sequence_repetition7.sv
3+
--bound 20
4+
^\[.*\] \(main\.a ##1 main\.b\) \[\*5\]: PROVED up to bound 20$
5+
^\[.*\] \(\!main\.b ##1 \!main\.a\) \[\*5\]: PROVED up to bound 20$
6+
^EXIT=0$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring
10+
--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module main(input clk);
2+
3+
bit a = 1, b = 0;
4+
5+
always_ff @(posedge clk) begin
6+
a = !a;
7+
b = !b;
8+
end
9+
10+
// a b a b ...
11+
initial assert property ((a ##1 b)[*5]);
12+
13+
// !b !a !b !a ...
14+
initial assert property ((!b ##1 !a)[*5]);
15+
16+
endmodule

src/trans-word-level/sequence.cpp

+14-28
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Author: Daniel Kroening, [email protected]
99
#include "sequence.h"
1010

1111
#include <util/arith_tools.h>
12+
#include <util/mathematical_types.h>
1213

1314
#include <ebmc/ebmc_error.h>
1415
#include <temporal-logic/temporal_logic.h>
@@ -367,36 +368,21 @@ sequence_matchest instantiate_sequence(
367368
else if(expr.id() == ID_sva_sequence_repetition_star) // [*...]
368369
{
369370
auto &repetition = to_sva_sequence_repetition_star_expr(expr);
370-
if(repetition.is_unbounded() && repetition.repetitions_given())
371+
if(repetition.is_empty_match())
371372
{
372-
// [*x:$]
373-
auto from = numeric_cast_v<mp_integer>(repetition.from());
374-
auto &op = repetition.op();
375-
376-
// Is op a sequence or a state predicate?
377-
if(is_SVA_sequence_operator(op))
378-
PRECONDITION(false); // no support
379-
380-
sequence_matchest result;
381-
382-
// we incrementally add conjuncts to the condition
383-
exprt::operandst conjuncts;
384-
385-
for(mp_integer u = t; u < no_timeframes; ++u)
386-
{
387-
// does op hold in timeframe u?
388-
auto cond_u = instantiate(op, u, no_timeframes);
389-
conjuncts.push_back(cond_u);
390-
391-
if(conjuncts.size() >= from)
392-
result.push_back({u, conjunction(conjuncts)});
393-
}
394-
395-
// Empty match allowed?
396-
if(from == 0)
397-
result.push_back({t, true_exprt{}});
373+
// [*0] denotes the empty match
374+
return {{t, true_exprt{}}};
375+
}
376+
else if(repetition.is_unbounded() && repetition.repetitions_given())
377+
{
378+
// [*from:$] -> op[*from:to]
379+
// with to = no_timeframes - t
380+
auto to = from_integer(no_timeframes - t, integer_typet{});
381+
auto new_repetition = sva_sequence_repetition_star_exprt{
382+
repetition.op(), repetition.from(), to};
398383

399-
return result;
384+
return instantiate_sequence(
385+
new_repetition.lower(), semantics, t, no_timeframes);
400386
}
401387
else
402388
{

src/verilog/sva_expr.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ exprt sva_sequence_repetition_star_exprt::lower() const
7979
{
8080
// expand x[*n] into x ##1 x ##1 ...
8181
auto n = numeric_cast_v<mp_integer>(repetitions());
82-
DATA_INVARIANT(n >= 1, "number of repetitions must be at least one");
82+
PRECONDITION(n >= 1); // [*0] is a special case, denoting the empty match
8383

8484
exprt result = op();
8585

@@ -103,7 +103,7 @@ exprt sva_sequence_repetition_star_exprt::lower() const
103103
auto from_int = numeric_cast_v<mp_integer>(from());
104104
auto to_int = numeric_cast_v<mp_integer>(to());
105105

106-
DATA_INVARIANT(from_int >= 1, "number of repetitions must be at least one");
106+
DATA_INVARIANT(from_int >= 0, "number of repetitions must not be negative");
107107
DATA_INVARIANT(
108108
to_int >= from_int, "number of repetitions must be interval");
109109

src/verilog/sva_expr.h

+6
Original file line numberDiff line numberDiff line change
@@ -1401,6 +1401,12 @@ class sva_sequence_repetition_exprt : public ternary_exprt
14011401
return op1().is_not_nil();
14021402
}
14031403

1404+
/// op[*0] is a special case, denoting the empty match
1405+
bool is_empty_match() const
1406+
{
1407+
return !is_range() && repetitions_given() && op0().is_zero();
1408+
}
1409+
14041410
// The number of repetitions must be a constant after elaboration.
14051411
const constant_exprt &repetitions() const
14061412
{

0 commit comments

Comments
 (0)