Skip to content

Commit 43cf02c

Browse files
committed
BMC: completeness thresholds larger than one
1 parent 2d61d66 commit 43cf02c

File tree

3 files changed

+68
-37
lines changed

3 files changed

+68
-37
lines changed

regression/verilog/SVA/sequence_and1.bmc.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ sequence_and1.sv
55
^\[main\.p1\] strong\(main\.x == 0 and main\.x == 1\): REFUTED$
66
^\[main\.p2\] main\.x == 0 and \(nexttime main\.x == 1\): PROVED up to bound \d+$
77
^\[main\.p3\] \(nexttime main\.x == 1\) and main\.x == 0: PROVED up to bound \d+$
8-
^\[main\.p4\] \(main\.x == 0 and main\.x != 10\) |=> main\.x == 1: PROVED up to bound \d+$
8+
^\[main\.p4\] \(main\.x == 0 and main\.x != 10\) |=> main\.x == 1: PROVED$
99
^EXIT=10$
1010
^SIGNAL=0$
1111
--

regression/verilog/SVA/sequence_and2.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
CORE
22
sequence_and2.sv
33

4-
\[.*\] \(1 and \(##2 1\)\) \|-> main\.x == 2: PROVED up to bound 5$
5-
\[.*\] \(\(##2 1\) and 1\) \|-> main\.x == 2: PROVED up to bound 5$
4+
^\[.*\] \(1 and \(##2 1\)\) \|-> main\.x == 2: PROVED up to bound 5$
5+
^\[.*\] \(\(##2 1\) and 1\) \|-> main\.x == 2: PROVED up to bound 5$
66
^EXIT=0$
77
^SIGNAL=0$
88
--

src/ebmc/completeness_threshold.cpp

Lines changed: 65 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,22 @@ Author: Daniel Kroening, [email protected]
1616

1717
#include "bmc.h"
1818

19-
bool has_low_completeness_threshold(const exprt &expr)
19+
// counting number of transitions
20+
std::optional<mp_integer> completeness_threshold(const exprt &expr)
2021
{
2122
if(!has_temporal_operator(expr))
2223
{
23-
return true; // state predicate only
24+
return 0; // state predicate only
2425
}
2526
else if(expr.id() == ID_X)
2627
{
2728
// X p
28-
return !has_temporal_operator(to_X_expr(expr).op());
29+
// Increases the CT by one.
30+
auto ct_p = completeness_threshold(to_X_expr(expr).op());
31+
if(ct_p.has_value())
32+
return *ct_p + 1;
33+
else
34+
return {};
2935
}
3036
else if(
3137
expr.id() == ID_sva_nexttime || expr.id() == ID_sva_s_nexttime ||
@@ -37,69 +43,92 @@ bool has_low_completeness_threshold(const exprt &expr)
3743
else if(expr.id() == ID_sva_ranged_always)
3844
{
3945
auto &always_expr = to_sva_ranged_always_expr(expr);
40-
if(has_temporal_operator(always_expr.op()))
41-
return false;
42-
else if(always_expr.upper().is_constant())
46+
if(always_expr.upper().is_constant())
4347
{
44-
auto lower_int = numeric_cast_v<mp_integer>(always_expr.lower());
4548
auto upper_int =
4649
numeric_cast_v<mp_integer>(to_constant_expr(always_expr.upper()));
47-
return lower_int >= 0 && lower_int <= 1 && upper_int >= 0 &&
48-
upper_int <= 1;
50+
51+
if(upper_int < 0)
52+
return {};
53+
54+
// increases the CT by upper_int
55+
auto ct_op = completeness_threshold(always_expr.op());
56+
if(ct_op.has_value())
57+
return *ct_op + upper_int;
58+
else
59+
return {};
4960
}
5061
else
51-
return false;
62+
return {};
5263
}
5364
else if(expr.id() == ID_sva_s_always)
5465
{
5566
auto &s_always_expr = to_sva_s_always_expr(expr);
56-
if(has_temporal_operator(s_always_expr.op()))
57-
return false;
67+
68+
auto upper_int =
69+
numeric_cast_v<mp_integer>(to_constant_expr(s_always_expr.upper()));
70+
71+
if(upper_int < 0)
72+
return {};
73+
74+
// increases the CT by upper_int
75+
auto ct_op = completeness_threshold(s_always_expr.op());
76+
if(ct_op.has_value())
77+
return *ct_op + upper_int;
5878
else
59-
{
60-
auto lower_int = numeric_cast_v<mp_integer>(s_always_expr.lower());
61-
auto upper_int = numeric_cast_v<mp_integer>(s_always_expr.upper());
62-
return lower_int >= 0 && lower_int <= 1 && upper_int >= 0 &&
63-
upper_int <= 1;
64-
}
79+
return {};
6580
}
6681
else if(
6782
expr.id() == ID_sva_strong || expr.id() == ID_sva_weak ||
6883
expr.id() == ID_sva_implicit_strong || expr.id() == ID_sva_implicit_weak)
6984
{
7085
auto &sequence = to_sva_sequence_property_expr_base(expr).sequence();
71-
return has_low_completeness_threshold(sequence);
86+
return completeness_threshold(sequence);
7287
}
7388
else if(expr.id() == ID_sva_boolean)
7489
{
75-
return true;
90+
return 0; // state predicate only
7691
}
7792
else if(expr.id() == ID_sva_or || expr.id() == ID_sva_and)
7893
{
94+
mp_integer max_ct = 0;
95+
7996
for(auto &op : expr.operands())
80-
if(!has_low_completeness_threshold(op))
81-
return false;
82-
return true;
97+
{
98+
auto ct_op = completeness_threshold(op);
99+
if(ct_op.has_value())
100+
max_ct = std::max(*ct_op, max_ct);
101+
else
102+
return {}; // no CT
103+
}
104+
105+
return max_ct;
83106
}
84107
else if(expr.id() == ID_sva_sequence_property)
85108
{
86109
PRECONDITION(false); // should have been turned into implicit weak/strong
87110
}
88111
else
89-
return false;
112+
return {};
90113
}
91114

92-
bool has_low_completeness_threshold(const ebmc_propertiest::propertyt &property)
115+
std::optional<mp_integer> completeness_threshold(const ebmc_propertiest::propertyt &property)
93116
{
94-
return has_low_completeness_threshold(property.normalized_expr);
117+
return completeness_threshold(property.normalized_expr);
95118
}
96119

97-
bool have_low_completeness_threshold(const ebmc_propertiest &properties)
120+
std::optional<mp_integer> completeness_threshold(const ebmc_propertiest &properties)
98121
{
122+
std::optional<mp_integer> max_ct;
123+
99124
for(auto &property : properties.properties)
100-
if(has_low_completeness_threshold(property))
101-
return true;
102-
return false;
125+
{
126+
auto ct_opt = completeness_threshold(property);
127+
if(ct_opt.has_value())
128+
max_ct = std::max(max_ct.value_or(0), *ct_opt);
129+
}
130+
131+
return max_ct;
103132
}
104133

105134
property_checker_resultt completeness_threshold(
@@ -110,13 +139,15 @@ property_checker_resultt completeness_threshold(
110139
message_handlert &message_handler)
111140
{
112141
// Do we have an eligibile property?
113-
if(!have_low_completeness_threshold(properties))
142+
auto ct_opt = completeness_threshold(properties);
143+
144+
if(!ct_opt.has_value())
114145
return property_checker_resultt{properties}; // give up
115146

116147
// Do BMC with two timeframes
117148
auto result = bmc(
118-
1, // bound
119-
false, // convert_only
149+
numeric_cast_v<std::size_t>(*ct_opt), // bound
150+
false, // convert_only
120151
cmdline.isset("bmc-with-assumptions"),
121152
transition_system,
122153
properties,
@@ -128,7 +159,7 @@ property_checker_resultt completeness_threshold(
128159
if(property.is_proved_with_bound())
129160
{
130161
// Turn "PROVED up to bound k" into "PROVED" if k>=CT
131-
if(has_low_completeness_threshold(property) && property.bound >= 1)
162+
if(completeness_threshold(property).has_value())
132163
property.proved();
133164
else
134165
property.unknown();

0 commit comments

Comments
 (0)