002a4f631dab7677bfafc43451ee9725b44f53ac
1 /********************* */
2 /*! \file aig_bitblaster.cpp
4 ** Top contributors (to current version):
5 ** Liana Hadarean, Mathias Preiner, Tim King
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8 ** in the top-level source directory and their institutional affiliations.
9 ** All rights reserved. See the file COPYING in the top-level source
10 ** directory for licensing information.\endverbatim
12 ** \brief AIG bitblaster.
17 #include "theory/bv/bitblast/aig_bitblaster.h"
19 #include "base/check.h"
20 #include "cvc4_private.h"
21 #include "options/bv_options.h"
22 #include "prop/cnf_stream.h"
23 #include "prop/sat_solver.h"
24 #include "prop/sat_solver_factory.h"
25 #include "smt/smt_statistics_registry.h"
30 #include "base/abc/abc.h"
31 #include "base/main/main.h"
32 #include "sat/cnf/cnf.h"
34 extern Aig_Man_t
* Abc_NtkToDar(Abc_Ntk_t
* pNtk
, int fExors
, int fRegisters
);
37 // Function is defined as static in ABC. Not sure how else to do this.
38 static inline int Cnf_Lit2Var(int Lit
)
40 return (Lit
& 1) ? -(Lit
>> 1) - 1 : (Lit
>> 1) + 1;
48 std::string toString
<Abc_Obj_t
*> (const std::vector
<Abc_Obj_t
*>& bits
) {
49 Unreachable() << "Don't know how to print AIG";
54 Abc_Obj_t
* mkTrue
<Abc_Obj_t
*>() {
55 return Abc_AigConst1(AigBitblaster::currentAigNtk());
59 Abc_Obj_t
* mkFalse
<Abc_Obj_t
*>() {
60 return Abc_ObjNot(mkTrue
<Abc_Obj_t
*>());
64 Abc_Obj_t
* mkNot
<Abc_Obj_t
*>(Abc_Obj_t
* a
) {
69 Abc_Obj_t
* mkOr
<Abc_Obj_t
*>(Abc_Obj_t
* a
, Abc_Obj_t
* b
) {
70 return Abc_AigOr(AigBitblaster::currentAigM(), a
, b
);
74 Abc_Obj_t
* mkOr
<Abc_Obj_t
*>(const std::vector
<Abc_Obj_t
*>& children
) {
75 Assert(children
.size());
76 if (children
.size() == 1)
79 Abc_Obj_t
* result
= children
[0];
80 for (unsigned i
= 1; i
< children
.size(); ++i
) {
81 result
= Abc_AigOr(AigBitblaster::currentAigM(), result
, children
[i
]);
88 Abc_Obj_t
* mkAnd
<Abc_Obj_t
*>(Abc_Obj_t
* a
, Abc_Obj_t
* b
) {
89 return Abc_AigAnd(AigBitblaster::currentAigM(), a
, b
);
93 Abc_Obj_t
* mkAnd
<Abc_Obj_t
*>(const std::vector
<Abc_Obj_t
*>& children
) {
94 Assert(children
.size());
95 if (children
.size() == 1)
98 Abc_Obj_t
* result
= children
[0];
99 for (unsigned i
= 1; i
< children
.size(); ++i
) {
100 result
= Abc_AigAnd(AigBitblaster::currentAigM(), result
, children
[i
]);
106 Abc_Obj_t
* mkXor
<Abc_Obj_t
*>(Abc_Obj_t
* a
, Abc_Obj_t
* b
) {
107 return Abc_AigXor(AigBitblaster::currentAigM(), a
, b
);
111 Abc_Obj_t
* mkIff
<Abc_Obj_t
*>(Abc_Obj_t
* a
, Abc_Obj_t
* b
) {
112 return mkNot(mkXor(a
, b
));
116 Abc_Obj_t
* mkIte
<Abc_Obj_t
*>(Abc_Obj_t
* cond
, Abc_Obj_t
* a
, Abc_Obj_t
* b
) {
117 return Abc_AigMux(AigBitblaster::currentAigM(), cond
, a
, b
);
120 thread_local Abc_Ntk_t
* AigBitblaster::s_abcAigNetwork
= nullptr;
122 Abc_Ntk_t
* AigBitblaster::currentAigNtk() {
123 if (!AigBitblaster::s_abcAigNetwork
) {
125 s_abcAigNetwork
= Abc_NtkAlloc( ABC_NTK_STRASH
, ABC_FUNC_AIG
, 1);
126 char pName
[] = "CVC5::theory::bv::AigNetwork";
127 s_abcAigNetwork
->pName
= Extra_UtilStrsav(pName
);
130 return s_abcAigNetwork
;
134 Abc_Aig_t
* AigBitblaster::currentAigM() {
135 return (Abc_Aig_t
*)(currentAigNtk()->pManFunc
);
138 AigBitblaster::AigBitblaster()
139 : TBitblaster
<Abc_Obj_t
*>(),
140 d_nullContext(new context::Context()),
143 d_aigOutputNode(NULL
),
146 prop::SatSolver
* solver
= nullptr;
147 switch (options::bvSatSolver())
149 case options::SatSolverMode::MINISAT
:
151 prop::BVSatSolverInterface
* minisat
=
152 prop::SatSolverFactory::createMinisat(
153 d_nullContext
.get(), smtStatisticsRegistry(), "AigBitblaster");
154 d_notify
.reset(new MinisatEmptyNotify());
155 minisat
->setNotify(d_notify
.get());
159 case options::SatSolverMode::CADICAL
:
160 solver
= prop::SatSolverFactory::createCadical(smtStatisticsRegistry(),
163 case options::SatSolverMode::CRYPTOMINISAT
:
164 solver
= prop::SatSolverFactory::createCryptoMinisat(
165 smtStatisticsRegistry(), "AigBitblaster");
167 case options::SatSolverMode::KISSAT
:
168 solver
= prop::SatSolverFactory::createKissat(smtStatisticsRegistry(),
171 default: CVC4_FATAL() << "Unknown SAT solver type";
173 d_satSolver
.reset(solver
);
176 AigBitblaster::~AigBitblaster() {}
178 Abc_Obj_t
* AigBitblaster::bbFormula(TNode node
) {
179 Assert(node
.getType().isBoolean());
180 Debug("bitvector-bitblast") << "AigBitblaster::bbFormula "<< node
<< "\n";
185 Abc_Obj_t
* result
= NULL
;
187 Debug("bitvector-aig") << "AigBitblaster::convertToAig " << node
<<"\n";
188 switch (node
.getKind()) {
191 result
= bbFormula(node
[0]);
192 for (unsigned i
= 1; i
< node
.getNumChildren(); ++i
) {
193 Abc_Obj_t
* child
= bbFormula(node
[i
]);
194 result
= mkAnd(result
, child
);
200 result
= bbFormula(node
[0]);
201 for (unsigned i
= 1; i
< node
.getNumChildren(); ++i
) {
202 Abc_Obj_t
* child
= bbFormula(node
[i
]);
203 result
= mkOr(result
, child
);
209 result
= bbFormula(node
[0]);
210 for (unsigned i
= 1; i
< node
.getNumChildren(); ++i
) {
211 Abc_Obj_t
* child
= bbFormula(node
[i
]);
212 result
= mkXor(result
, child
);
218 Assert(node
.getNumChildren() == 2);
219 Abc_Obj_t
* child1
= bbFormula(node
[0]);
220 Abc_Obj_t
* child2
= bbFormula(node
[1]);
222 result
= mkOr(mkNot(child1
), child2
);
227 Assert(node
.getNumChildren() == 3);
228 Abc_Obj_t
* a
= bbFormula(node
[0]);
229 Abc_Obj_t
* b
= bbFormula(node
[1]);
230 Abc_Obj_t
* c
= bbFormula(node
[2]);
231 result
= mkIte(a
, b
, c
);
236 Abc_Obj_t
* child1
= bbFormula(node
[0]);
237 result
= mkNot(child1
);
240 case kind::CONST_BOOLEAN
:
242 result
= node
.getConst
<bool>() ? mkTrue
<Abc_Obj_t
*>() : mkFalse
<Abc_Obj_t
*>();
247 if( node
[0].getType().isBoolean() ){
248 Assert(node
.getNumChildren() == 2);
249 Abc_Obj_t
* child1
= bbFormula(node
[0]);
250 Abc_Obj_t
* child2
= bbFormula(node
[1]);
252 result
= mkIff(child1
, child2
);
259 result
= mkInput(node
);
262 result
= getBBAtom(node
);
266 cacheAig(node
, result
);
267 Debug("bitvector-aig") << "AigBitblaster::bbFormula done " << node
<< " => " << result
<<"\n";
271 void AigBitblaster::bbAtom(TNode node
) {
272 if (hasBBAtom(node
)) {
276 Debug("bitvector-bitblast") << "Bitblasting atom " << node
<<"\n";
278 // the bitblasted definition of the atom
279 Node normalized
= Rewriter::rewrite(node
);
280 Abc_Obj_t
* atom_bb
= (d_atomBBStrategies
[normalized
.getKind()])(normalized
, this);
281 storeBBAtom(node
, atom_bb
);
282 Debug("bitvector-bitblast") << "Done bitblasting atom " << node
<<"\n";
285 void AigBitblaster::bbTerm(TNode node
, Bits
& bits
) {
286 if (hasBBTerm(node
)) {
287 getBBTerm(node
, bits
);
290 Assert(node
.getType().isBitVector());
292 Debug("bitvector-bitblast") << "Bitblasting term " << node
<<"\n";
293 d_termBBStrategies
[node
.getKind()] (node
, bits
, this);
295 Assert(bits
.size() == utils::getSize(node
));
296 storeBBTerm(node
, bits
);
300 void AigBitblaster::cacheAig(TNode node
, Abc_Obj_t
* aig
) {
301 Assert(!hasAig(node
));
302 d_aigCache
.insert(std::make_pair(node
, aig
));
304 bool AigBitblaster::hasAig(TNode node
) {
305 return d_aigCache
.find(node
) != d_aigCache
.end();
307 Abc_Obj_t
* AigBitblaster::getAig(TNode node
) {
308 Assert(hasAig(node
));
309 Debug("bitvector-aig") << "AigSimplifer::getAig " << node
<< " => " << d_aigCache
.find(node
)->second
<<"\n";
310 return d_aigCache
.find(node
)->second
;
313 void AigBitblaster::makeVariable(TNode node
, Bits
& bits
) {
315 for (unsigned i
= 0; i
< utils::getSize(node
); ++i
) {
316 Node bit
= utils::mkBitOf(node
, i
);
317 Abc_Obj_t
* input
= mkInput(bit
);
318 cacheAig(bit
, input
);
319 bits
.push_back(input
);
323 Abc_Obj_t
* AigBitblaster::mkInput(TNode input
) {
324 Assert(!hasInput(input
));
325 Assert(input
.getKind() == kind::BITVECTOR_BITOF
326 || (input
.getType().isBoolean() && input
.isVar()));
327 Abc_Obj_t
* aig_input
= Abc_NtkCreatePi(currentAigNtk());
328 // d_aigCache.insert(std::make_pair(input, aig_input));
329 d_nodeToAigInput
.insert(std::make_pair(input
, aig_input
));
330 Debug("bitvector-aig") << "AigSimplifer::mkInput " << input
<< " " << aig_input
<<"\n";
334 bool AigBitblaster::hasInput(TNode input
) {
335 return d_nodeToAigInput
.find(input
) != d_nodeToAigInput
.end();
338 bool AigBitblaster::solve(TNode node
) {
339 // setting output of network to be the query
340 Assert(d_aigOutputNode
== NULL
);
341 Abc_Obj_t
* query
= bbFormula(node
);
342 d_aigOutputNode
= Abc_NtkCreatePo(currentAigNtk());
343 Abc_ObjAddFanin(d_aigOutputNode
, query
);
346 convertToCnfAndAssert();
347 // no need to use abc anymore
349 TimerStat::CodeTimer
solveTimer(d_statistics
.d_solveTime
);
350 prop::SatValue result
= d_satSolver
->solve();
352 Assert(result
!= prop::SAT_VALUE_UNKNOWN
);
353 return result
== prop::SAT_VALUE_TRUE
;
357 void addAliases(Abc_Frame_t
* pAbc
);
359 void AigBitblaster::simplifyAig() {
360 TimerStat::CodeTimer
simpTimer(d_statistics
.d_simplificationTime
);
362 Abc_AigCleanup(currentAigM());
363 Assert(Abc_NtkCheck(currentAigNtk()));
365 const char* command
= options::bitvectorAigSimplifications().c_str();
366 Abc_Frame_t
* pAbc
= Abc_FrameGetGlobalFrame();
367 Abc_FrameSetCurrentNetwork(pAbc
, currentAigNtk());
370 if ( Cmd_CommandExecute( pAbc
, command
) ) {
371 fprintf( stdout
, "Cannot execute command \"%s\".\n", command
);
374 s_abcAigNetwork
= Abc_FrameReadNtk(pAbc
);
378 void AigBitblaster::convertToCnfAndAssert() {
379 TimerStat::CodeTimer
cnfConversionTimer(d_statistics
.d_cnfConversionTime
);
381 Aig_Man_t
* pMan
= NULL
;
382 Cnf_Dat_t
* pCnf
= NULL
;
383 Assert(Abc_NtkIsStrash(currentAigNtk()));
385 // convert to the AIG manager
386 pMan
= Abc_NtkToDar(currentAigNtk(), 0, 0 );
389 // // free old network
390 // Abc_NtkDelete(currentAigNtk());
391 // s_abcAigNetwork = NULL;
393 Assert(pMan
!= NULL
);
394 Assert(Aig_ManCheck(pMan
));
395 pCnf
= Cnf_DeriveFast( pMan
, 0 );
397 assertToSatSolver(pCnf
);
399 Cnf_DataFree( pCnf
);
404 void AigBitblaster::assertToSatSolver(Cnf_Dat_t
* pCnf
) {
405 unsigned numVariables
= pCnf
->nVars
;
406 unsigned numClauses
= pCnf
->nClauses
;
408 d_statistics
.d_numVariables
+= numVariables
;
409 d_statistics
.d_numClauses
+= numClauses
;
411 // create variables in the sat solver
412 std::vector
<prop::SatVariable
> sat_variables
;
413 for (unsigned i
= 0; i
< numVariables
; ++i
) {
414 sat_variables
.push_back(d_satSolver
->newVar(false, false, false));
417 // construct clauses and add to sat solver
419 for (unsigned i
= 0; i
< numClauses
; i
++ ) {
420 prop::SatClause clause
;
421 for (pLit
= pCnf
->pClauses
[i
], pStop
= pCnf
->pClauses
[i
+1]; pLit
< pStop
; pLit
++ ) {
422 int int_lit
= Cnf_Lit2Var(*pLit
);
423 Assert(int_lit
!= 0);
424 unsigned index
= int_lit
< 0? -int_lit
: int_lit
;
425 Assert(index
- 1 < sat_variables
.size());
426 prop::SatLiteral
lit(sat_variables
[index
-1], int_lit
< 0);
427 clause
.push_back(lit
);
429 d_satSolver
->addClause(clause
, false);
433 void addAliases(Abc_Frame_t
* pAbc
) {
434 std::vector
<std::string
> aliases
;
435 aliases
.push_back("alias b balance");
436 aliases
.push_back("alias rw rewrite");
437 aliases
.push_back("alias rwz rewrite -z");
438 aliases
.push_back("alias rf refactor");
439 aliases
.push_back("alias rfz refactor -z");
440 aliases
.push_back("alias re restructure");
441 aliases
.push_back("alias rez restructure -z");
442 aliases
.push_back("alias rs resub");
443 aliases
.push_back("alias rsz resub -z");
444 aliases
.push_back("alias rsk6 rs -K 6");
445 aliases
.push_back("alias rszk5 rsz -K 5");
446 aliases
.push_back("alias bl b -l");
447 aliases
.push_back("alias rwl rw -l");
448 aliases
.push_back("alias rwzl rwz -l");
449 aliases
.push_back("alias rwzl rwz -l");
450 aliases
.push_back("alias rfl rf -l");
451 aliases
.push_back("alias rfzl rfz -l");
452 aliases
.push_back("alias brw \"b; rw\"");
454 for (unsigned i
= 0; i
< aliases
.size(); ++i
) {
455 if ( Cmd_CommandExecute( pAbc
, aliases
[i
].c_str() ) ) {
456 fprintf( stdout
, "Cannot execute command \"%s\".\n", aliases
[i
].c_str() );
462 bool AigBitblaster::hasBBAtom(TNode atom
) const {
463 return d_bbAtoms
.find(atom
) != d_bbAtoms
.end();
466 void AigBitblaster::storeBBAtom(TNode atom
, Abc_Obj_t
* atom_bb
) {
467 d_bbAtoms
.insert(std::make_pair(atom
, atom_bb
));
470 Abc_Obj_t
* AigBitblaster::getBBAtom(TNode atom
) const {
471 Assert(hasBBAtom(atom
));
472 return d_bbAtoms
.find(atom
)->second
;
475 AigBitblaster::Statistics::Statistics()
476 : d_numClauses("theory::bv::AigBitblaster::numClauses", 0)
477 , d_numVariables("theory::bv::AigBitblaster::numVariables", 0)
478 , d_simplificationTime("theory::bv::AigBitblaster::simplificationTime")
479 , d_cnfConversionTime("theory::bv::AigBitblaster::cnfConversionTime")
480 , d_solveTime("theory::bv::AigBitblaster::solveTime")
482 smtStatisticsRegistry()->registerStat(&d_numClauses
);
483 smtStatisticsRegistry()->registerStat(&d_numVariables
);
484 smtStatisticsRegistry()->registerStat(&d_simplificationTime
);
485 smtStatisticsRegistry()->registerStat(&d_cnfConversionTime
);
486 smtStatisticsRegistry()->registerStat(&d_solveTime
);
489 AigBitblaster::Statistics::~Statistics() {
490 smtStatisticsRegistry()->unregisterStat(&d_numClauses
);
491 smtStatisticsRegistry()->unregisterStat(&d_numVariables
);
492 smtStatisticsRegistry()->unregisterStat(&d_simplificationTime
);
493 smtStatisticsRegistry()->unregisterStat(&d_cnfConversionTime
);
494 smtStatisticsRegistry()->unregisterStat(&d_solveTime
);
498 } // namespace theory
500 #endif // CVC4_USE_ABC