Skip to content

Commit 1f8f975

Browse files
committed
word-level BMC: allow SVA and/or/implies at property level
1 parent aeecd2e commit 1f8f975

File tree

6 files changed

+94
-6
lines changed

6 files changed

+94
-6
lines changed

regression/verilog/SVA/sva_iff2.desc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
sva_iff2.sv
3+
--bound 10
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
--

regression/verilog/SVA/sva_iff2.sv

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module main(input a, b);
2+
3+
// p0: assert property ((always a) iff (always a));
4+
p1: assert property ((eventually[0:1] a) iff (eventually[0:1] a));
5+
// p2: assert property ((s_eventually a) iff (s_eventually a));
6+
p3: assert property ((a until b) iff (a until b));
7+
// p4: assert property ((a s_until b) iff (a s_until a));
8+
p5: assert property ((a until_with b) iff (a until_with b));
9+
p6: assert property ((a s_until_with b) iff (a s_until_with a));
10+
11+
endmodule

src/temporal-logic/nnf.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,23 @@ std::optional<exprt> negate_property_node(const exprt &expr)
6868
{
6969
return to_not_expr(expr).op();
7070
}
71+
else if(expr.id() == ID_sva_always)
72+
{
73+
// not always p --> s_eventually not p
74+
return sva_s_eventually_exprt{not_exprt{to_sva_always_expr(expr).op()}};
75+
}
76+
else if(expr.id() == ID_sva_s_eventually)
77+
{
78+
// not s_eventually p --> always not p
79+
return sva_always_exprt{not_exprt{to_sva_s_eventually_expr(expr).op()}};
80+
}
81+
else if(expr.id() == ID_sva_eventually)
82+
{
83+
// not eventually[i:j] p --> s_always[i:j] not p
84+
auto &eventually = to_sva_eventually_expr(expr);
85+
return sva_s_always_exprt{
86+
eventually.lower(), eventually.upper(), not_exprt{eventually.op()}};
87+
}
7188
else if(expr.id() == ID_sva_until)
7289
{
7390
// ¬(φ W ψ) ≡ (¬φ strongR ¬ψ)

src/trans-word-level/property.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,11 @@ static obligationst property_obligations_rec(
519519
return property_obligations_rec(
520520
op_negated_opt.value(), current, no_timeframes);
521521
}
522+
else if(is_SVA_sequence(op))
523+
{
524+
return obligationst{
525+
instantiate_property(property_expr, current, no_timeframes)};
526+
}
522527
else if(is_temporal_operator(op))
523528
{
524529
throw ebmc_errort() << "failed to make NNF for " << op.id();
@@ -530,6 +535,23 @@ static obligationst property_obligations_rec(
530535
instantiate_property(property_expr, current, no_timeframes)};
531536
}
532537
}
538+
else if(property_expr.id() == ID_sva_implies)
539+
{
540+
// We need NNF, hence we go via implies_exprt.
541+
// Note that this is not an SVA sequence operator.
542+
auto &sva_implies_expr = to_sva_implies_expr(property_expr);
543+
auto implies_expr =
544+
implies_exprt{sva_implies_expr.lhs(), sva_implies_expr.rhs()};
545+
return property_obligations_rec(implies_expr, current, no_timeframes);
546+
}
547+
else if(property_expr.id() == ID_sva_iff)
548+
{
549+
// We need NNF, hence we go via equal_exprt.
550+
// Note that this is not an SVA sequence operator.
551+
auto &sva_iff_expr = to_sva_iff_expr(property_expr);
552+
auto equal_expr = equal_exprt{sva_iff_expr.lhs(), sva_iff_expr.rhs()};
553+
return property_obligations_rec(equal_expr, current, no_timeframes);
554+
}
533555
else
534556
{
535557
return obligationst{
@@ -549,6 +571,26 @@ Function: property_obligations
549571
550572
\*******************************************************************/
551573

574+
obligationst property_obligations(
575+
const exprt &property_expr,
576+
const mp_integer &t,
577+
const mp_integer &no_timeframes)
578+
{
579+
return property_obligations_rec(property_expr, t, no_timeframes);
580+
}
581+
582+
/*******************************************************************\
583+
584+
Function: property_obligations
585+
586+
Inputs:
587+
588+
Outputs:
589+
590+
Purpose:
591+
592+
\*******************************************************************/
593+
552594
obligationst property_obligations(
553595
const exprt &property_expr,
554596
const mp_integer &no_timeframes)

src/trans-word-level/property.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,11 @@ symbol_exprt lasso_symbol(const mp_integer &k, const mp_integer &i);
4242
/// Returns true iff the given property requires lasso constraints for BMC.
4343
bool requires_lasso_constraints(const exprt &);
4444

45+
class obligationst;
46+
47+
obligationst property_obligations(
48+
const exprt &,
49+
const mp_integer &t,
50+
const mp_integer &no_timeframes);
51+
4552
#endif

src/trans-word-level/sequence.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ Author: Daniel Kroening, [email protected]
1212

1313
#include <verilog/sva_expr.h>
1414

15-
#include "instantiate_word_level.h"
15+
#include "obligations.h"
16+
#include "property.h"
1617

1718
std::vector<std::pair<mp_integer, exprt>> instantiate_sequence(
1819
exprt expr,
@@ -153,13 +154,14 @@ std::vector<std::pair<mp_integer, exprt>> instantiate_sequence(
153154
// 3. The end time of the composite sequence is
154155
// the end time of the operand sequence that completes last.
155156
// Condition (3) is TBD.
156-
exprt::operandst conjuncts;
157+
obligationst obligations;
157158

158159
for(auto &op : expr.operands())
159-
conjuncts.push_back(instantiate_property(op, t, no_timeframes).second);
160+
{
161+
obligations.add(property_obligations(op, t, no_timeframes));
162+
}
160163

161-
exprt condition = conjunction(conjuncts);
162-
return {{t, condition}};
164+
return {obligations.conjunction()};
163165
}
164166
else if(expr.id() == ID_sva_or)
165167
{
@@ -177,6 +179,7 @@ std::vector<std::pair<mp_integer, exprt>> instantiate_sequence(
177179
else
178180
{
179181
// not a sequence, evaluate as state predicate
180-
return {instantiate_property(expr, t, no_timeframes)};
182+
auto obligations = property_obligations(expr, t, no_timeframes);
183+
return {obligations.conjunction()};
181184
}
182185
}

0 commit comments

Comments
 (0)