Skip to content

introduce verilog_sva_property_typet #1081

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions src/ebmc/completeness_threshold.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,18 @@ bool has_low_completeness_threshold(const exprt &expr)
expr.id() == ID_sva_implicit_strong || expr.id() == ID_sva_implicit_weak)
{
auto &sequence = to_sva_sequence_property_expr_base(expr).sequence();
if(!is_SVA_sequence_operator(sequence))
return true;
else
return false;
return has_low_completeness_threshold(sequence);
}
else if(expr.id() == ID_sva_boolean)
{
return true;
}
else if(expr.id() == ID_sva_or || expr.id() == ID_sva_and)
{
for(auto &op : expr.operands())
if(!has_low_completeness_threshold(op))
return false;
return true;
}
else if(expr.id() == ID_sva_sequence_property)
{
Expand Down
2 changes: 2 additions & 0 deletions src/hw_cbmc_irep_ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ IREP_ID_ONE(smv_EBG)
IREP_ID_ONE(smv_ABG)
IREP_ID_ONE(smv_ABU)
IREP_ID_ONE(smv_EBU)
IREP_ID_ONE(sva_boolean)
IREP_ID_ONE(sva_accept_on)
IREP_ID_ONE(sva_reject_on)
IREP_ID_ONE(sva_sync_accept_on)
Expand Down Expand Up @@ -139,6 +140,7 @@ IREP_ID_ONE(verilog_null)
IREP_ID_ONE(verilog_event)
IREP_ID_ONE(verilog_event_trigger)
IREP_ID_ONE(verilog_string)
IREP_ID_ONE(verilog_sva_property)
IREP_ID_ONE(verilog_sva_sequence)
IREP_ID_ONE(reg)
IREP_ID_ONE(macromodule)
Expand Down
18 changes: 18 additions & 0 deletions src/temporal-logic/nnf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,24 @@ std::optional<exprt> negate_property_node(const exprt &expr)
return sva_non_overlapped_implication_exprt{
followed_by.antecedent(), not_b};
}
else if(expr.id() == ID_sva_overlapped_implication)
{
// 1800 2017 16.12.9
// !(a |-> b) ---> a #-# !b
auto &implication = to_sva_implication_base_expr(expr);
auto not_b = not_exprt{implication.consequent()};
return sva_followed_by_exprt{
implication.antecedent(), ID_sva_overlapped_followed_by, not_b};
}
else if(expr.id() == ID_sva_non_overlapped_implication)
{
// 1800 2017 16.12.9
// !(a |=> b) ---> a #=# !b
auto &implication = to_sva_implication_base_expr(expr);
auto not_b = not_exprt{implication.consequent()};
return sva_followed_by_exprt{
implication.antecedent(), ID_sva_nonoverlapped_followed_by, not_b};
}
else
return {};
}
Expand Down
27 changes: 23 additions & 4 deletions src/temporal-logic/normalize_property.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,26 @@ Author: Daniel Kroening, [email protected]
exprt normalize_pre_sva_non_overlapped_implication(
sva_non_overlapped_implication_exprt expr)
{
// Same as a->always[1:1] b if lhs is not a sequence.
if(!is_SVA_sequence_operator(expr.lhs()))
// a|=>b is the same as a->always[1:1] b if lhs is not a proper sequence.
if(expr.lhs().id() == ID_sva_boolean)
{
const auto &lhs_cond = to_sva_boolean_expr(expr.lhs()).op();
auto one = natural_typet{}.one_expr();
return or_exprt{
not_exprt{expr.lhs()}, sva_ranged_always_exprt{one, one, expr.rhs()}};
not_exprt{lhs_cond}, sva_ranged_always_exprt{one, one, expr.rhs()}};
}
else
return std::move(expr);
}

exprt normalize_pre_sva_overlapped_implication(
sva_overlapped_implication_exprt expr)
{
// a|->b is the same as a->b if lhs is not a proper sequence.
if(expr.lhs().id() == ID_sva_boolean)
{
const auto &lhs_cond = to_sva_boolean_expr(expr.lhs()).op();
return implies_exprt{lhs_cond, expr.rhs()};
}
else
return std::move(expr);
Expand All @@ -42,6 +56,11 @@ exprt normalize_property_rec(exprt expr)
expr = normalize_pre_sva_non_overlapped_implication(
to_sva_non_overlapped_implication_expr(expr));
}
else if(expr.id() == ID_sva_overlapped_implication)
{
expr = normalize_pre_sva_overlapped_implication(
to_sva_overlapped_implication_expr(expr));
}
else if(expr.id() == ID_sva_nexttime)
{
auto one = natural_typet{}.one_expr();
Expand Down Expand Up @@ -86,7 +105,7 @@ exprt normalize_property(exprt expr)
{
// top-level only
if(expr.id() == ID_sva_cover)
expr = sva_always_exprt{not_exprt{to_sva_cover_expr(expr).op()}};
expr = sva_always_exprt{sva_not_exprt{to_sva_cover_expr(expr).op()}};

expr = trivial_sva(expr);

Expand Down
5 changes: 2 additions & 3 deletions src/temporal-logic/normalize_property.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ Author: Daniel Kroening, [email protected]

/// This applies the following rewrites:
///
/// cover(φ) --> G¬φ
///
/// -----Propositional-----
/// ¬(a ∨ b) --> ¬a ∧ ¬b
/// ¬(a ∧ b) --> ¬a ∨ ¬b
/// (a -> b) --> ¬a ∨ b
///
/// -----SVA-----
/// sva_non_overlapped_implication --> ¬a ∨ always[1:1] b if a is not an SVA sequence
/// a|=>b --> ¬a ∨ always[1:1] b if a is not an SVA sequence
/// a|->b --> a⇒b if a is not an SVA sequence
/// sva_nexttime φ --> sva_always[1:1] φ
/// sva_nexttime[i] φ --> sva_always[i:i] φ
/// sva_s_nexttime φ --> sva_always[1:1] φ
Expand Down
4 changes: 2 additions & 2 deletions src/temporal-logic/sva_to_ltl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ struct ltl_sequence_matcht

std::vector<ltl_sequence_matcht> LTL_sequence_matches(const exprt &sequence)
{
if(!is_SVA_sequence_operator(sequence))
if(sequence.id() == ID_sva_boolean)
{
// atomic proposition
return {{sequence, 1}};
return {{to_sva_boolean_expr(sequence).op(), 1}};
}
else if(sequence.id() == ID_sva_sequence_concatenation)
{
Expand Down
61 changes: 38 additions & 23 deletions src/temporal-logic/trivial_sva.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ Author: Daniel Kroening, [email protected]

#include "temporal_logic.h"

static std::optional<exprt> is_state_formula(const exprt &expr)
static std::optional<exprt> is_state_predicate(const exprt &expr)
{
if(expr.id() == ID_typecast && expr.type().id() == ID_verilog_sva_sequence)
return to_typecast_expr(expr).op();
else if(expr.type().id() == ID_bool)
return expr;
if(expr.id() == ID_sva_boolean)
return to_sva_boolean_expr(expr).op();
else
return {};
}
Expand All @@ -30,8 +28,8 @@ exprt trivial_sva(exprt expr)
// Same as regular implication if lhs and rhs are not sequences.
auto &sva_implication = to_sva_overlapped_implication_expr(expr);

auto lhs = is_state_formula(sva_implication.lhs());
auto rhs = is_state_formula(sva_implication.rhs());
auto lhs = is_state_predicate(sva_implication.lhs());
auto rhs = is_state_predicate(sva_implication.rhs());

if(lhs.has_value() && rhs.has_value())
expr = implies_exprt{*lhs, *rhs};
Expand All @@ -50,27 +48,43 @@ exprt trivial_sva(exprt expr)
{
auto &sva_and = to_sva_and_expr(expr);

// Same as a ∧ b if the expression is not a sequence.
auto lhs = is_state_formula(sva_and.lhs());
auto rhs = is_state_formula(sva_and.rhs());

if(lhs.has_value() && rhs.has_value())
expr = and_exprt{*lhs, *rhs};
// can be sequence or property
if(expr.type().id() == ID_verilog_sva_sequence)
{
// Same as a ∧ b if the expression is not a sequence.
auto lhs = is_state_predicate(sva_and.lhs());
auto rhs = is_state_predicate(sva_and.rhs());

if(lhs.has_value() && rhs.has_value())
expr = sva_boolean_exprt{and_exprt{*lhs, *rhs}, expr.type()};
}
else
{
expr = and_exprt{sva_and.lhs(), sva_and.rhs()};
}
}
else if(expr.id() == ID_sva_or)
{
auto &sva_or = to_sva_or_expr(expr);

// Same as a ∨ b if the expression is not a sequence.
auto lhs = is_state_formula(sva_or.lhs());
auto rhs = is_state_formula(sva_or.rhs());

if(lhs.has_value() && rhs.has_value())
expr = or_exprt{*lhs, *rhs};
// can be sequence or property
if(expr.type().id() == ID_verilog_sva_sequence)
{
// Same as a ∨ b if the expression is not a sequence.
auto lhs = is_state_predicate(sva_or.lhs());
auto rhs = is_state_predicate(sva_or.rhs());

if(lhs.has_value() && rhs.has_value())
expr = sva_boolean_exprt{or_exprt{*lhs, *rhs}, expr.type()};
}
else
{
expr = or_exprt{sva_or.lhs(), sva_or.rhs()};
}
}
else if(expr.id() == ID_sva_not)
{
// Same as regular 'not'. These do not apply to sequences.
// Same as boolean 'not'. These do not apply to sequences.
expr = not_exprt{to_sva_not_expr(expr).op()};
}
else if(expr.id() == ID_sva_if)
Expand Down Expand Up @@ -113,9 +127,10 @@ exprt trivial_sva(exprt expr)
{
// We simplify sequences to boolean expressions, and hence can drop
// the sva_sequence_property converter
auto &op = to_sva_sequence_property_expr_base(expr).sequence();
if(op.type().id() == ID_bool)
return op;
auto &sequence = to_sva_sequence_property_expr_base(expr).sequence();
auto pred_opt = is_state_predicate(sequence);
if(pred_opt.has_value())
return *pred_opt;
}

return expr;
Expand Down
9 changes: 5 additions & 4 deletions src/trans-word-level/property.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -537,10 +537,10 @@ static obligationst property_obligations_rec(
return property_obligations_rec(
to_typecast_expr(property_expr).op(), current, no_timeframes);
}
else if(property_expr.id() == ID_not)
else if(property_expr.id() == ID_sva_not)
{
// We need NNF, try to eliminate the negation.
auto &op = to_not_expr(property_expr).op();
auto &op = to_sva_not_expr(property_expr).op();

auto op_negated_opt = negate_property_node(op);

Expand Down Expand Up @@ -576,8 +576,9 @@ static obligationst property_obligations_rec(
else
{
// state formula
return obligationst{
instantiate_property(property_expr, current, no_timeframes)};
auto sampled =
instantiate_property(not_exprt{op}, current, no_timeframes);
return obligationst{sampled};
}
}
else if(property_expr.id() == ID_sva_implies)
Expand Down
12 changes: 9 additions & 3 deletions src/trans-word-level/sequence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,10 +454,16 @@ sequence_matchest instantiate_sequence(

return result;
}
else
else if(expr.id() == ID_sva_boolean)
{
// not a sequence, evaluate as state predicate
auto instantiated = instantiate_property(expr, t, no_timeframes);
// a state predicate
auto &predicate = to_sva_boolean_expr(expr).op();
auto instantiated = instantiate_property(predicate, t, no_timeframes);
return {{instantiated.first, instantiated.second}};
}
else
{
DATA_INVARIANT_WITH_DIAGNOSTICS(
false, "unexpected sequence expression", expr.pretty());
}
}
6 changes: 6 additions & 0 deletions src/verilog/expr2verilog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1815,6 +1815,12 @@ expr2verilogt::resultt expr2verilogt::convert_rec(const exprt &src)
return convert_rec(to_sva_sequence_property_expr_base(src).sequence());
}

else if(src.id() == ID_sva_boolean)
{
// These are invisible
return convert_rec(to_sva_boolean_expr(src).op());
}

else if(src.id()==ID_sva_sequence_concatenation)
return convert_sva_sequence_concatenation(
to_binary_expr(src), precedence = verilog_precedencet::MIN);
Expand Down
4 changes: 3 additions & 1 deletion src/verilog/sva_expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ exprt sva_sequence_repetition_star_exprt::lower() const
{
auto n_expr = from_integer(n, integer_typet{});
result = sva_or_exprt{
std::move(result), sva_sequence_repetition_star_exprt{op(), n_expr}};
std::move(result),
sva_sequence_repetition_star_exprt{op(), n_expr},
verilog_sva_sequence_typet{}};
}

return result;
Expand Down
Loading
Loading