Skip to content

Commit f24a826

Browse files
authored
Merge pull request #1071 from diffblue/sva-default-sequence-semantics
SVA: default sequence semantics
2 parents 2e28a03 + 94e4f4d commit f24a826

File tree

8 files changed

+108
-19
lines changed

8 files changed

+108
-19
lines changed

src/hw_cbmc_irep_ids.h

+2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ IREP_ID_ONE(sva_accept_on)
4949
IREP_ID_ONE(sva_reject_on)
5050
IREP_ID_ONE(sva_sync_accept_on)
5151
IREP_ID_ONE(sva_sync_reject_on)
52+
IREP_ID_ONE(sva_implicit_strong)
53+
IREP_ID_ONE(sva_implicit_weak)
5254
IREP_ID_ONE(sva_strong)
5355
IREP_ID_ONE(sva_weak)
5456
IREP_ID_ONE(sva_if)

src/temporal-logic/trivial_sva.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,13 @@ exprt trivial_sva(exprt expr)
107107
op = trivial_sva(op);
108108

109109
// post-traversal
110-
if(expr.id() == ID_sva_sequence_property)
110+
if(
111+
expr.id() == ID_sva_weak || expr.id() == ID_sva_strong ||
112+
expr.id() == ID_sva_implicit_weak || expr.id() == ID_sva_implicit_strong)
111113
{
112114
// We simplify sequences to boolean expressions, and hence can drop
113115
// the sva_sequence_property converter
114-
auto &op = to_sva_sequence_property_expr(expr).sequence();
116+
auto &op = to_sva_sequence_property_expr_base(expr).sequence();
115117
if(op.type().id() == ID_bool)
116118
return op;
117119
}

src/trans-word-level/property.cpp

+24-4
Original file line numberDiff line numberDiff line change
@@ -527,10 +527,24 @@ static obligationst property_obligations_rec(
527527
return property_obligations_rec(
528528
op_negated_opt.value(), current, no_timeframes);
529529
}
530-
else if(is_SVA_sequence_operator(op))
530+
else if(
531+
op.id() == ID_sva_strong || op.id() == ID_sva_weak ||
532+
op.id() == ID_sva_implicit_strong || op.id() == ID_sva_implicit_weak)
531533
{
532-
return obligationst{
533-
instantiate_property(property_expr, current, no_timeframes)};
534+
// The sequence must not match.
535+
auto &sequence = to_sva_sequence_property_expr_base(op).sequence();
536+
537+
const auto matches =
538+
instantiate_sequence(sequence, current, no_timeframes);
539+
540+
obligationst obligations;
541+
542+
for(auto &match : matches)
543+
{
544+
obligations.add(match.end_time, not_exprt{match.condition});
545+
}
546+
547+
return obligations;
534548
}
535549
else if(is_temporal_operator(op))
536550
{
@@ -647,7 +661,8 @@ static obligationst property_obligations_rec(
647661
}
648662
else if(
649663
property_expr.id() == ID_sva_strong || property_expr.id() == ID_sva_weak ||
650-
property_expr.id() == ID_sva_sequence_property)
664+
property_expr.id() == ID_sva_implicit_strong ||
665+
property_expr.id() == ID_sva_implicit_weak)
651666
{
652667
auto &sequence =
653668
to_sva_sequence_property_expr_base(property_expr).sequence();
@@ -667,6 +682,11 @@ static obligationst property_obligations_rec(
667682

668683
return obligationst{max, disjunction(disjuncts)};
669684
}
685+
else if(property_expr.id() == ID_sva_sequence_property)
686+
{
687+
// Should have been turned into sva_implict_weak or sva_implict_strong in the type checker.
688+
PRECONDITION(false);
689+
}
670690
else
671691
{
672692
return obligationst{

src/verilog/expr2verilog.cpp

+13-4
Original file line numberDiff line numberDiff line change
@@ -536,9 +536,14 @@ expr2verilogt::resultt expr2verilogt::convert_sva_unary(
536536

537537
if(op.id() == ID_typecast)
538538
op_operands = to_typecast_expr(op).op().operands().size();
539-
else if(src.op().id() == ID_sva_sequence_property)
539+
else if(
540+
src.op().id() == ID_sva_sequence_property ||
541+
src.op().id() == ID_sva_implicit_weak ||
542+
src.op().id() == ID_sva_implicit_strong)
543+
{
540544
op_operands =
541-
to_sva_sequence_property_expr(op).sequence().operands().size();
545+
to_sva_sequence_property_expr_base(op).sequence().operands().size();
546+
}
542547
else
543548
op_operands = op.operands().size();
544549

@@ -1816,8 +1821,12 @@ expr2verilogt::resultt expr2verilogt::convert_rec(const exprt &src)
18161821
else if(src.id() == ID_sva_weak)
18171822
return convert_function("weak", src);
18181823

1819-
else if(src.id() == ID_sva_sequence_property)
1820-
return convert_rec(to_sva_sequence_property_expr(src).sequence());
1824+
else if(
1825+
src.id() == ID_sva_sequence_property ||
1826+
src.id() == ID_sva_implicit_strong || src.id() == ID_sva_implicit_weak)
1827+
{
1828+
return convert_rec(to_sva_sequence_property_expr_base(src).sequence());
1829+
}
18211830

18221831
else if(src.id()==ID_sva_sequence_concatenation)
18231832
return convert_sva_sequence_concatenation(

src/verilog/sva_expr.h

+18-9
Original file line numberDiff line numberDiff line change
@@ -1143,7 +1143,7 @@ to_sva_sequence_property_expr_base(const exprt &expr)
11431143
}
11441144

11451145
inline sva_sequence_property_expr_baset &
1146-
to_sva_sequence_property_base_expr(exprt &expr)
1146+
to_sva_sequence_property_expr_base(exprt &expr)
11471147
{
11481148
sva_sequence_property_expr_baset::check(expr);
11491149
return static_cast<sva_sequence_property_expr_baset &>(expr);
@@ -1152,45 +1152,47 @@ to_sva_sequence_property_base_expr(exprt &expr)
11521152
class sva_strong_exprt : public sva_sequence_property_expr_baset
11531153
{
11541154
public:
1155-
sva_strong_exprt(exprt __op)
1156-
: sva_sequence_property_expr_baset(ID_sva_strong, std::move(__op))
1155+
sva_strong_exprt(irep_idt __id, exprt __op)
1156+
: sva_sequence_property_expr_baset(__id, std::move(__op))
11571157
{
11581158
}
11591159
};
11601160

11611161
inline const sva_strong_exprt &to_sva_strong_expr(const exprt &expr)
11621162
{
1163-
PRECONDITION(expr.id() == ID_sva_strong);
1163+
PRECONDITION(
1164+
expr.id() == ID_sva_strong || expr.id() == ID_sva_implicit_strong);
11641165
sva_strong_exprt::check(expr);
11651166
return static_cast<const sva_strong_exprt &>(expr);
11661167
}
11671168

11681169
inline sva_strong_exprt &to_sva_strong_expr(exprt &expr)
11691170
{
1170-
PRECONDITION(expr.id() == ID_sva_strong);
1171+
PRECONDITION(
1172+
expr.id() == ID_sva_strong || expr.id() == ID_sva_implicit_strong);
11711173
sva_strong_exprt::check(expr);
11721174
return static_cast<sva_strong_exprt &>(expr);
11731175
}
11741176

11751177
class sva_weak_exprt : public sva_sequence_property_expr_baset
11761178
{
11771179
public:
1178-
sva_weak_exprt(exprt __op)
1179-
: sva_sequence_property_expr_baset(ID_sva_weak, std::move(__op))
1180+
sva_weak_exprt(irep_idt __id, exprt __op)
1181+
: sva_sequence_property_expr_baset(__id, std::move(__op))
11801182
{
11811183
}
11821184
};
11831185

11841186
inline const sva_weak_exprt &to_sva_weak_expr(const exprt &expr)
11851187
{
1186-
PRECONDITION(expr.id() == ID_sva_weak);
1188+
PRECONDITION(expr.id() == ID_sva_weak || expr.id() == ID_sva_implicit_weak);
11871189
sva_weak_exprt::check(expr);
11881190
return static_cast<const sva_weak_exprt &>(expr);
11891191
}
11901192

11911193
inline sva_weak_exprt &to_sva_weak_expr(exprt &expr)
11921194
{
1193-
PRECONDITION(expr.id() == ID_sva_weak);
1195+
PRECONDITION(expr.id() == ID_sva_weak || expr.id() == ID_sva_implicit_weak);
11941196
sva_weak_exprt::check(expr);
11951197
return static_cast<sva_weak_exprt &>(expr);
11961198
}
@@ -1584,4 +1586,11 @@ to_sva_sequence_property_expr(exprt &expr)
15841586
return static_cast<sva_sequence_property_exprt &>(expr);
15851587
}
15861588

1589+
/// SVA sequences can be interpreted as weak or strong
1590+
enum class sva_sequence_semanticst
1591+
{
1592+
WEAK,
1593+
STRONG
1594+
};
1595+
15871596
#endif

src/verilog/verilog_typecheck.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,12 @@ void verilog_typecheckt::convert_assert_assume_cover(
10601060
convert_sva(cond);
10611061
require_sva_property(cond);
10621062

1063+
// 1800-2017 16.12.2 Sequence property
1064+
if(module_item.id() == ID_verilog_cover_property)
1065+
set_default_sequence_semantics(cond, sva_sequence_semanticst::STRONG);
1066+
else
1067+
set_default_sequence_semantics(cond, sva_sequence_semanticst::WEAK);
1068+
10631069
// We create a symbol for the property.
10641070
// The 'value' of the symbol is set by synthesis.
10651071
const irep_idt &identifier = module_item.identifier();
@@ -1125,6 +1131,12 @@ void verilog_typecheckt::convert_assert_assume_cover(
11251131
convert_sva(cond);
11261132
require_sva_property(cond);
11271133

1134+
// 1800-2017 16.12.2 Sequence property
1135+
if(statement.id() == ID_verilog_cover_property)
1136+
set_default_sequence_semantics(cond, sva_sequence_semanticst::STRONG);
1137+
else
1138+
set_default_sequence_semantics(cond, sva_sequence_semanticst::WEAK);
1139+
11281140
// We create a symbol for the property.
11291141
// The 'value' is set by synthesis.
11301142
const irep_idt &identifier = statement.identifier();

src/verilog/verilog_typecheck_expr.h

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Daniel Kroening, [email protected]
1414
#include <util/namespace.h>
1515
#include <util/std_expr.h>
1616

17+
#include "sva_expr.h"
1718
#include "verilog_typecheck_base.h"
1819

1920
#include <stack>
@@ -207,6 +208,8 @@ class verilog_typecheck_exprt:public verilog_typecheck_baset
207208
[[nodiscard]] exprt convert_binary_sva(binary_exprt);
208209
[[nodiscard]] exprt convert_ternary_sva(ternary_exprt);
209210

211+
static void set_default_sequence_semantics(exprt &, sva_sequence_semanticst);
212+
210213
// system functions
211214
exprt bits(const exprt &);
212215
std::optional<mp_integer> bits_rec(const typet &) const;

src/verilog/verilog_typecheck_sva.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -430,3 +430,35 @@ exprt verilog_typecheck_exprt::convert_sva_rec(exprt expr)
430430
return convert_expr_rec(expr);
431431
}
432432
}
433+
434+
// 1800-2017 16.12.2 Sequence property
435+
// Sequences are by default _weak_ when used in assert property
436+
// or assume property, and are _strong_ when used in cover property.
437+
// This flips when below the SVA not operator.
438+
void verilog_typecheck_exprt::set_default_sequence_semantics(
439+
exprt &expr,
440+
sva_sequence_semanticst semantics)
441+
{
442+
if(expr.id() == ID_sva_sequence_property)
443+
{
444+
// apply
445+
if(semantics == sva_sequence_semanticst::WEAK)
446+
expr.id(ID_sva_implicit_weak);
447+
else
448+
expr.id(ID_sva_implicit_strong);
449+
}
450+
else if(expr.id() == ID_sva_not)
451+
{
452+
// flip
453+
semantics = semantics == sva_sequence_semanticst::WEAK
454+
? sva_sequence_semanticst::STRONG
455+
: sva_sequence_semanticst::WEAK;
456+
457+
set_default_sequence_semantics(to_sva_not_expr(expr).op(), semantics);
458+
}
459+
else
460+
{
461+
for(auto &op : expr.operands())
462+
set_default_sequence_semantics(op, semantics);
463+
}
464+
}

0 commit comments

Comments
 (0)