Skip to content

Commit ee8cbfa

Browse files
committed
liveness engine
1 parent bc38997 commit ee8cbfa

File tree

5 files changed

+182
-0
lines changed

5 files changed

+182
-0
lines changed

Diff for: src/ebmc/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ SRC = \
1919
k_induction.cpp \
2020
liveness_to_safety.cpp \
2121
live_signal.cpp \
22+
liveness_engine.cpp \
2223
main.cpp \
2324
netlist.cpp \
2425
neural_liveness.cpp \

Diff for: src/ebmc/ebmc_parse_options.h

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class ebmc_parse_optionst:public parse_options_baset
4040
"(compute-interpolant)(interpolation)(interpolation-vmcai)"
4141
"(ic3)(property):(constr)(h)(new-mode)(aiger)"
4242
"(interpolation-word)(interpolator):(bdd)"
43+
"(liveness)"
4344
"(ranking-function):"
4445
"(smt2)(bitwuzla)(boolector)(cvc3)(cvc4)(cvc5)(mathsat)(yices)(z3)"
4546
"(minisat)(cadical)"

Diff for: src/ebmc/liveness_engine.cpp

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*******************************************************************\
2+
3+
Module: Liveness Engine
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#include "liveness_engine.h"
10+
11+
#include <util/format_expr.h>
12+
13+
#include <temporal-logic/ctl.h>
14+
#include <temporal-logic/ltl.h>
15+
#include <verilog/sva_expr.h>
16+
17+
#include <deque>
18+
#include <unordered_map>
19+
20+
// G F p
21+
class is_live_exprt : public unary_predicate_exprt
22+
{
23+
public:
24+
explicit is_live_exprt(exprt op)
25+
: unary_predicate_exprt{"is_live", std::move(op)}
26+
{
27+
}
28+
};
29+
30+
class liveness_enginet
31+
{
32+
public:
33+
liveness_enginet(
34+
const cmdlinet &_cmdline,
35+
const transition_systemt &_transition_system,
36+
message_handlert &_message_handler)
37+
: cmdline(_cmdline),
38+
transition_system(_transition_system),
39+
message(_message_handler)
40+
{
41+
}
42+
43+
void operator()(const is_live_exprt &);
44+
45+
protected:
46+
const cmdlinet &cmdline;
47+
const transition_systemt &transition_system;
48+
messaget message;
49+
50+
std::unordered_map<is_live_exprt, bool, irep_hash> truth;
51+
52+
std::deque<std::pair<is_live_exprt, bool>> queue;
53+
54+
void enqueue(const is_live_exprt &expr, bool value)
55+
{
56+
message.status() << (value ? "T: " : "F: ");
57+
message.status() << format(expr) << messaget::eom;
58+
queue.emplace_back(expr, value);
59+
}
60+
61+
static is_live_exprt negate_p(const is_live_exprt &expr)
62+
{
63+
if(expr.op().id() == ID_not)
64+
return is_live_exprt{to_not_expr(expr.op()).op()};
65+
else if(expr.op().is_false())
66+
return is_live_exprt{true_exprt{}};
67+
else if(expr.op().is_true())
68+
return is_live_exprt{false_exprt{}};
69+
else
70+
return is_live_exprt{not_exprt{expr.op()}};
71+
}
72+
};
73+
74+
void liveness_enginet::operator()(const is_live_exprt &expr)
75+
{
76+
enqueue(expr, false);
77+
78+
while(!queue.empty())
79+
{
80+
auto entry = queue.front();
81+
queue.pop_front();
82+
83+
auto truth_it = truth.find(entry.first);
84+
if(truth_it != truth.end())
85+
{
86+
if(truth_it->second != entry.second)
87+
{
88+
message.result() << "Contradiction on " << format(expr)
89+
<< messaget::eom;
90+
return;
91+
}
92+
}
93+
else
94+
{
95+
// ¬GFp ⇒ GF¬p
96+
if(!entry.second)
97+
enqueue(negate_p(entry.first), true);
98+
}
99+
}
100+
}
101+
102+
std::optional<is_live_exprt> is_live_expr(const exprt &expr)
103+
{
104+
// G F p
105+
if(
106+
expr.id() == ID_G && to_G_expr(expr).op().id() == ID_F &&
107+
!has_temporal_operator(to_F_expr(to_G_expr(expr).op()).op()))
108+
{
109+
auto p = to_F_expr(to_G_expr(expr).op()).op();
110+
return is_live_exprt{p};
111+
}
112+
113+
// AG AF p
114+
if(
115+
expr.id() == ID_AG && to_AG_expr(expr).op().id() == ID_AF &&
116+
!has_temporal_operator(to_AF_expr(to_AG_expr(expr).op()).op()))
117+
{
118+
auto p = to_AF_expr(to_AG_expr(expr).op()).op();
119+
return is_live_exprt{p};
120+
}
121+
122+
// always s_eventually p
123+
if(
124+
expr.id() == ID_sva_always &&
125+
to_sva_always_expr(expr).op().id() == ID_sva_s_eventually &&
126+
!has_temporal_operator(
127+
to_sva_s_eventually_expr(to_sva_always_expr(expr).op()).op()))
128+
{
129+
// always s_eventually p --> AG AF p
130+
auto p = to_sva_s_eventually_expr(to_sva_always_expr(expr).op()).op();
131+
return is_live_exprt{p};
132+
}
133+
134+
return {};
135+
}
136+
137+
property_checker_resultt liveness_engine(
138+
const cmdlinet &cmdline,
139+
transition_systemt &transition_system,
140+
ebmc_propertiest &properties,
141+
message_handlert &message_handler)
142+
{
143+
for(auto &property : properties.properties)
144+
{
145+
auto is_live_opt = is_live_expr(property.normalized_expr);
146+
if(is_live_opt.has_value())
147+
{
148+
liveness_enginet{cmdline, transition_system, message_handler}(
149+
*is_live_opt);
150+
}
151+
}
152+
153+
return property_checker_resultt{properties};
154+
}

Diff for: src/ebmc/liveness_engine.h

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*******************************************************************\
2+
3+
Module: Liveness Engine
4+
5+
Author: Daniel Kroening, [email protected]
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_EBMC_LIVENESS_ENGINE_H
10+
#define CPROVER_EBMC_LIVENESS_ENGINE_H
11+
12+
#include "property_checker.h"
13+
14+
property_checker_resultt liveness_engine(
15+
const cmdlinet &,
16+
transition_systemt &,
17+
ebmc_propertiest &,
18+
message_handlert &);
19+
20+
#endif

Diff for: src/ebmc/property_checker.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Author: Daniel Kroening, [email protected]
2121
#include "ebmc_solver_factory.h"
2222
#include "ic3_engine.h"
2323
#include "k_induction.h"
24+
#include "liveness_engine.h"
2425
#include "netlist.h"
2526
#include "output_file.h"
2627
#include "report_results.h"
@@ -442,6 +443,11 @@ property_checker_resultt property_checker(
442443
cmdline, transition_system, properties, message_handler);
443444
#endif
444445
}
446+
else if(cmdline.isset("liveness"))
447+
{
448+
return liveness_engine(
449+
cmdline, transition_system, properties, message_handler);
450+
}
445451
else if(cmdline.isset("bound"))
446452
{
447453
// word-level BMC

0 commit comments

Comments
 (0)