Skip to content

Commit cbb6c03

Browse files
authored
Merge pull request #1157 from diffblue/sva_sequence_match_unsupportedt
`LTL_sequence_matches` now throws `sva_sequence_match_unsupportedt`
2 parents b1a5576 + b9a5c93 commit cbb6c03

File tree

5 files changed

+147
-72
lines changed

5 files changed

+147
-72
lines changed

src/temporal-logic/sva_sequence_match.cpp

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,6 @@ std::vector<sva_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
6464
auto matches_lhs = LTL_sequence_matches(concatenation.lhs());
6565
auto matches_rhs = LTL_sequence_matches(concatenation.rhs());
6666

67-
if(matches_lhs.empty() || matches_rhs.empty())
68-
return {};
69-
7067
std::vector<sva_sequence_matcht> result;
7168

7269
// cross product
@@ -86,9 +83,6 @@ std::vector<sva_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
8683
auto &repetition = to_sva_sequence_repetition_star_expr(sequence);
8784
auto matches_op = LTL_sequence_matches(repetition.op());
8885

89-
if(matches_op.empty())
90-
return {};
91-
9286
std::vector<sva_sequence_matcht> result;
9387

9488
if(repetition.repetitions_given())
@@ -97,7 +91,7 @@ std::vector<sva_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
9791
{
9892
if(repetition.is_unbounded()) // [*n:$]
9993
{
100-
return {}; // no support
94+
throw sva_sequence_match_unsupportedt{sequence}; // no support
10195
}
10296
else // [*n:m]
10397
{
@@ -118,7 +112,7 @@ std::vector<sva_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
118112
}
119113
}
120114
else // [*]
121-
return {}; // no support
115+
throw sva_sequence_match_unsupportedt{sequence}; // no support
122116

123117
return result;
124118
}
@@ -128,9 +122,6 @@ std::vector<sva_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
128122
auto matches = LTL_sequence_matches(delay.op());
129123
auto from_int = numeric_cast_v<mp_integer>(delay.from());
130124

131-
if(matches.empty())
132-
return {};
133-
134125
if(!delay.is_range())
135126
{
136127
// delay as instructed
@@ -143,7 +134,7 @@ std::vector<sva_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
143134
}
144135
else if(delay.is_unbounded())
145136
{
146-
return {}; // can't encode
137+
throw sva_sequence_match_unsupportedt{sequence}; // can't encode
147138
}
148139
else
149140
{
@@ -175,9 +166,6 @@ std::vector<sva_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
175166
auto matches_lhs = LTL_sequence_matches(and_expr.lhs());
176167
auto matches_rhs = LTL_sequence_matches(and_expr.rhs());
177168

178-
if(matches_lhs.empty() || matches_rhs.empty())
179-
return {};
180-
181169
std::vector<sva_sequence_matcht> result;
182170

183171
for(auto &match_lhs : matches_lhs)
@@ -214,7 +202,7 @@ std::vector<sva_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
214202
{
215203
auto op_matches = LTL_sequence_matches(op);
216204
if(op_matches.empty())
217-
return {}; // not supported
205+
throw sva_sequence_match_unsupportedt{sequence}; // not supported
218206
for(auto &match : op_matches)
219207
result.push_back(std::move(match));
220208
}
@@ -223,6 +211,6 @@ std::vector<sva_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
223211
}
224212
else
225213
{
226-
return {}; // unsupported
214+
throw sva_sequence_match_unsupportedt{sequence}; // not supported
227215
}
228216
}

src/temporal-logic/sva_sequence_match.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ struct sva_sequence_matcht
2626
{
2727
}
2828

29+
// a match with given sequence of conditions
30+
explicit sva_sequence_matcht(std::vector<exprt> __cond_vector)
31+
: cond_vector(std::move(__cond_vector))
32+
{
33+
}
34+
2935
std::vector<exprt> cond_vector;
3036

3137
std::size_t length()
@@ -40,9 +46,26 @@ struct sva_sequence_matcht
4046

4147
// generate true ##1 ... ##1 true with length n
4248
static sva_sequence_matcht true_match(const mp_integer &n);
49+
50+
bool operator==(const sva_sequence_matcht &other) const
51+
{
52+
return cond_vector == other.cond_vector;
53+
}
54+
};
55+
56+
class sva_sequence_match_unsupportedt
57+
{
58+
public:
59+
explicit sva_sequence_match_unsupportedt(exprt __expr)
60+
: expr(std::move(__expr))
61+
{
62+
}
63+
64+
exprt expr;
4365
};
4466

45-
// the set of potential matches for the given sequence expression
67+
/// The set of potential matches for the given sequence expression.
68+
/// Throws sva_sequence_match_unsupportedt when given sequence that cannot be translated.
4669
std::vector<sva_sequence_matcht> LTL_sequence_matches(const exprt &);
4770

4871
#endif // CPROVER_TEMPORAL_LOGICS_SVA_SEQUENCE_MATCH_H

src/temporal-logic/sva_to_ltl.cpp

Lines changed: 68 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -139,72 +139,82 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
139139
expr.id() == ID_sva_non_overlapped_implication)
140140
{
141141
auto &implication = to_sva_implication_base_expr(expr);
142-
auto matches = LTL_sequence_matches(implication.sequence());
143142

144-
if(matches.empty())
145-
return {};
143+
try
144+
{
145+
auto matches = LTL_sequence_matches(implication.sequence());
146146

147-
// All matches must be followed
148-
// by the property being true
149-
exprt::operandst conjuncts;
147+
// All matches must be followed
148+
// by the property being true
149+
exprt::operandst conjuncts;
150150

151-
auto property_rec = SVA_to_LTL(implication.property());
151+
auto property_rec = SVA_to_LTL(implication.property());
152152

153-
if(!property_rec.has_value())
154-
return {};
153+
if(!property_rec.has_value())
154+
return {};
155155

156-
for(auto &match : matches)
157-
{
158-
const auto overlapped = expr.id() == ID_sva_overlapped_implication;
159-
if(match.empty_match() && overlapped)
160-
{
161-
// ignore the empty match
162-
}
163-
else
156+
for(auto &match : matches)
164157
{
165-
auto delay = match.length() + (overlapped ? 0 : 1) - 1;
166-
auto delayed_property = n_Xes(delay, property_rec.value());
167-
conjuncts.push_back(implies_exprt{ltl(match), delayed_property});
158+
const auto overlapped = expr.id() == ID_sva_overlapped_implication;
159+
if(match.empty_match() && overlapped)
160+
{
161+
// ignore the empty match
162+
}
163+
else
164+
{
165+
auto delay = match.length() + (overlapped ? 0 : 1) - 1;
166+
auto delayed_property = n_Xes(delay, property_rec.value());
167+
conjuncts.push_back(implies_exprt{ltl(match), delayed_property});
168+
}
168169
}
169-
}
170170

171-
return conjunction(conjuncts);
171+
return conjunction(conjuncts);
172+
}
173+
catch(sva_sequence_match_unsupportedt)
174+
{
175+
return {};
176+
}
172177
}
173178
else if(
174179
expr.id() == ID_sva_nonoverlapped_followed_by ||
175180
expr.id() == ID_sva_overlapped_followed_by)
176181
{
177182
auto &followed_by = to_sva_followed_by_expr(expr);
178-
auto matches = LTL_sequence_matches(followed_by.sequence());
179183

180-
if(matches.empty())
181-
return {};
184+
try
185+
{
186+
auto matches = LTL_sequence_matches(followed_by.sequence());
182187

183-
// There must be at least one match that is followed
184-
// by the property being true
185-
exprt::operandst disjuncts;
188+
// There must be at least one match that is followed
189+
// by the property being true
190+
exprt::operandst disjuncts;
186191

187-
auto property_rec = SVA_to_LTL(followed_by.property());
192+
auto property_rec = SVA_to_LTL(followed_by.property());
188193

189-
if(!property_rec.has_value())
190-
return {};
194+
if(!property_rec.has_value())
195+
return {};
191196

192-
for(auto &match : matches)
193-
{
194-
const auto overlapped = expr.id() == ID_sva_overlapped_followed_by;
195-
if(match.empty_match() && overlapped)
196-
{
197-
// ignore the empty match
198-
}
199-
else
197+
for(auto &match : matches)
200198
{
201-
auto delay = match.length() + (overlapped ? 0 : 1) - 1;
202-
auto delayed_property = n_Xes(delay, property_rec.value());
203-
disjuncts.push_back(and_exprt{ltl(match), delayed_property});
199+
const auto overlapped = expr.id() == ID_sva_overlapped_followed_by;
200+
if(match.empty_match() && overlapped)
201+
{
202+
// ignore the empty match
203+
}
204+
else
205+
{
206+
auto delay = match.length() + (overlapped ? 0 : 1) - 1;
207+
auto delayed_property = n_Xes(delay, property_rec.value());
208+
disjuncts.push_back(and_exprt{ltl(match), delayed_property});
209+
}
204210
}
205-
}
206211

207-
return disjunction(disjuncts);
212+
return disjunction(disjuncts);
213+
}
214+
catch(sva_sequence_match_unsupportedt)
215+
{
216+
return {};
217+
}
208218
}
209219
else if(expr.id() == ID_sva_sequence_property)
210220
{
@@ -217,21 +227,25 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
217227
{
218228
auto &sequence = to_sva_sequence_property_expr_base(expr).sequence();
219229

220-
// evaluates to true if there's at least one non-empty match of the sequence
221-
auto matches = LTL_sequence_matches(sequence);
230+
try
231+
{
232+
// evaluates to true if there's at least one non-empty match of the sequence
233+
auto matches = LTL_sequence_matches(sequence);
222234

223-
if(matches.empty())
224-
return {};
235+
exprt::operandst disjuncts;
225236

226-
exprt::operandst disjuncts;
237+
for(auto &match : matches)
238+
{
239+
if(!match.empty_match())
240+
disjuncts.push_back(ltl(match));
241+
}
227242

228-
for(auto &match : matches)
243+
return disjunction(disjuncts);
244+
}
245+
catch(sva_sequence_match_unsupportedt)
229246
{
230-
if(!match.empty_match())
231-
disjuncts.push_back(ltl(match));
247+
return {};
232248
}
233-
234-
return disjunction(disjuncts);
235249
}
236250
else if(expr.id() == ID_sva_s_until)
237251
{

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ SRC = unit_tests.cpp
66
# Test source files
77
SRC += smvlang/expr2smv.cpp \
88
temporal-logic/ltl_sva_to_string.cpp \
9+
temporal-logic/sva_sequence_match.cpp \
910
temporal-logic/nnf.cpp \
1011
# Empty last line
1112

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*******************************************************************\
2+
3+
Module: SVA Sequence Matches
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include <util/arith_tools.h>
10+
#include <util/mathematical_types.h>
11+
12+
#include <temporal-logic/sva_sequence_match.h>
13+
#include <testing-utils/use_catch.h>
14+
#include <verilog/sva_expr.h>
15+
16+
SCENARIO("Generating the matches for an SVA sequence")
17+
{
18+
const auto sequence_type = verilog_sva_sequence_typet{};
19+
20+
GIVEN("A boolean formula")
21+
{
22+
auto p = symbol_exprt{"p", bool_typet{}};
23+
24+
REQUIRE(
25+
LTL_sequence_matches(sva_boolean_exprt{p, sequence_type}) ==
26+
std::vector<sva_sequence_matcht>{sva_sequence_matcht{p}});
27+
}
28+
29+
GIVEN("##1 p")
30+
{
31+
auto p = symbol_exprt{"p", bool_typet{}};
32+
auto one = from_integer(1, integer_typet{});
33+
34+
REQUIRE(
35+
LTL_sequence_matches(
36+
sva_cycle_delay_exprt{one, sva_boolean_exprt{p, sequence_type}}) ==
37+
std::vector<sva_sequence_matcht>{sva_sequence_matcht{{true_exprt{}, p}}});
38+
}
39+
40+
GIVEN("##[*] p")
41+
{
42+
auto p = symbol_exprt{"p", bool_typet{}};
43+
44+
CHECK_THROWS_AS(
45+
LTL_sequence_matches(
46+
sva_cycle_delay_star_exprt{sva_boolean_exprt{p, sequence_type}}),
47+
sva_sequence_match_unsupportedt);
48+
}
49+
}

0 commit comments

Comments
 (0)