Skip to content

Commit 421e83b

Browse files
committed
SVA: introduce admits_empty
This introduces the function admits_empty, following 1800-2017 F.4.3. It returns true iff the given SVA sequence admits an empty match.
1 parent 8f220ab commit 421e83b

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

src/temporal-logic/sva_sequence_match.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Author: Daniel Kroening, [email protected]
1313

1414
#include <verilog/sva_expr.h>
1515

16+
#include "temporal_logic.h"
17+
1618
sva_sequence_matcht sva_sequence_matcht::true_match(const mp_integer &n)
1719
{
1820
sva_sequence_matcht result;
@@ -214,3 +216,57 @@ std::vector<sva_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
214216
throw sva_sequence_match_unsupportedt{sequence}; // not supported
215217
}
216218
}
219+
220+
bool admits_empty(const exprt &expr)
221+
{
222+
PRECONDITION(expr.type().id() == ID_verilog_sva_sequence);
223+
PRECONDITION(is_SVA_sequence_operator(expr));
224+
225+
if(expr.id() == ID_sva_boolean)
226+
return false; // admits_empty(b) = 0
227+
else if(expr.id() == ID_sva_cycle_delay)
228+
{
229+
auto &cycle_delay = to_sva_cycle_delay_expr(expr);
230+
if(cycle_delay.from().is_zero() && !cycle_delay.is_range())
231+
{
232+
// admits_empty((r1 ##0 r2)) = 0
233+
return false;
234+
}
235+
else
236+
{
237+
// admits_empty((r1 ##1 r2)) = admits_empty(r1) && admits_empty(r2)
238+
return cycle_delay.lhs().is_not_nil() &&
239+
admits_empty(cycle_delay.lhs()) && admits_empty(cycle_delay.rhs());
240+
}
241+
}
242+
else if(expr.id() == ID_sva_or)
243+
{
244+
// admits_empty((r1 or r2)) = admits_empty(r1) || admits_empty(r2)
245+
auto &or_expr = to_sva_or_expr(expr);
246+
return admits_empty(or_expr.lhs()) || admits_empty(or_expr.rhs());
247+
}
248+
else if(expr.id() == ID_sva_sequence_intersect)
249+
{
250+
// admits_empty((r1 intersect r2)) = admits_empty(r1) && admits_empty(r2)
251+
auto &intersect_expr = to_sva_sequence_intersect_expr(expr);
252+
return admits_empty(intersect_expr.lhs()) &&
253+
admits_empty(intersect_expr.rhs());
254+
}
255+
else if(expr.id() == ID_sva_sequence_first_match)
256+
{
257+
// admits_empty(first_match(r)) = admits_empty(r)
258+
auto &first_match_expr = to_sva_sequence_first_match_expr(expr);
259+
return admits_empty(first_match_expr.lhs()) &&
260+
admits_empty(first_match_expr.rhs());
261+
}
262+
else if(expr.id() == ID_sva_sequence_repetition_star)
263+
{
264+
// admits_empty(r[*0]) = 1
265+
// admits_empty(r[*1:$]) = admits_empty(r)
266+
auto &repetition_expr = to_sva_sequence_repetition_star_expr(expr);
267+
}
268+
else
269+
{
270+
DATA_INVARIANT(false, "unexpected SVA sequence: " + expr.id_string());
271+
}
272+
}

src/temporal-logic/sva_sequence_match.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,8 @@ class sva_sequence_match_unsupportedt
6868
/// Throws sva_sequence_match_unsupportedt when given sequence that cannot be translated.
6969
std::vector<sva_sequence_matcht> LTL_sequence_matches(const exprt &);
7070

71+
/// 1800-2017 F.4.3
72+
/// Returns true iff the given SVA sequence admits an empty match.
73+
bool admits_empty(const exprt &);
74+
7175
#endif // CPROVER_TEMPORAL_LOGICS_SVA_SEQUENCE_MATCH_H

0 commit comments

Comments
 (0)