Skip to content

Commit ca996d1

Browse files
committed
introduce verilog_sva_property_typet
This introduces a type for Verilog SVA properties to distinguish properties from state predicates and sequences.
1 parent 3e66d13 commit ca996d1

12 files changed

+313
-90
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
named_property1.sv
3+
4+
^file .* line 12: sequence required, but got property$
5+
^EXIT=2$
6+
^SIGNAL=0$
7+
--
8+
--
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module main(input clk);
2+
3+
wire [31:0] x = 10;
4+
5+
property x_is_ten;
6+
x == 10
7+
endproperty : x_is_ten
8+
9+
// Cannot be used as a sequence, even when it syntactically
10+
// qualifies as a sequence.
11+
sequence some_sequence;
12+
x_is_ten
13+
endsequence
14+
15+
endmodule

src/hw_cbmc_irep_ids.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ IREP_ID_ONE(verilog_null)
147147
IREP_ID_ONE(verilog_event)
148148
IREP_ID_ONE(verilog_event_trigger)
149149
IREP_ID_ONE(verilog_string)
150+
IREP_ID_ONE(verilog_sva_property)
150151
IREP_ID_ONE(verilog_sva_sequence)
151152
IREP_ID_ONE(reg)
152153
IREP_ID_ONE(macromodule)

src/temporal-logic/ltl_sva_to_string.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,8 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
250250
auto &followed_by = to_sva_followed_by_expr(expr);
251251
auto not_b = not_exprt{followed_by.consequent()};
252252
return rec(
253-
not_exprt{
254-
sva_overlapped_implication_exprt{followed_by.antecedent(), not_b}},
253+
not_exprt{sva_overlapped_implication_exprt{
254+
followed_by.antecedent(), not_b, bool_typet{}}},
255255
mode);
256256
}
257257
else if(expr.id() == ID_sva_nonoverlapped_followed_by)
@@ -262,8 +262,8 @@ ltl_sva_to_stringt::rec(const exprt &expr, modet mode)
262262
auto &followed_by = to_sva_followed_by_expr(expr);
263263
auto not_b = not_exprt{followed_by.consequent()};
264264
return rec(
265-
not_exprt{
266-
sva_non_overlapped_implication_exprt{followed_by.antecedent(), not_b}},
265+
not_exprt{sva_non_overlapped_implication_exprt{
266+
followed_by.antecedent(), not_b, bool_typet{}}},
267267
mode);
268268
}
269269
else if(expr.id() == ID_sva_sequence_property)

src/temporal-logic/normalize_property.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ exprt normalize_pre_sva_non_overlapped_implication(
2727
{
2828
const auto &lhs_cond = to_sva_boolean_expr(expr.lhs()).op();
2929
auto one = natural_typet{}.one_expr();
30-
return or_exprt{
31-
not_exprt{lhs_cond}, sva_ranged_always_exprt{one, one, expr.rhs()}};
30+
auto ranged_always = sva_ranged_always_exprt{one, one, expr.rhs()};
31+
ranged_always.type() = bool_typet{};
32+
return or_exprt{not_exprt{lhs_cond}, ranged_always};
3233
}
3334
else
3435
return std::move(expr);
@@ -63,24 +64,32 @@ exprt normalize_property_rec(exprt expr)
6364
else if(expr.id() == ID_sva_nexttime)
6465
{
6566
auto one = natural_typet{}.one_expr();
66-
expr = sva_ranged_always_exprt{one, one, to_sva_nexttime_expr(expr).op()};
67+
expr = sva_ranged_always_exprt{
68+
one, one, to_sva_nexttime_expr(expr).op(), bool_typet{}};
6769
}
6870
else if(expr.id() == ID_sva_s_nexttime)
6971
{
7072
auto one = natural_typet{}.one_expr();
71-
expr = sva_s_always_exprt{one, one, to_sva_s_nexttime_expr(expr).op()};
73+
expr = sva_s_always_exprt{
74+
one, one, to_sva_s_nexttime_expr(expr).op(), bool_typet{}};
7275
}
7376
else if(expr.id() == ID_sva_indexed_nexttime)
7477
{
7578
auto &nexttime_expr = to_sva_indexed_nexttime_expr(expr);
7679
expr = sva_ranged_always_exprt{
77-
nexttime_expr.index(), nexttime_expr.index(), nexttime_expr.op()};
80+
nexttime_expr.index(),
81+
nexttime_expr.index(),
82+
nexttime_expr.op(),
83+
bool_typet{}};
7884
}
7985
else if(expr.id() == ID_sva_indexed_s_nexttime)
8086
{
8187
auto &nexttime_expr = to_sva_indexed_s_nexttime_expr(expr);
8288
expr = sva_s_always_exprt{
83-
nexttime_expr.index(), nexttime_expr.index(), nexttime_expr.op()};
89+
nexttime_expr.index(),
90+
nexttime_expr.index(),
91+
nexttime_expr.op(),
92+
bool_typet{}};
8493
}
8594

8695
// normalize the operands
@@ -104,7 +113,7 @@ exprt normalize_property(exprt expr)
104113
{
105114
// top-level only
106115
if(expr.id() == ID_sva_cover)
107-
expr = sva_always_exprt{not_exprt{to_sva_cover_expr(expr).op()}};
116+
expr = sva_always_exprt{sva_not_exprt{to_sva_cover_expr(expr).op()}};
108117

109118
expr = trivial_sva(expr);
110119

src/temporal-logic/sva_to_ltl.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,38 @@ exprt SVA_to_LTL(exprt expr)
238238
{
239239
return expr;
240240
}
241+
else if(expr.id() == ID_sva_implies)
242+
{
243+
// maps cleanly to 'implies'
244+
auto &sva_implies = to_sva_implies_expr(expr);
245+
auto rec_lhs = SVA_to_LTL(sva_implies.lhs());
246+
auto rec_rhs = SVA_to_LTL(sva_implies.rhs());
247+
return implies_exprt{rec_rhs, rec_lhs};
248+
}
249+
else if(expr.id() == ID_sva_iff)
250+
{
251+
// maps cleanly to =
252+
auto &sva_iff = to_sva_iff_expr(expr);
253+
auto rec_lhs = SVA_to_LTL(sva_iff.lhs());
254+
auto rec_rhs = SVA_to_LTL(sva_iff.rhs());
255+
return equal_exprt{rec_rhs, rec_lhs};
256+
}
257+
else if(expr.id() == ID_sva_and)
258+
{
259+
// maps cleanly to Boolean and
260+
auto &sva_iff = to_sva_iff_expr(expr);
261+
auto rec_lhs = SVA_to_LTL(sva_iff.lhs());
262+
auto rec_rhs = SVA_to_LTL(sva_iff.rhs());
263+
return and_exprt{rec_rhs, rec_lhs};
264+
}
265+
else if(expr.id() == ID_sva_or)
266+
{
267+
// maps cleanly to Boolean or
268+
auto &sva_iff = to_sva_iff_expr(expr);
269+
auto rec_lhs = SVA_to_LTL(sva_iff.lhs());
270+
auto rec_rhs = SVA_to_LTL(sva_iff.rhs());
271+
return or_exprt{rec_rhs, rec_lhs};
272+
}
241273
else if(
242274
expr.id() == ID_and || expr.id() == ID_implies || expr.id() == ID_or ||
243275
expr.id() == ID_not)

src/temporal-logic/trivial_sva.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ static std::optional<exprt> is_state_predicate(const exprt &expr)
2323
exprt trivial_sva(exprt expr)
2424
{
2525
// pre-traversal
26+
if(expr.type().id() == ID_verilog_sva_property)
27+
{
28+
expr.type() = bool_typet{};
29+
}
2630

2731
// rewrite the operands, recursively
2832
for(auto &op : expr.operands())

src/verilog/sva_expr.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ Author: Daniel Kroening, [email protected]
1111
#include <util/arith_tools.h>
1212
#include <util/mathematical_types.h>
1313

14+
exprt sva_iff_exprt::implications() const
15+
{
16+
return sva_and_exprt{
17+
sva_implies_exprt{lhs(), rhs()}, sva_implies_exprt{rhs(), lhs()}, type()};
18+
}
19+
1420
exprt sva_cycle_delay_plus_exprt::lower() const
1521
{
1622
// same as ##[1:$]

0 commit comments

Comments
 (0)