Skip to content

Commit d4d83c6

Browse files
committed
SMV netlist: translate some SVA to LTL
Parts of SVA map directly to LTL. This allows extending the set of formulas converted to LTL when outputting an SMV model.
1 parent b861e8b commit d4d83c6

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

Diff for: src/temporal-logic/temporal_logic.cpp

+77
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Author: Daniel Kroening, [email protected]
1212

1313
#include <verilog/sva_expr.h>
1414

15+
#include "ltl.h"
16+
1517
bool is_temporal_operator(const exprt &expr)
1618
{
1719
return is_CTL_operator(expr) || is_LTL_operator(expr) ||
@@ -152,3 +154,78 @@ bool is_SVA_always_s_eventually_p(const exprt &expr)
152154
!has_temporal_operator(
153155
to_sva_s_eventually_expr(to_sva_always_expr(expr).op()).op());
154156
}
157+
158+
std::optional<exprt> SVA_to_LTL(const exprt &expr)
159+
{
160+
// Some SVA is directly mappable to LTL
161+
if(expr.id() == ID_sva_always)
162+
{
163+
auto rec = SVA_to_LTL(to_sva_always_expr(expr).op());
164+
if(rec.has_value())
165+
return G_exprt{rec.value()};
166+
else
167+
return {};
168+
}
169+
else if(expr.id() == ID_sva_s_eventually)
170+
{
171+
auto rec = SVA_to_LTL(to_sva_s_eventually_expr(expr).op());
172+
if(rec.has_value())
173+
return F_exprt{rec.value()};
174+
else
175+
return {};
176+
}
177+
else if(expr.id() == ID_sva_s_nexttime)
178+
{
179+
auto rec = SVA_to_LTL(to_sva_s_nexttime_expr(expr).op());
180+
if(rec.has_value())
181+
return X_exprt{rec.value()};
182+
else
183+
return {};
184+
}
185+
else if(expr.id() == ID_sva_nexttime)
186+
{
187+
auto rec = SVA_to_LTL(to_sva_nexttime_expr(expr).op());
188+
if(rec.has_value())
189+
return X_exprt{rec.value()};
190+
else
191+
return {};
192+
}
193+
else if(expr.id() == ID_sva_overlapped_implication)
194+
{
195+
auto &implication = to_sva_overlapped_implication_expr(expr);
196+
auto rec_lhs = SVA_to_LTL(implication.lhs());
197+
auto rec_rhs = SVA_to_LTL(implication.rhs());
198+
if(rec_lhs.has_value() && rec_rhs.has_value())
199+
return implies_exprt{rec_lhs.value(), rec_rhs.value()};
200+
else
201+
return {};
202+
}
203+
else if(expr.id() == ID_sva_non_overlapped_implication)
204+
{
205+
auto &implication = to_sva_non_overlapped_implication_expr(expr);
206+
auto rec_lhs = SVA_to_LTL(implication.lhs());
207+
auto rec_rhs = SVA_to_LTL(implication.rhs());
208+
if(rec_lhs.has_value() && rec_rhs.has_value())
209+
return implies_exprt{rec_lhs.value(), X_exprt{rec_rhs.value()}};
210+
else
211+
return {};
212+
}
213+
else if(
214+
expr.id() == ID_and || expr.id() == ID_implies || expr.id() == ID_or ||
215+
expr.id() == ID_not)
216+
{
217+
exprt copy = expr;
218+
for(auto &op : copy.operands())
219+
{
220+
auto rec = SVA_to_LTL(op);
221+
if(!rec.has_value())
222+
return {};
223+
op = rec.value();
224+
}
225+
return copy;
226+
}
227+
else if(!has_temporal_operator(expr))
228+
return expr;
229+
else
230+
return {};
231+
}

Diff for: src/temporal-logic/temporal_logic.h

+4
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,8 @@ bool is_SVA_always_p(const exprt &);
7777
/// Returns true iff the given expression is always s_eventually p
7878
bool is_SVA_always_s_eventually_p(const exprt &);
7979

80+
/// If possible, this maps an SVA expression to an equivalent LTL
81+
/// expression, or otherwise returns {}.
82+
std::optional<exprt> SVA_to_LTL(const exprt &);
83+
8084
#endif

0 commit comments

Comments
 (0)