Skip to content

Commit 4abd0a3

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 0a1c5ce commit 4abd0a3

File tree

4 files changed

+58
-27
lines changed

4 files changed

+58
-27
lines changed

src/trans-word-level/sequence.cpp

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Author: Daniel Kroening, [email protected]
99
#include "sequence.h"
1010

1111
#include <util/arith_tools.h>
12+
//#include <util/ebmc_util.h>
13+
//#include <util/std_expr.h>
1214

1315
#include <ebmc/ebmc_error.h>
1416
#include <temporal-logic/temporal_logic.h>
@@ -18,6 +20,40 @@ Author: Daniel Kroening, [email protected]
1820
#include "obligations.h"
1921
#include "property.h"
2022

23+
exprt sequence_count_condition(
24+
const sva_sequence_repetition_exprt &expr,
25+
const exprt &counter)
26+
{
27+
if(expr.is_range())
28+
{
29+
// number of repetitions inside a range
30+
auto from = numeric_cast_v<mp_integer>(expr.from());
31+
32+
if(expr.is_unbounded())
33+
{
34+
return binary_relation_exprt{
35+
counter, ID_ge, from_integer(from, counter.type())};
36+
}
37+
else
38+
{
39+
auto to = numeric_cast_v<mp_integer>(expr.to());
40+
41+
return and_exprt{
42+
binary_relation_exprt{
43+
counter, ID_ge, from_integer(from, counter.type())},
44+
binary_relation_exprt{
45+
counter, ID_le, from_integer(to, counter.type())}};
46+
}
47+
}
48+
else
49+
{
50+
// fixed number of repetitions
51+
auto repetitions_int = numeric_cast_v<mp_integer>(expr.repetitions());
52+
53+
return equal_exprt{counter, from_integer(repetitions_int, counter.type())};
54+
}
55+
}
56+
2157
sequence_matchest instantiate_sequence(
2258
exprt expr,
2359
sva_sequence_semanticst semantics,
@@ -346,11 +382,8 @@ sequence_matchest instantiate_sequence(
346382
}
347383
else if(expr.id() == ID_sva_sequence_goto_repetition)
348384
{
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);
385+
auto &repetition = to_sva_sequence_goto_repetition_expr(expr);
386+
auto &condition = repetition.op();
354387

355388
sequence_matchest result;
356389

@@ -359,54 +392,47 @@ sequence_matchest instantiate_sequence(
359392
const auto bits = address_bits(no_timeframes);
360393
const auto zero = from_integer(0, unsignedbv_typet{bits});
361394
const auto one = from_integer(1, unsignedbv_typet{bits});
362-
const auto repetitions = from_integer(repetitions_int, zero.type());
363395
exprt matches = zero;
364396

365397
for(mp_integer u = t; u < no_timeframes; ++u)
366398
{
367399
// match of op in timeframe u?
368-
auto rec_op = instantiate(op, u, no_timeframes);
400+
auto rec_op = instantiate(condition, u, no_timeframes);
369401

370402
// add up
371403
matches = plus_exprt{matches, if_exprt{rec_op, one, zero}};
372404

373405
// We have a match for op[->n] if there is a match in timeframe
374406
// u and matches is n.
375-
result.emplace_back(
376-
u, and_exprt{rec_op, equal_exprt{matches, repetitions}});
407+
result.emplace_back(u, sequence_count_condition(repetition, matches));
377408
}
378409

379410
return result;
380411
}
381412
else if(expr.id() == ID_sva_sequence_non_consecutive_repetition)
382413
{
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);
414+
auto &repetition = to_sva_sequence_non_consecutive_repetition_expr(expr);
415+
auto &condition = repetition.op();
388416

389417
sequence_matchest result;
390418

391419
// We add up the number of matches of 'op' starting from
392420
// timeframe u, until the end of our unwinding.
393-
const auto bits =
394-
address_bits(std::max(no_timeframes, repetitions_int + 1));
421+
const auto bits = address_bits(no_timeframes);
395422
const auto zero = from_integer(0, unsignedbv_typet{bits});
396423
const auto one = from_integer(1, zero.type());
397-
const auto repetitions = from_integer(repetitions_int, zero.type());
398424
exprt matches = zero;
399425

400426
for(mp_integer u = t; u < no_timeframes; ++u)
401427
{
402428
// match of op in timeframe u?
403-
auto rec_op = instantiate(op, u, no_timeframes);
429+
auto rec_op = instantiate(condition, u, no_timeframes);
404430

405431
// add up
406432
matches = plus_exprt{matches, if_exprt{rec_op, one, zero}};
407433

408434
// We have a match for op[=n] if matches is n.
409-
result.emplace_back(u, equal_exprt{matches, repetitions});
435+
result.emplace_back(u, sequence_count_condition(repetition, matches));
410436
}
411437

412438
return result;

src/verilog/expr2verilog.cpp

Lines changed: 9 additions & 7 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 3 additions & 0 deletions
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)