Skip to content

Commit fd9b801

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 range. This adds support for the range case.
1 parent 78d038d commit fd9b801

File tree

6 files changed

+201
-89
lines changed

6 files changed

+201
-89
lines changed

src/trans-word-level/sequence.cpp

+42-16
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Author: Daniel Kroening, [email protected]
1010

1111
#include <util/arith_tools.h>
1212
#include <util/ebmc_util.h>
13+
#include <util/std_expr.h>
1314

1415
#include <temporal-logic/temporal_logic.h>
1516
#include <verilog/sva_expr.h>
@@ -18,6 +19,39 @@ Author: Daniel Kroening, [email protected]
1819
#include "obligations.h"
1920
#include "property.h"
2021

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 lower = numeric_cast_v<mp_integer>(
30+
expr.lower());
31+
32+
if(expr.is_unbounded())
33+
{
34+
return binary_relation_exprt{counter, ID_ge, from_integer(lower, counter.type())};
35+
}
36+
else
37+
{
38+
auto upper = numeric_cast_v<mp_integer>(
39+
to_constant_expr(expr.upper()));
40+
41+
return and_exprt{binary_relation_exprt{counter, ID_ge, from_integer(lower, counter.type())},
42+
binary_relation_exprt{counter, ID_le, from_integer(upper, counter.type())}};
43+
}
44+
}
45+
else
46+
{
47+
// fixed number of repetitions
48+
auto repetitions_int = numeric_cast_v<mp_integer>(
49+
expr.repetitions());
50+
51+
return equal_exprt{counter, from_integer(repetitions_int, counter.type())};
52+
}
53+
}
54+
2155
sequence_matchest instantiate_sequence(
2256
exprt expr,
2357
const mp_integer &t,
@@ -311,11 +345,8 @@ sequence_matchest instantiate_sequence(
311345
}
312346
else if(expr.id() == ID_sva_sequence_goto_repetition)
313347
{
314-
// The 'op' is a Boolean condition, not a sequence.
315-
auto &op = to_sva_sequence_goto_repetition_expr(expr).op();
316-
auto repetitions_int = numeric_cast_v<mp_integer>(
317-
to_sva_sequence_goto_repetition_expr(expr).repetitions());
318-
PRECONDITION(repetitions_int >= 1);
348+
auto &repetition = to_sva_sequence_goto_repetition_expr(expr);
349+
auto &condition = repetition.condition();
319350

320351
sequence_matchest result;
321352

@@ -324,32 +355,28 @@ sequence_matchest instantiate_sequence(
324355
const auto bits = address_bits(no_timeframes);
325356
const auto zero = from_integer(0, unsignedbv_typet{bits});
326357
const auto one = from_integer(1, unsignedbv_typet{bits});
327-
const auto repetitions = from_integer(repetitions_int, zero.type());
328358
exprt matches = zero;
329359

330360
for(mp_integer u = t; u < no_timeframes; ++u)
331361
{
332362
// match of op in timeframe u?
333-
auto rec_op = instantiate(op, u, no_timeframes);
363+
auto rec_op = instantiate(condition, u, no_timeframes);
334364

335365
// add up
336366
matches = plus_exprt{matches, if_exprt{rec_op, one, zero}};
337367

338368
// We have a match for op[->n] if there is a match in timeframe
339369
// u and matches is n.
340370
result.emplace_back(
341-
u, and_exprt{rec_op, equal_exprt{matches, repetitions}});
371+
u, sequence_count_condition(repetition, matches));
342372
}
343373

344374
return result;
345375
}
346376
else if(expr.id() == ID_sva_sequence_non_consecutive_repetition)
347377
{
348-
// The 'op' is a Boolean condition, not a sequence.
349-
auto &op = to_sva_sequence_non_consecutive_repetition_expr(expr).op();
350-
auto repetitions_int = numeric_cast_v<mp_integer>(
351-
to_sva_sequence_non_consecutive_repetition_expr(expr).repetitions());
352-
PRECONDITION(repetitions_int >= 1);
378+
auto &repetition = to_sva_sequence_non_consecutive_repetition_expr(expr);
379+
auto &condition = repetition.condition();
353380

354381
sequence_matchest result;
355382

@@ -358,19 +385,18 @@ sequence_matchest instantiate_sequence(
358385
const auto bits = address_bits(no_timeframes);
359386
const auto zero = from_integer(0, unsignedbv_typet{bits});
360387
const auto one = from_integer(1, zero.type());
361-
const auto repetitions = from_integer(repetitions_int, zero.type());
362388
exprt matches = zero;
363389

364390
for(mp_integer u = t; u < no_timeframes; ++u)
365391
{
366392
// match of op in timeframe u?
367-
auto rec_op = instantiate(op, u, no_timeframes);
393+
auto rec_op = instantiate(condition, u, no_timeframes);
368394

369395
// add up
370396
matches = plus_exprt{matches, if_exprt{rec_op, one, zero}};
371397

372398
// We have a match for op[=n] if matches is n.
373-
result.emplace_back(u, equal_exprt{matches, repetitions});
399+
result.emplace_back(u, sequence_count_condition(repetition, matches));
374400
}
375401

376402
return result;

src/verilog/expr2verilog.cpp

+19-10
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_binary_repetition
611+
Function: expr2verilogt::convert_sva_sequence_repetition
612612
613613
Inputs:
614614
@@ -618,17 +618,26 @@ Function: expr2verilogt::convert_sva_binary_repetition
618618
619619
\*******************************************************************/
620620

621-
expr2verilogt::resultt expr2verilogt::convert_sva_binary_repetition(
621+
expr2verilogt::resultt expr2verilogt::convert_sva_sequence_repetition(
622622
const std::string &name,
623-
const binary_exprt &expr)
623+
const sva_sequence_repetition_exprt &expr)
624624
{
625-
auto op0 = convert_rec(expr.lhs());
626-
if(op0.p == verilog_precedencet::MIN)
627-
op0.s = "(" + op0.s + ")";
625+
auto condition = convert_rec(expr.condition());
628626

629-
auto op1 = convert_rec(expr.rhs());
627+
if(condition.p == verilog_precedencet::MIN)
628+
condition.s = "(" + condition.s + ")";
629+
630+
if(expr.is_range())
631+
{
632+
PRECONDITION(false);
633+
}
634+
else
635+
{
636+
auto repetitions = convert_rec(expr.repetitions());
630637

631-
return {verilog_precedencet::MIN, op0.s + " " + name + op1.s + "]"};
638+
return {
639+
verilog_precedencet::MIN, condition.s + " " + name + repetitions.s + "]"};
640+
}
632641
}
633642

634643
/*******************************************************************\
@@ -1878,7 +1887,7 @@ expr2verilogt::resultt expr2verilogt::convert_rec(const exprt &src)
18781887

18791888
else if(src.id() == ID_sva_sequence_non_consecutive_repetition)
18801889
return precedence = verilog_precedencet::MIN,
1881-
convert_sva_binary_repetition(
1890+
convert_sva_sequence_repetition(
18821891
"[=", to_sva_sequence_non_consecutive_repetition_expr(src));
18831892
// not sure about precedence
18841893

@@ -1888,7 +1897,7 @@ expr2verilogt::resultt expr2verilogt::convert_rec(const exprt &src)
18881897

18891898
else if(src.id() == ID_sva_sequence_goto_repetition)
18901899
return precedence = verilog_precedencet::MIN,
1891-
convert_sva_binary_repetition(
1900+
convert_sva_sequence_repetition(
18921901
"[->", to_sva_sequence_goto_repetition_expr(src));
18931902
// not sure about precedence
18941903

src/verilog/expr2verilog_class.h

+4-2
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_repetition_exprt;
2021
class sva_sequence_first_match_exprt;
2122

2223
// Precedences (higher means binds more strongly).
@@ -137,8 +138,9 @@ class expr2verilogt
137138

138139
resultt convert_sva_binary(const std::string &name, const binary_exprt &);
139140

140-
resultt
141-
convert_sva_binary_repetition(const std::string &name, const binary_exprt &);
141+
resultt convert_sva_sequence_repetition(
142+
const std::string &name,
143+
const sva_sequence_repetition_exprt &);
142144

143145
resultt convert_sva_sequence_consecutive_repetition(
144146
const sva_sequence_consecutive_repetition_exprt &);

src/verilog/parser.y

+18-2
Original file line numberDiff line numberDiff line change
@@ -2707,12 +2707,28 @@ consecutive_repetition:
27072707

27082708
non_consecutive_repetition:
27092709
"[=" const_or_range_expression ']'
2710-
{ init($$, ID_sva_sequence_non_consecutive_repetition); mto($$, $2); }
2710+
{ init($$, ID_sva_sequence_non_consecutive_repetition);
2711+
if(stack_expr($2).id() == ID_sva_cycle_delay)
2712+
swapop($$, $2);
2713+
else
2714+
{
2715+
mto($$, $2);
2716+
stack_expr($$).add_to_operands(nil_exprt{});
2717+
}
2718+
}
27112719
;
27122720

27132721
goto_repetition:
27142722
"[->" const_or_range_expression ']'
2715-
{ init($$, ID_sva_sequence_goto_repetition); mto($$, $2); }
2723+
{ init($$, ID_sva_sequence_goto_repetition);
2724+
if(stack_expr($2).id() == ID_sva_cycle_delay)
2725+
swapop($$, $2);
2726+
else
2727+
{
2728+
mto($$, $2);
2729+
stack_expr($$).add_to_operands(nil_exprt{});
2730+
}
2731+
}
27162732
;
27172733

27182734
cycle_delay_range:

src/verilog/sva_expr.h

+77-39
Original file line numberDiff line numberDiff line change
@@ -1364,24 +1364,29 @@ to_sva_sequence_consecutive_repetition_expr(exprt &expr)
13641364
return static_cast<sva_sequence_consecutive_repetition_exprt &>(expr);
13651365
}
13661366

1367-
class sva_sequence_goto_repetition_exprt : public binary_exprt
1367+
/// [->...] and [*...]
1368+
class sva_sequence_repetition_exprt : public ternary_exprt
13681369
{
13691370
public:
1370-
sva_sequence_goto_repetition_exprt(exprt __op, constant_exprt __repetitions)
1371-
: binary_exprt{
1371+
sva_sequence_repetition_exprt(
1372+
irep_idt __id,
1373+
exprt __op,
1374+
constant_exprt __repetitions)
1375+
: ternary_exprt{
1376+
__id,
13721377
std::move(__op),
1373-
ID_sva_sequence_goto_repetition,
13741378
std::move(__repetitions),
1375-
bool_typet{}}
1379+
nil_exprt{},
1380+
verilog_sva_sequence_typet{}}
13761381
{
13771382
}
13781383

1379-
const exprt &op() const
1384+
const exprt &condition() const
13801385
{
13811386
return op0();
13821387
}
13831388

1384-
exprt &op()
1389+
exprt &condition()
13851390
{
13861391
return op0();
13871392
}
@@ -1397,9 +1402,67 @@ class sva_sequence_goto_repetition_exprt : public binary_exprt
13971402
return static_cast<constant_exprt &>(op1());
13981403
}
13991404

1405+
bool is_range() const
1406+
{
1407+
return upper().is_not_nil();
1408+
}
1409+
1410+
bool is_unbounded() const
1411+
{
1412+
return upper().id() == ID_infinity;
1413+
}
1414+
1415+
const constant_exprt &lower() const
1416+
{
1417+
return static_cast<const constant_exprt &>(op1());
1418+
}
1419+
1420+
constant_exprt &lower()
1421+
{
1422+
return static_cast<constant_exprt &>(op1());
1423+
}
1424+
1425+
// might be $
1426+
const exprt &upper() const
1427+
{
1428+
return op2();
1429+
}
1430+
1431+
exprt &upper()
1432+
{
1433+
return op2();
1434+
}
1435+
14001436
protected:
1401-
using binary_exprt::op0;
1402-
using binary_exprt::op1;
1437+
using ternary_exprt::op0;
1438+
using ternary_exprt::op1;
1439+
using ternary_exprt::op2;
1440+
};
1441+
1442+
inline const sva_sequence_repetition_exprt &
1443+
to_sva_sequence_repetition_expr(const exprt &expr)
1444+
{
1445+
sva_sequence_repetition_exprt::check(expr);
1446+
return static_cast<const sva_sequence_repetition_exprt &>(expr);
1447+
}
1448+
1449+
inline sva_sequence_repetition_exprt &
1450+
to_sva_sequence_repetition_expr(exprt &expr)
1451+
{
1452+
sva_sequence_repetition_exprt::check(expr);
1453+
return static_cast<sva_sequence_repetition_exprt &>(expr);
1454+
}
1455+
1456+
class sva_sequence_goto_repetition_exprt : public sva_sequence_repetition_exprt
1457+
{
1458+
public:
1459+
sva_sequence_goto_repetition_exprt(exprt __op, constant_exprt __repetitions)
1460+
: sva_sequence_repetition_exprt{
1461+
ID_sva_sequence_goto_repetition,
1462+
std::move(__op),
1463+
std::move(__repetitions)}
1464+
{
1465+
}
14031466
};
14041467

14051468
inline const sva_sequence_goto_repetition_exprt &
@@ -1418,44 +1481,19 @@ to_sva_sequence_goto_repetition_expr(exprt &expr)
14181481
return static_cast<sva_sequence_goto_repetition_exprt &>(expr);
14191482
}
14201483

1421-
class sva_sequence_non_consecutive_repetition_exprt : public binary_exprt
1484+
class sva_sequence_non_consecutive_repetition_exprt
1485+
: public sva_sequence_repetition_exprt
14221486
{
14231487
public:
14241488
sva_sequence_non_consecutive_repetition_exprt(
14251489
exprt __op,
14261490
constant_exprt __repetitions)
1427-
: binary_exprt{
1428-
std::move(__op),
1491+
: sva_sequence_repetition_exprt{
14291492
ID_sva_sequence_non_consecutive_repetition,
1430-
std::move(__repetitions),
1431-
bool_typet{}}
1432-
{
1433-
}
1434-
1435-
const exprt &op() const
1436-
{
1437-
return op0();
1438-
}
1439-
1440-
exprt &op()
1441-
{
1442-
return op0();
1443-
}
1444-
1445-
// The number of repetitions must be a constant after elaboration.
1446-
const constant_exprt &repetitions() const
1447-
{
1448-
return static_cast<const constant_exprt &>(op1());
1449-
}
1450-
1451-
constant_exprt &repetitions()
1493+
std::move(__op),
1494+
std::move(__repetitions)}
14521495
{
1453-
return static_cast<constant_exprt &>(op1());
14541496
}
1455-
1456-
protected:
1457-
using binary_exprt::op0;
1458-
using binary_exprt::op1;
14591497
};
14601498

14611499
inline const sva_sequence_non_consecutive_repetition_exprt &

0 commit comments

Comments
 (0)