Skip to content

Commit bae8701

Browse files
authored
Merge pull request #226 from diffblue/fix-lasso
ebmc: fix encoding of 'eventually'
2 parents a1b07c2 + c7ba2ed commit bae8701

File tree

7 files changed

+90
-30
lines changed

7 files changed

+90
-30
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
eventually2.sv
3+
--module main --bound 20
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// count up from 0 to 10, with option to reset
2+
3+
module main(input clk, input reset);
4+
5+
reg [7:0] counter;
6+
7+
initial counter = 0;
8+
9+
always @(posedge clk)
10+
if(reset)
11+
counter = 0;
12+
else if(counter != 10)
13+
counter = counter + 1;
14+
15+
// expected to pass for any bound
16+
p0: assert property (eventually (reset || counter == 10));
17+
18+
endmodule
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
eventually3.sv
3+
--module main --bound 11
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^\[main\.property\.p0\] always \(eventually main\.counter <= 5\): FAILURE$
7+
--
8+
^warning: ignoring
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module main(input clk);
2+
3+
reg [7:0] counter;
4+
5+
initial counter = 0;
6+
7+
always @(posedge clk)
8+
if(counter < 10)
9+
counter = counter + 1;
10+
else
11+
counter = 6;
12+
13+
// expected to fail with any bound greater or equal 11
14+
p0: assert property (eventually counter<=5);
15+
16+
endmodule

src/trans-word-level/instantiate_word_level.cpp

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -266,32 +266,36 @@ void wl_instantiatet::instantiate_rec(exprt &expr)
266266

267267
// The following needs to be satisfied for a counterexample
268268
// to Fp:
269-
// (1) No state up to the current state satisfies 'p'.
270-
// (2) The current state is equal to some earlier state.
269+
// (1) There is a loop from the current state i back to
270+
// some earlier state k < i.
271+
// (1) No state j with k<=k<=i on the lasso satisfies 'p'.
271272
//
272273
// We look backwards instead of forwards so that 'current'
273274
// is the last state of the counterexample trace.
275+
//
276+
// Note that this is trivially true when current is zero,
277+
// as a single state cannot demonstrate the loop.
274278

275-
if(current == 0)
276-
{
277-
// there is no counterexample to Fp with just one state
278-
expr = true_exprt();
279-
}
280-
else
281-
{
282-
exprt::operandst conjuncts = {lasso_symbol(current)};
279+
exprt::operandst conjuncts = {};
280+
const std::size_t i = current;
283281

284-
// save the current time frame, we'll change it
285-
save_currentt save_current(current);
282+
for(std::size_t k = 0; k < i; k++)
283+
{
284+
exprt::operandst disjuncts = {not_exprt(lasso_symbol(k, i))};
286285

287-
for(; current<no_timeframes; current++)
286+
for(std::size_t j = k; j <= i; j++)
288287
{
289-
conjuncts.push_back(not_exprt(p));
290-
instantiate_rec(conjuncts.back());
288+
// save the current time frame, we'll change it
289+
save_currentt save_current(current);
290+
current = j;
291+
disjuncts.push_back(p);
292+
instantiate_rec(disjuncts.back());
291293
}
292294

293-
expr = not_exprt(conjunction(conjuncts));
295+
conjuncts.push_back(disjunction(disjuncts));
294296
}
297+
298+
expr = conjunction(conjuncts);
295299
}
296300
else if(expr.id()==ID_sva_until ||
297301
expr.id()==ID_sva_s_until)

src/trans-word-level/property.cpp

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,13 @@ Function: states_equal
7878
\*******************************************************************/
7979

8080
exprt states_equal(
81-
std::size_t i,
8281
std::size_t k,
82+
std::size_t i,
8383
const std::vector<symbol_exprt> &variables_to_compare)
8484
{
85+
// We require k<i to avoid the symmetric constraints.
86+
PRECONDITION(k < i);
87+
8588
exprt::operandst conjuncts;
8689
conjuncts.reserve(variables_to_compare.size());
8790

@@ -107,9 +110,13 @@ Function: lasso_symbol
107110
108111
\*******************************************************************/
109112

110-
symbol_exprt lasso_symbol(std::size_t timeframe)
113+
symbol_exprt lasso_symbol(std::size_t k, std::size_t i)
111114
{
112-
irep_idt lasso_identifier = "lasso::" + std::to_string(timeframe);
115+
// True when states i and k are equal.
116+
// We require k<i to avoid the symmetric constraints.
117+
PRECONDITION(k < i);
118+
irep_idt lasso_identifier =
119+
"lasso::" + std::to_string(i) + "-back-to-" + std::to_string(k);
113120
return symbol_exprt(lasso_identifier, bool_typet());
114121
}
115122

@@ -135,10 +142,10 @@ void lasso_constraints(
135142
// is an identical state s_k = s_i with k<i.
136143
// "Identical" is defined as "state variables and top-level inputs match".
137144

138-
// gather the state variables
139145
std::vector<symbol_exprt> variables_to_compare;
140-
const symbol_tablet &symbol_table = ns.get_symbol_table();
141146

147+
// Gather the state variables.
148+
const symbol_tablet &symbol_table = ns.get_symbol_table();
142149
auto lower = symbol_table.symbol_module_map.lower_bound(module_identifier);
143150
auto upper = symbol_table.symbol_module_map.upper_bound(module_identifier);
144151

@@ -168,15 +175,13 @@ void lasso_constraints(
168175

169176
for(std::size_t i = 1; i < no_timeframes; i++)
170177
{
171-
// Is there a loop back to any time frame k with k<i?
172-
exprt::operandst disjuncts;
173-
disjuncts.reserve(i);
174-
175178
for(std::size_t k = 0; k < i; k++)
176-
disjuncts.push_back(states_equal(k, i, variables_to_compare));
177-
178-
auto lasso_symbol = ::lasso_symbol(i);
179-
solver.set_to_true(equal_exprt(lasso_symbol, disjunction(disjuncts)));
179+
{
180+
// Is there a loop back from time frame i back to time frame k?
181+
auto lasso_symbol = ::lasso_symbol(k, i);
182+
auto equal = states_equal(k, i, variables_to_compare);
183+
solver.set_to_true(equal_exprt(lasso_symbol, equal));
184+
}
180185
}
181186
}
182187

src/trans-word-level/property.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ void lasso_constraints(
3131
const namespacet &,
3232
const irep_idt &module_identifier);
3333

34-
symbol_exprt lasso_symbol(std::size_t);
34+
/// Is there a loop from i back to k?
35+
/// Precondition: k<i
36+
symbol_exprt lasso_symbol(std::size_t k, std::size_t i);
3537

3638
/// Returns true iff the given property requires lasso constraints.
3739
bool requires_lasso_constraints(const exprt &);

0 commit comments

Comments
 (0)