Skip to content

Commit 51f61c2

Browse files
committed
move bit-level BMC to property_checker
This moves the bit-level BMC engine invocation from ebmc_baset to property_checker(...).
1 parent 0fc2ab6 commit 51f61c2

File tree

3 files changed

+277
-13
lines changed

3 files changed

+277
-13
lines changed

src/ebmc/ebmc_parse_options.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -304,14 +304,11 @@ int ebmc_parse_optionst::doit()
304304
if(cmdline.isset("compute-ct"))
305305
return ebmc_base.do_compute_ct();
306306

307-
if(cmdline.isset("aig") || cmdline.isset("dimacs"))
308-
return ebmc_base.do_bit_level_bmc();
309-
else
310-
return property_checker(
311-
cmdline,
312-
ebmc_base.transition_system,
313-
ebmc_base.properties,
314-
ui_message_handler);
307+
return property_checker(
308+
cmdline,
309+
ebmc_base.transition_system,
310+
ebmc_base.properties,
311+
ui_message_handler);
315312
}
316313
}
317314
catch(const ebmc_errort &ebmc_error)

src/ebmc/property_checker.cpp

Lines changed: 271 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,20 @@ Author: Daniel Kroening, [email protected]
1010

1111
#include <util/string2int.h>
1212

13+
#include <solvers/sat/satcheck.h>
14+
#include <trans-netlist/trans_to_netlist.h>
15+
#include <trans-netlist/trans_trace_netlist.h>
16+
#include <trans-netlist/unwind_netlist.h>
17+
1318
#include "bmc.h"
19+
#include "dimacs_writer.h"
1420
#include "ebmc_error.h"
1521
#include "ebmc_solver_factory.h"
22+
#include "output_file.h"
1623
#include "report_results.h"
1724

25+
#include <iostream>
26+
1827
int word_level_bmc(
1928
const cmdlinet &cmdline,
2029
const transition_systemt &transition_system,
@@ -112,13 +121,271 @@ int word_level_bmc(
112121
return result;
113122
}
114123

124+
int finish_bit_level_bmc(
125+
std::size_t bound,
126+
const bmc_mapt &bmc_map,
127+
propt &solver,
128+
const transition_systemt &transition_system,
129+
ebmc_propertiest &properties,
130+
message_handlert &message_handler)
131+
{
132+
auto sat_start_time = std::chrono::steady_clock::now();
133+
134+
messaget message{message_handler};
135+
message.status() << "Solving with " << solver.solver_text() << messaget::eom;
136+
137+
for(auto &property : properties.properties)
138+
{
139+
if(property.is_disabled())
140+
continue;
141+
142+
if(property.is_failure())
143+
continue;
144+
145+
if(property.is_assumed())
146+
continue;
147+
148+
message.status() << "Checking " << property.name << messaget::eom;
149+
150+
literalt property_literal = !solver.land(property.timeframe_literals);
151+
152+
bvt assumptions;
153+
assumptions.push_back(property_literal);
154+
155+
propt::resultt prop_result = solver.prop_solve(assumptions);
156+
157+
switch(prop_result)
158+
{
159+
case propt::resultt::P_SATISFIABLE:
160+
{
161+
property.refuted();
162+
message.result() << "SAT: counterexample found" << messaget::eom;
163+
164+
namespacet ns{transition_system.symbol_table};
165+
166+
property.witness_trace =
167+
compute_trans_trace(property.timeframe_literals, bmc_map, solver, ns);
168+
}
169+
break;
170+
171+
case propt::resultt::P_UNSATISFIABLE:
172+
message.result() << "UNSAT: No counterexample found within bound"
173+
<< messaget::eom;
174+
property.proved_with_bound(bound);
175+
break;
176+
177+
case propt::resultt::P_ERROR:
178+
message.error() << "Error from decision procedure" << messaget::eom;
179+
return 2;
180+
181+
default:
182+
message.error() << "Unexpected result from decision procedure"
183+
<< messaget::eom;
184+
return 1;
185+
}
186+
}
187+
188+
auto sat_stop_time = std::chrono::steady_clock::now();
189+
190+
message.statistics()
191+
<< "Solver time: "
192+
<< std::chrono::duration<double>(sat_stop_time - sat_start_time).count()
193+
<< messaget::eom;
194+
195+
return properties.exit_code();
196+
}
197+
198+
int bit_level_bmc(
199+
cnft &solver,
200+
bool convert_only,
201+
const cmdlinet &cmdline,
202+
transition_systemt &transition_system,
203+
ebmc_propertiest &properties,
204+
message_handlert &message_handler)
205+
{
206+
messaget message{message_handler};
207+
208+
std::size_t bound;
209+
210+
if(cmdline.isset("bound"))
211+
{
212+
bound = unsafe_string2unsigned(cmdline.get_value("bound"));
213+
}
214+
else
215+
{
216+
message.warning() << "using default bound 1" << messaget::eom;
217+
bound = 1;
218+
}
219+
220+
int result;
221+
222+
try
223+
{
224+
bmc_mapt bmc_map;
225+
226+
if(!convert_only)
227+
if(properties.properties.empty())
228+
throw "no properties";
229+
230+
// make net-list
231+
netlistt netlist;
232+
message.status() << "Generating Netlist" << messaget::eom;
233+
234+
convert_trans_to_netlist(
235+
transition_system.symbol_table,
236+
transition_system.main_symbol->name,
237+
properties.make_property_map(),
238+
netlist,
239+
message.get_message_handler());
240+
241+
message.statistics() << "Latches: " << netlist.var_map.latches.size()
242+
<< ", nodes: " << netlist.number_of_nodes()
243+
<< messaget::eom;
244+
245+
messaget message{message_handler};
246+
message.status() << "Unwinding Netlist" << messaget::eom;
247+
248+
bmc_map.map_timeframes(netlist, bound + 1, solver);
249+
250+
::unwind(netlist, bmc_map, message, solver);
251+
252+
const namespacet ns(transition_system.symbol_table);
253+
254+
// convert the properties
255+
for(auto &property : properties.properties)
256+
{
257+
if(property.is_disabled())
258+
continue;
259+
260+
if(!netlist_bmc_supports_property(property.normalized_expr))
261+
{
262+
property.failure("property not supported by netlist BMC engine");
263+
continue;
264+
}
265+
266+
// look up the property in the netlist
267+
auto netlist_property = netlist.properties.find(property.identifier);
268+
CHECK_RETURN(netlist_property != netlist.properties.end());
269+
270+
::unwind_property(
271+
netlist_property->second, bmc_map, property.timeframe_literals);
272+
273+
if(property.is_assumed())
274+
{
275+
// force these to be true
276+
for(auto l : property.timeframe_literals)
277+
solver.l_set_to(l, true);
278+
}
279+
else
280+
{
281+
// freeze for incremental usage
282+
for(auto l : property.timeframe_literals)
283+
solver.set_frozen(l);
284+
}
285+
}
286+
287+
if(convert_only)
288+
result = 0;
289+
else
290+
{
291+
result = finish_bit_level_bmc(
292+
bound, bmc_map, solver, transition_system, properties, message_handler);
293+
report_results(cmdline, properties, ns, message_handler);
294+
}
295+
}
296+
297+
catch(const char *e)
298+
{
299+
messaget message{message_handler};
300+
message.error() << e << messaget::eom;
301+
return 10;
302+
}
303+
304+
catch(const std::string &e)
305+
{
306+
messaget message{message_handler};
307+
message.error() << e << messaget::eom;
308+
return 10;
309+
}
310+
311+
catch(int)
312+
{
313+
return 10;
314+
}
315+
316+
return result;
317+
}
318+
319+
int bit_level_bmc(
320+
const cmdlinet &cmdline,
321+
transition_systemt &transition_system,
322+
ebmc_propertiest &properties,
323+
message_handlert &message_handler)
324+
{
325+
if(cmdline.isset("dimacs"))
326+
{
327+
if(cmdline.isset("outfile"))
328+
{
329+
auto outfile = output_filet{cmdline.get_value("outfile")};
330+
331+
messaget message{message_handler};
332+
message.status() << "Writing DIMACS CNF to `" << outfile.name() << "'"
333+
<< messaget::eom;
334+
335+
dimacs_cnf_writert dimacs_cnf_writer{outfile.stream(), message_handler};
336+
337+
return bit_level_bmc(
338+
dimacs_cnf_writer,
339+
true,
340+
cmdline,
341+
transition_system,
342+
properties,
343+
message_handler);
344+
}
345+
else
346+
{
347+
dimacs_cnf_writert dimacs_cnf_writer{std::cout, message_handler};
348+
349+
return bit_level_bmc(
350+
dimacs_cnf_writer,
351+
true,
352+
cmdline,
353+
transition_system,
354+
properties,
355+
message_handler);
356+
}
357+
}
358+
else
359+
{
360+
if(cmdline.isset("outfile"))
361+
throw ebmc_errort()
362+
<< "Cannot write to outfile without file format option";
363+
364+
satcheckt satcheck{message_handler};
365+
366+
messaget message{message_handler};
367+
message.status() << "Using " << satcheck.solver_text() << messaget::eom;
368+
369+
return bit_level_bmc(
370+
satcheck, false, cmdline, transition_system, properties, message_handler);
371+
}
372+
}
373+
115374
int property_checker(
116375
const cmdlinet &cmdline,
117-
const transition_systemt &transition_system,
376+
transition_systemt &transition_system,
118377
ebmc_propertiest &properties,
119378
message_handlert &message_handler)
120379
{
121-
// default engine is word-level BMC
122-
return word_level_bmc(
123-
cmdline, transition_system, properties, message_handler);
380+
if(cmdline.isset("aig") || cmdline.isset("dimacs"))
381+
{
382+
return bit_level_bmc(
383+
cmdline, transition_system, properties, message_handler);
384+
}
385+
else
386+
{
387+
// default engine is word-level BMC
388+
return word_level_bmc(
389+
cmdline, transition_system, properties, message_handler);
390+
}
124391
}

src/ebmc/property_checker.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Author: Daniel Kroening, [email protected]
1414

1515
int property_checker(
1616
const cmdlinet &,
17-
const transition_systemt &,
17+
transition_systemt &,
1818
ebmc_propertiest &,
1919
message_handlert &);
2020

0 commit comments

Comments
 (0)