1111#include < verilog/sva_expr.h>
1212
1313#include " ltl.h"
14+ #include " sva_sequence_match.h"
1415#include " temporal_logic.h"
1516
1617static exprt n_Xes (mp_integer n, exprt op)
@@ -22,153 +23,18 @@ static exprt n_Xes(mp_integer n, exprt op)
2223 return n_Xes (n - 1 , X_exprt{std::move (op)});
2324}
2425
25- // Returns a set of match conditions (given as LTL formula)
26- struct ltl_sequence_matcht
26+ // c0 ∧ X c1 ∧ XX c2 ....
27+ static exprt ltl ( const sva_sequence_matcht &match)
2728{
28- // the empty match
29- ltl_sequence_matcht ()
29+ exprt::operandst conjuncts;
30+ conjuncts.reserve (match.cond_vector .size ());
31+ for (std::size_t i = 0 ; i < match.cond_vector .size (); i++)
3032 {
33+ auto &c = match.cond_vector [i];
34+ if (!c.is_true ())
35+ conjuncts.push_back (n_Xes (i, c));
3136 }
32-
33- // a match of length 1
34- explicit ltl_sequence_matcht (exprt __cond) : cond_vector{1 , std::move (__cond)}
35- {
36- }
37-
38- std::vector<exprt> cond_vector;
39-
40- std::size_t length ()
41- {
42- return cond_vector.size ();
43- }
44-
45- bool empty_match () const
46- {
47- return cond_vector.empty ();
48- }
49-
50- // c0 ∧ X c1 ∧ XX c2 ....
51- exprt cond_expr () const
52- {
53- exprt::operandst conjuncts;
54- conjuncts.reserve (cond_vector.size ());
55- for (std::size_t i = 0 ; i < cond_vector.size (); i++)
56- {
57- auto &c = cond_vector[i];
58- if (!c.is_true ())
59- conjuncts.push_back (n_Xes (i, c));
60- }
61- return conjunction (conjuncts);
62- }
63-
64- // generate true ##1 ... ##1 true with length n
65- static ltl_sequence_matcht true_match (const mp_integer &n)
66- {
67- ltl_sequence_matcht result;
68- for (mp_integer i; i < n; ++i)
69- result.cond_vector .push_back (true_exprt{});
70- return result;
71- }
72- };
73-
74- // nonoverlapping concatenation
75- ltl_sequence_matcht concat (ltl_sequence_matcht a, const ltl_sequence_matcht &b)
76- {
77- a.cond_vector .insert (
78- a.cond_vector .end (), b.cond_vector .begin (), b.cond_vector .end ());
79- return a;
80- }
81-
82- // overlapping concatenation
83- ltl_sequence_matcht
84- overlapping_concat (ltl_sequence_matcht a, ltl_sequence_matcht b)
85- {
86- PRECONDITION (!a.empty_match ());
87- PRECONDITION (!b.empty_match ());
88- auto a_last = a.cond_vector .back ();
89- a.cond_vector .pop_back ();
90- b.cond_vector .front () = conjunction ({a_last, b.cond_vector .front ()});
91- return concat (std::move (a), b);
92- }
93-
94- std::vector<ltl_sequence_matcht> LTL_sequence_matches (const exprt &sequence)
95- {
96- if (sequence.id () == ID_sva_boolean)
97- {
98- // atomic proposition
99- return {ltl_sequence_matcht{to_sva_boolean_expr (sequence).op ()}};
100- }
101- else if (sequence.id () == ID_sva_sequence_concatenation)
102- {
103- auto &concatenation = to_sva_sequence_concatenation_expr (sequence);
104- auto matches_lhs = LTL_sequence_matches (concatenation.lhs ());
105- auto matches_rhs = LTL_sequence_matches (concatenation.rhs ());
106-
107- if (matches_lhs.empty () || matches_rhs.empty ())
108- return {};
109-
110- std::vector<ltl_sequence_matcht> result;
111-
112- // cross product
113- for (auto &match_lhs : matches_lhs)
114- for (auto &match_rhs : matches_rhs)
115- {
116- // Sequence concatenation is overlapping
117- auto new_match = overlapping_concat (match_lhs, match_rhs);
118- CHECK_RETURN (
119- new_match.length () == match_lhs.length () + match_rhs.length () - 1 );
120- result.push_back (std::move (new_match));
121- }
122- return result;
123- }
124- else if (sequence.id () == ID_sva_cycle_delay)
125- {
126- auto &delay = to_sva_cycle_delay_expr (sequence);
127- auto matches = LTL_sequence_matches (delay.op ());
128- auto from_int = numeric_cast_v<mp_integer>(delay.from ());
129-
130- if (matches.empty ())
131- return {};
132-
133- if (delay.to ().is_nil ())
134- {
135- // delay as instructed
136- auto delay_sequence = ltl_sequence_matcht::true_match (from_int);
137-
138- for (auto &match : matches)
139- match = concat (delay_sequence, match);
140-
141- return matches;
142- }
143- else if (delay.to ().id () == ID_infinity)
144- {
145- return {}; // can't encode
146- }
147- else if (delay.to ().is_constant ())
148- {
149- auto to_int = numeric_cast_v<mp_integer>(to_constant_expr (delay.to ()));
150- std::vector<ltl_sequence_matcht> new_matches;
151-
152- for (mp_integer i = from_int; i <= to_int; ++i)
153- {
154- // delay as instructed
155- auto delay_sequence = ltl_sequence_matcht::true_match (i);
156-
157- for (const auto &match : matches)
158- {
159- new_matches.push_back (concat (delay_sequence, match));
160- }
161- }
162-
163- return new_matches;
164- }
165- else
166- return {};
167- }
168- else
169- {
170- return {}; // unsupported
171- }
37+ return conjunction (conjuncts);
17238}
17339
17440// / takes an SVA property as input, and returns an equivalent LTL property,
@@ -296,7 +162,7 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
296162 {
297163 auto delay = match.length () + (overlapped ? 0 : 1 ) - 1 ;
298164 auto delayed_property = n_Xes (delay, property_rec.value ());
299- conjuncts.push_back (implies_exprt{match. cond_expr ( ), delayed_property});
165+ conjuncts.push_back (implies_exprt{ltl (match ), delayed_property});
300166 }
301167 }
302168
@@ -332,7 +198,7 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
332198 {
333199 auto delay = match.length () + (overlapped ? 0 : 1 ) - 1 ;
334200 auto delayed_property = n_Xes (delay, property_rec.value ());
335- disjuncts.push_back (and_exprt{match. cond_expr ( ), delayed_property});
201+ disjuncts.push_back (and_exprt{ltl (match ), delayed_property});
336202 }
337203 }
338204
@@ -360,7 +226,7 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
360226 for (auto &match : matches)
361227 {
362228 if (!match.empty_match ())
363- disjuncts.push_back (match. cond_expr ( ));
229+ disjuncts.push_back (ltl (match ));
364230 }
365231
366232 return disjunction (disjuncts);
0 commit comments