@@ -8,11 +8,13 @@ Author: Daniel Kroening, kroening@kroening.com
88
99#include " property.h"
1010
11+ #include < util/arith_tools.h>
1112#include < util/expr_iterator.h>
1213#include < util/namespace.h>
1314#include < util/std_expr.h>
1415#include < util/symbol_table.h>
1516
17+ #include < ebmc/ebmc_error.h>
1618#include < temporal-logic/temporal_expr.h>
1719#include < temporal-logic/temporal_logic.h>
1820#include < verilog/sva_expr.h>
@@ -56,6 +58,8 @@ bool bmc_supports_property(const exprt &expr)
5658 return bmc_supports_property (to_X_expr (expr).op ());
5759 else if (expr.id () == ID_sva_always)
5860 return true ;
61+ else if (expr.id () == ID_sva_ranged_always)
62+ return true ;
5963 else
6064 return false ;
6165}
@@ -75,12 +79,12 @@ Function: property_obligations_rec
7579static void property_obligations_rec (
7680 const exprt &property_expr,
7781 decision_proceduret &solver,
78- std:: size_t current,
79- std:: size_t no_timeframes,
82+ const mp_integer & current,
83+ const mp_integer & no_timeframes,
8084 const namespacet &ns,
81- std::map<std:: size_t , exprt::operandst> &obligations)
85+ std::map<mp_integer , exprt::operandst> &obligations)
8286{
83- PRECONDITION (current < no_timeframes);
87+ PRECONDITION (current >= 0 && current < no_timeframes);
8488
8589 if (property_expr.id () == ID_X)
8690 {
@@ -108,7 +112,43 @@ static void property_obligations_rec(
108112 PRECONDITION (false );
109113 }(property_expr);
110114
111- for (std::size_t c = current; c < no_timeframes; c++)
115+ for (mp_integer c = current; c < no_timeframes; ++c)
116+ {
117+ property_obligations_rec (phi, solver, c, no_timeframes, ns, obligations);
118+ }
119+ }
120+ else if (
121+ property_expr.id () == ID_sva_ranged_always ||
122+ property_expr.id () == ID_sva_s_always)
123+ {
124+ auto &phi = property_expr.id () == ID_sva_ranged_always
125+ ? to_sva_ranged_always_expr (property_expr).op ()
126+ : to_sva_s_always_expr (property_expr).op ();
127+ auto &range = property_expr.id () == ID_sva_ranged_always
128+ ? to_sva_ranged_always_expr (property_expr).range ()
129+ : to_sva_s_always_expr (property_expr).range ();
130+
131+ auto from_opt = numeric_cast<mp_integer>(range.op0 ());
132+ if (!from_opt.has_value ())
133+ throw ebmc_errort () << " failed to convert SVA always from index" ;
134+
135+ auto from = std::max (mp_integer{0 }, *from_opt);
136+
137+ mp_integer to;
138+
139+ if (range.op1 ().id () == ID_infinity)
140+ {
141+ to = no_timeframes - 1 ;
142+ }
143+ else
144+ {
145+ auto to_opt = numeric_cast<mp_integer>(range.op1 ());
146+ if (!to_opt.has_value ())
147+ throw ebmc_errort () << " failed to convert SVA always to index" ;
148+ to = std::min (*to_opt, no_timeframes - 1 );
149+ }
150+
151+ for (mp_integer c = from; c <= to; ++c)
112152 {
113153 property_obligations_rec (phi, solver, c, no_timeframes, ns, obligations);
114154 }
@@ -133,13 +173,13 @@ Function: property_obligations
133173
134174\*******************************************************************/
135175
136- static std::map<std:: size_t , exprt::operandst> property_obligations (
176+ static std::map<mp_integer , exprt::operandst> property_obligations (
137177 const exprt &property_expr,
138178 decision_proceduret &solver,
139- std:: size_t no_timeframes,
179+ const mp_integer & no_timeframes,
140180 const namespacet &ns)
141181{
142- std::map<std:: size_t , exprt::operandst> obligations;
182+ std::map<mp_integer , exprt::operandst> obligations;
143183
144184 property_obligations_rec (
145185 property_expr, solver, 0 , no_timeframes, ns, obligations);
@@ -178,8 +218,10 @@ void property(
178218 for (auto &obligation_it : obligations)
179219 {
180220 auto t = obligation_it.first ;
181- DATA_INVARIANT (t < no_timeframes, " obligation must have valid timeframe" );
182- prop_handles[t] = conjunction (obligation_it.second );
221+ DATA_INVARIANT (
222+ t >= 0 && t < no_timeframes, " obligation must have valid timeframe" );
223+ auto t_int = numeric_cast_v<std::size_t >(t);
224+ prop_handles[t_int] = conjunction (obligation_it.second );
183225 }
184226}
185227
0 commit comments