Skip to content

Commit eb5072b

Browse files
kroeningtautschnig
authored andcommitted
SVA: sequence property expressions
SVA Sequences can be used as properties, in one of three ways: 1. weak(s) 2. strong(s) 3. s The third form is interpreted as strong when used in a cover statement, and as weak in assert/assume. The SVA not operator flips this around. This adds a new expression, sva_sequence_property_exprt, to denote this conversion.
1 parent cea28dd commit eb5072b

File tree

9 files changed

+94
-16
lines changed

9 files changed

+94
-16
lines changed

regression/verilog/SVA/sequence2.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ CORE
22
sequence2.sv
33
--bound 10 --numbered-trace
44
^\[main\.p0] ##\[0:\$\] main\.x == 10: REFUTED$
5-
^Counterexample with 7 states:$
5+
^Counterexample with \d+ states:$
66
^main\.x@0 = 0$
77
^main\.x@1 = 1$
88
^main\.x@2 = 2$

src/hw_cbmc_irep_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ IREP_ID_ONE(sva_sequence_first_match)
6363
IREP_ID_ONE(sva_sequence_goto_repetition)
6464
IREP_ID_ONE(sva_sequence_intersect)
6565
IREP_ID_ONE(sva_sequence_non_consecutive_repetition)
66+
IREP_ID_ONE(sva_sequence_property)
6667
IREP_ID_ONE(sva_sequence_repetition_star)
6768
IREP_ID_ONE(sva_sequence_repetition_plus)
6869
IREP_ID_ONE(sva_sequence_throughout)

src/temporal-logic/trivial_sva.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,12 @@ exprt trivial_sva(exprt expr)
107107
op = trivial_sva(op);
108108

109109
// post-traversal
110-
if(expr.id() == ID_typecast)
110+
if(expr.id() == ID_sva_sequence_property)
111111
{
112-
// We typecast sequences to bool, and hence can drop
113-
// casts from bool to bool
114-
auto &op = to_typecast_expr(expr).op();
115-
if(expr.type().id() == ID_bool && op.type().id() == ID_bool)
112+
// We simplify sequences to boolean expressions, and hence can drop
113+
// the sva_sequence_property converter
114+
auto &op = to_sva_sequence_property_expr(expr).op();
115+
if(op.type().id() == ID_bool)
116116
return op;
117117
}
118118

src/trans-word-level/instantiate_word_level.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,24 @@ wl_instantiatet::instantiate_rec(exprt expr, const mp_integer &t) const
140140

141141
return {max, disjunction(disjuncts)};
142142
}
143+
else if(expr.id() == ID_sva_sequence_property)
144+
{
145+
// sequence expressions -- these may have multiple potential
146+
// match points, and evaluate to true if any of them matches
147+
auto &sequence = to_sva_sequence_property_expr(expr);
148+
const auto matches = instantiate_sequence(sequence, t, no_timeframes);
149+
exprt::operandst disjuncts;
150+
disjuncts.reserve(matches.size());
151+
mp_integer max = t;
152+
153+
for(auto &match : matches)
154+
{
155+
disjuncts.push_back(match.condition);
156+
max = std::max(max, match.end_time);
157+
}
158+
159+
return {max, disjunction(disjuncts)};
160+
}
143161
else if(expr.id() == ID_verilog_past)
144162
{
145163
auto &verilog_past = to_verilog_past_expr(expr);

src/trans-word-level/property.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,25 @@ static obligationst property_obligations_rec(
507507
std::max(obligations_true.first, obligations_false.first),
508508
if_exprt{cond, obligations_true.second, obligations_false.second}};
509509
}
510+
else if(property_expr.id() == ID_sva_sequence_property)
511+
{
512+
// Sequences can be used as property, and evaluate to true
513+
// when there is at least one match.
514+
auto &sequence = to_sva_sequence_property_expr(property_expr).op();
515+
auto matches = instantiate_sequence(sequence, current, no_timeframes);
516+
517+
exprt::operandst disjuncts;
518+
disjuncts.reserve(matches.size());
519+
mp_integer max = current;
520+
521+
for(auto &match : matches)
522+
{
523+
disjuncts.push_back(match.condition);
524+
max = std::max(max, match.end_time);
525+
}
526+
527+
return obligationst{max, disjunction(disjuncts)};
528+
}
510529
else if(
511530
property_expr.id() == ID_typecast &&
512531
to_typecast_expr(property_expr).op().type().id() == ID_bool)

src/verilog/expr2verilog.cpp

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -530,18 +530,25 @@ expr2verilogt::resultt expr2verilogt::convert_sva_unary(
530530
const std::string &name,
531531
const unary_exprt &src)
532532
{
533-
auto op = convert_rec(src.op());
533+
auto &op = src.op();
534+
535+
std::size_t op_operands = 0;
536+
537+
if(op.id() == ID_typecast)
538+
op_operands = to_typecast_expr(op).op().operands().size();
539+
else if(src.op().id() == ID_sva_sequence_property)
540+
op_operands = to_sva_sequence_property_expr(op).op().operands().size();
541+
else
542+
op_operands = op.operands().size();
534543

535-
auto op_skip_typecast =
536-
src.op().id() == ID_typecast ? to_typecast_expr(src.op()).op() : src.op();
544+
auto op_rec = convert_rec(op);
537545

538-
if(
539-
op.p == verilog_precedencet::MIN && op_skip_typecast.operands().size() >= 2)
546+
if(op_rec.p == verilog_precedencet::MIN && op_operands >= 2)
540547
{
541-
op.s = "(" + op.s + ")";
548+
op_rec.s = "(" + op_rec.s + ")";
542549
}
543550

544-
return {verilog_precedencet::MIN, name + " " + op.s};
551+
return {verilog_precedencet::MIN, name + " " + op_rec.s};
545552
}
546553

547554
/*******************************************************************\
@@ -1808,6 +1815,9 @@ expr2verilogt::resultt expr2verilogt::convert_rec(const exprt &src)
18081815
else if(src.id() == ID_sva_weak)
18091816
return convert_function("weak", src);
18101817

1818+
else if(src.id() == ID_sva_sequence_property)
1819+
return convert_rec(to_sva_sequence_property_expr(src).op());
1820+
18111821
else if(src.id()==ID_sva_sequence_concatenation)
18121822
return convert_sva_sequence_concatenation(
18131823
to_binary_expr(src), precedence = verilog_precedencet::MIN);

src/verilog/sva_expr.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1515,4 +1515,31 @@ to_sva_sequence_first_match_expr(exprt &expr)
15151515
return static_cast<sva_sequence_first_match_exprt &>(expr);
15161516
}
15171517

1518+
/// 1800-2017 16.12.2 Sequence property
1519+
/// Equivalent to weak(...) or strong(...) depending on context.
1520+
class sva_sequence_property_exprt : public unary_predicate_exprt
1521+
{
1522+
public:
1523+
explicit sva_sequence_property_exprt(exprt op)
1524+
: unary_predicate_exprt(ID_sva_sequence_property, std::move(op))
1525+
{
1526+
}
1527+
};
1528+
1529+
static inline const sva_sequence_property_exprt &
1530+
to_sva_sequence_property_expr(const exprt &expr)
1531+
{
1532+
PRECONDITION(expr.id() == ID_sva_sequence_property);
1533+
sva_sequence_property_exprt::check(expr, validation_modet::INVARIANT);
1534+
return static_cast<const sva_sequence_property_exprt &>(expr);
1535+
}
1536+
1537+
static inline sva_sequence_property_exprt &
1538+
to_sva_sequence_property_expr(exprt &expr)
1539+
{
1540+
PRECONDITION(expr.id() == ID_sva_sequence_property);
1541+
sva_sequence_property_exprt::check(expr, validation_modet::INVARIANT);
1542+
return static_cast<sva_sequence_property_exprt &>(expr);
1543+
}
1544+
15181545
#endif

src/verilog/verilog_typecheck.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1785,7 +1785,7 @@ void verilog_typecheckt::convert_property_declaration(
17851785
auto full_identifier = hierarchical_identifier(base_name);
17861786

17871787
convert_sva(declaration.cond());
1788-
make_boolean(declaration.cond());
1788+
require_sva_property(declaration.cond());
17891789

17901790
auto type = bool_typet{};
17911791
type.set(ID_C_verilog_type, ID_verilog_property_declaration);

src/verilog/verilog_typecheck_sva.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,11 @@ void verilog_typecheck_exprt::require_sva_property(exprt &expr)
5252

5353
if(type.id() == ID_verilog_sva_sequence)
5454
{
55-
// cast to boolean
56-
make_boolean(expr);
55+
// 1800 2017 16.12.2 Sequence property
56+
// These yield an implicit weak(...) or strong(...), but we
57+
// only know which one once the sequence is used in an assert/assume
58+
// or cover.
59+
expr = sva_sequence_property_exprt{std::move(expr)};
5760
}
5861
else if(
5962
type.id() == ID_bool || type.id() == ID_unsignedbv ||

0 commit comments

Comments
 (0)