2005-07-29 17:01:00 +02:00
|
|
|
/**CFile****************************************************************
|
|
|
|
|
|
|
|
|
|
FileName [abcSat.c]
|
|
|
|
|
|
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
|
|
|
|
|
|
PackageName [Network and node package.]
|
|
|
|
|
|
|
|
|
|
Synopsis [Procedures to solve the miter using the internal SAT solver.]
|
|
|
|
|
|
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
|
|
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
|
|
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
|
|
|
|
|
|
Revision [$Id: abcSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "abc.h"
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/// DECLARATIONS ///
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2006-04-07 17:01:00 +02:00
|
|
|
extern Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk );
|
2005-12-25 17:01:00 +01:00
|
|
|
static nMuxes;
|
|
|
|
|
|
2005-07-29 17:01:00 +02:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
2005-10-12 17:01:00 +02:00
|
|
|
/// FUNCTION DEFINITIONS ///
|
2005-07-29 17:01:00 +02:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Attempts to solve the miter using an internal SAT solver.]
|
|
|
|
|
|
2005-09-08 17:01:00 +02:00
|
|
|
Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT.]
|
2005-07-29 17:01:00 +02:00
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
2006-06-11 17:01:00 +02:00
|
|
|
int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, sint64 nConfLimit, sint64 nInsLimit, int fJFront, int fVerbose, sint64 * pNumConfs, sint64 * pNumInspects )
|
2005-07-29 17:01:00 +02:00
|
|
|
{
|
|
|
|
|
solver * pSat;
|
|
|
|
|
lbool status;
|
2005-09-08 17:01:00 +02:00
|
|
|
int RetValue, clk;
|
2005-07-29 17:01:00 +02:00
|
|
|
|
2006-06-11 17:01:00 +02:00
|
|
|
if ( pNumConfs )
|
|
|
|
|
*pNumConfs = 0;
|
|
|
|
|
if ( pNumInspects )
|
|
|
|
|
*pNumInspects = 0;
|
|
|
|
|
|
2006-02-20 17:01:00 +01:00
|
|
|
assert( Abc_NtkIsStrash(pNtk) );
|
2005-07-29 17:01:00 +02:00
|
|
|
assert( Abc_NtkLatchNum(pNtk) == 0 );
|
|
|
|
|
|
2006-10-07 17:01:00 +02:00
|
|
|
// if ( Abc_NtkPoNum(pNtk) > 1 )
|
|
|
|
|
// fprintf( stdout, "Warning: The miter has %d outputs. SAT will try to prove all of them.\n", Abc_NtkPoNum(pNtk) );
|
2005-07-29 17:01:00 +02:00
|
|
|
|
|
|
|
|
// load clauses into the solver
|
|
|
|
|
clk = clock();
|
2006-04-07 17:01:00 +02:00
|
|
|
pSat = Abc_NtkMiterSatCreate( pNtk, fJFront );
|
2005-12-22 17:01:00 +01:00
|
|
|
if ( pSat == NULL )
|
|
|
|
|
return 1;
|
2005-09-08 17:01:00 +02:00
|
|
|
// printf( "Created SAT problem with %d variable and %d clauses. ", solver_nvars(pSat), solver_nclauses(pSat) );
|
2005-07-29 17:01:00 +02:00
|
|
|
// PRT( "Time", clock() - clk );
|
|
|
|
|
|
|
|
|
|
// simplify the problem
|
|
|
|
|
clk = clock();
|
|
|
|
|
status = solver_simplify(pSat);
|
2005-09-08 17:01:00 +02:00
|
|
|
// printf( "Simplified the problem to %d variables and %d clauses. ", solver_nvars(pSat), solver_nclauses(pSat) );
|
2005-07-29 17:01:00 +02:00
|
|
|
// PRT( "Time", clock() - clk );
|
2005-09-15 17:01:00 +02:00
|
|
|
if ( status == 0 )
|
2005-07-29 17:01:00 +02:00
|
|
|
{
|
|
|
|
|
solver_delete( pSat );
|
2005-09-15 17:01:00 +02:00
|
|
|
// printf( "The problem is UNSATISFIABLE after simplification.\n" );
|
2005-12-22 17:01:00 +01:00
|
|
|
return 1;
|
2005-07-29 17:01:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// solve the miter
|
|
|
|
|
clk = clock();
|
|
|
|
|
if ( fVerbose )
|
|
|
|
|
pSat->verbosity = 1;
|
2006-06-11 17:01:00 +02:00
|
|
|
status = solver_solve( pSat, NULL, NULL, (sint64)nConfLimit, (sint64)nInsLimit );
|
2005-09-08 17:01:00 +02:00
|
|
|
if ( status == l_Undef )
|
|
|
|
|
{
|
|
|
|
|
// printf( "The problem timed out.\n" );
|
|
|
|
|
RetValue = -1;
|
|
|
|
|
}
|
|
|
|
|
else if ( status == l_True )
|
|
|
|
|
{
|
|
|
|
|
// printf( "The problem is SATISFIABLE.\n" );
|
|
|
|
|
RetValue = 0;
|
|
|
|
|
}
|
|
|
|
|
else if ( status == l_False )
|
|
|
|
|
{
|
|
|
|
|
// printf( "The problem is UNSATISFIABLE.\n" );
|
|
|
|
|
RetValue = 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
assert( 0 );
|
|
|
|
|
// PRT( "SAT solver time", clock() - clk );
|
2006-06-11 17:01:00 +02:00
|
|
|
// printf( "The number of conflicts = %d.\n", (int)pSat->solver_stats.conflicts );
|
2005-09-08 17:01:00 +02:00
|
|
|
|
2005-12-25 17:01:00 +01:00
|
|
|
// if the problem is SAT, get the counterexample
|
|
|
|
|
if ( status == l_True )
|
|
|
|
|
{
|
2006-02-11 17:01:00 +01:00
|
|
|
// Vec_Int_t * vCiIds = Abc_NtkGetCiIds( pNtk );
|
|
|
|
|
Vec_Int_t * vCiIds = Abc_NtkGetCiSatVarNums( pNtk );
|
2005-12-25 17:01:00 +01:00
|
|
|
pNtk->pModel = solver_get_model( pSat, vCiIds->pArray, vCiIds->nSize );
|
|
|
|
|
Vec_IntFree( vCiIds );
|
|
|
|
|
}
|
|
|
|
|
// free the solver
|
2006-04-07 17:01:00 +02:00
|
|
|
if ( fVerbose )
|
|
|
|
|
Asat_SatPrintStats( stdout, pSat );
|
2006-06-11 17:01:00 +02:00
|
|
|
|
|
|
|
|
if ( pNumConfs )
|
|
|
|
|
*pNumConfs = (int)pSat->solver_stats.conflicts;
|
|
|
|
|
if ( pNumInspects )
|
|
|
|
|
*pNumInspects = (int)pSat->solver_stats.inspects;
|
|
|
|
|
|
2005-12-25 17:01:00 +01:00
|
|
|
solver_delete( pSat );
|
|
|
|
|
return RetValue;
|
|
|
|
|
}
|
|
|
|
|
|
2006-02-11 17:01:00 +01:00
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Returns the array of CI IDs.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
Vec_Int_t * Abc_NtkGetCiSatVarNums( Abc_Ntk_t * pNtk )
|
|
|
|
|
{
|
|
|
|
|
Vec_Int_t * vCiIds;
|
|
|
|
|
Abc_Obj_t * pObj;
|
|
|
|
|
int i;
|
|
|
|
|
vCiIds = Vec_IntAlloc( Abc_NtkCiNum(pNtk) );
|
|
|
|
|
Abc_NtkForEachCi( pNtk, pObj, i )
|
|
|
|
|
Vec_IntPush( vCiIds, (int)pObj->pCopy );
|
|
|
|
|
return vCiIds;
|
|
|
|
|
}
|
|
|
|
|
|
2005-12-25 17:01:00 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Adds trivial clause.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Abc_NtkClauseTriv( solver * pSat, Abc_Obj_t * pNode, Vec_Int_t * vVars )
|
|
|
|
|
{
|
|
|
|
|
//printf( "Adding triv %d. %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->solver_stats.clauses );
|
|
|
|
|
vVars->nSize = 0;
|
|
|
|
|
Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) );
|
|
|
|
|
// Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) );
|
|
|
|
|
return solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
|
|
|
|
|
}
|
|
|
|
|
|
2006-10-07 17:01:00 +02:00
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Adds trivial clause.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Abc_NtkClauseTop( solver * pSat, Vec_Ptr_t * vNodes, Vec_Int_t * vVars )
|
|
|
|
|
{
|
|
|
|
|
Abc_Obj_t * pNode;
|
|
|
|
|
int i;
|
|
|
|
|
//printf( "Adding triv %d. %d\n", Abc_ObjRegular(pNode)->Id, (int)pSat->solver_stats.clauses );
|
|
|
|
|
vVars->nSize = 0;
|
|
|
|
|
Vec_PtrForEachEntry( vNodes, pNode, i )
|
|
|
|
|
Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->pCopy, Abc_ObjIsComplement(pNode) ) );
|
|
|
|
|
// Vec_IntPush( vVars, toLitCond( (int)Abc_ObjRegular(pNode)->Id, Abc_ObjIsComplement(pNode) ) );
|
|
|
|
|
return solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
|
|
|
|
|
}
|
|
|
|
|
|
2005-12-25 17:01:00 +01:00
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Adds trivial clause.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Abc_NtkClauseAnd( solver * pSat, Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, Vec_Int_t * vVars )
|
|
|
|
|
{
|
|
|
|
|
int fComp1, Var, Var1, i;
|
|
|
|
|
//printf( "Adding AND %d. (%d) %d\n", pNode->Id, vSuper->nSize+1, (int)pSat->solver_stats.clauses );
|
|
|
|
|
|
|
|
|
|
assert( !Abc_ObjIsComplement( pNode ) );
|
|
|
|
|
assert( Abc_ObjIsNode( pNode ) );
|
|
|
|
|
|
|
|
|
|
// nVars = solver_nvars(pSat);
|
|
|
|
|
Var = (int)pNode->pCopy;
|
|
|
|
|
// Var = pNode->Id;
|
|
|
|
|
|
|
|
|
|
// assert( Var < nVars );
|
|
|
|
|
for ( i = 0; i < vSuper->nSize; i++ )
|
|
|
|
|
{
|
|
|
|
|
// get the predecessor nodes
|
|
|
|
|
// get the complemented attributes of the nodes
|
|
|
|
|
fComp1 = Abc_ObjIsComplement(vSuper->pArray[i]);
|
|
|
|
|
// determine the variable numbers
|
|
|
|
|
Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->pCopy;
|
|
|
|
|
// Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id;
|
|
|
|
|
|
|
|
|
|
// check that the variables are in the SAT manager
|
|
|
|
|
// assert( Var1 < nVars );
|
|
|
|
|
|
|
|
|
|
// suppose the AND-gate is A * B = C
|
|
|
|
|
// add !A => !C or A + !C
|
|
|
|
|
// fprintf( pFile, "%d %d 0%c", Var1, -Var, 10 );
|
|
|
|
|
vVars->nSize = 0;
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(Var1, fComp1) );
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(Var, 1 ) );
|
|
|
|
|
if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add A & B => C or !A + !B + C
|
|
|
|
|
// fprintf( pFile, "%d %d %d 0%c", -Var1, -Var2, Var, 10 );
|
|
|
|
|
vVars->nSize = 0;
|
|
|
|
|
for ( i = 0; i < vSuper->nSize; i++ )
|
|
|
|
|
{
|
|
|
|
|
// get the predecessor nodes
|
|
|
|
|
// get the complemented attributes of the nodes
|
|
|
|
|
fComp1 = Abc_ObjIsComplement(vSuper->pArray[i]);
|
|
|
|
|
// determine the variable numbers
|
|
|
|
|
Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->pCopy;
|
|
|
|
|
// Var1 = (int)Abc_ObjRegular(vSuper->pArray[i])->Id;
|
|
|
|
|
// add this variable to the array
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(Var1, !fComp1) );
|
|
|
|
|
}
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(Var, 0) );
|
|
|
|
|
return solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Adds trivial clause.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Abc_NtkClauseMux( solver * pSat, Abc_Obj_t * pNode, Abc_Obj_t * pNodeC, Abc_Obj_t * pNodeT, Abc_Obj_t * pNodeE, Vec_Int_t * vVars )
|
|
|
|
|
{
|
|
|
|
|
int VarF, VarI, VarT, VarE, fCompT, fCompE;
|
|
|
|
|
//printf( "Adding mux %d. %d\n", pNode->Id, (int)pSat->solver_stats.clauses );
|
|
|
|
|
|
|
|
|
|
assert( !Abc_ObjIsComplement( pNode ) );
|
|
|
|
|
assert( Abc_NodeIsMuxType( pNode ) );
|
|
|
|
|
// get the variable numbers
|
|
|
|
|
VarF = (int)pNode->pCopy;
|
|
|
|
|
VarI = (int)pNodeC->pCopy;
|
|
|
|
|
VarT = (int)Abc_ObjRegular(pNodeT)->pCopy;
|
|
|
|
|
VarE = (int)Abc_ObjRegular(pNodeE)->pCopy;
|
|
|
|
|
// VarF = (int)pNode->Id;
|
|
|
|
|
// VarI = (int)pNodeC->Id;
|
|
|
|
|
// VarT = (int)Abc_ObjRegular(pNodeT)->Id;
|
|
|
|
|
// VarE = (int)Abc_ObjRegular(pNodeE)->Id;
|
|
|
|
|
|
|
|
|
|
// get the complementation flags
|
|
|
|
|
fCompT = Abc_ObjIsComplement(pNodeT);
|
|
|
|
|
fCompE = Abc_ObjIsComplement(pNodeE);
|
|
|
|
|
|
|
|
|
|
// f = ITE(i, t, e)
|
|
|
|
|
// i' + t' + f
|
|
|
|
|
// i' + t + f'
|
|
|
|
|
// i + e' + f
|
|
|
|
|
// i + e + f'
|
|
|
|
|
// create four clauses
|
|
|
|
|
vVars->nSize = 0;
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarI, 1) );
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarT, 1^fCompT) );
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarF, 0) );
|
|
|
|
|
if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
|
|
|
|
|
return 0;
|
|
|
|
|
vVars->nSize = 0;
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarI, 1) );
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarT, 0^fCompT) );
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarF, 1) );
|
|
|
|
|
if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
|
|
|
|
|
return 0;
|
|
|
|
|
vVars->nSize = 0;
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarI, 0) );
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarE, 1^fCompE) );
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarF, 0) );
|
|
|
|
|
if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
|
|
|
|
|
return 0;
|
|
|
|
|
vVars->nSize = 0;
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarI, 0) );
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarE, 0^fCompE) );
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarF, 1) );
|
|
|
|
|
if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
|
|
|
|
|
return 0;
|
2006-01-18 17:01:00 +01:00
|
|
|
|
2005-12-25 17:01:00 +01:00
|
|
|
if ( VarT == VarE )
|
|
|
|
|
{
|
2006-01-18 17:01:00 +01:00
|
|
|
// assert( fCompT == !fCompE );
|
2005-12-25 17:01:00 +01:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// two additional clauses
|
|
|
|
|
// t' & e' -> f' t + e + f'
|
|
|
|
|
// t & e -> f t' + e' + f
|
|
|
|
|
vVars->nSize = 0;
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarT, 0^fCompT) );
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarE, 0^fCompE) );
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarF, 1) );
|
|
|
|
|
if ( !solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize ) )
|
|
|
|
|
return 0;
|
|
|
|
|
vVars->nSize = 0;
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarT, 1^fCompT) );
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarE, 1^fCompE) );
|
|
|
|
|
Vec_IntPush( vVars, toLitCond(VarF, 0) );
|
|
|
|
|
return solver_addclause( pSat, vVars->pArray, vVars->pArray + vVars->nSize );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Abc_NtkCollectSupergate_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, int fFirst, int fStopAtMux )
|
|
|
|
|
{
|
|
|
|
|
int RetValue1, RetValue2, i;
|
|
|
|
|
// check if the node is visited
|
|
|
|
|
if ( Abc_ObjRegular(pNode)->fMarkB )
|
|
|
|
|
{
|
|
|
|
|
// check if the node occurs in the same polarity
|
|
|
|
|
for ( i = 0; i < vSuper->nSize; i++ )
|
|
|
|
|
if ( vSuper->pArray[i] == pNode )
|
|
|
|
|
return 1;
|
|
|
|
|
// check if the node is present in the opposite polarity
|
|
|
|
|
for ( i = 0; i < vSuper->nSize; i++ )
|
|
|
|
|
if ( vSuper->pArray[i] == Abc_ObjNot(pNode) )
|
|
|
|
|
return -1;
|
|
|
|
|
assert( 0 );
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
// if the new node is complemented or a PI, another gate begins
|
|
|
|
|
if ( !fFirst )
|
|
|
|
|
if ( Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || Abc_ObjFanoutNum(pNode) > 1 || fStopAtMux && Abc_NodeIsMuxType(pNode) )
|
|
|
|
|
{
|
|
|
|
|
Vec_PtrPush( vSuper, pNode );
|
|
|
|
|
Abc_ObjRegular(pNode)->fMarkB = 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
assert( !Abc_ObjIsComplement(pNode) );
|
|
|
|
|
assert( Abc_ObjIsNode(pNode) );
|
|
|
|
|
// go through the branches
|
|
|
|
|
RetValue1 = Abc_NtkCollectSupergate_rec( Abc_ObjChild0(pNode), vSuper, 0, fStopAtMux );
|
|
|
|
|
RetValue2 = Abc_NtkCollectSupergate_rec( Abc_ObjChild1(pNode), vSuper, 0, fStopAtMux );
|
|
|
|
|
if ( RetValue1 == -1 || RetValue2 == -1 )
|
|
|
|
|
return -1;
|
|
|
|
|
// return 1 if at least one branch has a duplicate
|
|
|
|
|
return RetValue1 || RetValue2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
void Abc_NtkCollectSupergate( Abc_Obj_t * pNode, int fStopAtMux, Vec_Ptr_t * vNodes )
|
|
|
|
|
{
|
|
|
|
|
int RetValue, i;
|
|
|
|
|
assert( !Abc_ObjIsComplement(pNode) );
|
|
|
|
|
// collect the nodes in the implication supergate
|
|
|
|
|
Vec_PtrClear( vNodes );
|
|
|
|
|
RetValue = Abc_NtkCollectSupergate_rec( pNode, vNodes, 1, fStopAtMux );
|
|
|
|
|
assert( vNodes->nSize > 1 );
|
|
|
|
|
// unmark the visited nodes
|
|
|
|
|
for ( i = 0; i < vNodes->nSize; i++ )
|
|
|
|
|
Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0;
|
|
|
|
|
// if we found the node and its complement in the same implication supergate,
|
|
|
|
|
// return empty set of nodes (meaning that we should use constant-0 node)
|
|
|
|
|
if ( RetValue == -1 )
|
|
|
|
|
vNodes->nSize = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-08-03 17:01:00 +02:00
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Computes the factor of the node.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Abc_NtkNodeFactor( Abc_Obj_t * pObj, int nLevelMax )
|
|
|
|
|
{
|
|
|
|
|
// nLevelMax = ((nLevelMax)/2)*3;
|
2006-08-04 17:01:00 +02:00
|
|
|
assert( (int)pObj->Level <= nLevelMax );
|
2006-08-03 17:01:00 +02:00
|
|
|
// return (int)(100000000.0 * pow(0.999, nLevelMax - pObj->Level));
|
|
|
|
|
return (int)(100000000.0 * (1 + 0.01 * pObj->Level));
|
|
|
|
|
// return (int)(100000000.0 / ((nLevelMax)/2)*3 - pObj->Level);
|
|
|
|
|
}
|
|
|
|
|
|
2005-12-25 17:01:00 +01:00
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Sets up the SAT solver.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
2006-04-07 17:01:00 +02:00
|
|
|
int Abc_NtkMiterSatCreateInt( solver * pSat, Abc_Ntk_t * pNtk, int fJFront )
|
2005-12-25 17:01:00 +01:00
|
|
|
{
|
|
|
|
|
Abc_Obj_t * pNode, * pFanin, * pNodeC, * pNodeT, * pNodeE;
|
|
|
|
|
Vec_Ptr_t * vNodes, * vSuper;
|
2006-09-16 17:01:00 +02:00
|
|
|
Vec_Flt_t * vFactors;
|
2006-04-07 17:01:00 +02:00
|
|
|
Vec_Int_t * vVars, * vFanio;
|
|
|
|
|
Vec_Vec_t * vCircuit;
|
2005-12-25 17:01:00 +01:00
|
|
|
int i, k, fUseMuxes = 1;
|
2006-04-07 17:01:00 +02:00
|
|
|
int clk1 = clock(), clk;
|
2006-06-11 17:01:00 +02:00
|
|
|
int fOrderCiVarsFirst = 0;
|
2006-11-22 17:01:00 +01:00
|
|
|
int nLevelsMax = Abc_AigLevel(pNtk);
|
2006-08-23 17:01:00 +02:00
|
|
|
int RetValue = 0;
|
2005-12-25 17:01:00 +01:00
|
|
|
|
|
|
|
|
assert( Abc_NtkIsStrash(pNtk) );
|
|
|
|
|
|
2006-03-03 17:01:00 +01:00
|
|
|
// clean the CI node pointers
|
|
|
|
|
Abc_NtkForEachCi( pNtk, pNode, i )
|
|
|
|
|
pNode->pCopy = NULL;
|
|
|
|
|
|
2005-12-25 17:01:00 +01:00
|
|
|
// start the data structures
|
2006-08-03 17:01:00 +02:00
|
|
|
vNodes = Vec_PtrAlloc( 1000 ); // the nodes corresponding to vars in the solver
|
|
|
|
|
vSuper = Vec_PtrAlloc( 100 ); // the nodes belonging to the given implication supergate
|
|
|
|
|
vVars = Vec_IntAlloc( 100 ); // the temporary array for variables in the clause
|
2006-04-07 17:01:00 +02:00
|
|
|
if ( fJFront )
|
|
|
|
|
vCircuit = Vec_VecAlloc( 1000 );
|
|
|
|
|
// vCircuit = Vec_VecStart( 184 );
|
2005-12-25 17:01:00 +01:00
|
|
|
|
|
|
|
|
// add the clause for the constant node
|
2006-08-22 17:01:00 +02:00
|
|
|
pNode = Abc_AigConst1(pNtk);
|
2005-12-25 17:01:00 +01:00
|
|
|
pNode->fMarkA = 1;
|
|
|
|
|
pNode->pCopy = (Abc_Obj_t *)vNodes->nSize;
|
|
|
|
|
Vec_PtrPush( vNodes, pNode );
|
|
|
|
|
Abc_NtkClauseTriv( pSat, pNode, vVars );
|
2006-05-08 17:01:00 +02:00
|
|
|
/*
|
|
|
|
|
// add the PI variables first
|
|
|
|
|
Abc_NtkForEachCi( pNtk, pNode, i )
|
|
|
|
|
{
|
|
|
|
|
pNode->fMarkA = 1;
|
|
|
|
|
pNode->pCopy = (Abc_Obj_t *)vNodes->nSize;
|
|
|
|
|
Vec_PtrPush( vNodes, pNode );
|
|
|
|
|
}
|
|
|
|
|
*/
|
2005-12-25 17:01:00 +01:00
|
|
|
// collect the nodes that need clauses and top-level assignments
|
2006-10-07 17:01:00 +02:00
|
|
|
Vec_PtrClear( vSuper );
|
2005-12-25 17:01:00 +01:00
|
|
|
Abc_NtkForEachCo( pNtk, pNode, i )
|
|
|
|
|
{
|
|
|
|
|
// get the fanin
|
|
|
|
|
pFanin = Abc_ObjFanin0(pNode);
|
|
|
|
|
// create the node's variable
|
|
|
|
|
if ( pFanin->fMarkA == 0 )
|
|
|
|
|
{
|
|
|
|
|
pFanin->fMarkA = 1;
|
|
|
|
|
pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize;
|
|
|
|
|
Vec_PtrPush( vNodes, pFanin );
|
|
|
|
|
}
|
|
|
|
|
// add the trivial clause
|
2006-10-07 17:01:00 +02:00
|
|
|
Vec_PtrPush( vSuper, Abc_ObjChild0(pNode) );
|
2005-12-25 17:01:00 +01:00
|
|
|
}
|
2006-10-07 17:01:00 +02:00
|
|
|
if ( !Abc_NtkClauseTop( pSat, vSuper, vVars ) )
|
|
|
|
|
goto Quits;
|
|
|
|
|
|
2005-12-25 17:01:00 +01:00
|
|
|
|
|
|
|
|
// add the clauses
|
|
|
|
|
Vec_PtrForEachEntry( vNodes, pNode, i )
|
|
|
|
|
{
|
|
|
|
|
assert( !Abc_ObjIsComplement(pNode) );
|
2006-08-22 17:01:00 +02:00
|
|
|
if ( !Abc_AigNodeIsAnd(pNode) )
|
2005-12-25 17:01:00 +01:00
|
|
|
continue;
|
|
|
|
|
//printf( "%d ", pNode->Id );
|
|
|
|
|
|
|
|
|
|
// add the clauses
|
|
|
|
|
if ( fUseMuxes && Abc_NodeIsMuxType(pNode) )
|
|
|
|
|
{
|
|
|
|
|
nMuxes++;
|
|
|
|
|
|
|
|
|
|
pNodeC = Abc_NodeRecognizeMux( pNode, &pNodeT, &pNodeE );
|
|
|
|
|
Vec_PtrClear( vSuper );
|
|
|
|
|
Vec_PtrPush( vSuper, pNodeC );
|
|
|
|
|
Vec_PtrPush( vSuper, pNodeT );
|
|
|
|
|
Vec_PtrPush( vSuper, pNodeE );
|
|
|
|
|
// add the fanin nodes to explore
|
|
|
|
|
Vec_PtrForEachEntry( vSuper, pFanin, k )
|
|
|
|
|
{
|
|
|
|
|
pFanin = Abc_ObjRegular(pFanin);
|
|
|
|
|
if ( pFanin->fMarkA == 0 )
|
|
|
|
|
{
|
|
|
|
|
pFanin->fMarkA = 1;
|
|
|
|
|
pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize;
|
|
|
|
|
Vec_PtrPush( vNodes, pFanin );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// add the clauses
|
|
|
|
|
if ( !Abc_NtkClauseMux( pSat, pNode, pNodeC, pNodeT, pNodeE, vVars ) )
|
2006-08-23 17:01:00 +02:00
|
|
|
goto Quits;
|
2005-12-25 17:01:00 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// get the supergate
|
|
|
|
|
Abc_NtkCollectSupergate( pNode, fUseMuxes, vSuper );
|
|
|
|
|
// add the fanin nodes to explore
|
|
|
|
|
Vec_PtrForEachEntry( vSuper, pFanin, k )
|
|
|
|
|
{
|
|
|
|
|
pFanin = Abc_ObjRegular(pFanin);
|
|
|
|
|
if ( pFanin->fMarkA == 0 )
|
|
|
|
|
{
|
|
|
|
|
pFanin->fMarkA = 1;
|
|
|
|
|
pFanin->pCopy = (Abc_Obj_t *)vNodes->nSize;
|
|
|
|
|
Vec_PtrPush( vNodes, pFanin );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// add the clauses
|
|
|
|
|
if ( vSuper->nSize == 0 )
|
|
|
|
|
{
|
|
|
|
|
if ( !Abc_NtkClauseTriv( pSat, Abc_ObjNot(pNode), vVars ) )
|
2006-04-07 17:01:00 +02:00
|
|
|
// if ( !Abc_NtkClauseTriv( pSat, pNode, vVars ) )
|
2006-08-23 17:01:00 +02:00
|
|
|
goto Quits;
|
2005-12-25 17:01:00 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if ( !Abc_NtkClauseAnd( pSat, pNode, vSuper, vVars ) )
|
2006-08-23 17:01:00 +02:00
|
|
|
goto Quits;
|
2005-12-25 17:01:00 +01:00
|
|
|
}
|
|
|
|
|
}
|
2006-04-07 17:01:00 +02:00
|
|
|
// add the variables to the J-frontier
|
|
|
|
|
if ( !fJFront )
|
|
|
|
|
continue;
|
|
|
|
|
// make sure that the fanin entries go first
|
|
|
|
|
assert( pNode->pCopy );
|
|
|
|
|
Vec_VecExpand( vCircuit, (int)pNode->pCopy );
|
|
|
|
|
vFanio = Vec_VecEntry( vCircuit, (int)pNode->pCopy );
|
|
|
|
|
Vec_PtrForEachEntryReverse( vSuper, pFanin, k )
|
|
|
|
|
// Vec_PtrForEachEntry( vSuper, pFanin, k )
|
|
|
|
|
{
|
|
|
|
|
pFanin = Abc_ObjRegular( pFanin );
|
|
|
|
|
assert( pFanin->pCopy && pFanin->pCopy != pNode->pCopy );
|
|
|
|
|
Vec_IntPushFirst( vFanio, (int)pFanin->pCopy );
|
|
|
|
|
Vec_VecPush( vCircuit, (int)pFanin->pCopy, pNode->pCopy );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-06-11 17:01:00 +02:00
|
|
|
// set preferred variables
|
|
|
|
|
if ( fOrderCiVarsFirst )
|
|
|
|
|
{
|
|
|
|
|
int * pPrefVars = ALLOC( int, Abc_NtkCiNum(pNtk) );
|
|
|
|
|
int nVars = 0;
|
|
|
|
|
Abc_NtkForEachCi( pNtk, pNode, i )
|
|
|
|
|
{
|
|
|
|
|
if ( pNode->fMarkA == 0 )
|
|
|
|
|
continue;
|
|
|
|
|
pPrefVars[nVars++] = (int)pNode->pCopy;
|
|
|
|
|
}
|
|
|
|
|
nVars = ABC_MIN( nVars, 10 );
|
|
|
|
|
Asat_SolverSetPrefVars( pSat, pPrefVars, nVars );
|
|
|
|
|
}
|
|
|
|
|
|
2006-04-07 17:01:00 +02:00
|
|
|
// create the variable order
|
|
|
|
|
if ( fJFront )
|
|
|
|
|
{
|
|
|
|
|
clk = clock();
|
|
|
|
|
Asat_JManStart( pSat, vCircuit );
|
|
|
|
|
Vec_VecFree( vCircuit );
|
|
|
|
|
PRT( "Setup", clock() - clk );
|
|
|
|
|
// Asat_JManStop( pSat );
|
|
|
|
|
// PRT( "Total", clock() - clk1 );
|
2005-12-25 17:01:00 +01:00
|
|
|
}
|
2006-09-16 17:01:00 +02:00
|
|
|
|
|
|
|
|
Abc_NtkStartReverseLevels( pNtk );
|
|
|
|
|
vFactors = Vec_FltStart( solver_nvars(pSat) );
|
|
|
|
|
Abc_NtkForEachNode( pNtk, pNode, i )
|
|
|
|
|
if ( pNode->fMarkA )
|
|
|
|
|
Vec_FltWriteEntry( vFactors, (int)pNode->pCopy, (float)pow(0.97, Abc_NodeReadReverseLevel(pNode)) );
|
|
|
|
|
Abc_NtkForEachCi( pNtk, pNode, i )
|
|
|
|
|
if ( pNode->fMarkA )
|
|
|
|
|
Vec_FltWriteEntry( vFactors, (int)pNode->pCopy, (float)pow(0.97, nLevelsMax+1) );
|
|
|
|
|
// set the PI levels
|
|
|
|
|
// Abc_NtkForEachObj( pNtk, pNode, i )
|
|
|
|
|
// if ( pNode->fMarkA )
|
|
|
|
|
// printf( "(%d) %.3f ", Abc_NodeReadReverseLevel(pNode), Vec_FltEntry(vFactors, (int)pNode->pCopy) );
|
|
|
|
|
// printf( "\n" );
|
|
|
|
|
Asat_SolverSetFactors( pSat, Vec_FltReleaseArray(vFactors) );
|
|
|
|
|
Vec_FltFree( vFactors );
|
|
|
|
|
|
2006-08-03 17:01:00 +02:00
|
|
|
/*
|
|
|
|
|
// create factors
|
|
|
|
|
vLevels = Vec_IntStart( Vec_PtrSize(vNodes) ); // the reverse levels of the nodes
|
|
|
|
|
Abc_NtkForEachObj( pNtk, pNode, i )
|
|
|
|
|
if ( pNode->fMarkA )
|
|
|
|
|
Vec_IntWriteEntry( vLevels, (int)pNode->pCopy, Abc_NtkNodeFactor(pNode, nLevelsMax) );
|
|
|
|
|
assert( Vec_PtrSize(vNodes) == Vec_IntSize(vLevels) );
|
|
|
|
|
Asat_SolverSetFactors( pSat, Vec_IntReleaseArray(vLevels) );
|
|
|
|
|
Vec_IntFree( vLevels );
|
|
|
|
|
*/
|
2006-08-23 17:01:00 +02:00
|
|
|
RetValue = 1;
|
|
|
|
|
Quits :
|
2005-12-25 17:01:00 +01:00
|
|
|
// delete
|
|
|
|
|
Vec_IntFree( vVars );
|
|
|
|
|
Vec_PtrFree( vNodes );
|
|
|
|
|
Vec_PtrFree( vSuper );
|
2006-08-23 17:01:00 +02:00
|
|
|
return RetValue;
|
2005-12-25 17:01:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Sets up the SAT solver.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
2006-04-07 17:01:00 +02:00
|
|
|
solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fJFront )
|
2005-12-25 17:01:00 +01:00
|
|
|
{
|
|
|
|
|
solver * pSat;
|
|
|
|
|
Abc_Obj_t * pNode;
|
|
|
|
|
int RetValue, i, clk = clock();
|
|
|
|
|
|
|
|
|
|
nMuxes = 0;
|
|
|
|
|
|
|
|
|
|
pSat = solver_new();
|
2006-04-07 17:01:00 +02:00
|
|
|
RetValue = Abc_NtkMiterSatCreateInt( pSat, pNtk, fJFront );
|
2005-12-25 17:01:00 +01:00
|
|
|
Abc_NtkForEachObj( pNtk, pNode, i )
|
|
|
|
|
pNode->fMarkA = 0;
|
2006-01-18 17:01:00 +01:00
|
|
|
// Asat_SolverWriteDimacs( pSat, "temp_sat.cnf", NULL, NULL, 1 );
|
2005-12-25 17:01:00 +01:00
|
|
|
if ( RetValue == 0 )
|
|
|
|
|
{
|
|
|
|
|
solver_delete(pSat);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2006-02-20 17:01:00 +01:00
|
|
|
// printf( "Ands = %6d. Muxes = %6d (%5.2f %%). ", Abc_NtkNodeNum(pNtk), nMuxes, 300.0*nMuxes/Abc_NtkNodeNum(pNtk) );
|
|
|
|
|
// PRT( "Creating solver", clock() - clk );
|
2005-12-25 17:01:00 +01:00
|
|
|
return pSat;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2005-07-29 17:01:00 +02:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/// END OF FILE ///
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|