Skip to content

Commit 93e7d44

Browse files
authored
Merge pull request #1028 from diffblue/sequence_first_match2
SVA: `first_match`
2 parents 8aa6385 + a01f331 commit 93e7d44

File tree

11 files changed

+158
-12
lines changed

11 files changed

+158
-12
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* SystemVerilog: typedefs from package scopes
44
* SystemVerilog: assignment patterns with keys for structs
55
* SystemVerilog: unbased unsigned literals '0, '1, 'x, 'z
6+
* SystemVerilog: first_match
67
* Verilog: 'dx, 'dz
78
* SMV: LTL V operator, xnor operator
89
* SMV: word types and operators

regression/verilog/SVA/sequence_first_match1.desc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
CORE
22
sequence_first_match1.sv
33
--bound 5
4-
^\[.*\] first_match\(main\.x == 0\): FAILURE: property not supported by BMC engine$
5-
^EXIT=10$
4+
^\[.*\] first_match\(main\.x == 0\): PROVED up to bound 5$
5+
^\[.*\] first_match\(main\.x == 0, main\.x\+\+\): PROVED up to bound 5$
6+
^EXIT=0$
67
^SIGNAL=0$
78
--
89
^warning: ignoring
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
sequence_first_match2.sv
3+
--bound 5
4+
^\[.*\] \(##1 1\) or \(\(##2 1\) \|-> main.x == 1\): PROVED up to bound 5$
5+
^\[.*\] first_match\(\(##1 1\) or \(##2 1\)\) \|-> main\.x == 1: PROVED up to bound 5$
6+
^\[.*\] 1 or \(\(##1 1\) \|-> main\.x == 0\): PROVED up to bound 5$
7+
^\[.*\] first_match\(1 or \(##1 1\)\) \|-> main\.x == 0: PROVED up to bound 5$
8+
^EXIT=0$
9+
^SIGNAL=0$
10+
--
11+
^warning: ignoring
12+
--
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module main(input clk);
2+
3+
reg [31:0] x = 0;
4+
5+
always @(posedge clk)
6+
x<=x+1;
7+
8+
// Starting from a particular state,
9+
// first_match yields the sequence that _ends_ first.
10+
11+
// fails
12+
initial p0: assert property ((##1 1) or (##2 1) |-> x==1);
13+
14+
// passes
15+
initial p1: assert property (first_match((##1 1) or (##2 1)) |-> x==1);
16+
17+
// fails
18+
initial p2: assert property (1 or ##1 1 |-> x==0);
19+
20+
// passes
21+
initial p3: assert property (first_match(1 or ##1 1) |-> x==0);
22+
23+
endmodule

src/trans-word-level/property.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,6 @@ Function: bmc_supports_SVA_property
111111

112112
bool bmc_supports_SVA_property(const exprt &expr)
113113
{
114-
// sva_sequence_first_match is not supported yet
115-
if(has_subexpr(expr, ID_sva_sequence_first_match))
116-
return false;
117-
118114
// sva_sequence_within is not supported yet
119115
if(has_subexpr(expr, ID_sva_sequence_within))
120116
return false;

src/trans-word-level/sequence.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,36 @@ std::vector<std::pair<mp_integer, exprt>> instantiate_sequence(
158158
}
159159
else if(expr.id() == ID_sva_sequence_first_match)
160160
{
161-
PRECONDITION(false);
161+
auto &first_match = to_sva_sequence_first_match_expr(expr);
162+
163+
const auto lhs_match_points =
164+
instantiate_sequence(first_match.lhs(), t, no_timeframes);
165+
166+
// the match of seq with the earliest ending clock tick is a
167+
// match of first_match (seq)
168+
std::optional<mp_integer> earliest;
169+
170+
for(auto &match : lhs_match_points)
171+
{
172+
if(!earliest.has_value() || earliest.value() > match.first)
173+
earliest = match.first;
174+
}
175+
176+
if(!earliest.has_value())
177+
return {}; // no match
178+
179+
std::vector<std::pair<mp_integer, exprt>> result;
180+
181+
for(auto &match : lhs_match_points)
182+
{
183+
// Earliest?
184+
if(match.first == earliest.value())
185+
{
186+
result.push_back(match);
187+
}
188+
}
189+
190+
return result;
162191
}
163192
else if(expr.id() == ID_sva_sequence_throughout)
164193
{

src/verilog/expr2verilog.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,36 @@ expr2verilogt::resultt expr2verilogt::convert_sva_sequence_concatenation(
215215

216216
/*******************************************************************\
217217
218+
Function: expr2verilogt::convert_sva_sequence_first_match
219+
220+
Inputs:
221+
222+
Outputs:
223+
224+
Purpose:
225+
226+
\*******************************************************************/
227+
228+
expr2verilogt::resultt expr2verilogt::convert_sva_sequence_first_match(
229+
const sva_sequence_first_match_exprt &src)
230+
{
231+
std::string dest = "first_match(";
232+
233+
dest += convert_rec(src.lhs()).s;
234+
235+
if(src.rhs().is_not_nil())
236+
{
237+
dest += ", ";
238+
dest += convert_rec(src.rhs()).s;
239+
}
240+
241+
dest += ')';
242+
243+
return {verilog_precedencet::MAX, dest};
244+
}
245+
246+
/*******************************************************************\
247+
218248
Function: expr2verilogt::convert_binary
219249
220250
Inputs:
@@ -1782,7 +1812,8 @@ expr2verilogt::resultt expr2verilogt::convert_rec(const exprt &src)
17821812
// not sure about precedence
17831813

17841814
else if(src.id() == ID_sva_sequence_first_match)
1785-
return convert_function("first_match", src);
1815+
return convert_sva_sequence_first_match(
1816+
to_sva_sequence_first_match_expr(src));
17861817

17871818
else if(src.id() == ID_sva_sequence_intersect)
17881819
return precedence = verilog_precedencet::MIN,
@@ -1956,6 +1987,9 @@ expr2verilogt::resultt expr2verilogt::convert_rec(const exprt &src)
19561987
else if(src.id() == ID_verilog_value_range)
19571988
return convert_value_range(to_verilog_value_range_expr(src));
19581989

1990+
else if(src.id() == ID_postincrement)
1991+
return convert_sva_unary(to_unary_expr(src), "++");
1992+
19591993
else if(
19601994
src.id() == ID_nand || src.id() == ID_nor || src.id() == ID_xnor ||
19611995
src.id() == ID_xor)

src/verilog/expr2verilog_class.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class sva_case_exprt;
1717
class sva_if_exprt;
1818
class sva_ranged_predicate_exprt;
1919
class sva_sequence_consecutive_repetition_exprt;
20+
class sva_sequence_first_match_exprt;
2021

2122
// Precedences (higher means binds more strongly).
2223
// Follows Table 11-2 in IEEE 1800-2017.
@@ -160,6 +161,9 @@ class expr2verilogt
160161
resultt
161162
convert_sva_sequence_concatenation(const binary_exprt &, verilog_precedencet);
162163

164+
resultt
165+
convert_sva_sequence_first_match(const sva_sequence_first_match_exprt &);
166+
163167
resultt convert_function_call(const class function_call_exprt &);
164168

165169
resultt convert_non_indexed_part_select(

src/verilog/parser.y

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2621,7 +2621,7 @@ sequence_expr_proper:
26212621
| sequence_expr "or" sequence_expr
26222622
{ init($$, ID_sva_or); mto($$, $1); mto($$, $3); }
26232623
| "first_match" '(' sequence_expr ')'
2624-
{ init($$, ID_sva_sequence_first_match); mto($$, $3); }
2624+
{ init($$, ID_sva_sequence_first_match); mto($$, $3); stack_expr($$).add_to_operands(nil_exprt{}); }
26252625
| "first_match" '(' sequence_expr ',' sequence_match_item_brace ')'
26262626
{ init($$, ID_sva_sequence_first_match); mto($$, $3); mto($$, $5); }
26272627
| expression_or_dist "throughout" sequence_expr

src/verilog/sva_expr.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,4 +1332,38 @@ to_sva_sequence_throughout_expr(exprt &expr)
13321332
return static_cast<sva_sequence_throughout_exprt &>(expr);
13331333
}
13341334

1335+
class sva_sequence_first_match_exprt : public binary_exprt
1336+
{
1337+
public:
1338+
// the second operand is optional
1339+
explicit sva_sequence_first_match_exprt(exprt op)
1340+
: binary_exprt(std::move(op), ID_sva_sequence_first_match, nil_exprt{})
1341+
{
1342+
}
1343+
1344+
sva_sequence_first_match_exprt(exprt op, exprt action)
1345+
: binary_exprt(
1346+
std::move(op),
1347+
ID_sva_sequence_first_match,
1348+
std::move(action))
1349+
{
1350+
}
1351+
};
1352+
1353+
static inline const sva_sequence_first_match_exprt &
1354+
to_sva_sequence_first_match_expr(const exprt &expr)
1355+
{
1356+
PRECONDITION(expr.id() == ID_sva_sequence_first_match);
1357+
sva_sequence_first_match_exprt::check(expr, validation_modet::INVARIANT);
1358+
return static_cast<const sva_sequence_first_match_exprt &>(expr);
1359+
}
1360+
1361+
static inline sva_sequence_first_match_exprt &
1362+
to_sva_sequence_first_match_expr(exprt &expr)
1363+
{
1364+
PRECONDITION(expr.id() == ID_sva_sequence_first_match);
1365+
sva_sequence_first_match_exprt::check(expr, validation_modet::INVARIANT);
1366+
return static_cast<sva_sequence_first_match_exprt &>(expr);
1367+
}
1368+
13351369
#endif

0 commit comments

Comments
 (0)