Skip to content

Commit bfa80bf

Browse files
committed
ebmc: force inputs to be equal when comparing states
The definition of a counterexample with a lasso requires two states to be equal. This must include the top-level inputs, or otherwise the lasso is not demonstrated.
1 parent d4ed123 commit bfa80bf

File tree

3 files changed

+56
-6
lines changed

3 files changed

+56
-6
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
eventually1.sv
3+
--module main --bound 1 --trace
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^Counterexample:$
7+
--
8+
^ main\.reset = 0$
9+
^warning: ignoring
10+
--
11+
The last state must be identical to the first state on the trace.
12+
In both states reset must be 1.
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
2+
3+
module main(input clk, input reset);
4+
5+
reg [3: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 fail, owing to reset
16+
p0: assert property (eventually counter == 10);
17+
18+
endmodule

src/trans-word-level/property.cpp

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,12 @@ Function: states_equal
8080
exprt states_equal(
8181
std::size_t i,
8282
std::size_t k,
83-
const std::vector<symbol_exprt> &state_vars)
83+
const std::vector<symbol_exprt> &variables_to_compare)
8484
{
8585
exprt::operandst conjuncts;
86-
conjuncts.reserve(state_vars.size());
86+
conjuncts.reserve(variables_to_compare.size());
8787

88-
for(auto &var : state_vars)
88+
for(auto &var : variables_to_compare)
8989
{
9090
auto i_var = timeframe_symbol(i, var);
9191
auto k_var = timeframe_symbol(k, var);
@@ -131,8 +131,12 @@ void lasso_constraints(
131131
const namespacet &ns,
132132
const irep_idt &module_identifier)
133133
{
134+
// The definition of a lasso to state s_i is that there
135+
// is an identical state s_k = s_i with k<i.
136+
// "Identical" is defined as "state variables and top-level inputs match".
137+
134138
// gather the state variables
135-
std::vector<symbol_exprt> state_vars;
139+
std::vector<symbol_exprt> variables_to_compare;
136140
const symbol_tablet &symbol_table = ns.get_symbol_table();
137141

138142
auto lower = symbol_table.symbol_module_map.lower_bound(module_identifier);
@@ -143,7 +147,23 @@ void lasso_constraints(
143147
const symbolt &symbol = ns.lookup(it->second);
144148

145149
if(symbol.is_state_var)
146-
state_vars.push_back(symbol.symbol_expr());
150+
variables_to_compare.push_back(symbol.symbol_expr());
151+
}
152+
153+
// gather the top-level inputs
154+
const auto &module_symbol = ns.lookup(module_identifier);
155+
DATA_INVARIANT(module_symbol.type.id() == ID_module, "expected a module");
156+
const auto &ports = module_symbol.type.find(ID_ports);
157+
158+
for(auto &port : static_cast<const exprt &>(ports).operands())
159+
{
160+
DATA_INVARIANT(port.id() == ID_symbol, "port must be a symbol");
161+
if(port.get_bool(ID_input) && !port.get_bool(ID_output))
162+
{
163+
symbol_exprt input_symbol(port.get(ID_identifier), port.type());
164+
input_symbol.add_source_location() = port.source_location();
165+
variables_to_compare.push_back(std::move(input_symbol));
166+
}
147167
}
148168

149169
for(std::size_t i = 1; i < no_timeframes; i++)
@@ -153,7 +173,7 @@ void lasso_constraints(
153173
disjuncts.reserve(i);
154174

155175
for(std::size_t k = 0; k < i; k++)
156-
disjuncts.push_back(states_equal(k, i, state_vars));
176+
disjuncts.push_back(states_equal(k, i, variables_to_compare));
157177

158178
auto lasso_symbol = ::lasso_symbol(i);
159179
solver.set_to_true(equal_exprt(lasso_symbol, disjunction(disjuncts)));

0 commit comments

Comments
 (0)