Skip to content

Commit 28c0ba6

Browse files
committed
introduce sva_boolean_exprt
IEEE 1800-2017 16.6 Boolean expressions introduces rules on how to convert Boolean expressions into SVA sequences or properties. This introduces an expression for this conversion.
1 parent 9b402aa commit 28c0ba6

File tree

10 files changed

+99
-14
lines changed

10 files changed

+99
-14
lines changed

regression/verilog/SVA/sva_and1.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
sva_and1.sv
33

4-
^\[main\.p0\] always \(1 and 1\): PROVED$
4+
^\[main\.p0\] always \(1 and 1\): PROVED up to bound 5$
55
^\[main\.p1\] always \(1 and 0\): REFUTED$
66
^\[main\.p2\] always \(1 and 32'b0000000000000000000000000000000x\): REFUTED$
77
^EXIT=10$

src/ebmc/completeness_threshold.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,18 @@ bool has_low_completeness_threshold(const exprt &expr)
6868
expr.id() == ID_sva_implicit_strong || expr.id() == ID_sva_implicit_weak)
6969
{
7070
auto &sequence = to_sva_sequence_property_expr_base(expr).sequence();
71-
if(!is_SVA_sequence_operator(sequence))
72-
return true;
73-
else
74-
return false;
71+
return has_low_completeness_threshold(sequence);
72+
}
73+
else if(expr.id() == ID_sva_boolean)
74+
{
75+
return true;
76+
}
77+
else if(expr.id() == ID_sva_or || expr.id() == ID_sva_and)
78+
{
79+
for(auto &op : expr.operands())
80+
if(!has_low_completeness_threshold(op))
81+
return false;
82+
return true;
7583
}
7684
else if(expr.id() == ID_sva_sequence_property)
7785
{

src/hw_cbmc_irep_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ IREP_ID_ONE(smv_EBG)
4545
IREP_ID_ONE(smv_ABG)
4646
IREP_ID_ONE(smv_ABU)
4747
IREP_ID_ONE(smv_EBU)
48+
IREP_ID_ONE(sva_boolean)
4849
IREP_ID_ONE(sva_accept_on)
4950
IREP_ID_ONE(sva_reject_on)
5051
IREP_ID_ONE(sva_sync_accept_on)

src/temporal-logic/nnf.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,24 @@ std::optional<exprt> negate_property_node(const exprt &expr)
149149
return sva_non_overlapped_implication_exprt{
150150
followed_by.antecedent(), not_b};
151151
}
152+
else if(expr.id() == ID_sva_overlapped_implication)
153+
{
154+
// 1800 2017 16.12.9
155+
// !(a |-> b) ---> a #-# !b
156+
auto &implication = to_sva_implication_base_expr(expr);
157+
auto not_b = not_exprt{implication.consequent()};
158+
return sva_followed_by_exprt{
159+
implication.antecedent(), ID_sva_overlapped_followed_by, not_b};
160+
}
161+
else if(expr.id() == ID_sva_non_overlapped_implication)
162+
{
163+
// 1800 2017 16.12.9
164+
// !(a |=> b) ---> a #=# !b
165+
auto &implication = to_sva_implication_base_expr(expr);
166+
auto not_b = not_exprt{implication.consequent()};
167+
return sva_followed_by_exprt{
168+
implication.antecedent(), ID_sva_nonoverlapped_followed_by, not_b};
169+
}
152170
else
153171
return {};
154172
}

src/temporal-logic/normalize_property.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,26 @@ Author: Daniel Kroening, [email protected]
2323
exprt normalize_pre_sva_non_overlapped_implication(
2424
sva_non_overlapped_implication_exprt expr)
2525
{
26-
// Same as a->always[1:1] b if lhs is not a sequence.
27-
if(!is_SVA_sequence_operator(expr.lhs()))
26+
// a|=>b is the same as a->always[1:1] b if lhs is not a proper sequence.
27+
if(expr.lhs().id() == ID_sva_boolean)
2828
{
29+
const auto &lhs_cond = to_sva_boolean_expr(expr.lhs()).op();
2930
auto one = natural_typet{}.one_expr();
3031
return or_exprt{
31-
not_exprt{expr.lhs()}, sva_ranged_always_exprt{one, one, expr.rhs()}};
32+
not_exprt{lhs_cond}, sva_ranged_always_exprt{one, one, expr.rhs()}};
33+
}
34+
else
35+
return std::move(expr);
36+
}
37+
38+
exprt normalize_pre_sva_overlapped_implication(
39+
sva_overlapped_implication_exprt expr)
40+
{
41+
// a|->b is the same as a->b if lhs is not a proper sequence.
42+
if(expr.lhs().id() == ID_sva_boolean)
43+
{
44+
const auto &lhs_cond = to_sva_boolean_expr(expr.lhs()).op();
45+
return implies_exprt{lhs_cond, expr.rhs()};
3246
}
3347
else
3448
return std::move(expr);
@@ -42,6 +56,11 @@ exprt normalize_property_rec(exprt expr)
4256
expr = normalize_pre_sva_non_overlapped_implication(
4357
to_sva_non_overlapped_implication_expr(expr));
4458
}
59+
else if(expr.id() == ID_sva_overlapped_implication)
60+
{
61+
expr = normalize_pre_sva_overlapped_implication(
62+
to_sva_overlapped_implication_expr(expr));
63+
}
4564
else if(expr.id() == ID_sva_nexttime)
4665
{
4766
auto one = natural_typet{}.one_expr();

src/temporal-logic/sva_to_ltl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ struct ltl_sequence_matcht
4242

4343
std::vector<ltl_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
4444
{
45-
if(!is_SVA_sequence_operator(sequence))
45+
if(sequence.id() == ID_sva_boolean)
4646
{
4747
// atomic proposition
48-
return {{sequence, 1}};
48+
return {{to_sva_boolean_expr(sequence).op(), 1}};
4949
}
5050
else if(sequence.id() == ID_sva_sequence_concatenation)
5151
{

src/trans-word-level/sequence.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -454,10 +454,19 @@ sequence_matchest instantiate_sequence(
454454

455455
return result;
456456
}
457-
else
457+
else if(expr.id() == ID_sva_boolean)
458458
{
459-
// not a sequence, evaluate as state predicate
460-
auto instantiated = instantiate_property(expr, t, no_timeframes);
459+
// a state predicate
460+
auto &predicate = to_sva_boolean_expr(expr).op();
461+
auto instantiated = instantiate_property(predicate, t, no_timeframes);
461462
return {{instantiated.first, instantiated.second}};
462463
}
464+
else
465+
{
466+
DATA_CHECK_WITH_DIAGNOSTICS(
467+
validation_modet::INVARIANT,
468+
false,
469+
"unexpected sequence expression",
470+
expr.pretty());
471+
}
463472
}

src/verilog/expr2verilog.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1815,6 +1815,12 @@ expr2verilogt::resultt expr2verilogt::convert_rec(const exprt &src)
18151815
return convert_rec(to_sva_sequence_property_expr_base(src).sequence());
18161816
}
18171817

1818+
else if(src.id() == ID_sva_boolean)
1819+
{
1820+
// These are invisible
1821+
return convert_rec(to_sva_boolean_expr(src).op());
1822+
}
1823+
18181824
else if(src.id()==ID_sva_sequence_concatenation)
18191825
return convert_sva_sequence_concatenation(
18201826
to_binary_expr(src), precedence = verilog_precedencet::MIN);

src/verilog/sva_expr.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,29 @@ Author: Daniel Kroening, [email protected]
1313

1414
#include "verilog_types.h"
1515

16+
/// 1800-2017 16.6 Boolean expressions
17+
/// Conversion of a Boolean expression into a sequence or property
18+
class sva_boolean_exprt : public unary_exprt
19+
{
20+
public:
21+
sva_boolean_exprt(exprt condition, typet __type)
22+
: unary_exprt(ID_sva_boolean, std::move(condition), std::move(__type))
23+
{
24+
}
25+
};
26+
27+
static inline const sva_boolean_exprt &to_sva_boolean_expr(const exprt &expr)
28+
{
29+
sva_boolean_exprt::check(expr, validation_modet::INVARIANT);
30+
return static_cast<const sva_boolean_exprt &>(expr);
31+
}
32+
33+
static inline sva_boolean_exprt &to_sva_boolean_expr(exprt &expr)
34+
{
35+
sva_boolean_exprt::check(expr, validation_modet::INVARIANT);
36+
return static_cast<sva_boolean_exprt &>(expr);
37+
}
38+
1639
/// accept_on, reject_on, sync_accept_on, sync_reject_on, disable_iff
1740
class sva_abort_exprt : public binary_predicate_exprt
1841
{

src/verilog/verilog_typecheck_sva.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ void verilog_typecheck_exprt::require_sva_sequence(exprt &expr)
3535
}
3636
else
3737
{
38-
// state formula, can cast to sequence
38+
// state formula, can convert to sequence
3939
make_boolean(expr);
40+
expr = sva_boolean_exprt{std::move(expr), verilog_sva_sequence_typet{}};
4041
}
4142
}
4243
else

0 commit comments

Comments
 (0)