Skip to content

Commit f98faf5

Browse files
authored
Merge pull request #1038 from diffblue/nonconsecutive_rep
SVA: `[->n]` and `[=n]`
2 parents 838e27e + a59bb46 commit f98faf5

File tree

6 files changed

+186
-14
lines changed

6 files changed

+186
-14
lines changed

CHANGELOG

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* SystemVerilog: assignment patterns with keys for structs
66
* SystemVerilog: unbased unsigned literals '0, '1, 'x, 'z
77
* SystemVerilog: first_match
8+
* SystemVerilog: [->n] and [=n]
89
* SystemVerilog: bugfix for |-> and |=>
910
* SystemVerilog: bugfix for SVA sequence and
1011
* Verilog: 'dx, 'dz

regression/verilog/SVA/sequence_repetition1.desc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ CORE
22
sequence_repetition1.sv
33
--bound 10
44
^\[.*\] main\.half_x == 0 \[\*2\]: PROVED up to bound 10$
5-
^\[.*\] main\.half_x == 0 \[->2\]: FAILURE: property not supported by BMC engine$
6-
^\[.*\] main\.half_x == 0 \[=2\]: FAILURE: property not supported by BMC engine$
5+
^\[.*\] main\.half_x == 0 \[->2\]: PROVED up to bound 10$
6+
^\[.*\] main\.half_x == 0 \[=2\]: PROVED up to bound 10$
77
^\[.*\] main\.x == 0 \[\*2\]: REFUTED$
8-
^\[.*\] main\.x == 0 \[->2\]: FAILURE: property not supported by BMC engine$
9-
^\[.*\] main\.x == 0 \[=2\]: FAILURE: property not supported by BMC engine$
8+
^\[.*\] main\.x == 0 \[->2\]: REFUTED$
9+
^\[.*\] main\.x == 0 \[=2\]: REFUTED$
1010
^EXIT=10$
1111
^SIGNAL=0$
1212
--

src/trans-word-level/property.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,6 @@ bool bmc_supports_SVA_property(const exprt &expr)
115115
if(has_subexpr(expr, ID_sva_sequence_within))
116116
return false;
117117

118-
// sva_sequence_non_consecutive_repetition is not supported yet
119-
if(has_subexpr(expr, ID_sva_sequence_non_consecutive_repetition))
120-
return false;
121-
122-
// sva_sequence_goto_repetition is not supported yet
123-
if(has_subexpr(expr, ID_sva_sequence_goto_repetition))
124-
return false;
125-
126118
return true;
127119
}
128120

src/trans-word-level/sequence.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,72 @@ sequence_matchest instantiate_sequence(
279279

280280
return result;
281281
}
282+
else if(expr.id() == ID_sva_sequence_goto_repetition)
283+
{
284+
// The 'op' is a Boolean condition, not a sequence.
285+
auto &op = to_sva_sequence_goto_repetition_expr(expr).op();
286+
auto repetitions_int = numeric_cast_v<mp_integer>(
287+
to_sva_sequence_goto_repetition_expr(expr).repetitions());
288+
PRECONDITION(repetitions_int >= 1);
289+
290+
sequence_matchest result;
291+
292+
// We add up the number of matches of 'op' starting from
293+
// timeframe u, until the end of our unwinding.
294+
const auto bits = address_bits(no_timeframes);
295+
const auto zero = from_integer(0, unsignedbv_typet{bits});
296+
const auto one = from_integer(1, unsignedbv_typet{bits});
297+
const auto repetitions = from_integer(repetitions_int, zero.type());
298+
exprt matches = zero;
299+
300+
for(mp_integer u = t; u < no_timeframes; ++u)
301+
{
302+
// match of op in timeframe u?
303+
auto rec_op = instantiate(op, u, no_timeframes);
304+
305+
// add up
306+
matches = plus_exprt{matches, if_exprt{rec_op, one, zero}};
307+
308+
// We have a match for op[->n] if there is a match in timeframe
309+
// u and matches is n.
310+
result.emplace_back(
311+
u, and_exprt{rec_op, equal_exprt{matches, repetitions}});
312+
}
313+
314+
return result;
315+
}
316+
else if(expr.id() == ID_sva_sequence_non_consecutive_repetition)
317+
{
318+
// The 'op' is a Boolean condition, not a sequence.
319+
auto &op = to_sva_sequence_non_consecutive_repetition_expr(expr).op();
320+
auto repetitions_int = numeric_cast_v<mp_integer>(
321+
to_sva_sequence_non_consecutive_repetition_expr(expr).repetitions());
322+
PRECONDITION(repetitions_int >= 1);
323+
324+
sequence_matchest result;
325+
326+
// We add up the number of matches of 'op' starting from
327+
// timeframe u, until the end of our unwinding.
328+
const auto bits = address_bits(no_timeframes);
329+
const auto zero = from_integer(0, unsignedbv_typet{bits});
330+
const auto one = from_integer(1, zero.type());
331+
const auto repetitions = from_integer(repetitions_int, zero.type());
332+
exprt matches = zero;
333+
334+
for(mp_integer u = t; u < no_timeframes; ++u)
335+
{
336+
// match of op in timeframe u?
337+
auto rec_op = instantiate(op, u, no_timeframes);
338+
339+
// add up
340+
matches = plus_exprt{matches, if_exprt{rec_op, one, zero}};
341+
342+
// We have a match for op[=n] if matches is n.
343+
result.emplace_back(u, equal_exprt{matches, repetitions});
344+
}
345+
346+
return result;
347+
}
282348
else
283349
{
284350
// not a sequence, evaluate as state predicate

src/verilog/expr2verilog.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,7 +1856,8 @@ expr2verilogt::resultt expr2verilogt::convert_rec(const exprt &src)
18561856

18571857
else if(src.id() == ID_sva_sequence_non_consecutive_repetition)
18581858
return precedence = verilog_precedencet::MIN,
1859-
convert_sva_binary_repetition("[=", to_binary_expr(src));
1859+
convert_sva_binary_repetition(
1860+
"[=", to_sva_sequence_non_consecutive_repetition_expr(src));
18601861
// not sure about precedence
18611862

18621863
else if(src.id() == ID_sva_sequence_consecutive_repetition)
@@ -1865,7 +1866,8 @@ expr2verilogt::resultt expr2verilogt::convert_rec(const exprt &src)
18651866

18661867
else if(src.id() == ID_sva_sequence_goto_repetition)
18671868
return precedence = verilog_precedencet::MIN,
1868-
convert_sva_binary_repetition("[->", to_binary_expr(src));
1869+
convert_sva_binary_repetition(
1870+
"[->", to_sva_sequence_goto_repetition_expr(src));
18691871
// not sure about precedence
18701872

18711873
else if(src.id() == ID_sva_ranged_always)

src/verilog/sva_expr.h

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,6 +1318,117 @@ to_sva_sequence_consecutive_repetition_expr(exprt &expr)
13181318
return static_cast<sva_sequence_consecutive_repetition_exprt &>(expr);
13191319
}
13201320

1321+
class sva_sequence_goto_repetition_exprt : public binary_exprt
1322+
{
1323+
public:
1324+
sva_sequence_goto_repetition_exprt(exprt __op, constant_exprt __repetitions)
1325+
: binary_exprt{
1326+
std::move(__op),
1327+
ID_sva_sequence_goto_repetition,
1328+
std::move(__repetitions),
1329+
bool_typet{}}
1330+
{
1331+
}
1332+
1333+
const exprt &op() const
1334+
{
1335+
return op0();
1336+
}
1337+
1338+
exprt &op()
1339+
{
1340+
return op0();
1341+
}
1342+
1343+
// The number of repetitions must be a constant after elaboration.
1344+
const constant_exprt &repetitions() const
1345+
{
1346+
return static_cast<const constant_exprt &>(op1());
1347+
}
1348+
1349+
constant_exprt &repetitions()
1350+
{
1351+
return static_cast<constant_exprt &>(op1());
1352+
}
1353+
1354+
protected:
1355+
using binary_exprt::op0;
1356+
using binary_exprt::op1;
1357+
};
1358+
1359+
inline const sva_sequence_goto_repetition_exprt &
1360+
to_sva_sequence_goto_repetition_expr(const exprt &expr)
1361+
{
1362+
PRECONDITION(expr.id() == ID_sva_sequence_goto_repetition);
1363+
sva_sequence_goto_repetition_exprt::check(expr);
1364+
return static_cast<const sva_sequence_goto_repetition_exprt &>(expr);
1365+
}
1366+
1367+
inline sva_sequence_goto_repetition_exprt &
1368+
to_sva_sequence_goto_repetition_expr(exprt &expr)
1369+
{
1370+
PRECONDITION(expr.id() == ID_sva_sequence_goto_repetition);
1371+
sva_sequence_goto_repetition_exprt::check(expr);
1372+
return static_cast<sva_sequence_goto_repetition_exprt &>(expr);
1373+
}
1374+
1375+
class sva_sequence_non_consecutive_repetition_exprt : public binary_exprt
1376+
{
1377+
public:
1378+
sva_sequence_non_consecutive_repetition_exprt(
1379+
exprt __op,
1380+
constant_exprt __repetitions)
1381+
: binary_exprt{
1382+
std::move(__op),
1383+
ID_sva_sequence_non_consecutive_repetition,
1384+
std::move(__repetitions),
1385+
bool_typet{}}
1386+
{
1387+
}
1388+
1389+
const exprt &op() const
1390+
{
1391+
return op0();
1392+
}
1393+
1394+
exprt &op()
1395+
{
1396+
return op0();
1397+
}
1398+
1399+
// The number of repetitions must be a constant after elaboration.
1400+
const constant_exprt &repetitions() const
1401+
{
1402+
return static_cast<const constant_exprt &>(op1());
1403+
}
1404+
1405+
constant_exprt &repetitions()
1406+
{
1407+
return static_cast<constant_exprt &>(op1());
1408+
}
1409+
1410+
protected:
1411+
using binary_exprt::op0;
1412+
using binary_exprt::op1;
1413+
};
1414+
1415+
inline const sva_sequence_non_consecutive_repetition_exprt &
1416+
to_sva_sequence_non_consecutive_repetition_expr(const exprt &expr)
1417+
{
1418+
PRECONDITION(expr.id() == ID_sva_sequence_non_consecutive_repetition);
1419+
sva_sequence_non_consecutive_repetition_exprt::check(expr);
1420+
return static_cast<const sva_sequence_non_consecutive_repetition_exprt &>(
1421+
expr);
1422+
}
1423+
1424+
inline sva_sequence_non_consecutive_repetition_exprt &
1425+
to_sva_sequence_non_consecutive_repetition_expr(exprt &expr)
1426+
{
1427+
PRECONDITION(expr.id() == ID_sva_sequence_non_consecutive_repetition);
1428+
sva_sequence_non_consecutive_repetition_exprt::check(expr);
1429+
return static_cast<sva_sequence_non_consecutive_repetition_exprt &>(expr);
1430+
}
1431+
13211432
class sva_sequence_intersect_exprt : public binary_exprt
13221433
{
13231434
public:

0 commit comments

Comments
 (0)