Skip to content

Commit 94e4f4d

Browse files
committed
SVA: default sequence semantics
SVA sequences can have weak or strong semantics. 1800-2017 16.12.2 Sequence property requires that sequences in properties that are not explicitly marked as strong or weak are interpreted as weak when used in assert property or assume property, and strong otherwise. The Verilog type checker now emits corresponding expressions sva_implict_weak and sva_implicit_strong for uses of SVA sequences in properties.
1 parent aac75f1 commit 94e4f4d

File tree

8 files changed

+108
-19
lines changed

8 files changed

+108
-19
lines changed

src/hw_cbmc_irep_ids.h

Lines changed: 2 additions & 0 deletions
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

Lines changed: 4 additions & 2 deletions
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

Lines changed: 24 additions & 4 deletions
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

Lines changed: 13 additions & 4 deletions
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

Lines changed: 18 additions & 9 deletions
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

Lines changed: 12 additions & 0 deletions
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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 32 additions & 0 deletions
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)