Skip to content

Commit e7e9a69

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 0a1c5ce commit e7e9a69

File tree

6 files changed

+101
-30
lines changed

6 files changed

+101
-30
lines changed

src/hw_cbmc_irep_ids.h

+1
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/normalize_property.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,13 @@ 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+
// 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()}};
3233
}
3334
else
3435
return std::move(expr);

src/trans-word-level/sequence.cpp

+12-3
Original file line numberDiff line numberDiff line change
@@ -411,10 +411,19 @@ sequence_matchest instantiate_sequence(
411411

412412
return result;
413413
}
414-
else
414+
else if(expr.id() == ID_sva_boolean)
415415
{
416-
// not a sequence, evaluate as state predicate
417-
auto instantiated = instantiate_property(expr, t, no_timeframes);
416+
// a state predicate
417+
auto &predicate = to_sva_boolean_expr(expr).op();
418+
auto instantiated = instantiate_property(predicate, t, no_timeframes);
418419
return {{instantiated.first, instantiated.second}};
419420
}
421+
else
422+
{
423+
DATA_CHECK_WITH_DIAGNOSTICS(
424+
validation_modet::INVARIANT,
425+
false,
426+
"unexpected sequence expression",
427+
expr.pretty());
428+
}
420429
}

src/verilog/expr2verilog.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -1810,6 +1810,12 @@ expr2verilogt::resultt expr2verilogt::convert_rec(const exprt &src)
18101810
return convert_rec(to_sva_sequence_property_expr_base(src).sequence());
18111811
}
18121812

1813+
else if(src.id() == ID_sva_boolean)
1814+
{
1815+
// These are invisible
1816+
return convert_rec(to_sva_boolean_expr(src).op());
1817+
}
1818+
18131819
else if(src.id()==ID_sva_sequence_concatenation)
18141820
return convert_sva_sequence_concatenation(
18151821
to_binary_expr(src), precedence = verilog_precedencet::MIN);

src/verilog/sva_expr.h

+23
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

+55-24
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
@@ -86,10 +87,8 @@ exprt verilog_typecheck_exprt::convert_unary_sva(unary_exprt expr)
8687
return std::move(expr);
8788
}
8889
else if(
89-
expr.id() == ID_sva_cycle_delay_plus || // ##[+]
90-
expr.id() == ID_sva_cycle_delay_star || // ##[*]
91-
expr.id() == ID_sva_sequence_repetition_plus || // x[+]
92-
expr.id() == ID_sva_sequence_repetition_star) // x[*}
90+
expr.id() == ID_sva_cycle_delay_plus || // ##[+]
91+
expr.id() == ID_sva_cycle_delay_star) // ##[*]
9392
{
9493
// These take a sequence as argument.
9594
// For some, the grammar allows properties to implement and/or over
@@ -99,6 +98,16 @@ exprt verilog_typecheck_exprt::convert_unary_sva(unary_exprt expr)
9998
expr.type() = verilog_sva_sequence_typet{};
10099
return std::move(expr);
101100
}
101+
else if(
102+
expr.id() == ID_sva_sequence_repetition_plus || // x[+]
103+
expr.id() == ID_sva_sequence_repetition_star) // x[*]
104+
{
105+
// These take a Boolean as argument, and yield a sequence.
106+
convert_expr(expr.op());
107+
make_boolean(expr.op());
108+
expr.type() = verilog_sva_sequence_typet{};
109+
return std::move(expr);
110+
}
102111
else if(expr.id() == ID_sva_weak || expr.id() == ID_sva_strong)
103112
{
104113
convert_sva(expr.op());
@@ -109,7 +118,11 @@ exprt verilog_typecheck_exprt::convert_unary_sva(unary_exprt expr)
109118
else
110119
{
111120
// not SVA
112-
return convert_expr_rec(std::move(expr));
121+
DATA_CHECK_WITH_DIAGNOSTICS(
122+
validation_modet::INVARIANT,
123+
false,
124+
"unexpected unary SVA expression",
125+
expr.pretty());
113126
}
114127
}
115128

@@ -123,14 +136,12 @@ exprt verilog_typecheck_exprt::convert_binary_sva(binary_exprt expr)
123136
// These yield sequences when both operands are sequences, and
124137
// properties otherwise.
125138
if(
126-
(expr.lhs().type().id() == ID_verilog_sva_sequence ||
127-
!has_temporal_operator(expr.lhs())) &&
128-
(expr.rhs().type().id() == ID_verilog_sva_sequence ||
129-
!has_temporal_operator(expr.rhs())))
139+
expr.lhs().type().id() == ID_verilog_sva_sequence &&
140+
expr.rhs().type().id() == ID_verilog_sva_sequence)
130141
{
131-
expr.type() = verilog_sva_sequence_typet{};
132142
require_sva_sequence(expr.lhs());
133143
require_sva_sequence(expr.rhs());
144+
expr.type() = verilog_sva_sequence_typet{};
134145
}
135146
else
136147
{
@@ -294,8 +305,12 @@ exprt verilog_typecheck_exprt::convert_binary_sva(binary_exprt expr)
294305
}
295306
else
296307
{
297-
// not SVA
298-
return convert_expr_rec(std::move(expr));
308+
// unexpected SVA expression
309+
DATA_CHECK_WITH_DIAGNOSTICS(
310+
validation_modet::INVARIANT,
311+
false,
312+
"unexpected binary SVA expression",
313+
expr.pretty());
299314
}
300315
}
301316

@@ -409,22 +424,38 @@ exprt verilog_typecheck_exprt::convert_ternary_sva(ternary_exprt expr)
409424
else
410425
{
411426
// not SVA
412-
return convert_expr_rec(std::move(expr));
427+
DATA_CHECK_WITH_DIAGNOSTICS(
428+
validation_modet::INVARIANT,
429+
false,
430+
"unexpected ternary SVA expression",
431+
expr.pretty());
413432
}
414433
}
415434

416435
exprt verilog_typecheck_exprt::convert_sva_rec(exprt expr)
417436
{
418-
switch(expr.operands().size())
419-
{
420-
case 1:
421-
return convert_unary_sva(to_unary_expr(expr));
422-
case 2:
423-
return convert_binary_sva(to_binary_expr(expr));
424-
case 3:
425-
return convert_ternary_sva(to_ternary_expr(expr));
426-
default:
427-
return convert_expr_rec(expr);
437+
if(is_SVA_operator(expr))
438+
{
439+
switch(expr.operands().size())
440+
{
441+
case 1:
442+
return convert_unary_sva(to_unary_expr(expr));
443+
case 2:
444+
return convert_binary_sva(to_binary_expr(expr));
445+
case 3:
446+
return convert_ternary_sva(to_ternary_expr(expr));
447+
default:
448+
DATA_CHECK_WITH_DIAGNOSTICS(
449+
validation_modet::INVARIANT,
450+
false,
451+
"unexpected SVA expression",
452+
expr.pretty());
453+
}
454+
}
455+
else
456+
{
457+
// not SVA, but an expression that gets sampled.
458+
return convert_expr_rec(std::move(expr));
428459
}
429460
}
430461

0 commit comments

Comments
 (0)