@@ -8,6 +8,7 @@ Author: Daniel Kroening, kroening@kroening.com
88
99#include " temporal_logic.h"
1010
11+ #include < util/arith_tools.h>
1112#include < util/expr_util.h>
1213
1314#include < verilog/sva_expr.h>
@@ -211,6 +212,15 @@ std::optional<exprt> LTL_to_CTL(exprt expr)
211212 return {};
212213}
213214
215+ static exprt n_Xes (mp_integer n, exprt op)
216+ {
217+ PRECONDITION (n >= 0 );
218+ if (n == 0 )
219+ return op;
220+ else
221+ return n_Xes (n - 1 , X_exprt{std::move (op)});
222+ }
223+
214224std::optional<exprt> SVA_to_LTL (exprt expr)
215225{
216226 // Some SVA is directly mappable to LTL
@@ -222,6 +232,64 @@ std::optional<exprt> SVA_to_LTL(exprt expr)
222232 else
223233 return {};
224234 }
235+ else if (expr.id () == ID_sva_ranged_always)
236+ {
237+ auto &ranged_always = to_sva_ranged_always_expr (expr);
238+ auto rec = SVA_to_LTL (ranged_always.op ());
239+ if (rec.has_value ())
240+ {
241+ // always [l:u] op ---> X ... X (op ∧ X op ∧ ... ∧ X ... X op)
242+ auto lower_int = numeric_cast_v<mp_integer>(ranged_always.lower ());
243+
244+ // Is there an upper end of the range?
245+ if (ranged_always.upper ().is_constant ())
246+ {
247+ // upper end set
248+ auto upper_int =
249+ numeric_cast_v<mp_integer>(to_constant_expr (ranged_always.upper ()));
250+ PRECONDITION (upper_int >= lower_int);
251+ auto diff = upper_int - lower_int;
252+
253+ exprt::operandst conjuncts;
254+
255+ for (auto i = 0 ; i <= diff; i++)
256+ conjuncts.push_back (n_Xes (i, rec.value ()));
257+
258+ return n_Xes (lower_int, conjunction (conjuncts));
259+ }
260+ else if (ranged_always.upper ().id () == ID_infinity)
261+ {
262+ // always [l:$] op ---> X ... X G op
263+ return n_Xes (lower_int, G_exprt{rec.value ()});
264+ }
265+ else
266+ PRECONDITION (false );
267+ }
268+ else
269+ return {};
270+ }
271+ else if (expr.id () == ID_sva_s_always)
272+ {
273+ auto &ranged_always = to_sva_s_always_expr (expr);
274+ auto rec = SVA_to_LTL (ranged_always.op ());
275+ if (rec.has_value ())
276+ {
277+ // s_always [l:u] op ---> X ... X (op ∧ X op ∧ ... ∧ X ... X op)
278+ auto lower_int = numeric_cast_v<mp_integer>(ranged_always.lower ());
279+ auto upper_int = numeric_cast_v<mp_integer>(ranged_always.upper ());
280+ PRECONDITION (upper_int >= lower_int);
281+ auto diff = upper_int - lower_int;
282+
283+ exprt::operandst conjuncts;
284+
285+ for (auto i = 0 ; i <= diff; i++)
286+ conjuncts.push_back (n_Xes (i, rec.value ()));
287+
288+ return n_Xes (lower_int, conjunction (conjuncts));
289+ }
290+ else
291+ return {};
292+ }
225293 else if (expr.id () == ID_sva_s_eventually)
226294 {
227295 auto rec = SVA_to_LTL (to_sva_s_eventually_expr (expr).op ());
0 commit comments