Skip to content

Commit cbba092

Browse files
committed
SVA's [->x:y] and [*x:y]
Both the goto repetition operator and the consecutive repetition operator can either take a singleton number of repetition or a (possibly unbounded) range. This adds support for the range case.
1 parent 0a1c5ce commit cbba092

File tree

5 files changed

+88
-37
lines changed

5 files changed

+88
-37
lines changed

regression/verilog/SVA/cover_sequence4.desc

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE
22
cover_sequence4.sv
33
--bound 3
44
^\[main\.p0\] cover \(1 \[=10\]\): REFUTED up to bound 3$
@@ -9,4 +9,3 @@ cover_sequence4.sv
99
--
1010
^warning: ignoring
1111
--
12-
Implementation of [=x:y] is missing.

src/trans-word-level/sequence.cpp

+74-27
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,63 @@ Author: Daniel Kroening, [email protected]
1818
#include "obligations.h"
1919
#include "property.h"
2020

21+
// condition on counters for ocurrences of non-consecutive repetitions
22+
exprt sequence_count_condition(
23+
const sva_sequence_repetition_exprt &expr,
24+
const exprt &counter)
25+
{
26+
if(expr.is_range())
27+
{
28+
// number of repetitions inside a range
29+
auto from = numeric_cast_v<mp_integer>(expr.from());
30+
31+
if(expr.is_unbounded())
32+
{
33+
return binary_relation_exprt{
34+
counter, ID_ge, from_integer(from, counter.type())};
35+
}
36+
else
37+
{
38+
auto to = numeric_cast_v<mp_integer>(expr.to());
39+
40+
return and_exprt{
41+
binary_relation_exprt{
42+
counter, ID_ge, from_integer(from, counter.type())},
43+
binary_relation_exprt{
44+
counter, ID_le, from_integer(to, counter.type())}};
45+
}
46+
}
47+
else
48+
{
49+
// fixed number of repetitions
50+
auto repetitions = numeric_cast_v<mp_integer>(expr.repetitions());
51+
return equal_exprt{counter, from_integer(repetitions, counter.type())};
52+
}
53+
}
54+
55+
/// determine type for the repetition counter
56+
typet sequence_count_type(
57+
const sva_sequence_repetition_exprt &expr,
58+
const mp_integer &no_timeframes)
59+
{
60+
mp_integer max;
61+
62+
if(expr.is_range())
63+
{
64+
if(expr.is_unbounded())
65+
max = numeric_cast_v<mp_integer>(expr.from());
66+
else
67+
max = numeric_cast_v<mp_integer>(expr.to());
68+
}
69+
else
70+
max = numeric_cast_v<mp_integer>(expr.repetitions());
71+
72+
max = std::max(no_timeframes, max);
73+
74+
auto bits = address_bits(max + 1);
75+
return unsignedbv_typet{bits};
76+
}
77+
2178
sequence_matchest instantiate_sequence(
2279
exprt expr,
2380
sva_sequence_semanticst semantics,
@@ -307,7 +364,7 @@ sequence_matchest instantiate_sequence(
307364

308365
return result;
309366
}
310-
else if(expr.id() == ID_sva_sequence_consecutive_repetition)
367+
else if(expr.id() == ID_sva_sequence_consecutive_repetition) // [*...]
311368
{
312369
// x[*n] is syntactic sugar for x ##1 ... ##1 x, with n repetitions
313370
auto &repetition = to_sva_sequence_consecutive_repetition_expr(expr);
@@ -344,69 +401,59 @@ sequence_matchest instantiate_sequence(
344401

345402
return result;
346403
}
347-
else if(expr.id() == ID_sva_sequence_goto_repetition)
404+
else if(expr.id() == ID_sva_sequence_goto_repetition) // [->...]
348405
{
349-
// The 'op' is a Boolean condition, not a sequence.
350-
auto &op = to_sva_sequence_goto_repetition_expr(expr).op();
351-
auto repetitions_int = numeric_cast_v<mp_integer>(
352-
to_sva_sequence_goto_repetition_expr(expr).repetitions());
353-
PRECONDITION(repetitions_int >= 1);
406+
auto &repetition = to_sva_sequence_goto_repetition_expr(expr);
407+
auto &condition = repetition.op();
354408

355409
sequence_matchest result;
356410

357411
// We add up the number of matches of 'op' starting from
358412
// timeframe u, until the end of our unwinding.
359-
const auto bits = address_bits(no_timeframes);
360-
const auto zero = from_integer(0, unsignedbv_typet{bits});
361-
const auto one = from_integer(1, unsignedbv_typet{bits});
362-
const auto repetitions = from_integer(repetitions_int, zero.type());
413+
const auto type = sequence_count_type(repetition, no_timeframes);
414+
const auto zero = from_integer(0, type);
415+
const auto one = from_integer(1, type);
363416
exprt matches = zero;
364417

365418
for(mp_integer u = t; u < no_timeframes; ++u)
366419
{
367420
// match of op in timeframe u?
368-
auto rec_op = instantiate(op, u, no_timeframes);
421+
auto rec_op = instantiate(condition, u, no_timeframes);
369422

370423
// add up
371424
matches = plus_exprt{matches, if_exprt{rec_op, one, zero}};
372425

373426
// We have a match for op[->n] if there is a match in timeframe
374427
// u and matches is n.
375-
result.emplace_back(
376-
u, and_exprt{rec_op, equal_exprt{matches, repetitions}});
428+
result.emplace_back(u, sequence_count_condition(repetition, matches));
377429
}
378430

379431
return result;
380432
}
381-
else if(expr.id() == ID_sva_sequence_non_consecutive_repetition)
433+
else if(expr.id() == ID_sva_sequence_non_consecutive_repetition) // [=...]
382434
{
383-
// The 'op' is a Boolean condition, not a sequence.
384-
auto &op = to_sva_sequence_non_consecutive_repetition_expr(expr).op();
385-
auto repetitions_int = numeric_cast_v<mp_integer>(
386-
to_sva_sequence_non_consecutive_repetition_expr(expr).repetitions());
387-
PRECONDITION(repetitions_int >= 1);
435+
auto &repetition = to_sva_sequence_non_consecutive_repetition_expr(expr);
436+
auto &condition = repetition.op();
388437

389438
sequence_matchest result;
390439

391440
// We add up the number of matches of 'op' starting from
392441
// timeframe u, until the end of our unwinding.
393-
const auto bits =
394-
address_bits(std::max(no_timeframes, repetitions_int + 1));
395-
const auto zero = from_integer(0, unsignedbv_typet{bits});
396-
const auto one = from_integer(1, zero.type());
397-
const auto repetitions = from_integer(repetitions_int, zero.type());
442+
const auto type = sequence_count_type(repetition, no_timeframes);
443+
const auto zero = from_integer(0, type);
444+
const auto one = from_integer(1, type);
398445
exprt matches = zero;
399446

400447
for(mp_integer u = t; u < no_timeframes; ++u)
401448
{
402449
// match of op in timeframe u?
403-
auto rec_op = instantiate(op, u, no_timeframes);
450+
auto rec_op = instantiate(condition, u, no_timeframes);
404451

405452
// add up
406453
matches = plus_exprt{matches, if_exprt{rec_op, one, zero}};
407454

408455
// We have a match for op[=n] if matches is n.
409-
result.emplace_back(u, equal_exprt{matches, repetitions});
456+
result.emplace_back(u, sequence_count_condition(repetition, matches));
410457
}
411458

412459
return result;

src/verilog/expr2verilog.cpp

+9-7
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ expr2verilogt::resultt expr2verilogt::convert_sva_binary(
608608

609609
/*******************************************************************\
610610
611-
Function: expr2verilogt::convert_sva_sequence_consecutive_repetition
611+
Function: expr2verilogt::convert_sva_sequence_repetition
612612
613613
Inputs:
614614
@@ -622,20 +622,22 @@ expr2verilogt::resultt expr2verilogt::convert_sva_sequence_repetition(
622622
const std::string &name,
623623
const sva_sequence_repetition_exprt &expr)
624624
{
625-
auto op = convert_rec(expr.op());
626-
if(op.p == verilog_precedencet::MIN)
627-
op.s = "(" + op.s + ")";
625+
auto op_rec = convert_rec(expr.op());
626+
627+
if(op_rec.p == verilog_precedencet::MIN)
628+
op_rec.s = "(" + op_rec.s + ")";
628629

629-
std::string dest = op.s + " [" + name;
630+
std::string dest = op_rec.s + " [" + name;
630631

631632
if(expr.is_range())
632633
{
633634
dest += convert_rec(expr.from()).s;
635+
dest += ':';
634636

635637
if(expr.is_unbounded())
636-
dest += ":$";
638+
dest += '$';
637639
else
638-
dest += ":" + convert_rec(expr.to()).s;
640+
dest += convert_rec(expr.to()).s;
639641
}
640642
else
641643
dest += convert_rec(expr.repetitions()).s;

src/verilog/expr2verilog_class.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ class sva_abort_exprt;
1616
class sva_case_exprt;
1717
class sva_if_exprt;
1818
class sva_ranged_predicate_exprt;
19-
class sva_sequence_repetition_exprt;
2019
class sva_sequence_first_match_exprt;
20+
class sva_sequence_repetition_exprt;
2121

2222
// Precedences (higher means binds more strongly).
2323
// Follows Table 11-2 in IEEE 1800-2017.

src/verilog/verilog_typecheck_sva.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,9 @@ exprt verilog_typecheck_exprt::convert_ternary_sva(ternary_exprt expr)
352352

353353
expr.op1() = from_integer(n, integer_typet{});
354354

355+
if(expr.op2().is_not_nil())
356+
convert_expr(expr.op2());
357+
355358
expr.type() = verilog_sva_sequence_typet{};
356359

357360
return std::move(expr);

0 commit comments

Comments
 (0)