Skip to content

Commit b9a5c93

Browse files
committed
LTL_sequence_matches now throws sva_sequence_match_unsupportedt
This allows reporting the sequence expression that is unsupported.
1 parent 96e6ba3 commit b9a5c93

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
@@ -137,72 +137,82 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
137137
expr.id() == ID_sva_non_overlapped_implication)
138138
{
139139
auto &implication = to_sva_implication_base_expr(expr);
140-
auto matches = LTL_sequence_matches(implication.sequence());
141140

142-
if(matches.empty())
143-
return {};
141+
try
142+
{
143+
auto matches = LTL_sequence_matches(implication.sequence());
144144

145-
// All matches must be followed
146-
// by the property being true
147-
exprt::operandst conjuncts;
145+
// All matches must be followed
146+
// by the property being true
147+
exprt::operandst conjuncts;
148148

149-
auto property_rec = SVA_to_LTL(implication.property());
149+
auto property_rec = SVA_to_LTL(implication.property());
150150

151-
if(!property_rec.has_value())
152-
return {};
151+
if(!property_rec.has_value())
152+
return {};
153153

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

169-
return conjunction(conjuncts);
169+
return conjunction(conjuncts);
170+
}
171+
catch(sva_sequence_match_unsupportedt)
172+
{
173+
return {};
174+
}
170175
}
171176
else if(
172177
expr.id() == ID_sva_nonoverlapped_followed_by ||
173178
expr.id() == ID_sva_overlapped_followed_by)
174179
{
175180
auto &followed_by = to_sva_followed_by_expr(expr);
176-
auto matches = LTL_sequence_matches(followed_by.sequence());
177181

178-
if(matches.empty())
179-
return {};
182+
try
183+
{
184+
auto matches = LTL_sequence_matches(followed_by.sequence());
180185

181-
// There must be at least one match that is followed
182-
// by the property being true
183-
exprt::operandst disjuncts;
186+
// There must be at least one match that is followed
187+
// by the property being true
188+
exprt::operandst disjuncts;
184189

185-
auto property_rec = SVA_to_LTL(followed_by.property());
190+
auto property_rec = SVA_to_LTL(followed_by.property());
186191

187-
if(!property_rec.has_value())
188-
return {};
192+
if(!property_rec.has_value())
193+
return {};
189194

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

205-
return disjunction(disjuncts);
210+
return disjunction(disjuncts);
211+
}
212+
catch(sva_sequence_match_unsupportedt)
213+
{
214+
return {};
215+
}
206216
}
207217
else if(expr.id() == ID_sva_sequence_property)
208218
{
@@ -215,21 +225,25 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
215225
{
216226
auto &sequence = to_sva_sequence_property_expr_base(expr).sequence();
217227

218-
// evaluates to true if there's at least one non-empty match of the sequence
219-
auto matches = LTL_sequence_matches(sequence);
228+
try
229+
{
230+
// evaluates to true if there's at least one non-empty match of the sequence
231+
auto matches = LTL_sequence_matches(sequence);
220232

221-
if(matches.empty())
222-
return {};
233+
exprt::operandst disjuncts;
223234

224-
exprt::operandst disjuncts;
235+
for(auto &match : matches)
236+
{
237+
if(!match.empty_match())
238+
disjuncts.push_back(ltl(match));
239+
}
225240

226-
for(auto &match : matches)
241+
return disjunction(disjuncts);
242+
}
243+
catch(sva_sequence_match_unsupportedt)
227244
{
228-
if(!match.empty_match())
229-
disjuncts.push_back(ltl(match));
245+
return {};
230246
}
231-
232-
return disjunction(disjuncts);
233247
}
234248
else if(expr.id() == ID_sva_s_until)
235249
{

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)