Skip to content

Commit 22418ab

Browse files
committed
property instantiation now returns largest timeframe used
The word-level property instantiation now returns the largest timeframe used, in addition to the instantiated property. This enables making the counterexample have the right length.
1 parent 8aeba7c commit 22418ab

File tree

4 files changed

+79
-120
lines changed

4 files changed

+79
-120
lines changed

regression/verilog/SVA/sequence1.desc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
KNOWNBUG
1+
CORE
22
sequence1.sv
33
--bound 20 --numbered-trace
4+
^\[main\.property\.1\] ##\[0:9\] main\.x == 100: REFUTED$
5+
^Counterexample with 10 states:$
6+
^main\.x@0 = 0$
7+
^main\.x@9 = 9$
48
^EXIT=10$
59
^SIGNAL=0$
610
--
711
^warning: ignoring
812
--
9-
The trace shown only has one state, but 10 are expected.

src/trans-word-level/instantiate_word_level.cpp

Lines changed: 65 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ class wl_instantiatet
7777
}
7878

7979
/// Instantiate the given expression for timeframe t
80-
[[nodiscard]] exprt operator()(exprt expr, const mp_integer &t) const
80+
[[nodiscard]] std::pair<mp_integer, exprt>
81+
operator()(exprt expr, const mp_integer &t) const
8182
{
8283
return instantiate_rec(std::move(expr), t);
8384
}
@@ -86,7 +87,8 @@ class wl_instantiatet
8687
const mp_integer &no_timeframes;
8788
const namespacet &ns;
8889

89-
[[nodiscard]] exprt instantiate_rec(exprt, const mp_integer &t) const;
90+
[[nodiscard]] std::pair<mp_integer, exprt>
91+
instantiate_rec(exprt, const mp_integer &t) const;
9092
[[nodiscard]] typet instantiate_rec(typet, const mp_integer &t) const;
9193
};
9294

@@ -123,18 +125,20 @@ Function: wl_instantiatet::instantiate_rec
123125
124126
\*******************************************************************/
125127

126-
exprt wl_instantiatet::instantiate_rec(exprt expr, const mp_integer &t) const
128+
std::pair<mp_integer, exprt>
129+
wl_instantiatet::instantiate_rec(exprt expr, const mp_integer &t) const
127130
{
128131
expr.type() = instantiate_rec(expr.type(), t);
129132

130133
if(expr.id() == ID_next_symbol)
131134
{
132135
expr.id(ID_symbol);
133-
return timeframe_symbol(t + 1, to_symbol_expr(std::move(expr)));
136+
auto u = t + 1;
137+
return {u, timeframe_symbol(u, to_symbol_expr(std::move(expr)))};
134138
}
135139
else if(expr.id() == ID_symbol)
136140
{
137-
return timeframe_symbol(t, to_symbol_expr(std::move(expr)));
141+
return {t, timeframe_symbol(t, to_symbol_expr(std::move(expr)))};
138142
}
139143
else if(expr.id()==ID_sva_cycle_delay) // ##[1:2] something
140144
{
@@ -150,7 +154,7 @@ exprt wl_instantiatet::instantiate_rec(exprt expr, const mp_integer &t) const
150154

151155
// Do we exceed the bound? Make it 'true'
152156
if(u >= no_timeframes)
153-
return true_exprt();
157+
return {no_timeframes - 1, true_exprt()};
154158
else
155159
return instantiate_rec(sva_cycle_delay_expr.op(), u);
156160
}
@@ -168,35 +172,29 @@ exprt wl_instantiatet::instantiate_rec(exprt expr, const mp_integer &t) const
168172
else if(to_integer_non_constant(sva_cycle_delay_expr.to(), to))
169173
throw "failed to convert sva_cycle_delay offsets";
170174

171-
// This is an 'or', and we let it fail if the bound is too small.
175+
auto lower = t + from;
176+
auto upper = t + to;
177+
178+
// Do we exceed the bound? Make it 'true'
179+
if(upper >= no_timeframes)
180+
return {no_timeframes - 1, true_exprt()};
172181

173182
exprt::operandst disjuncts;
174183

175-
for(mp_integer offset = from; offset < to; ++offset)
184+
for(mp_integer u = lower; u <= upper; ++u)
176185
{
177-
auto u = t + offset;
178-
179-
if(u >= no_timeframes)
180-
{
181-
}
182-
else
183-
{
184-
disjuncts.push_back(instantiate_rec(sva_cycle_delay_expr.op(), u));
185-
}
186+
disjuncts.push_back(
187+
instantiate_rec(sva_cycle_delay_expr.op(), u).second);
186188
}
187189

188-
return disjunction(disjuncts);
190+
return {upper, disjunction(disjuncts)};
189191
}
190192
}
191193
else if(expr.id()==ID_sva_sequence_concatenation)
192194
{
193195
// much like regular 'and'
194196
expr.id(ID_and);
195-
196-
for(auto &op : expr.operands())
197-
op = instantiate_rec(op, t);
198-
199-
return expr;
197+
return instantiate_rec(expr, t);
200198
}
201199
else if(expr.id()==ID_sva_always)
202200
{
@@ -206,10 +204,10 @@ exprt wl_instantiatet::instantiate_rec(exprt expr, const mp_integer &t) const
206204

207205
for(auto u = t; u < no_timeframes; ++u)
208206
{
209-
conjuncts.push_back(instantiate_rec(op, u));
207+
conjuncts.push_back(instantiate_rec(op, u).second);
210208
}
211209

212-
return conjunction(conjuncts);
210+
return {no_timeframes - 1, conjunction(conjuncts)};
213211
}
214212
else if(expr.id() == ID_X)
215213
{
@@ -220,7 +218,7 @@ exprt wl_instantiatet::instantiate_rec(exprt expr, const mp_integer &t) const
220218
return instantiate_rec(to_X_expr(expr).op(), next);
221219
}
222220
else
223-
return true_exprt(); // works on NNF only
221+
return {no_timeframes - 1, true_exprt()}; // works on NNF only
224222
}
225223
else if(expr.id() == ID_sva_eventually)
226224
{
@@ -238,14 +236,14 @@ exprt wl_instantiatet::instantiate_rec(exprt expr, const mp_integer &t) const
238236
// This is weak, and passes if any of the timeframes
239237
// does not exist.
240238
if(t + lower >= no_timeframes || t + upper >= no_timeframes)
241-
return true_exprt();
239+
return {no_timeframes - 1, true_exprt()};
242240

243241
exprt::operandst disjuncts = {};
244242

245243
for(mp_integer u = t + lower; u <= t + upper; ++u)
246-
disjuncts.push_back(instantiate_rec(op, u));
244+
disjuncts.push_back(instantiate_rec(op, u).second);
247245

248-
return disjunction(disjuncts);
246+
return {no_timeframes - 1, disjunction(disjuncts)};
249247
}
250248
else if(
251249
expr.id() == ID_sva_s_eventually || expr.id() == ID_F || expr.id() == ID_AF)
@@ -273,13 +271,13 @@ exprt wl_instantiatet::instantiate_rec(exprt expr, const mp_integer &t) const
273271

274272
for(mp_integer j = k; j <= i; ++j)
275273
{
276-
disjuncts.push_back(instantiate_rec(p, j));
274+
disjuncts.push_back(instantiate_rec(p, j).second);
277275
}
278276

279277
conjuncts.push_back(disjunction(disjuncts));
280278
}
281279

282-
return conjunction(conjuncts);
280+
return {no_timeframes - 1, conjunction(conjuncts)};
283281
}
284282
else if(expr.id()==ID_sva_until ||
285283
expr.id()==ID_sva_s_until)
@@ -292,19 +290,19 @@ exprt wl_instantiatet::instantiate_rec(exprt expr, const mp_integer &t) const
292290

293291
// we expand: p U q <=> q || (p && X(p U q))
294292
exprt tmp_q = to_binary_expr(expr).op1();
295-
tmp_q = instantiate_rec(tmp_q, t);
293+
tmp_q = instantiate_rec(tmp_q, t).second;
296294

297295
exprt expansion = to_binary_expr(expr).op0();
298-
expansion = instantiate_rec(expansion, t);
296+
expansion = instantiate_rec(expansion, t).second;
299297

300298
const auto next = t + 1;
301299

302300
if(next < no_timeframes)
303301
{
304-
expansion = and_exprt(expansion, instantiate_rec(expr, next));
302+
expansion = and_exprt(expansion, instantiate_rec(expr, next).second);
305303
}
306304

307-
return or_exprt(tmp_q, expansion);
305+
return {no_timeframes - 1, or_exprt(tmp_q, expansion)};
308306
}
309307
else if(expr.id()==ID_sva_until_with ||
310308
expr.id()==ID_sva_s_until_with)
@@ -335,7 +333,7 @@ exprt wl_instantiatet::instantiate_rec(exprt expr, const mp_integer &t) const
335333
if(ticks > t)
336334
{
337335
// return the 'default value' for the type
338-
return default_value(verilog_past.type());
336+
return {t, default_value(verilog_past.type())};
339337
}
340338
else
341339
{
@@ -344,9 +342,15 @@ exprt wl_instantiatet::instantiate_rec(exprt expr, const mp_integer &t) const
344342
}
345343
else
346344
{
345+
mp_integer max = t;
347346
for(auto &op : expr.operands())
348-
op = instantiate_rec(op, t);
349-
return expr;
347+
{
348+
auto tmp = instantiate_rec(op, t);
349+
op = tmp.second;
350+
max = std::max(max, tmp.first);
351+
}
352+
353+
return {max, expr};
350354
}
351355
}
352356

@@ -386,5 +390,27 @@ exprt instantiate(
386390
const namespacet &ns)
387391
{
388392
wl_instantiatet wl_instantiate(no_timeframes, ns);
389-
return wl_instantiate(expr, t);
393+
return wl_instantiate(expr, t).second;
394+
}
395+
396+
/*******************************************************************\
397+
398+
Function: instantiate_property
399+
400+
Inputs:
401+
402+
Outputs:
403+
404+
Purpose:
405+
406+
\*******************************************************************/
407+
408+
std::pair<mp_integer, exprt> instantiate_property(
409+
const exprt &expr,
410+
const mp_integer &current,
411+
const mp_integer &no_timeframes,
412+
const namespacet &ns)
413+
{
414+
wl_instantiatet wl_instantiate(no_timeframes, ns);
415+
return wl_instantiate(expr, current);
390416
}

src/trans-word-level/instantiate_word_level.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ exprt instantiate(
2020
const mp_integer &no_timeframes,
2121
const namespacet &);
2222

23+
std::pair<mp_integer, exprt> instantiate_property(
24+
const exprt &,
25+
const mp_integer &current,
26+
const mp_integer &no_timeframes,
27+
const namespacet &);
28+
2329
std::string
2430
timeframe_identifier(const mp_integer &timeframe, const irep_idt &identifier);
2531

src/trans-word-level/property.cpp

Lines changed: 3 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -78,54 +78,6 @@ bool bmc_supports_property(const exprt &expr)
7878

7979
/*******************************************************************\
8080
81-
Function: max_property_obligation
82-
83-
Inputs:
84-
85-
Outputs:
86-
87-
Purpose:
88-
89-
\*******************************************************************/
90-
91-
static void property_obligations_rec(
92-
const exprt &property_expr,
93-
decision_proceduret &,
94-
const mp_integer &current,
95-
const mp_integer &no_timeframes,
96-
const namespacet &,
97-
std::map<mp_integer, exprt::operandst> &obligations);
98-
99-
static std::pair<mp_integer, exprt> max_property_obligation(
100-
const exprt &property_expr,
101-
decision_proceduret &solver,
102-
const mp_integer &current,
103-
const mp_integer &no_timeframes,
104-
const namespacet &ns)
105-
{
106-
// Generate one obligation, equivalent to the conjunction
107-
// for the maximum timeframe.
108-
109-
std::map<mp_integer, exprt::operandst> obligations;
110-
111-
property_obligations_rec(
112-
property_expr, solver, current, no_timeframes, ns, obligations);
113-
114-
exprt::operandst conjuncts;
115-
mp_integer max_timeframe = 0;
116-
117-
for(auto &[timeframe, exprs] : obligations)
118-
{
119-
max_timeframe = std::max(max_timeframe, timeframe);
120-
for(auto &conjunct : exprs)
121-
conjuncts.push_back(conjunct);
122-
}
123-
124-
return std::pair<mp_integer, exprt>{max_timeframe, conjunction(conjuncts)};
125-
}
126-
127-
/*******************************************************************\
128-
12981
Function: property_obligations_rec
13082
13183
Inputs:
@@ -146,17 +98,7 @@ static void property_obligations_rec(
14698
{
14799
PRECONDITION(current >= 0 && current < no_timeframes);
148100

149-
if(property_expr.id() == ID_X)
150-
{
151-
auto next = current + 1;
152-
if(next < no_timeframes)
153-
{
154-
auto &op = to_X_expr(property_expr).op();
155-
property_obligations_rec(
156-
op, solver, next, no_timeframes, ns, obligations);
157-
}
158-
}
159-
else if(
101+
if(
160102
property_expr.id() == ID_AG || property_expr.id() == ID_G ||
161103
property_expr.id() == ID_sva_always)
162104
{
@@ -254,28 +196,10 @@ static void property_obligations_rec(
254196
property_obligations_rec(
255197
op, solver, current, no_timeframes, ns, obligations);
256198
}
257-
else if(property_expr.id() == ID_or)
258-
{
259-
// generate one obligation, equivalent to the disjunction,
260-
// for the maximum timeframe
261-
mp_integer max_timeframe = 0;
262-
exprt::operandst disjuncts;
263-
264-
for(auto &op : to_or_expr(property_expr).operands())
265-
{
266-
auto obligation =
267-
max_property_obligation(op, solver, current, no_timeframes, ns);
268-
max_timeframe = std::max(max_timeframe, obligation.first);
269-
disjuncts.push_back(obligation.second);
270-
}
271-
272-
obligations[max_timeframe].push_back(disjunction(disjuncts));
273-
}
274199
else
275200
{
276-
// current state property
277-
exprt tmp = instantiate(property_expr, current, no_timeframes, ns);
278-
obligations[current].push_back(tmp);
201+
auto tmp = instantiate_property(property_expr, current, no_timeframes, ns);
202+
obligations[tmp.first].push_back(tmp.second);
279203
}
280204
}
281205

0 commit comments

Comments
 (0)