Skip to content

Commit 41c817d

Browse files
committed
use sva_sequence_repetition_exprt for [*] and [+]
The base class sva_sequence_repetition_exprt is now also used for the SVA consecutive sequence repetition operators [*] and [+].
1 parent 0a1c5ce commit 41c817d

File tree

9 files changed

+191
-67
lines changed

9 files changed

+191
-67
lines changed

regression/verilog/SVA/sequence_repetition2.desc

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
CORE
22
sequence_repetition2.sv
33
--bound 10
4-
^\[main\.p0\] main\.x == 0\[\*\]: PROVED up to bound 10$
5-
^\[main\.p1\] main\.x == 1\[\*\]: PROVED up to bound 10$
6-
^\[main\.p2\] \(main\.x == 0\[\+\]\) #=# main\.x == 1: PROVED up to bound 10$
7-
^\[main\.p3\] main\.x == 0\[\+\]: PROVED up to bound 10$
8-
^\[main\.p4\] main\.half_x == 0\[\*\]: PROVED up to bound 10$
9-
^\[main\.p5\] 0\[\*\]: PROVED up to bound 10$
10-
^\[main\.p6\] main\.x == 1\[\+\]: REFUTED$
11-
^\[main\.p7\] \(main\.x == 0\[\+\]\) #-# main\.x == 1: REFUTED$
12-
^\[main\.p8\] 0\[\+\]: REFUTED$
4+
^\[main\.p0\] main\.x == 0 \[\*\]: PROVED up to bound 10$
5+
^\[main\.p1\] main\.x == 1 \[\*\]: PROVED up to bound 10$
6+
^\[main\.p2\] \(main\.x == 0 \[\+\]\) #=# main\.x == 1: PROVED up to bound 10$
7+
^\[main\.p3\] main\.x == 0 \[\+\]: PROVED up to bound 10$
8+
^\[main\.p4\] main\.half_x == 0 \[\*\]: PROVED up to bound 10$
9+
^\[main\.p5\] 0 \[\*\]: PROVED up to bound 10$
10+
^\[main\.p6\] main\.x == 1 \[\+\]: REFUTED$
11+
^\[main\.p7\] \(main\.x == 0 \[\+\]\) #-# main\.x == 1: REFUTED$
12+
^\[main\.p8\] 0 \[\+\]: REFUTED$
1313
^EXIT=10$
1414
^SIGNAL=0$
1515
--

src/hw_cbmc_irep_ids.h

-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ IREP_ID_ONE(sva_sequence_goto_repetition)
6666
IREP_ID_ONE(sva_sequence_intersect)
6767
IREP_ID_ONE(sva_sequence_non_consecutive_repetition)
6868
IREP_ID_ONE(sva_sequence_property)
69-
IREP_ID_ONE(sva_sequence_repetition_star)
7069
IREP_ID_ONE(sva_sequence_repetition_plus)
7170
IREP_ID_ONE(sva_sequence_throughout)
7271
IREP_ID_ONE(sva_sequence_within)

src/temporal-logic/temporal_logic.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@ bool is_SVA_sequence_operator(const exprt &expr)
113113
id == ID_sva_sequence_goto_repetition ||
114114
id == ID_sva_sequence_consecutive_repetition ||
115115
id == ID_sva_sequence_non_consecutive_repetition ||
116-
id == ID_sva_sequence_repetition_star ||
117116
id == ID_sva_sequence_repetition_plus;
118117
}
119118

src/trans-word-level/sequence.cpp

+38-28
Original file line numberDiff line numberDiff line change
@@ -309,42 +309,52 @@ sequence_matchest instantiate_sequence(
309309
}
310310
else if(expr.id() == ID_sva_sequence_consecutive_repetition)
311311
{
312-
// x[*n] is syntactic sugar for x ##1 ... ##1 x, with n repetitions
313312
auto &repetition = to_sva_sequence_consecutive_repetition_expr(expr);
314-
return instantiate_sequence(
315-
repetition.lower(), semantics, t, no_timeframes);
316-
}
317-
else if(
318-
expr.id() == ID_sva_sequence_repetition_plus ||
319-
expr.id() == ID_sva_sequence_repetition_star)
320-
{
321-
// x[+] and x[*]
322-
auto &op = to_unary_expr(expr).op();
313+
if(repetition.is_unbounded() && repetition.repetitions_given())
314+
{
315+
// [x:$]
316+
auto from = numeric_cast_v<mp_integer>(repetition.from());
317+
auto &op = repetition.op();
323318

324-
// Is x a sequence or a state predicate?
325-
if(is_SVA_sequence_operator(op))
326-
PRECONDITION(false); // no support
319+
// Is op a sequence or a state predicate?
320+
if(is_SVA_sequence_operator(op))
321+
PRECONDITION(false); // no support
327322

328-
sequence_matchest result;
323+
sequence_matchest result;
329324

330-
// we incrementally add conjuncts to the condition
331-
exprt::operandst conjuncts;
325+
// we incrementally add conjuncts to the condition
326+
exprt::operandst conjuncts;
332327

333-
for(mp_integer u = t; u < no_timeframes; ++u)
334-
{
335-
// does x hold in state u?
336-
auto cond_u = instantiate(op, u, no_timeframes);
337-
conjuncts.push_back(cond_u);
338-
result.push_back({u, conjunction(conjuncts)});
339-
}
328+
for(mp_integer u = t; u < no_timeframes; ++u)
329+
{
330+
// does op hold in timeframe u?
331+
auto cond_u = instantiate(op, u, no_timeframes);
332+
conjuncts.push_back(cond_u);
340333

341-
// In addition to the above, x[*] allows an empty match.
342-
if(expr.id() == ID_sva_sequence_repetition_star)
343-
result.push_back({t, true_exprt{}});
334+
if(conjuncts.size() >= from)
335+
result.push_back({u, conjunction(conjuncts)});
336+
}
344337

345-
return result;
338+
// Empty match allowed?
339+
if(from == 0)
340+
result.push_back({t, true_exprt{}});
341+
342+
return result;
343+
}
344+
else
345+
{
346+
// [*], [*n], [*x:y]
347+
return instantiate_sequence(
348+
repetition.lower(), semantics, t, no_timeframes);
349+
}
350+
}
351+
else if(expr.id() == ID_sva_sequence_repetition_plus) // x[+]
352+
{
353+
auto &repetition = to_sva_sequence_repetition_plus_expr(expr);
354+
return instantiate_sequence(
355+
repetition.lower(), semantics, t, no_timeframes);
346356
}
347-
else if(expr.id() == ID_sva_sequence_goto_repetition)
357+
else if(expr.id() == ID_sva_sequence_goto_repetition) // [->...]
348358
{
349359
// The 'op' is a Boolean condition, not a sequence.
350360
auto &op = to_sva_sequence_goto_repetition_expr(expr).op();

src/verilog/expr2verilog.cpp

+12-15
Original file line numberDiff line numberDiff line change
@@ -628,17 +628,20 @@ expr2verilogt::resultt expr2verilogt::convert_sva_sequence_repetition(
628628

629629
std::string dest = op.s + " [" + name;
630630

631-
if(expr.is_range())
631+
if(expr.repetitions_given())
632632
{
633-
dest += convert_rec(expr.from()).s;
633+
if(expr.is_range())
634+
{
635+
dest += convert_rec(expr.from()).s;
634636

635-
if(expr.is_unbounded())
636-
dest += ":$";
637+
if(expr.is_unbounded())
638+
dest += ":$";
639+
else
640+
dest += ":" + convert_rec(expr.to()).s;
641+
}
637642
else
638-
dest += ":" + convert_rec(expr.to()).s;
643+
dest += convert_rec(expr.repetitions()).s;
639644
}
640-
else
641-
dest += convert_rec(expr.repetitions()).s;
642645

643646
dest += ']';
644647

@@ -1848,15 +1851,9 @@ expr2verilogt::resultt expr2verilogt::convert_rec(const exprt &src)
18481851
return precedence = verilog_precedencet::MIN,
18491852
convert_sva_unary("always", to_sva_always_expr(src));
18501853

1851-
else if(src.id() == ID_sva_sequence_repetition_star)
1852-
return precedence = verilog_precedencet::MIN,
1853-
convert_sva_unary(to_unary_expr(src), "[*]");
1854-
// not sure about precedence
1855-
18561854
else if(src.id() == ID_sva_sequence_repetition_plus)
1857-
return precedence = verilog_precedencet::MIN,
1858-
convert_sva_unary(to_unary_expr(src), "[+]");
1859-
// not sure about precedence
1855+
return convert_sva_sequence_repetition(
1856+
"+", to_sva_sequence_repetition_plus_expr(src));
18601857

18611858
else if(src.id() == ID_sva_sequence_non_consecutive_repetition)
18621859
return convert_sva_sequence_repetition(

src/verilog/parser.y

+6-2
Original file line numberDiff line numberDiff line change
@@ -2700,9 +2700,13 @@ consecutive_repetition:
27002700
}
27012701
}
27022702
| "[*" ']'
2703-
{ init($$, ID_sva_sequence_repetition_star); }
2703+
{ init($$, ID_sva_sequence_consecutive_repetition);
2704+
stack_expr($$).add_to_operands(nil_exprt{}, nil_exprt{});
2705+
}
27042706
| "[+" ']'
2705-
{ init($$, ID_sva_sequence_repetition_plus); }
2707+
{ init($$, ID_sva_sequence_repetition_plus);
2708+
stack_expr($$).add_to_operands(nil_exprt{}, nil_exprt{});
2709+
}
27062710
;
27072711

27082712
non_consecutive_repetition:

src/verilog/sva_expr.cpp

+14-1
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,25 @@ exprt sva_case_exprt::lowering() const
5757
disjunction(disjuncts), case_items.front().result(), reduced_rec};
5858
}
5959

60+
exprt sva_sequence_repetition_plus_exprt::lower() const
61+
{
62+
// [+] is the same as [*1:$]
63+
return sva_sequence_consecutive_repetition_exprt{
64+
op(), from_integer(1, integer_typet{}), infinity_exprt{integer_typet{}}};
65+
}
66+
6067
exprt sva_sequence_consecutive_repetition_exprt::lower() const
6168
{
6269
PRECONDITION(
6370
op().type().id() == ID_bool || op().type().id() == ID_verilog_sva_sequence);
6471

65-
if(!is_range())
72+
if(!repetitions_given())
73+
{
74+
// op[*] is the same as op[*0:$]
75+
return sva_sequence_consecutive_repetition_exprt{
76+
op(), from_integer(0, integer_typet{}), infinity_exprt{integer_typet{}}};
77+
}
78+
else if(!is_range())
6679
{
6780
// expand x[*n] into x ##1 x ##1 ...
6881
auto n = numeric_cast_v<mp_integer>(repetitions());

src/verilog/sva_expr.h

+96-3
Original file line numberDiff line numberDiff line change
@@ -1325,10 +1325,22 @@ inline sva_case_exprt &to_sva_case_expr(exprt &expr)
13251325
}
13261326

13271327
/// Base class for [->...], [*...], [=...]
1328-
/// The ... constraint may be x, x:y, x:$
1328+
/// The ... constraint may be blank, x, x:y, x:$
13291329
class sva_sequence_repetition_exprt : public ternary_exprt
13301330
{
13311331
public:
1332+
/// number of repetitions not given, e.g., [*] or [+]
1333+
sva_sequence_repetition_exprt(exprt __op, irep_idt __id)
1334+
: ternary_exprt{
1335+
__id,
1336+
std::move(__op),
1337+
nil_exprt{},
1338+
nil_exprt{},
1339+
verilog_sva_sequence_typet{}}
1340+
{
1341+
}
1342+
1343+
/// fixed number of repetitions
13321344
sva_sequence_repetition_exprt(
13331345
exprt __op,
13341346
irep_idt __id,
@@ -1342,6 +1354,7 @@ class sva_sequence_repetition_exprt : public ternary_exprt
13421354
{
13431355
}
13441356

1357+
/// bounded range for the number of repetitions
13451358
sva_sequence_repetition_exprt(
13461359
exprt __op,
13471360
irep_idt __id,
@@ -1356,6 +1369,21 @@ class sva_sequence_repetition_exprt : public ternary_exprt
13561369
{
13571370
}
13581371

1372+
/// unbounded range for the number of repetitions
1373+
sva_sequence_repetition_exprt(
1374+
exprt __op,
1375+
irep_idt __id,
1376+
constant_exprt __from,
1377+
infinity_exprt __to)
1378+
: ternary_exprt{
1379+
__id,
1380+
std::move(__op),
1381+
std::move(__from),
1382+
std::move(__to),
1383+
verilog_sva_sequence_typet{}}
1384+
{
1385+
}
1386+
13591387
// May be a sequence for [*...], Boolean otherwise
13601388
const exprt &op() const
13611389
{
@@ -1367,16 +1395,22 @@ class sva_sequence_repetition_exprt : public ternary_exprt
13671395
return op0();
13681396
}
13691397

1398+
/// true if number of repetitions is given
1399+
bool repetitions_given() const
1400+
{
1401+
return op1().is_not_nil();
1402+
}
1403+
13701404
// The number of repetitions must be a constant after elaboration.
13711405
const constant_exprt &repetitions() const
13721406
{
1373-
PRECONDITION(!is_range());
1407+
PRECONDITION(repetitions_given() && !is_range());
13741408
return static_cast<const constant_exprt &>(op1());
13751409
}
13761410

13771411
constant_exprt &repetitions()
13781412
{
1379-
PRECONDITION(!is_range());
1413+
PRECONDITION(repetitions_given() && !is_range());
13801414
return static_cast<constant_exprt &>(op1());
13811415
}
13821416

@@ -1434,10 +1468,52 @@ to_sva_sequence_repetition_expr(exprt &expr)
14341468
return static_cast<sva_sequence_repetition_exprt &>(expr);
14351469
}
14361470

1471+
/// op[+]
1472+
class sva_sequence_repetition_plus_exprt : public sva_sequence_repetition_exprt
1473+
{
1474+
public:
1475+
/// The operand is a sequence
1476+
explicit sva_sequence_repetition_plus_exprt(exprt op)
1477+
: sva_sequence_repetition_exprt{
1478+
std::move(op),
1479+
ID_sva_sequence_repetition_plus}
1480+
{
1481+
}
1482+
1483+
// op[*1:$]
1484+
exprt lower() const;
1485+
};
1486+
1487+
static inline const sva_sequence_repetition_plus_exprt &
1488+
to_sva_sequence_repetition_plus_expr(const exprt &expr)
1489+
{
1490+
PRECONDITION(expr.id() == ID_sva_sequence_repetition_plus);
1491+
sva_sequence_repetition_plus_exprt::check(expr);
1492+
return static_cast<const sva_sequence_repetition_plus_exprt &>(expr);
1493+
}
1494+
1495+
static inline sva_sequence_repetition_plus_exprt &
1496+
to_sva_sequence_repetition_plus_expr(exprt &expr)
1497+
{
1498+
PRECONDITION(expr.id() == ID_sva_sequence_repetition_plus);
1499+
sva_sequence_repetition_plus_exprt::check(expr);
1500+
return static_cast<sva_sequence_repetition_plus_exprt &>(expr);
1501+
}
1502+
1503+
/// [*] or [*n] or [*x:y] or [*x:$]
14371504
class sva_sequence_consecutive_repetition_exprt
14381505
: public sva_sequence_repetition_exprt
14391506
{
14401507
public:
1508+
/// op[*]
1509+
explicit sva_sequence_consecutive_repetition_exprt(exprt __op)
1510+
: sva_sequence_repetition_exprt{
1511+
std::move(__op),
1512+
ID_sva_sequence_consecutive_repetition}
1513+
{
1514+
}
1515+
1516+
/// op[*n]
14411517
sva_sequence_consecutive_repetition_exprt(
14421518
exprt __op,
14431519
constant_exprt __repetitions)
@@ -1448,6 +1524,7 @@ class sva_sequence_consecutive_repetition_exprt
14481524
{
14491525
}
14501526

1527+
/// op[*x:y]
14511528
sva_sequence_consecutive_repetition_exprt(
14521529
exprt __op,
14531530
constant_exprt __from,
@@ -1460,6 +1537,22 @@ class sva_sequence_consecutive_repetition_exprt
14601537
{
14611538
}
14621539

1540+
/// op[*x:$]
1541+
sva_sequence_consecutive_repetition_exprt(
1542+
exprt __op,
1543+
constant_exprt __from,
1544+
infinity_exprt __to)
1545+
: sva_sequence_repetition_exprt{
1546+
std::move(__op),
1547+
ID_sva_sequence_consecutive_repetition,
1548+
std::move(__from),
1549+
std::move(__to)}
1550+
{
1551+
}
1552+
1553+
/// [*] --> [0:$]
1554+
/// [*n] --> op ##1 op ##1 op ...
1555+
/// [*x:y] --> op[*x] or op[*x+1] or ... or op[*y]
14631556
exprt lower() const;
14641557
};
14651558

0 commit comments

Comments
 (0)