Skip to content

Commit 4cb485d

Browse files
committed
BMC: implement weak/strong sequences
This implements strong semantics for SVA sequences in the word-level BMC engine. Strong semantics are used with an explicit strong(...) operator or for SVA cover. The difference between weak and strong semantics arises in BMC when the sequence reaches the end of the unwinding: using weak semantics, the sequence matches, whereas using strong semantics the sequence does not.
1 parent 831cc43 commit 4cb485d

14 files changed

+191
-67
lines changed

CHANGELOG

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* SystemVerilog: within
1010
* SystemVerilog: bugfix for |-> and |=>
1111
* SystemVerilog: bugfix for SVA sequence and
12+
* SystemVerilog: strong/weak sequence semantics
1213
* Verilog: 'dx, 'dz
1314
* SMV: LTL V operator, xnor operator
1415
* SMV: word types and operators

regression/verilog/SVA/cover_sequence2.desc

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
KNOWNBUG
1+
CORE
22
cover_sequence2.sv
3-
--bound 2
4-
^\[main\.p0\] cover \(main\.x == 2 ##1 main\.x == 3 ##1 main\.x == 100\): PROVED$
5-
^\[main\.p1\] cover \(main\.x == 98 ##1 main\.x == 99 ##1 main\.x == 100\): REFUTED up to bound 2$
3+
--bound 5
4+
^\[main\.p0\] cover \(main\.x == 2 ##1 main\.x == 3 ##1 main\.x == 100\): REFUTED up to bound 5$
5+
^\[main\.p1\] cover \(main\.x == 98 ##1 main\.x == 99 ##1 main\.x == 100\): REFUTED up to bound 5$
6+
^\[main\.p2\] cover \(main\.x == 3 ##1 main\.x == 4 ##1 main\.x == 5\): PROVED$
7+
^\[main\.p3\] cover \(main\.x == 4 ##1 main\.x == 5 ##1 main\.x == 6\): REFUTED up to bound 5$
68
^EXIT=10$
79
^SIGNAL=0$
810
--
911
^warning: ignoring
1012
--
11-
Cover property p0 cannot ever hold, but is shown proven when using a small bound.
+9-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
module main(input clk);
22

33
// count up
4-
reg [7:0] x = 0;
4+
int x = 0;
55

6-
always @(posedge clk)
6+
always_ff @(posedge clk)
77
x++;
88

99
// expected to fail
1010
p0: cover property (x==2 ##1 x==3 ##1 x==100);
1111

12-
// expected to fail until bound reaches 100
12+
// expected to fail until x reaches 100
1313
p1: cover property (x==98 ##1 x==99 ##1 x==100);
1414

15+
// expected to pass once x reaches 5
16+
p2: cover property (x==3 ##1 x==4 ##1 x==5);
17+
18+
// expected to pass once x reaches 6
19+
p3: cover property (x==4 ##1 x==5 ##1 x==6);
20+
1521
endmodule
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
cover_sequence3.sv
3+
--bound 3
4+
^\[main\.p0\] cover \(1 \[\*10\]\): REFUTED up to bound 3$
5+
^\[main\.p1\] cover \(1 \[\*4:10\]\): PROVED$
6+
^\[main\.p2\] cover \(1 \[\*5:10\]\): REFUTED up to bound 3$
7+
^EXIT=10$
8+
^SIGNAL=0$
9+
--
10+
^warning: ignoring
11+
--
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module main(input clk);
2+
3+
// count up
4+
int x = 0;
5+
6+
always_ff @(posedge clk)
7+
x++;
8+
9+
// passes with bound >=9
10+
p0: cover property (1[*10]);
11+
12+
// passes with bound >=3
13+
p1: cover property (1[*4:10]);
14+
15+
// passes with bound >=4
16+
p2: cover property (1[*5:10]);
17+
18+
endmodule
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
KNOWNBUG
2+
cover_sequence4.sv
3+
--bound 3
4+
^\[main\.p0\] cover \(1 \[=10\]\): REFUTED up to bound 3$
5+
^\[main\.p1\] cover \(1 \[=4:10\]\): PROVED$
6+
^\[main\.p2\] cover \(1 \[=5:10\]\): REFUTED up to bound 3$
7+
^EXIT=10$
8+
^SIGNAL=0$
9+
--
10+
^warning: ignoring
11+
--
12+
Implementation of [=x:y] is missing.
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module main(input clk);
2+
3+
// count up
4+
int x = 0;
5+
6+
always_ff @(posedge clk)
7+
x++;
8+
9+
// passes with bound >=9
10+
p0: cover property (1[=10]);
11+
12+
// passes with bound >=3
13+
p1: cover property (1[=4:10]);
14+
15+
// passes with bound >=4
16+
p2: cover property (1[=5:10]);
17+
18+
endmodule

regression/verilog/SVA/sequence2.desc

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
KNOWNBUG
1+
CORE
22
sequence2.sv
3-
--bound 10 --numbered-trace
4-
^\[main\.p0] ##\[0:\$\] main\.x == 10: PROVED up to bound 10$
5-
^\[main\.p1] ##\[0:\$\] main\.x == 10: REFUTED$
3+
--bound 10
4+
^\[main\.p0] weak\(##\[0:\$\] main\.x == 10\): PROVED up to bound 10$
5+
^\[main\.p1] strong\(##\[0:\$\] main\.x == 10\): REFUTED$
66
^EXIT=10$
77
^SIGNAL=0$
88
--
99
^warning: ignoring
1010
--
11-
strong(...) is missing.

regression/verilog/SVA/sequence3.desc

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
KNOWNBUG
1+
CORE
22
sequence3.sv
33
--bound 20 --numbered-trace
4-
^\[main\.p0\] ##\[\*\] main\.x == 6: REFUTED$
5-
^\[main\.p1\] ##\[\*\] main\.x == 5: PROVED up to bound 20$
6-
^\[main\.p2\] ##\[\+\] main\.x == 0: REFUTED$
7-
^\[main\.p3\] ##\[\+\] main\.x == 5: PROVED up to bound 20$
4+
^\[main\.p0\] strong\(##\[\*\] main\.x == 6\): REFUTED$
5+
^\[main\.p1\] strong\(##\[\*\] main\.x == 5\): PROVED up to bound 20$
6+
^\[main\.p2\] strong\(##\[\+\] main\.x == 0\): REFUTED$
7+
^\[main\.p3\] strong\(##\[\+\] main\.x == 5\): PROVED up to bound 20$
88
^EXIT=10$
99
^SIGNAL=0$
1010
--
1111
^warning: ignoring
1212
--
13-
strong(...) is missing

regression/verilog/SVA/strong1.desc

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
strong1.sv
3-
--bound 20
4-
^\[main\.p0\] strong\(##\[0:9\] main\.x == 100\): REFUTED$
3+
--bound 4
4+
^\[main\.p0\] strong\(##\[0:9\] main\.x == 5\): REFUTED$
55
^EXIT=10$
66
^SIGNAL=0$
77
--

regression/verilog/SVA/strong1.sv

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module main;
88
always @(posedge clk)
99
x<=x+1;
1010

11-
// fails
12-
initial p0: assert property (strong(##[0:9] x==100));
11+
// fails if bound is too low
12+
initial p0: assert property (strong(##[0:9] x==5));
1313

1414
endmodule

src/trans-word-level/property.cpp

+46-11
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,32 @@ bool bmc_supports_property(const exprt &expr)
140140

141141
/*******************************************************************\
142142
143+
Function: sva_sequence_semantics
144+
145+
Inputs:
146+
147+
Outputs:
148+
149+
Purpose:
150+
151+
\*******************************************************************/
152+
153+
static sva_sequence_semanticst sva_sequence_semantics(irep_idt id)
154+
{
155+
if(id == ID_sva_strong)
156+
return sva_sequence_semanticst::STRONG;
157+
else if(id == ID_sva_weak)
158+
return sva_sequence_semanticst::WEAK;
159+
else if(id == ID_sva_implicit_strong)
160+
return sva_sequence_semanticst::STRONG;
161+
else if(id == ID_sva_implicit_weak)
162+
return sva_sequence_semanticst::WEAK;
163+
else
164+
PRECONDITION(false);
165+
}
166+
167+
/*******************************************************************\
168+
143169
Function: property_obligations_rec
144170
145171
Inputs:
@@ -527,16 +553,17 @@ static obligationst property_obligations_rec(
527553
op.id() == ID_sva_strong || op.id() == ID_sva_weak ||
528554
op.id() == ID_sva_implicit_strong || op.id() == ID_sva_implicit_weak)
529555
{
530-
// The sequence must not match.
531556
auto &sequence = to_sva_sequence_property_expr_base(op).sequence();
557+
auto semantics = sva_sequence_semantics(op.id());
532558

533559
const auto matches =
534-
instantiate_sequence(sequence, current, no_timeframes);
560+
instantiate_sequence(sequence, semantics, current, no_timeframes);
535561

536562
obligationst obligations;
537563

538564
for(auto &match : matches)
539565
{
566+
// The sequence must not match.
540567
obligations.add(match.end_time, not_exprt{match.condition});
541568
}
542569

@@ -577,10 +604,13 @@ static obligationst property_obligations_rec(
577604
auto &implication = to_binary_expr(property_expr);
578605

579606
// The LHS is a sequence, the RHS is a property.
580-
// The implication must hold for _all_ matches on the LHS,
607+
// The implication must hold for _all_ (strong) matches on the LHS,
581608
// i.e., each pair of LHS match and RHS obligation yields an obligation.
582-
const auto lhs_match_points =
583-
instantiate_sequence(implication.lhs(), current, no_timeframes);
609+
const auto lhs_match_points = instantiate_sequence(
610+
implication.lhs(),
611+
sva_sequence_semanticst::STRONG,
612+
current,
613+
no_timeframes);
584614

585615
obligationst result;
586616

@@ -620,9 +650,12 @@ static obligationst property_obligations_rec(
620650
// the result is a property expression.
621651
auto &followed_by = to_sva_followed_by_expr(property_expr);
622652

623-
// get match points for LHS sequence
624-
auto matches =
625-
instantiate_sequence(followed_by.antecedent(), current, no_timeframes);
653+
// get (proper) match points for LHS sequence
654+
auto matches = instantiate_sequence(
655+
followed_by.antecedent(),
656+
sva_sequence_semanticst::STRONG,
657+
current,
658+
no_timeframes);
626659

627660
exprt::operandst disjuncts;
628661
mp_integer t = current;
@@ -660,12 +693,14 @@ static obligationst property_obligations_rec(
660693
property_expr.id() == ID_sva_implicit_strong ||
661694
property_expr.id() == ID_sva_implicit_weak)
662695
{
696+
// sequence expressions -- these may have multiple potential
697+
// match points, and evaluate to true if any of them matches
663698
auto &sequence =
664699
to_sva_sequence_property_expr_base(property_expr).sequence();
700+
auto semantics = sva_sequence_semantics(property_expr.id());
665701

666-
// sequence expressions -- these may have multiple potential
667-
// match points, and evaluate to true if any of them matches
668-
const auto matches = instantiate_sequence(sequence, current, no_timeframes);
702+
const auto matches =
703+
instantiate_sequence(sequence, semantics, current, no_timeframes);
669704
exprt::operandst disjuncts;
670705
disjuncts.reserve(matches.size());
671706
mp_integer max = current;

0 commit comments

Comments
 (0)