Skip to content

Commit e8e4c55

Browse files
authored
Merge pull request #1030 from diffblue/sequence_repetition5
SVA: consecutive repetition with range
2 parents 8254d29 + 4d94960 commit e8e4c55

File tree

8 files changed

+196
-17
lines changed

8 files changed

+196
-17
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
sequence_repetition5.sv
3+
--bound 20
4+
^\[.*\] main\.pulse ##1 \!main\.pulse \[\*1:9\] ##1 main.pulse: PROVED up to bound 20$
5+
^\[.*\] main\.pulse ##1 \!main\.pulse \[\*1:8\] ##1 main.pulse: REFUTED$
6+
^EXIT=10$
7+
^SIGNAL=0$
8+
--
9+
^warning: ignoring
10+
--
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module main(input clk, input data);
2+
3+
reg [31:0] x = 0;
4+
5+
always_ff @(posedge clk)
6+
if(x == 9 || (x >= 1 && data))
7+
x = 0;
8+
else
9+
x++;
10+
11+
wire pulse = x == 0;
12+
13+
// should pass
14+
initial p0: assert property (pulse ##1 !pulse[*1:9] ##1 pulse);
15+
16+
// should fail
17+
initial p1: assert property (pulse ##1 !pulse[*1:8] ##1 pulse);
18+
19+
endmodule

src/verilog/expr2verilog.cpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,38 @@ expr2verilogt::resultt expr2verilogt::convert_sva_binary_repetition(
582582

583583
/*******************************************************************\
584584
585+
Function: expr2verilogt::convert_sva_sequence_consecutive_repetition
586+
587+
Inputs:
588+
589+
Outputs:
590+
591+
Purpose:
592+
593+
\*******************************************************************/
594+
595+
expr2verilogt::resultt
596+
expr2verilogt::convert_sva_sequence_consecutive_repetition(
597+
const sva_sequence_consecutive_repetition_exprt &expr)
598+
{
599+
auto op = convert_rec(expr.op());
600+
if(op.p == verilog_precedencet::MIN)
601+
op.s = "(" + op.s + ")";
602+
603+
std::string dest = op.s + " [*" + convert_rec(expr.from()).s;
604+
605+
if(expr.is_unbounded())
606+
dest += ":$";
607+
else if(expr.to().is_not_nil())
608+
dest += ":" + convert_rec(expr.to()).s;
609+
610+
dest += ']';
611+
612+
return {verilog_precedencet::MIN, dest};
613+
}
614+
615+
/*******************************************************************\
616+
585617
Function: expr2verilogt::convert_sva_abort
586618
587619
Inputs:
@@ -1797,9 +1829,8 @@ expr2verilogt::resultt expr2verilogt::convert_rec(const exprt &src)
17971829
// not sure about precedence
17981830

17991831
else if(src.id() == ID_sva_sequence_consecutive_repetition)
1800-
return precedence = verilog_precedencet::MIN,
1801-
convert_sva_binary_repetition("[*", to_binary_expr(src));
1802-
// not sure about precedence
1832+
return convert_sva_sequence_consecutive_repetition(
1833+
to_sva_sequence_consecutive_repetition_expr(src));
18031834

18041835
else if(src.id() == ID_sva_sequence_goto_repetition)
18051836
return precedence = verilog_precedencet::MIN,

src/verilog/expr2verilog_class.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class sva_abort_exprt;
1616
class sva_case_exprt;
1717
class sva_if_exprt;
1818
class sva_ranged_predicate_exprt;
19+
class sva_sequence_consecutive_repetition_exprt;
1920

2021
// Precedences (higher means binds more strongly).
2122
// Follows Table 11-2 in IEEE 1800-2017.
@@ -138,6 +139,9 @@ class expr2verilogt
138139
resultt
139140
convert_sva_binary_repetition(const std::string &name, const binary_exprt &);
140141

142+
resultt convert_sva_sequence_consecutive_repetition(
143+
const sva_sequence_consecutive_repetition_exprt &);
144+
141145
resultt convert_sva_abort(const std::string &name, const sva_abort_exprt &);
142146

143147
resultt

src/verilog/parser.y

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2653,7 +2653,15 @@ sequence_abbrev:
26532653

26542654
consecutive_repetition:
26552655
"[*" const_or_range_expression ']'
2656-
{ init($$, ID_sva_sequence_consecutive_repetition); mto($$, $2); }
2656+
{ init($$, ID_sva_sequence_consecutive_repetition);
2657+
if(stack_expr($2).id() == ID_sva_cycle_delay)
2658+
swapop($$, $2);
2659+
else
2660+
{
2661+
mto($$, $2);
2662+
stack_expr($$).add_to_operands(nil_exprt{});
2663+
}
2664+
}
26572665
| "[*" ']'
26582666
{ init($$, ID_sva_sequence_repetition_star); }
26592667
| "[+" ']'

src/verilog/sva_expr.cpp

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,50 @@ exprt sva_case_exprt::lowering() const
4141

4242
exprt sva_sequence_consecutive_repetition_exprt::lower() const
4343
{
44-
auto n = numeric_cast_v<mp_integer>(to_constant_expr(rhs()));
45-
DATA_INVARIANT(n >= 1, "number of repetitions must be at least one");
44+
PRECONDITION(op().type().id() == ID_bool);
4645

47-
exprt result = lhs();
46+
if(to().is_nil())
47+
{
48+
// expand x[*n] into x ##1 x ##1 ...
49+
auto n = numeric_cast_v<mp_integer>(to_constant_expr(from()));
50+
DATA_INVARIANT(n >= 1, "number of repetitions must be at least one");
51+
52+
exprt result = op();
53+
54+
for(; n >= 2; --n)
55+
{
56+
auto cycle_delay =
57+
sva_cycle_delay_exprt{from_integer(1, integer_typet{}), op()};
58+
result = sva_sequence_concatenation_exprt{
59+
std::move(result), std::move(cycle_delay)};
60+
}
4861

49-
for(; n >= 2; --n)
62+
return result;
63+
}
64+
else if(is_unbounded())
5065
{
51-
auto cycle_delay =
52-
sva_cycle_delay_exprt{from_integer(1, integer_typet{}), lhs()};
53-
result = sva_sequence_concatenation_exprt{
54-
std::move(result), std::move(cycle_delay)};
66+
PRECONDITION(false);
5567
}
68+
else
69+
{
70+
// expand x[*a:b] into x[*a] or x[*a+1] or ... or x[*b]
71+
auto from_int = numeric_cast_v<mp_integer>(to_constant_expr(from()));
72+
auto to_int = numeric_cast_v<mp_integer>(to_constant_expr(to()));
5673

57-
return result;
74+
DATA_INVARIANT(from_int >= 1, "number of repetitions must be at least one");
75+
DATA_INVARIANT(
76+
to_int >= from_int, "number of repetitions must be interval");
77+
78+
exprt result = sva_sequence_consecutive_repetition_exprt{op(), from()};
79+
80+
for(mp_integer n = from_int + 1; n <= to_int; ++n)
81+
{
82+
auto n_expr = from_integer(n, integer_typet{});
83+
result = sva_or_exprt{
84+
std::move(result),
85+
sva_sequence_consecutive_repetition_exprt{op(), n_expr}};
86+
}
87+
88+
return result;
89+
}
5890
}

src/verilog/sva_expr.h

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,14 +1155,75 @@ inline sva_case_exprt &to_sva_case_expr(exprt &expr)
11551155
return static_cast<sva_case_exprt &>(expr);
11561156
}
11571157

1158-
class sva_sequence_consecutive_repetition_exprt : public binary_predicate_exprt
1158+
class sva_sequence_consecutive_repetition_exprt : public ternary_exprt
11591159
{
11601160
public:
1161+
sva_sequence_consecutive_repetition_exprt(exprt __op, exprt __repetitions)
1162+
: ternary_exprt{
1163+
ID_sva_sequence_consecutive_repetition,
1164+
std::move(__op),
1165+
std::move(__repetitions),
1166+
nil_exprt{},
1167+
bool_typet{}}
1168+
{
1169+
}
1170+
1171+
sva_sequence_consecutive_repetition_exprt(
1172+
exprt __op,
1173+
exprt __from,
1174+
exprt __to)
1175+
: ternary_exprt{
1176+
ID_sva_sequence_consecutive_repetition,
1177+
std::move(__op),
1178+
std::move(__from),
1179+
std::move(__to),
1180+
bool_typet{}}
1181+
{
1182+
}
1183+
11611184
exprt lower() const;
11621185

1186+
const exprt &op() const
1187+
{
1188+
return op0();
1189+
}
1190+
1191+
exprt &op()
1192+
{
1193+
return op0();
1194+
}
1195+
1196+
const exprt &from() const
1197+
{
1198+
return op1();
1199+
}
1200+
1201+
exprt &from()
1202+
{
1203+
return op1();
1204+
}
1205+
1206+
// may be nil (just the singleton 'from') or
1207+
// infinity (half-open interval starting at 'from')
1208+
const exprt &to() const
1209+
{
1210+
return op2();
1211+
}
1212+
1213+
exprt &to()
1214+
{
1215+
return op2();
1216+
}
1217+
1218+
bool is_unbounded() const
1219+
{
1220+
return to().id() == ID_infinity;
1221+
}
1222+
11631223
protected:
1164-
using binary_predicate_exprt::op0;
1165-
using binary_predicate_exprt::op1;
1224+
using ternary_exprt::op0;
1225+
using ternary_exprt::op1;
1226+
using ternary_exprt::op2;
11661227
};
11671228

11681229
inline const sva_sequence_consecutive_repetition_exprt &

src/verilog/verilog_typecheck_sva.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ exprt verilog_typecheck_exprt::convert_binary_sva(binary_exprt expr)
137137
return std::move(expr);
138138
}
139139
else if(
140-
expr.id() == ID_sva_sequence_consecutive_repetition ||
141140
expr.id() == ID_sva_sequence_non_consecutive_repetition ||
142141
expr.id() == ID_sva_sequence_goto_repetition)
143142
{
@@ -208,6 +207,21 @@ exprt verilog_typecheck_exprt::convert_ternary_sva(ternary_exprt expr)
208207

209208
return std::move(expr);
210209
}
210+
else if(expr.id() == ID_sva_sequence_consecutive_repetition) // x[*1:2]
211+
{
212+
auto &repetition = to_sva_sequence_consecutive_repetition_expr(expr);
213+
214+
convert_sva(repetition.op());
215+
make_boolean(repetition.op());
216+
217+
convert_expr(repetition.from());
218+
219+
if(repetition.to().is_not_nil())
220+
convert_expr(repetition.to());
221+
222+
expr.type() = bool_typet{};
223+
return std::move(expr);
224+
}
211225
else if(
212226
expr.id() == ID_sva_eventually || expr.id() == ID_sva_ranged_s_eventually ||
213227
expr.id() == ID_sva_s_always || expr.id() == ID_sva_ranged_always)

0 commit comments

Comments
 (0)